Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
8 changes: 4 additions & 4 deletions examples/jsm/tsl/lighting/ClusteredLightsNode.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { DataTexture, FloatType, RGBAFormat, Vector2, Vector3, LightsNode, NodeUpdateType } from 'three/webgpu';

import {
attributeArray, nodeProxy, int, float, vec3, vec4, ivec2, ivec4, uniform, Break, Loop, positionView,
attributeArray, nodeProxy, uint, int, float, vec3, vec4, ivec2, ivec4, uniform, Break, Loop, positionView,
Fn, If, Return, textureLoad, instanceIndex, screenCoordinate, directPointLight,
renderGroup,
min, max, pow, log, clamp, dot
Expand Down Expand Up @@ -472,9 +472,9 @@ class ClusteredLightsNode extends LightsNode {
const invFocalY = float( 1 ).div( this._cameraProjectionMatrix.element( 1 ).element( 1 ) );

// 3D cluster coordinates from instanceIndex
const cx = instanceIndex.mod( NX );
const cy = instanceIndex.div( NX ).mod( NY );
const cz = instanceIndex.div( NX * NY );
const cx = instanceIndex.mod( uint( NX ) );
const cy = instanceIndex.div( uint( NX ) ).mod( uint( NY ) );
const cz = instanceIndex.div( uint( NX * NY ) );

// NDC X/Y bounds of the cluster.
// Y is flipped: cy=0 is the top screen row (fragment y=0), which is NDC y=+1.
Expand Down
6 changes: 3 additions & 3 deletions examples/jsm/tsl/lighting/TiledLightsNode.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { DataTexture, FloatType, RGBAFormat, Vector2, Vector3, LightsNode, NodeUpdateType } from 'three/webgpu';

import {
attributeArray, nodeProxy, int, float, vec2, ivec2, ivec4, uniform, Break, Loop, positionView,
attributeArray, nodeProxy, uint, int, float, vec2, ivec2, ivec4, uniform, Break, Loop, positionView,
Fn, If, Return, textureLoad, instanceIndex, screenCoordinate, directPointLight
} from 'three/tsl';

Expand Down Expand Up @@ -364,8 +364,8 @@ class TiledLightsNode extends LightsNode {
const tiledBufferSize = bufferSize.clone().divideScalar( tileSize ).floor();

const tileScreen = vec2(
instanceIndex.mod( tiledBufferSize.width ),
instanceIndex.div( tiledBufferSize.width )
instanceIndex.mod( uint( tiledBufferSize.width ) ),
instanceIndex.div( uint( tiledBufferSize.width ) )
).mul( tileSize ).div( screenSize );

const blockSize = float( tileSize ).div( screenSize );
Expand Down
16 changes: 8 additions & 8 deletions examples/webgpu_compute_nanite-style.html
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,7 @@
const lodChunkStart = lodData.z;

// Calculate Work Items (64 triangles per item)
const workItems = lodNumTriangles.add( 63 ).div( 64 );
const workItems = lodNumTriangles.add( uint( 63 ) ).div( uint( 64 ) );

// Evaluate each Chunk (Cluster)
Loop( { name: 'cIdx', type: 'uint', start: uint( 0 ), end: workItems, condition: '<' }, ( { cIdx: chunkIndex } ) => {
Expand Down Expand Up @@ -530,7 +530,7 @@

// Split totalWorkgroups into 2D dispatch if it exceeds 65535
const dispatchX = min( totalWorkgroups, maxDim );
const dispatchY = totalWorkgroups.add( maxDim ).sub( 1 ).div( maxDim );
const dispatchY = totalWorkgroups.add( maxDim ).sub( uint( 1 ) ).div( maxDim );

dispatchBuffer.element( 0 ).assign( dispatchX );
dispatchBuffer.element( 1 ).assign( dispatchY );
Expand All @@ -554,8 +554,8 @@

If( instanceIndex.lessThan( totalThreads ), () => {

const workItemId = instanceIndex.div( 64 );
const localTriangleIndex = instanceIndex.mod( 64 );
const workItemId = instanceIndex.div( uint( 64 ) );
const localTriangleIndex = instanceIndex.mod( uint( 64 ) );

const workItem = workQueueBuffer.element( workItemId );
const instId = workItem.x;
Expand Down Expand Up @@ -807,8 +807,8 @@
hwMaterial.positionNode = Fn( () => {

// vertexIndex: 0,1,2, 3,4,5, 6,7,8, ...
const triIndex = vertexIndex.div( 3 ); // which triangle in HW queue
const localVert = vertexIndex.mod( 3 ); // which vertex (0, 1, 2)
const triIndex = vertexIndex.div( uint( 3 ) ); // which triangle in HW queue
const localVert = vertexIndex.mod( uint( 3 ) ); // which vertex (0, 1, 2)

const payload32 = hwQueueRead.element( triIndex.add( 1 ) );
const instId = payload32.shiftRight( TRIANGLE_INDEX_BITS );
Expand Down Expand Up @@ -841,7 +841,7 @@

If( materialModeUniform.equal( 0 ), () => {

const meshletId = meshletIdBuffer.element( megaTriangleIndex ).add( instId.mul( 1000 ) );
const meshletId = meshletIdBuffer.element( megaTriangleIndex ).add( instId.mul( uint( 1000 ) ) );
outColor.assign( hashColor( meshletId ) );

} ).Else( () => {
Expand Down Expand Up @@ -994,7 +994,7 @@

If( materialModeUniform.equal( 0 ), () => {

const meshletId = meshletIdBuffer.element( megaTriangleIndex ).add( instId.mul( 1000 ) );
const meshletId = meshletIdBuffer.element( megaTriangleIndex ).add( instId.mul( uint( 1000 ) ) );
outColor.assign( hashColor( meshletId ) );

} ).Else( () => {
Expand Down
6 changes: 3 additions & 3 deletions examples/webgpu_compute_particles.html
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
<script type="module">

import * as THREE from 'three/webgpu';
import { Fn, If, uniform, float, uv, vec3, hash, shapeCircle,
import { Fn, If, uniform, float, uv, uint, vec3, hash, shapeCircle,
instancedArray, instanceIndex } from 'three/tsl';

import { Inspector } from 'three/addons/inspector/Inspector.js';
Expand Down Expand Up @@ -86,8 +86,8 @@
const position = positions.element( instanceIndex );
const color = colors.element( instanceIndex );

const x = instanceIndex.mod( amount );
const z = instanceIndex.div( amount );
const x = instanceIndex.mod( uint( amount ) );
const z = instanceIndex.div( uint( amount ) );

position.x = offset.sub( x ).mul( separation );
position.z = offset.sub( z ).mul( separation );
Expand Down
6 changes: 3 additions & 3 deletions examples/webgpu_compute_texture.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
<script type="module">

import * as THREE from 'three/webgpu';
import { texture, textureStore, Fn, instanceIndex, float, uvec2, vec4 } from 'three/tsl';
import { texture, textureStore, Fn, instanceIndex, uint, float, uvec2, vec4 } from 'three/tsl';

import WebGPU from 'three/addons/capabilities/WebGPU.js';

Expand Down Expand Up @@ -73,8 +73,8 @@

const computeTexture = Fn( ( { storageTexture } ) => {

const posX = instanceIndex.mod( width );
const posY = instanceIndex.div( width );
const posX = instanceIndex.mod( uint( width ) );
const posY = instanceIndex.div( uint( width ) );
const indexUV = uvec2( posX, posY );

// https://www.shadertoy.com/view/Xst3zN
Expand Down
10 changes: 5 additions & 5 deletions examples/webgpu_compute_texture_pingpong.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
<script type="module">

import * as THREE from 'three/webgpu';
import { storageTexture, textureStore, Fn, instanceIndex, uniform, float, vec2, vec4, uvec2, ivec2, int, NodeAccess } from 'three/tsl';
import { storageTexture, textureStore, Fn, instanceIndex, uniform, float, vec2, vec4, uvec2, ivec2, uint, int, NodeAccess } from 'three/tsl';

import WebGPU from 'three/addons/capabilities/WebGPU.js';

Expand Down Expand Up @@ -99,8 +99,8 @@

const computeInit = Fn( () => {

const posX = instanceIndex.mod( width );
const posY = instanceIndex.div( width );
const posX = instanceIndex.mod( uint( width ) );
const posY = instanceIndex.div( uint( width ) );
const indexUV = uvec2( posX, posY );
const uv = vec2( float( posX ).div( width ), float( posY ).div( height ) );

Expand Down Expand Up @@ -130,8 +130,8 @@
// compute loop: read from one texture, blur, write to another
const computePingPong = Fn( ( [ readTex, writeTex ] ) => {

const posX = instanceIndex.mod( width );
const posY = instanceIndex.div( width );
const posX = instanceIndex.mod( uint( width ) );
const posY = instanceIndex.div( uint( width ) );
const indexUV = ivec2( int( posX ), int( posY ) );

const color = blur( readTex, indexUV );
Expand Down
2 changes: 1 addition & 1 deletion src/nodes/accessors/Morph.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const _morphBaseInfluences = /*@__PURE__*/ new WeakMap();
*/
const getMorph = /*@__PURE__*/ Fn( ( { bufferMap, influence, stride, width, depth, offset } ) => {

const texelIndex = int( vertexIndex ).mul( stride ).add( offset );
const texelIndex = int( vertexIndex ).mul( int( stride ) ).add( offset );

const y = texelIndex.div( width );
const x = texelIndex.sub( y.mul( width ) );
Expand Down
27 changes: 27 additions & 0 deletions src/nodes/core/NodeBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ const toFloat = ( value ) => {

};

const _componentTypeRanks = { bool: 0, uint: 1, int: 2, float: 3 };

/**
* Base class for builders which generate a shader program based
* on a 3D object and its node material definition.
Expand Down Expand Up @@ -1469,6 +1471,18 @@ class NodeBuilder {

}

/**
* Whether the given type is a scalar type or not.
*
* @param {string} type - The type to check.
* @return {boolean} Whether the given type is a scalar type or not.
*/
isScalar( type ) {

return type === 'float' || type === 'bool' || type === 'int' || type === 'uint';

}

/**
* Whether the given type is a vector type or not.
*
Expand Down Expand Up @@ -1717,6 +1731,19 @@ class NodeBuilder {

}

/**
* Returns the higher-ranked component type for the given component types.
*
* @param {string} typeA - The first type.
* @param {string} typeB - The second type.
* @return {string} The new type.
*/
getPromotedComponentType( typeA, typeB ) {

return _componentTypeRanks[ typeA ] >= _componentTypeRanks[ typeB ] ? typeA : typeB;

}

/**
* Returns the integer type pendant for the given type.
*
Expand Down
5 changes: 3 additions & 2 deletions src/nodes/math/Hash.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Fn } from '../tsl/TSLBase.js';
import { uint } from '../tsl/TSLCore.js';

/**
* Generates a hash value in the range `[0, 1]` from the given seed.
Expand All @@ -12,8 +13,8 @@ export const hash = /*@__PURE__*/ Fn( ( [ seed ] ) => {

// Taken from https://www.shadertoy.com/view/XlGcRh, originally from pcg-random.org

const state = seed.toUint().mul( 747796405 ).add( 2891336453 );
const word = state.shiftRight( state.shiftRight( 28 ).add( 4 ) ).bitXor( state ).mul( 277803737 );
const state = seed.toUint().mul( uint( 747796405 ) ).add( uint( 2891336453 ) );
const word = state.shiftRight( state.shiftRight( 28 ).add( 4 ) ).bitXor( state ).mul( uint( 277803737 ) );
const result = word.shiftRight( 22 ).bitXor( word );

return result.toFloat().mul( 1 / 2 ** 32 ); // Convert to range [0, 1)
Expand Down
30 changes: 24 additions & 6 deletions src/nodes/math/MathNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,21 +109,31 @@ class MathNode extends TempNode {
const bLen = builder.isMatrix( bType ) ? 0 : builder.getTypeLength( bType );
const cLen = builder.isMatrix( cType ) ? 0 : builder.getTypeLength( cType );

let type;

if ( aLen > bLen && aLen > cLen ) {

return aType;
type = aType;

} else if ( bLen > cLen ) {

return bType;
type = bType;

} else if ( cLen > aLen ) {

return cType;
type = cType;

} else {

type = aType;

}

return aType;
let promotedType = builder.getComponentType( aType );
if ( bType !== null ) promotedType = builder.getPromotedComponentType( promotedType, builder.getComponentType( bType ) );
if ( cType !== null ) promotedType = builder.getPromotedComponentType( promotedType, builder.getComponentType( cType ) );

return builder.changeComponentType( type, promotedType );

}

Expand Down Expand Up @@ -227,7 +237,7 @@ class MathNode extends TempNode {

let method = this.method;

const type = this.getNodeType( builder );
let type = this.getNodeType( builder );
const inputType = this.getInputType( builder );

const a = this.aNode;
Expand All @@ -238,7 +248,7 @@ class MathNode extends TempNode {

if ( method === MathNode.NEGATE ) {

return builder.format( '( - ' + a.build( builder, inputType ) + ' )', type, output );
return builder.format( `( - ${ a.build( builder, inputType ) } )`, type, output );

} else {

Expand Down Expand Up @@ -303,6 +313,14 @@ class MathNode extends TempNode {

}

if ( method === MathNode.DOT ) {

// WGSL returns component type, whereas GLSL always returns float.

type = builder.getComponentType( inputType );

}

return builder.format( `${ builder.getMethod( method, type ) }( ${params.join( ', ' )} )`, type, output );

}
Expand Down
Loading