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

TSL: Fast access to transformed / normal for Batch and possibility to custom it #30468

Open
Makio64 opened this issue Feb 6, 2025 · 2 comments

Comments

@Makio64
Copy link
Contributor

Makio64 commented Feb 6, 2025

Description

Currently we can't access the "final" position of a vertex in a batch mesh.

The result is we have to rewrite the whole vertex node from batchmesh and then add our Custom logic, something like this :

	return Fn( ( builder ) => {
		let batchingIdNode = null

		// WebGL fallback if
		if ( batchingIdNode === null ) {
			// check if https://github.com/mrdoob/three.js/blob/841ea631018e0bf40c7de1b54811101f77f1e1b3/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js#L626
			if ( builder.getDrawIndex() === null ) {
				batchingIdNode = instanceIndex
			} else {
				batchingIdNode = drawIndex
			}
		}

		const getIndirectIndex = Fn( ( [id] ) => {
			const size = textureSize( textureLoad( builder.object._indirectTexture ), 0 )
			const x = int( id ).modInt( int( size ) )
			const y = int( id ).div( int( size ) )
			return textureLoad( builder.object._indirectTexture, ivec2( x, y ) ).x

		} ).setLayout( {
			name: 'getIndirectIndex',
			type: 'uint',
			inputs: [{ name: 'id', type: 'int' }]
		} )

		const matriceTexture = builder.object._matricesTexture

		const size = textureSize( textureLoad( matriceTexture ), 0 )
		const j = float( getIndirectIndex( int( batchingIdNode ) ) ).mul( 4 ).toVar()

		const x = int( j.mod( size ) )
		const y = int( j ).div( int( size ) )
		const batchingMatrix = mat4(
			textureLoad( matriceTexture, ivec2( x, y ) ),
			textureLoad( matriceTexture, ivec2( x.add( 1 ), y ) ),
			textureLoad( matriceTexture, ivec2( x.add( 2 ), y ) ),
			textureLoad( matriceTexture, ivec2( x.add( 3 ), y ) )
		)

		const bm = mat3( batchingMatrix )
		let batchPos = batchingMatrix.mul( positionLocal ).xyz.toVar()

		// -- > DO CUSTOM STUFF ON MESH POSITION HERE
		// example : batchPos.z.addAssign( time.mul( -3 ) )
		// --> OR : 
		// if( builder.material.batchPositionNode ) {
		//	batchPos = builder.material.batchPositionNode( batchPos )
		//}

		// positionWorld is broken by vertexNode, had to recalculate here
		varyingTransformBatch.assign( modelWorldMatrix.mul( batchPos ) )

		const transformed = modelViewMatrix.mul( batchPos ).toVar()
		positionView.assign( transformed ) // <------- fix point lights

		const mvPosition = transformed

		// Normals
		const transformedNormal = normalLocal.div( vec3( bm[ 0 ].dot( bm[ 0 ] ), bm[ 1 ].dot( bm[ 1 ] ), bm[ 2 ].dot( bm[ 2 ] ) ) )
		const batchingNormal = bm.mul( transformedNormal ).xyz
		normalLocal.assign( batchingNormal )

		// -- > ASSIGN FINAL POSITION / NORMAL
		// to be used in other node ( outputNode / normalNode / ... )
		varyingTransformNormal.assign( normalLocal )

		if ( builder.hasGeometryAttribute( 'tangent' ) ) {
			tangentLocal.mulAssign( bm )
		}

		return cameraProjectionMatrix.mul( mvPosition )
	} )()

Solution

I would love to see batchPosition to get the position of the bach (batchPos in the previous code) but also a batchPositionNode in material so we can add logic to it without having to rewrite it all.

Similar features for normal would be great

Alternatives

Rewrite all as above but it didnt seems good for maintenance.

@gkjohnson gkjohnson changed the title Fast access to transformed / normal for Batch and possibility to custom it TSL: Fast access to transformed / normal for Batch and possibility to custom it Feb 6, 2025
@Mugen87
Copy link
Collaborator

Mugen87 commented Feb 6, 2025

Currently we can't access the "final" position of a vertex in a batch mesh.

Like with InstanceNode, MorphNode or SkinningNode, BatchNode updates the TSL object positionLocal. So positionLocal should reflect the changes that have been applied to the vertex positions (the same holds for normalLocal and tangentLocal btw).

Is that what you are looking for?

@Makio64
Copy link
Contributor Author

Makio64 commented Feb 6, 2025

Its part of what I need but I should double check why I over engined this part..

I ideally need to have :

  • vertex position before customization
  • possibility to customize the position
  • vertex position after customization ( already the case with positionLocal )
  • access to the instance position ( not the vertex pos but the instance stock in the matrix )

Some use case :

  • instance position : in fs, we make the whole object fading if it got out of a certain radius.
  • before customization : in vs we apply an effect (example:bending), but we want effect like fog to be based on original position for better eye candy
  • after customization : have the final position always useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants