Closed WestLangley closed 10 years ago
I noticed that there has been discussion for a while, about how to write shaders in Three.js in an easier way, without commas and quotations.
I'm currently writing GLSL shaders in external files (.vert, .frag) and then using AJAX to load the contents in, non-asynchronously. Seems to work for what I need to do.
Is there any particular reason why such an approach is not considered?
Is there any particular reason why such an approach is not considered?
Saving on network requests?
one reason why you may not want to put your code in comments is that js minifiers may just strip out the code.
on moving shader code into vert and frag files is worth considering - we could have an automated build tool which codgens our current shader compatible code (in a way like this)
@skeelogy, i realized we have met once in life at DN few years back :)
@mrdoob Yes that makes sense. Just curious.
@zz85 Wow, didn't know that it's you, from your username. Great to see that you are doing so well here!
one reason why you may not want to put your code in comments is that js minifiers may just strip out the code.
OK, well that shoots down this idea...
@zz85 I think has the best approach, IMHO
@zz85 good point!
@preserve
is a jsdoc tag which preserve the comment. it is used to preserve comment which contains license text. it may fix the issue but it makes it less eleguant.
apparently i cant make uglify to keep this comment, with or without @preserve
.
so i agree with @WestLangley it likely kills the idea.
@skeelogy i'm a nobody here, but nice to see you adopting three.js too :)
@mrdoob @WestLangley i'll try to pen my thoughts and come up with a poc later if we're still interested to pursue a better way to write shaders here.
Actually I wouldn't change much at how we are writing shaders for now. But I think of writing a new layer on top of the existing layer which makes use of shadernodes, like in blender.
this brings up the discussion we had eariler in #2162
@gero3 what you're want might be similiar to @unconed's https://github.com/unconed/ShaderGraph.js
The pain currently we have writing shader code the way we do it is this:
Altough shadergraph is similar to what I mean, It wouldn't be possible to create the base three.js shaders. There are a bit of problems with the way it defines nodes.
If 1 to 3 are the only requirements, then a build system with the shader chunks defined in files with extension glsl. And if we need to use shaderchunks in othere file we use a macro of format '#define THREEJSSHADERCHUNK{NAME}'. And if we use the correct indentation in the chunks, Then we have all 3 points. The build system would then just convert them back to the old system. The only problem i see with this is that the minified file will be larger due to indentation in the strings.
- the way we currently format shader code lose indentation when its compiled into the shader. not a problem to most people, but eyes hurt when you're trying to edit and debug shader code in the console.
That's fairly easy to solve.
The only problem i see with this is that the minified file will be larger due to indentation in the strings.
I think that's ok...
OK, here is @mrdoob's suggestion. Indentation is via tabs. It remains to see how well it works with ShaderChunks....
THREE.Shader = {
'shader1' : {
vertexShader : [
"#ifdef USE_LIGHTMAP",
" varying vec2 vUv2;",
"#endif",
"varying vec3 vNormal;",
"void main() {",
" #ifdef USE_LIGHTMAP",
" vUv2 = uv2;",
" #endif",
" vNormal = normalize( normalMatrix * normal );",
" gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
"}"
].join("\n")
}
};
console.log( THREE.Shader[ 'shader1' ].vertexShader );
#ifdef USE_LIGHTMAP
varying vec2 vUv2;
#endif
varying vec3 vNormal;
void main() {
#ifdef USE_LIGHTMAP
vUv2 = uv2;
#endif
vNormal = normalize( normalMatrix * normal );
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
@mrdoob is there something to modify existing materials in new refactored renderer ? Currently modifying existing materials isnt easy. either we use existing shaders, or we fall back on THREE.ShaderMaterial which is very raw to say the least.
suppose devs need to do some funky displacement in the vertex shader... devs need to clone the original material shader, say phong one, and modify the shader. All properties must be done manually in shader.uniforms.
not the ideal situation.
could we think about this while it is possible with the renderer refactorisation ?
Yup. That's something I keep in mind while reworking the renderer. It'll take me some time though.
my proposal is along the lines of what @gero3 says.
we place all glsl files with some marco template format in a directory structure.
build tool comes picks up all these files and auto generates code compatible to what we have right now (that is into our src directory).
i don't think additional bytes/indentation in final shader code is a big issue - we can have a DEVELOPMENT flag which preserves indentation, otherwise strip whitespace. then we wouldn't worry about how shader code should be formatted, and i think it makes it more friendly for others to try editing/contributing shader code.
besides: double quoting every line isn't the most space efficient compare to 'line0line0line0line'.split(0) // where 0 is unique character ;) my point being - allowing a tool to decide how it decides to generate the code would be better than us enforcing how the code should be written.
thoughts?
Ah just realized what I said about the string splitting thing is silly. Just need "Line1\nline2"
I'm thinking that pursuing a new shader coding pattern is not worth it. @zz85's deficiencies 1-3 are not that bad, IMHO.
From this discussion, it sounds like that a visual editor for creating ShaderMaterial-based shaders is what would be the most useful rather than changing the coding pattern, e.g. something like the Blender one mentioned above or Minko ShaderLab
It would be a great complement to the already good material editor that is in the three.js editor.
I was thinking of starting a Wiki page on "shader best practices," to help clarify how best to do shader work through some examples... But if things are about to be reworked, maybe it's better to wait. The current system seems to direct all custom shader work to ShaderMaterial, but I usually want to make a slight change to one of the base (Phong, Lambert, Particle..) materials. It would be great if you could add a custom uniform / attribute to Phong, and then override one of the shader chunks. Based on comments I've read on stackoverflow, you can't really do that. If not, that would be a key requirement for the new system - selfishly speaking :) .
Ah just realized what I said about the string splitting thing is silly. Just need "Line1\nline2"
Closure Compiler already does that for us. If you look at the minified file all the ["",""].join('\n')
stuff gets converted to single strings.
It would be a great complement to the already good material editor that is in the three.js editor.
All in good time :)
for those who still pursuing for a easier/different way to write shaders, ShaderDSL could be another interesting approach http://typedarray.org/shaderdsl-js-javascript-based-dsls-for-gpu-shaders/
@jeromeetienne has posted a gist with an interesting proposal. In it, he proposes a new pattern for coding shaders. I have provided some three.js-specific examples here.
Below,
shader1
uses the current pattern;shader2
uses the new pattern. Notice thatshader2
avoids the use of quotes and commas. It is also more readable in debug output.