Browse Source

WebGPURenderer: support mat2() and extend RotateNode to support vec2 rotation. (#27612)

* add mat2

* extend rotateNode to vec2

* remove unused code

* rework

---------

Co-authored-by: aardgoose <[email protected]>
aardgoose 1 năm trước cách đây
mục cha
commit
59ceca26a0

+ 1 - 0
examples/jsm/nodes/core/NodeBuilder.js

@@ -575,6 +575,7 @@ class NodeBuilder {
 
 		if ( vecNum !== null ) return Number( vecNum[ 1 ] );
 		if ( vecType === 'float' || vecType === 'bool' || vecType === 'int' || vecType === 'uint' ) return 1;
+		if ( /mat2/.test( type ) === true ) return 4;
 		if ( /mat3/.test( type ) === true ) return 9;
 		if ( /mat4/.test( type ) === true ) return 16;
 

+ 1 - 0
examples/jsm/nodes/core/constants.js

@@ -17,6 +17,7 @@ export const NodeType = {
 	VECTOR2: 'vec2',
 	VECTOR3: 'vec3',
 	VECTOR4: 'vec4',
+	MATRIX2: 'mat2',
 	MATRIX3: 'mat3',
 	MATRIX4: 'mat4'
 };

+ 1 - 7
examples/jsm/nodes/materials/SpriteNodeMaterial.js

@@ -61,13 +61,7 @@ class SpriteNodeMaterial extends NodeMaterial {
 
 		const rotation = float( rotationNode || materialRotation );
 
-		const cosAngle = rotation.cos();
-		const sinAngle = rotation.sin();
-
-		const rotatedPosition = vec2( // @TODO: Maybe we can create mat2 and write something like rotationMatrix.mul( alignedPosition )?
-			vec2( cosAngle, sinAngle.negate() ).dot( alignedPosition ),
-			vec2( sinAngle, cosAngle ).dot( alignedPosition )
-		);
+		const rotatedPosition = alignedPosition.rotate( rotation );
 
 		mvPosition = vec4( mvPosition.xy.add( rotatedPosition ), mvPosition.zw );
 

+ 9 - 0
examples/jsm/nodes/shadernode/ShaderNode.js

@@ -574,6 +574,11 @@ export const ivec4 = new ConvertType( 'ivec4' );
 export const uvec4 = new ConvertType( 'uvec4' );
 export const bvec4 = new ConvertType( 'bvec4' );
 
+export const mat2 = new ConvertType( 'mat2' );
+export const imat2 = new ConvertType( 'imat2' );
+export const umat2 = new ConvertType( 'umat2' );
+export const bmat2 = new ConvertType( 'bmat2' );
+
 export const mat3 = new ConvertType( 'mat3' );
 export const imat3 = new ConvertType( 'imat3' );
 export const umat3 = new ConvertType( 'umat3' );
@@ -604,6 +609,10 @@ addNodeElement( 'vec4', vec4 );
 addNodeElement( 'ivec4', ivec4 );
 addNodeElement( 'uvec4', uvec4 );
 addNodeElement( 'bvec4', bvec4 );
+addNodeElement( 'mat2', mat2 );
+addNodeElement( 'imat2', imat2 );
+addNodeElement( 'umat2', umat2 );
+addNodeElement( 'bmat2', bmat2 );
 addNodeElement( 'mat3', mat3 );
 addNodeElement( 'imat3', imat3 );
 addNodeElement( 'umat3', umat3 );

+ 32 - 7
examples/jsm/nodes/utils/RotateNode.js

@@ -4,6 +4,7 @@ import {
 	addNodeElement,
 	nodeProxy,
 	vec4,
+	mat2,
 	mat4,
 } from '../shadernode/ShaderNode.js';
 import { cos, sin } from '../math/MathNode.js';
@@ -12,23 +13,47 @@ class RotateNode extends TempNode {
 
 	constructor( positionNode, rotationNode ) {
 
-		super( 'vec3' );
+		super();
 
 		this.positionNode = positionNode;
 		this.rotationNode = rotationNode;
 
 	}
 
-	setup() {
+	getNodeType( builder ) {
+
+		return this.positionNode.getNodeType( builder );
+
+	}
+
+	setup( builder ) {
 
 		const { rotationNode, positionNode } = this;
 
-		const rotation = rotationNode;
-		const rotationXMatrix = mat4( vec4( 1.0, 0.0, 0.0, 0.0 ), vec4( 0.0, cos( rotation.x ), sin( rotation.x ).negate(), 0.0 ), vec4( 0.0, sin( rotation.x ), cos( rotation.x ), 0.0 ), vec4( 0.0, 0.0, 0.0, 1.0 ) );
-		const rotationYMatrix = mat4( vec4( cos( rotation.y ), 0.0, sin( rotation.y ), 0.0 ), vec4( 0.0, 1.0, 0.0, 0.0 ), vec4( sin( rotation.y ).negate(), 0.0, cos( rotation.y ), 0.0 ), vec4( 0.0, 0.0, 0.0, 1.0 ) );
-		const rotationZMatrix = mat4( vec4( cos( rotation.z ), sin( rotation.z ).negate(), 0.0, 0.0 ), vec4( sin( rotation.z ), cos( rotation.z ), 0.0, 0.0 ), vec4( 0.0, 0.0, 1.0, 0.0 ), vec4( 0.0, 0.0, 0.0, 1.0 ) );
+		const nodeType = this.getNodeType( builder );
+
+		if ( nodeType === 'vec2' ) {
+
+			const cosAngle = rotationNode.cos();
+			const sinAngle = rotationNode.sin();
+
+			const rotationMatrix = mat2(
+				cosAngle, sinAngle,
+				sinAngle.negate(), cosAngle
+			);
+
+			return rotationMatrix.mul( positionNode );
+
+		} else {
+
+			const rotation = rotationNode;
+			const rotationXMatrix = mat4( vec4( 1.0, 0.0, 0.0, 0.0 ), vec4( 0.0, cos( rotation.x ), sin( rotation.x ).negate(), 0.0 ), vec4( 0.0, sin( rotation.x ), cos( rotation.x ), 0.0 ), vec4( 0.0, 0.0, 0.0, 1.0 ) );
+			const rotationYMatrix = mat4( vec4( cos( rotation.y ), 0.0, sin( rotation.y ), 0.0 ), vec4( 0.0, 1.0, 0.0, 0.0 ), vec4( sin( rotation.y ).negate(), 0.0, cos( rotation.y ), 0.0 ), vec4( 0.0, 0.0, 0.0, 1.0 ) );
+			const rotationZMatrix = mat4( vec4( cos( rotation.z ), sin( rotation.z ).negate(), 0.0, 0.0 ), vec4( sin( rotation.z ), cos( rotation.z ), 0.0, 0.0 ), vec4( 0.0, 0.0, 1.0, 0.0 ), vec4( 0.0, 0.0, 0.0, 1.0 ) );
+
+			return rotationXMatrix.mul( rotationYMatrix ).mul( rotationZMatrix ).mul( vec4( positionNode, 1.0 ) ).xyz;
 
-		return rotationXMatrix.mul( rotationYMatrix ).mul( rotationZMatrix ).mul( vec4( positionNode, 1.0 ) ).xyz;
+		}
 
 	}
 

+ 1 - 9
examples/jsm/nodes/utils/RotateUVNode.js

@@ -18,17 +18,9 @@ class RotateUVNode extends TempNode {
 
 		const { uvNode, rotationNode, centerNode } = this;
 
-		const cosAngle = rotationNode.cos();
-		const sinAngle = rotationNode.sin();
-
 		const vector = uvNode.sub( centerNode );
 
-		const rotatedVector = vec2( // @TODO: Maybe we can create mat2 and write something like rotationMatrix.mul( vector )?
-			vec2( cosAngle, sinAngle ).dot( vector ),
-			vec2( sinAngle.negate(), cosAngle ).dot( vector )
-		);
-
-		return rotatedVector.add( centerNode );
+		return vector.rotate( rotationNode ).add( centerNode );
 
 	}
 

+ 5 - 0
examples/jsm/renderers/webgpu/nodes/WGSLNodeBuilder.js

@@ -55,6 +55,11 @@ const wgslTypeLib = {
 	uvec4: 'vec4<u32>',
 	bvec4: 'vec4<bool>',
 
+	mat2: 'mat2x2<f32>',
+	imat2: 'mat2x2<i32>',
+	umat2: 'mat2x2<u32>',
+	bmat2: 'mat2x2<bool>',
+
 	mat3: 'mat3x3<f32>',
 	imat3: 'mat3x3<i32>',
 	umat3: 'mat3x3<u32>',