Skip to content
Closed
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions examples/files.json
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,9 @@
"misc_exporter_usdz",
"misc_lookat"
],
"misc / nodes": [
"misc_nodes_gpgpu"
],
"css2d": [
"css2d_label"
],
Expand Down
2 changes: 1 addition & 1 deletion examples/jsm/nodes/accessors/BufferNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import UniformNode from '../core/UniformNode.js';

class BufferNode extends UniformNode {

constructor( value, bufferType, bufferCount = 0 ) {
constructor( value, bufferType = 'float', bufferCount = 0 ) {

super( value, bufferType );

Expand Down
2 changes: 2 additions & 0 deletions examples/jsm/nodes/accessors/TextureNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ class TextureNode extends UniformNode {

generate( builder, output ) {

this.construct( builder ); // this is required for some reason?
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not really sure why...


const { uvNode, levelNode } = builder.getNodeProperties( this );

const texture = this.value;
Expand Down
78 changes: 78 additions & 0 deletions examples/jsm/nodes/core/AssignNode.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import TempNode from './TempNode.js';

class AssignNode extends TempNode {

constructor( aNode, bNode ) {

super();

this.aNode = aNode;
this.bNode = bNode;

}

hasDependencies( builder ) {

return false;

}

getNodeType( builder, output ) {

const aNode = this.aNode;
const bNode = this.bNode;

const typeA = aNode.getNodeType( builder );
const typeB = bNode.getNodeType( builder );

if ( typeA === 'void' || typeB === 'void' ) {

return 'void';

} else {

return typeA;

}

}

generate( builder, output ) {

const aNode = this.aNode;
const type = this.getNodeType( builder, output );
const a = aNode.build( builder, type );

if ( aNode.isBufferNode === true || aNode.node.isBufferNode === true ) {

const nodeData = builder.getDataFromNode( aNode.isBufferNode ? aNode : aNode.node, builder.getShaderStage() );
const buffer = nodeData.uniformBuffer;
if ( buffer !== undefined ) {

builder.outComputeBuffer = buffer;
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think we should be able to support multiples buffers in WebGL too?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There could be only one output buffer (implemented as a render target). There can be multiple source buffers simultaneously.

Copy link
Contributor Author

@LeviPesin LeviPesin Jan 20, 2023

Choose a reason for hiding this comment

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

Maybe we can use WebGLMultipleRenderTargets for multiple out buffers... But this will require considerably changing WebGLNodeBuilder, I think (because currently it only allows writing to diffuseColor).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

But this will require considerably changing WebGLNodeBuilder, I think (because currently it only allows writing to diffuseColor).

Or maybe just change WebGLBuffer.setElement() from just returning the value to assigning it to a texture. This, I think, can also solve the problem with return stacks...

return buffer.setElement( this.bNode ).build( builder );

}

}

const bNode = this.bNode;
const b = bNode.build( builder, type );

if ( output !== 'void' ) {

builder.addFlowCode( `${a} = ${b}` );

return a;

} else if ( type !== 'void' ) {

return builder.format( `${a} = ${b}`, type, output );

}

}

}

export default AssignNode;
8 changes: 5 additions & 3 deletions examples/jsm/nodes/core/StackNode.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Node from './Node.js';
import OperatorNode from '../math/OperatorNode.js';
import AssignNode from './AssignNode.js';
import BypassNode from '../core/BypassNode.js';
import ExpressionNode from '../core/ExpressionNode.js';

Expand Down Expand Up @@ -32,7 +32,7 @@ class StackNode extends Node {

assign( targetNode, sourceValue ) {

return this.add( new OperatorNode( '=', targetNode, sourceValue ) );
return this.add( new AssignNode( targetNode, sourceValue ) );

}

Expand All @@ -44,7 +44,9 @@ class StackNode extends Node {

}

return this.outputNode ? this.outputNode.build( builder, ...params ) : super.build( builder, ...params );
const outputNode = this.outputNode && ( this.outputNode.uuid !== this.uuid ) ? this.outputNode : this.nodes[ this.nodes.length - 1 ].callNode;

return outputNode ? outputNode.build( builder, ...params ) : super.build( builder, ...params );

}

Expand Down
2 changes: 1 addition & 1 deletion examples/jsm/nodes/core/TempNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class TempNode extends Node {

return builder.format( nodeData.propertyName, type, output );

} else if ( builder.context.tempWrite !== false && type !== 'void ' && output !== 'void' && this.hasDependencies( builder ) ) {
} else if ( builder.context.tempWrite !== false && type !== 'void' && output !== 'void' && this.hasDependencies( builder ) ) {

const snippet = super.build( builder, type );

Expand Down
5 changes: 4 additions & 1 deletion examples/jsm/nodes/core/VarNode.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Node from './Node.js';
import OperatorNode from '../math/OperatorNode.js';
import AssignNode from './AssignNode.js';

class VarNode extends Node {

Expand All @@ -22,7 +23,9 @@ class VarNode extends Node {

assign( ...params ) {

return this.op( '=', ...params );
this.node = new AssignNode( this.node, ...params );

return this;

}

Expand Down
6 changes: 3 additions & 3 deletions examples/jsm/nodes/display/ViewportNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class ViewportNode extends Node {

getNodeType() {

return this.scope === ViewportNode.COORDINATE ? 'vec4' : 'vec2';
return this.scope === ViewportNode.COORDINATE ? 'uvec4' : ( this.scope === ViewportNode.COORDINATE ? 'uvec2' : 'vec2' );

}

Expand All @@ -41,7 +41,7 @@ class ViewportNode extends Node {

update( { renderer } ) {

renderer.getSize( resolution );
renderer.getSize( resolution || ( resolution = new Vector2() ) );

}

Expand All @@ -55,7 +55,7 @@ class ViewportNode extends Node {

if ( scope === ViewportNode.RESOLUTION ) {

output = uniform( resolution || ( resolution = new Vector2() ) );
output = uniform( resolution || ( resolution = new Vector2() ), 'uvec2' );

} else {

Expand Down
4 changes: 3 additions & 1 deletion examples/jsm/nodes/gpgpu/ComputeNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { NodeUpdateType } from '../core/constants.js';

class ComputeNode extends Node {

constructor( computeNode, count, workgroupSize = [ 64 ] ) {
constructor( computeNode, count = 0, populateOutArray = true, workgroupSize = [ 64 ] ) {

super( 'void' );

Expand All @@ -15,6 +15,8 @@ class ComputeNode extends Node {
this.workgroupSize = workgroupSize;
this.dispatchCount = 0;

this.populateOutArray = true;

this.updateType = NodeUpdateType.OBJECT;

this.updateDispatchCount();
Expand Down
22 changes: 3 additions & 19 deletions examples/jsm/nodes/math/OperatorNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,6 @@ class OperatorNode extends TempNode {

}

hasDependencies( builder ) {

return this.op !== '=' ? super.hasDependencies( builder ) : false;

}

getNodeType( builder, output ) {

const op = this.op;
Expand All @@ -47,7 +41,7 @@ class OperatorNode extends TempNode {

return 'void';

} else if ( op === '=' || op === '%' ) {
} else if ( op === '%' ) {

return typeA;

Expand Down Expand Up @@ -114,11 +108,7 @@ class OperatorNode extends TempNode {
typeA = aNode.getNodeType( builder );
typeB = bNode.getNodeType( builder );

if ( op === '=' ) {

typeB = typeA;

} else if ( op === '<' || op === '>' || op === '<=' || op === '>=' ) {
if ( op === '<' || op === '>' || op === '<=' || op === '>=' ) {

if ( builder.isVector( typeA ) ) {

Expand Down Expand Up @@ -168,13 +158,7 @@ class OperatorNode extends TempNode {

if ( output !== 'void' ) {

if ( op === '=' ) {

builder.addFlowCode( `${a} ${this.op} ${b}` );

return a;

} else if ( op === '<' && outputLength > 1 ) {
if ( op === '<' && outputLength > 1 ) {

return builder.format( `${ builder.getMethod( 'lessThan' ) }( ${a}, ${b} )`, type, output );

Expand Down
8 changes: 6 additions & 2 deletions examples/jsm/nodes/shadernode/ShaderNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ const shaderNodeHandler = {

return nodeObject( new SplitNode( node, prop ) );

} else if ( prop === 'width' || prop === 'height' ) {

// accessing property

return nodeObject( new SplitNode( node, prop === 'width' ? 'x' : 'y' ) );

} else if ( /^\d+$/.test( prop ) === true ) {

// accessing array
Expand Down Expand Up @@ -285,5 +291,3 @@ export const ConvertType = function ( type, cacheMap = null ) {
};

};

export const getConstNodeType = ( value ) => value.nodeType || value.convertTo || ( typeof value === 'string' ? value : null );
74 changes: 69 additions & 5 deletions examples/jsm/nodes/shadernode/ShaderNodeBaseElements.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// core
//import ArrayUniformNode from '../core/ArrayUniformNode.js';
import AssignNode from '../core/AssignNode.js';
import AttributeNode from '../core/AttributeNode.js';
import BypassNode from '../core/BypassNode.js';
import CacheNode from '../core/CacheNode.js';
Expand Down Expand Up @@ -52,7 +53,7 @@ import DiscardNode from '../utils/DiscardNode.js';
import MaxMipLevelNode from '../utils/MaxMipLevelNode.js';

// shader node utils
import { ShaderNode, nodeObject, nodeObjects, nodeArray, nodeProxy, nodeImmutable, ConvertType, getConstNodeType, cacheMaps } from './ShaderNode.js';
import { ShaderNode, nodeObject, nodeObjects, nodeArray, nodeProxy, nodeImmutable, ConvertType, cacheMaps } from './ShaderNode.js';

// shader node base

Expand Down Expand Up @@ -90,6 +91,68 @@ export const imat4 = new ConvertType( 'imat4' );
export const umat4 = new ConvertType( 'umat4' );
export const bmat4 = new ConvertType( 'bmat4' );

// utils functions

const getConstNodeType = ( value ) => ( value === undefined || value === null ) ? null : ( value.nodeType || value.convertTo || ( typeof value === 'string' ? value : null ) );

export function getBufferSrcFunction( bufferAttribute ) {

const array = bufferAttribute.array;

let functionType;

if ( ( array instanceof Int8Array ) || ( array instanceof Int16Array ) || ( array instanceof Int32Array ) ) {

functionType = 'int';

} else if ( ( array instanceof Uint8Array ) || ( array instanceof Uint8ClampedArray ) || ( array instanceof Uint16Array ) || ( array instanceof Uint32Array ) ) {

functionType = 'uint';

} else if ( array instanceof Float32Array ) {

functionType = 'float';

}

switch ( bufferAttribute.itemSize ) {

case 1:
return ( functionType === 'uint' ) ? uint : ( functionType === 'int' ) ? int : float;

case 2:
return ( functionType === 'uint' ) ? uvec2 : ( functionType === 'int' ) ? ivec2 : vec2;

case 3:
return ( functionType === 'uint' ) ? uvec3 : ( functionType === 'int' ) ? ivec3 : vec3;

case 4:
return ( functionType === 'uint' ) ? uvec4 : ( functionType === 'int' ) ? ivec4 : vec4;

}

}

export function getBufferOutFunction( bufferAttribute ) {

switch ( bufferAttribute.itemSize ) {

case 1:
return float;

case 2:
return vec2;

case 3:
return vec3;

case 4:
return vec4;

}

}

// core

// @TODO: ArrayUniformNode
Expand Down Expand Up @@ -142,13 +205,14 @@ export const INFINITY = float( 1e6 );

export const cond = nodeProxy( CondNode );

export const assign = nodeProxy( AssignNode );

export const add = nodeProxy( OperatorNode, '+' );
export const sub = nodeProxy( OperatorNode, '-' );
export const mul = nodeProxy( OperatorNode, '*' );
export const div = nodeProxy( OperatorNode, '/' );
export const remainder = nodeProxy( OperatorNode, '%' );
export const equal = nodeProxy( OperatorNode, '==' );
export const assign = nodeProxy( OperatorNode, '=' );
export const lessThan = nodeProxy( OperatorNode, '<' );
export const greaterThan = nodeProxy( OperatorNode, '>' );
export const lessThanEqual = nodeProxy( OperatorNode, '<=' );
Expand Down Expand Up @@ -213,8 +277,8 @@ export const faceforward = nodeProxy( MathNode, MathNode.FACEFORWARD );

// accessors

export const buffer = ( value, nodeOrType, count ) => nodeObject( new BufferNode( value, getConstNodeType( nodeOrType ), count ) );
export const storage = ( value, nodeOrType, count ) => nodeObject( new StorageBufferNode( value, getConstNodeType( nodeOrType ), count ) );
export const buffer = ( value, nodeOrType, count ) => nodeObject( new BufferNode( value, getConstNodeType( nodeOrType ) || getBufferSrcFunction( value )().nodeType, count ) );
export const storage = ( value, nodeOrType, count ) => nodeObject( new StorageBufferNode( value, getConstNodeType( nodeOrType ) || getBufferSrcFunction( value )().nodeType, count ) );

export const cameraProjectionMatrix = nodeImmutable( CameraNode, CameraNode.PROJECTION_MATRIX );
export const cameraViewMatrix = nodeImmutable( CameraNode, CameraNode.VIEW_MATRIX );
Expand Down Expand Up @@ -295,7 +359,7 @@ export const pointUV = nodeImmutable( PointUVNode );

// gpgpu

export const compute = ( node, count, workgroupSize ) => nodeObject( new ComputeNode( nodeObject( node ), count, workgroupSize ) );
export const compute = ( node, count, populateOutArray, workgroupSize ) => nodeObject( new ComputeNode( nodeObject( node ), count, populateOutArray, workgroupSize ) );

// display

Expand Down
Loading