Selaa lähdekoodia

Nodes: Triplanar Texture Mapping (#24714)

* Added TriplanarTexturesNode

* Added triplanarTexture() in webgpu_materials example
sunag 2 vuotta sitten
vanhempi
commit
430e610e79

+ 3 - 0
examples/jsm/nodes/Nodes.js

@@ -88,6 +88,7 @@ import RotateUVNode from './utils/RotateUVNode.js';
 import SplitNode from './utils/SplitNode.js';
 import SpriteSheetUVNode from './utils/SpriteSheetUVNode.js';
 import TimerNode from './utils/TimerNode.js';
+import TriplanarTexturesNode from './utils/TriplanarTexturesNode.js';
 
 // loaders
 import NodeLoader from './loaders/NodeLoader.js';
@@ -211,6 +212,7 @@ const nodeLib = {
 	SplitNode,
 	SpriteSheetUVNode,
 	TimerNode,
+	TriplanarTexturesNode,
 
 	// procedural
 	CheckerNode,
@@ -327,6 +329,7 @@ export {
 	SplitNode,
 	SpriteSheetUVNode,
 	TimerNode,
+	TriplanarTexturesNode,
 
 	// procedural
 	CheckerNode,

+ 4 - 0
examples/jsm/nodes/shadernode/ShaderNodeElements.js

@@ -24,6 +24,7 @@ import RemapNode from '../utils/RemapNode.js';
 import RotateUVNode from '../utils/RotateUVNode.js';
 import SpriteSheetUVNode from '../utils/SpriteSheetUVNode.js';
 import TimerNode from '../utils/TimerNode.js';
+import TriplanarTexturesNode from '../utils/TriplanarTexturesNode.js';
 
 // geometry
 import RangeNode from '../geometry/RangeNode.js';
@@ -117,6 +118,9 @@ export const timerGlobal = ( timeScale, value = 0 ) => nodeObject( new TimerNode
 export const timerDelta = ( timeScale, value = 0 ) => nodeObject( new TimerNode( TimerNode.DELTA, timeScale, value ) );
 export const frameId = nodeImmutable( TimerNode, TimerNode.FRAME );
 
+export const triplanarTextures = nodeProxy( TriplanarTexturesNode );
+export const triplanarTexture = ( texture, ...params ) => triplanarTextures( texture, texture, texture, ...params );
+
 // geometry
 
 export const range = ( min, max ) => nodeObject( new RangeNode( min, max ) );

+ 51 - 0
examples/jsm/nodes/utils/TriplanarTexturesNode.js

@@ -0,0 +1,51 @@
+import Node from '../core/Node.js';
+import { float, vec3, add, mul, div, dot, normalize, abs, texture, positionWorld, normalWorld } from '../shadernode/ShaderNodeBaseElements.js';
+
+class TriplanarTexturesNode extends Node {
+
+	constructor( textureXNode, textureYNode = null, textureZNode = null, scaleNode = float( 1 ), positionNode = positionWorld, normalNode = normalWorld ) {
+
+		super( 'vec4' );
+
+		this.textureXNode = textureXNode;
+		this.textureYNode = textureYNode;
+		this.textureZNode = textureZNode;
+
+		this.scaleNode = scaleNode;
+
+		this.positionNode = positionNode;
+		this.normalNode = normalNode;
+
+	}
+
+	construct() {
+
+		const { textureXNode, textureYNode, textureZNode, scaleNode, positionNode, normalNode } = this;
+
+		// Ref: https://github.com/keijiro/StandardTriplanar
+
+		// Blending factor of triplanar mapping
+		let bf = normalize( abs( normalNode ) );
+		bf = div( bf, dot( bf, vec3( 1.0 ) ) );
+
+		// Triplanar mapping
+		const tx = mul( positionNode.yz, scaleNode );
+		const ty = mul( positionNode.zx, scaleNode );
+		const tz = mul( positionNode.xy, scaleNode );
+
+		// Base color
+		const textureX = textureXNode.value;
+		const textureY = textureYNode !== null ? textureYNode.value : textureX;
+		const textureZ = textureZNode !== null ? textureZNode.value : textureX;
+
+		const cx = mul( texture( textureX, tx ), bf.x );
+		const cy = mul( texture( textureY, ty ), bf.y );
+		const cz = mul( texture( textureZ, tz ), bf.z );
+
+		return add( cx, cy, cz );
+
+	}
+
+}
+
+export default TriplanarTexturesNode;

+ 6 - 1
examples/webgpu_materials.html

@@ -34,7 +34,7 @@
 
 			import { TeapotGeometry } from 'three/addons/geometries/TeapotGeometry.js';
 
-			import { ShaderNode, vec3, dot } from 'three/nodes';
+			import { ShaderNode, vec3, dot, triplanarTexture } from 'three/nodes';
 
 			import Stats from 'three/addons/libs/stats.module.js';
 
@@ -177,6 +177,11 @@
 				material.colorNode = getWGSLTextureSample.call( { tex: textureNode, tex_sampler: textureNode, uv: new Nodes.UVNode() } );
 				materials.push( material );
 
+				// Triplanar Texture Mapping
+				material = new Nodes.MeshBasicNodeMaterial();
+				material.colorNode = triplanarTexture( new Nodes.TextureNode( texture ) );
+				materials.push( material );
+
 				//
 				// Geometry
 				//