123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441 |
- import { MathNode, GLSLNodeParser, NodeBuilder, NodeMaterial } from '../../../nodes/Nodes.js';
- import UniformsGroup from '../../common/UniformsGroup.js';
- import { NodeSampledTexture, NodeSampledCubeTexture } from '../../common/nodes/NodeSampledTexture.js';
- const glslMethods = {
- [ MathNode.ATAN2 ]: 'atan'
- };
- const precisionLib = {
- low: 'lowp',
- medium: 'mediump',
- high: 'highp'
- };
- class GLSLNodeBuilder extends NodeBuilder {
- constructor( object, renderer, scene = null ) {
- super( object, renderer, new GLSLNodeParser(), scene );
- this.uniformsGroup = {};
- }
- getMethod( method ) {
- return glslMethods[ method ] || method;
- }
- getTexture( texture, textureProperty, uvSnippet ) {
- if ( texture.isTextureCube ) {
- return `textureCube( ${textureProperty}, ${uvSnippet} )`;
- } else {
- return `texture( ${textureProperty}, ${uvSnippet} )`;
- }
- }
- getTextureLevel( texture, textureProperty, uvSnippet, biasSnippet ) {
- return `textureLod( ${textureProperty}, ${uvSnippet}, ${biasSnippet} )`;
- }
- getVars( shaderStage ) {
- const snippets = [];
- const vars = this.vars[ shaderStage ];
- for ( const variable of vars ) {
- snippets.push( `${ this.getVar( variable.type, variable.name ) };` );
- }
- return snippets.join( '\n\t' );
- }
- getUniforms( shaderStage ) {
- const uniforms = this.uniforms[ shaderStage ];
- const bindingSnippets = [];
- const groupSnippets = [];
- for ( const uniform of uniforms ) {
- let snippet = null;
- let group = false;
- if ( uniform.type === 'texture' ) {
- snippet = `sampler2D ${uniform.name};`;
- } else if ( uniform.type === 'cubeTexture' ) {
- snippet = `samplerCube ${uniform.name};`;
- } else {
- const vectorType = this.getVectorType( uniform.type );
- snippet = `${vectorType} ${uniform.name};`;
- group = true;
- }
- const precision = uniform.node.precision;
- if ( precision !== null ) {
- snippet = precisionLib[ precision ] + ' ' + snippet;
- }
- if ( group ) {
- snippet = '\t' + snippet;
- groupSnippets.push( snippet );
- } else {
- snippet = 'uniform ' + snippet;
- bindingSnippets.push( snippet );
- }
- }
- let output = '';
- if ( groupSnippets.length > 0 ) {
- output += this._getGLSLUniformStruct( shaderStage + 'NodeUniforms', groupSnippets.join( '\n' ) ) + '\n';
- }
- output += bindingSnippets.join( '\n' );
- return output;
- }
- getAttributes( shaderStage ) {
- let snippet = '';
- if ( shaderStage === 'vertex' ) {
- const attributes = this.attributes;
- let location = 0;
- for ( const attribute of attributes ) {
- snippet += `layout( location = ${ location ++ } ) in ${ attribute.type } ${ attribute.name };\n`;
- }
- }
- return snippet;
- }
- getVaryings( shaderStage ) {
- let snippet = '';
- const varyings = this.varyings;
- if ( shaderStage === 'vertex' ) {
- for ( const varying of varyings ) {
- snippet += `${varying.needsInterpolation ? 'out' : '/*out*/'} ${varying.type} ${varying.name};\n`;
- }
- } else if ( shaderStage === 'fragment' ) {
- for ( const varying of varyings ) {
- if ( varying.needsInterpolation ) {
- snippet += `in ${varying.type} ${varying.name};\n`;
- }
- }
- }
- return snippet;
- }
- getVertexIndex() {
- return 'gl_VertexID';
- }
- getFrontFacing() {
- return 'gl_FrontFacing';
- }
- getFragCoord() {
- return 'gl_FragCoord';
- }
- isFlipY() {
- return true;
- }
- _getGLSLUniformStruct( name, vars ) {
- return `
- layout( std140 ) uniform ${name} {
- ${vars}
- };`;
- }
- _getGLSLVertexCode( shaderData ) {
- return `#version 300 es
- ${ this.getSignature() }
- // precision
- precision highp float;
- precision highp int;
- // uniforms
- ${shaderData.uniforms}
- // varyings
- ${shaderData.varyings}
- // attributes
- ${shaderData.attributes}
- // codes
- ${shaderData.codes}
- void main() {
- // vars
- ${shaderData.vars}
- // flow
- ${shaderData.flow}
- gl_PointSize = 1.0;
- }
- `;
- }
- _getGLSLFragmentCode( shaderData ) {
- return `#version 300 es
- ${ this.getSignature() }
- // precision
- precision highp float;
- precision highp int;
- // uniforms
- ${shaderData.uniforms}
- // varyings
- ${shaderData.varyings}
- // codes
- ${shaderData.codes}
- layout( location = 0 ) out vec4 fragColor;
- void main() {
- // vars
- ${shaderData.vars}
- // flow
- ${shaderData.flow}
- }
- `;
- }
- buildCode() {
- const shadersData = this.material !== null ? { fragment: {}, vertex: {} } : { compute: {} };
- for ( const shaderStage in shadersData ) {
- let flow = '// code\n\n';
- flow += this.flowCode[ shaderStage ];
- const flowNodes = this.flowNodes[ shaderStage ];
- const mainNode = flowNodes[ flowNodes.length - 1 ];
- for ( const node of flowNodes ) {
- const flowSlotData = this.getFlowData( node/*, shaderStage*/ );
- const slotName = node.name;
- if ( slotName ) {
- if ( flow.length > 0 ) flow += '\n';
- flow += `\t// flow -> ${ slotName }\n\t`;
- }
- flow += `${ flowSlotData.code }\n\t`;
- if ( node === mainNode && shaderStage !== 'compute' ) {
- flow += '// result\n\t';
- if ( shaderStage === 'vertex' ) {
- flow += 'gl_Position = ';
- } else if ( shaderStage === 'fragment' ) {
- flow += 'fragColor = ';
- }
- flow += `${ flowSlotData.result };`;
- }
- }
- const stageData = shadersData[ shaderStage ];
- stageData.uniforms = this.getUniforms( shaderStage );
- stageData.attributes = this.getAttributes( shaderStage );
- stageData.varyings = this.getVaryings( shaderStage );
- stageData.vars = this.getVars( shaderStage );
- stageData.codes = this.getCodes( shaderStage );
- stageData.flow = flow;
- }
- if ( this.material !== null ) {
- this.vertexShader = this._getGLSLVertexCode( shadersData.vertex );
- this.fragmentShader = this._getGLSLFragmentCode( shadersData.fragment );
- //console.log( this.vertexShader );
- //console.log( this.fragmentShader );
- } else {
- console.warn( 'GLSLNodeBuilder: compute shaders are not supported.' );
- //this.computeShader = this._getGLSLComputeCode( shadersData.compute );
- }
- }
- getUniformFromNode( node, type, shaderStage, name = null ) {
- const uniformNode = super.getUniformFromNode( node, type, shaderStage, name );
- const nodeData = this.getDataFromNode( node, shaderStage );
- let uniformGPU = nodeData.uniformGPU;
- if ( uniformGPU === undefined ) {
- if ( type === 'texture' ) {
- uniformGPU = new NodeSampledTexture( uniformNode.name, uniformNode.node );
- this.bindings[ shaderStage ].push( uniformGPU );
- } else if ( type === 'cubeTexture' ) {
- uniformGPU = new NodeSampledCubeTexture( uniformNode.name, uniformNode.node );
- this.bindings[ shaderStage ].push( uniformGPU );
- } else {
- let uniformsGroup = this.uniformsGroup[ shaderStage ];
- if ( uniformsGroup === undefined ) {
- uniformsGroup = new UniformsGroup( shaderStage + 'NodeUniforms' );
- //uniformsGroup.setVisibility( gpuShaderStageLib[ shaderStage ] );
- this.uniformsGroup[ shaderStage ] = uniformsGroup;
- this.bindings[ shaderStage ].push( uniformsGroup );
- }
- uniformGPU = this.getNodeUniform( uniformNode, type );
- uniformsGroup.addUniform( uniformGPU );
- }
- nodeData.uniformGPU = uniformGPU;
- }
- return uniformNode;
- }
- build() {
- // @TODO: Move this code to super.build()
- const { object, material } = this;
- if ( material !== null ) {
- NodeMaterial.fromMaterial( material ).build( this );
- } else {
- this.addFlow( 'compute', object );
- }
- return super.build();
- }
- }
- export default GLSLNodeBuilder;
|