Bläddra i källkod

Nodes: Optional arguments to clamp( n, 0, 1 ) and rename saturate() to clamp() (#24663)

* optional arguments clamp( n, 0, 1 ) and rename saturate() to clamp()

* move clamp() arguments to ShaderNode
sunag 2 år sedan
förälder
incheckning
a07ffa43b9

+ 5 - 5
examples/jsm/nodes/functions/BSDF/BRDF_GGX.js

@@ -2,7 +2,7 @@ import F_Schlick from './F_Schlick.js';
 import V_GGX_SmithCorrelated from './V_GGX_SmithCorrelated.js';
 import D_GGX from './D_GGX.js';
 import {
-	ShaderNode, dotNV, add, mul, saturate, dot, pow2, normalize,
+	ShaderNode, dotNV, add, mul, clamp, dot, pow2, normalize,
 	transformedNormalView, positionViewDirection
 } from '../../shadernode/ShaderNodeBaseElements.js';
 
@@ -15,10 +15,10 @@ const BRDF_GGX = new ShaderNode( ( inputs ) => {
 
 	const halfDir = normalize( add( lightDirection, positionViewDirection ) );
 
-	const dotNL = saturate( dot( transformedNormalView, lightDirection ) );
-	//const dotNV = saturate( dot( transformedNormalView, positionViewDirection ) );
-	const dotNH = saturate( dot( transformedNormalView, halfDir ) );
-	const dotVH = saturate( dot( positionViewDirection, halfDir ) );
+	const dotNL = clamp( dot( transformedNormalView, lightDirection ) );
+	//const dotNV = clamp( dot( transformedNormalView, positionViewDirection ) );
+	const dotNH = clamp( dot( transformedNormalView, halfDir ) );
+	const dotVH = clamp( dot( positionViewDirection, halfDir ) );
 
 	const F = F_Schlick.call( { f0, f90, dotVH } );
 

+ 3 - 3
examples/jsm/nodes/functions/PhysicalLightingModel.js

@@ -3,7 +3,7 @@ import BRDF_GGX from './BSDF/BRDF_GGX.js';
 import DFGApprox from './BSDF/DFGApprox.js';
 import {
 	ShaderNode,
-	vec3, mul, saturate, add, sub, dot, div, transformedNormalView,
+	vec3, mul, clamp, add, sub, dot, div, transformedNormalView,
 	pow, exp2, dotNV,
 	diffuseColor, specularColor, roughness, temp
 } from '../shadernode/ShaderNodeElements.js';
@@ -61,7 +61,7 @@ const RE_Direct_Physical = new ShaderNode( ( inputs ) => {
 
 	const { lightDirection, lightColor, reflectedLight } = inputs;
 
-	const dotNL = saturate( dot( transformedNormalView, lightDirection ) );
+	const dotNL = clamp( dot( transformedNormalView, lightDirection ) );
 	const irradiance = mul( dotNL, lightColor );
 
 	reflectedLight.directDiffuse.add( mul( irradiance, BRDF_Lambert.call( { diffuseColor: diffuseColor.rgb } ) ) );
@@ -75,7 +75,7 @@ const RE_AmbientOcclusion_Physical = new ShaderNode( ( { ambientOcclusion, refle
 	const aoNV = add( dotNV, ambientOcclusion );
 	const aoExp = exp2( sub( mul( - 16.0, roughness ), 1.0 ) );
 
-	const aoNode = saturate( add( sub( pow( aoNV, aoExp ), 1.0 ), ambientOcclusion ) );
+	const aoNode = clamp( add( sub( pow( aoNV, aoExp ), 1.0 ), ambientOcclusion ) );
 
 	reflectedLight.indirectDiffuse.mul( ambientOcclusion );
 

+ 2 - 2
examples/jsm/nodes/functions/light/getDistanceAttenuation.js

@@ -1,5 +1,5 @@
 import {
-	ShaderNode, div, max, sub, mul, saturate, pow, pow2, pow4, cond, greaterThan
+	ShaderNode, div, max, sub, mul, clamp, pow, pow2, pow4, cond, greaterThan
 } from '../../shadernode/ShaderNodeBaseElements.js';
 
 const getDistanceAttenuation = new ShaderNode( ( inputs ) => {
@@ -13,7 +13,7 @@ const getDistanceAttenuation = new ShaderNode( ( inputs ) => {
 
 	return cond(
 		greaterThan( cutoffDistance, 0 ),
-		mul( distanceFalloff, pow2( saturate( sub( 1.0, pow4( div( lightDistance, cutoffDistance ) ) ) ) ) ),
+		mul( distanceFalloff, pow2( clamp( sub( 1.0, pow4( div( lightDistance, cutoffDistance ) ) ) ) ) ),
 		distanceFalloff
 	);
 

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

@@ -32,7 +32,6 @@ class MathNode extends TempNode {
 	static INVERT = 'invert';
 	static DFDX = 'dFdx';
 	static DFDY = 'dFdy';
-	static SATURATE = 'saturate';
 	static ROUND = 'round';
 
 	// 2 inputs
@@ -152,10 +151,6 @@ class MathNode extends TempNode {
 
 			return new MathNode( MathNode.NORMALIZE, mulNode ).build( builder );
 
-		} else if ( method === MathNode.SATURATE ) {
-
-			return builder.format( `clamp( ${ a.build( builder, inputType ) }, 0.0, 1.0 )`, type, output );
-
 		} else if ( method === MathNode.NEGATE ) {
 
 			return builder.format( '( -' + a.build( builder, inputType ) + ' )', type, output );

+ 2 - 3
examples/jsm/nodes/shadernode/ShaderNodeBaseElements.js

@@ -235,7 +235,6 @@ export const negate = nodeProxy( MathNode, MathNode.NEGATE );
 export const invert = nodeProxy( MathNode, MathNode.INVERT );
 export const dFdx = nodeProxy( MathNode, MathNode.DFDX );
 export const dFdy = nodeProxy( MathNode, MathNode.DFDY );
-export const saturate = nodeProxy( MathNode, MathNode.SATURATE );
 export const round = nodeProxy( MathNode, MathNode.ROUND );
 
 export const atan2 = nodeProxy( MathNode, MathNode.ATAN2 );
@@ -254,7 +253,7 @@ export const pow4 = nodeProxy( MathNode, MathNode.POW, 4 );
 export const transformDirection = nodeProxy( MathNode, MathNode.TRANSFORM_DIRECTION );
 
 export const mix = nodeProxy( MathNode, MathNode.MIX );
-export const clamp = nodeProxy( MathNode, MathNode.CLAMP );
+export const clamp = ( value, low = 0, high = 1 ) => nodeObject( new MathNode( MathNode.CLAMP, nodeObject( value ), nodeObject( low ), nodeObject( high ) ) );
 export const refract = nodeProxy( MathNode, MathNode.REFRACT );
 export const smoothstep = nodeProxy( MathNode, MathNode.SMOOTHSTEP );
 export const faceforward = nodeProxy( MathNode, MathNode.FACEFORWARD );
@@ -274,5 +273,5 @@ export const element = nodeProxy( ArrayElementNode );
 // miscellaneous
 
 export const difference = ( a, b ) => nodeObject( abs( sub( a, b ) ) );
-export const dotNV = saturate( dot( transformedNormalView, positionViewDirection ) );
+export const dotNV = clamp( dot( transformedNormalView, positionViewDirection ) );
 export const transformedNormalWorld = normalize( transformDirection( transformedNormalView, cameraViewMatrix ) );

+ 2 - 2
examples/jsm/nodes/utils/RemapNode.js

@@ -1,5 +1,5 @@
 import Node from '../core/Node.js';
-import { add, sub, div, mul, saturate } from '../shadernode/ShaderNodeBaseElements.js';
+import { add, sub, div, mul, clamp } from '../shadernode/ShaderNodeBaseElements.js';
 
 class RemapNode extends Node {
 
@@ -23,7 +23,7 @@ class RemapNode extends Node {
 
 		let t = div( sub( node, inLowNode ), sub( inHighNode, inLowNode ) );
 
-		if ( doClamp === true ) t = saturate( t );
+		if ( doClamp === true ) t = clamp( t );
 
 		return add( mul( sub( outHighNode, outLowNode ), t ), outLowNode );
 

+ 2 - 2
examples/webgl_nodes_materialx_noise.html

@@ -28,7 +28,7 @@
 		<script type="module">
 
 			import * as THREE from 'three';
-			import { MeshPhysicalNodeMaterial, add, mul, normalWorld, saturate, timerLocal } from 'three/nodes';
+			import { MeshPhysicalNodeMaterial, add, mul, normalWorld, clamp, timerLocal } from 'three/nodes';
 
 			import {
 				mx_perlin_noise_float,
@@ -110,7 +110,7 @@
 							// right bottom
 
 							material = new MeshPhysicalNodeMaterial();
-							material.colorNode = saturate( mul( add( mx_fractal_noise_float( mul( customUV, .2 ), 7, 2, .7 ), 1 ), .5 ) );
+							material.colorNode = clamp( mul( add( mx_fractal_noise_float( mul( customUV, .2 ), 7, 2, .7 ), 1 ), .5 ) );
 
 							mesh = new THREE.Mesh( geometry, material );
 							mesh.position.x = 100;

+ 2 - 2
examples/webgpu_cubemap_adjustments.html

@@ -33,7 +33,7 @@
 			import * as THREE from 'three';
 			import * as Nodes from 'three/nodes';
 
-			import { uniform, mix, cubeTexture, mul, reference, add, positionWorld, normalWorld, modelWorldMatrix, transformDirection, saturate, saturation, hue, reflectVector, context } from 'three/nodes';
+			import { uniform, mix, cubeTexture, mul, reference, add, positionWorld, normalWorld, modelWorldMatrix, transformDirection, clamp, saturation, hue, reflectVector, context } from 'three/nodes';
 
 			import WebGPU from 'three/addons/capabilities/WebGPU.js';
 			import WebGPURenderer from 'three/addons/renderers/webgpu/WebGPURenderer.js';
@@ -112,7 +112,7 @@
 					const custom1UV = mul( reflectNode.xyz, uniform( rotateY1Matrix ) );
 					const custom2UV = mul( reflectNode.xyz, uniform( rotateY2Matrix ) );
 
-					const mixCubeMaps = mix( cubeTexture( cube1Texture, custom1UV ), cubeTexture( cube2Texture, custom2UV ), saturate( add( positionWorld.y, mixNode ) ) );
+					const mixCubeMaps = mix( cubeTexture( cube1Texture, custom1UV ), cubeTexture( cube2Texture, custom2UV ), clamp( add( positionWorld.y, mixNode ) ) );
 					const proceduralEnv = mix( mixCubeMaps, normalWorld, proceduralNode );
 					const intensityFilter = mul( proceduralEnv, intensityNode );
 					const hueFilter = hue( intensityFilter, hueNode );

+ 2 - 2
examples/webgpu_particles.html

@@ -30,7 +30,7 @@
 
 			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
 
-			import { range, texture, mix, uv, mul, mod, rotateUV, color, max, min, div, saturate, positionWorld, invert, timerLocal } from 'three/nodes';
+			import { range, texture, mix, uv, mul, mod, rotateUV, color, max, min, div, clamp, positionWorld, invert, timerLocal } from 'three/nodes';
 
 			import WebGPU from 'three/addons/capabilities/WebGPU.js';
 			import WebGPURenderer from 'three/addons/renderers/webgpu/WebGPURenderer.js';
@@ -84,7 +84,7 @@
 
 				const opacityNode = mul( textureNode.a, invert( life ) );
 
-				const smokeColor = mix( color( 0x2c1501 ), color( 0x222222 ), saturate( mul( positionWorld.y, 3 ) ) );
+				const smokeColor = mix( color( 0x2c1501 ), color( 0x222222 ), clamp( mul( positionWorld.y, 3 ) ) );
 
 				// create particles