diff --git a/examples/files.js b/examples/files.js index fb8ce946c12344..4248d0f545ca0c 100644 --- a/examples/files.js +++ b/examples/files.js @@ -179,6 +179,7 @@ var files = { "webgl_materials_video", "webgl_materials_video_webcam", "webgl_materials_wireframe", + 'webgl_materials_shader_override', "webgl_mirror", "webgl_mirror_nodes", "webgl_modifier_simplifier", diff --git a/examples/webgl_materials_modified.html b/examples/webgl_materials_modified.html index 0cd0ec48609841..a5f9a5f845e652 100644 --- a/examples/webgl_materials_modified.html +++ b/examples/webgl_materials_modified.html @@ -91,29 +91,59 @@ scene = new THREE.Scene(); var material = new THREE.MeshNormalMaterial(); - material.onBeforeCompile = function ( shader ) { - // console.log( shader ) + // BEGIN custom shader injection ---- - shader.uniforms.time = { value: 0 }; + var myShader = [ + 'float theta = sin( time + position.y ) / 2.0;', + 'float c = cos( theta );', + 'float s = sin( theta );', + 'mat3 m = mat3( c, 0, s, 0, 1, 0, -s, 0, c );', + 'vec3 transformed = vec3( position ) * m;', + 'vNormal = vNormal * m;' + ].join( '\n' ); - shader.vertexShader = 'uniform float time;\n' + shader.vertexShader; - shader.vertexShader = shader.vertexShader.replace( - '#include ', - [ - 'float theta = sin( time + position.y ) / 2.0;', - 'float c = cos( theta );', - 'float s = sin( theta );', - 'mat3 m = mat3( c, 0, s, 0, 1, 0, -s, 0, c );', - 'vec3 transformed = vec3( position ) * m;', - 'vNormal = vNormal * m;' - ].join( '\n' ) - ); + material.shaderIncludes = { - materialShader = shader; + begin_vertex: myShader, + global_vertex: 'uniform float time;\n' + + }; + + material.shaderUniforms = { + time: { value: 0 } }; + //OR + + // material.shaderIncludes = { + + // begin_vertex: myShader, + + // }; + + // material.shaderUniforms = { + // time: { value: 0 , type:'float' } //if type is provided the uniform will be injected automatically + // }; + + materialShader = material; + + // material.onBeforeCompile = function ( shader ) { + + // shader.uniforms.time = { value: 0 }; + + // shader.vertexShader = 'uniform float time;\n' + shader.vertexShader; + + // shader.vertexShader = shader.vertexShader.replace( + // '#include ', + // myShader + // ); + + // materialShader = shader; + + // }; + loader = new THREE.JSONLoader(); loader.load( "obj/leeperrysmith/LeePerrySmith.js", function( geometry ) { @@ -188,7 +218,8 @@ if ( materialShader ) { - materialShader.uniforms.time.value = performance.now() / 1000; + // materialShader.uniforms.time.value = performance.now() / 1000; + materialShader.shaderUniforms.time.value = performance.now() / 1000; } diff --git a/examples/webgl_materials_shader_override.html b/examples/webgl_materials_shader_override.html new file mode 100644 index 00000000000000..1f9f163c53552d --- /dev/null +++ b/examples/webgl_materials_shader_override.html @@ -0,0 +1,333 @@ + + + + three.js webgl - shader include override example + + + + + +
+ three.js - Material shader override example by pailhead +
+ + + + + + + + + + + + + + + + + + + + diff --git a/src/renderers/WebGLRenderer.js b/src/renderers/WebGLRenderer.js index 80c55d8e9b1413..211acd181754f7 100644 --- a/src/renderers/WebGLRenderer.js +++ b/src/renderers/WebGLRenderer.js @@ -1496,15 +1496,35 @@ function WebGLRenderer( parameters ) { if ( programChange ) { + var shaderUniformsGLSL = '' + if ( parameters.shaderID ) { var shader = ShaderLib[ parameters.shaderID ]; + var computedUniforms = undefined !== material.shaderUniforms ? + UniformsUtils.merge([ UniformsUtils.clone( shader.uniforms ) , material.shaderUniforms ]) : + UniformsUtils.clone( shader.uniforms ); + + //if shader uniforms are present + for ( var u in material.shaderUniforms ) { + + var uniform = material.shaderUniforms[ u ]; + var type = uniform.type; + + if ( type ) { + + shaderUniformsGLSL += 'uniform ' + type + ' ' + u + ';\n' + + } + + } + materialProperties.shader = { name: material.type, - uniforms: UniformsUtils.clone( shader.uniforms ), - vertexShader: shader.vertexShader, - fragmentShader: shader.fragmentShader + uniforms: computedUniforms, + vertexShader: shaderUniformsGLSL + shader.vertexShader, + fragmentShader: shaderUniformsGLSL + shader.fragmentShader }; } else { @@ -1822,6 +1842,16 @@ function WebGLRenderer( parameters ) { } + //follow the same pattern with common uniforms - + //refreshUniformsCommon looks at some known uniforms and refreshes them + //refreshUniformsCustom should look at unknown uniforms but in a known place + + if ( undefined !== material.shaderUniforms ) { + + refreshUniformsCustom( m_uniforms, material ); + + } + // refresh uniforms common to several materials if ( fog && material.fog ) { @@ -2063,6 +2093,17 @@ function WebGLRenderer( parameters ) { } + //same pattern as refreshUniformsFOO + function refreshUniformsCustom( uniforms, material ) { + + for ( var uniform in material.shaderUniforms ) { + + uniforms[ uniform ].value = material.shaderUniforms[ uniform ].value; + + } + + } + function refreshUniformsLine( uniforms, material ) { uniforms.diffuse.value = material.color; diff --git a/src/renderers/shaders/ShaderChunk.js b/src/renderers/shaders/ShaderChunk.js index 92b3840d782c01..39b46b91faab06 100644 --- a/src/renderers/shaders/ShaderChunk.js +++ b/src/renderers/shaders/ShaderChunk.js @@ -32,6 +32,8 @@ import fog_vertex from './ShaderChunk/fog_vertex.glsl'; import fog_pars_vertex from './ShaderChunk/fog_pars_vertex.glsl'; import fog_fragment from './ShaderChunk/fog_fragment.glsl'; import fog_pars_fragment from './ShaderChunk/fog_pars_fragment.glsl'; +import global_fragment from './ShaderChunk/global_fragment.glsl'; +import global_vertex from './ShaderChunk/global_vertex.glsl'; import gradientmap_pars_fragment from './ShaderChunk/gradientmap_pars_fragment.glsl'; import lightmap_fragment from './ShaderChunk/lightmap_fragment.glsl'; import lightmap_pars_fragment from './ShaderChunk/lightmap_pars_fragment.glsl'; @@ -144,6 +146,8 @@ export var ShaderChunk = { fog_pars_vertex: fog_pars_vertex, fog_fragment: fog_fragment, fog_pars_fragment: fog_pars_fragment, + global_fragment: global_fragment, + global_vertex: global_vertex, gradientmap_pars_fragment: gradientmap_pars_fragment, lightmap_fragment: lightmap_fragment, lightmap_pars_fragment: lightmap_pars_fragment, diff --git a/src/renderers/shaders/ShaderChunk/global_fragment.glsl b/src/renderers/shaders/ShaderChunk/global_fragment.glsl new file mode 100644 index 00000000000000..9b719e45bf7674 --- /dev/null +++ b/src/renderers/shaders/ShaderChunk/global_fragment.glsl @@ -0,0 +1 @@ +// template for injecting varying, uniform and functions above main below other includes \ No newline at end of file diff --git a/src/renderers/shaders/ShaderChunk/global_vertex.glsl b/src/renderers/shaders/ShaderChunk/global_vertex.glsl new file mode 100644 index 00000000000000..768496dc72ee03 --- /dev/null +++ b/src/renderers/shaders/ShaderChunk/global_vertex.glsl @@ -0,0 +1 @@ +// template for injecting varying, uniform , attributes and functions above main below other includes \ No newline at end of file diff --git a/src/renderers/shaders/ShaderLib/depth_frag.glsl b/src/renderers/shaders/ShaderLib/depth_frag.glsl index 4078a9c68fe797..ebe5c00429bbfc 100644 --- a/src/renderers/shaders/ShaderLib/depth_frag.glsl +++ b/src/renderers/shaders/ShaderLib/depth_frag.glsl @@ -11,6 +11,7 @@ #include #include #include +#include void main() { diff --git a/src/renderers/shaders/ShaderLib/depth_vert.glsl b/src/renderers/shaders/ShaderLib/depth_vert.glsl index edf12fb744183b..95c77b8eaccffd 100644 --- a/src/renderers/shaders/ShaderLib/depth_vert.glsl +++ b/src/renderers/shaders/ShaderLib/depth_vert.glsl @@ -5,6 +5,7 @@ #include #include #include +#include void main() { diff --git a/src/renderers/shaders/ShaderLib/distanceRGBA_frag.glsl b/src/renderers/shaders/ShaderLib/distanceRGBA_frag.glsl index 8dbf8f401106d1..9246cca52c951d 100644 --- a/src/renderers/shaders/ShaderLib/distanceRGBA_frag.glsl +++ b/src/renderers/shaders/ShaderLib/distanceRGBA_frag.glsl @@ -11,6 +11,7 @@ varying vec3 vWorldPosition; #include #include #include +#include void main () { diff --git a/src/renderers/shaders/ShaderLib/distanceRGBA_vert.glsl b/src/renderers/shaders/ShaderLib/distanceRGBA_vert.glsl index abecdefa7fc0c2..2839addbbbfe28 100644 --- a/src/renderers/shaders/ShaderLib/distanceRGBA_vert.glsl +++ b/src/renderers/shaders/ShaderLib/distanceRGBA_vert.glsl @@ -8,6 +8,7 @@ varying vec3 vWorldPosition; #include #include #include +#include void main() { diff --git a/src/renderers/shaders/ShaderLib/linedashed_frag.glsl b/src/renderers/shaders/ShaderLib/linedashed_frag.glsl index 3c93173641c085..cb866c32b50708 100644 --- a/src/renderers/shaders/ShaderLib/linedashed_frag.glsl +++ b/src/renderers/shaders/ShaderLib/linedashed_frag.glsl @@ -11,6 +11,7 @@ varying float vLineDistance; #include #include #include +#include void main() { diff --git a/src/renderers/shaders/ShaderLib/linedashed_vert.glsl b/src/renderers/shaders/ShaderLib/linedashed_vert.glsl index 5d7057dbf1d623..980e7803e1a336 100644 --- a/src/renderers/shaders/ShaderLib/linedashed_vert.glsl +++ b/src/renderers/shaders/ShaderLib/linedashed_vert.glsl @@ -8,6 +8,7 @@ varying float vLineDistance; #include #include #include +#include void main() { diff --git a/src/renderers/shaders/ShaderLib/meshbasic_frag.glsl b/src/renderers/shaders/ShaderLib/meshbasic_frag.glsl index f0bc5397258a33..56ecf6c28e59f1 100644 --- a/src/renderers/shaders/ShaderLib/meshbasic_frag.glsl +++ b/src/renderers/shaders/ShaderLib/meshbasic_frag.glsl @@ -20,6 +20,7 @@ uniform float opacity; #include #include #include +#include void main() { diff --git a/src/renderers/shaders/ShaderLib/meshbasic_vert.glsl b/src/renderers/shaders/ShaderLib/meshbasic_vert.glsl index 20f3c15cbfe6bd..0e51bd7160cf4f 100644 --- a/src/renderers/shaders/ShaderLib/meshbasic_vert.glsl +++ b/src/renderers/shaders/ShaderLib/meshbasic_vert.glsl @@ -8,6 +8,7 @@ #include #include #include +#include void main() { diff --git a/src/renderers/shaders/ShaderLib/meshlambert_frag.glsl b/src/renderers/shaders/ShaderLib/meshlambert_frag.glsl index aeb9571696b8bd..8063aaf9eb0d92 100644 --- a/src/renderers/shaders/ShaderLib/meshlambert_frag.glsl +++ b/src/renderers/shaders/ShaderLib/meshlambert_frag.glsl @@ -30,6 +30,7 @@ varying vec3 vLightFront; #include #include #include +#include void main() { diff --git a/src/renderers/shaders/ShaderLib/meshlambert_vert.glsl b/src/renderers/shaders/ShaderLib/meshlambert_vert.glsl index 2498399bc05577..09bacb0a359bc6 100644 --- a/src/renderers/shaders/ShaderLib/meshlambert_vert.glsl +++ b/src/renderers/shaders/ShaderLib/meshlambert_vert.glsl @@ -21,6 +21,7 @@ varying vec3 vLightFront; #include #include #include +#include void main() { diff --git a/src/renderers/shaders/ShaderLib/meshphong_frag.glsl b/src/renderers/shaders/ShaderLib/meshphong_frag.glsl index 0bf233740a6aec..377a6ae9076b9d 100644 --- a/src/renderers/shaders/ShaderLib/meshphong_frag.glsl +++ b/src/renderers/shaders/ShaderLib/meshphong_frag.glsl @@ -29,6 +29,7 @@ uniform float opacity; #include #include #include +#include void main() { diff --git a/src/renderers/shaders/ShaderLib/meshphong_vert.glsl b/src/renderers/shaders/ShaderLib/meshphong_vert.glsl index e79d5fe416750c..79b9233eef9bbb 100644 --- a/src/renderers/shaders/ShaderLib/meshphong_vert.glsl +++ b/src/renderers/shaders/ShaderLib/meshphong_vert.glsl @@ -20,6 +20,7 @@ varying vec3 vViewPosition; #include #include #include +#include void main() { diff --git a/src/renderers/shaders/ShaderLib/meshphysical_frag.glsl b/src/renderers/shaders/ShaderLib/meshphysical_frag.glsl index a66b04c764e86d..e2074314fe2543 100644 --- a/src/renderers/shaders/ShaderLib/meshphysical_frag.glsl +++ b/src/renderers/shaders/ShaderLib/meshphysical_frag.glsl @@ -43,6 +43,7 @@ varying vec3 vViewPosition; #include #include #include +#include void main() { diff --git a/src/renderers/shaders/ShaderLib/meshphysical_vert.glsl b/src/renderers/shaders/ShaderLib/meshphysical_vert.glsl index 4dbc2d41e02811..388b59f94f1892 100644 --- a/src/renderers/shaders/ShaderLib/meshphysical_vert.glsl +++ b/src/renderers/shaders/ShaderLib/meshphysical_vert.glsl @@ -19,6 +19,7 @@ varying vec3 vViewPosition; #include #include #include +#include void main() { diff --git a/src/renderers/shaders/ShaderLib/normal_frag.glsl b/src/renderers/shaders/ShaderLib/normal_frag.glsl index 705efad90964f2..0db7fad86d8609 100644 --- a/src/renderers/shaders/ShaderLib/normal_frag.glsl +++ b/src/renderers/shaders/ShaderLib/normal_frag.glsl @@ -19,6 +19,7 @@ uniform float opacity; #include #include #include +#include void main() { diff --git a/src/renderers/shaders/ShaderLib/normal_vert.glsl b/src/renderers/shaders/ShaderLib/normal_vert.glsl index 034d580c983e27..f464063db234bc 100644 --- a/src/renderers/shaders/ShaderLib/normal_vert.glsl +++ b/src/renderers/shaders/ShaderLib/normal_vert.glsl @@ -17,6 +17,7 @@ #include #include #include +#include void main() { diff --git a/src/renderers/shaders/ShaderLib/points_frag.glsl b/src/renderers/shaders/ShaderLib/points_frag.glsl index f42755951722e7..11c48131a04ec4 100644 --- a/src/renderers/shaders/ShaderLib/points_frag.glsl +++ b/src/renderers/shaders/ShaderLib/points_frag.glsl @@ -9,6 +9,7 @@ uniform float opacity; #include #include #include +#include void main() { diff --git a/src/renderers/shaders/ShaderLib/points_vert.glsl b/src/renderers/shaders/ShaderLib/points_vert.glsl index a3cb26d2d32c84..2fbe8870c44c2e 100644 --- a/src/renderers/shaders/ShaderLib/points_vert.glsl +++ b/src/renderers/shaders/ShaderLib/points_vert.glsl @@ -7,6 +7,7 @@ uniform float scale; #include #include #include +#include void main() { diff --git a/src/renderers/webgl/WebGLProgram.js b/src/renderers/webgl/WebGLProgram.js index f8915534a354f7..1f60e4321a7e83 100644 --- a/src/renderers/webgl/WebGLProgram.js +++ b/src/renderers/webgl/WebGLProgram.js @@ -150,13 +150,13 @@ function replaceLightNums( string, parameters ) { } -function parseIncludes( string ) { +function parseIncludes( string , materialIncludes ) { var pattern = /^[ \t]*#include +<([\w\d.]+)>/gm; function replace( match, include ) { - var replace = ShaderChunk[ include ]; + var replace = undefined !== materialIncludes[ include ] ? materialIncludes[ include ] : ShaderChunk[ include ]; if ( replace === undefined ) { @@ -200,6 +200,9 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters var defines = material.defines; + + var materialIncludes = material.shaderIncludes; + var vertexShader = shader.vertexShader; var fragmentShader = shader.fragmentShader; @@ -281,6 +284,8 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters var customDefines = generateDefines( defines ); + var customIncludes = undefined !== materialIncludes ? materialIncludes : {}; + // var program = gl.createProgram(); @@ -500,10 +505,11 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters } - vertexShader = parseIncludes( vertexShader ); + vertexShader = parseIncludes( vertexShader, customIncludes ); vertexShader = replaceLightNums( vertexShader, parameters ); - fragmentShader = parseIncludes( fragmentShader ); + fragmentShader = parseIncludes( fragmentShader, customIncludes ); + fragmentShader = replaceLightNums( fragmentShader, parameters ); if ( ! material.isShaderMaterial ) { diff --git a/src/renderers/webgl/WebGLPrograms.js b/src/renderers/webgl/WebGLPrograms.js index 633a3397e7c7a1..86262f8b6711f0 100644 --- a/src/renderers/webgl/WebGLPrograms.js +++ b/src/renderers/webgl/WebGLPrograms.js @@ -241,10 +241,18 @@ function WebGLPrograms( renderer, extensions, capabilities ) { } - array.push( material.onBeforeCompile.toString() ); + if ( material.shaderIncludes !== undefined ){ - array.push( renderer.gammaOutput ); + for( var include in material.shaderIncludes ){ + + array.push( material.shaderIncludes[ include ] ); + + } + } + + array.push( renderer.gammaOutput ); + return array.join(); };