ソースを参照

WebGPURenderer: Add BumpMapNode (#26449)

* Add BumpMapNode

* fix default position view
sunag 2 年 前
コミット
54119baad4

+ 14 - 1
examples/jsm/nodes/accessors/ExtendedMaterialNode.js

@@ -4,6 +4,7 @@ import MaterialNode from './MaterialNode.js';
 import { materialReference } from './MaterialReferenceNode.js';
 import { normalView } from './NormalNode.js';
 import { normalMap } from '../display/NormalMapNode.js';
+import { bumpMap } from '../display/BumpMapNode.js';
 import { addNodeClass } from '../core/Node.js';
 import { nodeImmutable } from '../shadernode/ShaderNode.js';
 
@@ -39,7 +40,19 @@ class ExtendedMaterialNode extends MaterialNode {
 
 		if ( scope === ExtendedMaterialNode.NORMAL ) {
 
-			node = material.normalMap ? normalMap( this.getTexture( 'normalMap' ), materialReference( 'normalScale', 'vec2' ) ) : normalView;
+			if ( material.normalMap ) {
+
+				node = normalMap( this.getTexture( 'normalMap' ), materialReference( 'normalScale', 'vec2' ) );
+
+			} else if ( material.bumpMap ) {
+
+				node = bumpMap( material.bumpMap, materialReference( 'bumpScale', 'float' ) );
+
+			} else {
+
+				node = normalView;
+
+			}
 
 		} else if ( scope === ExtendedMaterialNode.CLEARCOAT_NORMAL ) {
 

+ 3 - 5
examples/jsm/nodes/accessors/MaterialNode.js

@@ -1,6 +1,6 @@
 import Node, { addNodeClass } from '../core/Node.js';
 import { materialReference } from './MaterialReferenceNode.js';
-import { nodeImmutable } from '../shadernode/ShaderNode.js';
+import { nodeImmutable, float } from '../shadernode/ShaderNode.js';
 
 class MaterialNode extends Node {
 
@@ -112,15 +112,13 @@ class MaterialNode extends Node {
 
 		} else if ( scope === MaterialNode.SPECULAR_STRENGTH ) {
 
-			const specularNode = this.getColor( 'specular' );
-
 			if ( material.specularMap && material.specularMap.isTexture === true ) {
 
-				node = specularNode.mul( this.getTexture( 'specularMap' ).r );
+				node = this.getTexture( 'specularMap' ).r;
 
 			} else {
 
-				node = specularNode;
+				node = float( 1 );
 
 			}
 

+ 77 - 0
examples/jsm/nodes/display/BumpMapNode.js

@@ -0,0 +1,77 @@
+import TempNode from '../core/TempNode.js';
+import { texture } from '../accessors/TextureNode.js';
+import { addNodeClass } from '../core/Node.js';
+import { uv } from '../accessors/UVNode.js';
+import { normalView } from '../accessors/NormalNode.js';
+import { positionView } from '../accessors/PositionNode.js';
+import { faceDirection } from './FrontFacingNode.js';
+import { tslFn, nodeProxy, vec2 } from '../shadernode/ShaderNode.js';
+
+// Bump Mapping Unparametrized Surfaces on the GPU by Morten S. Mikkelsen
+// https://mmikk.github.io/papers3d/mm_sfgrad_bump.pdf
+
+// Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2)
+
+const dHdxy_fwd = tslFn( ( { bumpTexture, bumpScale } ) => {
+
+	const uvNode = uv();
+
+	const Hll = texture( bumpTexture, uvNode ).x;
+
+	return vec2(
+		texture( bumpTexture, uvNode.add( uvNode.dFdx() ) ).x.sub( Hll ),
+		texture( bumpTexture, uvNode.add( uvNode.dFdy() ) ).x.sub( Hll )
+	).mul( bumpScale );
+
+} );
+
+const perturbNormalArb = tslFn( ( inputs ) => {
+
+	const { surf_pos, surf_norm, dHdxy } = inputs;
+
+	const vSigmaX = surf_pos.dFdx();
+	const vSigmaY = surf_pos.dFdy();
+	const vN = surf_norm; // normalized
+
+	const R1 = vSigmaY.cross( vN );
+	const R2 = vN.cross( vSigmaX );
+
+	const fDet = vSigmaX.dot( R1 ).mul( faceDirection );
+
+	const vGrad = fDet.sign().mul( dHdxy.x.mul( R1 ).add( dHdxy.y.mul( R2 ) ) );
+
+	return fDet.abs().mul( surf_norm ).sub( vGrad ).normalize();
+
+} );
+
+class BumpMapNode extends TempNode {
+
+	constructor( texture, scaleNode = null ) {
+
+		super( 'vec3' );
+
+		this.texture = texture;
+		this.scaleNode = scaleNode;
+
+	}
+
+	construct() {
+
+		const bumpScale = this.scaleNode !== null ? this.scaleNode : 1;
+		const dHdxy = dHdxy_fwd( { bumpTexture: this.texture, bumpScale } );
+
+		return perturbNormalArb( {
+			surf_pos: positionView.negate(),
+			surf_norm: normalView,
+			dHdxy
+		} );
+
+	}
+
+}
+
+export default BumpMapNode;
+
+export const bumpMap = nodeProxy( BumpMapNode );
+
+addNodeClass( BumpMapNode );

+ 2 - 2
examples/jsm/nodes/display/NormalMapNode.js

@@ -15,7 +15,7 @@ import { TangentSpaceNormalMap, ObjectSpaceNormalMap } from 'three';
 // Normal Mapping Without Precomputed Tangents
 // http://www.thetenthplanet.de/archives/1180
 
-const perturbNormal2ArbNode = tslFn( ( inputs ) => {
+const perturbNormal2Arb = tslFn( ( inputs ) => {
 
 	const { eye_pos, surf_norm, mapN, uv } = inputs;
 
@@ -80,7 +80,7 @@ class NormalMapNode extends TempNode {
 
 			} else {
 
-				outputNode = perturbNormal2ArbNode( {
+				outputNode = perturbNormal2Arb( {
 					eye_pos: positionView,
 					surf_norm: normalView,
 					mapN: normalMap,