sunag 2 месяцев назад
Родитель
Сommit
ecf6e9c2a1

+ 1 - 0
src/Three.TSL.js

@@ -127,6 +127,7 @@ export const clamp = TSL.clamp;
 export const clearcoat = TSL.clearcoat;
 export const clearcoatNormalView = TSL.clearcoatNormalView;
 export const clearcoatRoughness = TSL.clearcoatRoughness;
+export const clipSpace = TSL.clipSpace;
 export const code = TSL.code;
 export const color = TSL.color;
 export const colorSpaceToWorking = TSL.colorSpaceToWorking;

+ 3 - 1
src/materials/nodes/NodeMaterial.js

@@ -539,6 +539,8 @@ class NodeMaterial extends Material {
 
 		const vertexNode = this.vertexNode || mvp;
 
+		builder.context.clipSpace = vertexNode;
+
 		builder.stack.outputNode = vertexNode;
 
 		this.setupHardwareClipping( builder );
@@ -803,7 +805,7 @@ class NodeMaterial extends Material {
 
 		this.setupPosition( builder );
 
-		builder.context.vertex = builder.removeStack();
+		builder.context.position = builder.removeStack();
 
 		return modelViewProjection;
 

+ 41 - 1
src/nodes/accessors/Position.js

@@ -1,6 +1,28 @@
 import { attribute } from '../core/AttributeNode.js';
-import { Fn, vec3 } from '../tsl/TSLCore.js';
+import { Fn, vec3, vec4 } from '../tsl/TSLCore.js';
 import { modelWorldMatrix } from './ModelNode.js';
+import { cameraProjectionMatrixInverse, cameraWorldMatrix } from './Camera.js';
+import { warnOnce } from '../../utils.js';
+
+/**
+ * TSL object that represents the clip space position of the current rendered object.
+ *
+ * @tsl
+ * @type {VaryingNode<vec4>}
+ */
+export const clipSpace = /*@__PURE__*/ ( Fn( ( builder ) => {
+
+	if ( builder.shaderStage !== 'fragment' ) {
+
+		warnOnce( 'TSL: `clipSpace` is only available in fragment stage.' );
+
+		return vec4();
+
+	}
+
+	return builder.context.clipSpace.toVarying( 'v_clipSpace' );
+
+} ).once() )();
 
 /**
  * TSL object that represents the position attribute of the current rendered object.
@@ -35,6 +57,14 @@ export const positionPrevious = /*@__PURE__*/ positionGeometry.toVarying( 'posit
  */
 export const positionWorld = /*@__PURE__*/ ( Fn( ( builder ) => {
 
+	if ( builder.shaderStage === 'fragment' && builder.material.vertexNode ) {
+
+		// reconstruct world position from view position
+
+		return cameraWorldMatrix.mul( positionView ).xyz.toVar( 'positionWorld' );
+
+	}
+
 	return modelWorldMatrix.mul( positionLocal ).xyz.toVarying( builder.getSubBuildProperty( 'v_positionWorld' ) );
 
 }, 'vec3' ).once( [ 'POSITION' ] ) )();
@@ -61,6 +91,16 @@ export const positionWorldDirection = /*@__PURE__*/ ( Fn( () => {
  */
 export const positionView = /*@__PURE__*/ ( Fn( ( builder ) => {
 
+	if ( builder.shaderStage === 'fragment' && builder.material.vertexNode ) {
+
+		// reconstruct view position from clip space
+
+		const viewPos = cameraProjectionMatrixInverse.mul( clipSpace );
+
+		return viewPos.xyz.div( viewPos.w ).toVar( 'positionView' );
+
+	}
+
 	return builder.context.setupPositionView().toVarying( 'v_positionView' );
 
 }, 'vec3' ).once( [ 'POSITION' ] ) )();

+ 2 - 2
src/nodes/core/NodeBuilder.js

@@ -2916,9 +2916,9 @@ class NodeBuilder {
 
 			this.setBuildStage( buildStage );
 
-			if ( this.context.vertex && this.context.vertex.isNode ) {
+			if ( this.context.position && this.context.position.isNode ) {
 
-				this.flowNodeFromShaderStage( 'vertex', this.context.vertex );
+				this.flowNodeFromShaderStage( 'vertex', this.context.position );
 
 			}
 

+ 2 - 2
src/renderers/webgpu/nodes/WGSLNodeBuilder.js

@@ -1663,7 +1663,7 @@ ${ flowData.code }
 
 		if ( shaderStage === 'vertex' ) {
 
-			this.getBuiltin( 'position', 'Vertex', 'vec4<f32>', 'vertex' );
+			this.getBuiltin( 'position', 'builtinClipSpace', 'vec4<f32>', 'vertex' );
 
 		}
 
@@ -1961,7 +1961,7 @@ ${ flowData.code }
 
 					if ( shaderStage === 'vertex' ) {
 
-						flow += `varyings.Vertex = ${ flowSlotData.result };`;
+						flow += `varyings.builtinClipSpace = ${ flowSlotData.result };`;
 
 					} else if ( shaderStage === 'fragment' ) {
 

粤ICP备19079148号