Skip to content

Commit 1402d24

Browse files
mvaligurskyMartin Valigurskywilleastcott
authored andcommitted
Update to render passes - generate scene half sized texture (#7175)
* Update to render passes - generate scene half sized texture * Update src/platform/graphics/render-target.js Co-authored-by: Will Eastcott <[email protected]> --------- Co-authored-by: Martin Valigursky <[email protected]> Co-authored-by: Will Eastcott <[email protected]>
1 parent cd8b89b commit 1402d24

File tree

5 files changed

+95
-52
lines changed

5 files changed

+95
-52
lines changed

examples/src/examples/graphics/clustered-lighting.example.mjs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,6 @@ assetListLoader.load(() => {
100100
const cylinderMesh = pc.Mesh.fromGeometry(app.graphicsDevice, new pc.CylinderGeometry({ capSegments: 200 }));
101101
const cylinder = new pc.Entity();
102102
cylinder.addComponent('render', {
103-
material: material,
104103
meshInstances: [new pc.MeshInstance(cylinderMesh, material)],
105104
castShadows: true
106105
});

src/extras/render-passes/render-pass-bloom.js

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ import { RenderPassDownsample } from './render-pass-downsample.js';
99
import { RenderPassUpsample } from './render-pass-upsample.js';
1010
import { math } from '../../core/math/math.js';
1111

12+
/**
13+
* @import { GraphicsDevice } from '../../platform/graphics/graphics-device.js'
14+
*/
15+
1216
// based on https://learnopengl.com/Guest-Articles/2022/Phys.-Based-Bloom
1317
/**
1418
* Render pass implementation of HDR bloom effect.
@@ -27,6 +31,12 @@ class RenderPassBloom extends RenderPass {
2731

2832
renderTargets = [];
2933

34+
/**
35+
* @param {GraphicsDevice} device - The graphics device.
36+
* @param {Texture} sourceTexture - The source texture, usually at half the resolution of the
37+
* render target getting blurred.
38+
* @param {number} format - The texture format.
39+
*/
3040
constructor(device, sourceTexture, format) {
3141
super(device);
3242
this._sourceTexture = sourceTexture;
@@ -95,8 +105,7 @@ class RenderPassBloom extends RenderPass {
95105
let passSourceTexture = this._sourceTexture;
96106
for (let i = 0; i < numPasses; i++) {
97107

98-
const fast = i === 0; // fast box downscale for the first pass
99-
const pass = new RenderPassDownsample(device, passSourceTexture, fast);
108+
const pass = new RenderPassDownsample(device, passSourceTexture);
100109
const rt = this.renderTargets[i];
101110
pass.init(rt, {
102111
resizeSource: passSourceTexture,
@@ -130,24 +139,6 @@ class RenderPassBloom extends RenderPass {
130139
this.destroyRenderTargets(1);
131140
}
132141

133-
set sourceTexture(value) {
134-
this._sourceTexture = value;
135-
136-
if (this.beforePasses.length > 0) {
137-
const firstPass = this.beforePasses[0];
138-
139-
// change resize source
140-
firstPass.options.resizeSource = value;
141-
142-
// change downsample source
143-
firstPass.sourceTexture = value;
144-
}
145-
}
146-
147-
get sourceTexture() {
148-
return this._sourceTexture;
149-
}
150-
151142
frameUpdate() {
152143
super.frameUpdate();
153144

src/extras/render-passes/render-pass-camera-frame.js

Lines changed: 72 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import { RenderPassPrepass } from './render-pass-prepass.js';
1313
import { RenderPassSsao } from './render-pass-ssao.js';
1414
import { SSAOTYPE_COMBINE, SSAOTYPE_LIGHTING, SSAOTYPE_NONE } from './constants.js';
1515
import { Debug } from '../../core/debug.js';
16+
import { RenderPassDownsample } from './render-pass-downsample.js';
17+
import { Color } from '../../core/math/color.js';
1618

1719
class CameraFrameOptions {
1820
formats;
@@ -71,6 +73,8 @@ class RenderPassCameraFrame extends RenderPass {
7173

7274
taaPass;
7375

76+
scenePassHalf;
77+
7478
_renderTargetScale = 1;
7579

7680
/**
@@ -96,13 +100,20 @@ class RenderPassCameraFrame extends RenderPass {
96100
reset() {
97101

98102
this.sceneTexture = null;
103+
this.sceneTextureHalf = null;
99104

100105
if (this.rt) {
101106
this.rt.destroyTextureBuffers();
102107
this.rt.destroy();
103108
this.rt = null;
104109
}
105110

111+
if (this.rtHalf) {
112+
this.rtHalf.destroyTextureBuffers();
113+
this.rtHalf.destroy();
114+
this.rtHalf = null;
115+
}
116+
106117
// destroy all passes we created
107118
this.beforePasses.forEach(pass => pass.destroy());
108119
this.beforePasses.length = 0;
@@ -116,6 +127,7 @@ class RenderPassCameraFrame extends RenderPass {
116127
this.ssaoPass = null;
117128
this.taaPass = null;
118129
this.afterPass = null;
130+
this.scenePassHalf = null;
119131
}
120132

121133
sanitizeOptions(options) {
@@ -180,6 +192,29 @@ class RenderPassCameraFrame extends RenderPass {
180192
}
181193
}
182194

195+
createRenderTarget(name, depth, stencil, samples, flipY) {
196+
197+
const texture = new Texture(this.device, {
198+
name: name,
199+
width: 4,
200+
height: 4,
201+
format: this.hdrFormat,
202+
mipmaps: false,
203+
minFilter: FILTER_LINEAR,
204+
magFilter: FILTER_LINEAR,
205+
addressU: ADDRESS_CLAMP_TO_EDGE,
206+
addressV: ADDRESS_CLAMP_TO_EDGE
207+
});
208+
209+
return new RenderTarget({
210+
colorBuffer: texture,
211+
depth: depth,
212+
stencil: stencil,
213+
samples: samples,
214+
flipY: flipY
215+
});
216+
}
217+
183218
setupRenderPasses(options) {
184219

185220
const { device } = this;
@@ -188,6 +223,12 @@ class RenderPassCameraFrame extends RenderPass {
188223

189224
this.hdrFormat = device.getRenderableHdrFormat(options.formats, true, options.samples) || PIXELFORMAT_RGBA8;
190225

226+
// HDR bloom is not supported on RGBA8 format
227+
this._bloomEnabled = options.bloomEnabled && this.hdrFormat !== PIXELFORMAT_RGBA8;
228+
229+
// bloom needs half resolution scene texture
230+
this._sceneHalfEnabled = this._bloomEnabled;
231+
191232
// camera renders in HDR mode (linear output, no tonemapping)
192233
cameraComponent.gammaCorrection = GAMMA_NONE;
193234
cameraComponent.toneMapping = TONEMAP_NONE;
@@ -196,25 +237,15 @@ class RenderPassCameraFrame extends RenderPass {
196237
cameraComponent.shaderParams.ssaoEnabled = options.ssaoType === SSAOTYPE_LIGHTING;
197238

198239
// create a render target to render the scene into
199-
this.sceneTexture = new Texture(device, {
200-
name: 'SceneColor',
201-
width: 4,
202-
height: 4,
203-
format: this.hdrFormat,
204-
mipmaps: false,
205-
minFilter: FILTER_LINEAR,
206-
magFilter: FILTER_LINEAR,
207-
addressU: ADDRESS_CLAMP_TO_EDGE,
208-
addressV: ADDRESS_CLAMP_TO_EDGE
209-
});
210-
211-
this.rt = new RenderTarget({
212-
colorBuffer: this.sceneTexture,
213-
depth: true,
214-
stencil: options.stencil,
215-
samples: options.samples,
216-
flipY: !!targetRenderTarget?.flipY // flipY is inherited from the target renderTarget
217-
});
240+
const flipY = !!targetRenderTarget?.flipY; // flipY is inherited from the target renderTarget
241+
this.rt = this.createRenderTarget('SceneColor', true, options.stencil, options.samples, flipY);
242+
this.sceneTexture = this.rt.colorBuffer;
243+
244+
// when half size scene color buffer is used
245+
if (this._sceneHalfEnabled) {
246+
this.rtHalf = this.createRenderTarget('SceneColorHalf', false, false, 1, flipY);
247+
this.sceneTextureHalf = this.rtHalf.colorBuffer;
248+
}
218249

219250
this.sceneOptions = {
220251
resizeSource: targetRenderTarget,
@@ -231,7 +262,7 @@ class RenderPassCameraFrame extends RenderPass {
231262
collectPasses() {
232263

233264
// use these prepared render passes in the order they should be executed
234-
return [this.prePass, this.ssaoPass, this.scenePass, this.colorGrabPass, this.scenePassTransparent, this.taaPass, this.bloomPass, this.composePass, this.afterPass];
265+
return [this.prePass, this.ssaoPass, this.scenePass, this.colorGrabPass, this.scenePassTransparent, this.taaPass, this.scenePassHalf, this.bloomPass, this.composePass, this.afterPass];
235266
}
236267

237268
createPasses(options) {
@@ -248,8 +279,11 @@ class RenderPassCameraFrame extends RenderPass {
248279
// TAA
249280
const sceneTextureWithTaa = this.setupTaaPass(options);
250281

282+
// downscale to half resolution
283+
this.setupSceneHalfPass(options, sceneTextureWithTaa);
284+
251285
// bloom
252-
this.setupBloomPass(options, sceneTextureWithTaa);
286+
this.setupBloomPass(options, this.sceneTextureHalf);
253287

254288
// compose
255289
this.setupComposePass(options);
@@ -328,9 +362,23 @@ class RenderPassCameraFrame extends RenderPass {
328362
}
329363
}
330364

365+
setupSceneHalfPass(options, sourceTexture) {
366+
367+
if (this._sceneHalfEnabled) {
368+
this.scenePassHalf = new RenderPassDownsample(this.device, this.sceneTexture, true);
369+
this.scenePassHalf.name = 'RenderPassSceneHalf';
370+
this.scenePassHalf.init(this.rtHalf, {
371+
resizeSource: sourceTexture,
372+
scaleX: 0.5,
373+
scaleY: 0.5
374+
});
375+
this.scenePassHalf.setClearColor(Color.BLACK);
376+
}
377+
}
378+
331379
setupBloomPass(options, inputTexture) {
332-
// HDR bloom is not supported on RGBA8 format
333-
if (options.bloomEnabled && this.hdrFormat !== PIXELFORMAT_RGBA8) {
380+
381+
if (this._bloomEnabled) {
334382
// create a bloom pass, which generates bloom texture based on the provided texture
335383
this.bloomPass = new RenderPassBloom(this.device, inputTexture, this.hdrFormat);
336384
}
@@ -387,9 +435,7 @@ class RenderPassCameraFrame extends RenderPass {
387435

388436
// TAA history buffer is double buffered, assign the current one to the follow up passes.
389437
this.composePass.sceneTexture = sceneTexture;
390-
if (this.options.bloomEnabled && this.bloomPass) {
391-
this.bloomPass.sourceTexture = sceneTexture;
392-
}
438+
this.scenePassHalf?.setSourceTexture(sceneTexture);
393439
}
394440
}
395441

src/extras/render-passes/render-pass-downsample.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,13 @@ class RenderPassDownsample extends RenderPassShaderQuad {
6161
this.sourceInvResolutionValue = new Float32Array(2);
6262
}
6363

64+
setSourceTexture(value) {
65+
this._sourceTexture = value;
66+
67+
// change resize source
68+
this.options.resizeSource = value;
69+
}
70+
6471
execute() {
6572
this.sourceTextureId.setValue(this.sourceTexture);
6673

src/platform/graphics/render-target.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -312,13 +312,13 @@ class RenderTarget {
312312
*/
313313
resize(width, height) {
314314

315-
if (this.mipLevel > 0) {
316-
Debug.warn('Only render target rendering to mipLevel 0 can be resized, ignoring.', this);
317-
return;
318-
}
319-
320315
if (this.width !== width || this.height !== height) {
321316

317+
if (this.mipLevel > 0) {
318+
Debug.warn('Only a render target rendering to mipLevel 0 can be resized, ignoring.', this);
319+
return;
320+
}
321+
322322
// release existing
323323
const device = this._device;
324324
this.destroyFrameBuffers();

0 commit comments

Comments
 (0)