Browse Source

Merge pull request #19833 from sunag/dev-gethash

NodeMaterial: getHash and customProgramCacheKey
Mr.doob 5 years ago
parent
commit
d09193d21c

+ 2 - 0
examples/jsm/nodes/core/InputNode.js

@@ -22,6 +22,8 @@ InputNode.prototype.setReadonly = function ( value ) {
 
 	this.readonly = value;
 
+	this.hashProperties = this.readonly ? [ "value" ] : undefined;
+
 	return this;
 
 };

+ 2 - 0
examples/jsm/nodes/core/Node.d.ts

@@ -10,6 +10,7 @@ export class Node {
 	userData: object;
 	readonly isNode: true;
 	frameId: number | undefined;
+	hashProperties: string[] | undefined;
 
 	analyze( builder: NodeBuilder, settings?: object ): void;
 	analyzeAndFlow( builder: NodeBuilder, output: string, settings?: object ): object;
@@ -21,6 +22,7 @@ export class Node {
 	getName( builder: NodeBuilder ): string;
 	getType( builder: NodeBuilder, output?: string ): string;
 	getJSONNode( meta?: object | string ): object | undefined;
+	getHash(): string;
 	copy( source: Node ): this;
 	createJSONNode( meta?: object | string ): object;
 	toJSON( meta?: object | string ): object;

+ 38 - 0
examples/jsm/nodes/core/Node.js

@@ -22,6 +22,8 @@ Node.prototype = {
 
 	isNode: true,
 
+	hashProperties: undefined,
+
 	analyze: function ( builder, settings ) {
 
 		settings = settings || {};
@@ -100,6 +102,42 @@ Node.prototype = {
 
 	},
 
+	getHash: function() {
+
+		var hash = '{';
+		var prop, obj;
+
+		for ( prop in this ) {
+
+			obj = this[ prop ];
+
+			if ( obj instanceof Node ) {
+
+				hash += '"' + prop + '":' + obj.getHash() + ',';
+
+			}
+
+		}
+
+		if ( this.hashProperties ) {
+
+			for ( var i = 0; i < this.hashProperties.length; i ++ ) {
+
+				prop = this.hashProperties[ i ];
+				obj = this[ prop ];
+
+				hash += '"' + prop + '":"' + String( obj ) + '",';
+
+			}
+
+		}
+
+		hash += '"id":"' + this.uuid + '"}';
+
+		return hash;
+
+	},
+
 	appendDepsNode: function ( builder, data, output ) {
 
 		data.deps = ( data.deps || 0 ) + 1;

+ 1 - 0
examples/jsm/nodes/effects/BlurNode.js

@@ -73,6 +73,7 @@ BlurNode.Nodes = ( function () {
 BlurNode.prototype = Object.create( TempNode.prototype );
 BlurNode.prototype.constructor = BlurNode;
 BlurNode.prototype.nodeType = "Blur";
+BlurNode.prototype.hashProperties = [ "blurX", "blurY" ];
 
 BlurNode.prototype.updateFrame = function ( /* frame */ ) {
 

+ 1 - 0
examples/jsm/nodes/effects/ColorAdjustmentNode.js

@@ -77,6 +77,7 @@ ColorAdjustmentNode.CONTRAST = 'contrast';
 ColorAdjustmentNode.prototype = Object.create( TempNode.prototype );
 ColorAdjustmentNode.prototype.constructor = ColorAdjustmentNode;
 ColorAdjustmentNode.prototype.nodeType = "ColorAdjustment";
+ColorAdjustmentNode.prototype.hashProperties = [ "method" ];
 
 ColorAdjustmentNode.prototype.generate = function ( builder, output ) {
 

+ 1 - 0
examples/jsm/nodes/materials/NodeMaterial.d.ts

@@ -27,6 +27,7 @@ export class NodeMaterial extends ShaderMaterial {
 
 	updateFrame( frame: NodeFrame ): void;
 	build( params?: NodeMaterialBuildParams ): this;
+	getHash(): string;
 	copy( source: NodeMaterial ): this;
 
 }

+ 37 - 26
examples/jsm/nodes/materials/NodeMaterial.js

@@ -26,32 +26,6 @@ function NodeMaterial( vertex, fragment ) {
 
 	this.updaters = [];
 
-	// onBeforeCompile can't be in the prototype because onBeforeCompile.toString varies per material
-
-	this.onBeforeCompile = function ( shader, renderer ) {
-
-		var materialProperties = renderer.properties.get( this );
-
-		if ( this.version !== materialProperties.__version ) {
-
-			this.build( { renderer: renderer } );
-
-			shader.uniforms = this.uniforms;
-			shader.vertexShader = this.vertexShader;
-			shader.fragmentShader = this.fragmentShader;
-
-		}
-
-	};
-
-	// it fix the programCache and share the code with others materials
-
-	this.onBeforeCompile.toString = function () {
-
-		return scope.needsCompile;
-
-	};
-
 }
 
 NodeMaterial.prototype = Object.create( ShaderMaterial.prototype );
@@ -91,6 +65,43 @@ Object.defineProperties( NodeMaterial.prototype, {
 
 } );
 
+NodeMaterial.prototype.onBeforeCompile = function ( shader, renderer ) {
+
+	var materialProperties = renderer.properties.get( this );
+
+	if ( this.version !== materialProperties.__version ) {
+
+		this.build( { renderer: renderer } );
+
+		shader.uniforms = this.uniforms;
+		shader.vertexShader = this.vertexShader;
+		shader.fragmentShader = this.fragmentShader;
+
+	}
+
+};
+
+NodeMaterial.prototype.customProgramCacheKey = function () {
+
+	var hash = this.getHash();
+
+	return hash;
+
+};
+
+NodeMaterial.prototype.getHash = function () {
+
+	var hash = '{';
+
+	hash += '"vertex":' + this.vertex.getHash() + ',';
+	hash += '"fragment":' + this.fragment.getHash();
+
+	hash += '}';
+
+	return hash;
+
+};
+
 NodeMaterial.prototype.updateFrame = function ( frame ) {
 
 	for ( var i = 0; i < this.updaters.length; ++ i ) {

+ 1 - 0
examples/jsm/nodes/math/MathNode.js

@@ -66,6 +66,7 @@ MathNode.FACEFORWARD = 'faceforward';
 MathNode.prototype = Object.create( TempNode.prototype );
 MathNode.prototype.constructor = MathNode;
 MathNode.prototype.nodeType = "Math";
+MathNode.prototype.hashProperties = [ "method" ];
 
 MathNode.prototype.getNumInputs = function ( /*builder*/ ) {
 

+ 1 - 0
examples/jsm/nodes/misc/BumpMapNode.js

@@ -96,6 +96,7 @@ BumpMapNode.Nodes = ( function () {
 BumpMapNode.prototype = Object.create( TempNode.prototype );
 BumpMapNode.prototype.constructor = BumpMapNode;
 BumpMapNode.prototype.nodeType = "BumpMap";
+BumpMapNode.prototype.hashProperties = [ "toNormalMap" ];
 
 BumpMapNode.prototype.generate = function ( builder, output ) {
 

+ 1 - 0
examples/jsm/nodes/utils/ColorSpaceNode.js

@@ -239,6 +239,7 @@ ColorSpaceNode.getEncodingComponents = function ( encoding ) {
 ColorSpaceNode.prototype = Object.create( TempNode.prototype );
 ColorSpaceNode.prototype.constructor = ColorSpaceNode;
 ColorSpaceNode.prototype.nodeType = "ColorSpace";
+ColorSpaceNode.prototype.hashProperties = [ "method" ];
 
 ColorSpaceNode.prototype.generate = function ( builder, output ) {