From 11e7f63af9fc2d0f6c5329528df77f7650d5e27a Mon Sep 17 00:00:00 2001 From: Olli Etuaho Date: Tue, 17 Sep 2019 18:04:16 +0300 Subject: [PATCH] Add callback to identify customized programs In case onBeforeCompile has conditional statements in it, the parameter values affecting the shader code can be returned from customProgramCode so the shader program is correctly fetched from cache or recompiled as needed. --- docs/api/en/materials/Material.html | 30 ++++++++++++++++++++++++++++ src/materials/Material.d.ts | 5 +++++ src/materials/Material.js | 6 ++++++ src/renderers/webgl/WebGLPrograms.js | 4 ++-- 4 files changed, 43 insertions(+), 2 deletions(-) diff --git a/docs/api/en/materials/Material.html b/docs/api/en/materials/Material.html index 09db0f2131416e..4cda1c4b403a86 100644 --- a/docs/api/en/materials/Material.html +++ b/docs/api/en/materials/Material.html @@ -343,6 +343,36 @@

[method:null onBeforeCompile]( [param:Shader shader], [param:WebGLRenderer r Unlike properties, the callback is not supported by [page:Material.clone .clone](), [page:Material.copy .copy]() and [page:Material.toJSON .toJSON]().

+

[method:String customProgramCacheKey]()

+

+ In case onBeforeCompile is used, this callback can be used to identify values of settings used in onBeforeCompile, so three.js can reuse a cached shader or recompile the shader for this material as needed. +

+ +

+ For example, if onBeforeCompile contains a conditional statement like:
+ + if ( black ) { + + shader.fragmentShader = shader.fragmentShader.replace('gl_FragColor = vec4(1)', 'gl_FragColor = vec4(0)') + + } + + + then customProgramCacheKey should be set like this:
+ + material.customProgramCacheKey = function() { + + return black ? '1' : '0'; + + } + + +

+ +

+ Unlike properties, the callback is not supported by [page:Material.clone .clone](), [page:Material.copy .copy]() and [page:Material.toJSON .toJSON](). +

+

[method:null setValues]( [param:object values] )

values -- a container with parameters.
diff --git a/src/materials/Material.d.ts b/src/materials/Material.d.ts index cdec1d114f0ae4..78de72aaa4069f 100644 --- a/src/materials/Material.d.ts +++ b/src/materials/Material.d.ts @@ -334,6 +334,11 @@ export class Material extends EventDispatcher { */ onBeforeCompile ( shader : Shader, renderer : WebGLRenderer ) : void; + /** + * In case onBeforeCompile is used, this callback can be used to identify values of settings used in onBeforeCompile, so three.js can reuse a cached shader or recompile the shader as needed. + */ + customProgramCacheKey(): string; + /** * Sets the properties based on the values. * @param values A container with parameters. diff --git a/src/materials/Material.js b/src/materials/Material.js index 3967f5d1aa3269..ca3af21793af38 100644 --- a/src/materials/Material.js +++ b/src/materials/Material.js @@ -86,6 +86,12 @@ Material.prototype = Object.assign( Object.create( EventDispatcher.prototype ), onBeforeCompile: function () {}, + customProgramCacheKey: function () { + + return this.onBeforeCompile.toString(); + + }, + setValues: function ( values ) { if ( values === undefined ) return; diff --git a/src/renderers/webgl/WebGLPrograms.js b/src/renderers/webgl/WebGLPrograms.js index b710c186c38823..9bba41e71126ca 100644 --- a/src/renderers/webgl/WebGLPrograms.js +++ b/src/renderers/webgl/WebGLPrograms.js @@ -288,7 +288,7 @@ function WebGLPrograms( renderer, extensions, capabilities ) { rendererExtensionDrawBuffers: isWebGL2 || extensions.get( 'WEBGL_draw_buffers' ) !== null, rendererExtensionShaderTextureLod: isWebGL2 || extensions.get( 'EXT_shader_texture_lod' ) !== null, - onBeforeCompile: material.onBeforeCompile + customProgramCacheKey: material.customProgramCacheKey() }; @@ -335,7 +335,7 @@ function WebGLPrograms( renderer, extensions, capabilities ) { } - array.push( parameters.onBeforeCompile.toString() ); + array.push( parameters.customProgramCacheKey ); return array.join();