Просмотр исходного кода

SSGINode: Fix wrong bitfield typecast. (#31873)

Michael Herzog 8 месяцев назад
Родитель
Сommit
77cc698023
1 измененных файлов с 52 добавлено и 37 удалено
  1. 52 37
      examples/jsm/tsl/display/SSGINode.js

+ 52 - 37
examples/jsm/tsl/display/SSGINode.js

@@ -1,5 +1,5 @@
 import { RenderTarget, Vector2, TempNode, QuadMesh, NodeMaterial, RendererUtils, MathUtils } from 'three/webgpu';
-import { clamp, normalize, reference, nodeObject, Fn, NodeUpdateType, uniform, vec4, passTexture, uv, logarithmicDepthToViewZ, viewZToPerspectiveDepth, getViewPosition, screenCoordinate, float, sub, fract, dot, vec2, rand, vec3, Loop, mul, PI, cos, sin, uint, cross, acos, sign, pow, luminance, If, max, abs, Break, sqrt, HALF_PI, PI2, div, ceil, shiftRight, uvec2, convertToTexture, bool, getNormalFromDepth } from 'three/tsl';
+import { clamp, normalize, reference, nodeObject, Fn, NodeUpdateType, uniform, vec4, passTexture, uv, logarithmicDepthToViewZ, viewZToPerspectiveDepth, getViewPosition, screenCoordinate, float, sub, fract, dot, vec2, rand, vec3, Loop, mul, PI, cos, sin, uint, cross, acos, sign, pow, luminance, If, max, abs, Break, sqrt, HALF_PI, div, ceil, shiftRight, convertToTexture, bool, getNormalFromDepth } from 'three/tsl';
 
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 const _size = /*@__PURE__*/ new Vector2();
@@ -377,6 +377,7 @@ class SSGINode extends TempNode {
 
 		const uvNode = uv();
 		const MAX_RAY = uint( 32 );
+		const globalOccludedBitfield = uint( 0 );
 
 		const sampleDepth = ( uv ) => {
 
@@ -403,6 +404,12 @@ class SSGINode extends TempNode {
 
 			return float( 0.25 ).mul( sub( position.y, position.x ).bitAnd( 3 ) );
 
+		} ).setLayout( {
+			name: 'spatialOffsets',
+			type: 'float',
+			inputs: [
+				{ name: 'position', type: 'vec2' }
+			]
 		} );
 
 		// Interleaved gradient function from Jimenez 2014 http://goo.gl/eomGso
@@ -411,6 +418,12 @@ class SSGINode extends TempNode {
 
 			return fract( float( 52.9829189 ).mul( fract( dot( position, vec2( 0.06711056, 0.00583715 ) ) ) ) );
 
+		} ).setLayout( {
+			name: 'gradientNoise',
+			type: 'float',
+			inputs: [
+				{ name: 'position', type: 'vec2' }
+			]
 		} );
 
 		const GTAOFastAcos = Fn( ( [ value ] ) => {
@@ -423,35 +436,31 @@ class SSGINode extends TempNode {
 
 			return vec2( x, y );
 
+		} ).setLayout( {
+			name: 'GTAOFastAcos',
+			type: 'vec2',
+			inputs: [
+				{ name: 'value', type: 'vec2' }
+			]
 		} );
 
-		const bitCount = Fn( ( [ value_immutable ] ) => {
+		const bitCount = Fn( ( [ value ] ) => {
 
-			const value = value_immutable;
-			value.assign( value.sub( value.shiftRight( uint( 1 ) ).bitAnd( uint( 0x55555555 ) ) ) );
-			value.assign( value.bitAnd( uint( 0x33333333 ) ).add( value.shiftRight( uint( 2 ) ).bitAnd( uint( 0x33333333 ) ) ) );
+			const v = uint( value );
+			v.assign( v.sub( v.shiftRight( uint( 1 ) ).bitAnd( uint( 0x55555555 ) ) ) );
+			v.assign( v.bitAnd( uint( 0x33333333 ) ).add( v.shiftRight( uint( 2 ) ).bitAnd( uint( 0x33333333 ) ) ) );
 
-			return value.add( value.shiftRight( uint( 4 ) ) ).bitAnd( uint( 0xF0F0F0F ) ).mul( uint( 0x1010101 ) ).shiftRight( uint( 24 ) );
+			return v.add( v.shiftRight( uint( 4 ) ) ).bitAnd( uint( 0xF0F0F0F ) ).mul( uint( 0x1010101 ) ).shiftRight( uint( 24 ) );
 
+		} ).setLayout( {
+			name: 'bitCount',
+			type: 'uint',
+			inputs: [
+				{ name: 'value', type: 'uint' }
+			]
 		} );
 
-		const computeOccludedBitfield = Fn( ( [ minHorizon, maxHorizon, globalOccludedBitfield ] ) => {
-
-			const startHorizonInt = uint( minHorizon.mul( float( MAX_RAY ) ) ).toConst();
-			const angleHorizonInt = uint( ceil( maxHorizon.sub( minHorizon ).mul( float( MAX_RAY ) ) ) ).toConst();
-			const angleHorizonBitfield = angleHorizonInt.greaterThan( uint( 0 ) ).select( uint( shiftRight( uint( 0xFFFFFFFF ), uint( 32 ).sub( MAX_RAY ).add( MAX_RAY.sub( angleHorizonInt ) ) ) ), uint( 0 ) ).toConst();
-			let currentOccludedBitfield = angleHorizonBitfield.shiftLeft( startHorizonInt );
-			currentOccludedBitfield = currentOccludedBitfield.bitAnd( globalOccludedBitfield.bitNot() );
-
-			const result = uvec2();
-			result.x = globalOccludedBitfield.bitOr( currentOccludedBitfield );
-			result.y = bitCount( currentOccludedBitfield );
-
-			return result;
-
-		} );
-
-		const horizonSampling = Fn( ( [ directionIsRight, RADIUS, viewPosition, slideDirTexelSize, initialRayStep, uvNode, viewDir, viewNormal, n, globalOccludedBitfield ] ) => {
+		const horizonSampling = Fn( ( [ directionIsRight, RADIUS, viewPosition, slideDirTexelSize, initialRayStep, uvNode, viewDir, viewNormal, n ] ) => {
 
 			const STEP_COUNT = this.stepCount.toConst();
 			const EXP_FACTOR = this.expFactor.toConst();
@@ -476,7 +485,6 @@ class SSGINode extends TempNode {
 			const samplingDirection = directionIsRight.equal( true ).select( 1, - 1 );
 
 			const color = vec3( 0 );
-			const occludedBitfield = uint( globalOccludedBitfield ).toVar();
 
 			const lastSampleViewPosition = vec3( viewPosition ).toVar();
 
@@ -502,9 +510,21 @@ class SSGINode extends TempNode {
 				frontBackHorizon = clamp( div( mul( samplingDirection, frontBackHorizon.negate() ).sub( n.sub( HALF_PI ) ), PI ) ); // Port note: subtract half pi instead of adding it
 				frontBackHorizon = directionIsRight.equal( true ).select( frontBackHorizon.yx, frontBackHorizon.xy ); // Front/Back get inverted depending on angle
 
-				const result = computeOccludedBitfield( frontBackHorizon.x, frontBackHorizon.y, occludedBitfield );
-				occludedBitfield.assign( result.x );
-				const numOccludedZones = result.y;
+				// inline ComputeOccludedBitfield() for easier debugging
+
+				const minHorizon = frontBackHorizon.x.toConst();
+				const maxHorizon = frontBackHorizon.y.toConst();
+
+				const startHorizonInt = uint( frontBackHorizon.mul( float( MAX_RAY ) ) ).toConst();
+				const angleHorizonInt = uint( ceil( maxHorizon.sub( minHorizon ).mul( float( MAX_RAY ) ) ) ).toConst();
+				const angleHorizonBitfield = angleHorizonInt.greaterThan( uint( 0 ) ).select( uint( shiftRight( uint( 0xFFFFFFFF ), uint( 32 ).sub( MAX_RAY ).add( MAX_RAY.sub( angleHorizonInt ) ) ) ), uint( 0 ) ).toConst();
+				let currentOccludedBitfield = angleHorizonBitfield.shiftLeft( startHorizonInt );
+				currentOccludedBitfield = currentOccludedBitfield.bitAnd( globalOccludedBitfield.bitNot() );
+
+				globalOccludedBitfield.assign( globalOccludedBitfield.bitOr( currentOccludedBitfield ) );
+				const numOccludedZones = bitCount( currentOccludedBitfield );
+
+				//
 
 				If( numOccludedZones.greaterThan( 0 ), () => { // If a ray hit the sample, that sample is visible from shading point
 
@@ -538,7 +558,7 @@ class SSGINode extends TempNode {
 
 			} );
 
-			return vec4( color, occludedBitfield );
+			return vec3( color );
 
 		} );
 
@@ -568,7 +588,7 @@ class SSGINode extends TempNode {
 
 			Loop( { start: uint( 0 ), end: ROTATION_COUNT, type: 'uint', condition: '<' }, ( { i } ) => {
 
-				const rotationAngle = mul( float( i ).add( noiseDirection ).add( this._temporalDirection ), PI2.div( float( ROTATION_COUNT ) ) ).toConst(); // Port note: PI was changed to PI2 to fix a sampling asymmetry issue
+				const rotationAngle = mul( float( i ).add( noiseDirection ).add( this._temporalDirection ), PI.div( float( ROTATION_COUNT ) ) ).toConst();
 				const sliceDir = vec3( vec2( cos( rotationAngle ), sin( rotationAngle ) ), 0 ).toConst();
 				const slideDirTexelSize = sliceDir.xy.mul( float( 1 ).div( this._resolution ) ).toConst();
 
@@ -580,15 +600,10 @@ class SSGINode extends TempNode {
 				const cos_n = clamp( dot( projectedNormalNormalized, viewDir ), - 1, 1 ).toConst();
 				const n = sign( dot( projectedNormal, tangent ) ).negate().mul( acos( cos_n ) ).toConst();
 
-				const globalOccludedBitfield = uint( 0 );
-
-				const resultRight = horizonSampling( bool( true ), RADIUS, viewPosition, slideDirTexelSize, initialRayStep, uvNode, viewDir, viewNormal, n, globalOccludedBitfield );
-				color.addAssign( resultRight.xyz );
-				globalOccludedBitfield.assign( resultRight.a );
+				globalOccludedBitfield.assign( 0 );
 
-				const resultLeft = horizonSampling( bool( false ), RADIUS, viewPosition, slideDirTexelSize, initialRayStep, uvNode, viewDir, viewNormal, n, globalOccludedBitfield );
-				color.addAssign( resultLeft.xyz );
-				globalOccludedBitfield.assign( resultLeft.a );
+				color.addAssign( horizonSampling( bool( true ), RADIUS, viewPosition, slideDirTexelSize, initialRayStep, uvNode, viewDir, viewNormal, n ) );
+				color.addAssign( horizonSampling( bool( false ), RADIUS, viewPosition, slideDirTexelSize, initialRayStep, uvNode, viewDir, viewNormal, n ) );
 
 				ao.addAssign( float( bitCount( globalOccludedBitfield ) ).div( float( MAX_RAY ) ) );
 

粤ICP备19079148号