All in one shader code
See original GitHub issueAn additional shader
property on ShaderMaterial that allows vertexs and fragment shaders in one code with a shared header would be useful. Declaring varyings or uniforms twice isn’t needed this way. Basically the property just parses the code and applies the properties to the ShaderMaterial. This way constants/defines, side, wireframe and other properties of ShaderMaterial could be declared as json too.
Additionally it could grab global uniforms stored in THREE.globals
or similar.
The AIO shader code could look like this:
varying vec2 vUv;
@ properties {
"side": "doubleSide"
}
@ vertex {
uniform float uTime;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
}
@ fragment {
uniform sampler2D map;
void main() {
gl_FragColor = texture2D(map, vUv);
}
}
Shader property pseudo code: `
THREE.globals = {};
Object.assign(THREE.ShaderMaterial.prototype, {
shaderCode: '',
get shader() {
return this.shaderCode
},
set shader( value ) {
this.shaderCode = value;
var name, type, uniform, match;
// Parse uniforms
var R_UNIFORMS = /uniform.([^ |\[]+).([A-z][^ |;|\[]+)/g;
var R_SECTORS = /@*([a-z]+).*\{([^@]+)}/g;
while ( match = R_UNIFORMS.exec(value) ) {
if ( match.length == 3 ) {
type = match[1];
name = match[2];
if ( THREE.globals[name] !== undefined ) {
this.uniforms[name] = THREE.globals[name];
}
}
}
// Header
var header = '';
match = /([^@]+)@/.exec(value);
if ( match ) {
header = match[1];
}
// Sectors
match = /@([a-z]+).*.\{([^@]+)\}/g.exec(value);
while ( match = R_SECTORS.exec(value) ) {
switch ( match[1] ) {
case 'vertex':
this.vertexShader = header + match[2];
break;
case 'fragment':
this.fragmentShader = header + match[2];
break;
case 'defines':
const defines = JSON.parse(match[2]);
for ( var name in defines ) {
this.defines[name] = defines[name];
}
break;
}
}
}
});`
Most engines use a custom extended shader language with preprocessing for similar tasks, THREE also already does some preprocessing. It’s just easier to work with.
It might cause syntax errors in some fancy editors when using glsl though, so it would require an adpation for that purpose. In my case i use Notepad++ for shaders with C++ highlighter, it already doesn’t error markup anything and bracketfolding works. I also use a Ace based editor, which can be extended with the regex rules.
Issue Analytics
- State:
- Created 6 years ago
- Reactions:2
- Comments:7 (5 by maintainers)
I think you should be able to extend
RawShaderMaterial
and useonBeforeCompile()
?Closing. The additional benefits do not justify the additional complexity in
ShaderMaterial
.“Smart” approaches are not always better. They often complicate things and lead to unexpected behaviors/side effects. Better to keep things simple and explicitly define vertex and fragment shader on its own.