Skip to content

Commit 172c2ee

Browse files
committed
TRAAPassNode: Implement prepass.
1 parent 13aa23a commit 172c2ee

File tree

1 file changed

+61
-72
lines changed

1 file changed

+61
-72
lines changed

examples/jsm/tsl/display/TRAAPassNode.js

Lines changed: 61 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Color, Vector2, PostProcessingUtils, NearestFilter, Matrix4 } from 'three';
1+
import { Color, Vector2, PostProcessingUtils, NearestFilter, Matrix4, DepthTexture, RenderTarget, HalfFloatType } from 'three';
22
import { add, float, If, Loop, int, Fn, min, max, clamp, nodeObject, PassNode, QuadMesh, texture, NodeMaterial, uniform, uv, vec2, vec4, luminance } from 'three/tsl';
33

44
const _quadMesh = /*@__PURE__*/ new QuadMesh();
@@ -34,20 +34,34 @@ class TRAAPassNode extends PassNode {
3434
this._jitterIndex = 0;
3535
this._originalProjectionMatrix = new Matrix4();
3636

37+
// render targets
38+
39+
this._sampleRenderTarget = new RenderTarget( 1, 1, { type: HalfFloatType } );
40+
this._historyRenderTarget = new RenderTarget( 1, 1, { type: HalfFloatType } );
41+
this._resolveRenderTarget = new RenderTarget( 1, 1, { type: HalfFloatType } );
42+
43+
this._sampleRenderTarget.depthTexture = new DepthTexture();
44+
this._sampleRenderTarget.texture.minFiler = NearestFilter;
45+
this._sampleRenderTarget.texture.magFilter = NearestFilter;
46+
3747
// uniforms
3848

3949
this._invSize = uniform( new Vector2() );
4050

41-
// render targets
42-
43-
this._sampleRenderTarget = null;
44-
this._historyRenderTarget = null;
51+
this._sampleTexture = texture( this._sampleRenderTarget.texture );
52+
this._depthTexture = texture( this._sampleRenderTarget.depthTexture );
53+
this._historyTexture = texture( this._historyRenderTarget.texture );
54+
this._velocityTexture = this.getTextureNode( 'velocity' );
4555

4656
// materials
4757

4858
this._resolveMaterial = new NodeMaterial();
4959
this._resolveMaterial.name = 'TRAA.Resolve';
5060

61+
this._prepassMaterial = new NodeMaterial();
62+
this._prepassMaterial.name = 'TRAA.Override';
63+
this._prepassMaterial.colorNode = vec4( 0, 0, 0, 1 );
64+
5165
}
5266

5367
setSize( width, height ) {
@@ -60,6 +74,7 @@ class TRAAPassNode extends PassNode {
6074

6175
this._sampleRenderTarget.setSize( this.renderTarget.width, this.renderTarget.height );
6276
this._historyRenderTarget.setSize( this.renderTarget.width, this.renderTarget.height );
77+
this._resolveRenderTarget.setSize( this.renderTarget.width, this.renderTarget.height );
6378

6479
this._invSize.value.set( 1 / this.renderTarget.width, 1 / this.renderTarget.height );
6580

@@ -85,11 +100,33 @@ class TRAAPassNode extends PassNode {
85100

86101
const needsRestart = this.setSize( size.width, size.height, renderer );
87102

88-
//
89-
90103
this._cameraNear.value = camera.near;
91104
this._cameraFar.value = camera.far;
92105

106+
// prepass
107+
108+
const mrt = this.getMRT();
109+
const velocityOutput = mrt.get( 'velocity' );
110+
111+
if ( velocityOutput === undefined ) {
112+
113+
throw new Error( 'THREE:TRAAPassNode: Missing velocity output in MRT configuration.' );
114+
115+
}
116+
117+
renderer.setMRT( mrt );
118+
scene.overrideMaterial = this._prepassMaterial;
119+
120+
renderer.setClearColor( this.clearColor, this.clearAlpha );
121+
renderer.setRenderTarget( this.renderTarget );
122+
renderer.clear();
123+
renderer.render( scene, camera );
124+
125+
scene.overrideMaterial = null;
126+
renderer.setMRT( null );
127+
128+
// configure jitter
129+
93130
const viewOffset = {
94131

95132
fullWidth: this.renderTarget.width,
@@ -107,9 +144,6 @@ class TRAAPassNode extends PassNode {
107144

108145
const jitterOffset = _JitterVectors[ this._jitterIndex ];
109146

110-
camera.updateProjectionMatrix();
111-
this._originalProjectionMatrix.copy( camera.projectionMatrix );
112-
113147
camera.setViewOffset(
114148

115149
viewOffset.fullWidth, viewOffset.fullHeight,
@@ -120,28 +154,13 @@ class TRAAPassNode extends PassNode {
120154

121155
);
122156

123-
const mrt = this.getMRT();
124-
const velocityOutput = mrt.get( 'velocity' );
125-
126-
if ( velocityOutput !== undefined ) {
127-
128-
velocityOutput.setProjectionMatrix( this._originalProjectionMatrix );
129-
130-
} else {
131-
132-
throw new Error( 'THREE:TRAAPassNode: Missing velocity output in MRT configuration.' );
133-
134-
}
135-
136-
renderer.setMRT( mrt );
157+
// render beauty with jitter
137158

138159
renderer.setClearColor( this.clearColor, this.clearAlpha );
139160
renderer.setRenderTarget( this._sampleRenderTarget );
140161
renderer.clear();
141162
renderer.render( scene, camera );
142163

143-
renderer.setMRT( null );
144-
145164
// every time when the dimensions change we need fresh history data. Copy the sample
146165
// into the history and final render target (no AA happens at that point).
147166

@@ -151,32 +170,29 @@ class TRAAPassNode extends PassNode {
151170
// there are currently warnings in the browser console indicating the texture dimensions do not match during the copy.
152171
// seems like some sort of timing issue
153172

154-
renderer.setRenderTarget( this._historyRenderTarget );
173+
renderer.setRenderTarget( this._historyRenderTarget ); // no resolve
155174
renderer.clear();
156175

176+
// update history and output
177+
157178
renderer.copyTextureToTexture( this._sampleRenderTarget.texture, this._historyRenderTarget.texture );
158179
renderer.copyTextureToTexture( this._sampleRenderTarget.texture, this.renderTarget.texture );
159180

160-
this._firstFrame = false;
161-
162181
} else {
163182

164183
// resolve
165184

166-
renderer.setRenderTarget( this.renderTarget );
185+
renderer.setRenderTarget( this._resolveRenderTarget );
167186
_quadMesh.material = this._resolveMaterial;
168187
_quadMesh.render( renderer );
169188

170-
// update history
189+
// update history and output
171190

172-
renderer.copyTextureToTexture( this.renderTarget.texture, this._historyRenderTarget.texture );
191+
renderer.copyTextureToTexture( this._resolveRenderTarget.texture, this._historyRenderTarget.texture );
192+
renderer.copyTextureToTexture( this._resolveRenderTarget.texture, this.renderTarget.texture );
173193

174194
}
175195

176-
// copy depth
177-
178-
renderer.copyTextureToTexture( this._sampleRenderTarget.depthTexture, this.renderTarget.depthTexture );
179-
180196
// update jitter index
181197

182198
this._jitterIndex ++;
@@ -202,37 +218,12 @@ class TRAAPassNode extends PassNode {
202218

203219
}
204220

205-
velocityOutput.setProjectionMatrix( null );
206-
207221
PostProcessingUtils.restoreRendererAndSceneState( renderer, scene, _rendererState );
208222

209223
}
210224

211225
setup( builder ) {
212226

213-
if ( this._sampleRenderTarget === null ) {
214-
215-
this._sampleRenderTarget = this.renderTarget.clone();
216-
this._historyRenderTarget = this.renderTarget.clone();
217-
218-
this._sampleRenderTarget.texture.minFiler = NearestFilter;
219-
this._sampleRenderTarget.texture.magFilter = NearestFilter;
220-
221-
const velocityTarget = this._sampleRenderTarget.texture.clone();
222-
velocityTarget.isRenderTargetTexture = true;
223-
velocityTarget.name = 'velocity';
224-
225-
this._sampleRenderTarget.textures.push( velocityTarget );
226-
227-
}
228-
229-
// textures
230-
231-
const historyTexture = texture( this._historyRenderTarget.texture );
232-
const sampleTexture = texture( this._sampleRenderTarget.textures[ 0 ] );
233-
const velocityTexture = texture( this._sampleRenderTarget.textures[ 1 ] );
234-
const depthTexture = texture( this._sampleRenderTarget.depthTexture );
235-
236227
const resolve = Fn( () => {
237228

238229
const uvNode = uv();
@@ -250,12 +241,12 @@ class TRAAPassNode extends PassNode {
250241
Loop( { start: int( - 1 ), end: int( 1 ), type: 'int', condition: '<=', name: 'y' }, ( { y } ) => {
251242

252243
const uvNeighbor = uvNode.add( vec2( float( x ), float( y ) ).mul( this._invSize ) ).toVar();
253-
const colorNeighbor = max( vec4( 0 ), sampleTexture.uv( uvNeighbor ) ).toVar(); // use max() to avoid propagate garbage values
244+
const colorNeighbor = max( vec4( 0 ), this._sampleTexture.uv( uvNeighbor ) ).toVar(); // use max() to avoid propagate garbage values
254245

255246
minColor.assign( min( minColor, colorNeighbor ) );
256247
maxColor.assign( max( maxColor, colorNeighbor ) );
257248

258-
const currentDepth = depthTexture.uv( uvNeighbor ).r.toVar();
249+
const currentDepth = this._depthTexture.uv( uvNeighbor ).r.toVar();
259250

260251
// find the sample position of the closest depth in the neighborhood (used for velocity)
261252

@@ -272,10 +263,10 @@ class TRAAPassNode extends PassNode {
272263

273264
// sampling/reprojection
274265

275-
const offset = velocityTexture.uv( closestDepthPixelPosition ).xy.mul( vec2( 0.5, - 0.5 ) ); // NDC to uv offset
266+
const offset = this._velocityTexture.uv( closestDepthPixelPosition ).xy.mul( vec2( 0.5, - 0.5 ) ); // NDC to uv offset
276267

277-
const currentColor = sampleTexture.uv( uvNode );
278-
const historyColor = historyTexture.uv( uvNode.sub( offset ) );
268+
const currentColor = this._sampleTexture.uv( uvNode );
269+
const historyColor = this._historyTexture.uv( uvNode.sub( offset ) );
279270

280271
// clamping
281272

@@ -311,14 +302,12 @@ class TRAAPassNode extends PassNode {
311302

312303
super.dispose();
313304

314-
if ( this._sampleRenderTarget !== null ) {
315-
316-
this._sampleRenderTarget.dispose();
317-
this._historyRenderTarget.dispose();
318-
319-
}
305+
this._sampleRenderTarget.dispose();
306+
this._historyRenderTarget.dispose();
307+
this._resolveRenderTarget.dispose();
320308

321309
this._resolveMaterial.dispose();
310+
this._prepassMaterial.dispose();
322311

323312
}
324313

0 commit comments

Comments
 (0)