Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nodes: Define stack.assign() as default. #26881

Merged
merged 2 commits into from
Oct 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/jsm/nodes/Nodes.js
Expand Up @@ -14,6 +14,7 @@ export { default as ContextNode, context, label } from './core/ContextNode.js';
export { default as IndexNode, vertexIndex, instanceIndex } from './core/IndexNode.js';
export { default as LightingModel } from './core/LightingModel.js';
export { default as Node, addNodeClass, createNodeFromType } from './core/Node.js';
export { default as VarNode, temp } from './core/VarNode.js';
export { default as NodeAttribute } from './core/NodeAttribute.js';
export { default as NodeBuilder } from './core/NodeBuilder.js';
export { default as NodeCache } from './core/NodeCache.js';
Expand All @@ -28,7 +29,6 @@ export { default as PropertyNode, property, output, diffuseColor, roughness, met
export { default as StackNode, stack } from './core/StackNode.js';
export { default as TempNode } from './core/TempNode.js';
export { default as UniformNode, uniform } from './core/UniformNode.js';
export { default as VarNode, temp } from './core/VarNode.js';
export { default as VaryingNode, varying } from './core/VaryingNode.js';
export { default as OutputStructNode, outputStruct } from './core/OutputStructNode.js';

Expand Down
3 changes: 1 addition & 2 deletions examples/jsm/nodes/accessors/ModelNode.js
@@ -1,6 +1,5 @@
import Object3DNode from './Object3DNode.js';
import { addNodeClass } from '../core/Node.js';
import { label } from '../core/ContextNode.js';
import { nodeImmutable } from '../shadernode/ShaderNode.js';

class ModelNode extends Object3DNode {
Expand All @@ -24,7 +23,7 @@ class ModelNode extends Object3DNode {
export default ModelNode;

export const modelDirection = nodeImmutable( ModelNode, ModelNode.DIRECTION );
export const modelViewMatrix = label( nodeImmutable( ModelNode, ModelNode.VIEW_MATRIX ), 'modelViewMatrix' );
export const modelViewMatrix = nodeImmutable( ModelNode, ModelNode.VIEW_MATRIX ).temp( 'ModelViewMatrix' );
export const modelNormalMatrix = nodeImmutable( ModelNode, ModelNode.NORMAL_MATRIX );
export const modelWorldMatrix = nodeImmutable( ModelNode, ModelNode.WORLD_MATRIX );
export const modelPosition = nodeImmutable( ModelNode, ModelNode.POSITION );
Expand Down
2 changes: 1 addition & 1 deletion examples/jsm/nodes/accessors/NormalNode.js
Expand Up @@ -86,7 +86,7 @@ NormalNode.WORLD = 'world';
export default NormalNode;

export const normalGeometry = nodeImmutable( NormalNode, NormalNode.GEOMETRY );
export const normalLocal = nodeImmutable( NormalNode, NormalNode.LOCAL );
export const normalLocal = nodeImmutable( NormalNode, NormalNode.LOCAL ).temp( 'Normal' );
export const normalView = nodeImmutable( NormalNode, NormalNode.VIEW );
export const normalWorld = nodeImmutable( NormalNode, NormalNode.WORLD );
export const transformedNormalView = property( 'vec3', 'TransformedNormalView' );
Expand Down
2 changes: 1 addition & 1 deletion examples/jsm/nodes/accessors/PositionNode.js
Expand Up @@ -95,7 +95,7 @@ PositionNode.VIEW_DIRECTION = 'viewDirection';
export default PositionNode;

export const positionGeometry = nodeImmutable( PositionNode, PositionNode.GEOMETRY );
export const positionLocal = nodeImmutable( PositionNode, PositionNode.LOCAL );
export const positionLocal = nodeImmutable( PositionNode, PositionNode.LOCAL ).temp( 'Position' );
export const positionWorld = nodeImmutable( PositionNode, PositionNode.WORLD );
export const positionWorldDirection = nodeImmutable( PositionNode, PositionNode.WORLD_DIRECTION );
export const positionView = nodeImmutable( PositionNode, PositionNode.VIEW );
Expand Down
4 changes: 3 additions & 1 deletion examples/jsm/nodes/core/LightingModel.js
@@ -1,6 +1,8 @@
class LightingModel {

init( /*input, stack, builder*/ ) { }
start( /*input, stack, builder*/ ) { }

finish( /*input, stack, builder*/ ) { }

direct( /*input, stack, builder*/ ) { }

Expand Down
2 changes: 2 additions & 0 deletions examples/jsm/nodes/core/PropertyNode.js
Expand Up @@ -9,6 +9,8 @@ class PropertyNode extends Node {

this.name = name;

this.isPropertyNode = true;

}

getHash( builder ) {
Expand Down
20 changes: 19 additions & 1 deletion examples/jsm/nodes/core/StackNode.js
Expand Up @@ -4,7 +4,8 @@ import { bypass } from '../core/BypassNode.js';
import { expression } from '../code/ExpressionNode.js';
import { cond } from '../math/CondNode.js';
import { loop } from '../utils/LoopNode.js';
import { ShaderNode, nodeProxy } from '../shadernode/ShaderNode.js';
import SetNode from '../utils/SetNode.js';
import { ShaderNode, nodeProxy, nodeObject } from '../shadernode/ShaderNode.js';

class StackNode extends Node {

Expand Down Expand Up @@ -68,6 +69,23 @@ class StackNode extends Node {

assign( targetNode, sourceValue ) {

sourceValue = nodeObject( sourceValue );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need all of this, we can just remove this function and rely on ShaderNode.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Fixed in #26821)


if ( targetNode.isSplitNode ) {

sourceValue = new SetNode( targetNode.node, targetNode.components, sourceValue );
targetNode = targetNode.node;

}

if ( targetNode.isPropertyNode !== true && targetNode.isVarNode !== true && targetNode.isArrayElementNode !== true && targetNode.isVaryingNode !== true ) {

console.error( 'THREE.TSL: Invalid assign, target must be a property or variable.', targetNode.getSelf() );

//return this;

}

return this.add( assign( targetNode, sourceValue ) );

}
Expand Down
25 changes: 2 additions & 23 deletions examples/jsm/nodes/core/VarNode.js
Expand Up @@ -10,21 +10,7 @@ class VarNode extends Node {
this.node = node;
this.name = name;

}

assign( node ) {

node.traverse( ( childNode, replaceNode ) => {

if ( replaceNode && childNode.uuid === this.uuid ) {

replaceNode( this.node );

}

} );
this.node = node;
return this;
this.isVarNode = true;

}

Expand All @@ -48,14 +34,7 @@ class VarNode extends Node {

generate( builder ) {

const node = this.node;
const name = this.name;

if ( name === null && node.isTempNode === true ) {

return node.build( builder );

}
const { node, name } = this;

const type = builder.getVectorType( this.getNodeType( builder ) );

Expand Down
2 changes: 2 additions & 0 deletions examples/jsm/nodes/core/VaryingNode.js
Expand Up @@ -11,6 +11,8 @@ class VaryingNode extends Node {
this.node = node;
this.name = name;

this.isVaryingNode = true;

}

isGlobal() {
Expand Down
10 changes: 5 additions & 5 deletions examples/jsm/nodes/functions/PhongLightingModel.js
Expand Up @@ -41,24 +41,24 @@ class PhongLightingModel extends LightingModel {

}

direct( { lightDirection, lightColor, reflectedLight } ) {
direct( { lightDirection, lightColor, reflectedLight }, stack ) {

const dotNL = transformedNormalView.dot( lightDirection ).clamp();
const irradiance = dotNL.mul( lightColor );

reflectedLight.directDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor: diffuseColor.rgb } ) ) );
stack.addAssign( reflectedLight.directDiffuse, irradiance.mul( BRDF_Lambert( { diffuseColor: diffuseColor.rgb } ) ) );

if ( this.specular === true ) {

reflectedLight.directSpecular.addAssign( irradiance.mul( BRDF_BlinnPhong( { lightDirection } ) ).mul( materialSpecularStrength ) );
stack.addAssign( reflectedLight.directSpecular, irradiance.mul( BRDF_BlinnPhong( { lightDirection } ) ).mul( materialSpecularStrength ) );

}

}

indirectDiffuse( { irradiance, reflectedLight } ) {
indirectDiffuse( { irradiance, reflectedLight }, stack ) {

reflectedLight.indirectDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor } ) ) );
stack.addAssign( reflectedLight.indirectDiffuse, irradiance.mul( BRDF_Lambert( { diffuseColor } ) ) );

}

Expand Down
102 changes: 56 additions & 46 deletions examples/jsm/nodes/functions/PhysicalLightingModel.js
Expand Up @@ -177,38 +177,18 @@ class PhysicalLightingModel extends LightingModel {

}

init( { reflectedLight } ) {
start( /*context*/ ) {

if ( this.clearcoat === true ) {

this.clearcoatRadiance = vec3().temp();
this.clearcoatSpecular = vec3().temp();

const dotNVcc = transformedClearcoatNormalView.dot( positionViewDirection ).clamp();

const Fcc = F_Schlick( {
dotVH: dotNVcc,
f0: clearcoatF0,
f90: clearcoatF90
} );

const outgoingLight = reflectedLight.total;
const clearcoatLight = outgoingLight.mul( clearcoat.mul( Fcc ).oneMinus() ).add( this.clearcoatSpecular.mul( clearcoat ) );

outgoingLight.assign( clearcoatLight );
this.clearcoatRadiance = vec3().temp( 'clearcoatRadiance' );
this.clearcoatSpecular = vec3().temp( 'clearcoatSpecular' );

}

if ( this.sheen === true ) {

this.sheenSpecular = vec3().temp();

const outgoingLight = reflectedLight.total;

const sheenEnergyComp = sheen.r.max( sheen.g ).max( sheen.b ).mul( 0.157 ).oneMinus();
const sheenLight = outgoingLight.mul( sheenEnergyComp ).add( this.sheenSpecular );

outgoingLight.assign( sheenLight );
this.sheenSpecular = vec3().temp( 'sheenSpecular' );

}

Expand All @@ -227,7 +207,7 @@ class PhysicalLightingModel extends LightingModel {
// Approximates multiscattering in order to preserve energy.
// http://www.jcgt.org/published/0008/01/03/

computeMultiscattering( singleScatter, multiScatter, specularF90 = float( 1 ) ) {
computeMultiscattering( stack, singleScatter, multiScatter, specularF90 = float( 1 ) ) {

const fab = DFGApprox( { roughness } );

Expand All @@ -241,19 +221,19 @@ class PhysicalLightingModel extends LightingModel {
const Favg = specularColor.add( specularColor.oneMinus().mul( 0.047619 ) ); // 1/21
const Fms = FssEss.mul( Favg ).div( Ems.mul( Favg ).oneMinus() );

singleScatter.addAssign( FssEss );
multiScatter.addAssign( Fms.mul( Ems ) );
stack.addAssign( singleScatter, FssEss );
stack.addAssign( multiScatter, Fms.mul( Ems ) );

}

direct( { lightDirection, lightColor, reflectedLight } ) {
direct( { lightDirection, lightColor, reflectedLight }, stack ) {

const dotNL = transformedNormalView.dot( lightDirection ).clamp();
const irradiance = dotNL.mul( lightColor );

if ( this.sheen === true ) {

this.sheenSpecular.addAssign( irradiance.mul( BRDF_Sheen( { lightDirection } ) ) );
stack.addAssign( this.sheenSpecular, irradiance.mul( BRDF_Sheen( { lightDirection } ) ) );

}

Expand All @@ -262,27 +242,27 @@ class PhysicalLightingModel extends LightingModel {
const dotNLcc = transformedClearcoatNormalView.dot( lightDirection ).clamp();
const ccIrradiance = dotNLcc.mul( lightColor );

this.clearcoatSpecular.addAssign( ccIrradiance.mul( BRDF_GGX( { lightDirection, f0: clearcoatF0, f90: clearcoatF90, roughness: clearcoatRoughness, normalView: transformedClearcoatNormalView } ) ) );
stack.addAssign( this.clearcoatSpecular, ccIrradiance.mul( BRDF_GGX( { lightDirection, f0: clearcoatF0, f90: clearcoatF90, roughness: clearcoatRoughness, normalView: transformedClearcoatNormalView } ) ) );

}

reflectedLight.directDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor: diffuseColor.rgb } ) ) );
stack.addAssign( reflectedLight.directDiffuse, irradiance.mul( BRDF_Lambert( { diffuseColor: diffuseColor.rgb } ) ) );

reflectedLight.directSpecular.addAssign( irradiance.mul( BRDF_GGX( { lightDirection, f0: specularColor, f90: 1, roughness, iridescence: this.iridescence, iridescenceFresnel: this.iridescenceFresnel } ) ) );
stack.addAssign( reflectedLight.directSpecular, irradiance.mul( BRDF_GGX( { lightDirection, f0: specularColor, f90: 1, roughness, iridescence: this.iridescence, iridescenceFresnel: this.iridescenceFresnel } ) ) );

}

indirectDiffuse( { irradiance, reflectedLight } ) {
indirectDiffuse( { irradiance, reflectedLight }, stack ) {

reflectedLight.indirectDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor } ) ) );
stack.addAssign( reflectedLight.indirectDiffuse, irradiance.mul( BRDF_Lambert( { diffuseColor } ) ) );

}

indirectSpecular( { radiance, iblIrradiance, reflectedLight, } ) {
indirectSpecular( { radiance, iblIrradiance, reflectedLight }, stack ) {

if ( this.sheen === true ) {

this.sheenSpecular.addAssign( iblIrradiance.mul(
stack.addAssign( this.sheenSpecular, iblIrradiance.mul(
sheen,
IBLSheenBRDF( transformedNormalView, positionViewDirection, sheenRoughness )
) );
Expand All @@ -300,30 +280,30 @@ class PhysicalLightingModel extends LightingModel {
roughness: clearcoatRoughness
} );

this.clearcoatSpecular.addAssign( this.clearcoatRadiance.mul( clearcoatEnv ) );
stack.addAssign( this.clearcoatSpecular, this.clearcoatRadiance.mul( clearcoatEnv ) );

}

// Both indirect specular and indirect diffuse light accumulate here

const singleScattering = vec3().temp();
const multiScattering = vec3().temp();
const singleScattering = vec3().temp( 'singleScattering' );
const multiScattering = vec3().temp( 'multiScattering' );
const cosineWeightedIrradiance = iblIrradiance.mul( 1 / Math.PI );

this.computeMultiscattering( singleScattering, multiScattering );
this.computeMultiscattering( stack, singleScattering, multiScattering );

const totalScattering = singleScattering.add( multiScattering );

const diffuse = diffuseColor.mul( totalScattering.r.max( totalScattering.g ).max( totalScattering.b ).oneMinus() );

reflectedLight.indirectSpecular.addAssign( radiance.mul( singleScattering ) );
reflectedLight.indirectSpecular.addAssign( multiScattering.mul( cosineWeightedIrradiance ) );
stack.addAssign( reflectedLight.indirectSpecular, radiance.mul( singleScattering ) );
stack.addAssign( reflectedLight.indirectSpecular, multiScattering.mul( cosineWeightedIrradiance ) );

reflectedLight.indirectDiffuse.addAssign( diffuse.mul( cosineWeightedIrradiance ) );
stack.addAssign( reflectedLight.indirectDiffuse, diffuse.mul( cosineWeightedIrradiance ) );

}

ambientOcclusion( { ambientOcclusion, reflectedLight } ) {
ambientOcclusion( { ambientOcclusion, reflectedLight }, stack ) {

const dotNV = transformedNormalView.dot( positionViewDirection ).clamp(); // @ TODO: Move to core dotNV

Expand All @@ -332,9 +312,39 @@ class PhysicalLightingModel extends LightingModel {

const aoNode = ambientOcclusion.sub( aoNV.pow( aoExp ).oneMinus() ).clamp();

reflectedLight.indirectDiffuse.mulAssign( ambientOcclusion );
stack.mulAssign( reflectedLight.indirectDiffuse, ambientOcclusion );
stack.mulAssign( reflectedLight.indirectSpecular, aoNode );

}

finish( context, stack ) {

const { outgoingLight } = context;

if ( this.clearcoat === true ) {

const dotNVcc = transformedClearcoatNormalView.dot( positionViewDirection ).clamp();

const Fcc = F_Schlick( {
dotVH: dotNVcc,
f0: clearcoatF0,
f90: clearcoatF90
} );

const clearcoatLight = outgoingLight.mul( clearcoat.mul( Fcc ).oneMinus() ).add( this.clearcoatSpecular.mul( clearcoat ) );

reflectedLight.indirectSpecular.mulAssign( aoNode );
stack.assign( outgoingLight, clearcoatLight );

}

if ( this.sheen === true ) {

const sheenEnergyComp = sheen.r.max( sheen.g ).max( sheen.b ).mul( 0.157 ).oneMinus();
const sheenLight = outgoingLight.mul( sheenEnergyComp ).add( this.sheenSpecular );

stack.assign( outgoingLight, sheenLight );

}

}

Expand Down
2 changes: 1 addition & 1 deletion examples/jsm/nodes/lighting/AONode.js
Expand Up @@ -16,7 +16,7 @@ class AONode extends LightingNode {
const aoIntensity = 1;
const aoNode = this.aoNode.x.sub( 1.0 ).mul( aoIntensity ).add( 1.0 );

builder.context.ambientOcclusion.mulAssign( aoNode );
builder.stack.mulAssign( builder.context.ambientOcclusion, aoNode );

}

Expand Down
4 changes: 2 additions & 2 deletions examples/jsm/nodes/lighting/AmbientLightNode.js
Expand Up @@ -12,9 +12,9 @@ class AmbientLightNode extends AnalyticLightNode {

}

setup( { context } ) {
setup( builder ) {

context.irradiance.addAssign( this.colorNode );
builder.stack.addAssign( builder.context.irradiance, this.colorNode );

}

Expand Down