Skip to content

Commit e2d1338

Browse files
authored
TSL: Editor (GLSL) (#26283)
* Added GLSLNodeBuilder * WebGLNodeBuilder: Fix redefinitions * update * add preview option * improve styles variables
1 parent 3b52c70 commit e2d1338

File tree

5 files changed

+361
-7
lines changed

5 files changed

+361
-7
lines changed

examples/jsm/nodes/accessors/CameraNode.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import Object3DNode from './Object3DNode.js';
22
import { addNodeClass } from '../core/Node.js';
3+
import { label } from '../core/ContextNode.js';
34
import { nodeImmutable } from '../shadernode/ShaderNode.js';
45

56
class CameraNode extends Object3DNode {
@@ -86,7 +87,7 @@ CameraNode.FAR = 'far';
8687

8788
export default CameraNode;
8889

89-
export const cameraProjectionMatrix = nodeImmutable( CameraNode, CameraNode.PROJECTION_MATRIX );
90+
export const cameraProjectionMatrix = label( nodeImmutable( CameraNode, CameraNode.PROJECTION_MATRIX ), 'projectionMatrix' );
9091
export const cameraNear = nodeImmutable( CameraNode, CameraNode.NEAR );
9192
export const cameraFar = nodeImmutable( CameraNode, CameraNode.FAR );
9293
export const cameraViewMatrix = nodeImmutable( CameraNode, CameraNode.VIEW_MATRIX );

examples/jsm/nodes/accessors/ModelNode.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import Object3DNode from './Object3DNode.js';
22
import { addNodeClass } from '../core/Node.js';
3+
import { label } from '../core/ContextNode.js';
34
import { nodeImmutable } from '../shadernode/ShaderNode.js';
45

56
class ModelNode extends Object3DNode {
@@ -23,7 +24,7 @@ class ModelNode extends Object3DNode {
2324
export default ModelNode;
2425

2526
export const modelDirection = nodeImmutable( ModelNode, ModelNode.DIRECTION );
26-
export const modelViewMatrix = nodeImmutable( ModelNode, ModelNode.VIEW_MATRIX );
27+
export const modelViewMatrix = label( nodeImmutable( ModelNode, ModelNode.VIEW_MATRIX ), 'modelViewMatrix' );
2728
export const modelNormalMatrix = nodeImmutable( ModelNode, ModelNode.NORMAL_MATRIX );
2829
export const modelWorldMatrix = nodeImmutable( ModelNode, ModelNode.WORLD_MATRIX );
2930
export const modelPosition = nodeImmutable( ModelNode, ModelNode.POSITION );
Lines changed: 334 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,334 @@
1+
import { MathNode, GLSLNodeParser, NodeBuilder, NodeMaterial } from 'three/nodes';
2+
3+
const glslMethods = {
4+
[ MathNode.ATAN2 ]: 'atan'
5+
};
6+
7+
const precisionLib = {
8+
low: 'lowp',
9+
medium: 'mediump',
10+
high: 'highp'
11+
};
12+
13+
class GLSLNodeBuilder extends NodeBuilder {
14+
15+
constructor( object, renderer ) {
16+
17+
super( object, renderer, new GLSLNodeParser() );
18+
19+
}
20+
21+
getMethod( method ) {
22+
23+
return glslMethods[ method ] || method;
24+
25+
}
26+
27+
getTexture( texture, textureProperty, uvSnippet ) {
28+
29+
if ( texture.isTextureCube ) {
30+
31+
return `textureCube( ${textureProperty}, ${uvSnippet} )`;
32+
33+
} else {
34+
35+
return `texture2D( ${textureProperty}, ${uvSnippet} )`;
36+
37+
}
38+
39+
}
40+
41+
getTextureBias( texture, textureProperty, uvSnippet, biasSnippet ) {
42+
43+
if ( this.material.extensions !== undefined ) this.material.extensions.shaderTextureLOD = true;
44+
45+
return `textureLod( ${textureProperty}, ${uvSnippet}, ${biasSnippet} )`;
46+
47+
}
48+
49+
getVars( shaderStage ) {
50+
51+
const snippets = [];
52+
53+
const vars = this.vars[ shaderStage ];
54+
55+
for ( const variable of vars ) {
56+
57+
snippets.push( `${ this.getVar( variable.type, variable.name ) };` );
58+
59+
}
60+
61+
return snippets.join( '\n\t' );
62+
63+
}
64+
65+
getUniforms( shaderStage ) {
66+
67+
const uniforms = this.uniforms[ shaderStage ];
68+
69+
let output = '';
70+
71+
for ( const uniform of uniforms ) {
72+
73+
let snippet = null;
74+
75+
if ( uniform.type === 'texture' ) {
76+
77+
snippet = `sampler2D ${uniform.name};\n`;
78+
79+
} else if ( uniform.type === 'cubeTexture' ) {
80+
81+
snippet = `samplerCube ${uniform.name};\n`;
82+
83+
} else {
84+
85+
const vectorType = this.getVectorType( uniform.type );
86+
87+
snippet = `${vectorType} ${uniform.name};\n`;
88+
89+
}
90+
91+
const precision = uniform.node.precision;
92+
93+
if ( precision !== null ) {
94+
95+
snippet = 'uniform ' + precisionLib[ precision ] + ' ' + snippet;
96+
97+
} else {
98+
99+
snippet = 'uniform ' + snippet;
100+
101+
}
102+
103+
output += snippet;
104+
105+
}
106+
107+
return output;
108+
109+
}
110+
111+
getAttributes( shaderStage ) {
112+
113+
let snippet = '';
114+
115+
if ( shaderStage === 'vertex' ) {
116+
117+
const attributes = this.attributes;
118+
119+
for ( const attribute of attributes ) {
120+
121+
snippet += `attribute ${attribute.type} ${attribute.name};\n`;
122+
123+
}
124+
125+
}
126+
127+
return snippet;
128+
129+
}
130+
131+
getVaryings( shaderStage ) {
132+
133+
let snippet = '';
134+
135+
const varyings = this.varyings;
136+
137+
if ( shaderStage === 'vertex' ) {
138+
139+
for ( const varying of varyings ) {
140+
141+
snippet += `${varying.needsInterpolation ? 'varying' : '/*varying*/'} ${varying.type} ${varying.name};\n`;
142+
143+
}
144+
145+
} else if ( shaderStage === 'fragment' ) {
146+
147+
for ( const varying of varyings ) {
148+
149+
if ( varying.needsInterpolation ) {
150+
151+
snippet += `varying ${varying.type} ${varying.name};\n`;
152+
153+
}
154+
155+
}
156+
157+
}
158+
159+
return snippet;
160+
161+
}
162+
163+
getFrontFacing() {
164+
165+
return 'gl_FrontFacing';
166+
167+
}
168+
169+
getFragCoord() {
170+
171+
return 'gl_FragCoord';
172+
173+
}
174+
175+
isFlipY() {
176+
177+
return true;
178+
179+
}
180+
181+
_getGLSLVertexCode( shaderData ) {
182+
183+
return `${ this.getSignature() }
184+
185+
// uniforms
186+
${shaderData.uniforms}
187+
188+
// varyings
189+
${shaderData.varyings}
190+
191+
// attributes
192+
${shaderData.attributes}
193+
194+
// codes
195+
${shaderData.codes}
196+
197+
void main() {
198+
199+
// vars
200+
${shaderData.vars}
201+
202+
// flow
203+
${shaderData.flow}
204+
205+
}
206+
`;
207+
208+
}
209+
210+
_getGLSLFragmentCode( shaderData ) {
211+
212+
return `${ this.getSignature() }
213+
214+
// precision
215+
precision highp float;
216+
precision highp int;
217+
218+
// uniforms
219+
${shaderData.uniforms}
220+
221+
// varyings
222+
${shaderData.varyings}
223+
224+
// codes
225+
${shaderData.codes}
226+
227+
void main() {
228+
229+
// vars
230+
${shaderData.vars}
231+
232+
// flow
233+
${shaderData.flow}
234+
235+
}
236+
`;
237+
238+
}
239+
240+
buildCode() {
241+
242+
const shadersData = this.material !== null ? { fragment: {}, vertex: {} } : { compute: {} };
243+
244+
for ( const shaderStage in shadersData ) {
245+
246+
let flow = '// code\n\n';
247+
flow += this.flowCode[ shaderStage ];
248+
249+
const flowNodes = this.flowNodes[ shaderStage ];
250+
const mainNode = flowNodes[ flowNodes.length - 1 ];
251+
252+
for ( const node of flowNodes ) {
253+
254+
const flowSlotData = this.getFlowData( node/*, shaderStage*/ );
255+
const slotName = node.name;
256+
257+
if ( slotName ) {
258+
259+
if ( flow.length > 0 ) flow += '\n';
260+
261+
flow += `\t// flow -> ${ slotName }\n\t`;
262+
263+
}
264+
265+
flow += `${ flowSlotData.code }\n\t`;
266+
267+
if ( node === mainNode && shaderStage !== 'compute' ) {
268+
269+
flow += '// result\n\t';
270+
271+
if ( shaderStage === 'vertex' ) {
272+
273+
flow += 'gl_Position = ';
274+
275+
} else if ( shaderStage === 'fragment' ) {
276+
277+
flow += 'gl_FragColor = ';
278+
279+
}
280+
281+
flow += `${ flowSlotData.result };`;
282+
283+
}
284+
285+
}
286+
287+
const stageData = shadersData[ shaderStage ];
288+
289+
stageData.uniforms = this.getUniforms( shaderStage );
290+
stageData.attributes = this.getAttributes( shaderStage );
291+
stageData.varyings = this.getVaryings( shaderStage );
292+
stageData.vars = this.getVars( shaderStage );
293+
stageData.codes = this.getCodes( shaderStage );
294+
stageData.flow = flow;
295+
296+
}
297+
298+
if ( this.material !== null ) {
299+
300+
this.vertexShader = this._getGLSLVertexCode( shadersData.vertex );
301+
this.fragmentShader = this._getGLSLFragmentCode( shadersData.fragment );
302+
303+
} else {
304+
305+
console.warn( 'GLSLNodeBuilder: compute shaders are not supported.' );
306+
//this.computeShader = this._getGLSLComputeCode( shadersData.compute );
307+
308+
}
309+
310+
}
311+
312+
build() {
313+
314+
// @TODO: Move this code to super.build()
315+
316+
const { object, material } = this;
317+
318+
if ( material !== null ) {
319+
320+
NodeMaterial.fromMaterial( material ).build( this );
321+
322+
} else {
323+
324+
this.addFlow( 'compute', object );
325+
326+
}
327+
328+
return super.build();
329+
330+
}
331+
332+
}
333+
334+
export default GLSLNodeBuilder;

examples/jsm/renderers/webgl/nodes/WebGLNodeBuilder.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,9 @@ class WebGLNodeBuilder extends NodeBuilder {
447447

448448
for ( const uniform of uniforms ) {
449449

450+
if ( /^(modelViewMatrix|projectionMatrix)$/.test( uniform.name ) )
451+
continue;
452+
450453
let snippet = null;
451454

452455
if ( uniform.type === 'texture' ) {

0 commit comments

Comments
 (0)