diff --git a/src/app/Renderer.ts b/src/app/Renderer.ts index 46246f4..a44309f 100644 --- a/src/app/Renderer.ts +++ b/src/app/Renderer.ts @@ -20,7 +20,6 @@ import { RenderPassType, placeholderFunc, } from '../renderer/types' -import { TextureDebugMeshType } from '../types' import { BLIT_PASS_REVEAL_ANIM_DURATION_MS, ENVIRONMENT_CUBE_TEXTURE_FACE_URLS, @@ -56,6 +55,7 @@ import { } from './constants' import { lerp } from '../renderer/math/math' +import { TextureDebugMeshType } from '../types' import LineDebugDrawable from './debug/LineDebugDrawable' import TexturesDebugContainer from './debug/textures-debug/TexturesDebugContainer' import DebugStatsContainer from './debug/timings-debug/DebugStatsContainer' @@ -144,6 +144,9 @@ export default class Renderer extends RenderingContext { private resizeCounter = 0 + private viewportWidth = 0 + private viewportHeight = 0 + public set sunPositionX(v: number) { this.lightingManager.sunPositionX = v } @@ -160,12 +163,10 @@ export default class Renderer extends RenderingContext { this.lightingManager.sunIntensity = v } + private _ssaoEnabled = true public set ssaoEnabled(v: boolean) { - ;( - this.renderPassComposer.getPass( - RenderPassType.DirectionalAmbientLighting - ) as DirectionalAmbientLightRenderPass - ).ssaoMixFactor = v ? 1 : 0 + this._ssaoEnabled = v + this.recreateRenderComposer() } public set ssaoKernelSize(v: number) { @@ -302,25 +303,18 @@ export default class Renderer extends RenderingContext { ).debugMissedIntersections = v } + private _ssrEnabled = true + public set ssrEnabled(v: boolean) { - this.renderPassComposer.getPass(RenderPassType.Reflection).enabled = v - this.renderPassComposer - .getPass(RenderPassType.TAAResolve) - .clearInputTextures() - .addInputTextures([ - v - ? RENDER_PASS_COMPUTED_REFLECTIONS_TEXTURE - : RENDER_PASS_LIGHTING_RESULT_TEXTURE, - RENDER_PASS_VELOCITY_TEXTURE, - ]) + this._ssrEnabled = v + this.recreateRenderComposer() } + private _bloomEnabled = true public set bloomEnabled(v: boolean) { - this.renderPassComposer.getPass(RenderPassType.BloomDownsample).enabled = v - this.renderPassComposer.getPass(RenderPassType.BloomUpsample).enabled = v - ;( - this.renderPassComposer.getPass(RenderPassType.Blit) as BlitRenderPass - ).bloomEnabled = v + this._bloomEnabled = v + + this.recreateRenderComposer() } public set bloomFilterRadius(v: number) { @@ -513,7 +507,10 @@ export default class Renderer extends RenderingContext { }) } - private recreateRenderComposer(width: number, height: number) { + private recreateRenderComposer( + width = this.viewportWidth, + height = this.viewportHeight + ) { this.renderPassComposer?.destroy() this.renderPassComposer = new RenderPassComposer() @@ -536,17 +533,33 @@ export default class Renderer extends RenderingContext { RENDER_PASS_DEPTH_STENCIL_TEXTURE, ]) - const ssaoRenderPass = new SSAORenderPass(width, height) - .setCamera(this.mainCamera) - .addInputTextures([ - RENDER_PASS_NORMAL_METALLIC_ROUGHNESS_TEXTURE, - RENDER_PASS_DEPTH_STENCIL_TEXTURE, - ]) - .addOutputTexture(RENDER_PASS_SSAO_TEXTURE) + let ssaoRenderPass: SSAORenderPass + let ssaoBlurRenderPass: SSAOBlurRenderPass + + if (this._ssaoEnabled) { + ssaoRenderPass = new SSAORenderPass(width, height) + .addInputTextures([ + RENDER_PASS_NORMAL_METALLIC_ROUGHNESS_TEXTURE, + RENDER_PASS_DEPTH_STENCIL_TEXTURE, + ]) + .addOutputTexture(RENDER_PASS_SSAO_TEXTURE) + .setCamera(this.mainCamera) + + ssaoBlurRenderPass = new SSAOBlurRenderPass(width, height) + .addInputTexture(RENDER_PASS_SSAO_TEXTURE) + .addOutputTexture(RENDER_PASS_SSAO_BLUR_TEXTURE) + } + + const dirAmbientLightRenderPassInputTexNames = [ + RENDER_PASS_NORMAL_METALLIC_ROUGHNESS_TEXTURE, + RENDER_PASS_ALBEDO_REFLECTANCE_TEXTURE, + RENDER_PASS_DEPTH_STENCIL_TEXTURE, + RENDER_PASS_DIRECTIONAL_LIGHT_DEPTH_TEXTURE, + ] - const ssaoBlurRenderPass = new SSAOBlurRenderPass(width, height) - .addInputTexture(RENDER_PASS_SSAO_TEXTURE) - .addOutputTexture(RENDER_PASS_SSAO_BLUR_TEXTURE) + if (this._ssaoEnabled) { + dirAmbientLightRenderPassInputTexNames.push(RENDER_PASS_SSAO_TEXTURE) + } const directionalAmbientLightRenderPass = new DirectionalAmbientLightRenderPass( @@ -555,15 +568,11 @@ export default class Renderer extends RenderingContext { height ) .setCamera(this.mainCamera) - .addInputTextures([ - RENDER_PASS_NORMAL_METALLIC_ROUGHNESS_TEXTURE, - RENDER_PASS_ALBEDO_REFLECTANCE_TEXTURE, - RENDER_PASS_DEPTH_STENCIL_TEXTURE, - RENDER_PASS_SSAO_BLUR_TEXTURE, - RENDER_PASS_DIRECTIONAL_LIGHT_DEPTH_TEXTURE, - ]) + .addInputTextures(dirAmbientLightRenderPassInputTexNames) .addOutputTexture(RENDER_PASS_LIGHTING_RESULT_TEXTURE) + directionalAmbientLightRenderPass.ssaoMixFactor = this._ssaoEnabled ? 1 : 0 + if (this.envDiffuseTexture) { directionalAmbientLightRenderPass.setDiffuseIBLTexture( this.envDiffuseTexture @@ -581,16 +590,21 @@ export default class Renderer extends RenderingContext { ) } + const pointLightNonInstancedTexInputNames = [ + RENDER_PASS_NORMAL_METALLIC_ROUGHNESS_TEXTURE, + RENDER_PASS_ALBEDO_REFLECTANCE_TEXTURE, + RENDER_PASS_DEPTH_STENCIL_TEXTURE, + RENDER_PASS_LIGHTING_RESULT_TEXTURE, + ] + + if (this._ssaoEnabled) { + pointLightNonInstancedTexInputNames.push(RENDER_PASS_SSAO_TEXTURE) + } + const pointLightsNonInstancedNonCulledRenderPass = new PointLightsNonCulledRenderPass(width, height) .setCamera(this.mainCamera) - .addInputTextures([ - RENDER_PASS_NORMAL_METALLIC_ROUGHNESS_TEXTURE, - RENDER_PASS_ALBEDO_REFLECTANCE_TEXTURE, - RENDER_PASS_DEPTH_STENCIL_TEXTURE, - RENDER_PASS_SSAO_BLUR_TEXTURE, - RENDER_PASS_LIGHTING_RESULT_TEXTURE, - ]) + .addInputTextures(pointLightNonInstancedTexInputNames) .addOutputTexture(RENDER_PASS_LIGHTING_RESULT_TEXTURE) const pointLightsStencilMaskPass = new PointLightsMaskPass(width, height) @@ -600,15 +614,20 @@ export default class Renderer extends RenderingContext { .setLightsBuffer(this.lightingManager.gpuBuffer) .updateLightsMaskBindGroup() + const pointLightsRenderPassInputTexNames = [ + RENDER_PASS_NORMAL_METALLIC_ROUGHNESS_TEXTURE, + RENDER_PASS_ALBEDO_REFLECTANCE_TEXTURE, + RENDER_PASS_DEPTH_STENCIL_TEXTURE, + RENDER_PASS_LIGHTING_RESULT_TEXTURE, + ] + + if (this._ssaoEnabled) { + pointLightsRenderPassInputTexNames.push(RENDER_PASS_SSAO_TEXTURE) + } + const pointLightsRenderPass = new PointLightsRenderPass(width, height) .setCamera(this.mainCamera) - .addInputTextures([ - RENDER_PASS_NORMAL_METALLIC_ROUGHNESS_TEXTURE, - RENDER_PASS_ALBEDO_REFLECTANCE_TEXTURE, - RENDER_PASS_DEPTH_STENCIL_TEXTURE, - RENDER_PASS_SSAO_BLUR_TEXTURE, - RENDER_PASS_LIGHTING_RESULT_TEXTURE, - ]) + .addInputTextures(pointLightsRenderPassInputTexNames) .addOutputTexture(RENDER_PASS_LIGHTING_RESULT_TEXTURE) const transparentRenderPass = new TransparentRenderPass(width, height) @@ -633,70 +652,104 @@ export default class Renderer extends RenderingContext { RENDER_PASS_DEPTH_STENCIL_TEXTURE, ]) - const hiZCopyDepthComputePass = new HiZCopyDepthComputePass(width, height) - .addInputTexture(RENDER_PASS_DEPTH_STENCIL_TEXTURE) - .addOutputTexture(RENDER_PASS_HI_Z_DEPTH_TEXTURE) + let hiZCopyDepthComputePass: HiZCopyDepthComputePass + let hiZDepthComputePass: HiZDepthComputePass + let reflectionsComputePass: ReflectionComputePass - const hiZDepthComputePass = new HiZDepthComputePass(width, height) - .addInputTexture(RENDER_PASS_HI_Z_DEPTH_TEXTURE) - .addOutputTexture(RENDER_PASS_HI_Z_DEPTH_TEXTURE) + if (this._ssrEnabled) { + hiZCopyDepthComputePass = new HiZCopyDepthComputePass(width, height) + .addInputTexture(RENDER_PASS_DEPTH_STENCIL_TEXTURE) + .addOutputTexture(RENDER_PASS_HI_Z_DEPTH_TEXTURE) - const reflectionsComputePass = new ReflectionComputePass(width, height) - .setCamera(this.mainCamera) - .addInputTextures([ - RENDER_PASS_LIGHTING_RESULT_TEXTURE, - RENDER_PASS_NORMAL_METALLIC_ROUGHNESS_TEXTURE, - RENDER_PASS_ALBEDO_REFLECTANCE_TEXTURE, - RENDER_PASS_HI_Z_DEPTH_TEXTURE, - ]) - .addOutputTexture(RENDER_PASS_COMPUTED_REFLECTIONS_TEXTURE) + hiZDepthComputePass = new HiZDepthComputePass(width, height) + .addInputTexture(RENDER_PASS_HI_Z_DEPTH_TEXTURE) + .addOutputTexture(RENDER_PASS_HI_Z_DEPTH_TEXTURE) + reflectionsComputePass = new ReflectionComputePass(width, height) + .setCamera(this.mainCamera) + .addInputTextures([ + RENDER_PASS_LIGHTING_RESULT_TEXTURE, + RENDER_PASS_NORMAL_METALLIC_ROUGHNESS_TEXTURE, + RENDER_PASS_ALBEDO_REFLECTANCE_TEXTURE, + RENDER_PASS_HI_Z_DEPTH_TEXTURE, + ]) + .addOutputTexture(RENDER_PASS_COMPUTED_REFLECTIONS_TEXTURE) + } const taaResolveRenderPass = new TAAResolveRenderPass(width, height) .addInputTextures([ - RENDER_PASS_COMPUTED_REFLECTIONS_TEXTURE, + this._ssrEnabled + ? RENDER_PASS_COMPUTED_REFLECTIONS_TEXTURE + : RENDER_PASS_LIGHTING_RESULT_TEXTURE, RENDER_PASS_VELOCITY_TEXTURE, ]) .addOutputTexture(RENDER_PASS_TAA_RESOLVE_TEXTURE) - const bloomDownscaleRenderPass = new BloomDownscaleRenderPass(width, height) - .addInputTexture(RENDER_PASS_TAA_RESOLVE_TEXTURE) - .addOutputTexture(RENDER_PASS_BLOOM_TEXTURE) + let bloomDownscaleRenderPass: BloomDownscaleRenderPass + let bloomUpscaleRenderPass: BloomUpscaleRenderPass + + if (this._bloomEnabled) { + bloomDownscaleRenderPass = new BloomDownscaleRenderPass(width, height) + .addInputTexture(RENDER_PASS_TAA_RESOLVE_TEXTURE) + .addOutputTexture(RENDER_PASS_BLOOM_TEXTURE) + + bloomUpscaleRenderPass = new BloomUpscaleRenderPass(width, height) + .addInputTexture(RENDER_PASS_BLOOM_TEXTURE) + .addOutputTexture(RENDER_PASS_BLOOM_TEXTURE) + } - const bloomUpscaleRenderPass = new BloomUpscaleRenderPass(width, height) - .addInputTexture(RENDER_PASS_BLOOM_TEXTURE) - .addOutputTexture(RENDER_PASS_BLOOM_TEXTURE) + const blitRenderPassInputs: string[] = [] + + if (this._bloomEnabled) { + blitRenderPassInputs.push(RENDER_PASS_BLOOM_TEXTURE) + } + blitRenderPassInputs.push(RENDER_PASS_TAA_RESOLVE_TEXTURE) const blitRenderPass = new BlitRenderPass( width, height, this.resizeCounter > 0 - ).addInputTextures([ - RENDER_PASS_BLOOM_TEXTURE, - RENDER_PASS_TAA_RESOLVE_TEXTURE, - ]) + ).addInputTextures(blitRenderPassInputs) + + blitRenderPass.bloomEnabled = this._bloomEnabled + + this.renderPassComposer.addPass(shadowRenderPass).addPass(gbufferRenderPass) + + if (this._ssaoEnabled) { + this.renderPassComposer + .addPass(ssaoRenderPass) + .addPass(ssaoBlurRenderPass) + } this.renderPassComposer - .addPass(shadowRenderPass) - .addPass(gbufferRenderPass) - .addPass(ssaoRenderPass) - .addPass(ssaoBlurRenderPass) .addPass(directionalAmbientLightRenderPass) .addPass(pointLightsNonInstancedNonCulledRenderPass) .addPass(pointLightsStencilMaskPass) .addPass(pointLightsRenderPass) .addPass(transparentRenderPass) .addPass(skyboxRenderPass) - .addPass(hiZCopyDepthComputePass) - .addPass(hiZDepthComputePass) - .addPass(reflectionsComputePass) - .addPass(taaResolveRenderPass) - .addPass(bloomDownscaleRenderPass) - .addPass(bloomUpscaleRenderPass) - // .addPass(debugBBoxesPass) - .addPass(blitRenderPass) + + if (this._ssrEnabled) { + this.renderPassComposer + .addPass(hiZCopyDepthComputePass) + .addPass(hiZDepthComputePass) + .addPass(reflectionsComputePass) + } + + this.renderPassComposer.addPass(taaResolveRenderPass) + + if (this._bloomEnabled) { + this.renderPassComposer + .addPass(bloomDownscaleRenderPass) + .addPass(bloomUpscaleRenderPass) + } + + this.renderPassComposer.addPass(blitRenderPass) } public resize(w: number, h: number) { + this.viewportWidth = w + this.viewportHeight = h + this.debugCamera.onResize(w, h) this.mainCamera.onResize(w, h) @@ -749,10 +802,11 @@ export default class Renderer extends RenderingContext { RENDER_PASS_NORMAL_METALLIC_ROUGHNESS_TEXTURE ) ) - .setTextureGBufferSection( - TextureDebugMeshType.AO, - this.renderPassComposer.getTexture(RENDER_PASS_SSAO_BLUR_TEXTURE) - ) + // .setTextureGBufferSection( + // TextureDebugMeshType.AO, + // this.renderPassComposer.getTexture(RENDER_PASS_SSAO_BLUR_TEXTURE) || + // TextureLoader.dummyR16FTexture + // ) .setTextureGBufferSection( TextureDebugMeshType.Reflectance, this.renderPassComposer.getTexture( @@ -814,9 +868,7 @@ export default class Renderer extends RenderingContext { const fpsAverageStat = this.fpsDisplayAverage.get() const gpuAverageStat = this.gpuAverage.get() - if (fpsAverageStat > 70) { - this.mainCameraCtrl.speed = 20 - } + this.mainCameraCtrl.speed = fpsAverageStat > 70 ? 20 : 40 if (RenderingContext.supportsGPUTimestampQuery) { this.timingDebugContainer.setDisplayValue( diff --git a/src/app/constants.ts b/src/app/constants.ts index 6f48164..02f532c 100644 --- a/src/app/constants.ts +++ b/src/app/constants.ts @@ -109,3 +109,5 @@ export const MAIN_CAMERA_LOAD_ANIM_EASE: EaseType = 'quad_Out' export const FIREWORK_PARTICLES_LOAD_ANIM_DELAY_MS = 1000 export const FIREWORK_PARTICLES_LOAD_ANIM_DURATION_MS = 500 export const FIREWORK_PARTICLES_LOAD_ANIM_EASE: EaseType = 'quad_Out' + +export const PROFILE_MAX_FRAMES_COUNT = 70 diff --git a/src/app/lighting/LightingSystem.ts b/src/app/lighting/LightingSystem.ts index b309e18..f9c83f0 100644 --- a/src/app/lighting/LightingSystem.ts +++ b/src/app/lighting/LightingSystem.ts @@ -334,8 +334,6 @@ export default class LightingSystem extends LightingManager { ) } - console.log(this.lightsCount) - // this.particlesLength = this.particles.length; this.updateGPUBuffer() diff --git a/src/app/render-passes/BlitRenderPass.ts b/src/app/render-passes/BlitRenderPass.ts index a6195ae..4581229 100644 --- a/src/app/render-passes/BlitRenderPass.ts +++ b/src/app/render-passes/BlitRenderPass.ts @@ -7,6 +7,7 @@ import Scene from '../../renderer/scene/Scene' import FullScreenVertexShaderUtils, { FullScreenVertexShaderEntryFn, } from '../../renderer/shader/FullScreenVertexShaderUtils' +import TextureLoader from '../../renderer/texture/TextureLoader' import { EaseType, RenderPassType } from '../../renderer/types' import { BLIT_FRAGMENT_SHADER_ENTRY_NAME, @@ -194,8 +195,15 @@ export default class BlitRenderPass extends RenderPass { inputs: GPUTexture[] ): GPUTexture[] { if (!this.inputTextureViews.length) { - this.inputTextureViews.push(inputs[0].createView()) - this.inputTextureViews.push(inputs[1].createView()) + if (inputs.length === 1) { + this.inputTextureViews.push( + TextureLoader.dummyRGBA16FTexture.createView() + ) + this.inputTextureViews.push(inputs[0].createView()) + } else { + this.inputTextureViews.push(inputs[0].createView()) + this.inputTextureViews.push(inputs[1].createView()) + } const texturesBindGroupEntries: GPUBindGroupEntry[] = [ { diff --git a/src/app/render-passes/DirectionalAmbientLightRenderPass.ts b/src/app/render-passes/DirectionalAmbientLightRenderPass.ts index 6b017f1..e78d10b 100644 --- a/src/app/render-passes/DirectionalAmbientLightRenderPass.ts +++ b/src/app/render-passes/DirectionalAmbientLightRenderPass.ts @@ -308,16 +308,23 @@ export default class DirectionalAmbientLightRenderPass extends LightRenderPass { aspect: 'all', }) ) - this.inputTextureViews.push(inputs[3].createView()) this.inputTextureViews.push( - inputs[4].createView({ + inputs[3].createView({ dimension: '2d-array', }) ) + + let ssaoTexture = inputs[4] + if (!ssaoTexture) { + ssaoTexture = TextureLoader.dummyR16FTexture + } + + this.inputTextureViews.push(ssaoTexture.createView()) + this.updateGbufferBindGroupEntryAt(0, this.inputTextureViews[0]) .updateGbufferBindGroupEntryAt(1, this.inputTextureViews[1]) .updateGbufferBindGroupEntryAt(2, this.inputTextureViews[2]) - .updateGbufferBindGroupEntryAt(3, this.inputTextureViews[4]) + .updateGbufferBindGroupEntryAt(3, this.inputTextureViews[5]) .updateGbufferBindGroupEntryAt(4, { buffer: this.camera.gpuBuffer, }) @@ -327,7 +334,7 @@ export default class DirectionalAmbientLightRenderPass extends LightRenderPass { .recreateGBufferTexturesBindGroup() this.dirLightShadowBindGroupEntries[2].resource = - this.inputTextureViews[5] + this.inputTextureViews[4] this.recreateDirLightShadowBindGroup() } diff --git a/src/app/render-passes/PointLightsNonCulledRenderPass.ts b/src/app/render-passes/PointLightsNonCulledRenderPass.ts index 2b22c3f..15713ee 100644 --- a/src/app/render-passes/PointLightsNonCulledRenderPass.ts +++ b/src/app/render-passes/PointLightsNonCulledRenderPass.ts @@ -5,6 +5,7 @@ import VertexDescriptor from '../../renderer/core/VertexDescriptor' import CameraFaceCulledPointLight from '../../renderer/lighting/CameraFaceCulledPointLight' import Drawable from '../../renderer/scene/Drawable' import Scene from '../../renderer/scene/Scene' +import TextureLoader from '../../renderer/texture/TextureLoader' import { RenderPassType } from '../../renderer/types' import GetGBufferIntegrateShader, { GBufferIntegrateShaderEntryFn, @@ -77,7 +78,7 @@ export default class PointLightsNonCulledRenderPass extends LightRenderPass { } const renderPassColorAttachments: GPURenderPassColorAttachment[] = [ { - view: this.inputTextureViews[5], + view: this.inputTextureViews[4], loadOp: 'load', storeOp: 'store', }, @@ -114,12 +115,18 @@ export default class PointLightsNonCulledRenderPass extends LightRenderPass { }) ) this.inputTextureViews.push(inputs[3].createView()) - this.inputTextureViews.push(inputs[4].createView()) + + let ssaoTexture = inputs[4] + if (!ssaoTexture) { + ssaoTexture = TextureLoader.dummyR16FTexture + } + + this.inputTextureViews.push(ssaoTexture.createView()) this.updateGbufferBindGroupEntryAt(0, this.inputTextureViews[0]) .updateGbufferBindGroupEntryAt(1, this.inputTextureViews[1]) .updateGbufferBindGroupEntryAt(2, this.inputTextureViews[3]) - .updateGbufferBindGroupEntryAt(3, this.inputTextureViews[4]) + .updateGbufferBindGroupEntryAt(3, this.inputTextureViews[5]) .updateGbufferBindGroupEntryAt(4, { buffer: this.camera.gpuBuffer, }) @@ -164,6 +171,7 @@ export default class PointLightsNonCulledRenderPass extends LightRenderPass { this.postRender(commandEncoder) - return [inputs[4]] + const out = inputs[3] + return [out] } } diff --git a/src/app/render-passes/PointLightsRenderPass.ts b/src/app/render-passes/PointLightsRenderPass.ts index d2ae12e..7165e51 100644 --- a/src/app/render-passes/PointLightsRenderPass.ts +++ b/src/app/render-passes/PointLightsRenderPass.ts @@ -3,6 +3,7 @@ import RenderingContext from '../../renderer/core/RenderingContext' import VertexDescriptor from '../../renderer/core/VertexDescriptor' import Drawable from '../../renderer/scene/Drawable' import Scene from '../../renderer/scene/Scene' +import TextureLoader from '../../renderer/texture/TextureLoader' import { RenderPassType } from '../../renderer/types' import GetGBufferIntegrateShader, { GBufferIntegrateShaderEntryFn, @@ -78,7 +79,7 @@ export default class PointLightsRenderPass extends LightRenderPass { } const renderPassColorAttachments: GPURenderPassColorAttachment[] = [ { - view: this.inputTextureViews[5], + view: this.inputTextureViews[4], loadOp: 'load', storeOp: 'store', }, @@ -119,12 +120,17 @@ export default class PointLightsRenderPass extends LightRenderPass { }) ) this.inputTextureViews.push(inputs[3].createView()) - this.inputTextureViews.push(inputs[4].createView()) + + let ssaoTexture = inputs[4] + if (!ssaoTexture) { + ssaoTexture = TextureLoader.dummyR16FTexture + } + this.inputTextureViews.push(ssaoTexture.createView()) this.updateGbufferBindGroupEntryAt(0, this.inputTextureViews[0]) .updateGbufferBindGroupEntryAt(1, this.inputTextureViews[1]) .updateGbufferBindGroupEntryAt(2, this.inputTextureViews[3]) - .updateGbufferBindGroupEntryAt(3, this.inputTextureViews[4]) + .updateGbufferBindGroupEntryAt(3, this.inputTextureViews[5]) .updateGbufferBindGroupEntryAt(4, { buffer: this.camera.gpuBuffer, }) @@ -169,6 +175,6 @@ export default class PointLightsRenderPass extends LightRenderPass { this.postRender(commandEncoder) - return [inputs[4]] + return [inputs[3]] } } diff --git a/src/app/shaders/GBufferIntegrateShader.ts b/src/app/shaders/GBufferIntegrateShader.ts index 84bacfc..3ce34b3 100644 --- a/src/app/shaders/GBufferIntegrateShader.ts +++ b/src/app/shaders/GBufferIntegrateShader.ts @@ -66,6 +66,7 @@ const GetGBufferIntegrateShader = ( #if ${lightPassType === RenderPassType.DirectionalAmbientLighting} material.ambientOcclusion = mix(1.0, ao, ssaoMixFactor); + // return vec4f(ao, 0, 0, 1); #endif let viewSpacePos = calcViewSpacePos(camera, coord.xy, depth); diff --git a/src/index.ts b/src/index.ts index 78e49fb..3744c47 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,7 @@ import * as dat from 'dat.gui' import Renderer from './app/Renderer' +import { PROFILE_MAX_FRAMES_COUNT } from './app/constants' +import RollingAverage from './renderer/math/RollingAverage' import { IGUIParams, SSRMethod } from './types' const $canvas = document.getElementById('c') as HTMLCanvasElement @@ -41,18 +43,69 @@ const GUI_PARAMS: IGUIParams = { // "Debug Bounding Boxes": false, // "Debug Point Lines Curve": false, 'Enable SSAO': true, - 'SSAO Kernel Size': 8, - 'SSAO Radius': 0.2, - 'SSAO Strength': 3, + 'SSAO Kernel Size': 64, + 'SSAO Radius': 0.5, + 'SSAO Strength': 2, } -renderer.onIntroAnimComplete = createGUI +const fpsDisplayAverage = new RollingAverage(2000) +let oldTimeMs = 0 +let introAnimPlayed = false +let ssrEnabledManuallySet = false +let ssrEnabledPerfAutomaticallySet = false +let bloomEnabledManuallySet = false +let bloomEnabledPerfAutomaticallySet = false +let ssaoEnabledManuallySet = false + +renderer.onIntroAnimComplete = onIntroAnimComplete requestAnimationFrame(renderFrame) window.addEventListener('resize', resize) resize() function renderFrame() { const nowMs = performance.now() + const dt = (nowMs - oldTimeMs) / 1000 + oldTimeMs = nowMs + + fpsDisplayAverage.addSample(1 / dt) + const fpsAverageStat = fpsDisplayAverage.get() + + if ( + GUI_PARAMS['Enable SSR'] && + !ssrEnabledManuallySet && + fpsDisplayAverage.getSamplesCount() > PROFILE_MAX_FRAMES_COUNT && + fpsAverageStat < 60 + ) { + console.log('1. performance too low. disabling ssr') + GUI_PARAMS['Enable SSR'] = false + renderer.ssrEnabled = false + ssrEnabledPerfAutomaticallySet = true + } + + if ( + GUI_PARAMS['Enable Bloom'] && + !bloomEnabledManuallySet && + ssrEnabledPerfAutomaticallySet && + fpsDisplayAverage.getSamplesCount() > PROFILE_MAX_FRAMES_COUNT && + fpsAverageStat < 60 + ) { + console.log('2. performance still too low. disabling bloom') + GUI_PARAMS['Enable Bloom'] = false + renderer.bloomEnabled = false + bloomEnabledPerfAutomaticallySet = true + } + + if ( + GUI_PARAMS['Enable SSAO'] && + !ssaoEnabledManuallySet && + bloomEnabledPerfAutomaticallySet && + fpsDisplayAverage.getSamplesCount() > PROFILE_MAX_FRAMES_COUNT && + fpsAverageStat < 60 + ) { + console.log('3. performance still too low. disabling ssao') + GUI_PARAMS['Enable SSAO'] = false + renderer.ssaoEnabled = false + } renderer.renderFrame(nowMs) requestAnimationFrame(renderFrame) @@ -74,7 +127,8 @@ function offsetLogoAndStats() { document.getElementById('timings-debug-container').classList.toggle('faded') } -function createGUI() { +function onIntroAnimComplete() { + introAnimPlayed = true const gui = new dat.GUI({ width: 270 }) gui.close() @@ -155,10 +209,12 @@ function createGUI() { if (v) { lastBloomEnabled = GUI_PARAMS['Enable Bloom'] GUI_PARAMS['Enable Bloom'] = false + bloomEnabledManuallySet = true renderer.bloomEnabled = false } else { if (lastBloomEnabled) { GUI_PARAMS['Enable Bloom'] = true + bloomEnabledManuallySet = true renderer.bloomEnabled = true } } @@ -173,6 +229,7 @@ function createGUI() { const ssaoFolder = gui.addFolder('Screen space Ambient Occlusion') ssaoFolder.open() ssaoFolder.add(GUI_PARAMS, 'Enable SSAO').onChange((v: boolean) => { + ssaoEnabledManuallySet = true renderer.ssaoEnabled = v }) ssaoFolder @@ -192,6 +249,7 @@ function createGUI() { ssrFolder.add(GUI_PARAMS, 'Enable SSR').onChange((v: boolean) => { renderer.ssrEnabled = v + ssrEnabledManuallySet = true }) ssrFolder .add(GUI_PARAMS, 'SSR Method', ['hi-z', 'linear']) @@ -212,6 +270,7 @@ function createGUI() { const bloomEnabledCtrl = bloomFolder .add(GUI_PARAMS, 'Enable Bloom') .onChange((v: boolean) => { + bloomEnabledManuallySet = true renderer.bloomEnabled = v }) bloomEnabledCtrl.listen() diff --git a/src/renderer/math/RollingAverage.ts b/src/renderer/math/RollingAverage.ts index 9044a4c..391541d 100644 --- a/src/renderer/math/RollingAverage.ts +++ b/src/renderer/math/RollingAverage.ts @@ -10,6 +10,10 @@ export default class RollingAverage { this.cursor = (this.cursor + 1) % this.numSamples } + public getSamplesCount(): number { + return this.samples.length + } + public get(): number { return this.total / this.samples.length } diff --git a/src/renderer/texture/TextureLoader.ts b/src/renderer/texture/TextureLoader.ts index de0a8aa..8bc0890 100644 --- a/src/renderer/texture/TextureLoader.ts +++ b/src/renderer/texture/TextureLoader.ts @@ -32,10 +32,38 @@ const DEBUG_PATTERN = new Uint8Array([ ]); let _dummyTexture: GPUTexture +let _dummyRGBA16FTexture: GPUTexture +let _dummyR16FTexture: GPUTexture let _dummyCubeTexture: GPUTexture let _bayerDitherPattern: GPUTexture export default class TextureLoader extends BaseUtilObject { + public static get dummyRGBA16FTexture(): GPUTexture { + if (_dummyRGBA16FTexture) { + return _dummyRGBA16FTexture + } + _dummyRGBA16FTexture = RenderingContext.device.createTexture({ + label: 'Dummy 1x1 RGBA16F Texture', + size: { width: 1, height: 1 }, + format: 'rgba16float', + usage: GPUTextureUsage.TEXTURE_BINDING, + }) + return _dummyRGBA16FTexture + } + + public static get dummyR16FTexture(): GPUTexture { + if (_dummyR16FTexture) { + return _dummyR16FTexture + } + _dummyR16FTexture = RenderingContext.device.createTexture({ + label: 'Dummy 1x1 R16F Texture', + size: { width: 1, height: 1 }, + format: 'r16float', + usage: GPUTextureUsage.TEXTURE_BINDING, + }) + return _dummyR16FTexture + } + public static get dummyTexture(): GPUTexture { if (_dummyTexture) { return _dummyTexture @@ -50,7 +78,7 @@ export default class TextureLoader extends BaseUtilObject { RenderingContext.device.queue.writeTexture( { texture: _dummyTexture, mipLevel: 0 }, DEBUG_PATTERN, - { offset: 0, bytesPerRow: 8 }, + { offset: 0, bytesPerRow: 8 * Uint8Array.BYTES_PER_ELEMENT }, { width: 8, height: 8,