@aura3d/rendering 3.0.1 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/BlendModes.d.ts +34 -0
- package/dist/BlendModes.d.ts.map +1 -0
- package/dist/BlendModes.js +42 -0
- package/dist/BlendModes.js.map +1 -0
- package/dist/DepthPass.d.ts +18 -0
- package/dist/DepthPass.d.ts.map +1 -1
- package/dist/DepthPass.js +103 -20
- package/dist/DepthPass.js.map +1 -1
- package/dist/EnvironmentBackgroundPass.d.ts +7 -0
- package/dist/EnvironmentBackgroundPass.d.ts.map +1 -1
- package/dist/EnvironmentBackgroundPass.js +39 -14
- package/dist/EnvironmentBackgroundPass.js.map +1 -1
- package/dist/EnvironmentMapResources.d.ts +1 -1
- package/dist/EnvironmentMapResources.d.ts.map +1 -1
- package/dist/EnvironmentMapResources.js +19 -8
- package/dist/EnvironmentMapResources.js.map +1 -1
- package/dist/EnvironmentPlatform.d.ts +6 -0
- package/dist/EnvironmentPlatform.d.ts.map +1 -1
- package/dist/EnvironmentPlatform.js +3 -1
- package/dist/EnvironmentPlatform.js.map +1 -1
- package/dist/EnvironmentPreset.d.ts +7 -0
- package/dist/EnvironmentPreset.d.ts.map +1 -1
- package/dist/EnvironmentPreset.js +11 -11
- package/dist/EnvironmentPreset.js.map +1 -1
- package/dist/EnvironmentPresetPack.d.ts +16 -0
- package/dist/EnvironmentPresetPack.d.ts.map +1 -1
- package/dist/EnvironmentPresetPack.js +28 -0
- package/dist/EnvironmentPresetPack.js.map +1 -1
- package/dist/ExternalParityRenderPreset.d.ts +15 -1
- package/dist/ExternalParityRenderPreset.d.ts.map +1 -1
- package/dist/ExternalParityRenderPreset.js +52 -7
- package/dist/ExternalParityRenderPreset.js.map +1 -1
- package/dist/ForwardPass.d.ts +240 -50
- package/dist/ForwardPass.d.ts.map +1 -1
- package/dist/ForwardPass.js +845 -866
- package/dist/ForwardPass.js.map +1 -1
- package/dist/Geometry.d.ts +44 -1
- package/dist/Geometry.d.ts.map +1 -1
- package/dist/Geometry.js +174 -24
- package/dist/Geometry.js.map +1 -1
- package/dist/InstancedPBRMaterial.d.ts +5 -0
- package/dist/InstancedPBRMaterial.d.ts.map +1 -1
- package/dist/InstancedPBRMaterial.js +7 -0
- package/dist/InstancedPBRMaterial.js.map +1 -1
- package/dist/LightCollector.d.ts +8 -0
- package/dist/LightCollector.d.ts.map +1 -1
- package/dist/LightCollector.js +1 -1
- package/dist/LightCollector.js.map +1 -1
- package/dist/LightUniforms.d.ts +78 -0
- package/dist/LightUniforms.d.ts.map +1 -1
- package/dist/LightUniforms.js +100 -0
- package/dist/LightUniforms.js.map +1 -1
- package/dist/Material.d.ts +15 -0
- package/dist/Material.d.ts.map +1 -1
- package/dist/Material.js +19 -2
- package/dist/Material.js.map +1 -1
- package/dist/MaterialBinding.d.ts +10 -0
- package/dist/MaterialBinding.d.ts.map +1 -1
- package/dist/MaterialBinding.js +91 -1
- package/dist/MaterialBinding.js.map +1 -1
- package/dist/MaterialPresets.d.ts +60 -0
- package/dist/MaterialPresets.d.ts.map +1 -1
- package/dist/MaterialPresets.js +212 -0
- package/dist/MaterialPresets.js.map +1 -1
- package/dist/NormalMappedPBRMaterial.d.ts +5 -0
- package/dist/NormalMappedPBRMaterial.d.ts.map +1 -1
- package/dist/NormalMappedPBRMaterial.js +7 -0
- package/dist/NormalMappedPBRMaterial.js.map +1 -1
- package/dist/OceanSurface.d.ts +8 -0
- package/dist/OceanSurface.d.ts.map +1 -1
- package/dist/OceanSurface.js +10 -79
- package/dist/OceanSurface.js.map +1 -1
- package/dist/PBRLightingDefaults.d.ts +8 -0
- package/dist/PBRLightingDefaults.d.ts.map +1 -1
- package/dist/PBRLightingDefaults.js +8 -0
- package/dist/PBRLightingDefaults.js.map +1 -1
- package/dist/PBRMaterial.d.ts +5 -0
- package/dist/PBRMaterial.d.ts.map +1 -1
- package/dist/PBRMaterial.js +7 -0
- package/dist/PBRMaterial.js.map +1 -1
- package/dist/PostProcessPass.d.ts +6 -490
- package/dist/PostProcessPass.d.ts.map +1 -1
- package/dist/PostProcessPass.js +6 -2016
- package/dist/PostProcessPass.js.map +1 -1
- package/dist/ProceduralMaterialTextures.d.ts +28 -0
- package/dist/ProceduralMaterialTextures.d.ts.map +1 -0
- package/dist/ProceduralMaterialTextures.js +217 -0
- package/dist/ProceduralMaterialTextures.js.map +1 -0
- package/dist/ReflectionProbe.d.ts.map +1 -1
- package/dist/ReflectionProbe.js +4 -1
- package/dist/ReflectionProbe.js.map +1 -1
- package/dist/RenderBackend.d.ts +2 -0
- package/dist/RenderBackend.d.ts.map +1 -1
- package/dist/RenderBackend.js +3 -0
- package/dist/RenderBackend.js.map +1 -1
- package/dist/RenderDevice.d.ts +92 -5
- package/dist/RenderDevice.d.ts.map +1 -1
- package/dist/RenderDevice.js +166 -9
- package/dist/RenderDevice.js.map +1 -1
- package/dist/RenderGraph.d.ts.map +1 -1
- package/dist/RenderGraph.js +17 -0
- package/dist/RenderGraph.js.map +1 -1
- package/dist/RenderPass.d.ts +7 -0
- package/dist/RenderPass.d.ts.map +1 -1
- package/dist/RenderPass.js.map +1 -1
- package/dist/RenderPipeline.d.ts +5 -0
- package/dist/RenderPipeline.d.ts.map +1 -1
- package/dist/RenderPipeline.js +6 -0
- package/dist/RenderPipeline.js.map +1 -1
- package/dist/Renderer.d.ts +261 -66
- package/dist/Renderer.d.ts.map +1 -1
- package/dist/Renderer.js +889 -1254
- package/dist/Renderer.js.map +1 -1
- package/dist/RendererPostprocessPlan.d.ts +4 -0
- package/dist/RendererPostprocessPlan.d.ts.map +1 -1
- package/dist/RendererPostprocessPlan.js +16 -2
- package/dist/RendererPostprocessPlan.js.map +1 -1
- package/dist/RendererTiming.d.ts +27 -0
- package/dist/RendererTiming.d.ts.map +1 -1
- package/dist/RendererTiming.js +179 -12
- package/dist/RendererTiming.js.map +1 -1
- package/dist/ResolutionGovernor.d.ts +56 -0
- package/dist/ResolutionGovernor.d.ts.map +1 -0
- package/dist/ResolutionGovernor.js +87 -0
- package/dist/ResolutionGovernor.js.map +1 -0
- package/dist/Sampler.d.ts +34 -1
- package/dist/Sampler.d.ts.map +1 -1
- package/dist/Sampler.js +55 -2
- package/dist/Sampler.js.map +1 -1
- package/dist/ShaderLibrary.d.ts.map +1 -1
- package/dist/ShaderLibrary.js +15 -10
- package/dist/ShaderLibrary.js.map +1 -1
- package/dist/ShaderLibraryCore.d.ts.map +1 -1
- package/dist/ShaderLibraryCore.js +3 -2
- package/dist/ShaderLibraryCore.js.map +1 -1
- package/dist/ShaderModule.d.ts +7 -1
- package/dist/ShaderModule.d.ts.map +1 -1
- package/dist/ShaderModule.js +20 -5
- package/dist/ShaderModule.js.map +1 -1
- package/dist/ShadowPass.d.ts.map +1 -1
- package/dist/ShadowPass.js +14 -7
- package/dist/ShadowPass.js.map +1 -1
- package/dist/SkinnedLitMaterial.d.ts +5 -0
- package/dist/SkinnedLitMaterial.d.ts.map +1 -1
- package/dist/SkinnedLitMaterial.js +13 -0
- package/dist/SkinnedLitMaterial.js.map +1 -1
- package/dist/SkinningBounds.d.ts +18 -0
- package/dist/SkinningBounds.d.ts.map +1 -1
- package/dist/SkinningBounds.js +78 -0
- package/dist/SkinningBounds.js.map +1 -1
- package/dist/SkinningPaletteTextureCache.d.ts +117 -0
- package/dist/SkinningPaletteTextureCache.d.ts.map +1 -0
- package/dist/SkinningPaletteTextureCache.js +205 -0
- package/dist/SkinningPaletteTextureCache.js.map +1 -0
- package/dist/SkinningUniforms.d.ts +56 -0
- package/dist/SkinningUniforms.d.ts.map +1 -0
- package/dist/SkinningUniforms.js +262 -0
- package/dist/SkinningUniforms.js.map +1 -0
- package/dist/TemporalHistory.d.ts +33 -0
- package/dist/TemporalHistory.d.ts.map +1 -1
- package/dist/TemporalHistory.js +84 -1
- package/dist/TemporalHistory.js.map +1 -1
- package/dist/TerrainHeightfield.d.ts +12 -0
- package/dist/TerrainHeightfield.d.ts.map +1 -1
- package/dist/TerrainHeightfield.js +29 -6
- package/dist/TerrainHeightfield.js.map +1 -1
- package/dist/TerrainTiles.d.ts +40 -10
- package/dist/TerrainTiles.d.ts.map +1 -1
- package/dist/TerrainTiles.js +18 -57
- package/dist/TerrainTiles.js.map +1 -1
- package/dist/Texture.d.ts +47 -2
- package/dist/Texture.d.ts.map +1 -1
- package/dist/Texture.js +119 -3
- package/dist/Texture.js.map +1 -1
- package/dist/TexturedPBRMaterial.d.ts +24 -0
- package/dist/TexturedPBRMaterial.d.ts.map +1 -1
- package/dist/TexturedPBRMaterial.js +72 -20
- package/dist/TexturedPBRMaterial.js.map +1 -1
- package/dist/TransmissionRenderTarget.d.ts +33 -0
- package/dist/TransmissionRenderTarget.d.ts.map +1 -0
- package/dist/TransmissionRenderTarget.js +61 -0
- package/dist/TransmissionRenderTarget.js.map +1 -0
- package/dist/VegetationScatter.js +1 -1
- package/dist/VegetationScatter.js.map +1 -1
- package/dist/VolumetricFog.d.ts +42 -0
- package/dist/VolumetricFog.d.ts.map +1 -1
- package/dist/VolumetricFog.js +52 -1
- package/dist/VolumetricFog.js.map +1 -1
- package/dist/WaterSurface.d.ts +5 -0
- package/dist/WaterSurface.d.ts.map +1 -1
- package/dist/WaterSurface.js +5 -0
- package/dist/WaterSurface.js.map +1 -1
- package/dist/WebGL2Device.d.ts +153 -207
- package/dist/WebGL2Device.d.ts.map +1 -1
- package/dist/WebGL2Device.js +822 -3706
- package/dist/WebGL2Device.js.map +1 -1
- package/dist/WebGL2StateCache.d.ts +15 -1
- package/dist/WebGL2StateCache.d.ts.map +1 -1
- package/dist/WebGL2StateCache.js +31 -2
- package/dist/WebGL2StateCache.js.map +1 -1
- package/dist/WebGPUDevice.d.ts +0 -4
- package/dist/WebGPUDevice.d.ts.map +1 -1
- package/dist/WebGPUDevice.js +31 -605
- package/dist/WebGPUDevice.js.map +1 -1
- package/dist/WebGPUSkinningLimits.d.ts +10 -1
- package/dist/WebGPUSkinningLimits.d.ts.map +1 -1
- package/dist/WebGPUSkinningLimits.js +15 -1
- package/dist/WebGPUSkinningLimits.js.map +1 -1
- package/dist/advanced-runtime/index.d.ts +6 -2
- package/dist/advanced-runtime/index.d.ts.map +1 -1
- package/dist/advanced-runtime/index.js +0 -1
- package/dist/advanced-runtime/index.js.map +1 -1
- package/dist/animation/AnimationRenderPreset.d.ts +1 -1
- package/dist/animation/AnimationRenderPreset.d.ts.map +1 -1
- package/dist/animation/AnimationRenderPreset.js +1 -1
- package/dist/animation/AnimationRenderPreset.js.map +1 -1
- package/dist/animation/applyAnimationRenderPreset.d.ts +1 -1
- package/dist/animation/applyAnimationRenderPreset.d.ts.map +1 -1
- package/dist/animation/index.d.ts +2 -1
- package/dist/animation/index.d.ts.map +1 -1
- package/dist/animation/index.js +1 -1
- package/dist/animation/index.js.map +1 -1
- package/dist/atmosphere/CloudLayer.d.ts +24 -0
- package/dist/atmosphere/CloudLayer.d.ts.map +1 -0
- package/dist/atmosphere/CloudLayer.js +30 -0
- package/dist/atmosphere/CloudLayer.js.map +1 -0
- package/dist/atmosphere/FogVolumes.d.ts +30 -0
- package/dist/atmosphere/FogVolumes.d.ts.map +1 -0
- package/dist/atmosphere/FogVolumes.js +96 -0
- package/dist/atmosphere/FogVolumes.js.map +1 -0
- package/dist/atmosphere/GradientSky.d.ts +40 -0
- package/dist/atmosphere/GradientSky.d.ts.map +1 -0
- package/dist/atmosphere/GradientSky.js +75 -0
- package/dist/atmosphere/GradientSky.js.map +1 -0
- package/dist/atmosphere/HeightFog.d.ts +154 -0
- package/dist/atmosphere/HeightFog.d.ts.map +1 -0
- package/dist/atmosphere/HeightFog.js +379 -0
- package/dist/atmosphere/HeightFog.js.map +1 -0
- package/dist/atmosphere/PreethamSky.d.ts +38 -0
- package/dist/atmosphere/PreethamSky.d.ts.map +1 -0
- package/dist/atmosphere/PreethamSky.js +150 -0
- package/dist/atmosphere/PreethamSky.js.map +1 -0
- package/dist/atmosphere/SkyBackgroundPass.d.ts +63 -0
- package/dist/atmosphere/SkyBackgroundPass.d.ts.map +1 -0
- package/dist/atmosphere/SkyBackgroundPass.js +233 -0
- package/dist/atmosphere/SkyBackgroundPass.js.map +1 -0
- package/dist/atmosphere/SkyCaptureAdapter.d.ts +45 -0
- package/dist/atmosphere/SkyCaptureAdapter.d.ts.map +1 -0
- package/dist/atmosphere/SkyCaptureAdapter.js +65 -0
- package/dist/atmosphere/SkyCaptureAdapter.js.map +1 -0
- package/dist/atmosphere/SkyEval.d.ts +56 -0
- package/dist/atmosphere/SkyEval.d.ts.map +1 -0
- package/dist/atmosphere/SkyEval.js +99 -0
- package/dist/atmosphere/SkyEval.js.map +1 -0
- package/dist/atmosphere/StarField.d.ts +26 -0
- package/dist/atmosphere/StarField.d.ts.map +1 -0
- package/dist/atmosphere/StarField.js +31 -0
- package/dist/atmosphere/StarField.js.map +1 -0
- package/dist/atmosphere/VolumetricFogPass.d.ts +69 -0
- package/dist/atmosphere/VolumetricFogPass.d.ts.map +1 -0
- package/dist/atmosphere/VolumetricFogPass.js +265 -0
- package/dist/atmosphere/VolumetricFogPass.js.map +1 -0
- package/dist/atmosphere/fogChunks.d.ts +8 -0
- package/dist/atmosphere/fogChunks.d.ts.map +1 -0
- package/dist/atmosphere/fogChunks.js +39 -0
- package/dist/atmosphere/fogChunks.js.map +1 -0
- package/dist/atmosphere/fogUniformStore.d.ts +20 -0
- package/dist/atmosphere/fogUniformStore.d.ts.map +1 -0
- package/dist/atmosphere/fogUniformStore.js +45 -0
- package/dist/atmosphere/fogUniformStore.js.map +1 -0
- package/dist/atmosphere/shaders/fog.glsl.d.ts +10 -0
- package/dist/atmosphere/shaders/fog.glsl.d.ts.map +1 -0
- package/dist/atmosphere/shaders/fog.glsl.js +161 -0
- package/dist/atmosphere/shaders/fog.glsl.js.map +1 -0
- package/dist/atmosphere/shaders/volumetric-apply.glsl.d.ts +3 -0
- package/dist/atmosphere/shaders/volumetric-apply.glsl.d.ts.map +1 -0
- package/dist/atmosphere/shaders/volumetric-apply.glsl.js +61 -0
- package/dist/atmosphere/shaders/volumetric-apply.glsl.js.map +1 -0
- package/dist/atmosphere/shaders/volumetric-inject.glsl.d.ts +4 -0
- package/dist/atmosphere/shaders/volumetric-inject.glsl.d.ts.map +1 -0
- package/dist/atmosphere/shaders/volumetric-inject.glsl.js +129 -0
- package/dist/atmosphere/shaders/volumetric-inject.glsl.js.map +1 -0
- package/dist/atmosphere/shaders/volumetric-integrate.glsl.d.ts +3 -0
- package/dist/atmosphere/shaders/volumetric-integrate.glsl.d.ts.map +1 -0
- package/dist/atmosphere/shaders/volumetric-integrate.glsl.js +55 -0
- package/dist/atmosphere/shaders/volumetric-integrate.glsl.js.map +1 -0
- package/dist/atmosphere/shaders/wetness.glsl.d.ts +34 -0
- package/dist/atmosphere/shaders/wetness.glsl.d.ts.map +1 -0
- package/dist/atmosphere/shaders/wetness.glsl.js +101 -0
- package/dist/atmosphere/shaders/wetness.glsl.js.map +1 -0
- package/dist/atmosphere/sky.glsl.d.ts +8 -0
- package/dist/atmosphere/sky.glsl.d.ts.map +1 -0
- package/dist/atmosphere/sky.glsl.js +249 -0
- package/dist/atmosphere/sky.glsl.js.map +1 -0
- package/dist/batching/BatchedGeometryPool.d.ts +72 -0
- package/dist/batching/BatchedGeometryPool.d.ts.map +1 -0
- package/dist/batching/BatchedGeometryPool.js +138 -0
- package/dist/batching/BatchedGeometryPool.js.map +1 -0
- package/dist/batching/ContentKeys.d.ts +29 -0
- package/dist/batching/ContentKeys.d.ts.map +1 -0
- package/dist/batching/ContentKeys.js +220 -0
- package/dist/batching/ContentKeys.js.map +1 -0
- package/dist/batching/DrawDataTexture.d.ts +51 -0
- package/dist/batching/DrawDataTexture.d.ts.map +1 -0
- package/dist/batching/DrawDataTexture.js +99 -0
- package/dist/batching/DrawDataTexture.js.map +1 -0
- package/dist/batching/MultiDrawBatch.d.ts +64 -0
- package/dist/batching/MultiDrawBatch.d.ts.map +1 -0
- package/dist/batching/MultiDrawBatch.js +103 -0
- package/dist/batching/MultiDrawBatch.js.map +1 -0
- package/dist/batching/StaticMergePlanner.d.ts +80 -0
- package/dist/batching/StaticMergePlanner.d.ts.map +1 -0
- package/dist/batching/StaticMergePlanner.js +323 -0
- package/dist/batching/StaticMergePlanner.js.map +1 -0
- package/dist/batching/index.d.ts +8 -0
- package/dist/batching/index.d.ts.map +1 -0
- package/dist/batching/index.js +8 -0
- package/dist/batching/index.js.map +1 -0
- package/dist/batching/shaders/drawId.glsl.d.ts +29 -0
- package/dist/batching/shaders/drawId.glsl.d.ts.map +1 -0
- package/dist/batching/shaders/drawId.glsl.js +93 -0
- package/dist/batching/shaders/drawId.glsl.js.map +1 -0
- package/dist/batching/shaders/instanceEmissive.glsl.d.ts +16 -0
- package/dist/batching/shaders/instanceEmissive.glsl.d.ts.map +1 -0
- package/dist/batching/shaders/instanceEmissive.glsl.js +63 -0
- package/dist/batching/shaders/instanceEmissive.glsl.js.map +1 -0
- package/dist/cinematic/BloomPass.d.ts +5 -9
- package/dist/cinematic/BloomPass.d.ts.map +1 -1
- package/dist/cinematic/BloomPass.js +5 -17
- package/dist/cinematic/BloomPass.js.map +1 -1
- package/dist/cinematic/DepthHazePass.d.ts +5 -11
- package/dist/cinematic/DepthHazePass.d.ts.map +1 -1
- package/dist/cinematic/DepthHazePass.js +5 -19
- package/dist/cinematic/DepthHazePass.js.map +1 -1
- package/dist/cinematic/FilmGrainPass.d.ts +5 -8
- package/dist/cinematic/FilmGrainPass.d.ts.map +1 -1
- package/dist/cinematic/FilmGrainPass.js +5 -16
- package/dist/cinematic/FilmGrainPass.js.map +1 -1
- package/dist/cinematic/VignettePass.d.ts +5 -9
- package/dist/cinematic/VignettePass.d.ts.map +1 -1
- package/dist/cinematic/VignettePass.js +5 -16
- package/dist/cinematic/VignettePass.js.map +1 -1
- package/dist/cinematic/index.d.ts +2 -1
- package/dist/cinematic/index.d.ts.map +1 -1
- package/dist/cinematic/index.js +1 -1
- package/dist/cinematic/index.js.map +1 -1
- package/dist/contracts/atmosphere.d.ts +30 -0
- package/dist/contracts/atmosphere.d.ts.map +1 -0
- package/dist/contracts/atmosphere.js +42 -0
- package/dist/contracts/atmosphere.js.map +1 -0
- package/dist/contracts/blend.d.ts +28 -0
- package/dist/contracts/blend.d.ts.map +1 -0
- package/dist/contracts/blend.js +73 -0
- package/dist/contracts/blend.js.map +1 -0
- package/dist/contracts/core.d.ts +47 -0
- package/dist/contracts/core.d.ts.map +1 -0
- package/dist/contracts/core.js +70 -0
- package/dist/contracts/core.js.map +1 -0
- package/dist/contracts/deform.d.ts +38 -0
- package/dist/contracts/deform.d.ts.map +1 -0
- package/dist/contracts/deform.js +14 -0
- package/dist/contracts/deform.js.map +1 -0
- package/dist/contracts/device.d.ts +71 -0
- package/dist/contracts/device.d.ts.map +1 -0
- package/dist/contracts/device.js +97 -0
- package/dist/contracts/device.js.map +1 -0
- package/dist/contracts/environment.d.ts +55 -0
- package/dist/contracts/environment.d.ts.map +1 -0
- package/dist/contracts/environment.js +115 -0
- package/dist/contracts/environment.js.map +1 -0
- package/dist/contracts/flags.state.d.ts +15 -0
- package/dist/contracts/flags.state.d.ts.map +1 -0
- package/dist/contracts/flags.state.js +45 -0
- package/dist/contracts/flags.state.js.map +1 -0
- package/dist/contracts/frameGraph.d.ts +78 -0
- package/dist/contracts/frameGraph.d.ts.map +1 -0
- package/dist/contracts/frameGraph.js +32 -0
- package/dist/contracts/frameGraph.js.map +1 -0
- package/dist/contracts/frameUniforms.d.ts +43 -0
- package/dist/contracts/frameUniforms.d.ts.map +1 -0
- package/dist/contracts/frameUniforms.js +35 -0
- package/dist/contracts/frameUniforms.js.map +1 -0
- package/dist/contracts/geometry.d.ts +33 -0
- package/dist/contracts/geometry.d.ts.map +1 -0
- package/dist/contracts/geometry.js +59 -0
- package/dist/contracts/geometry.js.map +1 -0
- package/dist/contracts/index.d.ts +27 -0
- package/dist/contracts/index.d.ts.map +1 -0
- package/dist/contracts/index.js +27 -0
- package/dist/contracts/index.js.map +1 -0
- package/dist/contracts/materialLobes.d.ts +41 -0
- package/dist/contracts/materialLobes.d.ts.map +1 -0
- package/dist/contracts/materialLobes.js +14 -0
- package/dist/contracts/materialLobes.js.map +1 -0
- package/dist/contracts/output.d.ts +35 -0
- package/dist/contracts/output.d.ts.map +1 -0
- package/dist/contracts/output.js +18 -0
- package/dist/contracts/output.js.map +1 -0
- package/dist/contracts/particles.d.ts +41 -0
- package/dist/contracts/particles.d.ts.map +1 -0
- package/dist/contracts/particles.js +15 -0
- package/dist/contracts/particles.js.map +1 -0
- package/dist/contracts/post.d.ts +71 -0
- package/dist/contracts/post.d.ts.map +1 -0
- package/dist/contracts/post.js +28 -0
- package/dist/contracts/post.js.map +1 -0
- package/dist/contracts/program.d.ts +158 -0
- package/dist/contracts/program.d.ts.map +1 -0
- package/dist/contracts/program.js +128 -0
- package/dist/contracts/program.js.map +1 -0
- package/dist/contracts/quality.d.ts +93 -0
- package/dist/contracts/quality.d.ts.map +1 -0
- package/dist/contracts/quality.js +149 -0
- package/dist/contracts/quality.js.map +1 -0
- package/dist/contracts/renderItem.d.ts +58 -0
- package/dist/contracts/renderItem.d.ts.map +1 -0
- package/dist/contracts/renderItem.js +8 -0
- package/dist/contracts/renderItem.js.map +1 -0
- package/dist/contracts/renderSource.d.ts +63 -0
- package/dist/contracts/renderSource.d.ts.map +1 -0
- package/dist/contracts/renderSource.js +7 -0
- package/dist/contracts/renderSource.js.map +1 -0
- package/dist/contracts/rendererFactory.d.ts +42 -0
- package/dist/contracts/rendererFactory.d.ts.map +1 -0
- package/dist/contracts/rendererFactory.js +32 -0
- package/dist/contracts/rendererFactory.js.map +1 -0
- package/dist/contracts/sampling.d.ts +23 -0
- package/dist/contracts/sampling.d.ts.map +1 -0
- package/dist/contracts/sampling.js +17 -0
- package/dist/contracts/sampling.js.map +1 -0
- package/dist/contracts/shadows.d.ts +53 -0
- package/dist/contracts/shadows.d.ts.map +1 -0
- package/dist/contracts/shadows.js +66 -0
- package/dist/contracts/shadows.js.map +1 -0
- package/dist/contracts/testing/ChunkHarness.d.ts +18 -0
- package/dist/contracts/testing/ChunkHarness.d.ts.map +1 -0
- package/dist/contracts/testing/ChunkHarness.js +68 -0
- package/dist/contracts/testing/ChunkHarness.js.map +1 -0
- package/dist/contracts/textureFormats.d.ts +18 -0
- package/dist/contracts/textureFormats.d.ts.map +1 -0
- package/dist/contracts/textureFormats.js +13 -0
- package/dist/contracts/textureFormats.js.map +1 -0
- package/dist/contracts/velocity.d.ts +37 -0
- package/dist/contracts/velocity.d.ts.map +1 -0
- package/dist/contracts/velocity.js +22 -0
- package/dist/contracts/velocity.js.map +1 -0
- package/dist/environment/EnvUniforms.d.ts +42 -0
- package/dist/environment/EnvUniforms.d.ts.map +1 -0
- package/dist/environment/EnvUniforms.js +54 -0
- package/dist/environment/EnvUniforms.js.map +1 -0
- package/dist/environment/EnvironmentCache.d.ts +83 -0
- package/dist/environment/EnvironmentCache.d.ts.map +1 -0
- package/dist/environment/EnvironmentCache.js +205 -0
- package/dist/environment/EnvironmentCache.js.map +1 -0
- package/dist/environment/EnvironmentProbeFactory.d.ts +41 -0
- package/dist/environment/EnvironmentProbeFactory.d.ts.map +1 -0
- package/dist/environment/EnvironmentProbeFactory.js +52 -0
- package/dist/environment/EnvironmentProbeFactory.js.map +1 -0
- package/dist/environment/GPUPMREMGenerator.d.ts +44 -0
- package/dist/environment/GPUPMREMGenerator.d.ts.map +1 -0
- package/dist/environment/GPUPMREMGenerator.js +98 -0
- package/dist/environment/GPUPMREMGenerator.js.map +1 -0
- package/dist/environment/HdrEquirect.d.ts +28 -0
- package/dist/environment/HdrEquirect.d.ts.map +1 -0
- package/dist/environment/HdrEquirect.js +205 -0
- package/dist/environment/HdrEquirect.js.map +1 -0
- package/dist/environment/LightingSamplerBudget.d.ts +20 -0
- package/dist/environment/LightingSamplerBudget.d.ts.map +1 -0
- package/dist/environment/LightingSamplerBudget.js +94 -0
- package/dist/environment/LightingSamplerBudget.js.map +1 -0
- package/dist/environment/Prd02BackgroundShaderLibrary.d.ts +10 -0
- package/dist/environment/Prd02BackgroundShaderLibrary.d.ts.map +1 -0
- package/dist/environment/Prd02BackgroundShaderLibrary.js +100 -0
- package/dist/environment/Prd02BackgroundShaderLibrary.js.map +1 -0
- package/dist/environment/Rgb9e5Cube.d.ts +25 -0
- package/dist/environment/Rgb9e5Cube.d.ts.map +1 -0
- package/dist/environment/Rgb9e5Cube.js +103 -0
- package/dist/environment/Rgb9e5Cube.js.map +1 -0
- package/dist/environment/RoomEnvironmentScene.d.ts +57 -0
- package/dist/environment/RoomEnvironmentScene.d.ts.map +1 -0
- package/dist/environment/RoomEnvironmentScene.js +165 -0
- package/dist/environment/RoomEnvironmentScene.js.map +1 -0
- package/dist/environment/SphericalHarmonics.d.ts +32 -0
- package/dist/environment/SphericalHarmonics.d.ts.map +1 -0
- package/dist/environment/SphericalHarmonics.js +155 -0
- package/dist/environment/SphericalHarmonics.js.map +1 -0
- package/dist/environment/probeBuild.d.ts +97 -0
- package/dist/environment/probeBuild.d.ts.map +1 -0
- package/dist/environment/probeBuild.js +406 -0
- package/dist/environment/probeBuild.js.map +1 -0
- package/dist/environment/workers/cpuPrefilter.d.ts +58 -0
- package/dist/environment/workers/cpuPrefilter.d.ts.map +1 -0
- package/dist/environment/workers/cpuPrefilter.js +288 -0
- package/dist/environment/workers/cpuPrefilter.js.map +1 -0
- package/dist/forward/Deform.d.ts +56 -0
- package/dist/forward/Deform.d.ts.map +1 -0
- package/dist/forward/Deform.js +517 -0
- package/dist/forward/Deform.js.map +1 -0
- package/dist/forward/DrawSubmit.d.ts +32 -0
- package/dist/forward/DrawSubmit.d.ts.map +1 -0
- package/dist/forward/DrawSubmit.js +75 -0
- package/dist/forward/DrawSubmit.js.map +1 -0
- package/dist/forward/Lighting.d.ts +35 -0
- package/dist/forward/Lighting.d.ts.map +1 -0
- package/dist/forward/Lighting.js +477 -0
- package/dist/forward/Lighting.js.map +1 -0
- package/dist/forward/Transmission.d.ts +62 -0
- package/dist/forward/Transmission.d.ts.map +1 -0
- package/dist/forward/Transmission.js +299 -0
- package/dist/forward/Transmission.js.map +1 -0
- package/dist/forward/Velocity.d.ts +47 -0
- package/dist/forward/Velocity.d.ts.map +1 -0
- package/dist/forward/Velocity.js +153 -0
- package/dist/forward/Velocity.js.map +1 -0
- package/dist/forward/transmissionTargetStore.d.ts +21 -0
- package/dist/forward/transmissionTargetStore.d.ts.map +1 -0
- package/dist/forward/transmissionTargetStore.js +8 -0
- package/dist/forward/transmissionTargetStore.js.map +1 -0
- package/dist/geometry/Primitives.d.ts +28 -0
- package/dist/geometry/Primitives.d.ts.map +1 -0
- package/dist/geometry/Primitives.js +110 -0
- package/dist/geometry/Primitives.js.map +1 -0
- package/dist/index.d.ts +140 -58
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +102 -52
- package/dist/index.js.map +1 -1
- package/dist/lanes/index.d.ts +17 -0
- package/dist/lanes/index.d.ts.map +1 -0
- package/dist/lanes/index.js +17 -0
- package/dist/lanes/index.js.map +1 -0
- package/dist/lanes/prd01.d.ts +6 -0
- package/dist/lanes/prd01.d.ts.map +1 -0
- package/dist/lanes/prd01.js +19 -0
- package/dist/lanes/prd01.js.map +1 -0
- package/dist/lanes/prd02.d.ts +62 -0
- package/dist/lanes/prd02.d.ts.map +1 -0
- package/dist/lanes/prd02.js +117 -0
- package/dist/lanes/prd02.js.map +1 -0
- package/dist/lanes/prd03.d.ts +19 -0
- package/dist/lanes/prd03.d.ts.map +1 -0
- package/dist/lanes/prd03.js +55 -0
- package/dist/lanes/prd03.js.map +1 -0
- package/dist/lanes/prd04.d.ts +22 -0
- package/dist/lanes/prd04.d.ts.map +1 -0
- package/dist/lanes/prd04.js +35 -0
- package/dist/lanes/prd04.js.map +1 -0
- package/dist/lanes/prd05.d.ts +4 -0
- package/dist/lanes/prd05.d.ts.map +1 -0
- package/dist/lanes/prd05.js +31 -0
- package/dist/lanes/prd05.js.map +1 -0
- package/dist/lanes/prd06.d.ts +33 -0
- package/dist/lanes/prd06.d.ts.map +1 -0
- package/dist/lanes/prd06.js +217 -0
- package/dist/lanes/prd06.js.map +1 -0
- package/dist/lanes/prd07.d.ts +49 -0
- package/dist/lanes/prd07.d.ts.map +1 -0
- package/dist/lanes/prd07.js +112 -0
- package/dist/lanes/prd07.js.map +1 -0
- package/dist/lanes/prd08.d.ts +2 -0
- package/dist/lanes/prd08.d.ts.map +1 -0
- package/dist/lanes/prd08.js +17 -0
- package/dist/lanes/prd08.js.map +1 -0
- package/dist/lanes/prd09.d.ts +6 -0
- package/dist/lanes/prd09.d.ts.map +1 -0
- package/dist/lanes/prd09.js +6 -0
- package/dist/lanes/prd09.js.map +1 -0
- package/dist/lanes/prd10.d.ts +2 -0
- package/dist/lanes/prd10.d.ts.map +1 -0
- package/dist/lanes/prd10.js +10 -0
- package/dist/lanes/prd10.js.map +1 -0
- package/dist/lanes/prd11.d.ts +61 -0
- package/dist/lanes/prd11.d.ts.map +1 -0
- package/dist/lanes/prd11.js +244 -0
- package/dist/lanes/prd11.js.map +1 -0
- package/dist/lanes/prd12.d.ts +6 -0
- package/dist/lanes/prd12.d.ts.map +1 -0
- package/dist/lanes/prd12.js +6 -0
- package/dist/lanes/prd12.js.map +1 -0
- package/dist/lanes/prd13.d.ts +6 -0
- package/dist/lanes/prd13.d.ts.map +1 -0
- package/dist/lanes/prd13.js +6 -0
- package/dist/lanes/prd13.js.map +1 -0
- package/dist/lanes/prd14.d.ts +6 -0
- package/dist/lanes/prd14.d.ts.map +1 -0
- package/dist/lanes/prd14.js +6 -0
- package/dist/lanes/prd14.js.map +1 -0
- package/dist/lanes/prd15.d.ts +6 -0
- package/dist/lanes/prd15.d.ts.map +1 -0
- package/dist/lanes/prd15.js +6 -0
- package/dist/lanes/prd15.js.map +1 -0
- package/dist/materials/PhysicalFeatures.d.ts +71 -0
- package/dist/materials/PhysicalFeatures.d.ts.map +1 -0
- package/dist/materials/PhysicalFeatures.js +255 -0
- package/dist/materials/PhysicalFeatures.js.map +1 -0
- package/dist/materials/PhysicalMaterial.d.ts +85 -0
- package/dist/materials/PhysicalMaterial.d.ts.map +1 -1
- package/dist/materials/PhysicalMaterial.js +21 -0
- package/dist/materials/PhysicalMaterial.js.map +1 -1
- package/dist/materials/features.d.ts +47 -0
- package/dist/materials/features.d.ts.map +1 -0
- package/dist/materials/features.js +282 -0
- package/dist/materials/features.js.map +1 -0
- package/dist/materials/lobes.d.ts +3 -0
- package/dist/materials/lobes.d.ts.map +1 -0
- package/dist/materials/lobes.js +225 -0
- package/dist/materials/lobes.js.map +1 -0
- package/dist/output/HdrTarget.d.ts +27 -0
- package/dist/output/HdrTarget.d.ts.map +1 -0
- package/dist/output/HdrTarget.js +48 -0
- package/dist/output/HdrTarget.js.map +1 -0
- package/dist/output/OutputPass.d.ts +28 -0
- package/dist/output/OutputPass.d.ts.map +1 -0
- package/dist/output/OutputPass.js +142 -0
- package/dist/output/OutputPass.js.map +1 -0
- package/dist/output/ToneMappingOperators.glsl.d.ts +22 -0
- package/dist/output/ToneMappingOperators.glsl.d.ts.map +1 -0
- package/dist/output/ToneMappingOperators.glsl.js +217 -0
- package/dist/output/ToneMappingOperators.glsl.js.map +1 -0
- package/dist/passes/ContactShadowPass.d.ts +57 -0
- package/dist/passes/ContactShadowPass.d.ts.map +1 -0
- package/dist/passes/ContactShadowPass.js +151 -0
- package/dist/passes/ContactShadowPass.js.map +1 -0
- package/dist/passes/Prd02ContactShadowsContributor.d.ts +16 -0
- package/dist/passes/Prd02ContactShadowsContributor.d.ts.map +1 -0
- package/dist/passes/Prd02ContactShadowsContributor.js +133 -0
- package/dist/passes/Prd02ContactShadowsContributor.js.map +1 -0
- package/dist/passes/Prd02SubFlags.d.ts +22 -0
- package/dist/passes/Prd02SubFlags.d.ts.map +1 -0
- package/dist/passes/Prd02SubFlags.js +32 -0
- package/dist/passes/Prd02SubFlags.js.map +1 -0
- package/dist/performance/BVH.d.ts +46 -0
- package/dist/performance/BVH.d.ts.map +1 -1
- package/dist/performance/BVH.js +212 -0
- package/dist/performance/BVH.js.map +1 -1
- package/dist/performance/Batcher.d.ts +11 -0
- package/dist/performance/Batcher.d.ts.map +1 -1
- package/dist/performance/Batcher.js +10 -0
- package/dist/performance/Batcher.js.map +1 -1
- package/dist/performance/FrustumCuller.d.ts +29 -0
- package/dist/performance/FrustumCuller.d.ts.map +1 -1
- package/dist/performance/FrustumCuller.js +78 -1
- package/dist/performance/FrustumCuller.js.map +1 -1
- package/dist/performance/LOD.d.ts +6 -0
- package/dist/performance/LOD.d.ts.map +1 -1
- package/dist/performance/LOD.js +12 -0
- package/dist/performance/LOD.js.map +1 -1
- package/dist/performance/RenderItemSorting.d.ts +2 -0
- package/dist/performance/RenderItemSorting.d.ts.map +1 -1
- package/dist/performance/RenderItemSorting.js +5 -1
- package/dist/performance/RenderItemSorting.js.map +1 -1
- package/dist/post/CubeLut.d.ts +15 -0
- package/dist/post/CubeLut.d.ts.map +1 -0
- package/dist/post/CubeLut.js +86 -0
- package/dist/post/CubeLut.js.map +1 -0
- package/dist/post/DisplayLutCache.d.ts +31 -0
- package/dist/post/DisplayLutCache.d.ts.map +1 -0
- package/dist/post/DisplayLutCache.js +44 -0
- package/dist/post/DisplayLutCache.js.map +1 -0
- package/dist/post/PostAntiAlias.d.ts +49 -0
- package/dist/post/PostAntiAlias.d.ts.map +1 -0
- package/dist/post/PostAntiAlias.js +75 -0
- package/dist/post/PostAntiAlias.js.map +1 -0
- package/dist/post/PostGraph.d.ts +206 -0
- package/dist/post/PostGraph.d.ts.map +1 -0
- package/dist/post/PostGraph.js +234 -0
- package/dist/post/PostGraph.js.map +1 -0
- package/dist/post/PostQualityTiers.d.ts +95 -0
- package/dist/post/PostQualityTiers.d.ts.map +1 -0
- package/dist/post/PostQualityTiers.js +62 -0
- package/dist/post/PostQualityTiers.js.map +1 -0
- package/dist/post/PostResources.d.ts +49 -0
- package/dist/post/PostResources.d.ts.map +1 -0
- package/dist/post/PostResources.js +119 -0
- package/dist/post/PostResources.js.map +1 -0
- package/dist/post/PostTimer.d.ts +37 -0
- package/dist/post/PostTimer.d.ts.map +1 -0
- package/dist/post/PostTimer.js +88 -0
- package/dist/post/PostTimer.js.map +1 -0
- package/dist/post/ScreenFeelPass.d.ts +83 -0
- package/dist/post/ScreenFeelPass.d.ts.map +1 -0
- package/dist/post/ScreenFeelPass.js +197 -0
- package/dist/post/ScreenFeelPass.js.map +1 -0
- package/dist/post/ToneOperators.d.ts +42 -0
- package/dist/post/ToneOperators.d.ts.map +1 -0
- package/dist/post/ToneOperators.js +179 -0
- package/dist/post/ToneOperators.js.map +1 -0
- package/dist/post/chunks/indirectFraction.glsl.d.ts +50 -0
- package/dist/post/chunks/indirectFraction.glsl.d.ts.map +1 -0
- package/dist/post/chunks/indirectFraction.glsl.js +82 -0
- package/dist/post/chunks/indirectFraction.glsl.js.map +1 -0
- package/dist/post/chunks/velocity.glsl.d.ts +35 -0
- package/dist/post/chunks/velocity.glsl.d.ts.map +1 -0
- package/dist/post/chunks/velocity.glsl.js +86 -0
- package/dist/post/chunks/velocity.glsl.js.map +1 -0
- package/dist/post/shaders/bloom.glsl.d.ts +21 -0
- package/dist/post/shaders/bloom.glsl.d.ts.map +1 -0
- package/dist/post/shaders/bloom.glsl.js +120 -0
- package/dist/post/shaders/bloom.glsl.js.map +1 -0
- package/dist/post/shaders/bloom.wgsl.d.ts +10 -0
- package/dist/post/shaders/bloom.wgsl.d.ts.map +1 -0
- package/dist/post/shaders/bloom.wgsl.js +121 -0
- package/dist/post/shaders/bloom.wgsl.js.map +1 -0
- package/dist/post/shaders/common.glsl.d.ts +11 -0
- package/dist/post/shaders/common.glsl.d.ts.map +1 -0
- package/dist/post/shaders/common.glsl.js +34 -0
- package/dist/post/shaders/common.glsl.js.map +1 -0
- package/dist/post/shaders/common.wgsl.d.ts +25 -0
- package/dist/post/shaders/common.wgsl.d.ts.map +1 -0
- package/dist/post/shaders/common.wgsl.js +48 -0
- package/dist/post/shaders/common.wgsl.js.map +1 -0
- package/dist/post/shaders/composite.glsl.d.ts +25 -0
- package/dist/post/shaders/composite.glsl.d.ts.map +1 -0
- package/dist/post/shaders/composite.glsl.js +96 -0
- package/dist/post/shaders/composite.glsl.js.map +1 -0
- package/dist/post/shaders/composite.wgsl.d.ts +10 -0
- package/dist/post/shaders/composite.wgsl.d.ts.map +1 -0
- package/dist/post/shaders/composite.wgsl.js +92 -0
- package/dist/post/shaders/composite.wgsl.js.map +1 -0
- package/dist/post/shaders/depthDownsample.glsl.d.ts +20 -0
- package/dist/post/shaders/depthDownsample.glsl.d.ts.map +1 -0
- package/dist/post/shaders/depthDownsample.glsl.js +78 -0
- package/dist/post/shaders/depthDownsample.glsl.js.map +1 -0
- package/dist/post/shaders/depthDownsample.wgsl.d.ts +17 -0
- package/dist/post/shaders/depthDownsample.wgsl.d.ts.map +1 -0
- package/dist/post/shaders/depthDownsample.wgsl.js +87 -0
- package/dist/post/shaders/depthDownsample.wgsl.js.map +1 -0
- package/dist/post/shaders/displayGrade.glsl.d.ts +18 -0
- package/dist/post/shaders/displayGrade.glsl.d.ts.map +1 -0
- package/dist/post/shaders/displayGrade.glsl.js +80 -0
- package/dist/post/shaders/displayGrade.glsl.js.map +1 -0
- package/dist/post/shaders/displayGrade.wgsl.d.ts +9 -0
- package/dist/post/shaders/displayGrade.wgsl.d.ts.map +1 -0
- package/dist/post/shaders/displayGrade.wgsl.js +75 -0
- package/dist/post/shaders/displayGrade.wgsl.js.map +1 -0
- package/dist/post/shaders/dof.glsl.d.ts +25 -0
- package/dist/post/shaders/dof.glsl.d.ts.map +1 -0
- package/dist/post/shaders/dof.glsl.js +129 -0
- package/dist/post/shaders/dof.glsl.js.map +1 -0
- package/dist/post/shaders/dof.wgsl.d.ts +11 -0
- package/dist/post/shaders/dof.wgsl.d.ts.map +1 -0
- package/dist/post/shaders/dof.wgsl.js +119 -0
- package/dist/post/shaders/dof.wgsl.js.map +1 -0
- package/dist/post/shaders/exposure.glsl.d.ts +43 -0
- package/dist/post/shaders/exposure.glsl.d.ts.map +1 -0
- package/dist/post/shaders/exposure.glsl.js +115 -0
- package/dist/post/shaders/exposure.glsl.js.map +1 -0
- package/dist/post/shaders/exposure.wgsl.d.ts +16 -0
- package/dist/post/shaders/exposure.wgsl.d.ts.map +1 -0
- package/dist/post/shaders/exposure.wgsl.js +97 -0
- package/dist/post/shaders/exposure.wgsl.js.map +1 -0
- package/dist/post/shaders/finalize.glsl.d.ts +17 -0
- package/dist/post/shaders/finalize.glsl.d.ts.map +1 -0
- package/dist/post/shaders/finalize.glsl.js +120 -0
- package/dist/post/shaders/finalize.glsl.js.map +1 -0
- package/dist/post/shaders/finalize.wgsl.d.ts +13 -0
- package/dist/post/shaders/finalize.wgsl.d.ts.map +1 -0
- package/dist/post/shaders/finalize.wgsl.js +124 -0
- package/dist/post/shaders/finalize.wgsl.js.map +1 -0
- package/dist/post/shaders/fxaa.glsl.d.ts +26 -0
- package/dist/post/shaders/fxaa.glsl.d.ts.map +1 -0
- package/dist/post/shaders/fxaa.glsl.js +246 -0
- package/dist/post/shaders/fxaa.glsl.js.map +1 -0
- package/dist/post/shaders/fxaa.wgsl.d.ts +17 -0
- package/dist/post/shaders/fxaa.wgsl.d.ts.map +1 -0
- package/dist/post/shaders/fxaa.wgsl.js +268 -0
- package/dist/post/shaders/fxaa.wgsl.js.map +1 -0
- package/dist/post/shaders/godrays.glsl.d.ts +16 -0
- package/dist/post/shaders/godrays.glsl.d.ts.map +1 -0
- package/dist/post/shaders/godrays.glsl.js +70 -0
- package/dist/post/shaders/godrays.glsl.js.map +1 -0
- package/dist/post/shaders/godrays.wgsl.d.ts +8 -0
- package/dist/post/shaders/godrays.wgsl.d.ts.map +1 -0
- package/dist/post/shaders/godrays.wgsl.js +60 -0
- package/dist/post/shaders/godrays.wgsl.js.map +1 -0
- package/dist/post/shaders/gtao.glsl.d.ts +29 -0
- package/dist/post/shaders/gtao.glsl.d.ts.map +1 -0
- package/dist/post/shaders/gtao.glsl.js +190 -0
- package/dist/post/shaders/gtao.glsl.js.map +1 -0
- package/dist/post/shaders/gtao.wgsl.d.ts +13 -0
- package/dist/post/shaders/gtao.wgsl.d.ts.map +1 -0
- package/dist/post/shaders/gtao.wgsl.js +163 -0
- package/dist/post/shaders/gtao.wgsl.js.map +1 -0
- package/dist/post/shaders/gtaoDenoise.glsl.d.ts +22 -0
- package/dist/post/shaders/gtaoDenoise.glsl.d.ts.map +1 -0
- package/dist/post/shaders/gtaoDenoise.glsl.js +121 -0
- package/dist/post/shaders/gtaoDenoise.glsl.js.map +1 -0
- package/dist/post/shaders/gtaoDenoise.wgsl.d.ts +11 -0
- package/dist/post/shaders/gtaoDenoise.wgsl.d.ts.map +1 -0
- package/dist/post/shaders/gtaoDenoise.wgsl.js +117 -0
- package/dist/post/shaders/gtaoDenoise.wgsl.js.map +1 -0
- package/dist/post/shaders/motionBlur.glsl.d.ts +21 -0
- package/dist/post/shaders/motionBlur.glsl.d.ts.map +1 -0
- package/dist/post/shaders/motionBlur.glsl.js +110 -0
- package/dist/post/shaders/motionBlur.glsl.js.map +1 -0
- package/dist/post/shaders/motionBlur.wgsl.d.ts +10 -0
- package/dist/post/shaders/motionBlur.wgsl.d.ts.map +1 -0
- package/dist/post/shaders/motionBlur.wgsl.js +102 -0
- package/dist/post/shaders/motionBlur.wgsl.js.map +1 -0
- package/dist/post/shaders/smaa.glsl.d.ts +28 -0
- package/dist/post/shaders/smaa.glsl.d.ts.map +1 -0
- package/dist/post/shaders/smaa.glsl.js +354 -0
- package/dist/post/shaders/smaa.glsl.js.map +1 -0
- package/dist/post/shaders/smaa.wgsl.d.ts +20 -0
- package/dist/post/shaders/smaa.wgsl.d.ts.map +1 -0
- package/dist/post/shaders/smaa.wgsl.js +375 -0
- package/dist/post/shaders/smaa.wgsl.js.map +1 -0
- package/dist/post/shaders/taa.glsl.d.ts +23 -0
- package/dist/post/shaders/taa.glsl.d.ts.map +1 -0
- package/dist/post/shaders/taa.glsl.js +169 -0
- package/dist/post/shaders/taa.glsl.js.map +1 -0
- package/dist/post/shaders/taa.wgsl.d.ts +10 -0
- package/dist/post/shaders/taa.wgsl.d.ts.map +1 -0
- package/dist/post/shaders/taa.wgsl.js +185 -0
- package/dist/post/shaders/taa.wgsl.js.map +1 -0
- package/dist/post/shaders/velocityDilate.glsl.d.ts +16 -0
- package/dist/post/shaders/velocityDilate.glsl.d.ts.map +1 -0
- package/dist/post/shaders/velocityDilate.glsl.js +45 -0
- package/dist/post/shaders/velocityDilate.glsl.js.map +1 -0
- package/dist/post/shaders/velocityDilate.wgsl.d.ts +8 -0
- package/dist/post/shaders/velocityDilate.wgsl.d.ts.map +1 -0
- package/dist/post/shaders/velocityDilate.wgsl.js +30 -0
- package/dist/post/shaders/velocityDilate.wgsl.js.map +1 -0
- package/dist/post/smaa/textures.d.ts +17 -0
- package/dist/post/smaa/textures.d.ts.map +1 -0
- package/dist/post/smaa/textures.js +17 -0
- package/dist/post/smaa/textures.js.map +1 -0
- package/dist/post/v2Entry.d.ts +25 -0
- package/dist/post/v2Entry.d.ts.map +1 -0
- package/dist/post/v2Entry.js +28 -0
- package/dist/post/v2Entry.js.map +1 -0
- package/dist/post/v2Stages.d.ts +156 -0
- package/dist/post/v2Stages.d.ts.map +1 -0
- package/dist/post/v2Stages.js +1189 -0
- package/dist/post/v2Stages.js.map +1 -0
- package/dist/postprocess/EffectComposer.d.ts +6 -109
- package/dist/postprocess/EffectComposer.d.ts.map +1 -1
- package/dist/postprocess/EffectComposer.js +6 -246
- package/dist/postprocess/EffectComposer.js.map +1 -1
- package/dist/postprocess/NativeBloomPyramid.d.ts +34 -0
- package/dist/postprocess/NativeBloomPyramid.d.ts.map +1 -1
- package/dist/postprocess/NativeBloomPyramid.js +57 -0
- package/dist/postprocess/NativeBloomPyramid.js.map +1 -1
- package/dist/postprocess/SSAOPass.d.ts +5 -5
- package/dist/postprocess/SSAOPass.d.ts.map +1 -1
- package/dist/postprocess/SSAOPass.js +5 -17
- package/dist/postprocess/SSAOPass.js.map +1 -1
- package/dist/probes/IrradianceVolume.d.ts +45 -0
- package/dist/probes/IrradianceVolume.d.ts.map +1 -0
- package/dist/probes/IrradianceVolume.js +230 -0
- package/dist/probes/IrradianceVolume.js.map +1 -0
- package/dist/probes/LtcLuts.d.ts +30 -0
- package/dist/probes/LtcLuts.d.ts.map +1 -0
- package/dist/probes/LtcLuts.js +120 -0
- package/dist/probes/LtcLuts.js.map +1 -0
- package/dist/probes/Prd02ProbesContributor.d.ts +53 -0
- package/dist/probes/Prd02ProbesContributor.d.ts.map +1 -0
- package/dist/probes/Prd02ProbesContributor.js +241 -0
- package/dist/probes/Prd02ProbesContributor.js.map +1 -0
- package/dist/probes/ProbeBoxProjection.d.ts +53 -0
- package/dist/probes/ProbeBoxProjection.d.ts.map +1 -0
- package/dist/probes/ProbeBoxProjection.js +99 -0
- package/dist/probes/ProbeBoxProjection.js.map +1 -0
- package/dist/probes/ReflectionProbeSystem.d.ts +64 -0
- package/dist/probes/ReflectionProbeSystem.d.ts.map +1 -0
- package/dist/probes/ReflectionProbeSystem.js +157 -0
- package/dist/probes/ReflectionProbeSystem.js.map +1 -0
- package/dist/production-runtime/PBRHDRPipeline.d.ts.map +1 -1
- package/dist/production-runtime/PBRHDRPipeline.js +23 -9
- package/dist/production-runtime/PBRHDRPipeline.js.map +1 -1
- package/dist/production-runtime/ProductionRendererTypes.d.ts +16 -6
- package/dist/production-runtime/ProductionRendererTypes.d.ts.map +1 -1
- package/dist/production-runtime/ProductionRendererTypes.js.map +1 -1
- package/dist/production-runtime/ProductionWebGPURenderer.d.ts +4 -4
- package/dist/production-runtime/ProductionWebGPURenderer.d.ts.map +1 -1
- package/dist/production-runtime/ProductionWebGPURenderer.js +10 -45
- package/dist/production-runtime/ProductionWebGPURenderer.js.map +1 -1
- package/dist/production-runtime/backendSelection.d.ts +26 -0
- package/dist/production-runtime/backendSelection.d.ts.map +1 -0
- package/dist/production-runtime/backendSelection.js +46 -0
- package/dist/production-runtime/backendSelection.js.map +1 -0
- package/dist/production-runtime/backends/WebGL2RendererBackend.d.ts +1 -1
- package/dist/production-runtime/backends/WebGL2RendererBackend.d.ts.map +1 -1
- package/dist/production-runtime/backends/WebGL2RendererBackend.js +8 -4
- package/dist/production-runtime/backends/WebGL2RendererBackend.js.map +1 -1
- package/dist/production-runtime/backends/WebGPURendererBackend.d.ts +2 -19
- package/dist/production-runtime/backends/WebGPURendererBackend.d.ts.map +1 -1
- package/dist/production-runtime/backends/WebGPURendererBackend.js +2 -18
- package/dist/production-runtime/backends/WebGPURendererBackend.js.map +1 -1
- package/dist/production-runtime/backends/webgl2/WebGL2Buffer.d.ts +2 -10
- package/dist/production-runtime/backends/webgl2/WebGL2Buffer.d.ts.map +1 -1
- package/dist/production-runtime/backends/webgl2/WebGL2Buffer.js +2 -7
- package/dist/production-runtime/backends/webgl2/WebGL2Buffer.js.map +1 -1
- package/dist/production-runtime/backends/webgl2/WebGL2Capabilities.d.ts +2 -10
- package/dist/production-runtime/backends/webgl2/WebGL2Capabilities.d.ts.map +1 -1
- package/dist/production-runtime/backends/webgl2/WebGL2Capabilities.js +2 -7
- package/dist/production-runtime/backends/webgl2/WebGL2Capabilities.js.map +1 -1
- package/dist/production-runtime/backends/webgl2/WebGL2RenderTarget.d.ts +2 -10
- package/dist/production-runtime/backends/webgl2/WebGL2RenderTarget.d.ts.map +1 -1
- package/dist/production-runtime/backends/webgl2/WebGL2RenderTarget.js +2 -7
- package/dist/production-runtime/backends/webgl2/WebGL2RenderTarget.js.map +1 -1
- package/dist/production-runtime/backends/webgl2/WebGL2Shader.d.ts +2 -10
- package/dist/production-runtime/backends/webgl2/WebGL2Shader.d.ts.map +1 -1
- package/dist/production-runtime/backends/webgl2/WebGL2Shader.js +2 -7
- package/dist/production-runtime/backends/webgl2/WebGL2Shader.js.map +1 -1
- package/dist/production-runtime/backends/webgl2/WebGL2StateCache.d.ts +1 -0
- package/dist/production-runtime/backends/webgl2/WebGL2StateCache.d.ts.map +1 -1
- package/dist/production-runtime/backends/webgl2/WebGL2StateCache.js +1 -0
- package/dist/production-runtime/backends/webgl2/WebGL2StateCache.js.map +1 -1
- package/dist/production-runtime/backends/webgl2/WebGL2Texture.d.ts +2 -10
- package/dist/production-runtime/backends/webgl2/WebGL2Texture.d.ts.map +1 -1
- package/dist/production-runtime/backends/webgl2/WebGL2Texture.js +2 -7
- package/dist/production-runtime/backends/webgl2/WebGL2Texture.js.map +1 -1
- package/dist/production-runtime/backends/webgpu/WebGPUBuffer.d.ts +2 -10
- package/dist/production-runtime/backends/webgpu/WebGPUBuffer.d.ts.map +1 -1
- package/dist/production-runtime/backends/webgpu/WebGPUBuffer.js +2 -7
- package/dist/production-runtime/backends/webgpu/WebGPUBuffer.js.map +1 -1
- package/dist/production-runtime/backends/webgpu/WebGPUCapabilities.d.ts +2 -10
- package/dist/production-runtime/backends/webgpu/WebGPUCapabilities.d.ts.map +1 -1
- package/dist/production-runtime/backends/webgpu/WebGPUCapabilities.js +2 -7
- package/dist/production-runtime/backends/webgpu/WebGPUCapabilities.js.map +1 -1
- package/dist/production-runtime/backends/webgpu/WebGPURenderTarget.d.ts +2 -10
- package/dist/production-runtime/backends/webgpu/WebGPURenderTarget.d.ts.map +1 -1
- package/dist/production-runtime/backends/webgpu/WebGPURenderTarget.js +2 -7
- package/dist/production-runtime/backends/webgpu/WebGPURenderTarget.js.map +1 -1
- package/dist/production-runtime/backends/webgpu/WebGPUShader.d.ts +2 -10
- package/dist/production-runtime/backends/webgpu/WebGPUShader.d.ts.map +1 -1
- package/dist/production-runtime/backends/webgpu/WebGPUShader.js +2 -7
- package/dist/production-runtime/backends/webgpu/WebGPUShader.js.map +1 -1
- package/dist/production-runtime/backends/webgpu/WebGPUTexture.d.ts +2 -10
- package/dist/production-runtime/backends/webgpu/WebGPUTexture.d.ts.map +1 -1
- package/dist/production-runtime/backends/webgpu/WebGPUTexture.js +2 -7
- package/dist/production-runtime/backends/webgpu/WebGPUTexture.js.map +1 -1
- package/dist/production-runtime/index.d.ts +6 -6
- package/dist/production-runtime/index.d.ts.map +1 -1
- package/dist/production-runtime/index.js +9 -3
- package/dist/production-runtime/index.js.map +1 -1
- package/dist/production-runtime/materials/GLTFMaterialAdapter.d.ts +12 -13
- package/dist/production-runtime/materials/GLTFMaterialAdapter.d.ts.map +1 -1
- package/dist/production-runtime/materials/GLTFMaterialAdapter.js +10 -4
- package/dist/production-runtime/materials/GLTFMaterialAdapter.js.map +1 -1
- package/dist/production-runtime/materials/GLTFPBRMaterialAdapter.d.ts +9 -2
- package/dist/production-runtime/materials/GLTFPBRMaterialAdapter.d.ts.map +1 -1
- package/dist/production-runtime/materials/GLTFPBRMaterialAdapter.js +7 -1
- package/dist/production-runtime/materials/GLTFPBRMaterialAdapter.js.map +1 -1
- package/dist/production-runtime/materials/MaterialCompiler.d.ts +10 -8
- package/dist/production-runtime/materials/MaterialCompiler.d.ts.map +1 -1
- package/dist/production-runtime/materials/MaterialCompiler.js +9 -4
- package/dist/production-runtime/materials/MaterialCompiler.js.map +1 -1
- package/dist/production-runtime/materials/PBRShaderFeatures.d.ts.map +1 -1
- package/dist/production-runtime/materials/PBRShaderFeatures.js +30 -1
- package/dist/production-runtime/materials/PBRShaderFeatures.js.map +1 -1
- package/dist/production-runtime/renderProofs.d.ts +54 -0
- package/dist/production-runtime/renderProofs.d.ts.map +1 -0
- package/dist/production-runtime/renderProofs.js +245 -0
- package/dist/production-runtime/renderProofs.js.map +1 -0
- package/dist/program/DFGLut.d.ts +23 -0
- package/dist/program/DFGLut.d.ts.map +1 -0
- package/dist/program/DFGLut.js +58 -0
- package/dist/program/DFGLut.js.map +1 -0
- package/dist/program/DFGLutData.d.ts +35 -0
- package/dist/program/DFGLutData.d.ts.map +1 -0
- package/dist/program/DFGLutData.js +52 -0
- package/dist/program/DFGLutData.js.map +1 -0
- package/dist/program/FeatureSelect.d.ts +35 -0
- package/dist/program/FeatureSelect.d.ts.map +1 -0
- package/dist/program/FeatureSelect.js +88 -0
- package/dist/program/FeatureSelect.js.map +1 -0
- package/dist/program/MaterialFeatures.d.ts +66 -0
- package/dist/program/MaterialFeatures.d.ts.map +1 -0
- package/dist/program/MaterialFeatures.js +242 -0
- package/dist/program/MaterialFeatures.js.map +1 -0
- package/dist/program/ProgramCache.d.ts +83 -0
- package/dist/program/ProgramCache.d.ts.map +1 -0
- package/dist/program/ProgramCache.js +194 -0
- package/dist/program/ProgramCache.js.map +1 -0
- package/dist/program/ProgramFeatures.d.ts +21 -0
- package/dist/program/ProgramFeatures.d.ts.map +1 -0
- package/dist/program/ProgramFeatures.js +95 -0
- package/dist/program/ProgramFeatures.js.map +1 -0
- package/dist/program/ProgramGenerator.d.ts +60 -0
- package/dist/program/ProgramGenerator.d.ts.map +1 -0
- package/dist/program/ProgramGenerator.js +760 -0
- package/dist/program/ProgramGenerator.js.map +1 -0
- package/dist/program/ProgramKey.d.ts +10 -0
- package/dist/program/ProgramKey.d.ts.map +1 -0
- package/dist/program/ProgramKey.js +13 -0
- package/dist/program/ProgramKey.js.map +1 -0
- package/dist/program/ProgramWarmup.d.ts +37 -0
- package/dist/program/ProgramWarmup.d.ts.map +1 -0
- package/dist/program/ProgramWarmup.js +68 -0
- package/dist/program/ProgramWarmup.js.map +1 -0
- package/dist/program/UniformLayout.d.ts +40 -0
- package/dist/program/UniformLayout.d.ts.map +1 -0
- package/dist/program/UniformLayout.js +105 -0
- package/dist/program/UniformLayout.js.map +1 -0
- package/dist/program/chunks/alpha.glsl.d.ts +7 -0
- package/dist/program/chunks/alpha.glsl.d.ts.map +1 -0
- package/dist/program/chunks/alpha.glsl.js +17 -0
- package/dist/program/chunks/alpha.glsl.js.map +1 -0
- package/dist/program/chunks/brdf.glsl.d.ts +12 -0
- package/dist/program/chunks/brdf.glsl.d.ts.map +1 -0
- package/dist/program/chunks/brdf.glsl.js +144 -0
- package/dist/program/chunks/brdf.glsl.js.map +1 -0
- package/dist/program/chunks/colorspace.glsl.d.ts +8 -0
- package/dist/program/chunks/colorspace.glsl.d.ts.map +1 -0
- package/dist/program/chunks/colorspace.glsl.js +16 -0
- package/dist/program/chunks/colorspace.glsl.js.map +1 -0
- package/dist/program/chunks/common.glsl.d.ts +7 -0
- package/dist/program/chunks/common.glsl.d.ts.map +1 -0
- package/dist/program/chunks/common.glsl.js +25 -0
- package/dist/program/chunks/common.glsl.js.map +1 -0
- package/dist/program/chunks/depth.glsl.d.ts +9 -0
- package/dist/program/chunks/depth.glsl.d.ts.map +1 -0
- package/dist/program/chunks/depth.glsl.js +18 -0
- package/dist/program/chunks/depth.glsl.js.map +1 -0
- package/dist/program/chunks/drawId.wgsl.d.ts +9 -0
- package/dist/program/chunks/drawId.wgsl.d.ts.map +1 -0
- package/dist/program/chunks/drawId.wgsl.js +29 -0
- package/dist/program/chunks/drawId.wgsl.js.map +1 -0
- package/dist/program/chunks/fog_default.glsl.d.ts +8 -0
- package/dist/program/chunks/fog_default.glsl.d.ts.map +1 -0
- package/dist/program/chunks/fog_default.glsl.js +31 -0
- package/dist/program/chunks/fog_default.glsl.js.map +1 -0
- package/dist/program/chunks/indirect_default.glsl.d.ts +29 -0
- package/dist/program/chunks/indirect_default.glsl.d.ts.map +1 -0
- package/dist/program/chunks/indirect_default.glsl.js +113 -0
- package/dist/program/chunks/indirect_default.glsl.js.map +1 -0
- package/dist/program/chunks/instanceEmissive.wgsl.d.ts +10 -0
- package/dist/program/chunks/instanceEmissive.wgsl.d.ts.map +1 -0
- package/dist/program/chunks/instanceEmissive.wgsl.js +21 -0
- package/dist/program/chunks/instanceEmissive.wgsl.js.map +1 -0
- package/dist/program/chunks/instancing.glsl.d.ts +8 -0
- package/dist/program/chunks/instancing.glsl.d.ts.map +1 -0
- package/dist/program/chunks/instancing.glsl.js +25 -0
- package/dist/program/chunks/instancing.glsl.js.map +1 -0
- package/dist/program/chunks/lights_legacy.glsl.d.ts +15 -0
- package/dist/program/chunks/lights_legacy.glsl.d.ts.map +1 -0
- package/dist/program/chunks/lights_legacy.glsl.js +95 -0
- package/dist/program/chunks/lights_legacy.glsl.js.map +1 -0
- package/dist/program/chunks/manifest.d.ts +42 -0
- package/dist/program/chunks/manifest.d.ts.map +1 -0
- package/dist/program/chunks/manifest.js +48 -0
- package/dist/program/chunks/manifest.js.map +1 -0
- package/dist/program/chunks/normal.glsl.d.ts +8 -0
- package/dist/program/chunks/normal.glsl.d.ts.map +1 -0
- package/dist/program/chunks/normal.glsl.js +34 -0
- package/dist/program/chunks/normal.glsl.js.map +1 -0
- package/dist/program/chunks/shadow_forward.glsl.d.ts +23 -0
- package/dist/program/chunks/shadow_forward.glsl.d.ts.map +1 -0
- package/dist/program/chunks/shadow_forward.glsl.js +73 -0
- package/dist/program/chunks/shadow_forward.glsl.js.map +1 -0
- package/dist/quality/DeviceClasses.d.ts +31 -0
- package/dist/quality/DeviceClasses.d.ts.map +1 -0
- package/dist/quality/DeviceClasses.js +83 -0
- package/dist/quality/DeviceClasses.js.map +1 -0
- package/dist/quality/DeviceProbe.d.ts +42 -0
- package/dist/quality/DeviceProbe.d.ts.map +1 -0
- package/dist/quality/DeviceProbe.js +83 -0
- package/dist/quality/DeviceProbe.js.map +1 -0
- package/dist/quality/FrameStats.d.ts +62 -0
- package/dist/quality/FrameStats.d.ts.map +1 -0
- package/dist/quality/FrameStats.js +220 -0
- package/dist/quality/FrameStats.js.map +1 -0
- package/dist/quality/PostprocessGuard.d.ts +49 -0
- package/dist/quality/PostprocessGuard.d.ts.map +1 -0
- package/dist/quality/PostprocessGuard.js +92 -0
- package/dist/quality/PostprocessGuard.js.map +1 -0
- package/dist/quality/QualityController.d.ts +93 -0
- package/dist/quality/QualityController.d.ts.map +1 -0
- package/dist/quality/QualityController.js +248 -0
- package/dist/quality/QualityController.js.map +1 -0
- package/dist/quality/QualityGovernor.d.ts +78 -0
- package/dist/quality/QualityGovernor.d.ts.map +1 -0
- package/dist/quality/QualityGovernor.js +170 -0
- package/dist/quality/QualityGovernor.js.map +1 -0
- package/dist/quality/QualityTier.d.ts +17 -0
- package/dist/quality/QualityTier.d.ts.map +1 -0
- package/dist/quality/QualityTier.js +23 -0
- package/dist/quality/QualityTier.js.map +1 -0
- package/dist/quality/RenderScaleController.d.ts +35 -0
- package/dist/quality/RenderScaleController.d.ts.map +1 -0
- package/dist/quality/RenderScaleController.js +57 -0
- package/dist/quality/RenderScaleController.js.map +1 -0
- package/dist/quality/RetentionPolicy.d.ts +11 -0
- package/dist/quality/RetentionPolicy.d.ts.map +1 -0
- package/dist/quality/RetentionPolicy.js +12 -0
- package/dist/quality/RetentionPolicy.js.map +1 -0
- package/dist/quality/TierResolver.d.ts +52 -0
- package/dist/quality/TierResolver.d.ts.map +1 -0
- package/dist/quality/TierResolver.js +155 -0
- package/dist/quality/TierResolver.js.map +1 -0
- package/dist/quality/liveTier.d.ts +23 -0
- package/dist/quality/liveTier.d.ts.map +1 -0
- package/dist/quality/liveTier.js +16 -0
- package/dist/quality/liveTier.js.map +1 -0
- package/dist/reference/BloomPass.d.ts +10 -0
- package/dist/reference/BloomPass.d.ts.map +1 -0
- package/dist/reference/BloomPass.js +18 -0
- package/dist/reference/BloomPass.js.map +1 -0
- package/dist/reference/DepthHazePass.d.ts +12 -0
- package/dist/reference/DepthHazePass.d.ts.map +1 -0
- package/dist/reference/DepthHazePass.js +20 -0
- package/dist/reference/DepthHazePass.js.map +1 -0
- package/dist/reference/EffectComposer.d.ts +110 -0
- package/dist/reference/EffectComposer.d.ts.map +1 -0
- package/dist/reference/EffectComposer.js +247 -0
- package/dist/reference/EffectComposer.js.map +1 -0
- package/dist/reference/FilmGrainPass.d.ts +9 -0
- package/dist/reference/FilmGrainPass.d.ts.map +1 -0
- package/dist/reference/FilmGrainPass.js +17 -0
- package/dist/reference/FilmGrainPass.js.map +1 -0
- package/dist/reference/PostProcessPass.d.ts +511 -0
- package/dist/reference/PostProcessPass.d.ts.map +1 -0
- package/dist/reference/PostProcessPass.js +2020 -0
- package/dist/reference/PostProcessPass.js.map +1 -0
- package/dist/reference/SSAOPass.d.ts +6 -0
- package/dist/reference/SSAOPass.d.ts.map +1 -0
- package/dist/reference/SSAOPass.js +18 -0
- package/dist/reference/SSAOPass.js.map +1 -0
- package/dist/reference/VignettePass.d.ts +10 -0
- package/dist/reference/VignettePass.d.ts.map +1 -0
- package/dist/reference/VignettePass.js +17 -0
- package/dist/reference/VignettePass.js.map +1 -0
- package/dist/reference/index.d.ts +15 -0
- package/dist/reference/index.d.ts.map +1 -0
- package/dist/reference/index.js +15 -0
- package/dist/reference/index.js.map +1 -0
- package/dist/renderer/Background.d.ts +49 -0
- package/dist/renderer/Background.d.ts.map +1 -0
- package/dist/renderer/Background.js +259 -0
- package/dist/renderer/Background.js.map +1 -0
- package/dist/renderer/CullingBatching.d.ts +55 -0
- package/dist/renderer/CullingBatching.d.ts.map +1 -0
- package/dist/renderer/CullingBatching.js +362 -0
- package/dist/renderer/CullingBatching.js.map +1 -0
- package/dist/renderer/DeviceLifecycle.d.ts +29 -0
- package/dist/renderer/DeviceLifecycle.d.ts.map +1 -0
- package/dist/renderer/DeviceLifecycle.js +48 -0
- package/dist/renderer/DeviceLifecycle.js.map +1 -0
- package/dist/renderer/FrameGraph.d.ts +96 -0
- package/dist/renderer/FrameGraph.d.ts.map +1 -0
- package/dist/renderer/FrameGraph.js +301 -0
- package/dist/renderer/FrameGraph.js.map +1 -0
- package/dist/renderer/InterleavedTransparentPass.d.ts +31 -0
- package/dist/renderer/InterleavedTransparentPass.d.ts.map +1 -0
- package/dist/renderer/InterleavedTransparentPass.js +65 -0
- package/dist/renderer/InterleavedTransparentPass.js.map +1 -0
- package/dist/renderer/PixelRatio.d.ts +64 -0
- package/dist/renderer/PixelRatio.d.ts.map +1 -0
- package/dist/renderer/PixelRatio.js +81 -0
- package/dist/renderer/PixelRatio.js.map +1 -0
- package/dist/renderer/PostprocessExecution.d.ts +82 -0
- package/dist/renderer/PostprocessExecution.d.ts.map +1 -0
- package/dist/renderer/PostprocessExecution.js +741 -0
- package/dist/renderer/PostprocessExecution.js.map +1 -0
- package/dist/renderer/Prd06ShaderWarmup.d.ts +32 -0
- package/dist/renderer/Prd06ShaderWarmup.d.ts.map +1 -0
- package/dist/renderer/Prd06ShaderWarmup.js +45 -0
- package/dist/renderer/Prd06ShaderWarmup.js.map +1 -0
- package/dist/renderer/RenderShared.d.ts +11 -0
- package/dist/renderer/RenderShared.d.ts.map +1 -0
- package/dist/renderer/RenderShared.js +47 -0
- package/dist/renderer/RenderShared.js.map +1 -0
- package/dist/renderer/RendererFactory.d.ts +3 -0
- package/dist/renderer/RendererFactory.d.ts.map +1 -0
- package/dist/renderer/RendererFactory.js +19 -0
- package/dist/renderer/RendererFactory.js.map +1 -0
- package/dist/renderer/RendererHost.d.ts +25 -0
- package/dist/renderer/RendererHost.d.ts.map +1 -0
- package/dist/renderer/RendererHost.js +4 -0
- package/dist/renderer/RendererHost.js.map +1 -0
- package/dist/renderer/SceneDepthCopyPass.d.ts +50 -0
- package/dist/renderer/SceneDepthCopyPass.d.ts.map +1 -0
- package/dist/renderer/SceneDepthCopyPass.js +124 -0
- package/dist/renderer/SceneDepthCopyPass.js.map +1 -0
- package/dist/renderer/ShadowOrchestration.d.ts +32 -0
- package/dist/renderer/ShadowOrchestration.d.ts.map +1 -0
- package/dist/renderer/ShadowOrchestration.js +491 -0
- package/dist/renderer/ShadowOrchestration.js.map +1 -0
- package/dist/renderer/SkinnedBounds.d.ts +6 -0
- package/dist/renderer/SkinnedBounds.d.ts.map +1 -0
- package/dist/renderer/SkinnedBounds.js +74 -0
- package/dist/renderer/SkinnedBounds.js.map +1 -0
- package/dist/renderer/coreOutputPostRoute.d.ts +40 -0
- package/dist/renderer/coreOutputPostRoute.d.ts.map +1 -0
- package/dist/renderer/coreOutputPostRoute.js +46 -0
- package/dist/renderer/coreOutputPostRoute.js.map +1 -0
- package/dist/renderer/postSkipped.d.ts +12 -0
- package/dist/renderer/postSkipped.d.ts.map +1 -0
- package/dist/renderer/postSkipped.js +54 -0
- package/dist/renderer/postSkipped.js.map +1 -0
- package/dist/renderer/qrSubFlags.d.ts +45 -0
- package/dist/renderer/qrSubFlags.d.ts.map +1 -0
- package/dist/renderer/qrSubFlags.js +130 -0
- package/dist/renderer/qrSubFlags.js.map +1 -0
- package/dist/resources/InstanceBuffer.d.ts +34 -0
- package/dist/resources/InstanceBuffer.d.ts.map +1 -0
- package/dist/resources/InstanceBuffer.js +96 -0
- package/dist/resources/InstanceBuffer.js.map +1 -0
- package/dist/resources/MorphTargetTexture.d.ts +53 -0
- package/dist/resources/MorphTargetTexture.d.ts.map +1 -0
- package/dist/resources/MorphTargetTexture.js +135 -0
- package/dist/resources/MorphTargetTexture.js.map +1 -0
- package/dist/resources/RenderTargetPool.d.ts +47 -0
- package/dist/resources/RenderTargetPool.d.ts.map +1 -0
- package/dist/resources/RenderTargetPool.js +113 -0
- package/dist/resources/RenderTargetPool.js.map +1 -0
- package/dist/resources/ResourceRegistry.d.ts +48 -0
- package/dist/resources/ResourceRegistry.d.ts.map +1 -0
- package/dist/resources/ResourceRegistry.js +95 -0
- package/dist/resources/ResourceRegistry.js.map +1 -0
- package/dist/resources/UniformBlock.d.ts +90 -0
- package/dist/resources/UniformBlock.d.ts.map +1 -0
- package/dist/resources/UniformBlock.js +184 -0
- package/dist/resources/UniformBlock.js.map +1 -0
- package/dist/shaders/camera-fade.glsl.d.ts +26 -0
- package/dist/shaders/camera-fade.glsl.d.ts.map +1 -0
- package/dist/shaders/camera-fade.glsl.js +109 -0
- package/dist/shaders/camera-fade.glsl.js.map +1 -0
- package/dist/shaders/chunks/contact_shadow.glsl.d.ts +12 -0
- package/dist/shaders/chunks/contact_shadow.glsl.d.ts.map +1 -0
- package/dist/shaders/chunks/contact_shadow.glsl.js +53 -0
- package/dist/shaders/chunks/contact_shadow.glsl.js.map +1 -0
- package/dist/shaders/chunks/lighting_ibl.glsl.d.ts +29 -0
- package/dist/shaders/chunks/lighting_ibl.glsl.d.ts.map +1 -0
- package/dist/shaders/chunks/lighting_ibl.glsl.js +122 -0
- package/dist/shaders/chunks/lighting_ibl.glsl.js.map +1 -0
- package/dist/shaders/chunks/lighting_mirrors.d.ts +18 -0
- package/dist/shaders/chunks/lighting_mirrors.d.ts.map +1 -0
- package/dist/shaders/chunks/lighting_mirrors.js +35 -0
- package/dist/shaders/chunks/lighting_mirrors.js.map +1 -0
- package/dist/shaders/chunks/lighting_punctual.glsl.d.ts +17 -0
- package/dist/shaders/chunks/lighting_punctual.glsl.d.ts.map +1 -0
- package/dist/shaders/chunks/lighting_punctual.glsl.js +197 -0
- package/dist/shaders/chunks/lighting_punctual.glsl.js.map +1 -0
- package/dist/shaders/chunks/sh9.glsl.d.ts +9 -0
- package/dist/shaders/chunks/sh9.glsl.d.ts.map +1 -0
- package/dist/shaders/chunks/sh9.glsl.js +41 -0
- package/dist/shaders/chunks/sh9.glsl.js.map +1 -0
- package/dist/shaders/chunks/shadow_caster.glsl.d.ts +10 -0
- package/dist/shaders/chunks/shadow_caster.glsl.d.ts.map +1 -0
- package/dist/shaders/chunks/shadow_caster.glsl.js +32 -0
- package/dist/shaders/chunks/shadow_caster.glsl.js.map +1 -0
- package/dist/shaders/chunks/shadow_receive.glsl.d.ts +13 -0
- package/dist/shaders/chunks/shadow_receive.glsl.d.ts.map +1 -0
- package/dist/shaders/chunks/shadow_receive.glsl.js +136 -0
- package/dist/shaders/chunks/shadow_receive.glsl.js.map +1 -0
- package/dist/shaders/debug-view.glsl.d.ts +18 -0
- package/dist/shaders/debug-view.glsl.d.ts.map +1 -0
- package/dist/shaders/debug-view.glsl.js +153 -0
- package/dist/shaders/debug-view.glsl.js.map +1 -0
- package/dist/shaders/deform/deform.glsl.d.ts +17 -0
- package/dist/shaders/deform/deform.glsl.d.ts.map +1 -0
- package/dist/shaders/deform/deform.glsl.js +99 -0
- package/dist/shaders/deform/deform.glsl.js.map +1 -0
- package/dist/shaders/deform/deform.wgsl.d.ts +15 -0
- package/dist/shaders/deform/deform.wgsl.d.ts.map +1 -0
- package/dist/shaders/deform/deform.wgsl.js +89 -0
- package/dist/shaders/deform/deform.wgsl.js.map +1 -0
- package/dist/shaders/deform/depthFeature.d.ts +22 -0
- package/dist/shaders/deform/depthFeature.d.ts.map +1 -0
- package/dist/shaders/deform/depthFeature.js +44 -0
- package/dist/shaders/deform/depthFeature.js.map +1 -0
- package/dist/shaders/deform/forwardFeature.d.ts +114 -0
- package/dist/shaders/deform/forwardFeature.d.ts.map +1 -0
- package/dist/shaders/deform/forwardFeature.js +300 -0
- package/dist/shaders/deform/forwardFeature.js.map +1 -0
- package/dist/shaders/deform/morph.glsl.d.ts +14 -0
- package/dist/shaders/deform/morph.glsl.d.ts.map +1 -0
- package/dist/shaders/deform/morph.glsl.js +45 -0
- package/dist/shaders/deform/morph.glsl.js.map +1 -0
- package/dist/shaders/deform/morph.wgsl.d.ts +21 -0
- package/dist/shaders/deform/morph.wgsl.d.ts.map +1 -0
- package/dist/shaders/deform/morph.wgsl.js +73 -0
- package/dist/shaders/deform/morph.wgsl.js.map +1 -0
- package/dist/shaders/deform/skinning.glsl.d.ts +8 -0
- package/dist/shaders/deform/skinning.glsl.d.ts.map +1 -0
- package/dist/shaders/deform/skinning.glsl.js +37 -0
- package/dist/shaders/deform/skinning.glsl.js.map +1 -0
- package/dist/shaders/deform/skinning.wgsl.d.ts +26 -0
- package/dist/shaders/deform/skinning.wgsl.d.ts.map +1 -0
- package/dist/shaders/deform/skinning.wgsl.js +58 -0
- package/dist/shaders/deform/skinning.wgsl.js.map +1 -0
- package/dist/shaders/deform/twins.d.ts +8 -0
- package/dist/shaders/deform/twins.d.ts.map +1 -0
- package/dist/shaders/deform/twins.js +20 -0
- package/dist/shaders/deform/twins.js.map +1 -0
- package/dist/shaders/lod-dither.glsl.d.ts +12 -0
- package/dist/shaders/lod-dither.glsl.d.ts.map +1 -0
- package/dist/shaders/lod-dither.glsl.js +101 -0
- package/dist/shaders/lod-dither.glsl.js.map +1 -0
- package/dist/shaders/physical/alpha_a2c.glsl.d.ts +19 -0
- package/dist/shaders/physical/alpha_a2c.glsl.d.ts.map +1 -0
- package/dist/shaders/physical/alpha_a2c.glsl.js +29 -0
- package/dist/shaders/physical/alpha_a2c.glsl.js.map +1 -0
- package/dist/shaders/physical/anisotropy.glsl.d.ts +23 -0
- package/dist/shaders/physical/anisotropy.glsl.d.ts.map +1 -0
- package/dist/shaders/physical/anisotropy.glsl.js +116 -0
- package/dist/shaders/physical/anisotropy.glsl.js.map +1 -0
- package/dist/shaders/physical/bsdf_lobes_common.glsl.d.ts +25 -0
- package/dist/shaders/physical/bsdf_lobes_common.glsl.d.ts.map +1 -0
- package/dist/shaders/physical/bsdf_lobes_common.glsl.js +95 -0
- package/dist/shaders/physical/bsdf_lobes_common.glsl.js.map +1 -0
- package/dist/shaders/physical/clearcoat.glsl.d.ts +23 -0
- package/dist/shaders/physical/clearcoat.glsl.d.ts.map +1 -0
- package/dist/shaders/physical/clearcoat.glsl.js +70 -0
- package/dist/shaders/physical/clearcoat.glsl.js.map +1 -0
- package/dist/shaders/physical/debug_view.glsl.d.ts +19 -0
- package/dist/shaders/physical/debug_view.glsl.d.ts.map +1 -0
- package/dist/shaders/physical/debug_view.glsl.js +76 -0
- package/dist/shaders/physical/debug_view.glsl.js.map +1 -0
- package/dist/shaders/physical/dispersion.glsl.d.ts +18 -0
- package/dist/shaders/physical/dispersion.glsl.d.ts.map +1 -0
- package/dist/shaders/physical/dispersion.glsl.js +67 -0
- package/dist/shaders/physical/dispersion.glsl.js.map +1 -0
- package/dist/shaders/physical/emissive_strength.glsl.d.ts +18 -0
- package/dist/shaders/physical/emissive_strength.glsl.d.ts.map +1 -0
- package/dist/shaders/physical/emissive_strength.glsl.js +20 -0
- package/dist/shaders/physical/emissive_strength.glsl.js.map +1 -0
- package/dist/shaders/physical/index.d.ts +27 -0
- package/dist/shaders/physical/index.d.ts.map +1 -0
- package/dist/shaders/physical/index.js +69 -0
- package/dist/shaders/physical/index.js.map +1 -0
- package/dist/shaders/physical/iridescence.glsl.d.ts +25 -0
- package/dist/shaders/physical/iridescence.glsl.d.ts.map +1 -0
- package/dist/shaders/physical/iridescence.glsl.js +186 -0
- package/dist/shaders/physical/iridescence.glsl.js.map +1 -0
- package/dist/shaders/physical/lobe_calls.glsl.d.ts +83 -0
- package/dist/shaders/physical/lobe_calls.glsl.d.ts.map +1 -0
- package/dist/shaders/physical/lobe_calls.glsl.js +397 -0
- package/dist/shaders/physical/lobe_calls.glsl.js.map +1 -0
- package/dist/shaders/physical/sheen.glsl.d.ts +24 -0
- package/dist/shaders/physical/sheen.glsl.d.ts.map +1 -0
- package/dist/shaders/physical/sheen.glsl.js +108 -0
- package/dist/shaders/physical/sheen.glsl.js.map +1 -0
- package/dist/shaders/physical/specular_ior.glsl.d.ts +20 -0
- package/dist/shaders/physical/specular_ior.glsl.d.ts.map +1 -0
- package/dist/shaders/physical/specular_ior.glsl.js +64 -0
- package/dist/shaders/physical/specular_ior.glsl.js.map +1 -0
- package/dist/shaders/physical/tangent_frame.glsl.d.ts +27 -0
- package/dist/shaders/physical/tangent_frame.glsl.d.ts.map +1 -0
- package/dist/shaders/physical/tangent_frame.glsl.js +71 -0
- package/dist/shaders/physical/tangent_frame.glsl.js.map +1 -0
- package/dist/shaders/physical/transmission.glsl.d.ts +25 -0
- package/dist/shaders/physical/transmission.glsl.d.ts.map +1 -0
- package/dist/shaders/physical/transmission.glsl.js +204 -0
- package/dist/shaders/physical/transmission.glsl.js.map +1 -0
- package/dist/shaders/physical/transmission_copy.glsl.d.ts +15 -0
- package/dist/shaders/physical/transmission_copy.glsl.d.ts.map +1 -0
- package/dist/shaders/physical/transmission_copy.glsl.js +33 -0
- package/dist/shaders/physical/transmission_copy.glsl.js.map +1 -0
- package/dist/shaders/physical/unlit.glsl.d.ts +17 -0
- package/dist/shaders/physical/unlit.glsl.d.ts.map +1 -0
- package/dist/shaders/physical/unlit.glsl.js +19 -0
- package/dist/shaders/physical/unlit.glsl.js.map +1 -0
- package/dist/shaders/physical/uv_transform.glsl.d.ts +18 -0
- package/dist/shaders/physical/uv_transform.glsl.d.ts.map +1 -0
- package/dist/shaders/physical/uv_transform.glsl.js +30 -0
- package/dist/shaders/physical/uv_transform.glsl.js.map +1 -0
- package/dist/shaders/physical/volume.glsl.d.ts +19 -0
- package/dist/shaders/physical/volume.glsl.d.ts.map +1 -0
- package/dist/shaders/physical/volume.glsl.js +47 -0
- package/dist/shaders/physical/volume.glsl.js.map +1 -0
- package/dist/shaders/physical-wgsl/alpha_a2c.wgsl.d.ts +8 -0
- package/dist/shaders/physical-wgsl/alpha_a2c.wgsl.d.ts.map +1 -0
- package/dist/shaders/physical-wgsl/alpha_a2c.wgsl.js +26 -0
- package/dist/shaders/physical-wgsl/alpha_a2c.wgsl.js.map +1 -0
- package/dist/shaders/physical-wgsl/anisotropy.wgsl.d.ts +10 -0
- package/dist/shaders/physical-wgsl/anisotropy.wgsl.d.ts.map +1 -0
- package/dist/shaders/physical-wgsl/anisotropy.wgsl.js +97 -0
- package/dist/shaders/physical-wgsl/anisotropy.wgsl.js.map +1 -0
- package/dist/shaders/physical-wgsl/bsdf_lobes_common.wgsl.d.ts +11 -0
- package/dist/shaders/physical-wgsl/bsdf_lobes_common.wgsl.d.ts.map +1 -0
- package/dist/shaders/physical-wgsl/bsdf_lobes_common.wgsl.js +76 -0
- package/dist/shaders/physical-wgsl/bsdf_lobes_common.wgsl.js.map +1 -0
- package/dist/shaders/physical-wgsl/clearcoat.wgsl.d.ts +9 -0
- package/dist/shaders/physical-wgsl/clearcoat.wgsl.d.ts.map +1 -0
- package/dist/shaders/physical-wgsl/clearcoat.wgsl.js +56 -0
- package/dist/shaders/physical-wgsl/clearcoat.wgsl.js.map +1 -0
- package/dist/shaders/physical-wgsl/debug_view.wgsl.d.ts +10 -0
- package/dist/shaders/physical-wgsl/debug_view.wgsl.d.ts.map +1 -0
- package/dist/shaders/physical-wgsl/debug_view.wgsl.js +71 -0
- package/dist/shaders/physical-wgsl/debug_view.wgsl.js.map +1 -0
- package/dist/shaders/physical-wgsl/dispersion.wgsl.d.ts +10 -0
- package/dist/shaders/physical-wgsl/dispersion.wgsl.d.ts.map +1 -0
- package/dist/shaders/physical-wgsl/dispersion.wgsl.js +51 -0
- package/dist/shaders/physical-wgsl/dispersion.wgsl.js.map +1 -0
- package/dist/shaders/physical-wgsl/emissive_strength.wgsl.d.ts +9 -0
- package/dist/shaders/physical-wgsl/emissive_strength.wgsl.d.ts.map +1 -0
- package/dist/shaders/physical-wgsl/emissive_strength.wgsl.js +15 -0
- package/dist/shaders/physical-wgsl/emissive_strength.wgsl.js.map +1 -0
- package/dist/shaders/physical-wgsl/index.d.ts +35 -0
- package/dist/shaders/physical-wgsl/index.d.ts.map +1 -0
- package/dist/shaders/physical-wgsl/index.js +51 -0
- package/dist/shaders/physical-wgsl/index.js.map +1 -0
- package/dist/shaders/physical-wgsl/iridescence.wgsl.d.ts +9 -0
- package/dist/shaders/physical-wgsl/iridescence.wgsl.d.ts.map +1 -0
- package/dist/shaders/physical-wgsl/iridescence.wgsl.js +162 -0
- package/dist/shaders/physical-wgsl/iridescence.wgsl.js.map +1 -0
- package/dist/shaders/physical-wgsl/sheen.wgsl.d.ts +9 -0
- package/dist/shaders/physical-wgsl/sheen.wgsl.d.ts.map +1 -0
- package/dist/shaders/physical-wgsl/sheen.wgsl.js +85 -0
- package/dist/shaders/physical-wgsl/sheen.wgsl.js.map +1 -0
- package/dist/shaders/physical-wgsl/specular_ior.wgsl.d.ts +10 -0
- package/dist/shaders/physical-wgsl/specular_ior.wgsl.d.ts.map +1 -0
- package/dist/shaders/physical-wgsl/specular_ior.wgsl.js +47 -0
- package/dist/shaders/physical-wgsl/specular_ior.wgsl.js.map +1 -0
- package/dist/shaders/physical-wgsl/tangent_frame.wgsl.d.ts +11 -0
- package/dist/shaders/physical-wgsl/tangent_frame.wgsl.d.ts.map +1 -0
- package/dist/shaders/physical-wgsl/tangent_frame.wgsl.js +57 -0
- package/dist/shaders/physical-wgsl/tangent_frame.wgsl.js.map +1 -0
- package/dist/shaders/physical-wgsl/transmission.wgsl.d.ts +14 -0
- package/dist/shaders/physical-wgsl/transmission.wgsl.d.ts.map +1 -0
- package/dist/shaders/physical-wgsl/transmission.wgsl.js +159 -0
- package/dist/shaders/physical-wgsl/transmission.wgsl.js.map +1 -0
- package/dist/shaders/physical-wgsl/unlit.wgsl.d.ts +8 -0
- package/dist/shaders/physical-wgsl/unlit.wgsl.d.ts.map +1 -0
- package/dist/shaders/physical-wgsl/unlit.wgsl.js +13 -0
- package/dist/shaders/physical-wgsl/unlit.wgsl.js.map +1 -0
- package/dist/shaders/physical-wgsl/uv_transform.wgsl.d.ts +10 -0
- package/dist/shaders/physical-wgsl/uv_transform.wgsl.d.ts.map +1 -0
- package/dist/shaders/physical-wgsl/uv_transform.wgsl.js +24 -0
- package/dist/shaders/physical-wgsl/uv_transform.wgsl.js.map +1 -0
- package/dist/shaders/physical-wgsl/volume.wgsl.d.ts +10 -0
- package/dist/shaders/physical-wgsl/volume.wgsl.d.ts.map +1 -0
- package/dist/shaders/physical-wgsl/volume.wgsl.js +35 -0
- package/dist/shaders/physical-wgsl/volume.wgsl.js.map +1 -0
- package/dist/shadows/DirectionalCascadeFitter.d.ts +97 -0
- package/dist/shadows/DirectionalCascadeFitter.d.ts.map +1 -0
- package/dist/shadows/DirectionalCascadeFitter.js +372 -0
- package/dist/shadows/DirectionalCascadeFitter.js.map +1 -0
- package/dist/shadows/Prd02DepthShaderLibrary.d.ts +77 -0
- package/dist/shadows/Prd02DepthShaderLibrary.d.ts.map +1 -0
- package/dist/shadows/Prd02DepthShaderLibrary.js +381 -0
- package/dist/shadows/Prd02DepthShaderLibrary.js.map +1 -0
- package/dist/shadows/Prd02ReceiveShadowContributor.d.ts +20 -0
- package/dist/shadows/Prd02ReceiveShadowContributor.d.ts.map +1 -0
- package/dist/shadows/Prd02ReceiveShadowContributor.js +20 -0
- package/dist/shadows/Prd02ReceiveShadowContributor.js.map +1 -0
- package/dist/shadows/Prd02ShadowBridge.d.ts +111 -0
- package/dist/shadows/Prd02ShadowBridge.d.ts.map +1 -0
- package/dist/shadows/Prd02ShadowBridge.js +267 -0
- package/dist/shadows/Prd02ShadowBridge.js.map +1 -0
- package/dist/shadows/Prd02ShadowFilter.d.ts +29 -0
- package/dist/shadows/Prd02ShadowFilter.d.ts.map +1 -0
- package/dist/shadows/Prd02ShadowFilter.js +35 -0
- package/dist/shadows/Prd02ShadowFilter.js.map +1 -0
- package/dist/shadows/Prd02ShadowsContributor.d.ts +44 -0
- package/dist/shadows/Prd02ShadowsContributor.d.ts.map +1 -0
- package/dist/shadows/Prd02ShadowsContributor.js +197 -0
- package/dist/shadows/Prd02ShadowsContributor.js.map +1 -0
- package/dist/shadows/ShadowAtlas.d.ts +59 -0
- package/dist/shadows/ShadowAtlas.d.ts.map +1 -0
- package/dist/shadows/ShadowAtlas.js +137 -0
- package/dist/shadows/ShadowAtlas.js.map +1 -0
- package/dist/shadows/ShadowDebugViews.d.ts +5 -0
- package/dist/shadows/ShadowDebugViews.d.ts.map +1 -1
- package/dist/shadows/ShadowDebugViews.js +15 -10
- package/dist/shadows/ShadowDebugViews.js.map +1 -1
- package/dist/shadows/ShadowFrameBinding.d.ts +18 -0
- package/dist/shadows/ShadowFrameBinding.d.ts.map +1 -0
- package/dist/shadows/ShadowFrameBinding.js +52 -0
- package/dist/shadows/ShadowFrameBinding.js.map +1 -0
- package/dist/shadows/ShadowSystem.d.ts +125 -0
- package/dist/shadows/ShadowSystem.d.ts.map +1 -0
- package/dist/shadows/ShadowSystem.js +293 -0
- package/dist/shadows/ShadowSystem.js.map +1 -0
- package/dist/textures/TextureBudget.d.ts +42 -0
- package/dist/textures/TextureBudget.d.ts.map +1 -0
- package/dist/textures/TextureBudget.js +180 -0
- package/dist/textures/TextureBudget.js.map +1 -0
- package/dist/vfx/BeamPass.d.ts +42 -0
- package/dist/vfx/BeamPass.d.ts.map +1 -0
- package/dist/vfx/BeamPass.js +249 -0
- package/dist/vfx/BeamPass.js.map +1 -0
- package/dist/vfx/BlendFallback.d.ts +19 -0
- package/dist/vfx/BlendFallback.d.ts.map +1 -0
- package/dist/vfx/BlendFallback.js +73 -0
- package/dist/vfx/BlendFallback.js.map +1 -0
- package/dist/vfx/DecalBatch.d.ts +120 -0
- package/dist/vfx/DecalBatch.d.ts.map +1 -0
- package/dist/vfx/DecalBatch.js +234 -0
- package/dist/vfx/DecalBatch.js.map +1 -0
- package/dist/vfx/DecalPass.d.ts +63 -0
- package/dist/vfx/DecalPass.d.ts.map +1 -0
- package/dist/vfx/DecalPass.js +159 -0
- package/dist/vfx/DecalPass.js.map +1 -0
- package/dist/vfx/LowResParticles.d.ts +31 -0
- package/dist/vfx/LowResParticles.d.ts.map +1 -0
- package/dist/vfx/LowResParticles.js +151 -0
- package/dist/vfx/LowResParticles.js.map +1 -0
- package/dist/vfx/MeshParticleBatch.d.ts +49 -0
- package/dist/vfx/MeshParticleBatch.d.ts.map +1 -0
- package/dist/vfx/MeshParticleBatch.js +184 -0
- package/dist/vfx/MeshParticleBatch.js.map +1 -0
- package/dist/vfx/MeshParticlePass.d.ts +28 -0
- package/dist/vfx/MeshParticlePass.d.ts.map +1 -0
- package/dist/vfx/MeshParticlePass.js +150 -0
- package/dist/vfx/MeshParticlePass.js.map +1 -0
- package/dist/vfx/ParticleBatchPass.d.ts +61 -0
- package/dist/vfx/ParticleBatchPass.d.ts.map +1 -0
- package/dist/vfx/ParticleBatchPass.js +320 -0
- package/dist/vfx/ParticleBatchPass.js.map +1 -0
- package/dist/vfx/ParticleGpuSim.d.ts +85 -0
- package/dist/vfx/ParticleGpuSim.d.ts.map +1 -0
- package/dist/vfx/ParticleGpuSim.js +301 -0
- package/dist/vfx/ParticleGpuSim.js.map +1 -0
- package/dist/vfx/ParticleInstanceLayout.d.ts +38 -0
- package/dist/vfx/ParticleInstanceLayout.d.ts.map +1 -0
- package/dist/vfx/ParticleInstanceLayout.js +105 -0
- package/dist/vfx/ParticleInstanceLayout.js.map +1 -0
- package/dist/vfx/ParticleSort.d.ts +21 -0
- package/dist/vfx/ParticleSort.d.ts.map +1 -0
- package/dist/vfx/ParticleSort.js +80 -0
- package/dist/vfx/ParticleSort.js.map +1 -0
- package/dist/vfx/ProceduralVolumeEmitter.d.ts +90 -0
- package/dist/vfx/ProceduralVolumeEmitter.d.ts.map +1 -0
- package/dist/vfx/ProceduralVolumeEmitter.js +155 -0
- package/dist/vfx/ProceduralVolumeEmitter.js.map +1 -0
- package/dist/vfx/RibbonBatch.d.ts +71 -0
- package/dist/vfx/RibbonBatch.d.ts.map +1 -0
- package/dist/vfx/RibbonBatch.js +234 -0
- package/dist/vfx/RibbonBatch.js.map +1 -0
- package/dist/vfx/RibbonPass.d.ts +21 -0
- package/dist/vfx/RibbonPass.d.ts.map +1 -0
- package/dist/vfx/RibbonPass.js +108 -0
- package/dist/vfx/RibbonPass.js.map +1 -0
- package/dist/vfx/SceneDepthAdapter.d.ts +28 -0
- package/dist/vfx/SceneDepthAdapter.d.ts.map +1 -0
- package/dist/vfx/SceneDepthAdapter.js +70 -0
- package/dist/vfx/SceneDepthAdapter.js.map +1 -0
- package/dist/vfx/VfxAtlas.d.ts +68 -0
- package/dist/vfx/VfxAtlas.d.ts.map +1 -0
- package/dist/vfx/VfxAtlas.js +106 -0
- package/dist/vfx/VfxAtlas.js.map +1 -0
- package/dist/vfx/contributors.d.ts +73 -0
- package/dist/vfx/contributors.d.ts.map +1 -0
- package/dist/vfx/contributors.js +615 -0
- package/dist/vfx/contributors.js.map +1 -0
- package/dist/vfx/decalLighting.d.ts +8 -0
- package/dist/vfx/decalLighting.d.ts.map +1 -0
- package/dist/vfx/decalLighting.js +53 -0
- package/dist/vfx/decalLighting.js.map +1 -0
- package/dist/vfx/depthSampler.d.ts +3 -0
- package/dist/vfx/depthSampler.d.ts.map +1 -0
- package/dist/vfx/depthSampler.js +10 -0
- package/dist/vfx/depthSampler.js.map +1 -0
- package/dist/vfx/prd07FeaturePars.d.ts +12 -0
- package/dist/vfx/prd07FeaturePars.d.ts.map +1 -0
- package/dist/vfx/prd07FeaturePars.js +54 -0
- package/dist/vfx/prd07FeaturePars.js.map +1 -0
- package/dist/vfx/shaders/beam.glsl.d.ts +11 -0
- package/dist/vfx/shaders/beam.glsl.d.ts.map +1 -0
- package/dist/vfx/shaders/beam.glsl.js +89 -0
- package/dist/vfx/shaders/beam.glsl.js.map +1 -0
- package/dist/vfx/shaders/decal.glsl.d.ts +14 -0
- package/dist/vfx/shaders/decal.glsl.d.ts.map +1 -0
- package/dist/vfx/shaders/decal.glsl.js +157 -0
- package/dist/vfx/shaders/decal.glsl.js.map +1 -0
- package/dist/vfx/shaders/gpu-sim.glsl.d.ts +5 -0
- package/dist/vfx/shaders/gpu-sim.glsl.d.ts.map +1 -0
- package/dist/vfx/shaders/gpu-sim.glsl.js +177 -0
- package/dist/vfx/shaders/gpu-sim.glsl.js.map +1 -0
- package/dist/vfx/shaders/lowresComposite.glsl.d.ts +9 -0
- package/dist/vfx/shaders/lowresComposite.glsl.d.ts.map +1 -0
- package/dist/vfx/shaders/lowresComposite.glsl.js +64 -0
- package/dist/vfx/shaders/lowresComposite.glsl.js.map +1 -0
- package/dist/vfx/shaders/mesh-particle.glsl.d.ts +4 -0
- package/dist/vfx/shaders/mesh-particle.glsl.d.ts.map +1 -0
- package/dist/vfx/shaders/mesh-particle.glsl.js +55 -0
- package/dist/vfx/shaders/mesh-particle.glsl.js.map +1 -0
- package/dist/vfx/shaders/particle.glsl.d.ts +24 -0
- package/dist/vfx/shaders/particle.glsl.d.ts.map +1 -0
- package/dist/vfx/shaders/particle.glsl.js +215 -0
- package/dist/vfx/shaders/particle.glsl.js.map +1 -0
- package/dist/vfx/shaders/ribbon.glsl.d.ts +9 -0
- package/dist/vfx/shaders/ribbon.glsl.d.ts.map +1 -0
- package/dist/vfx/shaders/ribbon.glsl.js +60 -0
- package/dist/vfx/shaders/ribbon.glsl.js.map +1 -0
- package/dist/vfx/shaders/volume.glsl.d.ts +5 -0
- package/dist/vfx/shaders/volume.glsl.d.ts.map +1 -0
- package/dist/vfx/shaders/volume.glsl.js +52 -0
- package/dist/vfx/shaders/volume.glsl.js.map +1 -0
- package/dist/webgl2/ContextLifecycle.d.ts +43 -0
- package/dist/webgl2/ContextLifecycle.d.ts.map +1 -0
- package/dist/webgl2/ContextLifecycle.js +189 -0
- package/dist/webgl2/ContextLifecycle.js.map +1 -0
- package/dist/webgl2/Counters.d.ts +58 -0
- package/dist/webgl2/Counters.d.ts.map +1 -0
- package/dist/webgl2/Counters.js +207 -0
- package/dist/webgl2/Counters.js.map +1 -0
- package/dist/webgl2/DeviceHost.d.ts +41 -0
- package/dist/webgl2/DeviceHost.d.ts.map +1 -0
- package/dist/webgl2/DeviceHost.js +3 -0
- package/dist/webgl2/DeviceHost.js.map +1 -0
- package/dist/webgl2/LegacyPost.d.ts +279 -0
- package/dist/webgl2/LegacyPost.d.ts.map +1 -0
- package/dist/webgl2/LegacyPost.js +2477 -0
- package/dist/webgl2/LegacyPost.js.map +1 -0
- package/dist/webgl2/MultiDraw.d.ts +96 -0
- package/dist/webgl2/MultiDraw.d.ts.map +1 -0
- package/dist/webgl2/MultiDraw.js +716 -0
- package/dist/webgl2/MultiDraw.js.map +1 -0
- package/dist/webgl2/Probe.d.ts +27 -0
- package/dist/webgl2/Probe.d.ts.map +1 -0
- package/dist/webgl2/Probe.js +303 -0
- package/dist/webgl2/Probe.js.map +1 -0
- package/dist/webgl2/Samplers.d.ts +20 -0
- package/dist/webgl2/Samplers.d.ts.map +1 -0
- package/dist/webgl2/Samplers.js +179 -0
- package/dist/webgl2/Samplers.js.map +1 -0
- package/dist/webgl2/TextureFormats.d.ts +48 -0
- package/dist/webgl2/TextureFormats.d.ts.map +1 -0
- package/dist/webgl2/TextureFormats.js +185 -0
- package/dist/webgl2/TextureFormats.js.map +1 -0
- package/dist/webgl2/TextureUpload.d.ts +38 -0
- package/dist/webgl2/TextureUpload.d.ts.map +1 -0
- package/dist/webgl2/TextureUpload.js +346 -0
- package/dist/webgl2/TextureUpload.js.map +1 -0
- package/dist/webgpu/WebGPUBuffer.d.ts +1 -0
- package/dist/webgpu/WebGPUBuffer.d.ts.map +1 -1
- package/dist/webgpu/WebGPUCompute.d.ts +1 -0
- package/dist/webgpu/WebGPUCompute.d.ts.map +1 -1
- package/dist/webgpu/WebGPUCompute.js +1 -0
- package/dist/webgpu/WebGPUCompute.js.map +1 -1
- package/dist/webgpu/WebGPUPipelineCache.d.ts +4 -0
- package/dist/webgpu/WebGPUPipelineCache.d.ts.map +1 -1
- package/dist/webgpu/WebGPUPipelineCache.js +4 -0
- package/dist/webgpu/WebGPUPipelineCache.js.map +1 -1
- package/dist/webgpu/WebGPUPostShaders.d.ts.map +1 -1
- package/dist/webgpu/WebGPUPostShaders.js +33 -2
- package/dist/webgpu/WebGPUPostShaders.js.map +1 -1
- package/dist/webgpu/WebGPUTexture.d.ts +1 -0
- package/dist/webgpu/WebGPUTexture.d.ts.map +1 -1
- package/dist/webgpu/WebGPUTexture.js.map +1 -1
- package/dist/world/chunks.d.ts +15 -0
- package/dist/world/chunks.d.ts.map +1 -0
- package/dist/world/chunks.js +56 -0
- package/dist/world/chunks.js.map +1 -0
- package/dist/world/index.d.ts +38 -0
- package/dist/world/index.d.ts.map +1 -0
- package/dist/world/index.js +39 -0
- package/dist/world/index.js.map +1 -0
- package/dist/world/shared/shaders/worldLightFallback.d.ts +12 -0
- package/dist/world/shared/shaders/worldLightFallback.d.ts.map +1 -0
- package/dist/world/shared/shaders/worldLightFallback.js +82 -0
- package/dist/world/shared/shaders/worldLightFallback.js.map +1 -0
- package/dist/world/space/PlanetMaterial.d.ts +24 -0
- package/dist/world/space/PlanetMaterial.d.ts.map +1 -0
- package/dist/world/space/PlanetMaterial.js +82 -0
- package/dist/world/space/PlanetMaterial.js.map +1 -0
- package/dist/world/space/SpaceSkyBake.d.ts +46 -0
- package/dist/world/space/SpaceSkyBake.d.ts.map +1 -0
- package/dist/world/space/SpaceSkyBake.js +145 -0
- package/dist/world/space/SpaceSkyBake.js.map +1 -0
- package/dist/world/space/shaders/planet.d.ts +8 -0
- package/dist/world/space/shaders/planet.d.ts.map +1 -0
- package/dist/world/space/shaders/planet.js +55 -0
- package/dist/world/space/shaders/planet.js.map +1 -0
- package/dist/world/space/shaders/spaceBake.d.ts +9 -0
- package/dist/world/space/shaders/spaceBake.d.ts.map +1 -0
- package/dist/world/space/shaders/spaceBake.js +102 -0
- package/dist/world/space/shaders/spaceBake.js.map +1 -0
- package/dist/world/terrain/SplatBake.d.ts +76 -0
- package/dist/world/terrain/SplatBake.d.ts.map +1 -0
- package/dist/world/terrain/SplatBake.js +308 -0
- package/dist/world/terrain/SplatBake.js.map +1 -0
- package/dist/world/terrain/TerrainCdlod.d.ts +67 -0
- package/dist/world/terrain/TerrainCdlod.d.ts.map +1 -0
- package/dist/world/terrain/TerrainCdlod.js +115 -0
- package/dist/world/terrain/TerrainCdlod.js.map +1 -0
- package/dist/world/terrain/TerrainHeightTexture.d.ts +44 -0
- package/dist/world/terrain/TerrainHeightTexture.d.ts.map +1 -0
- package/dist/world/terrain/TerrainHeightTexture.js +173 -0
- package/dist/world/terrain/TerrainHeightTexture.js.map +1 -0
- package/dist/world/terrain/TerrainPatchGeometry.d.ts +18 -0
- package/dist/world/terrain/TerrainPatchGeometry.d.ts.map +1 -0
- package/dist/world/terrain/TerrainPatchGeometry.js +40 -0
- package/dist/world/terrain/TerrainPatchGeometry.js.map +1 -0
- package/dist/world/terrain/shaders/terrain.vert.glsl.d.ts +19 -0
- package/dist/world/terrain/shaders/terrain.vert.glsl.d.ts.map +1 -0
- package/dist/world/terrain/shaders/terrain.vert.glsl.js +162 -0
- package/dist/world/terrain/shaders/terrain.vert.glsl.js.map +1 -0
- package/dist/world/terrain/shaders/terrainCdlod.d.ts +23 -0
- package/dist/world/terrain/shaders/terrainCdlod.d.ts.map +1 -0
- package/dist/world/terrain/shaders/terrainCdlod.js +110 -0
- package/dist/world/terrain/shaders/terrainCdlod.js.map +1 -0
- package/dist/world/terrain/shaders/terrainSplat.d.ts +26 -0
- package/dist/world/terrain/shaders/terrainSplat.d.ts.map +1 -0
- package/dist/world/terrain/shaders/terrainSplat.js +181 -0
- package/dist/world/terrain/shaders/terrainSplat.js.map +1 -0
- package/dist/world/vegetation/FoliageMaterial.d.ts +14 -0
- package/dist/world/vegetation/FoliageMaterial.d.ts.map +1 -0
- package/dist/world/vegetation/FoliageMaterial.js +107 -0
- package/dist/world/vegetation/FoliageMaterial.js.map +1 -0
- package/dist/world/vegetation/GrassField.d.ts +43 -0
- package/dist/world/vegetation/GrassField.d.ts.map +1 -0
- package/dist/world/vegetation/GrassField.js +68 -0
- package/dist/world/vegetation/GrassField.js.map +1 -0
- package/dist/world/vegetation/ImpostorMaterial.d.ts +20 -0
- package/dist/world/vegetation/ImpostorMaterial.d.ts.map +1 -0
- package/dist/world/vegetation/ImpostorMaterial.js +80 -0
- package/dist/world/vegetation/ImpostorMaterial.js.map +1 -0
- package/dist/world/vegetation/InstanceChunkGrid.d.ts +67 -0
- package/dist/world/vegetation/InstanceChunkGrid.d.ts.map +1 -0
- package/dist/world/vegetation/InstanceChunkGrid.js +150 -0
- package/dist/world/vegetation/InstanceChunkGrid.js.map +1 -0
- package/dist/world/vegetation/WindCpu.d.ts +19 -0
- package/dist/world/vegetation/WindCpu.d.ts.map +1 -0
- package/dist/world/vegetation/WindCpu.js +43 -0
- package/dist/world/vegetation/WindCpu.js.map +1 -0
- package/dist/world/vegetation/WindField.d.ts +42 -0
- package/dist/world/vegetation/WindField.d.ts.map +1 -0
- package/dist/world/vegetation/WindField.js +154 -0
- package/dist/world/vegetation/WindField.js.map +1 -0
- package/dist/world/vegetation/shaders/foliage.d.ts +8 -0
- package/dist/world/vegetation/shaders/foliage.d.ts.map +1 -0
- package/dist/world/vegetation/shaders/foliage.js +104 -0
- package/dist/world/vegetation/shaders/foliage.js.map +1 -0
- package/dist/world/vegetation/shaders/grass.d.ts +10 -0
- package/dist/world/vegetation/shaders/grass.d.ts.map +1 -0
- package/dist/world/vegetation/shaders/grass.js +79 -0
- package/dist/world/vegetation/shaders/grass.js.map +1 -0
- package/dist/world/vegetation/shaders/impostor.d.ts +9 -0
- package/dist/world/vegetation/shaders/impostor.d.ts.map +1 -0
- package/dist/world/vegetation/shaders/impostor.js +97 -0
- package/dist/world/vegetation/shaders/impostor.js.map +1 -0
- package/dist/world/vegetation/shaders/wind.d.ts +9 -0
- package/dist/world/vegetation/shaders/wind.d.ts.map +1 -0
- package/dist/world/vegetation/shaders/wind.js +103 -0
- package/dist/world/vegetation/shaders/wind.js.map +1 -0
- package/dist/world/water/GerstnerWaves.d.ts +65 -0
- package/dist/world/water/GerstnerWaves.d.ts.map +1 -0
- package/dist/world/water/GerstnerWaves.js +182 -0
- package/dist/world/water/GerstnerWaves.js.map +1 -0
- package/dist/world/water/ReflectionViewPass.d.ts +46 -0
- package/dist/world/water/ReflectionViewPass.d.ts.map +1 -0
- package/dist/world/water/ReflectionViewPass.js +85 -0
- package/dist/world/water/ReflectionViewPass.js.map +1 -0
- package/dist/world/water/SceneCopyFallback.d.ts +21 -0
- package/dist/world/water/SceneCopyFallback.d.ts.map +1 -0
- package/dist/world/water/SceneCopyFallback.js +150 -0
- package/dist/world/water/SceneCopyFallback.js.map +1 -0
- package/dist/world/water/UnderwaterState.d.ts +25 -0
- package/dist/world/water/UnderwaterState.d.ts.map +1 -0
- package/dist/world/water/UnderwaterState.js +134 -0
- package/dist/world/water/UnderwaterState.js.map +1 -0
- package/dist/world/water/WaterMaterial.d.ts +23 -0
- package/dist/world/water/WaterMaterial.d.ts.map +1 -0
- package/dist/world/water/WaterMaterial.js +129 -0
- package/dist/world/water/WaterMaterial.js.map +1 -0
- package/dist/world/water/shaders/caustics.d.ts +13 -0
- package/dist/world/water/shaders/caustics.d.ts.map +1 -0
- package/dist/world/water/shaders/caustics.js +103 -0
- package/dist/world/water/shaders/caustics.js.map +1 -0
- package/dist/world/water/shaders/gerstner.d.ts +9 -0
- package/dist/world/water/shaders/gerstner.d.ts.map +1 -0
- package/dist/world/water/shaders/gerstner.js +100 -0
- package/dist/world/water/shaders/gerstner.js.map +1 -0
- package/dist/world/water/shaders/water.d.ts +12 -0
- package/dist/world/water/shaders/water.d.ts.map +1 -0
- package/dist/world/water/shaders/water.js +112 -0
- package/dist/world/water/shaders/water.js.map +1 -0
- package/package.json +32 -11
package/dist/WebGL2Device.js
CHANGED
|
@@ -7,8 +7,50 @@ import {} from "./VertexFormat.js";
|
|
|
7
7
|
import { WebGL2StateCache } from "./WebGL2StateCache.js";
|
|
8
8
|
import { BLOOM_BRIGHT_LUT_HEIGHT, BLOOM_BRIGHT_LUT_WIDTH, BLOOM_COMPOSITE_LUT_SIZE, OUTLINE_BLEND_LUT_WIDTH, OUTLINE_LIMB_RADIX, createOutlineBlendLut, createOutlineGradientBound, createBloomBrightThresholdLut, createBloomCompositeLut } from "./postprocess/NativeLdrEffectLuts.js";
|
|
9
9
|
import { normalizeBloomQualityPreset, resolveBloomPyramidBlurRadii, resolveBloomPyramidPlan, resolveBloomPyramidResponseGain, } from "./postprocess/NativeBloomPyramid.js";
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
import { WebGL2Counters } from "./webgl2/Counters.js";
|
|
11
|
+
import { createWebGL2DeviceProbe } from "./webgl2/Probe.js";
|
|
12
|
+
import { WebGL2ContextLifecycle } from "./webgl2/ContextLifecycle.js";
|
|
13
|
+
import { WebGL2TextureRegistry } from "./webgl2/TextureUpload.js";
|
|
14
|
+
import { WebGL2SamplerRegistry } from "./webgl2/Samplers.js";
|
|
15
|
+
import { WebGL2DrawCallBinder } from "./webgl2/MultiDraw.js";
|
|
16
|
+
import { AURA_FRAME_BINDING, AURA_LIGHTS_BINDING } from "./resources/UniformBlock.js";
|
|
17
|
+
import { WebGL2ReadbackProbe } from "./webgl2/Probe.js";
|
|
18
|
+
import { WebGL2LegacyPostPipeline } from "./webgl2/LegacyPost.js";
|
|
19
|
+
import { cubeFaceTarget, rgba8TextureInternalFormat, textureUploadFormat, resolveRenderTargetFormat, resolveCompressedTextureFormat, magFilter, minFilter, addressMode } from "./webgl2/TextureFormats.js";
|
|
20
|
+
export const WEBGL_CUBE_FACES = ["px", "nx", "py", "ny", "pz", "nz"];
|
|
21
|
+
/**
|
|
22
|
+
* #621 (01-RTARRAY): immutable storage (`texStorage2D/3D`) only accepts SIZED
|
|
23
|
+
* internal formats. `resolveRenderTargetFormat("rgba8")` returns unsized
|
|
24
|
+
* `gl.RGBA`, which is valid for the `texImage2D` 2d path but makes
|
|
25
|
+
* texStorage raise INVALID_ENUM and allocate nothing, so cube/array colour
|
|
26
|
+
* framebuffers come out incomplete (GPU run 38143556299: "array: WebGL render
|
|
27
|
+
* target framebuffer status is invalid"). Float formats are already sized.
|
|
28
|
+
*/
|
|
29
|
+
export function renderTargetStorageFormat(gl, internalFormat) {
|
|
30
|
+
return internalFormat === gl.RGBA ? gl.RGBA8 : internalFormat;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Attachment-0 color format of a single-attachment 2d target: an explicit
|
|
34
|
+
* `colorAttachments[0].format` wins over the legacy `format` field.
|
|
35
|
+
*/
|
|
36
|
+
export function renderTargetColorFormat(descriptor) {
|
|
37
|
+
return descriptor.colorAttachments?.[0]?.format ?? descriptor.format ?? "rgba8";
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* MAX_TEXTURE_SIZE of the canvas's WebGL2 context (4096 when unavailable).
|
|
41
|
+
* Lives in the device owner file so callers never touch getContext
|
|
42
|
+
* themselves (single-renderer gate). Moved from the engine's deleted
|
|
43
|
+
* safe-basic webglRuntime in Live Fix E6.
|
|
44
|
+
*/
|
|
45
|
+
export function webGL2MaxTextureSize(canvas) {
|
|
46
|
+
return Number(canvas.getContext("webgl2")?.getParameter(WebGL2RenderingContext.MAX_TEXTURE_SIZE) ?? 4096);
|
|
47
|
+
}
|
|
48
|
+
/** C-08 named uniform-block → binding-point assignment applied post-link (T0-02). */
|
|
49
|
+
const NAMED_UNIFORM_BLOCK_BINDINGS = [
|
|
50
|
+
["AuraFrame", AURA_FRAME_BINDING],
|
|
51
|
+
["AuraLights", AURA_LIGHTS_BINDING]
|
|
52
|
+
];
|
|
53
|
+
export class WebGL2Buffer {
|
|
12
54
|
id;
|
|
13
55
|
usage;
|
|
14
56
|
byteLength;
|
|
@@ -16,6 +58,8 @@ class WebGL2Buffer {
|
|
|
16
58
|
handle;
|
|
17
59
|
gl;
|
|
18
60
|
disposed = false;
|
|
61
|
+
/** PRD-01 Phase 6 (CONTRACTS §6.1): device-side cleanup hook — VAO eviction. */
|
|
62
|
+
onDispose;
|
|
19
63
|
constructor(id, usage, byteLength, target, handle, gl) {
|
|
20
64
|
this.id = id;
|
|
21
65
|
this.usage = usage;
|
|
@@ -26,12 +70,14 @@ class WebGL2Buffer {
|
|
|
26
70
|
}
|
|
27
71
|
dispose() {
|
|
28
72
|
if (!this.disposed) {
|
|
29
|
-
this.gl.deleteBuffer(this.handle);
|
|
30
73
|
this.disposed = true;
|
|
74
|
+
// Evict VAOs referencing this buffer before the GL object goes away.
|
|
75
|
+
this.onDispose?.();
|
|
76
|
+
this.gl.deleteBuffer(this.handle);
|
|
31
77
|
}
|
|
32
78
|
}
|
|
33
79
|
}
|
|
34
|
-
class WebGL2ShaderProgram {
|
|
80
|
+
export class WebGL2ShaderProgram {
|
|
35
81
|
id;
|
|
36
82
|
label;
|
|
37
83
|
marker;
|
|
@@ -54,7 +100,7 @@ class WebGL2ShaderProgram {
|
|
|
54
100
|
}
|
|
55
101
|
}
|
|
56
102
|
}
|
|
57
|
-
class WebGL2RenderTarget {
|
|
103
|
+
export class WebGL2RenderTarget {
|
|
58
104
|
id;
|
|
59
105
|
width;
|
|
60
106
|
height;
|
|
@@ -71,7 +117,14 @@ class WebGL2RenderTarget {
|
|
|
71
117
|
gl;
|
|
72
118
|
disposed = false;
|
|
73
119
|
needsResolve = false;
|
|
74
|
-
|
|
120
|
+
dimension;
|
|
121
|
+
layers;
|
|
122
|
+
colorTextures;
|
|
123
|
+
layerTargets;
|
|
124
|
+
extraColorHandles;
|
|
125
|
+
layerFramebuffers;
|
|
126
|
+
layerChild;
|
|
127
|
+
constructor(id, width, height, label, colorTexture, depthTexture, framebuffer, colorHandle, depthHandle, depthTextureHandle, sampleCount, drawFramebuffer, multisampleColorHandle, gl, options = {}) {
|
|
75
128
|
this.id = id;
|
|
76
129
|
this.width = width;
|
|
77
130
|
this.height = height;
|
|
@@ -86,13 +139,31 @@ class WebGL2RenderTarget {
|
|
|
86
139
|
this.drawFramebuffer = drawFramebuffer;
|
|
87
140
|
this.multisampleColorHandle = multisampleColorHandle;
|
|
88
141
|
this.gl = gl;
|
|
142
|
+
this.dimension = options.dimension ?? "2d";
|
|
143
|
+
this.layers = options.layers;
|
|
144
|
+
this.colorTextures = options.colorTextures;
|
|
145
|
+
this.layerTargets = options.layerTargets;
|
|
146
|
+
this.extraColorHandles = options.extraColorHandles ?? [];
|
|
147
|
+
this.layerFramebuffers = options.layerFramebuffers ?? [];
|
|
148
|
+
this.layerChild = options.layerChild === true;
|
|
89
149
|
}
|
|
90
150
|
dispose() {
|
|
91
151
|
if (!this.disposed) {
|
|
152
|
+
if (this.layerChild) {
|
|
153
|
+
this.disposed = true;
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
for (const framebuffer of this.layerFramebuffers) {
|
|
157
|
+
if (framebuffer !== this.framebuffer)
|
|
158
|
+
this.gl.deleteFramebuffer(framebuffer);
|
|
159
|
+
}
|
|
92
160
|
this.gl.deleteFramebuffer(this.framebuffer);
|
|
93
161
|
if (this.drawFramebuffer !== this.framebuffer)
|
|
94
162
|
this.gl.deleteFramebuffer(this.drawFramebuffer);
|
|
95
163
|
this.gl.deleteTexture(this.colorHandle);
|
|
164
|
+
for (const handle of this.extraColorHandles) {
|
|
165
|
+
this.gl.deleteTexture(handle);
|
|
166
|
+
}
|
|
96
167
|
if (this.depthHandle)
|
|
97
168
|
this.gl.deleteRenderbuffer(this.depthHandle);
|
|
98
169
|
if (this.multisampleColorHandle)
|
|
@@ -100,7 +171,14 @@ class WebGL2RenderTarget {
|
|
|
100
171
|
if (this.depthTextureHandle)
|
|
101
172
|
this.gl.deleteTexture(this.depthTextureHandle);
|
|
102
173
|
this.colorTexture.dispose();
|
|
174
|
+
for (const texture of this.colorTextures ?? []) {
|
|
175
|
+
if (texture !== this.colorTexture)
|
|
176
|
+
texture.dispose();
|
|
177
|
+
}
|
|
103
178
|
this.depthTexture?.dispose();
|
|
179
|
+
for (const child of this.layerTargets ?? []) {
|
|
180
|
+
child.disposed = true;
|
|
181
|
+
}
|
|
104
182
|
this.disposed = true;
|
|
105
183
|
}
|
|
106
184
|
}
|
|
@@ -109,76 +187,13 @@ export class WebGL2Device {
|
|
|
109
187
|
errorCheckMode;
|
|
110
188
|
kind = "webgl2";
|
|
111
189
|
info;
|
|
112
|
-
disposed = false;
|
|
113
|
-
contextLost = false;
|
|
114
190
|
gl;
|
|
115
191
|
nextId = 1;
|
|
116
|
-
drawCalls = 0;
|
|
117
|
-
nativeTemporalPasses = 0;
|
|
118
|
-
nativeTemporalBindings = 0;
|
|
119
192
|
buffers = new Set();
|
|
193
|
+
disposedBufferCount = 0;
|
|
120
194
|
shaders = new Set();
|
|
121
195
|
renderTargets = new Set();
|
|
122
|
-
activeRenderTarget = null;
|
|
123
|
-
textures = new Map();
|
|
124
|
-
textureUploadModes = new Map();
|
|
125
|
-
fallbackTexture = null;
|
|
126
|
-
fallbackCubeTexture = null;
|
|
127
|
-
samplerObjectCache = new Map();
|
|
128
|
-
presentationProgram = null;
|
|
129
|
-
ldrPostprocessProgram = null;
|
|
130
|
-
bloomBrightExtractProgram = null;
|
|
131
|
-
bloomBlurProgram = null;
|
|
132
|
-
bloomCompositeProgram = null;
|
|
133
|
-
bloomDownsampleProgram = null;
|
|
134
|
-
bloomAccumulateProgram = null;
|
|
135
|
-
bloomPyramidResources = null;
|
|
136
|
-
outlineProgram = null;
|
|
137
|
-
ssaoProgram = null;
|
|
138
|
-
ssrProgram = null;
|
|
139
|
-
depthOfFieldProgram = null;
|
|
140
|
-
motionBlurProgram = null;
|
|
141
|
-
motionBlurVelocityTexture = null;
|
|
142
|
-
motionBlurVelocitySize = null;
|
|
143
|
-
taaProgram = null;
|
|
144
|
-
taaPresentationProgram = null;
|
|
145
|
-
taaHistoryTexture = null;
|
|
146
|
-
taaHistorySize = null;
|
|
147
|
-
bloomPingPongResources = null;
|
|
148
|
-
bloomBrightLutTexture = null;
|
|
149
|
-
bloomBrightLutThreshold = null;
|
|
150
|
-
bloomCompositeLutTexture = null;
|
|
151
|
-
bloomCompositeLutIntensity = null;
|
|
152
|
-
bloomCompositeLutShoulder = null;
|
|
153
|
-
lastBloomDiagnostics = null;
|
|
154
|
-
outlineBlendLutTexture = null;
|
|
155
|
-
outlineBlendLutKey = null;
|
|
156
|
-
depthReadbackProgram = null;
|
|
157
|
-
uniformLocationCache = new WeakMap();
|
|
158
|
-
textureSamplerParameterCache = new WeakMap();
|
|
159
196
|
stateCache = new WebGL2StateCache({ label: "webgl2-device-state-cache" });
|
|
160
|
-
textureUnitBindings = new Map();
|
|
161
|
-
vertexArrayCache = new Map();
|
|
162
|
-
vertexFormatIds = new WeakMap();
|
|
163
|
-
presentationVertexArray = null;
|
|
164
|
-
activeTextureUnitIndex = -1;
|
|
165
|
-
shaderProgramCreateCount = 0;
|
|
166
|
-
uniformLocationLookupCount = 0;
|
|
167
|
-
bufferUpdateCount = 0;
|
|
168
|
-
textureBindCount = 0;
|
|
169
|
-
samplerParameterUploadCount = 0;
|
|
170
|
-
samplerAnisotropyUploadCount = 0;
|
|
171
|
-
vertexArrayCreateCount = 0;
|
|
172
|
-
nativeInstancedSubmissions = 0;
|
|
173
|
-
nextVertexFormatId = 1;
|
|
174
|
-
releasedTextureHandles = 0;
|
|
175
|
-
nativeEnvironmentBindings = 0;
|
|
176
|
-
nativeShadowMapBindings = 0;
|
|
177
|
-
shadowRenderTargetsAllocated = 0;
|
|
178
|
-
lastError = null;
|
|
179
|
-
frameActive = false;
|
|
180
|
-
viewportWidth = 0;
|
|
181
|
-
viewportHeight = 0;
|
|
182
197
|
maxVertexAttributes;
|
|
183
198
|
anisotropicFilteringExtension;
|
|
184
199
|
maxTextureAnisotropy;
|
|
@@ -190,16 +205,15 @@ export class WebGL2Device {
|
|
|
190
205
|
* why the parity table listed context-loss recovery as a gap while the listeners existed — the
|
|
191
206
|
* device layer was never the gap, the absence of a public signal was.
|
|
192
207
|
*/
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
contextRestoredListener;
|
|
197
|
-
canvas;
|
|
208
|
+
host;
|
|
209
|
+
/** C-28: device capability probe, filled from extension detection in the ctor. */
|
|
210
|
+
probe;
|
|
198
211
|
static create(options) {
|
|
199
212
|
const gl = options.canvas.getContext("webgl2", {
|
|
200
213
|
antialias: options.antialias ?? true,
|
|
201
214
|
alpha: options.alpha ?? false,
|
|
202
|
-
preserveDrawingBuffer: options.preserveDrawingBuffer ?? false
|
|
215
|
+
preserveDrawingBuffer: options.preserveDrawingBuffer ?? false,
|
|
216
|
+
...(options.powerPreference !== undefined ? { powerPreference: options.powerPreference } : {})
|
|
203
217
|
});
|
|
204
218
|
if (!gl) {
|
|
205
219
|
throw new RenderDeviceError("WebGL2 is not available for the provided canvas", "WEBGL2_UNAVAILABLE");
|
|
@@ -256,39 +270,34 @@ export class WebGL2Device {
|
|
|
256
270
|
...(gl.getExtension("EXT_color_buffer_float") ? ["hdr-render-targets", "float-readback"] : [])
|
|
257
271
|
]
|
|
258
272
|
};
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
this.
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
}
|
|
288
|
-
});
|
|
289
|
-
canvas.addEventListener("webglcontextlost", this.contextLostListener);
|
|
290
|
-
canvas.addEventListener("webglcontextrestored", this.contextRestoredListener);
|
|
291
|
-
}
|
|
273
|
+
const host = {
|
|
274
|
+
gl,
|
|
275
|
+
stateCache: this.stateCache,
|
|
276
|
+
counters: new WebGL2Counters(),
|
|
277
|
+
buffers: this.buffers,
|
|
278
|
+
shaders: this.shaders,
|
|
279
|
+
renderTargets: this.renderTargets,
|
|
280
|
+
activeRenderTarget: null,
|
|
281
|
+
disposed: false,
|
|
282
|
+
contextLost: false,
|
|
283
|
+
errorCheckMode: this.errorCheckMode,
|
|
284
|
+
anisotropicFilteringExtension: this.anisotropicFilteringExtension,
|
|
285
|
+
maxTextureAnisotropy: this.maxTextureAnisotropy,
|
|
286
|
+
maxVertexAttributes: this.maxVertexAttributes,
|
|
287
|
+
resolveMultisampleTarget: (target) => this.resolveMultisampleTarget(target),
|
|
288
|
+
device: this
|
|
289
|
+
};
|
|
290
|
+
host.lifecycle = new WebGL2ContextLifecycle(host, canvas);
|
|
291
|
+
host.textureRegistry = new WebGL2TextureRegistry(host);
|
|
292
|
+
host.samplers = new WebGL2SamplerRegistry(host);
|
|
293
|
+
host.drawBinder = new WebGL2DrawCallBinder(host);
|
|
294
|
+
// #94 (Q-01-1): the C-29 restore hook (`renderer/DeviceLifecycle.ts`)
|
|
295
|
+
// calls `host.invalidateGpuObjects?.()` before the registry rebuild.
|
|
296
|
+
host.invalidateGpuObjects = () => this.invalidateGpuObjects();
|
|
297
|
+
host.probe = new WebGL2ReadbackProbe(host);
|
|
298
|
+
host.post = new WebGL2LegacyPostPipeline(host);
|
|
299
|
+
this.host = host;
|
|
300
|
+
this.probe = createWebGL2DeviceProbe(gl);
|
|
292
301
|
}
|
|
293
302
|
/**
|
|
294
303
|
* Subscribe to WebGL context loss. Returns an unsubscribe function.
|
|
@@ -297,21 +306,190 @@ export class WebGL2Device {
|
|
|
297
306
|
* memory pressure, on driver reset, or when a tab is backgrounded too long. What a caller can do is
|
|
298
307
|
* be told, so it can recreate resources rather than render nothing.
|
|
299
308
|
*/
|
|
309
|
+
get disposed() {
|
|
310
|
+
return this.host.disposed;
|
|
311
|
+
}
|
|
312
|
+
set disposed(value) {
|
|
313
|
+
this.host.disposed = value;
|
|
314
|
+
}
|
|
315
|
+
get contextLost() {
|
|
316
|
+
return this.host.contextLost;
|
|
317
|
+
}
|
|
318
|
+
set contextLost(value) {
|
|
319
|
+
this.host.contextLost = value;
|
|
320
|
+
}
|
|
300
321
|
onDeviceLost(listener) {
|
|
301
|
-
this.
|
|
302
|
-
return () => this.deviceLostListeners.delete(listener);
|
|
322
|
+
return this.host.lifecycle.onDeviceLost(listener);
|
|
303
323
|
}
|
|
304
|
-
/** Subscribe to context restoration. Returns an unsubscribe function. */
|
|
305
324
|
onDeviceRestored(listener) {
|
|
306
|
-
this.
|
|
307
|
-
return () => this.deviceRestoredListeners.delete(listener);
|
|
325
|
+
return this.host.lifecycle.onDeviceRestored(listener);
|
|
308
326
|
}
|
|
309
|
-
/** True while the WebGL context is lost. Polling alternative to {@link onDeviceLost}. */
|
|
310
327
|
isDeviceLost() {
|
|
311
|
-
return this.
|
|
328
|
+
return this.host.lifecycle.isDeviceLost();
|
|
329
|
+
}
|
|
330
|
+
beginFrame(width, height) {
|
|
331
|
+
this.host.lifecycle.beginFrame(width, height);
|
|
332
|
+
}
|
|
333
|
+
clear(color) {
|
|
334
|
+
this.host.lifecycle.clear(color);
|
|
335
|
+
}
|
|
336
|
+
clearRenderTarget(color, attachment) {
|
|
337
|
+
this.host.lifecycle.clearRenderTarget(color, attachment);
|
|
338
|
+
}
|
|
339
|
+
endFrame() {
|
|
340
|
+
this.host.lifecycle.endFrame();
|
|
341
|
+
}
|
|
342
|
+
draw(command) {
|
|
343
|
+
this.host.drawBinder.draw(command);
|
|
344
|
+
}
|
|
345
|
+
readPixels(x, y, width, height, attachment) {
|
|
346
|
+
return this.host.probe.readPixels(x, y, width, height, attachment);
|
|
347
|
+
}
|
|
348
|
+
readFloatPixels(x, y, width, height) {
|
|
349
|
+
return this.host.probe.readFloatPixels(x, y, width, height);
|
|
350
|
+
}
|
|
351
|
+
readDepthPixels(x, y, width, height) {
|
|
352
|
+
return this.host.probe.readDepthPixels(x, y, width, height);
|
|
353
|
+
}
|
|
354
|
+
writeRenderTargetPixels(target, pixels) {
|
|
355
|
+
this.host.probe.writeRenderTargetPixels(target, pixels);
|
|
356
|
+
}
|
|
357
|
+
presentRenderTarget(source) {
|
|
358
|
+
this.host.post.presentRenderTarget(source);
|
|
359
|
+
}
|
|
360
|
+
presentLdrPostprocess(source, options) {
|
|
361
|
+
this.host.post.presentLdrPostprocess(source, options);
|
|
362
|
+
}
|
|
363
|
+
executeReflectionSurfaceSsr(source, normalMask, output, options) {
|
|
364
|
+
this.host.post.executeReflectionSurfaceSsr(source, normalMask, output, options);
|
|
365
|
+
}
|
|
366
|
+
getBloomDiagnostics() {
|
|
367
|
+
return this.host.post.getBloomDiagnostics();
|
|
368
|
+
}
|
|
369
|
+
/** C-28: partial counters from existing diagnostics and the wrapped counter fields. */
|
|
370
|
+
counters() {
|
|
371
|
+
const diagnostics = this.getDiagnostics();
|
|
372
|
+
return {
|
|
373
|
+
drawCalls: this.host.counters.drawCalls,
|
|
374
|
+
bufferCreates: diagnostics.buffers,
|
|
375
|
+
textureUploads: diagnostics.textures ?? 0,
|
|
376
|
+
readbacks: this.host.counters.readbacks,
|
|
377
|
+
renderTargetsCreated: diagnostics.renderTargets ?? 0,
|
|
378
|
+
programCompiles: this.host.counters.programCompiles,
|
|
379
|
+
liveBuffers: diagnostics.buffers,
|
|
380
|
+
liveVertexArrays: this.host.drawBinder.vertexArrayCache.size,
|
|
381
|
+
textureBytes: diagnostics.textureBytes ?? 0,
|
|
382
|
+
renderTargetBytes: 0
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
resetFrameCounters() {
|
|
386
|
+
this.host.counters.drawCalls = 0;
|
|
387
|
+
this.host.counters.readbacks = 0;
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* PRD-01 §6.4 / 01-S7: with `KHR_parallel_shader_compile`, compile and
|
|
391
|
+
* link are issued without querying status, and the promise resolves once
|
|
392
|
+
* `COMPLETION_STATUS_KHR` reports done (polled per animation frame), so
|
|
393
|
+
* the caller's frame is not blocked. Without the extension this is the
|
|
394
|
+
* synchronous `createShaderProgram` wrapped in a resolved promise.
|
|
395
|
+
*/
|
|
396
|
+
compileAsync(sources) {
|
|
397
|
+
const ext = this.parallelShaderCompileExtension();
|
|
398
|
+
if (!ext)
|
|
399
|
+
return Promise.resolve(this.createShaderProgram(sources));
|
|
400
|
+
this.host.lifecycle.assertAlive();
|
|
401
|
+
this.assertShaderMarker(sources);
|
|
402
|
+
const vertexShader = this.issueShaderCompile(this.gl.VERTEX_SHADER, sources.vertex, sources.label);
|
|
403
|
+
const fragmentShader = this.issueShaderCompile(this.gl.FRAGMENT_SHADER, sources.fragment, sources.label);
|
|
404
|
+
const program = this.gl.createProgram();
|
|
405
|
+
if (!program) {
|
|
406
|
+
throw new RenderDeviceError("Failed to allocate WebGL shader program", "WEBGL_ALLOCATION_FAILED");
|
|
407
|
+
}
|
|
408
|
+
this.host.counters.shaderProgramCreateCount += 1;
|
|
409
|
+
this.gl.attachShader(program, vertexShader);
|
|
410
|
+
this.gl.attachShader(program, fragmentShader);
|
|
411
|
+
this.gl.linkProgram(program);
|
|
412
|
+
this.host.counters.programCompiles += 1;
|
|
413
|
+
this.parallelCompilesPending += 1;
|
|
414
|
+
return new Promise((resolve, reject) => {
|
|
415
|
+
const poll = () => {
|
|
416
|
+
if (this.host.disposed || this.host.contextLost) {
|
|
417
|
+
this.parallelCompilesPending -= 1;
|
|
418
|
+
reject(new RenderDeviceError("Device lost during parallel shader compile", "DEVICE_LOST", { label: sources.label }));
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
if (this.gl.getProgramParameter(program, ext.COMPLETION_STATUS_KHR) !== true) {
|
|
422
|
+
scheduleParallelCompilePoll(poll);
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
this.parallelCompilesPending -= 1;
|
|
426
|
+
try {
|
|
427
|
+
for (const [shader, type] of [[vertexShader, "vertex"], [fragmentShader, "fragment"]]) {
|
|
428
|
+
if (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {
|
|
429
|
+
const log = this.gl.getShaderInfoLog(shader) ?? "Unknown shader compile error";
|
|
430
|
+
this.gl.deleteShader(vertexShader);
|
|
431
|
+
this.gl.deleteShader(fragmentShader);
|
|
432
|
+
this.gl.deleteProgram(program);
|
|
433
|
+
throw new RenderDeviceError("WebGL shader compile failed", "SHADER_COMPILE_FAILED", { label: sources.label, log, stage: type });
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
this.gl.deleteShader(vertexShader);
|
|
437
|
+
this.gl.deleteShader(fragmentShader);
|
|
438
|
+
resolve(this.finalizeLinkedProgram(program, sources));
|
|
439
|
+
}
|
|
440
|
+
catch (error) {
|
|
441
|
+
reject(error);
|
|
442
|
+
}
|
|
443
|
+
};
|
|
444
|
+
scheduleParallelCompilePoll(poll);
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
/** Programs issued through `compileAsync`'s parallel path that have not completed yet. */
|
|
448
|
+
parallelCompilesPending = 0;
|
|
449
|
+
parallelCompileExt;
|
|
450
|
+
parallelShaderCompileExtension() {
|
|
451
|
+
if (this.parallelCompileExt === undefined) {
|
|
452
|
+
this.parallelCompileExt = this.gl.getExtension("KHR_parallel_shader_compile") ?? null;
|
|
453
|
+
}
|
|
454
|
+
return this.parallelCompileExt;
|
|
455
|
+
}
|
|
456
|
+
issueShaderCompile(type, source, label) {
|
|
457
|
+
const shader = this.gl.createShader(type);
|
|
458
|
+
if (!shader) {
|
|
459
|
+
throw new RenderDeviceError("Failed to allocate WebGL shader", "WEBGL_ALLOCATION_FAILED", { label });
|
|
460
|
+
}
|
|
461
|
+
this.gl.shaderSource(shader, source);
|
|
462
|
+
this.gl.compileShader(shader);
|
|
463
|
+
return shader;
|
|
464
|
+
}
|
|
465
|
+
assertShaderMarker(sources) {
|
|
466
|
+
if (!sources.vertex.includes(sources.marker) || !sources.fragment.includes(sources.marker)) {
|
|
467
|
+
throw new RenderDeviceError("Shader source marker is missing from compiled sources", "SHADER_MARKER_MISSING", {
|
|
468
|
+
label: sources.label,
|
|
469
|
+
marker: sources.marker
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
multiDrawElementsInstanced(draws) {
|
|
474
|
+
this.host.drawBinder.multiDrawElementsInstanced(draws);
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
477
|
+
* #94 (Q-01-1, C-28/C-29): forget every GL object name and uploaded value
|
|
478
|
+
* cached against the lost context — VAOs, uniform locations, last-value
|
|
479
|
+
* uniform snapshots, the GL state shadow and texture-unit bindings — so
|
|
480
|
+
* they recreate lazily on the next draw after `webglcontextrestored`.
|
|
481
|
+
* `counters().liveVertexArrays` reads 0 afterwards. Buffers, textures and
|
|
482
|
+
* programs are recreated by the C-29 ResourceRegistry rebuild that runs
|
|
483
|
+
* right after this in the restore hook.
|
|
484
|
+
*/
|
|
485
|
+
invalidateGpuObjects() {
|
|
486
|
+
this.host.drawBinder.invalidateGpuObjects();
|
|
487
|
+
this.host.stateCache.invalidate();
|
|
488
|
+
this.host.samplers.activeTextureUnitIndex = -1;
|
|
489
|
+
this.host.samplers.textureUnitBindings.clear();
|
|
312
490
|
}
|
|
313
491
|
createBuffer(usage, byteLength, initialData) {
|
|
314
|
-
this.assertAlive();
|
|
492
|
+
this.host.lifecycle.assertAlive();
|
|
315
493
|
if (byteLength <= 0 || !Number.isInteger(byteLength)) {
|
|
316
494
|
throw new RenderDeviceError("Buffer byteLength must be a positive integer", "INVALID_BUFFER_SIZE", { byteLength });
|
|
317
495
|
}
|
|
@@ -319,8 +497,12 @@ export class WebGL2Device {
|
|
|
319
497
|
if (!handle) {
|
|
320
498
|
throw new RenderDeviceError("Failed to allocate WebGL buffer", "WEBGL_ALLOCATION_FAILED");
|
|
321
499
|
}
|
|
322
|
-
const target = usage === "index"
|
|
323
|
-
|
|
500
|
+
const target = usage === "index"
|
|
501
|
+
? this.gl.ELEMENT_ARRAY_BUFFER
|
|
502
|
+
: usage === "uniform"
|
|
503
|
+
? this.gl.UNIFORM_BUFFER
|
|
504
|
+
: this.gl.ARRAY_BUFFER;
|
|
505
|
+
this.host.drawBinder.bindNoVertexArray();
|
|
324
506
|
this.stateCache.bindBuffer(target, handle, () => this.gl.bindBuffer(target, handle));
|
|
325
507
|
this.gl.bufferData(target, byteLength, this.gl.DYNAMIC_DRAW);
|
|
326
508
|
if (initialData) {
|
|
@@ -333,12 +515,20 @@ export class WebGL2Device {
|
|
|
333
515
|
this.gl.bufferSubData(target, 0, initialData);
|
|
334
516
|
}
|
|
335
517
|
const buffer = new WebGL2Buffer(this.nextId++, usage, byteLength, target, handle, this.gl);
|
|
518
|
+
buffer.onDispose = () => {
|
|
519
|
+
// §6.1 declared leak fix: cached VAOs key on buffer ids; a dead buffer's
|
|
520
|
+
// entries must die with it, and the live-buffer set drops the corpse
|
|
521
|
+
// (`disposedBuffers` stays meaningful via the monotonic counter).
|
|
522
|
+
this.host.drawBinder.evictVertexArraysForBuffer(buffer.id);
|
|
523
|
+
this.buffers.delete(buffer);
|
|
524
|
+
this.disposedBufferCount += 1;
|
|
525
|
+
};
|
|
336
526
|
this.buffers.add(buffer);
|
|
337
527
|
return buffer;
|
|
338
528
|
}
|
|
339
529
|
updateBuffer(buffer, byteOffset, data) {
|
|
340
|
-
this.assertAlive();
|
|
341
|
-
const webglBuffer = this.requireBuffer(buffer);
|
|
530
|
+
this.host.lifecycle.assertAlive();
|
|
531
|
+
const webglBuffer = this.host.drawBinder.requireBuffer(buffer);
|
|
342
532
|
if (byteOffset < 0 || byteOffset + data.byteLength > webglBuffer.byteLength) {
|
|
343
533
|
throw new RenderDeviceError("Buffer update range is out of bounds", "BUFFER_RANGE_OUT_OF_BOUNDS", {
|
|
344
534
|
byteOffset,
|
|
@@ -346,14 +536,22 @@ export class WebGL2Device {
|
|
|
346
536
|
byteLength: webglBuffer.byteLength
|
|
347
537
|
});
|
|
348
538
|
}
|
|
349
|
-
this.bindNoVertexArray();
|
|
539
|
+
this.host.drawBinder.bindNoVertexArray();
|
|
350
540
|
this.stateCache.bindBuffer(webglBuffer.target, webglBuffer.handle, () => this.gl.bindBuffer(webglBuffer.target, webglBuffer.handle));
|
|
351
541
|
this.gl.bufferSubData(webglBuffer.target, byteOffset, data);
|
|
352
|
-
this.bufferUpdateCount += 1;
|
|
542
|
+
this.host.counters.bufferUpdateCount += 1;
|
|
543
|
+
}
|
|
544
|
+
bindUniformBuffer(buffer, binding) {
|
|
545
|
+
this.host.lifecycle.assertAlive();
|
|
546
|
+
const webglBuffer = this.host.drawBinder.requireBuffer(buffer);
|
|
547
|
+
if (webglBuffer.target !== this.gl.UNIFORM_BUFFER) {
|
|
548
|
+
throw new RenderDeviceError("Buffer was not created with usage 'uniform'", "INVALID_BUFFER_USAGE", { bufferId: buffer.id });
|
|
549
|
+
}
|
|
550
|
+
this.gl.bindBufferBase(this.gl.UNIFORM_BUFFER, binding, webglBuffer.handle);
|
|
353
551
|
}
|
|
354
552
|
readBuffer(buffer, byteOffset = 0, byteLength = buffer.byteLength - byteOffset) {
|
|
355
|
-
this.assertAlive();
|
|
356
|
-
const webglBuffer = this.requireBuffer(buffer);
|
|
553
|
+
this.host.lifecycle.assertAlive();
|
|
554
|
+
const webglBuffer = this.host.drawBinder.requireBuffer(buffer);
|
|
357
555
|
if (byteOffset < 0 || byteLength < 0 || byteOffset + byteLength > webglBuffer.byteLength) {
|
|
358
556
|
throw new RenderDeviceError("Buffer read range is out of bounds", "BUFFER_RANGE_OUT_OF_BOUNDS", {
|
|
359
557
|
byteOffset,
|
|
@@ -362,42 +560,59 @@ export class WebGL2Device {
|
|
|
362
560
|
});
|
|
363
561
|
}
|
|
364
562
|
const output = new Uint8Array(byteLength);
|
|
365
|
-
this.bindNoVertexArray();
|
|
563
|
+
this.host.drawBinder.bindNoVertexArray();
|
|
366
564
|
this.stateCache.bindBuffer(webglBuffer.target, webglBuffer.handle, () => this.gl.bindBuffer(webglBuffer.target, webglBuffer.handle));
|
|
367
565
|
this.gl.getBufferSubData(webglBuffer.target, byteOffset, output);
|
|
368
566
|
return output;
|
|
369
567
|
}
|
|
370
568
|
createShaderProgram(sources) {
|
|
371
|
-
this.assertAlive();
|
|
372
|
-
|
|
373
|
-
throw new RenderDeviceError("Shader source marker is missing from compiled sources", "SHADER_MARKER_MISSING", {
|
|
374
|
-
label: sources.label,
|
|
375
|
-
marker: sources.marker
|
|
376
|
-
});
|
|
377
|
-
}
|
|
569
|
+
this.host.lifecycle.assertAlive();
|
|
570
|
+
this.assertShaderMarker(sources);
|
|
378
571
|
const vertexShader = this.compileShader(this.gl.VERTEX_SHADER, sources.vertex, sources.label);
|
|
379
572
|
const fragmentShader = this.compileShader(this.gl.FRAGMENT_SHADER, sources.fragment, sources.label);
|
|
380
573
|
const program = this.gl.createProgram();
|
|
381
574
|
if (!program) {
|
|
382
575
|
throw new RenderDeviceError("Failed to allocate WebGL shader program", "WEBGL_ALLOCATION_FAILED");
|
|
383
576
|
}
|
|
384
|
-
this.shaderProgramCreateCount += 1;
|
|
577
|
+
this.host.counters.shaderProgramCreateCount += 1;
|
|
385
578
|
this.gl.attachShader(program, vertexShader);
|
|
386
579
|
this.gl.attachShader(program, fragmentShader);
|
|
387
580
|
this.gl.linkProgram(program);
|
|
581
|
+
this.host.counters.programCompiles += 1;
|
|
388
582
|
this.gl.deleteShader(vertexShader);
|
|
389
583
|
this.gl.deleteShader(fragmentShader);
|
|
584
|
+
return this.finalizeLinkedProgram(program, sources);
|
|
585
|
+
}
|
|
586
|
+
/** LINK_STATUS check, named-block bindings and reflection for a linked program. */
|
|
587
|
+
finalizeLinkedProgram(program, sources) {
|
|
390
588
|
if (!this.gl.getProgramParameter(program, this.gl.LINK_STATUS)) {
|
|
391
589
|
const log = this.gl.getProgramInfoLog(program) ?? "Unknown shader link error";
|
|
392
590
|
this.gl.deleteProgram(program);
|
|
393
591
|
throw new RenderDeviceError("WebGL shader link failed", "SHADER_LINK_FAILED", { label: sources.label, log });
|
|
394
592
|
}
|
|
593
|
+
// T0-02/C-08: generated blocks declare `layout(std140)` with no baked
|
|
594
|
+
// `binding=`; the named-block → binding-point assignment is fixed here so
|
|
595
|
+
// every linked program gets AuraFrame→0 and AuraLights→1 regardless of
|
|
596
|
+
// declaration order. Programs that do not declare a block are skipped.
|
|
597
|
+
for (const [blockName, binding] of NAMED_UNIFORM_BLOCK_BINDINGS) {
|
|
598
|
+
const index = this.gl.getUniformBlockIndex(program, blockName);
|
|
599
|
+
if (index !== this.gl.INVALID_INDEX) {
|
|
600
|
+
this.gl.uniformBlockBinding(program, index, binding);
|
|
601
|
+
}
|
|
602
|
+
}
|
|
395
603
|
const shader = new WebGL2ShaderProgram(this.nextId++, sources.label, sources.marker, this.reflectProgram(program), program, this.gl);
|
|
396
604
|
this.shaders.add(shader);
|
|
397
605
|
return shader;
|
|
398
606
|
}
|
|
399
607
|
createRenderTarget(descriptor) {
|
|
400
|
-
this.assertAlive();
|
|
608
|
+
this.host.lifecycle.assertAlive();
|
|
609
|
+
if ((descriptor.dimension !== undefined && descriptor.dimension !== "2d") ||
|
|
610
|
+
descriptor.layers !== undefined ||
|
|
611
|
+
descriptor.depthOnly === true ||
|
|
612
|
+
descriptor.depthCompare === true ||
|
|
613
|
+
(descriptor.colorAttachments?.length ?? 0) > 1) {
|
|
614
|
+
return this.createFeatureRenderTarget(descriptor);
|
|
615
|
+
}
|
|
401
616
|
if (!Number.isInteger(descriptor.width) ||
|
|
402
617
|
descriptor.width <= 0 ||
|
|
403
618
|
!Number.isInteger(descriptor.height) ||
|
|
@@ -462,8 +677,15 @@ export class WebGL2Device {
|
|
|
462
677
|
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);
|
|
463
678
|
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);
|
|
464
679
|
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);
|
|
465
|
-
|
|
466
|
-
|
|
680
|
+
// A single `colorAttachments` entry is the attachment-0 format (CONTRACTS
|
|
681
|
+
// §3.4) and wins over the legacy `format` field. Before this, the 2d path
|
|
682
|
+
// ignored it, so `createHdrTarget` ({ format: "rgba8", colorAttachments:
|
|
683
|
+
// [{ format: "rgba16f" }] }) without coverage allocated an RGBA8 "HDR"
|
|
684
|
+
// scene target: linear radiance clamped at 1.0 and 8-bit dark banding
|
|
685
|
+
// before tone mapping (GPU run 38190015020: device ACES of 4.0 = 226 vs
|
|
686
|
+
// three 250; tonemap-ramp dark swatches ΔE2000 13-30).
|
|
687
|
+
const format = renderTargetColorFormat(descriptor);
|
|
688
|
+
const textureFormat = resolveRenderTargetFormat(this.gl, format);
|
|
467
689
|
this.gl.texImage2D(this.gl.TEXTURE_2D, 0, textureFormat.internalFormat, descriptor.width, descriptor.height, 0, this.gl.RGBA, textureFormat.type, null);
|
|
468
690
|
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, framebuffer);
|
|
469
691
|
this.gl.framebufferTexture2D(this.gl.FRAMEBUFFER, this.gl.COLOR_ATTACHMENT0, this.gl.TEXTURE_2D, colorHandle, 0);
|
|
@@ -524,587 +746,373 @@ export class WebGL2Device {
|
|
|
524
746
|
// Cascaded maps use the established renderer-csm-cascade-* labels.
|
|
525
747
|
// Count their actual allocation too, including the first shadow frame.
|
|
526
748
|
if (/shadow|(?:^|-)csm(?:-|$)/i.test(descriptor.label ?? ""))
|
|
527
|
-
this.shadowRenderTargetsAllocated += 1;
|
|
528
|
-
this.textures.set(target.colorTexture, colorHandle);
|
|
529
|
-
this.textureUploadModes.set(target.colorTexture, "rgba8");
|
|
749
|
+
this.host.counters.shadowRenderTargetsAllocated += 1;
|
|
750
|
+
this.host.textureRegistry.textures.set(target.colorTexture, colorHandle);
|
|
751
|
+
this.host.textureRegistry.textureUploadModes.set(target.colorTexture, "rgba8");
|
|
530
752
|
if (depthTexture && depthTextureHandle) {
|
|
531
|
-
this.textures.set(depthTexture, depthTextureHandle);
|
|
532
|
-
this.textureUploadModes.set(depthTexture, "depth-render-target");
|
|
753
|
+
this.host.textureRegistry.textures.set(depthTexture, depthTextureHandle);
|
|
754
|
+
this.host.textureRegistry.textureUploadModes.set(depthTexture, "depth-render-target");
|
|
533
755
|
}
|
|
534
756
|
return target;
|
|
535
757
|
}
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
throw new RenderDeviceError("Render target
|
|
549
|
-
|
|
758
|
+
/**
|
|
759
|
+
* PR 0a render-target fields (CONTRACTS §3.4): `dimension`/`layers` (cube +
|
|
760
|
+
* 2d-array layered targets rendered through `layerTargets`), `depthOnly`
|
|
761
|
+
* (no color attachment), `depthCompare` (comparison-sampler depth texture)
|
|
762
|
+
* and `colorAttachments` (MRT, per-layer `drawBuffers` state).
|
|
763
|
+
*/
|
|
764
|
+
createFeatureRenderTarget(descriptor) {
|
|
765
|
+
const gl = this.gl;
|
|
766
|
+
if (!Number.isInteger(descriptor.width) ||
|
|
767
|
+
descriptor.width <= 0 ||
|
|
768
|
+
!Number.isInteger(descriptor.height) ||
|
|
769
|
+
descriptor.height <= 0) {
|
|
770
|
+
throw new RenderDeviceError("Render target dimensions must be positive integers", "INVALID_RENDER_TARGET_SIZE", {
|
|
771
|
+
width: descriptor.width,
|
|
772
|
+
height: descriptor.height,
|
|
773
|
+
label: descriptor.label
|
|
550
774
|
});
|
|
551
775
|
}
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
if (target.sampleCount <= 1 || !target.needsResolve)
|
|
558
|
-
return;
|
|
559
|
-
const previousFramebuffer = this.gl.getParameter(this.gl.FRAMEBUFFER_BINDING);
|
|
560
|
-
this.gl.bindFramebuffer(this.gl.READ_FRAMEBUFFER, target.drawFramebuffer);
|
|
561
|
-
this.gl.bindFramebuffer(this.gl.DRAW_FRAMEBUFFER, target.framebuffer);
|
|
562
|
-
let mask = this.gl.COLOR_BUFFER_BIT;
|
|
563
|
-
if (target.depthTextureHandle)
|
|
564
|
-
mask |= this.gl.DEPTH_BUFFER_BIT;
|
|
565
|
-
this.gl.blitFramebuffer(0, 0, target.width, target.height, 0, 0, target.width, target.height, mask, this.gl.NEAREST);
|
|
566
|
-
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, previousFramebuffer);
|
|
567
|
-
target.needsResolve = false;
|
|
568
|
-
this.stateCache.invalidate();
|
|
569
|
-
}
|
|
570
|
-
writeRenderTargetPixels(target, pixels) {
|
|
571
|
-
this.assertAlive();
|
|
572
|
-
if (!(target instanceof WebGL2RenderTarget) || !this.renderTargets.has(target) || target.disposed) {
|
|
573
|
-
throw new RenderDeviceError("Render target is not a live WebGL2 resource owned by this device", "INVALID_RESOURCE", {
|
|
574
|
-
targetId: target.id
|
|
776
|
+
const dimension = descriptor.dimension ?? "2d";
|
|
777
|
+
if (descriptor.layers !== undefined && (!Number.isInteger(descriptor.layers) || descriptor.layers < 1)) {
|
|
778
|
+
throw new RenderDeviceError("Render target layer count must be a positive integer", "INVALID_RENDER_TARGET_SIZE", {
|
|
779
|
+
layers: descriptor.layers,
|
|
780
|
+
label: descriptor.label
|
|
575
781
|
});
|
|
576
782
|
}
|
|
577
|
-
if (
|
|
578
|
-
throw new RenderDeviceError("
|
|
579
|
-
|
|
580
|
-
|
|
783
|
+
if (descriptor.layers !== undefined && dimension !== "2d-array") {
|
|
784
|
+
throw new RenderDeviceError("Render target `layers` only applies to dimension \"2d-array\"", "INVALID_RENDER_TARGET_SIZE", {
|
|
785
|
+
dimension,
|
|
786
|
+
layers: descriptor.layers,
|
|
787
|
+
label: descriptor.label
|
|
581
788
|
});
|
|
582
789
|
}
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
790
|
+
const layerCount = dimension === "cube" ? 6 : dimension === "2d-array" ? descriptor.layers ?? 1 : 1;
|
|
791
|
+
const depthOnly = descriptor.depthOnly === true;
|
|
792
|
+
if (depthOnly && (descriptor.colorAttachments?.length ?? 0) > 0) {
|
|
793
|
+
throw new RenderDeviceError("Render target cannot combine `depthOnly` with `colorAttachments`", "INVALID_RENDER_TARGET_SIZE", {
|
|
794
|
+
label: descriptor.label
|
|
588
795
|
});
|
|
589
796
|
}
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
this.gl.texSubImage2D(this.gl.TEXTURE_2D, 0, 0, 0, target.width, target.height, this.gl.RGBA, this.gl.UNSIGNED_BYTE, pixels);
|
|
594
|
-
target.needsResolve = false;
|
|
595
|
-
}
|
|
596
|
-
finally {
|
|
597
|
-
this.restoreTextureUnit0(textureUnit0);
|
|
598
|
-
}
|
|
599
|
-
this.lastError = this.readError();
|
|
600
|
-
if (this.lastError) {
|
|
601
|
-
throw new RenderDeviceError("WebGL2 render-target pixel upload failed", "WEBGL_PIXEL_UPLOAD_FAILED", {
|
|
602
|
-
targetId: target.id,
|
|
603
|
-
error: this.lastError
|
|
797
|
+
if (depthOnly && descriptor.depth === false) {
|
|
798
|
+
throw new RenderDeviceError("Render target cannot combine `depthOnly` with `depth: false`", "INVALID_RENDER_TARGET_SIZE", {
|
|
799
|
+
label: descriptor.label
|
|
604
800
|
});
|
|
605
801
|
}
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
802
|
+
const sampleCount = descriptor.sampleCount ?? 1;
|
|
803
|
+
const colorAttachmentCount = depthOnly ? 0 : Math.max(1, descriptor.colorAttachments?.length ?? 1);
|
|
804
|
+
if (sampleCount > 1 && (depthOnly || descriptor.depthCompare === true || (descriptor.colorAttachments?.length ?? 0) > 1 || layerCount > 1)) {
|
|
805
|
+
throw new RenderDeviceError("Multisample render targets do not support layered, depth-only, compare or MRT descriptors", "INVALID_RENDER_TARGET_SAMPLE_COUNT", {
|
|
806
|
+
sampleCount,
|
|
807
|
+
label: descriptor.label
|
|
612
808
|
});
|
|
613
809
|
}
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
this.lastError = this.readError();
|
|
621
|
-
if (this.lastError) {
|
|
622
|
-
throw new RenderDeviceError(`WebGL2 render-target presentation failed: ${this.lastError}`, "WEBGL_PRESENT_FAILED", {
|
|
623
|
-
targetId: source.id,
|
|
624
|
-
error: this.lastError
|
|
810
|
+
const maxSamples = Number(gl.getParameter(gl.MAX_SAMPLES) ?? 1);
|
|
811
|
+
if (!Number.isInteger(sampleCount) || sampleCount < 1 || sampleCount > maxSamples) {
|
|
812
|
+
throw new RenderDeviceError("WebGL2 render-target sampleCount must be an integer supported by MAX_SAMPLES.", "INVALID_RENDER_TARGET_SAMPLE_COUNT", {
|
|
813
|
+
sampleCount,
|
|
814
|
+
maxSamples,
|
|
815
|
+
label: descriptor.label
|
|
625
816
|
});
|
|
626
817
|
}
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
818
|
+
const label = descriptor.label ?? "render-target";
|
|
819
|
+
const textureTarget = dimension === "cube" ? gl.TEXTURE_CUBE_MAP : dimension === "2d-array" ? gl.TEXTURE_2D_ARRAY : gl.TEXTURE_2D;
|
|
820
|
+
const depthMode = depthOnly || descriptor.depth === "texture" || (layerCount > 1 && descriptor.depth !== false) ? "texture" : descriptor.depth === false ? "none" : "renderbuffer";
|
|
821
|
+
const depthCompare = descriptor.depthCompare === true;
|
|
822
|
+
const colorFormats = depthOnly
|
|
823
|
+
? []
|
|
824
|
+
: colorAttachmentCount === 1 && !descriptor.colorAttachments
|
|
825
|
+
? [descriptor.format ?? "rgba8"]
|
|
826
|
+
: (descriptor.colorAttachments ?? [{ format: descriptor.format ?? "rgba8" }]).map((attachment) => attachment.format);
|
|
827
|
+
const colorHandles = [];
|
|
828
|
+
const colorTextures = [];
|
|
829
|
+
let depthTextureHandle = null;
|
|
830
|
+
const layerFramebuffers = [];
|
|
831
|
+
const cleanup = () => {
|
|
832
|
+
for (const handle of colorHandles)
|
|
833
|
+
gl.deleteTexture(handle);
|
|
834
|
+
if (depthTextureHandle)
|
|
835
|
+
gl.deleteTexture(depthTextureHandle);
|
|
836
|
+
for (const framebuffer of layerFramebuffers)
|
|
837
|
+
gl.deleteFramebuffer(framebuffer);
|
|
838
|
+
};
|
|
839
|
+
const previousActiveTexture = gl.getParameter(gl.ACTIVE_TEXTURE);
|
|
840
|
+
gl.activeTexture(gl.TEXTURE0);
|
|
841
|
+
const previousTexture = gl.getParameter(gl.TEXTURE_BINDING_2D);
|
|
842
|
+
const previousCubeTexture = gl.getParameter(gl.TEXTURE_BINDING_CUBE_MAP);
|
|
843
|
+
const previousArrayTexture = gl.getParameter(gl.TEXTURE_BINDING_2D_ARRAY);
|
|
844
|
+
const previousFramebuffer = gl.getParameter(gl.FRAMEBUFFER_BINDING);
|
|
845
|
+
for (let attachment = 0; attachment < colorFormats.length; attachment += 1) {
|
|
846
|
+
const format = colorFormats[attachment];
|
|
847
|
+
const textureFormat = resolveRenderTargetFormat(gl, format);
|
|
848
|
+
const handle = gl.createTexture();
|
|
849
|
+
if (!handle) {
|
|
850
|
+
cleanup();
|
|
851
|
+
throw new RenderDeviceError("Failed to allocate WebGL render target", "WEBGL_ALLOCATION_FAILED", { label });
|
|
852
|
+
}
|
|
853
|
+
colorHandles.push(handle);
|
|
854
|
+
colorTextures.push(new Texture({ width: descriptor.width, height: descriptor.height, format, label: colorAttachmentCount > 1 ? `${label}-color-${attachment}` : descriptor.label ?? "render-target-color", dimension, layers: dimension === "2d" ? undefined : layerCount, renderAttachment: true }));
|
|
855
|
+
gl.bindTexture(textureTarget, handle);
|
|
856
|
+
gl.texParameteri(textureTarget, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
857
|
+
gl.texParameteri(textureTarget, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
858
|
+
gl.texParameteri(textureTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
859
|
+
gl.texParameteri(textureTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
860
|
+
if (dimension === "2d") {
|
|
861
|
+
gl.texImage2D(textureTarget, 0, textureFormat.internalFormat, descriptor.width, descriptor.height, 0, gl.RGBA, textureFormat.type, null);
|
|
862
|
+
}
|
|
863
|
+
else if (dimension === "cube") {
|
|
864
|
+
gl.texStorage2D(textureTarget, 1, renderTargetStorageFormat(gl, textureFormat.internalFormat), descriptor.width, descriptor.height);
|
|
865
|
+
}
|
|
866
|
+
else {
|
|
867
|
+
gl.texStorage3D(textureTarget, 1, renderTargetStorageFormat(gl, textureFormat.internalFormat), descriptor.width, descriptor.height, layerCount);
|
|
634
868
|
}
|
|
635
869
|
}
|
|
636
|
-
|
|
637
|
-
if (
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
presentLdrPostprocess(source, options) {
|
|
652
|
-
this.assertAlive();
|
|
653
|
-
if (!(source instanceof WebGL2RenderTarget) || !this.renderTargets.has(source) || source.disposed) {
|
|
654
|
-
throw new RenderDeviceError("Render target is not a live WebGL2 resource owned by this device", "INVALID_RESOURCE", {
|
|
655
|
-
targetId: source.id
|
|
656
|
-
});
|
|
657
|
-
}
|
|
658
|
-
this.resolveMultisampleTarget(source);
|
|
659
|
-
const tonePass = options.passes.find((pass) => pass.name === "tone-mapping");
|
|
660
|
-
const bloomPass = options.passes.find((pass) => pass.name === "bloom");
|
|
661
|
-
const depthOfFieldPass = options.passes.find((pass) => pass.name === "depth-of-field");
|
|
662
|
-
const motionBlurPass = options.passes.find((pass) => pass.name === "motion-blur");
|
|
663
|
-
const ssaoPass = options.passes.find((pass) => pass.name === "ssao");
|
|
664
|
-
const ssrPass = options.passes.find((pass) => pass.name === "ssr");
|
|
665
|
-
const taaPass = options.passes.find((pass) => pass.name === "taa");
|
|
666
|
-
const outlinePass = options.passes.find((pass) => pass.name === "outline");
|
|
667
|
-
if (source.colorTexture.format !== "rgba8" && !tonePass) {
|
|
668
|
-
throw new RenderDeviceError("WebGL2 HDR postprocess presentation requires a tone-mapping pass before LDR output.", "WEBGL_LDR_POSTPROCESS_FORMAT_UNSUPPORTED", {
|
|
669
|
-
targetId: source.id,
|
|
670
|
-
format: source.colorTexture.format
|
|
671
|
-
});
|
|
672
|
-
}
|
|
673
|
-
if (source.colorTexture.format !== "rgba8" && (depthOfFieldPass || motionBlurPass || ssaoPass || ssrPass || taaPass || outlinePass) && !tonePass) {
|
|
674
|
-
throw new RenderDeviceError("WebGL2 byte-kernel postprocess requires rgba8 input or a preceding tone-mapping pass.", "WEBGL_LDR_POSTPROCESS_FORMAT_UNSUPPORTED", {
|
|
675
|
-
targetId: source.id,
|
|
676
|
-
format: source.colorTexture.format,
|
|
677
|
-
pass: depthOfFieldPass ? "depth-of-field" : motionBlurPass ? "motion-blur" : ssaoPass ? "ssao" : ssrPass ? "ssr" : taaPass ? "taa" : "outline"
|
|
678
|
-
});
|
|
679
|
-
}
|
|
680
|
-
if ((depthOfFieldPass || ssaoPass || ssrPass) && !source.depthTextureHandle) {
|
|
681
|
-
throw new RenderDeviceError("WebGL2 native depth postprocess requires a renderer-owned sampleable depth texture.", "WEBGL_LDR_POSTPROCESS_DEPTH_REQUIRED", {
|
|
682
|
-
targetId: source.id,
|
|
683
|
-
pass: depthOfFieldPass ? "depth-of-field" : ssaoPass ? "ssao" : "ssr"
|
|
684
|
-
});
|
|
685
|
-
}
|
|
686
|
-
// Raw GL depth is nonlinear (0.1/1000 defaults park the play area past
|
|
687
|
-
// 0.97), which blinded every depth-gated native pass. SSR and DOF compare
|
|
688
|
-
// linearized depth; SSAO keeps its legacy response (documented partial).
|
|
689
|
-
const depthRange = normalizeLdrDepthRange(options.depthRange);
|
|
690
|
-
const outputTarget = options.outputTarget;
|
|
691
|
-
if (outputTarget && (!(outputTarget instanceof WebGL2RenderTarget) || !this.renderTargets.has(outputTarget) || outputTarget.disposed)) {
|
|
692
|
-
throw new RenderDeviceError("Output render target is not a live WebGL2 resource owned by this device", "INVALID_RESOURCE", {
|
|
693
|
-
targetId: outputTarget.id
|
|
694
|
-
});
|
|
695
|
-
}
|
|
696
|
-
if (outputTarget && outputTarget.colorTexture.format !== "rgba8") {
|
|
697
|
-
throw new RenderDeviceError("WebGL2 LDR postprocess output target must be rgba8.", "WEBGL_LDR_POSTPROCESS_OUTPUT_FORMAT_UNSUPPORTED", {
|
|
698
|
-
targetId: outputTarget.id,
|
|
699
|
-
format: outputTarget.colorTexture.format
|
|
700
|
-
});
|
|
701
|
-
}
|
|
702
|
-
if (outputTarget && (outputTarget.width !== source.width || outputTarget.height !== source.height)) {
|
|
703
|
-
throw new RenderDeviceError("WebGL2 LDR postprocess source and output dimensions must match.", "WEBGL_LDR_POSTPROCESS_SIZE_MISMATCH", {
|
|
704
|
-
sourceWidth: source.width,
|
|
705
|
-
sourceHeight: source.height,
|
|
706
|
-
targetWidth: outputTarget.width,
|
|
707
|
-
targetHeight: outputTarget.height
|
|
870
|
+
let depthTexture;
|
|
871
|
+
if (depthMode === "texture") {
|
|
872
|
+
depthTextureHandle = gl.createTexture();
|
|
873
|
+
if (!depthTextureHandle) {
|
|
874
|
+
cleanup();
|
|
875
|
+
throw new RenderDeviceError("Failed to allocate WebGL render target", "WEBGL_ALLOCATION_FAILED", { label });
|
|
876
|
+
}
|
|
877
|
+
depthTexture = new Texture({
|
|
878
|
+
width: descriptor.width,
|
|
879
|
+
height: descriptor.height,
|
|
880
|
+
format: "depth24",
|
|
881
|
+
label: `${label}-depth`,
|
|
882
|
+
dimension,
|
|
883
|
+
layers: dimension === "2d" ? undefined : layerCount,
|
|
884
|
+
renderAttachment: true
|
|
708
885
|
});
|
|
886
|
+
gl.bindTexture(textureTarget, depthTextureHandle);
|
|
887
|
+
gl.texParameteri(textureTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
|
888
|
+
gl.texParameteri(textureTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
|
889
|
+
gl.texParameteri(textureTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
890
|
+
gl.texParameteri(textureTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
891
|
+
if (depthCompare) {
|
|
892
|
+
gl.texParameteri(textureTarget, gl.TEXTURE_COMPARE_MODE, gl.COMPARE_REF_TO_TEXTURE);
|
|
893
|
+
gl.texParameteri(textureTarget, gl.TEXTURE_COMPARE_FUNC, gl.LEQUAL);
|
|
894
|
+
}
|
|
895
|
+
if (dimension === "2d-array") {
|
|
896
|
+
gl.texImage3D(textureTarget, 0, gl.DEPTH_COMPONENT24, descriptor.width, descriptor.height, layerCount, 0, gl.DEPTH_COMPONENT, gl.UNSIGNED_INT, null);
|
|
897
|
+
}
|
|
898
|
+
else if (dimension === "cube") {
|
|
899
|
+
gl.texStorage2D(textureTarget, 1, gl.DEPTH_COMPONENT24, descriptor.width, descriptor.height);
|
|
900
|
+
}
|
|
901
|
+
else {
|
|
902
|
+
gl.texImage2D(textureTarget, 0, gl.DEPTH_COMPONENT24, descriptor.width, descriptor.height, 0, gl.DEPTH_COMPONENT, gl.UNSIGNED_INT, null);
|
|
903
|
+
}
|
|
709
904
|
}
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
? normalizeNativeMotionBlurOptions(motionBlurPass.options, source.width, source.height)
|
|
717
|
-
: undefined;
|
|
718
|
-
const ssaoOptions = ssaoPass ? normalizeNativeSsaoOptions(ssaoPass.options) : undefined;
|
|
719
|
-
const ssrOptions = ssrPass ? normalizeNativeSsrOptions(ssrPass.options) : undefined;
|
|
720
|
-
const taaOptions = taaPass ? normalizeNativeTaaOptions(taaPass.options, source.width, source.height) : undefined;
|
|
721
|
-
const outlineOptions = outlinePass ? normalizeNativeOutlineOptions(outlinePass.options) : undefined;
|
|
722
|
-
const program = this.ensureLdrPostprocessProgram();
|
|
723
|
-
const vertexArray = this.ensurePresentationVertexArray();
|
|
724
|
-
const sourceIsHdr = source.colorTexture.format !== "rgba8";
|
|
725
|
-
const bloomResources = bloomOptions || depthOfFieldOptions || motionBlurOptions || ssaoOptions || ssrOptions || taaOptions || outlineOptions
|
|
726
|
-
? this.ensureBloomPingPongResources(source.width, source.height, sourceIsHdr && Boolean(bloomOptions))
|
|
727
|
-
: undefined;
|
|
728
|
-
if (bloomOptions && !sourceIsHdr) {
|
|
729
|
-
this.ensureBloomLutTextures(bloomOptions);
|
|
730
|
-
}
|
|
731
|
-
if (outlineOptions) {
|
|
732
|
-
this.ensureOutlineBlendLutTexture(outlineOptions);
|
|
733
|
-
}
|
|
734
|
-
if (motionBlurOptions?.velocity) {
|
|
735
|
-
this.ensureMotionBlurVelocityTexture(source.width, source.height, motionBlurOptions.velocity);
|
|
736
|
-
}
|
|
737
|
-
if (taaOptions?.history) {
|
|
738
|
-
this.ensureTaaHistoryTexture(source.width, source.height, taaOptions.history);
|
|
739
|
-
}
|
|
740
|
-
const outputWidth = webglOutputTarget?.width ?? (this.viewportWidth || this.gl.drawingBufferWidth);
|
|
741
|
-
const outputHeight = webglOutputTarget?.height ?? (this.viewportHeight || this.gl.drawingBufferHeight);
|
|
742
|
-
const previousState = this.prepareFullscreenPresentation(webglOutputTarget?.framebuffer ?? null, outputWidth, outputHeight);
|
|
743
|
-
try {
|
|
744
|
-
let ldrSourceHandle = source.colorHandle;
|
|
745
|
-
let temporarySourceIndex = -1;
|
|
746
|
-
if (bloomOptions && bloomResources) {
|
|
747
|
-
if (bloomOptions.quality === "performance") {
|
|
748
|
-
ldrSourceHandle = this.executeNativeBloomPasses(ldrSourceHandle, bloomResources, bloomOptions, vertexArray, sourceIsHdr);
|
|
749
|
-
temporarySourceIndex = 1;
|
|
750
|
-
this.recordBloomDiagnostics(bloomOptions, source.width, source.height, sourceIsHdr, 1);
|
|
751
|
-
}
|
|
752
|
-
else {
|
|
753
|
-
const plan = resolveBloomPyramidPlan(source.width, source.height, bloomOptions.quality, sourceIsHdr);
|
|
754
|
-
const pyramid = this.ensureBloomPyramidResources(plan, sourceIsHdr);
|
|
755
|
-
const pyramidResult = this.executeNativeBloomPyramidPasses(ldrSourceHandle, source.width, source.height, pyramid, {
|
|
756
|
-
textureA: bloomResources.textures[0],
|
|
757
|
-
framebufferA: bloomResources.framebuffers[0],
|
|
758
|
-
textureB: bloomResources.textures[1],
|
|
759
|
-
framebufferB: bloomResources.framebuffers[1]
|
|
760
|
-
}, bloomOptions, vertexArray, sourceIsHdr);
|
|
761
|
-
// The pyramid sum lands in ping-pong texture A; composite it with the
|
|
762
|
-
// source through the proven single-scale composite program.
|
|
763
|
-
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, bloomResources.framebuffers[1]);
|
|
764
|
-
this.gl.viewport(0, 0, source.width, source.height);
|
|
765
|
-
const pyramidComposite = this.ensureBloomCompositeProgram();
|
|
766
|
-
this.gl.useProgram(pyramidComposite);
|
|
767
|
-
this.gl.bindVertexArray(vertexArray);
|
|
768
|
-
this.bindFullscreenTexture(0, ldrSourceHandle);
|
|
769
|
-
this.bindFullscreenTexture(1, pyramidResult);
|
|
770
|
-
if (this.bloomCompositeLutTexture)
|
|
771
|
-
this.bindFullscreenTexture(2, this.bloomCompositeLutTexture);
|
|
772
|
-
this.gl.uniform1i(this.gl.getUniformLocation(pyramidComposite, "u_source"), 0);
|
|
773
|
-
this.gl.uniform1i(this.gl.getUniformLocation(pyramidComposite, "u_blurred"), 1);
|
|
774
|
-
this.gl.uniform1i(this.gl.getUniformLocation(pyramidComposite, "u_compositeLut"), 2);
|
|
775
|
-
this.gl.uniform1i(this.gl.getUniformLocation(pyramidComposite, "u_hdr"), sourceIsHdr ? 1 : 0);
|
|
776
|
-
this.gl.uniform1f(this.gl.getUniformLocation(pyramidComposite, "u_intensity"), bloomOptions.intensity * resolveBloomPyramidResponseGain(plan));
|
|
777
|
-
this.gl.drawArrays(this.gl.TRIANGLES, 0, 3);
|
|
778
|
-
ldrSourceHandle = bloomResources.textures[1];
|
|
779
|
-
// The composited result lives in texture B, so subsequent passes
|
|
780
|
-
// must write texture A (index 0) to avoid sampling a bound target.
|
|
781
|
-
temporarySourceIndex = 0;
|
|
782
|
-
this.recordBloomDiagnostics(bloomOptions, source.width, source.height, sourceIsHdr, plan.mipCount);
|
|
783
|
-
}
|
|
905
|
+
let depthRenderbufferHandle = null;
|
|
906
|
+
if (depthMode === "renderbuffer") {
|
|
907
|
+
depthRenderbufferHandle = gl.createRenderbuffer();
|
|
908
|
+
if (!depthRenderbufferHandle) {
|
|
909
|
+
cleanup();
|
|
910
|
+
throw new RenderDeviceError("Failed to allocate WebGL render target", "WEBGL_ALLOCATION_FAILED", { label });
|
|
784
911
|
}
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
912
|
+
const previousRenderbuffer = gl.getParameter(gl.RENDERBUFFER_BINDING);
|
|
913
|
+
gl.bindRenderbuffer(gl.RENDERBUFFER, depthRenderbufferHandle);
|
|
914
|
+
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, descriptor.width, descriptor.height);
|
|
915
|
+
gl.bindRenderbuffer(gl.RENDERBUFFER, previousRenderbuffer);
|
|
916
|
+
}
|
|
917
|
+
const drawBuffers = depthOnly
|
|
918
|
+
? [gl.NONE]
|
|
919
|
+
: colorFormats.map((_, attachment) => gl.COLOR_ATTACHMENT0 + attachment);
|
|
920
|
+
const attachLayer = (framebuffer, layer) => {
|
|
921
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
|
|
922
|
+
if (depthOnly) {
|
|
923
|
+
gl.drawBuffers([gl.NONE]);
|
|
924
|
+
gl.readBuffer(gl.NONE);
|
|
925
|
+
}
|
|
926
|
+
else if (drawBuffers.length > 1) {
|
|
927
|
+
gl.drawBuffers(drawBuffers);
|
|
928
|
+
}
|
|
929
|
+
for (let attachment = 0; attachment < colorHandles.length; attachment += 1) {
|
|
930
|
+
if (dimension === "cube") {
|
|
931
|
+
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + attachment, gl.TEXTURE_CUBE_MAP_POSITIVE_X + layer, colorHandles[attachment], 0);
|
|
791
932
|
}
|
|
792
|
-
if (
|
|
793
|
-
|
|
794
|
-
ldrSourceHandle = this.executeNativeDepthOfFieldPass(ldrSourceHandle, source.depthTextureHandle, bloomResources, depthOfFieldOptions, vertexArray, depthOfFieldTargetIndex, depthRange);
|
|
795
|
-
temporarySourceIndex = depthOfFieldTargetIndex;
|
|
933
|
+
else if (dimension === "2d-array") {
|
|
934
|
+
gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + attachment, colorHandles[attachment], 0, layer);
|
|
796
935
|
}
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
ldrSourceHandle = this.executeNativeMotionBlurPass(ldrSourceHandle, bloomResources, motionBlurOptions, vertexArray, motionBlurTargetIndex);
|
|
800
|
-
temporarySourceIndex = motionBlurTargetIndex;
|
|
936
|
+
else {
|
|
937
|
+
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + attachment, gl.TEXTURE_2D, colorHandles[attachment], 0);
|
|
801
938
|
}
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
939
|
+
}
|
|
940
|
+
if (depthTextureHandle) {
|
|
941
|
+
if (dimension === "cube") {
|
|
942
|
+
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_CUBE_MAP_POSITIVE_X + layer, depthTextureHandle, 0);
|
|
806
943
|
}
|
|
807
|
-
if (
|
|
808
|
-
|
|
809
|
-
ldrSourceHandle = this.executeNativeSsrPass(ldrSourceHandle, source.depthTextureHandle, bloomResources, ssrOptions, vertexArray, ssrTargetIndex, depthRange);
|
|
810
|
-
temporarySourceIndex = ssrTargetIndex;
|
|
944
|
+
else if (dimension === "2d-array") {
|
|
945
|
+
gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, depthTextureHandle, 0, layer);
|
|
811
946
|
}
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
ldrSourceHandle = this.executeNativeTaaPass(ldrSourceHandle, bloomResources, taaOptions, vertexArray, taaTargetIndex);
|
|
815
|
-
temporarySourceIndex = taaTargetIndex;
|
|
947
|
+
else {
|
|
948
|
+
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, depthTextureHandle, 0);
|
|
816
949
|
}
|
|
817
950
|
}
|
|
818
|
-
if (
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
951
|
+
if (depthRenderbufferHandle) {
|
|
952
|
+
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthRenderbufferHandle);
|
|
953
|
+
}
|
|
954
|
+
return gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE;
|
|
955
|
+
};
|
|
956
|
+
for (let layer = 0; layer < layerCount; layer += 1) {
|
|
957
|
+
const framebuffer = gl.createFramebuffer();
|
|
958
|
+
if (!framebuffer) {
|
|
959
|
+
cleanup();
|
|
960
|
+
throw new RenderDeviceError("Failed to allocate WebGL render target", "WEBGL_ALLOCATION_FAILED", { label });
|
|
961
|
+
}
|
|
962
|
+
layerFramebuffers.push(framebuffer);
|
|
963
|
+
if (!attachLayer(framebuffer, layer)) {
|
|
964
|
+
const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
|
|
965
|
+
cleanup();
|
|
966
|
+
if (depthRenderbufferHandle)
|
|
967
|
+
gl.deleteRenderbuffer(depthRenderbufferHandle);
|
|
968
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, previousFramebuffer);
|
|
969
|
+
gl.bindTexture(gl.TEXTURE_2D, previousTexture);
|
|
970
|
+
if (previousCubeTexture !== null)
|
|
971
|
+
gl.bindTexture(gl.TEXTURE_CUBE_MAP, previousCubeTexture);
|
|
972
|
+
if (previousArrayTexture !== null)
|
|
973
|
+
gl.bindTexture(gl.TEXTURE_2D_ARRAY, previousArrayTexture);
|
|
974
|
+
gl.activeTexture(previousActiveTexture);
|
|
975
|
+
this.stateCache.invalidate();
|
|
976
|
+
throw new RenderDeviceError("WebGL render target framebuffer status is invalid", "FRAMEBUFFER_INVALID", { status, layer, label });
|
|
822
977
|
}
|
|
823
|
-
this.drawNativeLdrStage(ldrSourceHandle, webglOutputTarget?.framebuffer ?? null, outputWidth, outputHeight, program, vertexArray, depthOfFieldOptions || motionBlurOptions || ssaoOptions || ssrOptions || taaOptions || outlineOptions ? undefined : tonePass, depthOfFieldOptions || motionBlurOptions || ssaoOptions || ssrOptions || taaOptions || outlineOptions ? undefined : colorPass, fxaaPass, options.toneMappingDefaults);
|
|
824
|
-
this.gl.flush();
|
|
825
|
-
}
|
|
826
|
-
finally {
|
|
827
|
-
this.restoreFullscreenPresentationState(previousState, outputWidth, outputHeight);
|
|
828
|
-
}
|
|
829
|
-
this.lastError = this.readError();
|
|
830
|
-
if (this.lastError) {
|
|
831
|
-
throw new RenderDeviceError(`WebGL2 LDR postprocess presentation failed: ${this.lastError}`, "WEBGL_LDR_POSTPROCESS_FAILED", {
|
|
832
|
-
targetId: source.id,
|
|
833
|
-
error: this.lastError
|
|
834
|
-
});
|
|
835
|
-
}
|
|
836
|
-
this.setRenderTarget(webglOutputTarget ?? null);
|
|
837
|
-
}
|
|
838
|
-
readPixels(x, y, width, height) {
|
|
839
|
-
this.assertAlive();
|
|
840
|
-
if (![x, y, width, height].every(Number.isInteger) || x < 0 || y < 0 || width <= 0 || height <= 0) {
|
|
841
|
-
throw new RenderDeviceError("Readback rectangle must be positive and in bounds", "INVALID_READBACK_RECT", { x, y, width, height });
|
|
842
|
-
}
|
|
843
|
-
const boundsWidth = this.activeRenderTarget?.width ?? this.gl.drawingBufferWidth;
|
|
844
|
-
const boundsHeight = this.activeRenderTarget?.height ?? this.gl.drawingBufferHeight;
|
|
845
|
-
if (x + width > boundsWidth || y + height > boundsHeight) {
|
|
846
|
-
throw new RenderDeviceError("Readback rectangle exceeds framebuffer bounds", "READBACK_OUT_OF_BOUNDS", {
|
|
847
|
-
x,
|
|
848
|
-
y,
|
|
849
|
-
width,
|
|
850
|
-
height,
|
|
851
|
-
boundsWidth,
|
|
852
|
-
boundsHeight
|
|
853
|
-
});
|
|
854
|
-
}
|
|
855
|
-
const readTarget = this.activeRenderTarget;
|
|
856
|
-
if (readTarget) {
|
|
857
|
-
this.resolveMultisampleTarget(readTarget);
|
|
858
|
-
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, readTarget.framebuffer);
|
|
859
|
-
}
|
|
860
|
-
const pixels = new Uint8Array(width * height * 4);
|
|
861
|
-
this.gl.readPixels(x, y, width, height, this.gl.RGBA, this.gl.UNSIGNED_BYTE, pixels);
|
|
862
|
-
if (readTarget && readTarget.sampleCount > 1) {
|
|
863
|
-
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, readTarget.drawFramebuffer);
|
|
864
|
-
this.stateCache.invalidate();
|
|
865
978
|
}
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
if (
|
|
871
|
-
|
|
979
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, previousFramebuffer);
|
|
980
|
+
gl.bindTexture(gl.TEXTURE_2D, previousTexture);
|
|
981
|
+
if (previousCubeTexture !== null)
|
|
982
|
+
gl.bindTexture(gl.TEXTURE_CUBE_MAP, previousCubeTexture);
|
|
983
|
+
if (previousArrayTexture !== null)
|
|
984
|
+
gl.bindTexture(gl.TEXTURE_2D_ARRAY, previousArrayTexture);
|
|
985
|
+
gl.activeTexture(previousActiveTexture);
|
|
986
|
+
this.stateCache.invalidate();
|
|
987
|
+
const colorTexture = colorTextures[0] ?? new Texture({ width: descriptor.width, height: descriptor.height, format: "rgba8", label: `${label}-colorless`, dimension, renderAttachment: true });
|
|
988
|
+
let parentColorHandle = colorHandles[0];
|
|
989
|
+
if (!parentColorHandle) {
|
|
990
|
+
// Depth-only targets keep a placeholder Texture in `colorTexture`; give it a
|
|
991
|
+
// real (never-attached, never-registered) GL handle so dispose stays sound.
|
|
992
|
+
parentColorHandle = gl.createTexture();
|
|
993
|
+
if (!parentColorHandle) {
|
|
994
|
+
cleanup();
|
|
995
|
+
if (depthRenderbufferHandle)
|
|
996
|
+
gl.deleteRenderbuffer(depthRenderbufferHandle);
|
|
997
|
+
throw new RenderDeviceError("Failed to allocate WebGL render target", "WEBGL_ALLOCATION_FAILED", { label });
|
|
998
|
+
}
|
|
872
999
|
}
|
|
873
|
-
const
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
1000
|
+
const target = new WebGL2RenderTarget(this.nextId++, descriptor.width, descriptor.height, label, colorTexture, depthTexture, layerFramebuffers[0], parentColorHandle, depthRenderbufferHandle, depthTextureHandle, 1, layerFramebuffers[0], null, gl, {
|
|
1001
|
+
dimension,
|
|
1002
|
+
layers: layerCount > 1 ? layerCount : undefined,
|
|
1003
|
+
colorTextures: colorTextures.length > 1 ? colorTextures : undefined,
|
|
1004
|
+
extraColorHandles: colorHandles.slice(1),
|
|
1005
|
+
layerFramebuffers,
|
|
1006
|
+
layerChild: false
|
|
1007
|
+
});
|
|
1008
|
+
if (layerCount > 1) {
|
|
1009
|
+
const children = layerFramebuffers.map((framebuffer, layer) => new WebGL2RenderTarget(this.nextId++, descriptor.width, descriptor.height, `${label}-layer-${layer}`, colorTexture, depthTexture, framebuffer, colorHandles[0], null, depthTextureHandle, 1, framebuffer, null, gl, { dimension, layers: 1, colorTextures: target.colorTextures, layerChild: true }));
|
|
1010
|
+
// layerTargets shares parent GL resources; children only mark dispose.
|
|
1011
|
+
target.layerTargets = children;
|
|
1012
|
+
for (const child of children) {
|
|
1013
|
+
this.renderTargets.add(child);
|
|
1014
|
+
}
|
|
884
1015
|
}
|
|
885
|
-
|
|
886
|
-
if (
|
|
887
|
-
this.
|
|
888
|
-
|
|
1016
|
+
this.renderTargets.add(target);
|
|
1017
|
+
if (/shadow|(?:^|-)csm(?:-|$)/i.test(label))
|
|
1018
|
+
this.host.counters.shadowRenderTargetsAllocated += 1;
|
|
1019
|
+
for (let attachment = 0; attachment < colorHandles.length; attachment += 1) {
|
|
1020
|
+
this.host.textureRegistry.textures.set(colorTextures[attachment], colorHandles[attachment]);
|
|
1021
|
+
this.host.textureRegistry.textureUploadModes.set(colorTextures[attachment], colorFormats[attachment]);
|
|
889
1022
|
}
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, readTarget.drawFramebuffer);
|
|
894
|
-
this.stateCache.invalidate();
|
|
1023
|
+
if (depthTexture && depthTextureHandle) {
|
|
1024
|
+
this.host.textureRegistry.textures.set(depthTexture, depthTextureHandle);
|
|
1025
|
+
this.host.textureRegistry.textureUploadModes.set(depthTexture, "depth-render-target");
|
|
895
1026
|
}
|
|
896
|
-
return
|
|
1027
|
+
return target;
|
|
897
1028
|
}
|
|
898
|
-
|
|
899
|
-
this.assertAlive();
|
|
900
|
-
if (
|
|
901
|
-
|
|
1029
|
+
setRenderTarget(target) {
|
|
1030
|
+
this.host.lifecycle.assertAlive();
|
|
1031
|
+
if (this.host.activeRenderTarget && this.host.activeRenderTarget !== target) {
|
|
1032
|
+
this.resolveMultisampleTarget(this.host.activeRenderTarget);
|
|
902
1033
|
}
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
1034
|
+
if (target === null) {
|
|
1035
|
+
this.host.activeRenderTarget = null;
|
|
1036
|
+
this.stateCache.bindFramebuffer(this.gl.FRAMEBUFFER, null, () => this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, null));
|
|
1037
|
+
this.stateCache.viewport(0, 0, this.host.lifecycle.viewportWidth || this.gl.drawingBufferWidth, this.host.lifecycle.viewportHeight || this.gl.drawingBufferHeight, () => this.gl.viewport(0, 0, this.host.lifecycle.viewportWidth || this.gl.drawingBufferWidth, this.host.lifecycle.viewportHeight || this.gl.drawingBufferHeight));
|
|
1038
|
+
return;
|
|
908
1039
|
}
|
|
909
|
-
if (
|
|
910
|
-
throw new RenderDeviceError("
|
|
911
|
-
|
|
912
|
-
y,
|
|
913
|
-
width,
|
|
914
|
-
height,
|
|
915
|
-
boundsWidth: target.width,
|
|
916
|
-
boundsHeight: target.height
|
|
1040
|
+
if (!(target instanceof WebGL2RenderTarget) || !this.renderTargets.has(target) || target.disposed) {
|
|
1041
|
+
throw new RenderDeviceError("Render target is not a live WebGL2 resource owned by this device", "INVALID_RESOURCE", {
|
|
1042
|
+
targetId: target.id
|
|
917
1043
|
});
|
|
918
1044
|
}
|
|
919
|
-
this.
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
for (let index = 0; index < pixels.length; index += 1) {
|
|
923
|
-
const byteIndex = index * 4;
|
|
924
|
-
const r = encoded[byteIndex] ?? 255;
|
|
925
|
-
const g = encoded[byteIndex + 1] ?? 255;
|
|
926
|
-
const b = encoded[byteIndex + 2] ?? 255;
|
|
927
|
-
pixels[index] = Math.max(0, Math.min(1, r / 255 + g / 65025 + b / 16581375));
|
|
928
|
-
}
|
|
929
|
-
return pixels;
|
|
930
|
-
}
|
|
931
|
-
beginFrame(width, height) {
|
|
932
|
-
this.assertAlive();
|
|
933
|
-
if (this.frameActive) {
|
|
934
|
-
throw new RenderDeviceError("Frame is already active", "FRAME_ALREADY_ACTIVE");
|
|
935
|
-
}
|
|
936
|
-
if (width <= 0 || height <= 0) {
|
|
937
|
-
throw new RenderDeviceError("Frame dimensions must be positive", "INVALID_FRAME_SIZE", { width, height });
|
|
938
|
-
}
|
|
939
|
-
this.frameActive = true;
|
|
940
|
-
this.drawCalls = 0;
|
|
941
|
-
this.nativeEnvironmentBindings = 0;
|
|
942
|
-
this.nativeShadowMapBindings = 0;
|
|
943
|
-
this.activeTextureUnitIndex = -1;
|
|
944
|
-
this.textureUnitBindings.clear();
|
|
945
|
-
this.stateCache.invalidate();
|
|
946
|
-
this.viewportWidth = width;
|
|
947
|
-
this.viewportHeight = height;
|
|
948
|
-
this.stateCache.bindFramebuffer(this.gl.FRAMEBUFFER, this.activeRenderTarget?.framebuffer ?? null, () => this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this.activeRenderTarget?.framebuffer ?? null));
|
|
949
|
-
this.stateCache.viewport(0, 0, width, height, () => this.gl.viewport(0, 0, width, height));
|
|
950
|
-
this.stateCache.setEnabled(this.gl.DEPTH_TEST, true, () => this.gl.enable(this.gl.DEPTH_TEST));
|
|
951
|
-
this.stateCache.depthFunc(this.gl.LEQUAL, () => this.gl.depthFunc(this.gl.LEQUAL));
|
|
952
|
-
}
|
|
953
|
-
clear(color) {
|
|
954
|
-
this.assertFrame();
|
|
955
|
-
this.gl.clearColor(color[0], color[1], color[2], color[3]);
|
|
956
|
-
this.stateCache.depthMask(true, () => this.gl.depthMask(true));
|
|
957
|
-
this.gl.clearDepth(1);
|
|
958
|
-
this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);
|
|
959
|
-
if (this.activeRenderTarget?.sampleCount && this.activeRenderTarget.sampleCount > 1)
|
|
960
|
-
this.activeRenderTarget.needsResolve = true;
|
|
961
|
-
}
|
|
962
|
-
clearRenderTarget(color) {
|
|
963
|
-
this.assertFrame();
|
|
964
|
-
this.gl.clearColor(color[0], color[1], color[2], color[3]);
|
|
965
|
-
this.stateCache.depthMask(true, () => this.gl.depthMask(true));
|
|
966
|
-
this.gl.clearDepth(1);
|
|
967
|
-
this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);
|
|
968
|
-
if (this.activeRenderTarget?.sampleCount && this.activeRenderTarget.sampleCount > 1)
|
|
969
|
-
this.activeRenderTarget.needsResolve = true;
|
|
1045
|
+
this.host.activeRenderTarget = target;
|
|
1046
|
+
this.stateCache.bindFramebuffer(this.gl.FRAMEBUFFER, target.drawFramebuffer, () => this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, target.drawFramebuffer));
|
|
1047
|
+
this.stateCache.viewport(0, 0, target.width, target.height, () => this.gl.viewport(0, 0, target.width, target.height));
|
|
970
1048
|
}
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
this.
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
if (uniformError) {
|
|
985
|
-
throw new RenderDeviceError(`WebGL2 uniform upload failed for draw ${command.label ?? "unnamed"}: ${uniformError}`, "WEBGL_DRAW_FAILED", {
|
|
986
|
-
label: command.label,
|
|
987
|
-
stage: "uniforms",
|
|
988
|
-
error: uniformError
|
|
989
|
-
});
|
|
990
|
-
}
|
|
991
|
-
}
|
|
992
|
-
}
|
|
993
|
-
}
|
|
994
|
-
if (shader && command.vertexFormat) {
|
|
995
|
-
this.bindVertexArrayForCommand(command, shader, vertexBuffer);
|
|
996
|
-
if (this.errorCheckMode === "strict") {
|
|
997
|
-
const vertexFormatError = this.readError();
|
|
998
|
-
if (vertexFormatError) {
|
|
999
|
-
throw new RenderDeviceError(`WebGL2 vertex format binding failed for draw ${command.label ?? "unnamed"}: ${vertexFormatError}`, "WEBGL_DRAW_FAILED", {
|
|
1000
|
-
label: command.label,
|
|
1001
|
-
stage: "vertex-format",
|
|
1002
|
-
error: vertexFormatError
|
|
1003
|
-
});
|
|
1004
|
-
}
|
|
1005
|
-
}
|
|
1006
|
-
}
|
|
1007
|
-
else {
|
|
1008
|
-
this.bindNoVertexArray();
|
|
1009
|
-
this.stateCache.bindBuffer(this.gl.ARRAY_BUFFER, vertexBuffer.handle, () => this.gl.bindBuffer(this.gl.ARRAY_BUFFER, vertexBuffer.handle));
|
|
1010
|
-
}
|
|
1011
|
-
if (command.indexBuffer) {
|
|
1012
|
-
const indexBuffer = this.requireBuffer(command.indexBuffer);
|
|
1013
|
-
if (!shader || !command.vertexFormat) {
|
|
1014
|
-
this.stateCache.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, indexBuffer.handle, () => this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, indexBuffer.handle));
|
|
1015
|
-
}
|
|
1016
|
-
const type = command.indexType === "uint32" ? this.gl.UNSIGNED_INT : this.gl.UNSIGNED_SHORT;
|
|
1017
|
-
const indexByteSize = command.indexType === "uint32" ? 4 : 2;
|
|
1018
|
-
const indexOffset = (command.firstIndex ?? 0) * indexByteSize;
|
|
1019
|
-
if ((command.instanceCount ?? 1) > 1) {
|
|
1020
|
-
this.gl.drawElementsInstanced(this.primitive(command.topology), command.indexCount ?? 0, type, indexOffset, command.instanceCount ?? 1);
|
|
1021
|
-
this.nativeInstancedSubmissions += 1;
|
|
1022
|
-
}
|
|
1023
|
-
else {
|
|
1024
|
-
this.gl.drawElements(this.primitive(command.topology), command.indexCount ?? 0, type, indexOffset);
|
|
1025
|
-
}
|
|
1026
|
-
}
|
|
1027
|
-
else {
|
|
1028
|
-
if ((command.instanceCount ?? 1) > 1) {
|
|
1029
|
-
this.gl.drawArraysInstanced(this.primitive(command.topology), command.firstVertex ?? 0, command.vertexCount, command.instanceCount ?? 1);
|
|
1030
|
-
this.nativeInstancedSubmissions += 1;
|
|
1031
|
-
}
|
|
1032
|
-
else {
|
|
1033
|
-
this.gl.drawArrays(this.primitive(command.topology), command.firstVertex ?? 0, command.vertexCount);
|
|
1034
|
-
}
|
|
1035
|
-
}
|
|
1036
|
-
this.drawCalls += 1;
|
|
1037
|
-
if (this.activeRenderTarget?.sampleCount && this.activeRenderTarget.sampleCount > 1)
|
|
1038
|
-
this.activeRenderTarget.needsResolve = true;
|
|
1039
|
-
if (this.errorCheckMode === "strict") {
|
|
1040
|
-
const drawError = this.readError();
|
|
1041
|
-
if (drawError) {
|
|
1042
|
-
throw new RenderDeviceError(`WebGL2 draw failed for ${command.label ?? "unnamed"}: ${drawError}`, "WEBGL_DRAW_FAILED", {
|
|
1043
|
-
label: command.label,
|
|
1044
|
-
stage: "draw",
|
|
1045
|
-
error: drawError
|
|
1046
|
-
});
|
|
1047
|
-
}
|
|
1048
|
-
}
|
|
1049
|
-
}
|
|
1050
|
-
endFrame() {
|
|
1051
|
-
this.assertFrame();
|
|
1052
|
-
this.frameActive = false;
|
|
1053
|
-
this.lastError = this.readError();
|
|
1049
|
+
resolveMultisampleTarget(target) {
|
|
1050
|
+
if (target.sampleCount <= 1 || !target.needsResolve)
|
|
1051
|
+
return;
|
|
1052
|
+
const previousFramebuffer = this.gl.getParameter(this.gl.FRAMEBUFFER_BINDING);
|
|
1053
|
+
this.gl.bindFramebuffer(this.gl.READ_FRAMEBUFFER, target.drawFramebuffer);
|
|
1054
|
+
this.gl.bindFramebuffer(this.gl.DRAW_FRAMEBUFFER, target.framebuffer);
|
|
1055
|
+
let mask = this.gl.COLOR_BUFFER_BIT;
|
|
1056
|
+
if (target.depthTextureHandle)
|
|
1057
|
+
mask |= this.gl.DEPTH_BUFFER_BIT;
|
|
1058
|
+
this.gl.blitFramebuffer(0, 0, target.width, target.height, 0, 0, target.width, target.height, mask, this.gl.NEAREST);
|
|
1059
|
+
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, previousFramebuffer);
|
|
1060
|
+
target.needsResolve = false;
|
|
1061
|
+
this.stateCache.invalidate();
|
|
1054
1062
|
}
|
|
1055
1063
|
captureState() {
|
|
1056
1064
|
const viewport = this.gl.getParameter(this.gl.VIEWPORT);
|
|
1057
1065
|
return new Map([
|
|
1058
1066
|
["backend", this.kind],
|
|
1059
|
-
["disposed", this.disposed],
|
|
1060
|
-
["contextLost", this.contextLost],
|
|
1061
|
-
["frameActive", this.frameActive],
|
|
1067
|
+
["disposed", this.host.disposed],
|
|
1068
|
+
["contextLost", this.host.contextLost],
|
|
1069
|
+
["frameActive", this.host.lifecycle.frameActive],
|
|
1062
1070
|
["depthTest", this.gl.isEnabled(this.gl.DEPTH_TEST)],
|
|
1063
1071
|
["blend", this.gl.isEnabled(this.gl.BLEND)],
|
|
1064
1072
|
["cullFace", this.gl.isEnabled(this.gl.CULL_FACE)],
|
|
1065
1073
|
["program", this.gl.getParameter(this.gl.CURRENT_PROGRAM) ? "bound" : null],
|
|
1066
1074
|
["arrayBuffer", this.gl.getParameter(this.gl.ARRAY_BUFFER_BINDING) ? "bound" : null],
|
|
1067
1075
|
["elementArrayBuffer", this.gl.getParameter(this.gl.ELEMENT_ARRAY_BUFFER_BINDING) ? "bound" : null],
|
|
1068
|
-
["viewportWidth", this.viewportWidth],
|
|
1069
|
-
["viewportHeight", this.viewportHeight],
|
|
1076
|
+
["viewportWidth", this.host.lifecycle.viewportWidth],
|
|
1077
|
+
["viewportHeight", this.host.lifecycle.viewportHeight],
|
|
1070
1078
|
["actualViewportWidth", viewport[2] ?? 0],
|
|
1071
1079
|
["actualViewportHeight", viewport[3] ?? 0],
|
|
1072
|
-
["renderTarget", this.activeRenderTarget?.label ?? null],
|
|
1073
|
-
["drawCalls", this.drawCalls],
|
|
1074
|
-
["nativeTemporalPasses", this.nativeTemporalPasses],
|
|
1075
|
-
["nativeTemporalBindings", this.nativeTemporalBindings],
|
|
1076
|
-
["shaderProgramCreates", this.shaderProgramCreateCount],
|
|
1077
|
-
["uniformLocationLookups", this.uniformLocationLookupCount],
|
|
1078
|
-
["bufferUpdates", this.bufferUpdateCount],
|
|
1079
|
-
["textureBinds", this.textureBindCount],
|
|
1080
|
-
["samplerParameterUploads", this.samplerParameterUploadCount],
|
|
1081
|
-
["vertexArrayCreates", this.vertexArrayCreateCount],
|
|
1082
|
-
["samplerObjects", this.samplerObjectCache.size],
|
|
1083
|
-
["samplerAnisotropyUploads", this.samplerAnisotropyUploadCount],
|
|
1080
|
+
["renderTarget", this.host.activeRenderTarget?.label ?? null],
|
|
1081
|
+
["drawCalls", this.host.counters.drawCalls],
|
|
1082
|
+
["nativeTemporalPasses", this.host.counters.nativeTemporalPasses],
|
|
1083
|
+
["nativeTemporalBindings", this.host.counters.nativeTemporalBindings],
|
|
1084
|
+
["shaderProgramCreates", this.host.counters.shaderProgramCreateCount],
|
|
1085
|
+
["uniformLocationLookups", this.host.counters.uniformLocationLookupCount],
|
|
1086
|
+
["bufferUpdates", this.host.counters.bufferUpdateCount],
|
|
1087
|
+
["textureBinds", this.host.counters.textureBindCount],
|
|
1088
|
+
["samplerParameterUploads", this.host.counters.samplerParameterUploadCount],
|
|
1089
|
+
["vertexArrayCreates", this.host.counters.vertexArrayCreateCount],
|
|
1090
|
+
["samplerObjects", this.host.samplers.samplerObjectCache.size],
|
|
1091
|
+
["samplerAnisotropyUploads", this.host.counters.samplerAnisotropyUploadCount],
|
|
1084
1092
|
["maxTextureAnisotropy", this.maxTextureAnisotropy],
|
|
1085
|
-
["nativeEnvironmentBindings", this.nativeEnvironmentBindings],
|
|
1086
|
-
["nativeShadowMapBindings", this.nativeShadowMapBindings],
|
|
1087
|
-
["nativeInstancedSubmissions", this.nativeInstancedSubmissions],
|
|
1093
|
+
["nativeEnvironmentBindings", this.host.counters.nativeEnvironmentBindings],
|
|
1094
|
+
["nativeShadowMapBindings", this.host.counters.nativeShadowMapBindings],
|
|
1095
|
+
["nativeInstancedSubmissions", this.host.counters.nativeInstancedSubmissions],
|
|
1088
1096
|
["stateCacheIssued", this.stateCache.stats().issued],
|
|
1089
1097
|
["stateCacheSkipped", this.stateCache.stats().skipped]
|
|
1090
1098
|
]);
|
|
1091
1099
|
}
|
|
1092
1100
|
getDiagnostics() {
|
|
1093
|
-
this.releaseDisposedTextureHandles();
|
|
1101
|
+
this.host.textureRegistry.releaseDisposedTextureHandles();
|
|
1094
1102
|
const liveRenderTargets = [...this.renderTargets].filter((target) => !target.disposed);
|
|
1095
1103
|
const liveTextures = new Set([
|
|
1096
1104
|
...liveRenderTargets.map((target) => target.colorTexture),
|
|
1097
|
-
...[...this.textures.keys()].filter((texture) => !texture.disposed)
|
|
1105
|
+
...[...this.host.textureRegistry.textures.keys()].filter((texture) => !texture.disposed)
|
|
1098
1106
|
]);
|
|
1099
1107
|
const liveTextureList = [...liveTextures];
|
|
1100
1108
|
const compressedTextures = liveTextureList.filter((texture) => isCompressedTextureFormat(texture.format));
|
|
1101
|
-
const fallbackTextures = liveTextureList.filter((texture) => this.textureUploadModes.get(texture) === "fallback");
|
|
1109
|
+
const fallbackTextures = liveTextureList.filter((texture) => this.host.textureRegistry.textureUploadModes.get(texture) === "fallback");
|
|
1102
1110
|
const stateCacheStats = this.stateCache.stats();
|
|
1103
1111
|
const bufferBytes = [...this.buffers].filter((buffer) => !buffer.disposed).reduce((total, buffer) => total + buffer.byteLength, 0);
|
|
1104
1112
|
const textureBytes = liveTextureList.reduce((total, texture) => total + texture.byteLength, 0);
|
|
1105
|
-
const gpuTargetEntries = this.describeGpuTargetInventory(liveRenderTargets);
|
|
1113
|
+
const gpuTargetEntries = this.host.post.describeGpuTargetInventory(liveRenderTargets);
|
|
1106
1114
|
return {
|
|
1107
|
-
drawCalls: this.drawCalls,
|
|
1115
|
+
drawCalls: this.host.counters.drawCalls,
|
|
1108
1116
|
buffers: [...this.buffers].filter((buffer) => !buffer.disposed).length,
|
|
1109
1117
|
shaders: [...this.shaders].filter((shader) => !shader.disposed).length,
|
|
1110
1118
|
renderTargets: liveRenderTargets.length,
|
|
@@ -1117,14 +1125,14 @@ export class WebGL2Device {
|
|
|
1117
1125
|
compressedTextureBytes: compressedTextures.reduce((total, texture) => total + texture.byteLength, 0),
|
|
1118
1126
|
textureFallbacks: fallbackTextures.length,
|
|
1119
1127
|
textureFallbackBytes: fallbackTextures.reduce((total, texture) => total + texture.fallbackByteLength, 0),
|
|
1120
|
-
nativeEnvironmentBindings: this.nativeEnvironmentBindings,
|
|
1121
|
-
nativeShadowMapBindings: this.nativeShadowMapBindings,
|
|
1122
|
-
shadowRenderTargetsAllocated: this.shadowRenderTargetsAllocated,
|
|
1123
|
-
nativeInstancedSubmissions: this.nativeInstancedSubmissions,
|
|
1124
|
-
bloom: this.lastBloomDiagnostics,
|
|
1125
|
-
nativeTemporalPasses: this.nativeTemporalPasses,
|
|
1126
|
-
nativeTemporalBindings: this.nativeTemporalBindings,
|
|
1127
|
-
samplerAnisotropyUploads: this.samplerAnisotropyUploadCount,
|
|
1128
|
+
nativeEnvironmentBindings: this.host.counters.nativeEnvironmentBindings,
|
|
1129
|
+
nativeShadowMapBindings: this.host.counters.nativeShadowMapBindings,
|
|
1130
|
+
shadowRenderTargetsAllocated: this.host.counters.shadowRenderTargetsAllocated,
|
|
1131
|
+
nativeInstancedSubmissions: this.host.counters.nativeInstancedSubmissions,
|
|
1132
|
+
bloom: this.host.post.lastBloomDiagnostics,
|
|
1133
|
+
nativeTemporalPasses: this.host.counters.nativeTemporalPasses,
|
|
1134
|
+
nativeTemporalBindings: this.host.counters.nativeTemporalBindings,
|
|
1135
|
+
samplerAnisotropyUploads: this.host.counters.samplerAnisotropyUploadCount,
|
|
1128
1136
|
maxTextureAnisotropy: this.maxTextureAnisotropy,
|
|
1129
1137
|
stateCacheIssued: stateCacheStats.issued,
|
|
1130
1138
|
stateCacheSkipped: stateCacheStats.skipped,
|
|
@@ -1133,23 +1141,25 @@ export class WebGL2Device {
|
|
|
1133
1141
|
stateCacheBufferBinds: stateCacheStats.byOperation.bindBuffer?.issued ?? 0,
|
|
1134
1142
|
stateCacheVertexArrayBinds: stateCacheStats.byOperation.bindVertexArray?.issued ?? 0,
|
|
1135
1143
|
stateCacheSamplerBinds: stateCacheStats.byOperation.bindSampler?.issued ?? 0,
|
|
1136
|
-
disposedBuffers: [...this.buffers].filter((buffer) => buffer.disposed).length,
|
|
1144
|
+
disposedBuffers: this.disposedBufferCount + [...this.buffers].filter((buffer) => buffer.disposed).length,
|
|
1137
1145
|
disposedShaders: [...this.shaders].filter((shader) => shader.disposed).length,
|
|
1138
1146
|
disposedRenderTargets: [...this.renderTargets].filter((target) => target.disposed).length,
|
|
1139
|
-
disposedTextures: [...this.renderTargets].filter((target) => target.colorTexture.disposed).length + this.releasedTextureHandles,
|
|
1147
|
+
disposedTextures: [...this.renderTargets].filter((target) => target.colorTexture.disposed).length + this.host.counters.releasedTextureHandles,
|
|
1140
1148
|
...spreadGpuTargetInventory(gpuTargetEntries),
|
|
1141
|
-
|
|
1142
|
-
|
|
1149
|
+
programCompileCount: this.host.counters.programCompiles,
|
|
1150
|
+
readPixelsCalls: this.host.counters.readbacks,
|
|
1151
|
+
lastError: this.host.lifecycle.lastError,
|
|
1152
|
+
contextLost: this.host.contextLost
|
|
1143
1153
|
};
|
|
1144
1154
|
}
|
|
1145
1155
|
dispose() {
|
|
1146
|
-
if (this.canvas && "removeEventListener" in this.canvas) {
|
|
1147
|
-
this.deviceLostListeners.clear();
|
|
1148
|
-
this.deviceRestoredListeners.clear();
|
|
1149
|
-
if (this.contextLostListener)
|
|
1150
|
-
this.canvas.removeEventListener("webglcontextlost", this.contextLostListener);
|
|
1151
|
-
if (this.contextRestoredListener)
|
|
1152
|
-
this.canvas.removeEventListener("webglcontextrestored", this.contextRestoredListener);
|
|
1156
|
+
if (this.host.lifecycle.canvas && "removeEventListener" in this.host.lifecycle.canvas) {
|
|
1157
|
+
this.host.lifecycle.deviceLostListeners.clear();
|
|
1158
|
+
this.host.lifecycle.deviceRestoredListeners.clear();
|
|
1159
|
+
if (this.host.lifecycle.contextLostListener)
|
|
1160
|
+
this.host.lifecycle.canvas.removeEventListener("webglcontextlost", this.host.lifecycle.contextLostListener);
|
|
1161
|
+
if (this.host.lifecycle.contextRestoredListener)
|
|
1162
|
+
this.host.lifecycle.canvas.removeEventListener("webglcontextrestored", this.host.lifecycle.contextRestoredListener);
|
|
1153
1163
|
}
|
|
1154
1164
|
for (const buffer of this.buffers) {
|
|
1155
1165
|
buffer.dispose();
|
|
@@ -1160,2867 +1170,160 @@ export class WebGL2Device {
|
|
|
1160
1170
|
for (const target of this.renderTargets) {
|
|
1161
1171
|
target.dispose();
|
|
1162
1172
|
}
|
|
1163
|
-
for (const entry of this.vertexArrayCache.values()) {
|
|
1173
|
+
for (const entry of this.host.drawBinder.vertexArrayCache.values()) {
|
|
1164
1174
|
this.gl.deleteVertexArray(entry.handle);
|
|
1165
1175
|
}
|
|
1166
|
-
this.vertexArrayCache.clear();
|
|
1167
|
-
for (const sampler of this.samplerObjectCache.values()) {
|
|
1176
|
+
this.host.drawBinder.vertexArrayCache.clear();
|
|
1177
|
+
for (const sampler of this.host.samplers.samplerObjectCache.values()) {
|
|
1168
1178
|
this.gl.deleteSampler(sampler);
|
|
1169
1179
|
}
|
|
1170
|
-
this.samplerObjectCache.clear();
|
|
1171
|
-
for (const texture of this.textures.values()) {
|
|
1180
|
+
this.host.samplers.samplerObjectCache.clear();
|
|
1181
|
+
for (const texture of this.host.textureRegistry.textures.values()) {
|
|
1172
1182
|
this.gl.deleteTexture(texture);
|
|
1173
1183
|
}
|
|
1174
|
-
this.textureUploadModes.clear();
|
|
1175
|
-
if (this.fallbackTexture) {
|
|
1176
|
-
this.gl.deleteTexture(this.fallbackTexture);
|
|
1177
|
-
this.fallbackTexture = null;
|
|
1178
|
-
}
|
|
1179
|
-
if (this.fallbackCubeTexture) {
|
|
1180
|
-
this.gl.deleteTexture(this.fallbackCubeTexture);
|
|
1181
|
-
this.fallbackCubeTexture = null;
|
|
1182
|
-
}
|
|
1183
|
-
if (this.presentationProgram) {
|
|
1184
|
-
this.gl.deleteProgram(this.presentationProgram);
|
|
1185
|
-
this.presentationProgram = null;
|
|
1186
|
-
}
|
|
1187
|
-
if (this.ldrPostprocessProgram) {
|
|
1188
|
-
this.gl.deleteProgram(this.ldrPostprocessProgram);
|
|
1189
|
-
this.ldrPostprocessProgram = null;
|
|
1190
|
-
}
|
|
1191
|
-
if (this.bloomBrightExtractProgram) {
|
|
1192
|
-
this.gl.deleteProgram(this.bloomBrightExtractProgram);
|
|
1193
|
-
this.bloomBrightExtractProgram = null;
|
|
1194
|
-
}
|
|
1195
|
-
if (this.bloomBlurProgram) {
|
|
1196
|
-
this.gl.deleteProgram(this.bloomBlurProgram);
|
|
1197
|
-
this.bloomBlurProgram = null;
|
|
1198
|
-
}
|
|
1199
|
-
if (this.bloomCompositeProgram) {
|
|
1200
|
-
this.gl.deleteProgram(this.bloomCompositeProgram);
|
|
1201
|
-
this.bloomCompositeProgram = null;
|
|
1202
|
-
}
|
|
1203
|
-
if (this.bloomDownsampleProgram) {
|
|
1204
|
-
this.gl.deleteProgram(this.bloomDownsampleProgram);
|
|
1205
|
-
this.bloomDownsampleProgram = null;
|
|
1206
|
-
}
|
|
1207
|
-
if (this.bloomAccumulateProgram) {
|
|
1208
|
-
this.gl.deleteProgram(this.bloomAccumulateProgram);
|
|
1209
|
-
this.bloomAccumulateProgram = null;
|
|
1210
|
-
}
|
|
1211
|
-
if (this.outlineProgram) {
|
|
1212
|
-
this.gl.deleteProgram(this.outlineProgram);
|
|
1213
|
-
this.outlineProgram = null;
|
|
1214
|
-
}
|
|
1215
|
-
if (this.ssaoProgram) {
|
|
1216
|
-
this.gl.deleteProgram(this.ssaoProgram);
|
|
1217
|
-
this.ssaoProgram = null;
|
|
1218
|
-
}
|
|
1219
|
-
if (this.ssrProgram) {
|
|
1220
|
-
this.gl.deleteProgram(this.ssrProgram);
|
|
1221
|
-
this.ssrProgram = null;
|
|
1222
|
-
}
|
|
1223
|
-
if (this.depthOfFieldProgram) {
|
|
1224
|
-
this.gl.deleteProgram(this.depthOfFieldProgram);
|
|
1225
|
-
this.depthOfFieldProgram = null;
|
|
1226
|
-
}
|
|
1227
|
-
if (this.motionBlurProgram) {
|
|
1228
|
-
this.gl.deleteProgram(this.motionBlurProgram);
|
|
1229
|
-
this.motionBlurProgram = null;
|
|
1230
|
-
}
|
|
1231
|
-
if (this.motionBlurVelocityTexture) {
|
|
1232
|
-
this.gl.deleteTexture(this.motionBlurVelocityTexture);
|
|
1233
|
-
this.motionBlurVelocityTexture = null;
|
|
1234
|
-
this.motionBlurVelocitySize = null;
|
|
1235
|
-
}
|
|
1236
|
-
if (this.taaProgram) {
|
|
1237
|
-
this.gl.deleteProgram(this.taaProgram);
|
|
1238
|
-
this.taaProgram = null;
|
|
1239
|
-
}
|
|
1240
|
-
if (this.taaPresentationProgram) {
|
|
1241
|
-
this.gl.deleteProgram(this.taaPresentationProgram);
|
|
1242
|
-
this.taaPresentationProgram = null;
|
|
1243
|
-
}
|
|
1244
|
-
if (this.taaHistoryTexture) {
|
|
1245
|
-
this.gl.deleteTexture(this.taaHistoryTexture);
|
|
1246
|
-
this.taaHistoryTexture = null;
|
|
1247
|
-
this.taaHistorySize = null;
|
|
1248
|
-
}
|
|
1249
|
-
this.disposeBloomPingPongResources();
|
|
1250
|
-
this.disposeBloomPyramidResources();
|
|
1251
|
-
if (this.bloomBrightLutTexture) {
|
|
1252
|
-
this.gl.deleteTexture(this.bloomBrightLutTexture);
|
|
1253
|
-
this.bloomBrightLutTexture = null;
|
|
1254
|
-
this.bloomBrightLutThreshold = null;
|
|
1255
|
-
}
|
|
1256
|
-
if (this.bloomCompositeLutTexture) {
|
|
1257
|
-
this.gl.deleteTexture(this.bloomCompositeLutTexture);
|
|
1258
|
-
this.bloomCompositeLutTexture = null;
|
|
1259
|
-
this.bloomCompositeLutIntensity = null;
|
|
1260
|
-
this.bloomCompositeLutShoulder = null;
|
|
1261
|
-
}
|
|
1262
|
-
if (this.outlineBlendLutTexture) {
|
|
1263
|
-
this.gl.deleteTexture(this.outlineBlendLutTexture);
|
|
1264
|
-
this.outlineBlendLutTexture = null;
|
|
1265
|
-
this.outlineBlendLutKey = null;
|
|
1266
|
-
}
|
|
1267
|
-
if (this.presentationVertexArray) {
|
|
1268
|
-
this.gl.deleteVertexArray(this.presentationVertexArray);
|
|
1269
|
-
this.presentationVertexArray = null;
|
|
1270
|
-
}
|
|
1271
|
-
if (this.depthReadbackProgram) {
|
|
1272
|
-
this.gl.deleteProgram(this.depthReadbackProgram);
|
|
1273
|
-
this.depthReadbackProgram = null;
|
|
1274
|
-
}
|
|
1275
|
-
this.textures.clear();
|
|
1276
|
-
this.disposed = true;
|
|
1277
|
-
}
|
|
1278
|
-
copyDepthTextureToBytes(source, x, y, width, height) {
|
|
1279
|
-
const colorHandle = this.gl.createTexture();
|
|
1280
|
-
const framebuffer = this.gl.createFramebuffer();
|
|
1281
|
-
if (!colorHandle || !framebuffer) {
|
|
1282
|
-
if (colorHandle)
|
|
1283
|
-
this.gl.deleteTexture(colorHandle);
|
|
1284
|
-
if (framebuffer)
|
|
1285
|
-
this.gl.deleteFramebuffer(framebuffer);
|
|
1286
|
-
throw new RenderDeviceError("Failed to allocate WebGL2 depth readback target", "WEBGL_ALLOCATION_FAILED", {
|
|
1287
|
-
renderTarget: source.label
|
|
1288
|
-
});
|
|
1289
|
-
}
|
|
1290
|
-
const previousFramebuffer = this.gl.getParameter(this.gl.FRAMEBUFFER_BINDING);
|
|
1291
|
-
const previousProgram = this.gl.getParameter(this.gl.CURRENT_PROGRAM);
|
|
1292
|
-
const textureUnit0 = this.captureTextureUnit0();
|
|
1293
|
-
const viewport = this.gl.getParameter(this.gl.VIEWPORT);
|
|
1294
|
-
const depthTestEnabled = this.gl.isEnabled(this.gl.DEPTH_TEST);
|
|
1295
|
-
const depthMask = this.gl.getParameter(this.gl.DEPTH_WRITEMASK);
|
|
1296
|
-
const cullFaceEnabled = this.gl.isEnabled(this.gl.CULL_FACE);
|
|
1297
|
-
const blendEnabled = this.gl.isEnabled(this.gl.BLEND);
|
|
1298
|
-
const pixels = new Uint8Array(width * height * 4);
|
|
1299
|
-
try {
|
|
1300
|
-
this.gl.activeTexture(this.gl.TEXTURE0);
|
|
1301
|
-
this.gl.bindTexture(this.gl.TEXTURE_2D, colorHandle);
|
|
1302
|
-
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.NEAREST);
|
|
1303
|
-
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.NEAREST);
|
|
1304
|
-
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);
|
|
1305
|
-
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);
|
|
1306
|
-
this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA8, width, height, 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, null);
|
|
1307
|
-
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, framebuffer);
|
|
1308
|
-
this.gl.framebufferTexture2D(this.gl.FRAMEBUFFER, this.gl.COLOR_ATTACHMENT0, this.gl.TEXTURE_2D, colorHandle, 0);
|
|
1309
|
-
const status = this.gl.checkFramebufferStatus(this.gl.FRAMEBUFFER);
|
|
1310
|
-
if (status !== this.gl.FRAMEBUFFER_COMPLETE) {
|
|
1311
|
-
throw new RenderDeviceError("WebGL2 depth readback framebuffer status is invalid", "FRAMEBUFFER_INVALID", {
|
|
1312
|
-
renderTarget: source.label,
|
|
1313
|
-
status
|
|
1314
|
-
});
|
|
1315
|
-
}
|
|
1316
|
-
this.gl.viewport(0, 0, width, height);
|
|
1317
|
-
this.gl.disable(this.gl.DEPTH_TEST);
|
|
1318
|
-
this.gl.disable(this.gl.CULL_FACE);
|
|
1319
|
-
this.gl.disable(this.gl.BLEND);
|
|
1320
|
-
this.gl.depthMask(false);
|
|
1321
|
-
this.gl.useProgram(this.ensureDepthReadbackProgram());
|
|
1322
|
-
this.gl.activeTexture(this.gl.TEXTURE0);
|
|
1323
|
-
this.gl.bindTexture(this.gl.TEXTURE_2D, source.depthTextureHandle);
|
|
1324
|
-
this.gl.bindSampler(0, null);
|
|
1325
|
-
this.gl.uniform1i(this.gl.getUniformLocation(this.ensureDepthReadbackProgram(), "u_depth"), 0);
|
|
1326
|
-
this.gl.uniform4f(this.gl.getUniformLocation(this.ensureDepthReadbackProgram(), "u_sourceRect"), x / source.width, y / source.height, width / source.width, height / source.height);
|
|
1327
|
-
this.gl.drawArrays(this.gl.TRIANGLES, 0, 3);
|
|
1328
|
-
this.gl.readPixels(0, 0, width, height, this.gl.RGBA, this.gl.UNSIGNED_BYTE, pixels);
|
|
1329
|
-
const error = this.readError();
|
|
1330
|
-
if (error) {
|
|
1331
|
-
throw new RenderDeviceError("WebGL2 depth texture readback failed", "WEBGL_DEPTH_READBACK_FAILED", {
|
|
1332
|
-
renderTarget: source.label,
|
|
1333
|
-
error
|
|
1334
|
-
});
|
|
1335
|
-
}
|
|
1336
|
-
return pixels;
|
|
1337
|
-
}
|
|
1338
|
-
finally {
|
|
1339
|
-
this.restoreTextureUnit0(textureUnit0);
|
|
1340
|
-
this.gl.useProgram(previousProgram);
|
|
1341
|
-
if (depthTestEnabled)
|
|
1342
|
-
this.gl.enable(this.gl.DEPTH_TEST);
|
|
1343
|
-
else
|
|
1344
|
-
this.gl.disable(this.gl.DEPTH_TEST);
|
|
1345
|
-
if (cullFaceEnabled)
|
|
1346
|
-
this.gl.enable(this.gl.CULL_FACE);
|
|
1347
|
-
else
|
|
1348
|
-
this.gl.disable(this.gl.CULL_FACE);
|
|
1349
|
-
if (blendEnabled)
|
|
1350
|
-
this.gl.enable(this.gl.BLEND);
|
|
1351
|
-
else
|
|
1352
|
-
this.gl.disable(this.gl.BLEND);
|
|
1353
|
-
this.gl.depthMask(depthMask);
|
|
1354
|
-
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, previousFramebuffer);
|
|
1355
|
-
this.gl.viewport(viewport[0] ?? 0, viewport[1] ?? 0, viewport[2] ?? this.viewportWidth, viewport[3] ?? this.viewportHeight);
|
|
1356
|
-
this.gl.deleteTexture(colorHandle);
|
|
1357
|
-
this.gl.deleteFramebuffer(framebuffer);
|
|
1358
|
-
this.stateCache.invalidate();
|
|
1359
|
-
}
|
|
1360
|
-
}
|
|
1361
|
-
drawRenderTargetToBackbuffer(source, outputWidth, outputHeight) {
|
|
1362
|
-
const program = this.ensurePresentationProgram();
|
|
1363
|
-
const vertexArray = this.ensurePresentationVertexArray();
|
|
1364
|
-
const previousState = this.prepareFullscreenPresentation(null, outputWidth, outputHeight);
|
|
1365
|
-
this.gl.useProgram(program);
|
|
1366
|
-
this.gl.bindVertexArray(vertexArray);
|
|
1367
|
-
this.gl.activeTexture(this.gl.TEXTURE0);
|
|
1368
|
-
this.gl.bindTexture(this.gl.TEXTURE_2D, source.colorHandle);
|
|
1369
|
-
this.gl.bindSampler(0, null);
|
|
1370
|
-
try {
|
|
1371
|
-
const uniformLocation = this.gl.getUniformLocation(program, "u_source");
|
|
1372
|
-
this.gl.uniform1i(uniformLocation, 0);
|
|
1373
|
-
this.gl.drawArrays(this.gl.TRIANGLES, 0, 3);
|
|
1374
|
-
this.gl.flush();
|
|
1375
|
-
}
|
|
1376
|
-
finally {
|
|
1377
|
-
this.restoreFullscreenPresentationState(previousState, outputWidth, outputHeight);
|
|
1378
|
-
}
|
|
1379
|
-
}
|
|
1380
|
-
ensureBloomPingPongResources(width, height, hdr = false) {
|
|
1381
|
-
const current = this.bloomPingPongResources;
|
|
1382
|
-
if (current && current.width === width && current.height === height && current.hdr === hdr) {
|
|
1383
|
-
return current;
|
|
1384
|
-
}
|
|
1385
|
-
this.disposeBloomPingPongResources();
|
|
1386
|
-
this.disposeBloomPyramidResources();
|
|
1387
|
-
const textureUnit0 = this.captureTextureUnit0();
|
|
1388
|
-
const previousFramebuffer = this.gl.getParameter(this.gl.FRAMEBUFFER_BINDING);
|
|
1389
|
-
const textures = [];
|
|
1390
|
-
const framebuffers = [];
|
|
1391
|
-
try {
|
|
1392
|
-
for (let index = 0; index < 2; index += 1) {
|
|
1393
|
-
const texture = this.gl.createTexture();
|
|
1394
|
-
const framebuffer = this.gl.createFramebuffer();
|
|
1395
|
-
if (!texture || !framebuffer) {
|
|
1396
|
-
if (texture)
|
|
1397
|
-
this.gl.deleteTexture(texture);
|
|
1398
|
-
if (framebuffer)
|
|
1399
|
-
this.gl.deleteFramebuffer(framebuffer);
|
|
1400
|
-
throw new RenderDeviceError("Failed to allocate WebGL2 bloom ping-pong resources", "WEBGL_ALLOCATION_FAILED", {
|
|
1401
|
-
width,
|
|
1402
|
-
height,
|
|
1403
|
-
index
|
|
1404
|
-
});
|
|
1405
|
-
}
|
|
1406
|
-
textures.push(texture);
|
|
1407
|
-
framebuffers.push(framebuffer);
|
|
1408
|
-
this.gl.bindTexture(this.gl.TEXTURE_2D, texture);
|
|
1409
|
-
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.NEAREST);
|
|
1410
|
-
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.NEAREST);
|
|
1411
|
-
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);
|
|
1412
|
-
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);
|
|
1413
|
-
this.gl.texImage2D(this.gl.TEXTURE_2D, 0, hdr ? this.gl.RGBA16F : this.gl.RGBA8, width, height, 0, this.gl.RGBA, hdr ? this.gl.HALF_FLOAT : this.gl.UNSIGNED_BYTE, null);
|
|
1414
|
-
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, framebuffer);
|
|
1415
|
-
this.gl.framebufferTexture2D(this.gl.FRAMEBUFFER, this.gl.COLOR_ATTACHMENT0, this.gl.TEXTURE_2D, texture, 0);
|
|
1416
|
-
const status = this.gl.checkFramebufferStatus(this.gl.FRAMEBUFFER);
|
|
1417
|
-
if (status !== this.gl.FRAMEBUFFER_COMPLETE) {
|
|
1418
|
-
throw new RenderDeviceError("WebGL2 bloom ping-pong framebuffer status is invalid", "FRAMEBUFFER_INVALID", {
|
|
1419
|
-
width,
|
|
1420
|
-
height,
|
|
1421
|
-
index,
|
|
1422
|
-
status
|
|
1423
|
-
});
|
|
1424
|
-
}
|
|
1425
|
-
}
|
|
1426
|
-
const resources = {
|
|
1427
|
-
width,
|
|
1428
|
-
height,
|
|
1429
|
-
hdr,
|
|
1430
|
-
textures: [textures[0], textures[1]],
|
|
1431
|
-
framebuffers: [framebuffers[0], framebuffers[1]]
|
|
1432
|
-
};
|
|
1433
|
-
this.bloomPingPongResources = resources;
|
|
1434
|
-
return resources;
|
|
1435
|
-
}
|
|
1436
|
-
catch (error) {
|
|
1437
|
-
for (const texture of textures)
|
|
1438
|
-
this.gl.deleteTexture(texture);
|
|
1439
|
-
for (const framebuffer of framebuffers)
|
|
1440
|
-
this.gl.deleteFramebuffer(framebuffer);
|
|
1441
|
-
throw error;
|
|
1442
|
-
}
|
|
1443
|
-
finally {
|
|
1444
|
-
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, previousFramebuffer);
|
|
1445
|
-
this.restoreTextureUnit0(textureUnit0);
|
|
1446
|
-
this.stateCache.invalidate();
|
|
1447
|
-
}
|
|
1448
|
-
}
|
|
1449
|
-
ensureBloomLutTextures(options) {
|
|
1450
|
-
const updateBright = this.bloomBrightLutThreshold !== options.threshold;
|
|
1451
|
-
const updateComposite = this.bloomCompositeLutIntensity !== options.intensity ||
|
|
1452
|
-
this.bloomCompositeLutShoulder !== options.shoulder;
|
|
1453
|
-
if (this.bloomBrightLutTexture && this.bloomCompositeLutTexture && !updateBright && !updateComposite) {
|
|
1454
|
-
return;
|
|
1455
|
-
}
|
|
1456
|
-
const textureUnit0 = this.captureTextureUnit0();
|
|
1457
|
-
try {
|
|
1458
|
-
if (!this.bloomBrightLutTexture) {
|
|
1459
|
-
this.bloomBrightLutTexture = this.createNativeBloomDataTexture();
|
|
1460
|
-
}
|
|
1461
|
-
if (updateBright) {
|
|
1462
|
-
const pixels = createBloomBrightThresholdLut(options.threshold);
|
|
1463
|
-
this.gl.bindTexture(this.gl.TEXTURE_2D, this.bloomBrightLutTexture);
|
|
1464
|
-
this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA8, BLOOM_BRIGHT_LUT_WIDTH, BLOOM_BRIGHT_LUT_HEIGHT, 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, pixels);
|
|
1465
|
-
this.bloomBrightLutThreshold = options.threshold;
|
|
1466
|
-
}
|
|
1467
|
-
if (!this.bloomCompositeLutTexture) {
|
|
1468
|
-
this.bloomCompositeLutTexture = this.createNativeBloomDataTexture();
|
|
1469
|
-
}
|
|
1470
|
-
if (updateComposite) {
|
|
1471
|
-
const pixels = createBloomCompositeLut(options.intensity, { shoulder: options.shoulder });
|
|
1472
|
-
this.gl.bindTexture(this.gl.TEXTURE_2D, this.bloomCompositeLutTexture);
|
|
1473
|
-
this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA8, BLOOM_COMPOSITE_LUT_SIZE, BLOOM_COMPOSITE_LUT_SIZE, 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, pixels);
|
|
1474
|
-
this.bloomCompositeLutIntensity = options.intensity;
|
|
1475
|
-
this.bloomCompositeLutShoulder = options.shoulder;
|
|
1476
|
-
}
|
|
1477
|
-
}
|
|
1478
|
-
finally {
|
|
1479
|
-
this.restoreTextureUnit0(textureUnit0);
|
|
1480
|
-
this.stateCache.invalidate();
|
|
1481
|
-
}
|
|
1482
|
-
}
|
|
1483
|
-
createNativeBloomDataTexture() {
|
|
1484
|
-
const texture = this.gl.createTexture();
|
|
1485
|
-
if (!texture) {
|
|
1486
|
-
throw new RenderDeviceError("Failed to allocate WebGL2 bloom lookup texture", "WEBGL_ALLOCATION_FAILED");
|
|
1487
|
-
}
|
|
1488
|
-
this.gl.bindTexture(this.gl.TEXTURE_2D, texture);
|
|
1489
|
-
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.NEAREST);
|
|
1490
|
-
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.NEAREST);
|
|
1491
|
-
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);
|
|
1492
|
-
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);
|
|
1493
|
-
return texture;
|
|
1494
|
-
}
|
|
1495
|
-
ensureOutlineBlendLutTexture(options) {
|
|
1496
|
-
const combinedAlpha = options.opacity * (options.color[3] / 255);
|
|
1497
|
-
const key = `${options.color.join(",")}|${combinedAlpha}`;
|
|
1498
|
-
if (this.outlineBlendLutTexture && this.outlineBlendLutKey === key)
|
|
1499
|
-
return;
|
|
1500
|
-
const textureUnit0 = this.captureTextureUnit0();
|
|
1501
|
-
try {
|
|
1502
|
-
if (!this.outlineBlendLutTexture) {
|
|
1503
|
-
this.outlineBlendLutTexture = this.createNativeBloomDataTexture();
|
|
1504
|
-
}
|
|
1505
|
-
this.gl.bindTexture(this.gl.TEXTURE_2D, this.outlineBlendLutTexture);
|
|
1506
|
-
this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA8, OUTLINE_BLEND_LUT_WIDTH, 1, 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, createOutlineBlendLut(options.color, combinedAlpha));
|
|
1507
|
-
this.outlineBlendLutKey = key;
|
|
1508
|
-
}
|
|
1509
|
-
finally {
|
|
1510
|
-
this.restoreTextureUnit0(textureUnit0);
|
|
1511
|
-
this.stateCache.invalidate();
|
|
1512
|
-
}
|
|
1513
|
-
}
|
|
1514
|
-
ensureMotionBlurVelocityTexture(width, height, velocity) {
|
|
1515
|
-
const textureUnit0 = this.captureTextureUnit0();
|
|
1516
|
-
try {
|
|
1517
|
-
if (!this.motionBlurVelocityTexture) {
|
|
1518
|
-
this.motionBlurVelocityTexture = this.createNativeBloomDataTexture();
|
|
1519
|
-
}
|
|
1520
|
-
this.motionBlurVelocitySize = { width, height };
|
|
1521
|
-
this.gl.bindTexture(this.gl.TEXTURE_2D, this.motionBlurVelocityTexture);
|
|
1522
|
-
this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RG32F, width, height, 0, this.gl.RG, this.gl.FLOAT, velocity);
|
|
1523
|
-
}
|
|
1524
|
-
finally {
|
|
1525
|
-
this.restoreTextureUnit0(textureUnit0);
|
|
1526
|
-
this.stateCache.invalidate();
|
|
1527
|
-
}
|
|
1528
|
-
}
|
|
1529
|
-
ensureTaaHistoryTexture(width, height, history) {
|
|
1530
|
-
const textureUnit0 = this.captureTextureUnit0();
|
|
1531
|
-
try {
|
|
1532
|
-
if (!this.taaHistoryTexture) {
|
|
1533
|
-
this.taaHistoryTexture = this.createNativeBloomDataTexture();
|
|
1534
|
-
}
|
|
1535
|
-
this.taaHistorySize = { width, height };
|
|
1536
|
-
this.gl.bindTexture(this.gl.TEXTURE_2D, this.taaHistoryTexture);
|
|
1537
|
-
this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA8, width, height, 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, history);
|
|
1538
|
-
}
|
|
1539
|
-
finally {
|
|
1540
|
-
this.restoreTextureUnit0(textureUnit0);
|
|
1541
|
-
this.stateCache.invalidate();
|
|
1542
|
-
}
|
|
1543
|
-
}
|
|
1544
|
-
drawNativeLdrStage(sourceTexture, framebuffer, width, height, program, vertexArray, tonePass, colorPass, fxaaPass, toneMappingDefaults) {
|
|
1545
|
-
const toneOptions = { ...(toneMappingDefaults ?? {}), ...(tonePass?.options ?? {}) };
|
|
1546
|
-
const colorOptions = colorPass?.options ?? {};
|
|
1547
|
-
const fxaaOptions = fxaaPass?.options ?? {};
|
|
1548
|
-
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, framebuffer);
|
|
1549
|
-
this.gl.viewport(0, 0, width, height);
|
|
1550
|
-
this.gl.useProgram(program);
|
|
1551
|
-
this.gl.bindVertexArray(vertexArray);
|
|
1552
|
-
this.bindFullscreenTexture(0, sourceTexture);
|
|
1553
|
-
this.gl.uniform1i(this.gl.getUniformLocation(program, "u_source"), 0);
|
|
1554
|
-
this.gl.uniform2f(this.gl.getUniformLocation(program, "u_texelSize"), 1 / width, 1 / height);
|
|
1555
|
-
this.gl.uniform1i(this.gl.getUniformLocation(program, "u_hasToneMapping"), tonePass ? 1 : 0);
|
|
1556
|
-
this.gl.uniform1i(this.gl.getUniformLocation(program, "u_toneOperator"), toneMappingOperatorId(stringOption(toneOptions, "operator", "reinhard")));
|
|
1557
|
-
this.gl.uniform1i(this.gl.getUniformLocation(program, "u_inputColorSpace"), colorSpaceId(stringOption(toneOptions, "inputColorSpace", "linear")));
|
|
1558
|
-
this.gl.uniform1i(this.gl.getUniformLocation(program, "u_outputColorSpace"), colorSpaceId(stringOption(toneOptions, "outputColorSpace", "linear")));
|
|
1559
|
-
this.gl.uniform1f(this.gl.getUniformLocation(program, "u_exposure"), numberOption(toneOptions, "exposure", 1));
|
|
1560
|
-
this.gl.uniform1f(this.gl.getUniformLocation(program, "u_whitePoint"), Math.max(0.0001, numberOption(toneOptions, "whitePoint", 1)));
|
|
1561
|
-
this.gl.uniform1f(this.gl.getUniformLocation(program, "u_gamma"), Math.max(0.0001, numberOption(toneOptions, "gamma", 2.2)));
|
|
1562
|
-
this.gl.uniform1i(this.gl.getUniformLocation(program, "u_hasColorGrade"), colorPass ? 1 : 0);
|
|
1563
|
-
this.gl.uniform1f(this.gl.getUniformLocation(program, "u_contrast"), numberOption(colorOptions, "contrast", 1));
|
|
1564
|
-
this.gl.uniform1f(this.gl.getUniformLocation(program, "u_temperature"), numberOption(colorOptions, "temperature", 0));
|
|
1565
|
-
this.gl.uniform1f(this.gl.getUniformLocation(program, "u_tint"), numberOption(colorOptions, "tint", 0));
|
|
1566
|
-
this.gl.uniform1f(this.gl.getUniformLocation(program, "u_saturation"), numberOption(colorOptions, "saturation", 1));
|
|
1567
|
-
this.gl.uniform1f(this.gl.getUniformLocation(program, "u_vibrance"), numberOption(colorOptions, "vibrance", 0));
|
|
1568
|
-
this.gl.uniform1f(this.gl.getUniformLocation(program, "u_vignette"), numberOption(colorOptions, "vignette", 0));
|
|
1569
|
-
this.gl.uniform1f(this.gl.getUniformLocation(program, "u_sharpening"), numberOption(colorOptions, "sharpening", 0));
|
|
1570
|
-
this.gl.uniform1i(this.gl.getUniformLocation(program, "u_hasFxaa"), fxaaPass ? 1 : 0);
|
|
1571
|
-
this.gl.uniform1f(this.gl.getUniformLocation(program, "u_edgeThreshold"), numberOption(fxaaOptions, "edgeThreshold", 0.125));
|
|
1572
|
-
this.gl.uniform1f(this.gl.getUniformLocation(program, "u_subpixelBlend"), numberOption(fxaaOptions, "subpixelBlend", 0.75));
|
|
1573
|
-
this.gl.drawArrays(this.gl.TRIANGLES, 0, 3);
|
|
1574
|
-
}
|
|
1575
|
-
executeNativeBloomPasses(sourceTexture, resources, options, vertexArray, hdr) {
|
|
1576
|
-
const brightLut = this.bloomBrightLutTexture;
|
|
1577
|
-
const compositeLut = this.bloomCompositeLutTexture;
|
|
1578
|
-
if (!hdr && (!brightLut || !compositeLut)) {
|
|
1579
|
-
throw new RenderDeviceError("WebGL2 bloom lookup textures were not initialized", "WEBGL_ALLOCATION_FAILED");
|
|
1580
|
-
}
|
|
1581
|
-
const [textureA, textureB] = resources.textures;
|
|
1582
|
-
const [framebufferA, framebufferB] = resources.framebuffers;
|
|
1583
|
-
const brightProgram = this.ensureBloomBrightExtractProgram();
|
|
1584
|
-
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, framebufferA);
|
|
1585
|
-
this.gl.viewport(0, 0, resources.width, resources.height);
|
|
1586
|
-
this.gl.useProgram(brightProgram);
|
|
1587
|
-
this.gl.bindVertexArray(vertexArray);
|
|
1588
|
-
this.bindFullscreenTexture(0, sourceTexture);
|
|
1589
|
-
if (brightLut)
|
|
1590
|
-
this.bindFullscreenTexture(1, brightLut);
|
|
1591
|
-
this.gl.uniform1i(this.gl.getUniformLocation(brightProgram, "u_source"), 0);
|
|
1592
|
-
this.gl.uniform1i(this.gl.getUniformLocation(brightProgram, "u_brightLut"), 1);
|
|
1593
|
-
this.gl.uniform1i(this.gl.getUniformLocation(brightProgram, "u_hdr"), hdr ? 1 : 0);
|
|
1594
|
-
this.gl.uniform1f(this.gl.getUniformLocation(brightProgram, "u_threshold"), options.threshold);
|
|
1595
|
-
this.gl.uniform1f(this.gl.getUniformLocation(brightProgram, "u_softKnee"), options.softKnee);
|
|
1596
|
-
this.gl.drawArrays(this.gl.TRIANGLES, 0, 3);
|
|
1597
|
-
const blurProgram = this.ensureBloomBlurProgram();
|
|
1598
|
-
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, framebufferB);
|
|
1599
|
-
this.gl.useProgram(blurProgram);
|
|
1600
|
-
this.bindFullscreenTexture(0, textureA);
|
|
1601
|
-
this.gl.uniform1i(this.gl.getUniformLocation(blurProgram, "u_source"), 0);
|
|
1602
|
-
this.gl.uniform2i(this.gl.getUniformLocation(blurProgram, "u_size"), resources.width, resources.height);
|
|
1603
|
-
this.gl.uniform1i(this.gl.getUniformLocation(blurProgram, "u_radius"), options.radius);
|
|
1604
|
-
this.gl.uniform1i(this.gl.getUniformLocation(blurProgram, "u_horizontal"), 1);
|
|
1605
|
-
this.gl.uniform1i(this.gl.getUniformLocation(blurProgram, "u_hdr"), hdr ? 1 : 0);
|
|
1606
|
-
this.gl.drawArrays(this.gl.TRIANGLES, 0, 3);
|
|
1607
|
-
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, framebufferA);
|
|
1608
|
-
this.bindFullscreenTexture(0, textureB);
|
|
1609
|
-
this.gl.uniform1i(this.gl.getUniformLocation(blurProgram, "u_horizontal"), 0);
|
|
1610
|
-
this.gl.drawArrays(this.gl.TRIANGLES, 0, 3);
|
|
1611
|
-
const compositeProgram = this.ensureBloomCompositeProgram();
|
|
1612
|
-
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, framebufferB);
|
|
1613
|
-
this.gl.useProgram(compositeProgram);
|
|
1614
|
-
this.bindFullscreenTexture(0, sourceTexture);
|
|
1615
|
-
this.bindFullscreenTexture(1, textureA);
|
|
1616
|
-
if (compositeLut)
|
|
1617
|
-
this.bindFullscreenTexture(2, compositeLut);
|
|
1618
|
-
this.gl.uniform1i(this.gl.getUniformLocation(compositeProgram, "u_source"), 0);
|
|
1619
|
-
this.gl.uniform1i(this.gl.getUniformLocation(compositeProgram, "u_blurred"), 1);
|
|
1620
|
-
this.gl.uniform1i(this.gl.getUniformLocation(compositeProgram, "u_compositeLut"), 2);
|
|
1621
|
-
this.gl.uniform1i(this.gl.getUniformLocation(compositeProgram, "u_hdr"), hdr ? 1 : 0);
|
|
1622
|
-
this.gl.uniform1f(this.gl.getUniformLocation(compositeProgram, "u_intensity"), options.intensity);
|
|
1623
|
-
this.gl.drawArrays(this.gl.TRIANGLES, 0, 3);
|
|
1624
|
-
return textureB;
|
|
1625
|
-
}
|
|
1626
|
-
/**
|
|
1627
|
-
* Balanced/cinematic bloom: bright-extract once, then a half-resolution mip
|
|
1628
|
-
* chain where every level is downsampled, separably blurred, and accumulated
|
|
1629
|
-
* with its energy-preserving weight. Returns a full-resolution bloom texture
|
|
1630
|
-
* holding the weighted sum, ready for the existing composite program.
|
|
1631
|
-
*/
|
|
1632
|
-
executeNativeBloomPyramidPasses(sourceTexture, sourceWidth, sourceHeight, resources, fullResStaging, options, vertexArray, hdr) {
|
|
1633
|
-
const plan = resources.plan;
|
|
1634
|
-
const mipCount = plan.mips.length;
|
|
1635
|
-
const blurRadii = resolveBloomPyramidBlurRadii(plan, options.radius);
|
|
1636
|
-
const downsampleProgram = this.ensureBloomDownsampleProgram();
|
|
1637
|
-
const brightProgram = this.ensureBloomBrightExtractProgram();
|
|
1638
|
-
const blurProgram = this.ensureBloomBlurProgram();
|
|
1639
|
-
const accumulateProgram = this.ensureBloomAccumulateProgram();
|
|
1640
|
-
const brightLut = this.bloomBrightLutTexture;
|
|
1641
|
-
const mipTexture = (level, slot) => resources.textures[level * 2 + slot];
|
|
1642
|
-
const mipFramebuffer = (level, slot) => resources.framebuffers[level * 2 + slot];
|
|
1643
|
-
const mipSize = (level) => plan.mips[level];
|
|
1644
|
-
// Every level settles in slot 0 after the vertical blur.
|
|
1645
|
-
const blurredSlot = (_level) => 0;
|
|
1646
|
-
const drawDownsample = (fromTexture, fromWidth, fromHeight, toFramebuffer, toWidth, toHeight) => {
|
|
1647
|
-
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, toFramebuffer);
|
|
1648
|
-
this.gl.viewport(0, 0, toWidth, toHeight);
|
|
1649
|
-
this.gl.useProgram(downsampleProgram);
|
|
1650
|
-
this.gl.bindVertexArray(vertexArray);
|
|
1651
|
-
this.bindFullscreenTexture(0, fromTexture);
|
|
1652
|
-
this.gl.uniform1i(this.gl.getUniformLocation(downsampleProgram, "u_source"), 0);
|
|
1653
|
-
this.gl.uniform2f(this.gl.getUniformLocation(downsampleProgram, "u_texelSize"), 1 / fromWidth, 1 / fromHeight);
|
|
1654
|
-
this.gl.uniform2f(this.gl.getUniformLocation(downsampleProgram, "u_targetSize"), toWidth, toHeight);
|
|
1655
|
-
this.gl.drawArrays(this.gl.TRIANGLES, 0, 3);
|
|
1656
|
-
};
|
|
1657
|
-
const drawBrightExtract = (fromTexture, toFramebuffer, size) => {
|
|
1658
|
-
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, toFramebuffer);
|
|
1659
|
-
this.gl.viewport(0, 0, size.width, size.height);
|
|
1660
|
-
this.gl.useProgram(brightProgram);
|
|
1661
|
-
this.gl.bindVertexArray(vertexArray);
|
|
1662
|
-
this.bindFullscreenTexture(0, fromTexture);
|
|
1663
|
-
if (brightLut)
|
|
1664
|
-
this.bindFullscreenTexture(1, brightLut);
|
|
1665
|
-
this.gl.uniform1i(this.gl.getUniformLocation(brightProgram, "u_source"), 0);
|
|
1666
|
-
this.gl.uniform1i(this.gl.getUniformLocation(brightProgram, "u_brightLut"), 1);
|
|
1667
|
-
this.gl.uniform1i(this.gl.getUniformLocation(brightProgram, "u_hdr"), hdr ? 1 : 0);
|
|
1668
|
-
this.gl.uniform1f(this.gl.getUniformLocation(brightProgram, "u_threshold"), options.threshold);
|
|
1669
|
-
this.gl.uniform1f(this.gl.getUniformLocation(brightProgram, "u_softKnee"), options.softKnee);
|
|
1670
|
-
this.gl.drawArrays(this.gl.TRIANGLES, 0, 3);
|
|
1671
|
-
};
|
|
1672
|
-
const drawSeparableBlur = (readTexture, tmpTexture, tmpFramebuffer, outFramebuffer, size, radius) => {
|
|
1673
|
-
// Horizontal into the temp target, vertical back into the output target.
|
|
1674
|
-
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, tmpFramebuffer);
|
|
1675
|
-
this.gl.viewport(0, 0, size.width, size.height);
|
|
1676
|
-
this.gl.useProgram(blurProgram);
|
|
1677
|
-
this.gl.bindVertexArray(vertexArray);
|
|
1678
|
-
this.bindFullscreenTexture(0, readTexture);
|
|
1679
|
-
this.gl.uniform1i(this.gl.getUniformLocation(blurProgram, "u_source"), 0);
|
|
1680
|
-
this.gl.uniform2i(this.gl.getUniformLocation(blurProgram, "u_size"), size.width, size.height);
|
|
1681
|
-
this.gl.uniform1i(this.gl.getUniformLocation(blurProgram, "u_radius"), radius);
|
|
1682
|
-
this.gl.uniform1i(this.gl.getUniformLocation(blurProgram, "u_horizontal"), 1);
|
|
1683
|
-
this.gl.uniform1i(this.gl.getUniformLocation(blurProgram, "u_hdr"), hdr ? 1 : 0);
|
|
1684
|
-
this.gl.drawArrays(this.gl.TRIANGLES, 0, 3);
|
|
1685
|
-
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, outFramebuffer);
|
|
1686
|
-
this.bindFullscreenTexture(0, tmpTexture);
|
|
1687
|
-
this.gl.uniform1i(this.gl.getUniformLocation(blurProgram, "u_horizontal"), 0);
|
|
1688
|
-
this.gl.drawArrays(this.gl.TRIANGLES, 0, 3);
|
|
1689
|
-
};
|
|
1690
|
-
// Extract highlights at the source resolution before the first downsample.
|
|
1691
|
-
// Downsampling the complete scene first averaged narrow emissive sources
|
|
1692
|
-
// below the authored threshold, so balanced/cinematic bloom could execute
|
|
1693
|
-
// all native passes yet remain pixel-identical to disabled output.
|
|
1694
|
-
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, fullResStaging.framebufferA);
|
|
1695
|
-
this.gl.viewport(0, 0, sourceWidth, sourceHeight);
|
|
1696
|
-
this.gl.useProgram(brightProgram);
|
|
1697
|
-
this.gl.bindVertexArray(vertexArray);
|
|
1698
|
-
this.bindFullscreenTexture(0, sourceTexture);
|
|
1699
|
-
if (brightLut)
|
|
1700
|
-
this.bindFullscreenTexture(1, brightLut);
|
|
1701
|
-
this.gl.uniform1i(this.gl.getUniformLocation(brightProgram, "u_source"), 0);
|
|
1702
|
-
this.gl.uniform1i(this.gl.getUniformLocation(brightProgram, "u_brightLut"), 1);
|
|
1703
|
-
this.gl.uniform1i(this.gl.getUniformLocation(brightProgram, "u_hdr"), hdr ? 1 : 0);
|
|
1704
|
-
this.gl.uniform1f(this.gl.getUniformLocation(brightProgram, "u_threshold"), options.threshold);
|
|
1705
|
-
this.gl.uniform1f(this.gl.getUniformLocation(brightProgram, "u_softKnee"), options.softKnee);
|
|
1706
|
-
this.gl.drawArrays(this.gl.TRIANGLES, 0, 3);
|
|
1707
|
-
// Level 0 downsamples the extracted highlight field, then blurs H into
|
|
1708
|
-
// slot 1 and V back into slot 0. The result therefore settles in slot 0.
|
|
1709
|
-
const level0 = mipSize(0);
|
|
1710
|
-
drawDownsample(fullResStaging.textureA, sourceWidth, sourceHeight, mipFramebuffer(0, 0), level0.width, level0.height);
|
|
1711
|
-
drawSeparableBlur(mipTexture(0, 0), mipTexture(0, 1), mipFramebuffer(0, 1), mipFramebuffer(0, 0), level0, blurRadii[0]);
|
|
1712
|
-
for (let level = 1; level < mipCount; level += 1) {
|
|
1713
|
-
const size = mipSize(level);
|
|
1714
|
-
const previous = mipSize(level - 1);
|
|
1715
|
-
drawDownsample(mipTexture(level - 1, blurredSlot(level - 1)), previous.width, previous.height, mipFramebuffer(level, 0), size.width, size.height);
|
|
1716
|
-
// H into slot 1, V back into slot 0: blurred result settles in slot 0.
|
|
1717
|
-
drawSeparableBlur(mipTexture(level, 0), mipTexture(level, 1), mipFramebuffer(level, 1), mipFramebuffer(level, 0), size, blurRadii[level]);
|
|
1718
|
-
}
|
|
1719
|
-
// Accumulate smallest-to-largest, ping-ponging between the two
|
|
1720
|
-
// accumulators (a pass must never sample its own bound target).
|
|
1721
|
-
const weights = plan.weights;
|
|
1722
|
-
let readAccumulator = { texture: resources.accumulatorTextureA, framebuffer: resources.accumulatorFramebufferA };
|
|
1723
|
-
let writeAccumulator = { texture: resources.accumulatorTextureB, framebuffer: resources.accumulatorFramebufferB };
|
|
1724
|
-
// Clear both accumulators; the seed reads the cleared sibling, never the
|
|
1725
|
-
// bound target (feedback loop).
|
|
1726
|
-
for (const acc of [readAccumulator, writeAccumulator]) {
|
|
1727
|
-
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, acc.framebuffer);
|
|
1728
|
-
this.gl.viewport(0, 0, level0.width, level0.height);
|
|
1729
|
-
this.gl.clearColor(0, 0, 0, 0);
|
|
1730
|
-
this.gl.clear(this.gl.COLOR_BUFFER_BIT);
|
|
1731
|
-
}
|
|
1732
|
-
// Seed: smallest mip onto the cleared sibling accumulator.
|
|
1733
|
-
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, writeAccumulator.framebuffer);
|
|
1734
|
-
this.gl.viewport(0, 0, level0.width, level0.height);
|
|
1735
|
-
this.gl.useProgram(accumulateProgram);
|
|
1736
|
-
this.gl.bindVertexArray(vertexArray);
|
|
1737
|
-
this.bindFullscreenTexture(0, readAccumulator.texture);
|
|
1738
|
-
this.bindFullscreenTexture(1, mipTexture(mipCount - 1, blurredSlot(mipCount - 1)));
|
|
1739
|
-
this.gl.uniform1i(this.gl.getUniformLocation(accumulateProgram, "u_base"), 0);
|
|
1740
|
-
this.gl.uniform1i(this.gl.getUniformLocation(accumulateProgram, "u_bloom"), 1);
|
|
1741
|
-
this.gl.uniform1f(this.gl.getUniformLocation(accumulateProgram, "u_weight"), weights[mipCount - 1]);
|
|
1742
|
-
this.gl.drawArrays(this.gl.TRIANGLES, 0, 3);
|
|
1743
|
-
for (let level = mipCount - 2; level >= 0; level -= 1) {
|
|
1744
|
-
const nextRead = writeAccumulator;
|
|
1745
|
-
const nextWrite = readAccumulator;
|
|
1746
|
-
readAccumulator = nextRead;
|
|
1747
|
-
writeAccumulator = nextWrite;
|
|
1748
|
-
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, writeAccumulator.framebuffer);
|
|
1749
|
-
this.gl.viewport(0, 0, level0.width, level0.height);
|
|
1750
|
-
this.gl.useProgram(accumulateProgram);
|
|
1751
|
-
this.gl.bindVertexArray(vertexArray);
|
|
1752
|
-
this.bindFullscreenTexture(0, readAccumulator.texture);
|
|
1753
|
-
this.bindFullscreenTexture(1, mipTexture(level, blurredSlot(level)));
|
|
1754
|
-
this.gl.uniform1i(this.gl.getUniformLocation(accumulateProgram, "u_base"), 0);
|
|
1755
|
-
this.gl.uniform1i(this.gl.getUniformLocation(accumulateProgram, "u_bloom"), 1);
|
|
1756
|
-
this.gl.uniform1f(this.gl.getUniformLocation(accumulateProgram, "u_weight"), weights[level]);
|
|
1757
|
-
this.gl.drawArrays(this.gl.TRIANGLES, 0, 3);
|
|
1758
|
-
}
|
|
1759
|
-
// Upsample the weighted sum onto full-resolution staging target A, using
|
|
1760
|
-
// the cleared staging target B as the zero base (never sample A while
|
|
1761
|
-
// rendering into it).
|
|
1762
|
-
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, fullResStaging.framebufferB);
|
|
1763
|
-
this.gl.viewport(0, 0, sourceWidth, sourceHeight);
|
|
1764
|
-
this.gl.clearColor(0, 0, 0, 0);
|
|
1765
|
-
this.gl.clear(this.gl.COLOR_BUFFER_BIT);
|
|
1766
|
-
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, fullResStaging.framebufferA);
|
|
1767
|
-
this.gl.viewport(0, 0, sourceWidth, sourceHeight);
|
|
1768
|
-
this.gl.useProgram(accumulateProgram);
|
|
1769
|
-
this.gl.bindVertexArray(vertexArray);
|
|
1770
|
-
this.bindFullscreenTexture(0, fullResStaging.textureB);
|
|
1771
|
-
this.bindFullscreenTexture(1, writeAccumulator.texture);
|
|
1772
|
-
this.gl.uniform1i(this.gl.getUniformLocation(accumulateProgram, "u_base"), 0);
|
|
1773
|
-
this.gl.uniform1i(this.gl.getUniformLocation(accumulateProgram, "u_bloom"), 1);
|
|
1774
|
-
this.gl.uniform1f(this.gl.getUniformLocation(accumulateProgram, "u_weight"), 1);
|
|
1775
|
-
this.gl.drawArrays(this.gl.TRIANGLES, 0, 3);
|
|
1776
|
-
return fullResStaging.textureA;
|
|
1777
|
-
}
|
|
1778
|
-
executeNativeOutlinePasses(sourceTexture, resources, options, vertexArray, targetIndex) {
|
|
1779
|
-
const blendLut = this.outlineBlendLutTexture;
|
|
1780
|
-
if (!blendLut) {
|
|
1781
|
-
throw new RenderDeviceError("WebGL2 outline lookup texture was not initialized", "WEBGL_ALLOCATION_FAILED");
|
|
1782
|
-
}
|
|
1783
|
-
const program = this.ensureOutlineProgram();
|
|
1784
|
-
const targetTexture = resources.textures[targetIndex];
|
|
1785
|
-
const targetFramebuffer = resources.framebuffers[targetIndex];
|
|
1786
|
-
const bound = createOutlineGradientBound(options.threshold);
|
|
1787
|
-
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, targetFramebuffer);
|
|
1788
|
-
this.gl.viewport(0, 0, resources.width, resources.height);
|
|
1789
|
-
this.gl.useProgram(program);
|
|
1790
|
-
this.gl.bindVertexArray(vertexArray);
|
|
1791
|
-
this.bindFullscreenTexture(0, sourceTexture);
|
|
1792
|
-
this.bindFullscreenTexture(1, blendLut);
|
|
1793
|
-
this.gl.uniform1i(this.gl.getUniformLocation(program, "u_source"), 0);
|
|
1794
|
-
this.gl.uniform1i(this.gl.getUniformLocation(program, "u_blendLut"), 1);
|
|
1795
|
-
this.gl.uniform2i(this.gl.getUniformLocation(program, "u_size"), resources.width, resources.height);
|
|
1796
|
-
this.gl.uniform1i(this.gl.getUniformLocation(program, "u_width"), options.width);
|
|
1797
|
-
this.gl.uniform1f(this.gl.getUniformLocation(program, "u_boundHigh"), bound.highWord);
|
|
1798
|
-
this.gl.uniform1f(this.gl.getUniformLocation(program, "u_boundLow"), bound.lowWord);
|
|
1799
|
-
this.gl.drawArrays(this.gl.TRIANGLES, 0, 3);
|
|
1800
|
-
return targetTexture;
|
|
1801
|
-
}
|
|
1802
|
-
executeNativeSsaoPass(sourceTexture, depthTexture, resources, options, vertexArray, targetIndex) {
|
|
1803
|
-
const program = this.ensureSsaoProgram();
|
|
1804
|
-
const targetTexture = resources.textures[targetIndex];
|
|
1805
|
-
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, resources.framebuffers[targetIndex]);
|
|
1806
|
-
this.gl.viewport(0, 0, resources.width, resources.height);
|
|
1807
|
-
this.gl.useProgram(program);
|
|
1808
|
-
this.gl.bindVertexArray(vertexArray);
|
|
1809
|
-
this.bindFullscreenTexture(0, sourceTexture);
|
|
1810
|
-
this.bindFullscreenTexture(1, depthTexture);
|
|
1811
|
-
this.gl.uniform1i(this.gl.getUniformLocation(program, "u_source"), 0);
|
|
1812
|
-
this.gl.uniform1i(this.gl.getUniformLocation(program, "u_depth"), 1);
|
|
1813
|
-
this.gl.uniform2i(this.gl.getUniformLocation(program, "u_size"), resources.width, resources.height);
|
|
1814
|
-
this.gl.uniform1i(this.gl.getUniformLocation(program, "u_radius"), options.radius);
|
|
1815
|
-
this.gl.uniform1f(this.gl.getUniformLocation(program, "u_intensity"), options.intensity);
|
|
1816
|
-
this.gl.uniform1f(this.gl.getUniformLocation(program, "u_bias"), options.bias);
|
|
1817
|
-
this.gl.drawArrays(this.gl.TRIANGLES, 0, 3);
|
|
1818
|
-
return targetTexture;
|
|
1819
|
-
}
|
|
1820
|
-
executeNativeSsrPass(sourceTexture, depthTexture, resources, options, vertexArray, targetIndex, depthRange) {
|
|
1821
|
-
const targetTexture = resources.textures[targetIndex];
|
|
1822
|
-
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, resources.framebuffers[targetIndex]);
|
|
1823
|
-
this.drawSsrKernel(sourceTexture, depthTexture, resources.width, resources.height, options, vertexArray, depthRange);
|
|
1824
|
-
return targetTexture;
|
|
1825
|
-
}
|
|
1826
|
-
drawSsrKernel(sourceTexture, depthTexture, width, height, options, vertexArray, depthRange) {
|
|
1827
|
-
const program = this.ensureSsrProgram();
|
|
1828
|
-
this.gl.viewport(0, 0, width, height);
|
|
1829
|
-
this.gl.useProgram(program);
|
|
1830
|
-
this.gl.bindVertexArray(vertexArray);
|
|
1831
|
-
this.bindFullscreenTexture(0, sourceTexture);
|
|
1832
|
-
this.bindFullscreenTexture(1, depthTexture);
|
|
1833
|
-
this.bindFullscreenTexture(2, options.normalMask ?? sourceTexture);
|
|
1834
|
-
this.gl.uniform1i(this.gl.getUniformLocation(program, "u_source"), 0);
|
|
1835
|
-
this.gl.uniform1i(this.gl.getUniformLocation(program, "u_depth"), 1);
|
|
1836
|
-
this.gl.uniform1i(this.gl.getUniformLocation(program, "u_normalMask"), 2);
|
|
1837
|
-
this.gl.uniform1i(this.gl.getUniformLocation(program, "u_hasNormalMask"), options.normalMask ? 1 : 0);
|
|
1838
|
-
this.gl.uniform2i(this.gl.getUniformLocation(program, "u_size"), width, height);
|
|
1839
|
-
this.gl.uniform1f(this.gl.getUniformLocation(program, "u_intensity"), options.intensity);
|
|
1840
|
-
this.gl.uniform1f(this.gl.getUniformLocation(program, "u_maxDistance"), options.maxDistance);
|
|
1841
|
-
this.gl.uniform1i(this.gl.getUniformLocation(program, "u_maxSteps"), options.maxSteps ?? 32);
|
|
1842
|
-
this.gl.uniform1f(this.gl.getUniformLocation(program, "u_thickness"), options.thickness ?? 0.2);
|
|
1843
|
-
if (options.projection && options.inverseProjection) {
|
|
1844
|
-
this.gl.uniformMatrix4fv(this.gl.getUniformLocation(program, "u_projection"), false, options.projection);
|
|
1845
|
-
this.gl.uniformMatrix4fv(this.gl.getUniformLocation(program, "u_inverseProjection"), false, options.inverseProjection);
|
|
1846
|
-
}
|
|
1847
|
-
this.gl.uniform1f(this.gl.getUniformLocation(program, "u_depthNear"), depthRange.near);
|
|
1848
|
-
this.gl.uniform1f(this.gl.getUniformLocation(program, "u_depthFar"), depthRange.far);
|
|
1849
|
-
this.gl.drawArrays(this.gl.TRIANGLES, 0, 3);
|
|
1850
|
-
}
|
|
1851
|
-
executeNativeDepthOfFieldPass(sourceTexture, depthTexture, resources, options, vertexArray, targetIndex, depthRange) {
|
|
1852
|
-
const program = this.ensureDepthOfFieldProgram();
|
|
1853
|
-
const targetTexture = resources.textures[targetIndex];
|
|
1854
|
-
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, resources.framebuffers[targetIndex]);
|
|
1855
|
-
this.gl.viewport(0, 0, resources.width, resources.height);
|
|
1856
|
-
this.gl.useProgram(program);
|
|
1857
|
-
this.gl.bindVertexArray(vertexArray);
|
|
1858
|
-
this.bindFullscreenTexture(0, sourceTexture);
|
|
1859
|
-
this.bindFullscreenTexture(1, depthTexture);
|
|
1860
|
-
this.gl.uniform1i(this.gl.getUniformLocation(program, "u_source"), 0);
|
|
1861
|
-
this.gl.uniform1i(this.gl.getUniformLocation(program, "u_depth"), 1);
|
|
1862
|
-
this.gl.uniform2i(this.gl.getUniformLocation(program, "u_size"), resources.width, resources.height);
|
|
1863
|
-
this.gl.uniform1f(this.gl.getUniformLocation(program, "u_focusDepth"), options.focusDepth);
|
|
1864
|
-
this.gl.uniform1f(this.gl.getUniformLocation(program, "u_focusRange"), options.focusRange);
|
|
1865
|
-
this.gl.uniform1i(this.gl.getUniformLocation(program, "u_maxRadius"), options.maxRadius);
|
|
1866
|
-
this.gl.uniform1f(this.gl.getUniformLocation(program, "u_depthNear"), depthRange.near);
|
|
1867
|
-
this.gl.uniform1f(this.gl.getUniformLocation(program, "u_depthFar"), depthRange.far);
|
|
1868
|
-
this.gl.drawArrays(this.gl.TRIANGLES, 0, 3);
|
|
1869
|
-
return targetTexture;
|
|
1870
|
-
}
|
|
1871
|
-
executeNativeMotionBlurPass(sourceTexture, resources, options, vertexArray, targetIndex) {
|
|
1872
|
-
const velocityTexture = options.temporal ? this.requireTemporalTarget(options.temporal.velocity, resources.width, resources.height).colorHandle : this.motionBlurVelocityTexture;
|
|
1873
|
-
if (!velocityTexture) {
|
|
1874
|
-
throw new RenderDeviceError("WebGL2 motion-blur velocity texture was not initialized", "WEBGL_ALLOCATION_FAILED");
|
|
1875
|
-
}
|
|
1876
|
-
const program = this.ensureMotionBlurProgram();
|
|
1877
|
-
const targetTexture = resources.textures[targetIndex];
|
|
1878
|
-
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, resources.framebuffers[targetIndex]);
|
|
1879
|
-
this.gl.viewport(0, 0, resources.width, resources.height);
|
|
1880
|
-
this.gl.useProgram(program);
|
|
1881
|
-
this.gl.bindVertexArray(vertexArray);
|
|
1882
|
-
this.bindFullscreenTexture(0, sourceTexture);
|
|
1883
|
-
this.bindFullscreenTexture(1, velocityTexture);
|
|
1884
|
-
this.gl.uniform1i(this.gl.getUniformLocation(program, "u_source"), 0);
|
|
1885
|
-
this.gl.uniform1i(this.gl.getUniformLocation(program, "u_velocity"), 1);
|
|
1886
|
-
this.gl.uniform2i(this.gl.getUniformLocation(program, "u_size"), resources.width, resources.height);
|
|
1887
|
-
this.gl.uniform1i(this.gl.getUniformLocation(program, "u_samples"), options.samples);
|
|
1888
|
-
this.gl.uniform1f(this.gl.getUniformLocation(program, "u_scale"), options.scale);
|
|
1889
|
-
this.gl.uniform1i(this.gl.getUniformLocation(program, "u_velocityUv"), options.temporal ? 1 : 0);
|
|
1890
|
-
if (options.temporal) {
|
|
1891
|
-
this.nativeTemporalPasses++;
|
|
1892
|
-
this.nativeTemporalBindings++;
|
|
1893
|
-
}
|
|
1894
|
-
this.gl.drawArrays(this.gl.TRIANGLES, 0, 3);
|
|
1895
|
-
return targetTexture;
|
|
1184
|
+
this.host.textureRegistry.textureUploadModes.clear();
|
|
1185
|
+
if (this.host.textureRegistry.fallbackTexture) {
|
|
1186
|
+
this.gl.deleteTexture(this.host.textureRegistry.fallbackTexture);
|
|
1187
|
+
this.host.textureRegistry.fallbackTexture = null;
|
|
1188
|
+
}
|
|
1189
|
+
if (this.host.textureRegistry.fallbackCubeTexture) {
|
|
1190
|
+
this.gl.deleteTexture(this.host.textureRegistry.fallbackCubeTexture);
|
|
1191
|
+
this.host.textureRegistry.fallbackCubeTexture = null;
|
|
1192
|
+
}
|
|
1193
|
+
if (this.host.post.presentationProgram) {
|
|
1194
|
+
this.gl.deleteProgram(this.host.post.presentationProgram);
|
|
1195
|
+
this.host.post.presentationProgram = null;
|
|
1196
|
+
}
|
|
1197
|
+
if (this.host.post.ldrPostprocessProgram) {
|
|
1198
|
+
this.gl.deleteProgram(this.host.post.ldrPostprocessProgram);
|
|
1199
|
+
this.host.post.ldrPostprocessProgram = null;
|
|
1200
|
+
}
|
|
1201
|
+
if (this.host.post.bloomBrightExtractProgram) {
|
|
1202
|
+
this.gl.deleteProgram(this.host.post.bloomBrightExtractProgram);
|
|
1203
|
+
this.host.post.bloomBrightExtractProgram = null;
|
|
1204
|
+
}
|
|
1205
|
+
if (this.host.post.bloomBlurProgram) {
|
|
1206
|
+
this.gl.deleteProgram(this.host.post.bloomBlurProgram);
|
|
1207
|
+
this.host.post.bloomBlurProgram = null;
|
|
1208
|
+
}
|
|
1209
|
+
if (this.host.post.bloomCompositeProgram) {
|
|
1210
|
+
this.gl.deleteProgram(this.host.post.bloomCompositeProgram);
|
|
1211
|
+
this.host.post.bloomCompositeProgram = null;
|
|
1212
|
+
}
|
|
1213
|
+
if (this.host.post.bloomDownsampleProgram) {
|
|
1214
|
+
this.gl.deleteProgram(this.host.post.bloomDownsampleProgram);
|
|
1215
|
+
this.host.post.bloomDownsampleProgram = null;
|
|
1216
|
+
}
|
|
1217
|
+
if (this.host.post.bloomAccumulateProgram) {
|
|
1218
|
+
this.gl.deleteProgram(this.host.post.bloomAccumulateProgram);
|
|
1219
|
+
this.host.post.bloomAccumulateProgram = null;
|
|
1220
|
+
}
|
|
1221
|
+
if (this.host.post.outlineProgram) {
|
|
1222
|
+
this.gl.deleteProgram(this.host.post.outlineProgram);
|
|
1223
|
+
this.host.post.outlineProgram = null;
|
|
1224
|
+
}
|
|
1225
|
+
if (this.host.post.ssaoProgram) {
|
|
1226
|
+
this.gl.deleteProgram(this.host.post.ssaoProgram);
|
|
1227
|
+
this.host.post.ssaoProgram = null;
|
|
1228
|
+
}
|
|
1229
|
+
if (this.host.post.ssrProgram) {
|
|
1230
|
+
this.gl.deleteProgram(this.host.post.ssrProgram);
|
|
1231
|
+
this.host.post.ssrProgram = null;
|
|
1232
|
+
}
|
|
1233
|
+
if (this.host.post.depthOfFieldProgram) {
|
|
1234
|
+
this.gl.deleteProgram(this.host.post.depthOfFieldProgram);
|
|
1235
|
+
this.host.post.depthOfFieldProgram = null;
|
|
1236
|
+
}
|
|
1237
|
+
if (this.host.post.motionBlurProgram) {
|
|
1238
|
+
this.gl.deleteProgram(this.host.post.motionBlurProgram);
|
|
1239
|
+
this.host.post.motionBlurProgram = null;
|
|
1240
|
+
}
|
|
1241
|
+
if (this.host.post.motionBlurVelocityTexture) {
|
|
1242
|
+
this.gl.deleteTexture(this.host.post.motionBlurVelocityTexture);
|
|
1243
|
+
this.host.post.motionBlurVelocityTexture = null;
|
|
1244
|
+
this.host.post.motionBlurVelocitySize = null;
|
|
1245
|
+
}
|
|
1246
|
+
if (this.host.post.taaProgram) {
|
|
1247
|
+
this.gl.deleteProgram(this.host.post.taaProgram);
|
|
1248
|
+
this.host.post.taaProgram = null;
|
|
1249
|
+
}
|
|
1250
|
+
if (this.host.post.taaPresentationProgram) {
|
|
1251
|
+
this.gl.deleteProgram(this.host.post.taaPresentationProgram);
|
|
1252
|
+
this.host.post.taaPresentationProgram = null;
|
|
1253
|
+
}
|
|
1254
|
+
if (this.host.post.taaHistoryTexture) {
|
|
1255
|
+
this.gl.deleteTexture(this.host.post.taaHistoryTexture);
|
|
1256
|
+
this.host.post.taaHistoryTexture = null;
|
|
1257
|
+
this.host.post.taaHistorySize = null;
|
|
1258
|
+
}
|
|
1259
|
+
this.host.post.disposeBloomPingPongResources();
|
|
1260
|
+
this.host.post.disposeBloomPyramidResources();
|
|
1261
|
+
if (this.host.post.bloomBrightLutTexture) {
|
|
1262
|
+
this.gl.deleteTexture(this.host.post.bloomBrightLutTexture);
|
|
1263
|
+
this.host.post.bloomBrightLutTexture = null;
|
|
1264
|
+
this.host.post.bloomBrightLutThreshold = null;
|
|
1265
|
+
}
|
|
1266
|
+
if (this.host.post.bloomCompositeLutTexture) {
|
|
1267
|
+
this.gl.deleteTexture(this.host.post.bloomCompositeLutTexture);
|
|
1268
|
+
this.host.post.bloomCompositeLutTexture = null;
|
|
1269
|
+
this.host.post.bloomCompositeLutIntensity = null;
|
|
1270
|
+
this.host.post.bloomCompositeLutShoulder = null;
|
|
1271
|
+
}
|
|
1272
|
+
if (this.host.post.outlineBlendLutTexture) {
|
|
1273
|
+
this.gl.deleteTexture(this.host.post.outlineBlendLutTexture);
|
|
1274
|
+
this.host.post.outlineBlendLutTexture = null;
|
|
1275
|
+
this.host.post.outlineBlendLutKey = null;
|
|
1276
|
+
}
|
|
1277
|
+
if (this.host.post.presentationVertexArray) {
|
|
1278
|
+
this.gl.deleteVertexArray(this.host.post.presentationVertexArray);
|
|
1279
|
+
this.host.post.presentationVertexArray = null;
|
|
1280
|
+
}
|
|
1281
|
+
if (this.host.probe.depthReadbackProgram) {
|
|
1282
|
+
this.gl.deleteProgram(this.host.probe.depthReadbackProgram);
|
|
1283
|
+
this.host.probe.depthReadbackProgram = null;
|
|
1284
|
+
}
|
|
1285
|
+
this.host.textureRegistry.textures.clear();
|
|
1286
|
+
this.host.disposed = true;
|
|
1896
1287
|
}
|
|
1897
|
-
|
|
1898
|
-
const
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
if (!historyTexture) {
|
|
1902
|
-
throw new RenderDeviceError("WebGL2 TAA history texture was not initialized", "WEBGL_ALLOCATION_FAILED");
|
|
1903
|
-
}
|
|
1904
|
-
const accumulationProgram = this.ensureTaaProgram();
|
|
1905
|
-
const targetTexture = resources.textures[targetIndex];
|
|
1906
|
-
this.gl.viewport(0, 0, resources.width, resources.height);
|
|
1907
|
-
this.gl.useProgram(accumulationProgram);
|
|
1908
|
-
this.gl.bindVertexArray(vertexArray);
|
|
1909
|
-
this.bindFullscreenTexture(0, sourceTexture);
|
|
1910
|
-
this.bindFullscreenTexture(1, historyTexture);
|
|
1911
|
-
this.gl.uniform1i(this.gl.getUniformLocation(accumulationProgram, "u_source"), 0);
|
|
1912
|
-
this.gl.uniform1i(this.gl.getUniformLocation(accumulationProgram, "u_history"), 1);
|
|
1913
|
-
this.gl.uniform1f(this.gl.getUniformLocation(accumulationProgram, "u_blend"), temporal && !temporal.historyValid ? 0 : temporalAccumulationWeight(options.blend, temporal?.historyFrames));
|
|
1914
|
-
this.gl.uniform1i(this.gl.getUniformLocation(accumulationProgram, "u_temporal"), temporal ? 1 : 0);
|
|
1915
|
-
if (temporal) {
|
|
1916
|
-
const velocity = this.requireTemporalTarget(temporal.velocity, resources.width, resources.height);
|
|
1917
|
-
const destination = this.requireTemporalTarget(temporal.historyOutput, resources.width, resources.height);
|
|
1918
|
-
if (destination === historyTarget || destination === velocity || historyTarget === velocity)
|
|
1919
|
-
throw new RenderDeviceError("Temporal targets must not alias", "TEMPORAL_TARGET_ALIAS");
|
|
1920
|
-
this.bindFullscreenTexture(2, velocity.colorHandle);
|
|
1921
|
-
this.gl.uniform1i(this.gl.getUniformLocation(accumulationProgram, "u_velocity"), 2);
|
|
1922
|
-
// Resolve exactly once into the next history target. Presentation reads
|
|
1923
|
-
// this immutable result through a separate program, so display tuning
|
|
1924
|
-
// cannot alter the accumulated history shader or its stored bytes.
|
|
1925
|
-
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, destination.framebuffer);
|
|
1926
|
-
this.gl.drawArrays(this.gl.TRIANGLES, 0, 3);
|
|
1927
|
-
const presentationProgram = this.ensureTaaPresentationProgram();
|
|
1928
|
-
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, resources.framebuffers[targetIndex]);
|
|
1929
|
-
this.gl.useProgram(presentationProgram);
|
|
1930
|
-
this.bindFullscreenTexture(0, sourceTexture);
|
|
1931
|
-
this.bindFullscreenTexture(1, destination.colorHandle);
|
|
1932
|
-
this.gl.uniform1i(this.gl.getUniformLocation(presentationProgram, "u_source"), 0);
|
|
1933
|
-
this.gl.uniform1i(this.gl.getUniformLocation(presentationProgram, "u_accumulated"), 1);
|
|
1934
|
-
this.gl.drawArrays(this.gl.TRIANGLES, 0, 3);
|
|
1935
|
-
this.nativeTemporalPasses++;
|
|
1936
|
-
this.nativeTemporalBindings += 3;
|
|
1288
|
+
compileShader(type, source, label) {
|
|
1289
|
+
const shader = this.gl.createShader(type);
|
|
1290
|
+
if (!shader) {
|
|
1291
|
+
throw new RenderDeviceError("Failed to allocate WebGL shader", "WEBGL_ALLOCATION_FAILED", { label });
|
|
1937
1292
|
}
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1293
|
+
this.gl.shaderSource(shader, source);
|
|
1294
|
+
this.gl.compileShader(shader);
|
|
1295
|
+
if (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {
|
|
1296
|
+
const log = this.gl.getShaderInfoLog(shader) ?? "Unknown shader compile error";
|
|
1297
|
+
this.gl.deleteShader(shader);
|
|
1298
|
+
throw new RenderDeviceError("WebGL shader compile failed", "SHADER_COMPILE_FAILED", { label, log });
|
|
1941
1299
|
}
|
|
1942
|
-
return
|
|
1943
|
-
}
|
|
1944
|
-
requireTemporalTarget(target, width, height) {
|
|
1945
|
-
if (!(target instanceof WebGL2RenderTarget) || !this.renderTargets.has(target) || target.disposed || target.width !== width || target.height !== height || target.colorTexture.format !== "rgba16f")
|
|
1946
|
-
throw new RenderDeviceError("Temporal input must be a live same-device same-size RGBA16F target", "TEMPORAL_TARGET_INVALID");
|
|
1947
|
-
return target;
|
|
1948
|
-
}
|
|
1949
|
-
bindFullscreenTexture(unit, texture) {
|
|
1950
|
-
this.gl.activeTexture(this.gl.TEXTURE0 + unit);
|
|
1951
|
-
this.gl.bindTexture(this.gl.TEXTURE_2D, texture);
|
|
1952
|
-
this.gl.bindSampler(unit, null);
|
|
1953
|
-
}
|
|
1954
|
-
disposeBloomPingPongResources() {
|
|
1955
|
-
if (!this.bloomPingPongResources)
|
|
1956
|
-
return;
|
|
1957
|
-
for (const texture of this.bloomPingPongResources.textures)
|
|
1958
|
-
this.gl.deleteTexture(texture);
|
|
1959
|
-
for (const framebuffer of this.bloomPingPongResources.framebuffers)
|
|
1960
|
-
this.gl.deleteFramebuffer(framebuffer);
|
|
1961
|
-
this.bloomPingPongResources = null;
|
|
1962
|
-
}
|
|
1963
|
-
/**
|
|
1964
|
-
* Diagnostics for the most recent native bloom execution (muse3jsparity-PRD
|
|
1965
|
-
* A1). Null when no native bloom pass has run yet on this device.
|
|
1966
|
-
*/
|
|
1967
|
-
getBloomDiagnostics() {
|
|
1968
|
-
return this.lastBloomDiagnostics;
|
|
1969
|
-
}
|
|
1970
|
-
recordBloomDiagnostics(options, sourceWidth, sourceHeight, hdr, mipCount) {
|
|
1971
|
-
const plan = resolveBloomPyramidPlan(sourceWidth, sourceHeight, options.quality, hdr);
|
|
1972
|
-
const pingPongBytes = sourceWidth * sourceHeight * 4 * (hdr ? 2 : 1) * 2;
|
|
1973
|
-
const bytesPerChannel = plan.halfFloat ? 2 : 1;
|
|
1974
|
-
const level0 = plan.mips[0];
|
|
1975
|
-
const accumulatorBytes = level0.width * level0.height * 4 * bytesPerChannel;
|
|
1976
|
-
this.lastBloomDiagnostics = {
|
|
1977
|
-
quality: options.quality,
|
|
1978
|
-
mipCount,
|
|
1979
|
-
targetCount: options.quality === "performance" ? 2 : plan.mips.length * 2 + 1,
|
|
1980
|
-
targetBytes: (options.quality === "performance" ? pingPongBytes : plan.targetBytes + accumulatorBytes + pingPongBytes),
|
|
1981
|
-
compositeGain: options.intensity * resolveBloomPyramidResponseGain(plan),
|
|
1982
|
-
threshold: options.threshold,
|
|
1983
|
-
intensity: options.intensity,
|
|
1984
|
-
softKnee: options.softKnee,
|
|
1985
|
-
shoulder: options.shoulder,
|
|
1986
|
-
halfFloat: hdr || plan.halfFloat,
|
|
1987
|
-
};
|
|
1300
|
+
return shader;
|
|
1988
1301
|
}
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
*/
|
|
2003
|
-
describeGpuTargetInventory(liveRenderTargets) {
|
|
2004
|
-
const entries = liveRenderTargets.map((target) => ({
|
|
2005
|
-
label: target.label,
|
|
2006
|
-
kind: "render-target",
|
|
2007
|
-
bytes: target.colorTexture.byteLength + (target.depthTexture?.byteLength ?? 0),
|
|
2008
|
-
owner: resolveGpuTargetOwner(target.label)
|
|
2009
|
-
}));
|
|
2010
|
-
const pyramid = this.bloomPyramidResources;
|
|
2011
|
-
if (pyramid) {
|
|
2012
|
-
const bytesPerPixel = pyramid.hdr ? 8 : 4;
|
|
2013
|
-
pyramid.plan.mips.forEach((mip, index) => {
|
|
2014
|
-
for (const side of ["a", "b"]) {
|
|
2015
|
-
entries.push({
|
|
2016
|
-
label: `bloom-pyramid-mip${index}${side}`,
|
|
2017
|
-
kind: "pyramid-mip",
|
|
2018
|
-
bytes: mip.width * mip.height * bytesPerPixel,
|
|
2019
|
-
owner: "a1-bloom"
|
|
2020
|
-
});
|
|
2021
|
-
}
|
|
2022
|
-
});
|
|
2023
|
-
const level0 = pyramid.plan.mips[0];
|
|
2024
|
-
if (level0) {
|
|
2025
|
-
for (const side of ["a", "b"]) {
|
|
2026
|
-
entries.push({
|
|
2027
|
-
label: `bloom-pyramid-accumulator-${side}`,
|
|
2028
|
-
kind: "pyramid-accumulator",
|
|
2029
|
-
bytes: level0.width * level0.height * bytesPerPixel,
|
|
2030
|
-
owner: "a1-bloom"
|
|
2031
|
-
});
|
|
2032
|
-
}
|
|
2033
|
-
}
|
|
2034
|
-
}
|
|
2035
|
-
const pingPong = this.bloomPingPongResources;
|
|
2036
|
-
if (pingPong) {
|
|
2037
|
-
const bytesPerPixel = pingPong.hdr ? 8 : 4;
|
|
2038
|
-
for (const side of ["a", "b"]) {
|
|
2039
|
-
entries.push({
|
|
2040
|
-
label: `bloom-ping-pong-${side}`,
|
|
2041
|
-
kind: "ping-pong",
|
|
2042
|
-
bytes: pingPong.width * pingPong.height * bytesPerPixel,
|
|
2043
|
-
owner: "a1-bloom"
|
|
2044
|
-
});
|
|
1302
|
+
reflectProgram(program) {
|
|
1303
|
+
const attributes = new Map();
|
|
1304
|
+
const uniforms = new Set();
|
|
1305
|
+
const attributeDetails = new Map();
|
|
1306
|
+
const uniformDetails = new Map();
|
|
1307
|
+
const activeAttributes = this.gl.getProgramParameter(program, this.gl.ACTIVE_ATTRIBUTES);
|
|
1308
|
+
const activeUniforms = this.gl.getProgramParameter(program, this.gl.ACTIVE_UNIFORMS);
|
|
1309
|
+
for (let i = 0; i < activeAttributes; i += 1) {
|
|
1310
|
+
const info = this.gl.getActiveAttrib(program, i);
|
|
1311
|
+
if (info) {
|
|
1312
|
+
const location = this.gl.getAttribLocation(program, info.name);
|
|
1313
|
+
attributes.set(info.name, location);
|
|
1314
|
+
attributeDetails.set(info.name, { name: info.name, type: String(info.type), location, source: "vertex", line: 0 });
|
|
2045
1315
|
}
|
|
2046
1316
|
}
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
});
|
|
2054
|
-
}
|
|
2055
|
-
if (this.bloomCompositeLutTexture) {
|
|
2056
|
-
entries.push({
|
|
2057
|
-
label: "bloom-composite-lut",
|
|
2058
|
-
kind: "lut",
|
|
2059
|
-
bytes: BLOOM_COMPOSITE_LUT_SIZE * BLOOM_COMPOSITE_LUT_SIZE * 4,
|
|
2060
|
-
owner: "a1-bloom"
|
|
2061
|
-
});
|
|
2062
|
-
}
|
|
2063
|
-
if (this.outlineBlendLutTexture) {
|
|
2064
|
-
entries.push({ label: "outline-blend-lut", kind: "lut", bytes: OUTLINE_BLEND_LUT_WIDTH * 4, owner: "post" });
|
|
2065
|
-
}
|
|
2066
|
-
if (this.motionBlurVelocityTexture && this.motionBlurVelocitySize) {
|
|
2067
|
-
entries.push({
|
|
2068
|
-
label: "motion-blur-velocity",
|
|
2069
|
-
kind: "history",
|
|
2070
|
-
bytes: this.motionBlurVelocitySize.width * this.motionBlurVelocitySize.height * 8,
|
|
2071
|
-
owner: "post"
|
|
2072
|
-
});
|
|
2073
|
-
}
|
|
2074
|
-
if (this.taaHistoryTexture && this.taaHistorySize) {
|
|
2075
|
-
entries.push({
|
|
2076
|
-
label: "taa-history",
|
|
2077
|
-
kind: "history",
|
|
2078
|
-
bytes: this.taaHistorySize.width * this.taaHistorySize.height * 4,
|
|
2079
|
-
owner: "post"
|
|
2080
|
-
});
|
|
2081
|
-
}
|
|
2082
|
-
return entries;
|
|
2083
|
-
}
|
|
2084
|
-
disposeBloomPyramidResources() {
|
|
2085
|
-
if (!this.bloomPyramidResources)
|
|
2086
|
-
return;
|
|
2087
|
-
for (const texture of this.bloomPyramidResources.textures)
|
|
2088
|
-
this.gl.deleteTexture(texture);
|
|
2089
|
-
for (const framebuffer of this.bloomPyramidResources.framebuffers)
|
|
2090
|
-
this.gl.deleteFramebuffer(framebuffer);
|
|
2091
|
-
this.gl.deleteTexture(this.bloomPyramidResources.accumulatorTextureA);
|
|
2092
|
-
this.gl.deleteFramebuffer(this.bloomPyramidResources.accumulatorFramebufferA);
|
|
2093
|
-
this.gl.deleteTexture(this.bloomPyramidResources.accumulatorTextureB);
|
|
2094
|
-
this.gl.deleteFramebuffer(this.bloomPyramidResources.accumulatorFramebufferB);
|
|
2095
|
-
this.bloomPyramidResources = null;
|
|
2096
|
-
}
|
|
2097
|
-
/**
|
|
2098
|
-
* Mip-chain targets for the balanced/cinematic bloom pyramid. Each level is a
|
|
2099
|
-
* single texture+framebuffer at the planned size with linear filtering so the
|
|
2100
|
-
* downsample and accumulate passes can sample across levels. Half-float backs
|
|
2101
|
-
* the chain when the source is HDR or the cinematic preset requests it.
|
|
2102
|
-
*/
|
|
2103
|
-
ensureBloomPyramidResources(plan, hdr) {
|
|
2104
|
-
const current = this.bloomPyramidResources;
|
|
2105
|
-
if (current && current.plan.quality === plan.quality && current.hdr === (hdr || plan.halfFloat) &&
|
|
2106
|
-
current.plan.mips.length === plan.mips.length &&
|
|
2107
|
-
current.plan.mips.every((mip, index) => mip.width === plan.mips[index].width && mip.height === plan.mips[index].height)) {
|
|
2108
|
-
return current;
|
|
2109
|
-
}
|
|
2110
|
-
this.disposeBloomPyramidResources();
|
|
2111
|
-
const textureUnit0 = this.captureTextureUnit0();
|
|
2112
|
-
const previousFramebuffer = this.gl.getParameter(this.gl.FRAMEBUFFER_BINDING);
|
|
2113
|
-
const textures = [];
|
|
2114
|
-
const framebuffers = [];
|
|
2115
|
-
const useHalfFloat = hdr || plan.halfFloat;
|
|
2116
|
-
const allocateTarget = (width, height, label) => {
|
|
2117
|
-
const texture = this.gl.createTexture();
|
|
2118
|
-
const framebuffer = this.gl.createFramebuffer();
|
|
2119
|
-
if (!texture || !framebuffer) {
|
|
2120
|
-
if (texture)
|
|
2121
|
-
this.gl.deleteTexture(texture);
|
|
2122
|
-
if (framebuffer)
|
|
2123
|
-
this.gl.deleteFramebuffer(framebuffer);
|
|
2124
|
-
throw new RenderDeviceError(`Failed to allocate WebGL2 bloom pyramid ${label}`, "WEBGL_ALLOCATION_FAILED", { width, height });
|
|
2125
|
-
}
|
|
2126
|
-
textures.push(texture);
|
|
2127
|
-
framebuffers.push(framebuffer);
|
|
2128
|
-
this.gl.bindTexture(this.gl.TEXTURE_2D, texture);
|
|
2129
|
-
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);
|
|
2130
|
-
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);
|
|
2131
|
-
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);
|
|
2132
|
-
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);
|
|
2133
|
-
this.gl.texImage2D(this.gl.TEXTURE_2D, 0, useHalfFloat ? this.gl.RGBA16F : this.gl.RGBA8, width, height, 0, this.gl.RGBA, useHalfFloat ? this.gl.HALF_FLOAT : this.gl.UNSIGNED_BYTE, null);
|
|
2134
|
-
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, framebuffer);
|
|
2135
|
-
this.gl.framebufferTexture2D(this.gl.FRAMEBUFFER, this.gl.COLOR_ATTACHMENT0, this.gl.TEXTURE_2D, texture, 0);
|
|
2136
|
-
const status = this.gl.checkFramebufferStatus(this.gl.FRAMEBUFFER);
|
|
2137
|
-
if (status !== this.gl.FRAMEBUFFER_COMPLETE) {
|
|
2138
|
-
throw new RenderDeviceError("WebGL2 bloom pyramid framebuffer status is invalid", "FRAMEBUFFER_INVALID", { width, height, status });
|
|
2139
|
-
}
|
|
2140
|
-
return { texture, framebuffer };
|
|
2141
|
-
};
|
|
2142
|
-
try {
|
|
2143
|
-
// Two ping-pong targets per mip (separable blur needs distinct read/write
|
|
2144
|
-
// targets at the same size), plus two level-0-sized accumulators: the
|
|
2145
|
-
// weighted sum ping-pongs between them so no pass ever samples the
|
|
2146
|
-
// texture of its own bound framebuffer (feedback loop).
|
|
2147
|
-
for (const mip of plan.mips) {
|
|
2148
|
-
allocateTarget(mip.width, mip.height, "mip");
|
|
2149
|
-
allocateTarget(mip.width, mip.height, "mip");
|
|
1317
|
+
for (let i = 0; i < activeUniforms; i += 1) {
|
|
1318
|
+
const info = this.gl.getActiveUniform(program, i);
|
|
1319
|
+
if (info) {
|
|
1320
|
+
const name = info.name.replace(/\[0\]$/, "");
|
|
1321
|
+
uniforms.add(name);
|
|
1322
|
+
uniformDetails.set(name, { name, type: String(info.type), arraySize: info.size > 1 ? info.size : null, source: "fragment", line: 0 });
|
|
2150
1323
|
}
|
|
2151
|
-
const level0 = plan.mips[0];
|
|
2152
|
-
const accumulatorA = allocateTarget(level0.width, level0.height, "accumulator-a");
|
|
2153
|
-
const accumulatorB = allocateTarget(level0.width, level0.height, "accumulator-b");
|
|
2154
|
-
const finalResources = {
|
|
2155
|
-
plan,
|
|
2156
|
-
hdr: useHalfFloat,
|
|
2157
|
-
textures,
|
|
2158
|
-
framebuffers,
|
|
2159
|
-
accumulatorTextureA: accumulatorA.texture,
|
|
2160
|
-
accumulatorFramebufferA: accumulatorA.framebuffer,
|
|
2161
|
-
accumulatorTextureB: accumulatorB.texture,
|
|
2162
|
-
accumulatorFramebufferB: accumulatorB.framebuffer
|
|
2163
|
-
};
|
|
2164
|
-
this.bloomPyramidResources = finalResources;
|
|
2165
|
-
return finalResources;
|
|
2166
|
-
}
|
|
2167
|
-
catch (error) {
|
|
2168
|
-
for (const texture of textures)
|
|
2169
|
-
this.gl.deleteTexture(texture);
|
|
2170
|
-
for (const framebuffer of framebuffers)
|
|
2171
|
-
this.gl.deleteFramebuffer(framebuffer);
|
|
2172
|
-
throw error;
|
|
2173
1324
|
}
|
|
2174
|
-
|
|
2175
|
-
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, previousFramebuffer);
|
|
2176
|
-
this.restoreTextureUnit0(textureUnit0);
|
|
2177
|
-
this.stateCache.invalidate();
|
|
2178
|
-
}
|
|
2179
|
-
}
|
|
2180
|
-
captureTextureUnit0() {
|
|
2181
|
-
const activeTexture = this.gl.getParameter(this.gl.ACTIVE_TEXTURE);
|
|
2182
|
-
this.gl.activeTexture(this.gl.TEXTURE0);
|
|
2183
|
-
return {
|
|
2184
|
-
activeTexture,
|
|
2185
|
-
texture2d: this.gl.getParameter(this.gl.TEXTURE_BINDING_2D),
|
|
2186
|
-
sampler: this.gl.getParameter(this.gl.SAMPLER_BINDING)
|
|
2187
|
-
};
|
|
2188
|
-
}
|
|
2189
|
-
restoreTextureUnit0(snapshot) {
|
|
2190
|
-
this.gl.activeTexture(this.gl.TEXTURE0);
|
|
2191
|
-
this.gl.bindTexture(this.gl.TEXTURE_2D, snapshot.texture2d);
|
|
2192
|
-
this.gl.bindSampler(0, snapshot.sampler);
|
|
2193
|
-
this.gl.activeTexture(snapshot.activeTexture);
|
|
2194
|
-
}
|
|
2195
|
-
captureTextureUnitBinding(unit) {
|
|
2196
|
-
this.gl.activeTexture(this.gl.TEXTURE0 + unit);
|
|
2197
|
-
return {
|
|
2198
|
-
texture2d: this.gl.getParameter(this.gl.TEXTURE_BINDING_2D),
|
|
2199
|
-
sampler: this.gl.getParameter(this.gl.SAMPLER_BINDING)
|
|
2200
|
-
};
|
|
2201
|
-
}
|
|
2202
|
-
restoreTextureUnitBinding(unit, snapshot) {
|
|
2203
|
-
this.gl.activeTexture(this.gl.TEXTURE0 + unit);
|
|
2204
|
-
this.gl.bindTexture(this.gl.TEXTURE_2D, snapshot.texture2d);
|
|
2205
|
-
this.gl.bindSampler(unit, snapshot.sampler);
|
|
2206
|
-
}
|
|
2207
|
-
prepareFullscreenPresentation(framebuffer, outputWidth, outputHeight) {
|
|
2208
|
-
const textureUnit0 = this.captureTextureUnit0();
|
|
2209
|
-
const textureUnit1 = this.captureTextureUnitBinding(1);
|
|
2210
|
-
const textureUnit2 = this.captureTextureUnitBinding(2);
|
|
2211
|
-
this.gl.activeTexture(textureUnit0.activeTexture);
|
|
2212
|
-
const snapshot = {
|
|
2213
|
-
framebuffer: this.gl.getParameter(this.gl.FRAMEBUFFER_BINDING),
|
|
2214
|
-
program: this.gl.getParameter(this.gl.CURRENT_PROGRAM),
|
|
2215
|
-
textureUnit0,
|
|
2216
|
-
textureUnit1,
|
|
2217
|
-
textureUnit2,
|
|
2218
|
-
vertexArray: this.gl.getParameter(this.gl.VERTEX_ARRAY_BINDING),
|
|
2219
|
-
viewport: this.gl.getParameter(this.gl.VIEWPORT),
|
|
2220
|
-
colorMask: this.gl.getParameter(this.gl.COLOR_WRITEMASK),
|
|
2221
|
-
depthTestEnabled: this.gl.isEnabled(this.gl.DEPTH_TEST),
|
|
2222
|
-
cullFaceEnabled: this.gl.isEnabled(this.gl.CULL_FACE),
|
|
2223
|
-
blendEnabled: this.gl.isEnabled(this.gl.BLEND),
|
|
2224
|
-
scissorTestEnabled: this.gl.isEnabled(this.gl.SCISSOR_TEST),
|
|
2225
|
-
stencilTestEnabled: this.gl.isEnabled(this.gl.STENCIL_TEST),
|
|
2226
|
-
polygonOffsetFillEnabled: this.gl.isEnabled(this.gl.POLYGON_OFFSET_FILL),
|
|
2227
|
-
depthMask: this.gl.getParameter(this.gl.DEPTH_WRITEMASK)
|
|
2228
|
-
};
|
|
2229
|
-
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, framebuffer);
|
|
2230
|
-
this.gl.viewport(0, 0, outputWidth, outputHeight);
|
|
2231
|
-
this.gl.colorMask(true, true, true, true);
|
|
2232
|
-
this.gl.disable(this.gl.SCISSOR_TEST);
|
|
2233
|
-
this.gl.disable(this.gl.STENCIL_TEST);
|
|
2234
|
-
this.gl.disable(this.gl.POLYGON_OFFSET_FILL);
|
|
2235
|
-
this.gl.disable(this.gl.DEPTH_TEST);
|
|
2236
|
-
this.gl.disable(this.gl.CULL_FACE);
|
|
2237
|
-
this.gl.disable(this.gl.BLEND);
|
|
2238
|
-
this.gl.depthMask(false);
|
|
2239
|
-
return snapshot;
|
|
2240
|
-
}
|
|
2241
|
-
restoreFullscreenPresentationState(snapshot, fallbackWidth, fallbackHeight) {
|
|
2242
|
-
this.gl.bindVertexArray(snapshot.vertexArray);
|
|
2243
|
-
this.restoreTextureUnitBinding(2, snapshot.textureUnit2);
|
|
2244
|
-
this.restoreTextureUnitBinding(1, snapshot.textureUnit1);
|
|
2245
|
-
this.restoreTextureUnit0(snapshot.textureUnit0);
|
|
2246
|
-
this.gl.useProgram(snapshot.program);
|
|
2247
|
-
if (snapshot.depthTestEnabled)
|
|
2248
|
-
this.gl.enable(this.gl.DEPTH_TEST);
|
|
2249
|
-
else
|
|
2250
|
-
this.gl.disable(this.gl.DEPTH_TEST);
|
|
2251
|
-
if (snapshot.cullFaceEnabled)
|
|
2252
|
-
this.gl.enable(this.gl.CULL_FACE);
|
|
2253
|
-
else
|
|
2254
|
-
this.gl.disable(this.gl.CULL_FACE);
|
|
2255
|
-
if (snapshot.blendEnabled)
|
|
2256
|
-
this.gl.enable(this.gl.BLEND);
|
|
2257
|
-
else
|
|
2258
|
-
this.gl.disable(this.gl.BLEND);
|
|
2259
|
-
if (snapshot.scissorTestEnabled)
|
|
2260
|
-
this.gl.enable(this.gl.SCISSOR_TEST);
|
|
2261
|
-
else
|
|
2262
|
-
this.gl.disable(this.gl.SCISSOR_TEST);
|
|
2263
|
-
if (snapshot.stencilTestEnabled)
|
|
2264
|
-
this.gl.enable(this.gl.STENCIL_TEST);
|
|
2265
|
-
else
|
|
2266
|
-
this.gl.disable(this.gl.STENCIL_TEST);
|
|
2267
|
-
if (snapshot.polygonOffsetFillEnabled)
|
|
2268
|
-
this.gl.enable(this.gl.POLYGON_OFFSET_FILL);
|
|
2269
|
-
else
|
|
2270
|
-
this.gl.disable(this.gl.POLYGON_OFFSET_FILL);
|
|
2271
|
-
this.gl.colorMask(snapshot.colorMask[0] ?? true, snapshot.colorMask[1] ?? true, snapshot.colorMask[2] ?? true, snapshot.colorMask[3] ?? true);
|
|
2272
|
-
this.gl.depthMask(snapshot.depthMask);
|
|
2273
|
-
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, snapshot.framebuffer);
|
|
2274
|
-
this.gl.viewport(snapshot.viewport[0] ?? 0, snapshot.viewport[1] ?? 0, snapshot.viewport[2] ?? fallbackWidth, snapshot.viewport[3] ?? fallbackHeight);
|
|
2275
|
-
this.stateCache.invalidate();
|
|
2276
|
-
}
|
|
2277
|
-
ensurePresentationVertexArray() {
|
|
2278
|
-
if (this.presentationVertexArray)
|
|
2279
|
-
return this.presentationVertexArray;
|
|
2280
|
-
const vertexArray = this.gl.createVertexArray();
|
|
2281
|
-
if (!vertexArray) {
|
|
2282
|
-
throw new RenderDeviceError("Failed to allocate WebGL presentation vertex array", "WEBGL_ALLOCATION_FAILED");
|
|
2283
|
-
}
|
|
2284
|
-
this.presentationVertexArray = vertexArray;
|
|
2285
|
-
return vertexArray;
|
|
2286
|
-
}
|
|
2287
|
-
ensureDepthReadbackProgram() {
|
|
2288
|
-
if (this.depthReadbackProgram) {
|
|
2289
|
-
return this.depthReadbackProgram;
|
|
2290
|
-
}
|
|
2291
|
-
const vertex = this.compileShader(this.gl.VERTEX_SHADER, `#version 300 es
|
|
2292
|
-
precision highp float;
|
|
2293
|
-
out vec2 v_uv;
|
|
2294
|
-
void main() {
|
|
2295
|
-
vec2 position = vec2(float((gl_VertexID << 1) & 2), float(gl_VertexID & 2));
|
|
2296
|
-
v_uv = position;
|
|
2297
|
-
gl_Position = vec4(position * 2.0 - 1.0, 0.0, 1.0);
|
|
2298
|
-
}
|
|
2299
|
-
`, "webgl2-depth-readback");
|
|
2300
|
-
const fragment = this.compileShader(this.gl.FRAGMENT_SHADER, `#version 300 es
|
|
2301
|
-
precision highp float;
|
|
2302
|
-
uniform sampler2D u_depth;
|
|
2303
|
-
uniform vec4 u_sourceRect;
|
|
2304
|
-
in vec2 v_uv;
|
|
2305
|
-
out vec4 outColor;
|
|
2306
|
-
vec3 packDepth24(float value) {
|
|
2307
|
-
value = clamp(value, 0.0, 1.0);
|
|
2308
|
-
vec3 encoded = fract(value * vec3(1.0, 255.0, 65025.0));
|
|
2309
|
-
encoded -= encoded.yzz * vec3(1.0 / 255.0, 1.0 / 255.0, 0.0);
|
|
2310
|
-
return encoded;
|
|
2311
|
-
}
|
|
2312
|
-
void main() {
|
|
2313
|
-
vec2 uv = u_sourceRect.xy + v_uv * u_sourceRect.zw;
|
|
2314
|
-
outColor = vec4(packDepth24(texture(u_depth, uv).r), 1.0);
|
|
2315
|
-
}
|
|
2316
|
-
`, "webgl2-depth-readback");
|
|
2317
|
-
const program = this.gl.createProgram();
|
|
2318
|
-
if (!program) {
|
|
2319
|
-
this.gl.deleteShader(vertex);
|
|
2320
|
-
this.gl.deleteShader(fragment);
|
|
2321
|
-
throw new RenderDeviceError("Failed to allocate WebGL2 depth readback shader", "WEBGL_ALLOCATION_FAILED");
|
|
2322
|
-
}
|
|
2323
|
-
this.gl.attachShader(program, vertex);
|
|
2324
|
-
this.gl.attachShader(program, fragment);
|
|
2325
|
-
this.gl.linkProgram(program);
|
|
2326
|
-
this.gl.deleteShader(vertex);
|
|
2327
|
-
this.gl.deleteShader(fragment);
|
|
2328
|
-
if (!this.gl.getProgramParameter(program, this.gl.LINK_STATUS)) {
|
|
2329
|
-
const log = this.gl.getProgramInfoLog(program) ?? "Unknown depth readback shader link error";
|
|
2330
|
-
this.gl.deleteProgram(program);
|
|
2331
|
-
throw new RenderDeviceError("WebGL2 depth readback shader link failed", "SHADER_LINK_FAILED", { log });
|
|
2332
|
-
}
|
|
2333
|
-
this.depthReadbackProgram = program;
|
|
2334
|
-
return program;
|
|
1325
|
+
return { attributes, uniforms, attributeDetails, uniformDetails };
|
|
2335
1326
|
}
|
|
2336
|
-
ensurePresentationProgram() {
|
|
2337
|
-
if (this.presentationProgram) {
|
|
2338
|
-
return this.presentationProgram;
|
|
2339
|
-
}
|
|
2340
|
-
const vertex = this.compileShader(this.gl.VERTEX_SHADER, `#version 300 es
|
|
2341
|
-
precision highp float;
|
|
2342
|
-
out vec2 v_uv;
|
|
2343
|
-
void main() {
|
|
2344
|
-
vec2 position = vec2(float((gl_VertexID << 1) & 2), float(gl_VertexID & 2));
|
|
2345
|
-
v_uv = position;
|
|
2346
|
-
gl_Position = vec4(position * 2.0 - 1.0, 0.0, 1.0);
|
|
2347
|
-
}
|
|
2348
|
-
`, "webgl2-present-render-target");
|
|
2349
|
-
const fragment = this.compileShader(this.gl.FRAGMENT_SHADER, `#version 300 es
|
|
2350
|
-
precision highp float;
|
|
2351
|
-
uniform sampler2D u_source;
|
|
2352
|
-
in vec2 v_uv;
|
|
2353
|
-
out vec4 outColor;
|
|
2354
|
-
void main() {
|
|
2355
|
-
outColor = texture(u_source, v_uv);
|
|
2356
|
-
}
|
|
2357
|
-
`, "webgl2-present-render-target");
|
|
2358
|
-
const program = this.gl.createProgram();
|
|
2359
|
-
if (!program) {
|
|
2360
|
-
this.gl.deleteShader(vertex);
|
|
2361
|
-
this.gl.deleteShader(fragment);
|
|
2362
|
-
throw new RenderDeviceError("Failed to allocate WebGL presentation shader", "WEBGL_ALLOCATION_FAILED");
|
|
2363
|
-
}
|
|
2364
|
-
this.gl.attachShader(program, vertex);
|
|
2365
|
-
this.gl.attachShader(program, fragment);
|
|
2366
|
-
this.gl.linkProgram(program);
|
|
2367
|
-
this.gl.deleteShader(vertex);
|
|
2368
|
-
this.gl.deleteShader(fragment);
|
|
2369
|
-
if (!this.gl.getProgramParameter(program, this.gl.LINK_STATUS)) {
|
|
2370
|
-
const log = this.gl.getProgramInfoLog(program) ?? "Unknown presentation shader link error";
|
|
2371
|
-
this.gl.deleteProgram(program);
|
|
2372
|
-
throw new RenderDeviceError("WebGL presentation shader link failed", "SHADER_LINK_FAILED", { log });
|
|
2373
|
-
}
|
|
2374
|
-
this.presentationProgram = program;
|
|
2375
|
-
return program;
|
|
2376
|
-
}
|
|
2377
|
-
ensureBloomBrightExtractProgram() {
|
|
2378
|
-
if (this.bloomBrightExtractProgram) {
|
|
2379
|
-
return this.bloomBrightExtractProgram;
|
|
2380
|
-
}
|
|
2381
|
-
this.bloomBrightExtractProgram = this.createFullscreenProgram(`#version 300 es
|
|
2382
|
-
precision highp float;
|
|
2383
|
-
precision highp int;
|
|
2384
|
-
uniform sampler2D u_source;
|
|
2385
|
-
uniform sampler2D u_brightLut;
|
|
2386
|
-
uniform int u_hdr;
|
|
2387
|
-
uniform float u_threshold;
|
|
2388
|
-
uniform float u_softKnee;
|
|
2389
|
-
out vec4 outColor;
|
|
2390
|
-
|
|
2391
|
-
uvec4 byteTexel(sampler2D source, ivec2 coordinate) {
|
|
2392
|
-
return uvec4(texelFetch(source, coordinate, 0) * 255.0 + 0.5);
|
|
2393
|
-
}
|
|
2394
|
-
|
|
2395
|
-
void main() {
|
|
2396
|
-
ivec2 pixel = ivec2(gl_FragCoord.xy);
|
|
2397
|
-
if (u_hdr == 1) {
|
|
2398
|
-
vec4 source = texelFetch(u_source, pixel, 0);
|
|
2399
|
-
float luma = dot(source.rgb, vec3(0.2126, 0.7152, 0.0722));
|
|
2400
|
-
float kneeLow = max(u_threshold - u_softKnee, 0.0);
|
|
2401
|
-
float kneeHigh = min(u_threshold + u_softKnee, 1.0);
|
|
2402
|
-
float weight = u_softKnee <= 0.0
|
|
2403
|
-
? (luma >= u_threshold ? 1.0 : 0.0)
|
|
2404
|
-
: smoothstep(kneeLow, kneeHigh, luma);
|
|
2405
|
-
outColor = source * weight;
|
|
2406
|
-
return;
|
|
2407
|
-
}
|
|
2408
|
-
uvec4 source = byteTexel(u_source, pixel);
|
|
2409
|
-
uint colorIndex = (source.r << 16u) | (source.g << 8u) | source.b;
|
|
2410
|
-
uint byteIndex = colorIndex >> 3u;
|
|
2411
|
-
uint texelIndex = byteIndex >> 2u;
|
|
2412
|
-
ivec2 lutCoordinate = ivec2(
|
|
2413
|
-
int(texelIndex % ${BLOOM_BRIGHT_LUT_WIDTH}u),
|
|
2414
|
-
int(texelIndex / ${BLOOM_BRIGHT_LUT_WIDTH}u)
|
|
2415
|
-
);
|
|
2416
|
-
uvec4 packed = byteTexel(u_brightLut, lutCoordinate);
|
|
2417
|
-
uint component = byteIndex & 3u;
|
|
2418
|
-
uint packedByte = component == 0u
|
|
2419
|
-
? packed.r
|
|
2420
|
-
: component == 1u
|
|
2421
|
-
? packed.g
|
|
2422
|
-
: component == 2u
|
|
2423
|
-
? packed.b
|
|
2424
|
-
: packed.a;
|
|
2425
|
-
bool bright = ((packedByte >> (colorIndex & 7u)) & 1u) == 1u;
|
|
2426
|
-
outColor = bright ? vec4(source) / 255.0 : vec4(0.0);
|
|
2427
|
-
}
|
|
2428
|
-
`, "webgl2-bloom-bright-extract");
|
|
2429
|
-
return this.bloomBrightExtractProgram;
|
|
2430
|
-
}
|
|
2431
|
-
ensureBloomBlurProgram() {
|
|
2432
|
-
if (this.bloomBlurProgram) {
|
|
2433
|
-
return this.bloomBlurProgram;
|
|
2434
|
-
}
|
|
2435
|
-
this.bloomBlurProgram = this.createFullscreenProgram(`#version 300 es
|
|
2436
|
-
precision highp float;
|
|
2437
|
-
precision highp int;
|
|
2438
|
-
uniform sampler2D u_source;
|
|
2439
|
-
uniform ivec2 u_size;
|
|
2440
|
-
uniform int u_radius;
|
|
2441
|
-
uniform int u_horizontal;
|
|
2442
|
-
uniform int u_hdr;
|
|
2443
|
-
out vec4 outColor;
|
|
2444
|
-
|
|
2445
|
-
vec4 sourcePixel(ivec2 coordinate) {
|
|
2446
|
-
return texelFetch(u_source, clamp(coordinate, ivec2(0), u_size - ivec2(1)), 0);
|
|
2447
|
-
}
|
|
2448
|
-
|
|
2449
|
-
void main() {
|
|
2450
|
-
ivec2 pixel = ivec2(gl_FragCoord.xy);
|
|
2451
|
-
float sigma = max(float(u_radius) / 3.0, 0.5);
|
|
2452
|
-
float coefficient = 0.39894 / sigma;
|
|
2453
|
-
vec4 sum = sourcePixel(pixel) * coefficient;
|
|
2454
|
-
float weightSum = coefficient;
|
|
2455
|
-
for (int offset = 1; offset <= 16; offset += 1) {
|
|
2456
|
-
if (offset > u_radius) continue;
|
|
2457
|
-
float distance = float(offset);
|
|
2458
|
-
float weight = coefficient * exp(-0.5 * distance * distance / (sigma * sigma));
|
|
2459
|
-
ivec2 delta = u_horizontal == 1 ? ivec2(offset, 0) : ivec2(0, offset);
|
|
2460
|
-
sum += (sourcePixel(pixel + delta) + sourcePixel(pixel - delta)) * weight;
|
|
2461
|
-
weightSum += 2.0 * weight;
|
|
2462
|
-
}
|
|
2463
|
-
outColor = sum / max(weightSum, 0.000001);
|
|
2464
|
-
}
|
|
2465
|
-
`, "webgl2-bloom-blur");
|
|
2466
|
-
return this.bloomBlurProgram;
|
|
2467
|
-
}
|
|
2468
|
-
ensureBloomCompositeProgram() {
|
|
2469
|
-
if (this.bloomCompositeProgram) {
|
|
2470
|
-
return this.bloomCompositeProgram;
|
|
2471
|
-
}
|
|
2472
|
-
this.bloomCompositeProgram = this.createFullscreenProgram(`#version 300 es
|
|
2473
|
-
precision highp float;
|
|
2474
|
-
precision highp int;
|
|
2475
|
-
uniform sampler2D u_source;
|
|
2476
|
-
uniform sampler2D u_blurred;
|
|
2477
|
-
uniform sampler2D u_compositeLut;
|
|
2478
|
-
uniform int u_hdr;
|
|
2479
|
-
uniform float u_intensity;
|
|
2480
|
-
out vec4 outColor;
|
|
2481
|
-
|
|
2482
|
-
uvec4 byteTexel(sampler2D source, ivec2 coordinate) {
|
|
2483
|
-
return uvec4(texelFetch(source, coordinate, 0) * 255.0 + 0.5);
|
|
2484
|
-
}
|
|
2485
|
-
|
|
2486
|
-
float compositeChannel(uint source, uint blurred) {
|
|
2487
|
-
return texelFetch(u_compositeLut, ivec2(int(source), int(blurred)), 0).r;
|
|
2488
|
-
}
|
|
2489
|
-
|
|
2490
|
-
void main() {
|
|
2491
|
-
ivec2 pixel = ivec2(gl_FragCoord.xy);
|
|
2492
|
-
if (u_hdr == 1) {
|
|
2493
|
-
vec4 source = texelFetch(u_source, pixel, 0);
|
|
2494
|
-
vec3 blurred = texelFetch(u_blurred, pixel, 0).rgb;
|
|
2495
|
-
outColor = vec4(source.rgb + blurred * u_intensity, source.a);
|
|
2496
|
-
return;
|
|
2497
|
-
}
|
|
2498
|
-
uvec4 source = byteTexel(u_source, pixel);
|
|
2499
|
-
uvec4 blurred = byteTexel(u_blurred, pixel);
|
|
2500
|
-
outColor = vec4(
|
|
2501
|
-
compositeChannel(source.r, blurred.r),
|
|
2502
|
-
compositeChannel(source.g, blurred.g),
|
|
2503
|
-
compositeChannel(source.b, blurred.b),
|
|
2504
|
-
float(source.a) / 255.0
|
|
2505
|
-
);
|
|
2506
|
-
}
|
|
2507
|
-
`, "webgl2-bloom-composite");
|
|
2508
|
-
return this.bloomCompositeProgram;
|
|
2509
|
-
}
|
|
2510
|
-
ensureBloomDownsampleProgram() {
|
|
2511
|
-
if (this.bloomDownsampleProgram)
|
|
2512
|
-
return this.bloomDownsampleProgram;
|
|
2513
|
-
this.bloomDownsampleProgram = this.createFullscreenProgram(`#version 300 es
|
|
2514
|
-
precision highp float;
|
|
2515
|
-
uniform sampler2D u_source;
|
|
2516
|
-
uniform vec2 u_texelSize;
|
|
2517
|
-
uniform vec2 u_targetSize;
|
|
2518
|
-
out vec4 outColor;
|
|
2519
|
-
void main() {
|
|
2520
|
-
// gl_FragCoord is expressed in destination pixels. Normalize by the
|
|
2521
|
-
// destination size so every downsample covers the complete source image;
|
|
2522
|
-
// multiplying by source texel size cropped a half-size target to the
|
|
2523
|
-
// lower-left quarter of the preceding level.
|
|
2524
|
-
vec2 uv = gl_FragCoord.xy / u_targetSize;
|
|
2525
|
-
vec2 e = u_texelSize * 0.5;
|
|
2526
|
-
vec4 sum = texture(u_source, uv - e) + texture(u_source, uv + vec2(e.x, -e.y))
|
|
2527
|
-
+ texture(u_source, uv + vec2(-e.x, e.y)) + texture(u_source, uv + e);
|
|
2528
|
-
outColor = sum * 0.25;
|
|
2529
|
-
}
|
|
2530
|
-
`, "webgl2-bloom-downsample");
|
|
2531
|
-
return this.bloomDownsampleProgram;
|
|
2532
|
-
}
|
|
2533
|
-
ensureBloomAccumulateProgram() {
|
|
2534
|
-
if (this.bloomAccumulateProgram)
|
|
2535
|
-
return this.bloomAccumulateProgram;
|
|
2536
|
-
this.bloomAccumulateProgram = this.createFullscreenProgram(`#version 300 es
|
|
2537
|
-
precision highp float;
|
|
2538
|
-
uniform sampler2D u_base;
|
|
2539
|
-
uniform sampler2D u_bloom;
|
|
2540
|
-
uniform float u_weight;
|
|
2541
|
-
out vec4 outColor;
|
|
2542
|
-
void main() {
|
|
2543
|
-
ivec2 pixel = ivec2(gl_FragCoord.xy);
|
|
2544
|
-
vec4 base = texelFetch(u_base, pixel, 0);
|
|
2545
|
-
vec2 uv = (vec2(pixel) + 0.5) / vec2(textureSize(u_base, 0));
|
|
2546
|
-
vec3 bloom = texture(u_bloom, uv).rgb;
|
|
2547
|
-
outColor = vec4(base.rgb + bloom * u_weight, base.a);
|
|
2548
|
-
}
|
|
2549
|
-
`, "webgl2-bloom-accumulate");
|
|
2550
|
-
return this.bloomAccumulateProgram;
|
|
2551
|
-
}
|
|
2552
|
-
ensureOutlineProgram() {
|
|
2553
|
-
if (this.outlineProgram)
|
|
2554
|
-
return this.outlineProgram;
|
|
2555
|
-
this.outlineProgram = this.createFullscreenProgram(`#version 300 es
|
|
2556
|
-
precision highp float;
|
|
2557
|
-
precision highp int;
|
|
2558
|
-
uniform sampler2D u_source;
|
|
2559
|
-
uniform sampler2D u_blendLut;
|
|
2560
|
-
uniform ivec2 u_size;
|
|
2561
|
-
uniform int u_width;
|
|
2562
|
-
uniform float u_boundHigh;
|
|
2563
|
-
uniform float u_boundLow;
|
|
2564
|
-
out vec4 outColor;
|
|
2565
|
-
|
|
2566
|
-
uvec4 sourceByte(ivec2 coordinate) {
|
|
2567
|
-
ivec2 bounded = clamp(coordinate, ivec2(0), u_size - ivec2(1));
|
|
2568
|
-
return uvec4(texelFetch(u_source, bounded, 0) * 255.0 + 0.5);
|
|
2569
|
-
}
|
|
2570
|
-
|
|
2571
|
-
uint lumaNumerator(ivec2 coordinate) {
|
|
2572
|
-
uvec3 source = sourceByte(coordinate).rgb;
|
|
2573
|
-
return 2126u * source.r + 7152u * source.g + 722u * source.b;
|
|
2574
|
-
}
|
|
2575
|
-
|
|
2576
|
-
uvec2 squareWords(int signedValue) {
|
|
2577
|
-
uint value = uint(abs(signedValue));
|
|
2578
|
-
uint high = value >> 12u;
|
|
2579
|
-
uint low = value & 4095u;
|
|
2580
|
-
uint middle = 2u * high * low;
|
|
2581
|
-
uint lowWord = low * low + (middle & 4095u) * 4096u;
|
|
2582
|
-
uint highWord = high * high + (middle >> 12u);
|
|
2583
|
-
highWord += lowWord / ${OUTLINE_LIMB_RADIX}u;
|
|
2584
|
-
lowWord %= ${OUTLINE_LIMB_RADIX}u;
|
|
2585
|
-
return uvec2(highWord, lowWord);
|
|
2586
|
-
}
|
|
2587
|
-
|
|
2588
|
-
bool edgeAt(ivec2 pixel) {
|
|
2589
|
-
int nw = int(lumaNumerator(pixel + ivec2(-1, -1)));
|
|
2590
|
-
int n = int(lumaNumerator(pixel + ivec2(0, -1)));
|
|
2591
|
-
int ne = int(lumaNumerator(pixel + ivec2(1, -1)));
|
|
2592
|
-
int w = int(lumaNumerator(pixel + ivec2(-1, 0)));
|
|
2593
|
-
int e = int(lumaNumerator(pixel + ivec2(1, 0)));
|
|
2594
|
-
int sw = int(lumaNumerator(pixel + ivec2(-1, 1)));
|
|
2595
|
-
int s = int(lumaNumerator(pixel + ivec2(0, 1)));
|
|
2596
|
-
int se = int(lumaNumerator(pixel + ivec2(1, 1)));
|
|
2597
|
-
int gx = -nw - 2 * w - sw + ne + 2 * e + se;
|
|
2598
|
-
int gy = -nw - 2 * n - ne + sw + 2 * s + se;
|
|
2599
|
-
uvec2 x = squareWords(gx);
|
|
2600
|
-
uvec2 y = squareWords(gy);
|
|
2601
|
-
uint low = x.y + y.y;
|
|
2602
|
-
uint high = x.x + y.x;
|
|
2603
|
-
if (low >= ${OUTLINE_LIMB_RADIX}u) {
|
|
2604
|
-
low -= ${OUTLINE_LIMB_RADIX}u;
|
|
2605
|
-
high += 1u;
|
|
2606
|
-
}
|
|
2607
|
-
uint boundHigh = uint(u_boundHigh);
|
|
2608
|
-
uint boundLow = uint(u_boundLow);
|
|
2609
|
-
return high != boundHigh ? high > boundHigh : low >= boundLow;
|
|
2610
|
-
}
|
|
2611
|
-
|
|
2612
|
-
void main() {
|
|
2613
|
-
ivec2 pixel = ivec2(gl_FragCoord.xy);
|
|
2614
|
-
bool outlined = false;
|
|
2615
|
-
for (int offsetY = -6; offsetY <= 6 && !outlined; offsetY += 1) {
|
|
2616
|
-
for (int offsetX = -6; offsetX <= 6; offsetX += 1) {
|
|
2617
|
-
if (abs(offsetX) > u_width || abs(offsetY) > u_width) continue;
|
|
2618
|
-
if (offsetX * offsetX + offsetY * offsetY > u_width * u_width) continue;
|
|
2619
|
-
ivec2 candidate = clamp(pixel + ivec2(offsetX, offsetY), ivec2(0), u_size - ivec2(1));
|
|
2620
|
-
if (edgeAt(candidate)) {
|
|
2621
|
-
outlined = true;
|
|
2622
|
-
break;
|
|
2623
|
-
}
|
|
2624
|
-
}
|
|
2625
|
-
}
|
|
2626
|
-
uvec4 source = sourceByte(pixel);
|
|
2627
|
-
if (!outlined) {
|
|
2628
|
-
outColor = vec4(source) / 255.0;
|
|
2629
|
-
return;
|
|
2630
|
-
}
|
|
2631
|
-
outColor = vec4(
|
|
2632
|
-
texelFetch(u_blendLut, ivec2(int(source.r), 0), 0).r,
|
|
2633
|
-
texelFetch(u_blendLut, ivec2(int(source.g), 0), 0).g,
|
|
2634
|
-
texelFetch(u_blendLut, ivec2(int(source.b), 0), 0).b,
|
|
2635
|
-
float(source.a) / 255.0
|
|
2636
|
-
);
|
|
2637
|
-
}
|
|
2638
|
-
`, "webgl2-outline");
|
|
2639
|
-
return this.outlineProgram;
|
|
2640
|
-
}
|
|
2641
|
-
ensureSsaoProgram() {
|
|
2642
|
-
if (this.ssaoProgram)
|
|
2643
|
-
return this.ssaoProgram;
|
|
2644
|
-
this.ssaoProgram = this.createFullscreenProgram(`#version 300 es
|
|
2645
|
-
precision highp float;
|
|
2646
|
-
precision highp int;
|
|
2647
|
-
uniform sampler2D u_source;
|
|
2648
|
-
uniform sampler2D u_depth;
|
|
2649
|
-
uniform ivec2 u_size;
|
|
2650
|
-
uniform int u_radius;
|
|
2651
|
-
uniform float u_intensity;
|
|
2652
|
-
uniform float u_bias;
|
|
2653
|
-
out vec4 outColor;
|
|
2654
|
-
|
|
2655
|
-
float depthAt(ivec2 coordinate) {
|
|
2656
|
-
return texelFetch(u_depth, clamp(coordinate, ivec2(0), u_size - ivec2(1)), 0).r;
|
|
2657
|
-
}
|
|
2658
|
-
|
|
2659
|
-
void main() {
|
|
2660
|
-
ivec2 pixel = ivec2(gl_FragCoord.xy);
|
|
2661
|
-
float centerDepth = depthAt(pixel);
|
|
2662
|
-
float occlusion = 0.0;
|
|
2663
|
-
float samples = 0.0;
|
|
2664
|
-
for (int stepY = -1; stepY <= 1; stepY += 1) {
|
|
2665
|
-
for (int stepX = -1; stepX <= 1; stepX += 1) {
|
|
2666
|
-
if (stepX == 0 && stepY == 0) continue;
|
|
2667
|
-
float sampleDepth = depthAt(pixel + ivec2(stepX * u_radius, stepY * u_radius));
|
|
2668
|
-
occlusion += clamp(
|
|
2669
|
-
(centerDepth - sampleDepth - u_bias) / (0.14 + float(u_radius) * 0.04),
|
|
2670
|
-
0.0,
|
|
2671
|
-
1.0
|
|
2672
|
-
);
|
|
2673
|
-
samples += 1.0;
|
|
2674
|
-
}
|
|
2675
|
-
}
|
|
2676
|
-
float factor = max(0.18, 1.0 - (occlusion / max(1.0, samples)) * u_intensity * 0.72);
|
|
2677
|
-
vec4 source = texelFetch(u_source, pixel, 0);
|
|
2678
|
-
outColor = vec4(source.rgb * factor, source.a);
|
|
2679
|
-
}
|
|
2680
|
-
`, "webgl2-ssao");
|
|
2681
|
-
return this.ssaoProgram;
|
|
2682
|
-
}
|
|
2683
|
-
ensureSsrProgram() {
|
|
2684
|
-
if (this.ssrProgram)
|
|
2685
|
-
return this.ssrProgram;
|
|
2686
|
-
this.ssrProgram = this.createFullscreenProgram(`#version 300 es
|
|
2687
|
-
precision highp float;
|
|
2688
|
-
precision highp int;
|
|
2689
|
-
uniform sampler2D u_source;
|
|
2690
|
-
uniform sampler2D u_depth;
|
|
2691
|
-
uniform sampler2D u_normalMask;
|
|
2692
|
-
uniform ivec2 u_size;
|
|
2693
|
-
uniform float u_intensity;
|
|
2694
|
-
uniform float u_maxDistance;
|
|
2695
|
-
uniform int u_maxSteps;
|
|
2696
|
-
uniform float u_thickness;
|
|
2697
|
-
uniform int u_hasNormalMask;
|
|
2698
|
-
uniform mat4 u_projection;
|
|
2699
|
-
uniform mat4 u_inverseProjection;
|
|
2700
|
-
out vec4 outColor;
|
|
2701
|
-
vec3 positionAtDepth(vec2 uv, float depth) {
|
|
2702
|
-
vec4 p = u_inverseProjection * vec4(uv * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);
|
|
2703
|
-
return p.xyz / p.w;
|
|
2704
|
-
}
|
|
2705
|
-
vec3 positionAt(vec2 uv) {
|
|
2706
|
-
return positionAtDepth(uv, texture(u_depth, uv).r);
|
|
2707
|
-
}
|
|
2708
|
-
vec3 viewDirection(vec2 uv) {
|
|
2709
|
-
return normalize(positionAtDepth(uv, 0.999) - positionAtDepth(uv, 0.0));
|
|
2710
|
-
}
|
|
2711
|
-
vec2 projectPosition(vec3 p) {
|
|
2712
|
-
vec4 clip = u_projection * vec4(p, 1.0);
|
|
2713
|
-
return clip.xy / clip.w * 0.5 + 0.5;
|
|
2714
|
-
}
|
|
2715
|
-
float depthDifference(vec3 p, vec2 uv) {
|
|
2716
|
-
return dot(p - positionAt(uv), viewDirection(uv));
|
|
2717
|
-
}
|
|
2718
|
-
void main() {
|
|
2719
|
-
vec2 uv = gl_FragCoord.xy / vec2(u_size);
|
|
2720
|
-
vec4 base = texture(u_source, uv);
|
|
2721
|
-
outColor = base;
|
|
2722
|
-
vec3 origin = positionAt(uv);
|
|
2723
|
-
vec4 normalMask = texture(u_normalMask, uv);
|
|
2724
|
-
vec3 normal = u_hasNormalMask == 1 ? normalize(normalMask.xyz * 2.0 - 1.0) : normalize(cross(dFdx(origin), dFdy(origin)));
|
|
2725
|
-
float roughness = u_hasNormalMask == 1 ? normalMask.a : 0.25;
|
|
2726
|
-
if (texture(u_depth, uv).r >= 0.999999 || (u_hasNormalMask == 1 && normalMask.a == 0.0) || roughness >= 1.0) return;
|
|
2727
|
-
vec3 ray = normalize(reflect(viewDirection(uv), normal));
|
|
2728
|
-
float stepSize = u_maxDistance / float(u_maxSteps);
|
|
2729
|
-
vec3 start = origin + normal * u_thickness;
|
|
2730
|
-
float previous = 0.0;
|
|
2731
|
-
for (int i = 1; i <= 64; ++i) {
|
|
2732
|
-
if (i > u_maxSteps) break;
|
|
2733
|
-
float distanceAlong = float(i) * stepSize;
|
|
2734
|
-
vec3 candidate = start + ray * distanceAlong;
|
|
2735
|
-
vec4 candidateClip = u_projection * vec4(candidate, 1.0);
|
|
2736
|
-
if (candidateClip.w <= 0.0 || abs(candidateClip.z) >= candidateClip.w) break;
|
|
2737
|
-
vec2 hitUV = projectPosition(candidate);
|
|
2738
|
-
if (any(lessThanEqual(hitUV, vec2(0.0))) || any(greaterThanEqual(hitUV, vec2(1.0)))) break;
|
|
2739
|
-
float difference = depthDifference(candidate, hitUV);
|
|
2740
|
-
if (difference >= 0.0 && previous < 0.0) {
|
|
2741
|
-
float lo = distanceAlong - stepSize, hi = distanceAlong;
|
|
2742
|
-
for (int j = 0; j < 5; ++j) {
|
|
2743
|
-
float mid = (lo + hi) * 0.5;
|
|
2744
|
-
vec3 point = start + ray * mid;
|
|
2745
|
-
if (depthDifference(point, projectPosition(point)) >= 0.0) hi = mid; else lo = mid;
|
|
2746
|
-
}
|
|
2747
|
-
candidate = start + ray * hi;
|
|
2748
|
-
hitUV = projectPosition(candidate);
|
|
2749
|
-
difference = depthDifference(candidate, hitUV);
|
|
2750
|
-
if (difference > u_thickness || texture(u_depth, hitUV).r >= 0.999999) break;
|
|
2751
|
-
float edge = smoothstep(0.0, 0.08, min(min(hitUV.x, hitUV.y), min(1.0 - hitUV.x, 1.0 - hitUV.y)));
|
|
2752
|
-
float response = clamp(u_intensity * edge * (1.0 - roughness) * (1.0 - hi / u_maxDistance), 0.0, 1.0);
|
|
2753
|
-
outColor = vec4(mix(base.rgb, texture(u_source, hitUV).rgb, response), base.a);
|
|
2754
|
-
break;
|
|
2755
|
-
}
|
|
2756
|
-
previous = difference;
|
|
2757
|
-
}
|
|
2758
|
-
}
|
|
2759
|
-
`, "webgl2-ssr");
|
|
2760
|
-
return this.ssrProgram;
|
|
2761
|
-
}
|
|
2762
|
-
ensureDepthOfFieldProgram() {
|
|
2763
|
-
if (this.depthOfFieldProgram)
|
|
2764
|
-
return this.depthOfFieldProgram;
|
|
2765
|
-
this.depthOfFieldProgram = this.createFullscreenProgram(`#version 300 es
|
|
2766
|
-
precision highp float;
|
|
2767
|
-
precision highp int;
|
|
2768
|
-
uniform sampler2D u_source;
|
|
2769
|
-
uniform sampler2D u_depth;
|
|
2770
|
-
uniform ivec2 u_size;
|
|
2771
|
-
uniform float u_focusDepth;
|
|
2772
|
-
uniform float u_focusRange;
|
|
2773
|
-
uniform int u_maxRadius;
|
|
2774
|
-
uniform float u_depthNear;
|
|
2775
|
-
uniform float u_depthFar;
|
|
2776
|
-
out vec4 outColor;
|
|
2777
|
-
|
|
2778
|
-
// Same linearization contract as the SSR program, except focus is authored
|
|
2779
|
-
// directly as a linear-distance fraction (0 = near plane, 1 = far plane):
|
|
2780
|
-
// buffer-unit focus values are unusable once depth is linearized, because the
|
|
2781
|
-
// projection curve parks the whole play area inside a sliver of buffer units.
|
|
2782
|
-
// The CPU byte kernel keeps buffer-unit semantics; the divergence is
|
|
2783
|
-
// documented at normalizeLdrDepthRange.
|
|
2784
|
-
float a3dDofLinearDepth(float depth) {
|
|
2785
|
-
float viewZ = u_depthNear * u_depthFar / max(u_depthFar - depth * (u_depthFar - u_depthNear), 0.0001);
|
|
2786
|
-
return clamp((viewZ - u_depthNear) / max(u_depthFar - u_depthNear, 0.0001), 0.0, 1.0);
|
|
2787
|
-
}
|
|
2788
|
-
|
|
2789
|
-
void main() {
|
|
2790
|
-
ivec2 pixel = ivec2(gl_FragCoord.xy);
|
|
2791
|
-
vec4 source = texelFetch(u_source, pixel, 0);
|
|
2792
|
-
float linearDepth = a3dDofLinearDepth(texelFetch(u_depth, pixel, 0).r);
|
|
2793
|
-
float normalizedBlur = max(0.0, abs(linearDepth - u_focusDepth) - u_focusRange)
|
|
2794
|
-
/ max(u_focusRange, 0.001) * float(u_maxRadius);
|
|
2795
|
-
int radius = min(u_maxRadius, int(round(normalizedBlur)));
|
|
2796
|
-
if (radius == 0) {
|
|
2797
|
-
outColor = source;
|
|
2798
|
-
return;
|
|
2799
|
-
}
|
|
2800
|
-
vec3 sum = vec3(0.0);
|
|
2801
|
-
float samples = 0.0;
|
|
2802
|
-
for (int offsetY = -8; offsetY <= 8; offsetY += 1) {
|
|
2803
|
-
for (int offsetX = -8; offsetX <= 8; offsetX += 1) {
|
|
2804
|
-
if (abs(offsetX) > radius || abs(offsetY) > radius) continue;
|
|
2805
|
-
if (offsetX * offsetX + offsetY * offsetY > radius * radius) continue;
|
|
2806
|
-
ivec2 samplePixel = clamp(pixel + ivec2(offsetX, offsetY), ivec2(0), u_size - ivec2(1));
|
|
2807
|
-
sum += texelFetch(u_source, samplePixel, 0).rgb;
|
|
2808
|
-
samples += 1.0;
|
|
2809
|
-
}
|
|
2810
|
-
}
|
|
2811
|
-
outColor = vec4(sum / max(1.0, samples), source.a);
|
|
2812
|
-
}
|
|
2813
|
-
`, "webgl2-depth-of-field");
|
|
2814
|
-
return this.depthOfFieldProgram;
|
|
2815
|
-
}
|
|
2816
|
-
ensureMotionBlurProgram() {
|
|
2817
|
-
if (this.motionBlurProgram)
|
|
2818
|
-
return this.motionBlurProgram;
|
|
2819
|
-
this.motionBlurProgram = this.createFullscreenProgram(`#version 300 es
|
|
2820
|
-
precision highp float;
|
|
2821
|
-
precision highp int;
|
|
2822
|
-
uniform sampler2D u_source;
|
|
2823
|
-
uniform sampler2D u_velocity;
|
|
2824
|
-
uniform bool u_velocityUv;
|
|
2825
|
-
uniform ivec2 u_size;
|
|
2826
|
-
uniform int u_samples;
|
|
2827
|
-
uniform float u_scale;
|
|
2828
|
-
out vec4 outColor;
|
|
2829
|
-
|
|
2830
|
-
void main() {
|
|
2831
|
-
ivec2 pixel = ivec2(gl_FragCoord.xy);
|
|
2832
|
-
vec4 source = texelFetch(u_source, pixel, 0);
|
|
2833
|
-
vec2 velocity = texelFetch(u_velocity, pixel, 0).rg * u_scale;
|
|
2834
|
-
if (u_velocityUv) velocity *= vec2(u_size);
|
|
2835
|
-
velocity = clamp(velocity, vec2(-64.0), vec2(64.0));
|
|
2836
|
-
if (length(velocity) < 0.01) {
|
|
2837
|
-
outColor = source;
|
|
2838
|
-
return;
|
|
2839
|
-
}
|
|
2840
|
-
vec3 sum = vec3(0.0);
|
|
2841
|
-
for (int sampleIndex = 0; sampleIndex < 16; sampleIndex += 1) {
|
|
2842
|
-
if (sampleIndex >= u_samples) continue;
|
|
2843
|
-
float t = float(sampleIndex) / float(u_samples - 1) - 0.5;
|
|
2844
|
-
ivec2 samplePixel = ivec2(floor(vec2(pixel) - velocity * t + vec2(0.5)));
|
|
2845
|
-
samplePixel = clamp(samplePixel, ivec2(0), u_size - ivec2(1));
|
|
2846
|
-
sum += texelFetch(u_source, samplePixel, 0).rgb;
|
|
2847
|
-
}
|
|
2848
|
-
outColor = vec4(sum / float(u_samples), source.a);
|
|
2849
|
-
}
|
|
2850
|
-
`, "webgl2-motion-blur");
|
|
2851
|
-
return this.motionBlurProgram;
|
|
2852
|
-
}
|
|
2853
|
-
ensureTaaProgram() {
|
|
2854
|
-
if (this.taaProgram)
|
|
2855
|
-
return this.taaProgram;
|
|
2856
|
-
this.taaProgram = this.createFullscreenProgram(`#version 300 es
|
|
2857
|
-
precision highp float;
|
|
2858
|
-
uniform sampler2D u_source;
|
|
2859
|
-
uniform sampler2D u_history;
|
|
2860
|
-
uniform sampler2D u_velocity;
|
|
2861
|
-
uniform float u_blend;
|
|
2862
|
-
uniform bool u_temporal;
|
|
2863
|
-
out vec4 outColor;
|
|
2864
|
-
vec4 cubicWeights(float f) {
|
|
2865
|
-
float f2=f*f, f3=f2*f;
|
|
2866
|
-
return vec4(-0.5*f+f2-0.5*f3,1.0-2.5*f2+1.5*f3,0.5*f+2.0*f2-1.5*f3,-0.5*f2+0.5*f3);
|
|
2867
|
-
}
|
|
2868
|
-
vec4 historyAt(vec2 uv) {
|
|
2869
|
-
ivec2 size=textureSize(u_history,0);
|
|
2870
|
-
vec2 position=uv*vec2(size)-0.5;
|
|
2871
|
-
ivec2 base=ivec2(floor(position));
|
|
2872
|
-
vec4 wx=cubicWeights(fract(position.x)), wy=cubicWeights(fract(position.y));
|
|
2873
|
-
vec4 result=vec4(0.0);
|
|
2874
|
-
// Repeated bilinear history reconstruction diffuses a moving edge every
|
|
2875
|
-
// frame. Cubic reconstruction preserves it; the resolve's current-neighbor
|
|
2876
|
-
// clipping below bounds ringing before accumulation.
|
|
2877
|
-
for(int y=0;y<4;y++) for(int x=0;x<4;x++) {
|
|
2878
|
-
result+=texelFetch(u_history,clamp(base+ivec2(x-1,y-1),ivec2(0),size-1),0)*wx[x]*wy[y];
|
|
2879
|
-
}
|
|
2880
|
-
return result;
|
|
2881
|
-
}
|
|
2882
|
-
|
|
2883
|
-
void main() {
|
|
2884
|
-
ivec2 pixel = ivec2(gl_FragCoord.xy);
|
|
2885
|
-
ivec2 size = textureSize(u_source, 0);
|
|
2886
|
-
vec2 outputUV=(vec2(pixel)+0.5)/vec2(size);
|
|
2887
|
-
// Raster jitter supplies quadrature samples inside the output pixel.
|
|
2888
|
-
// Keep that sample on its pixel's accumulation grid; undoing the jitter
|
|
2889
|
-
// spatially filters it and defeats temporal coverage integration.
|
|
2890
|
-
vec2 sourceUV=outputUV;
|
|
2891
|
-
ivec2 sourcePixel=clamp(ivec2(floor(sourceUV*vec2(size))),ivec2(0),size-1);
|
|
2892
|
-
// Reconstruct current color on the stable output grid before accumulation.
|
|
2893
|
-
vec4 source = texelFetch(u_source, pixel, 0);
|
|
2894
|
-
vec4 motion = u_temporal ? texelFetch(u_velocity, sourcePixel, 0) : vec4(0.0);
|
|
2895
|
-
// A currently uncovered sample may still carry integrated foreground
|
|
2896
|
-
// coverage in history. Track nearby foreground motion for that coverage,
|
|
2897
|
-
// but retain this pixel's own current/previous depth tags: copying RGBA
|
|
2898
|
-
// wholesale falsely labels background color as a foreground surface.
|
|
2899
|
-
if (u_temporal) {
|
|
2900
|
-
float nearestDepth=motion.b;
|
|
2901
|
-
for(int y=-1;y<=1;y++) for(int x=-1;x<=1;x++) {
|
|
2902
|
-
vec4 candidate=texelFetch(u_velocity,clamp(pixel+ivec2(x,y),ivec2(0),size-1),0);
|
|
2903
|
-
if(candidate.b<nearestDepth) {nearestDepth=candidate.b;motion.xy=candidate.xy;}
|
|
2904
|
-
}
|
|
2905
|
-
}
|
|
2906
|
-
vec2 previousUV = outputUV-motion.xy;
|
|
2907
|
-
vec4 history = u_temporal ? historyAt(previousUV) : texture(u_history, previousUV);
|
|
2908
|
-
float weight = u_blend;
|
|
2909
|
-
if (u_temporal) {
|
|
2910
|
-
// Reprojected history incurs reconstruction error as the footprint moves
|
|
2911
|
-
// across the pixel grid. Reduce its confidence with displacement instead
|
|
2912
|
-
// of repeatedly giving a softened moving edge the stationary .9 weight.
|
|
2913
|
-
// Physical motion itself remains fully represented in previousUV.
|
|
2914
|
-
weight /= 1.0 + length(motion.xy * vec2(size));
|
|
2915
|
-
// Depth is categorical at a silhouette: bilinear alpha interpolation creates
|
|
2916
|
-
// nonexistent surfaces and rejects valid history on every jittered edge.
|
|
2917
|
-
// Test surface presence in the central history footprint. RGB remains
|
|
2918
|
-
// an integrated coverage value reconstructed from the wider cubic kernel.
|
|
2919
|
-
ivec2 previousBase=ivec2(floor(previousUV*vec2(size)-vec2(0.5)));
|
|
2920
|
-
float depthError=1.0;
|
|
2921
|
-
for(int y=0;y<2;y++) for(int x=0;x<2;x++) {
|
|
2922
|
-
float previousDepth=texelFetch(u_history,clamp(previousBase+ivec2(x,y),ivec2(0),size-1),0).a;
|
|
2923
|
-
depthError=min(depthError,abs(previousDepth-motion.a));
|
|
2924
|
-
}
|
|
2925
|
-
if (any(lessThan(previousUV,vec2(0.0))) || any(greaterThanEqual(previousUV,vec2(1.0))) || depthError>0.002) weight=0.0;
|
|
2926
|
-
vec3 lo=source.rgb, hi=source.rgb;
|
|
2927
|
-
for(int y=-1;y<=1;y++) for(int x=-1;x<=1;x++) { vec3 tap=texelFetch(u_source,clamp(pixel+ivec2(x,y),ivec2(0),size-1),0).rgb; lo=min(lo,tap); hi=max(hi,tap); }
|
|
2928
|
-
history.rgb=clamp(history.rgb,lo,hi);
|
|
2929
|
-
}
|
|
2930
|
-
vec3 resolved=mix(source.rgb,history.rgb,weight);
|
|
2931
|
-
outColor=vec4(resolved,u_temporal?motion.b:source.a);
|
|
2932
|
-
}
|
|
2933
|
-
`, "webgl2-taa-accumulation");
|
|
2934
|
-
return this.taaProgram;
|
|
2935
|
-
}
|
|
2936
|
-
ensureTaaPresentationProgram() {
|
|
2937
|
-
if (this.taaPresentationProgram)
|
|
2938
|
-
return this.taaPresentationProgram;
|
|
2939
|
-
this.taaPresentationProgram = this.createFullscreenProgram(`#version 300 es
|
|
2940
|
-
precision highp float;
|
|
2941
|
-
uniform sampler2D u_source;
|
|
2942
|
-
uniform sampler2D u_accumulated;
|
|
2943
|
-
out vec4 outColor;
|
|
2944
|
-
void main() {
|
|
2945
|
-
ivec2 pixel=ivec2(gl_FragCoord.xy);
|
|
2946
|
-
ivec2 size=textureSize(u_source,0);
|
|
2947
|
-
vec4 source=texelFetch(u_source,pixel,0);
|
|
2948
|
-
vec3 accumulated=texelFetch(u_accumulated,pixel,0).rgb;
|
|
2949
|
-
// Retained native pixels isolate the remaining spatial excess to the
|
|
2950
|
-
// horizontally moving silhouette. Apply a bounded three-tap unsharp resolve
|
|
2951
|
-
// to presentation only; accumulated history remains immutable.
|
|
2952
|
-
vec3 center=mix(source.rgb,accumulated,0.90);
|
|
2953
|
-
ivec2 leftPixel=clamp(pixel+ivec2(-1,0),ivec2(0),size-1);
|
|
2954
|
-
ivec2 rightPixel=clamp(pixel+ivec2(1,0),ivec2(0),size-1);
|
|
2955
|
-
vec3 left=mix(texelFetch(u_source,leftPixel,0).rgb,texelFetch(u_accumulated,leftPixel,0).rgb,0.90);
|
|
2956
|
-
vec3 right=mix(texelFetch(u_source,rightPixel,0).rgb,texelFetch(u_accumulated,rightPixel,0).rgb,0.90);
|
|
2957
|
-
outColor=vec4(clamp(center*1.04-(left+right)*0.02,0.0,1.0),source.a);
|
|
2958
|
-
}
|
|
2959
|
-
`, "webgl2-taa-presentation");
|
|
2960
|
-
return this.taaPresentationProgram;
|
|
2961
|
-
}
|
|
2962
|
-
createFullscreenProgram(fragmentSource, label) {
|
|
2963
|
-
const vertex = this.compileShader(this.gl.VERTEX_SHADER, `#version 300 es
|
|
2964
|
-
precision highp float;
|
|
2965
|
-
void main() {
|
|
2966
|
-
vec2 position = vec2(float((gl_VertexID << 1) & 2), float(gl_VertexID & 2));
|
|
2967
|
-
gl_Position = vec4(position * 2.0 - 1.0, 0.0, 1.0);
|
|
2968
|
-
}
|
|
2969
|
-
`, label);
|
|
2970
|
-
const fragment = this.compileShader(this.gl.FRAGMENT_SHADER, fragmentSource, label);
|
|
2971
|
-
const program = this.gl.createProgram();
|
|
2972
|
-
if (!program) {
|
|
2973
|
-
this.gl.deleteShader(vertex);
|
|
2974
|
-
this.gl.deleteShader(fragment);
|
|
2975
|
-
throw new RenderDeviceError("Failed to allocate WebGL2 fullscreen shader program", "WEBGL_ALLOCATION_FAILED", { label });
|
|
2976
|
-
}
|
|
2977
|
-
this.gl.attachShader(program, vertex);
|
|
2978
|
-
this.gl.attachShader(program, fragment);
|
|
2979
|
-
this.gl.linkProgram(program);
|
|
2980
|
-
this.gl.deleteShader(vertex);
|
|
2981
|
-
this.gl.deleteShader(fragment);
|
|
2982
|
-
if (!this.gl.getProgramParameter(program, this.gl.LINK_STATUS)) {
|
|
2983
|
-
const log = this.gl.getProgramInfoLog(program) ?? "Unknown fullscreen shader link error";
|
|
2984
|
-
this.gl.deleteProgram(program);
|
|
2985
|
-
throw new RenderDeviceError("WebGL2 fullscreen shader link failed", "SHADER_LINK_FAILED", { label, log });
|
|
2986
|
-
}
|
|
2987
|
-
return program;
|
|
2988
|
-
}
|
|
2989
|
-
ensureLdrPostprocessProgram() {
|
|
2990
|
-
if (this.ldrPostprocessProgram) {
|
|
2991
|
-
return this.ldrPostprocessProgram;
|
|
2992
|
-
}
|
|
2993
|
-
const vertex = this.compileShader(this.gl.VERTEX_SHADER, `#version 300 es
|
|
2994
|
-
precision highp float;
|
|
2995
|
-
out vec2 v_uv;
|
|
2996
|
-
void main() {
|
|
2997
|
-
vec2 position = vec2(float((gl_VertexID << 1) & 2), float(gl_VertexID & 2));
|
|
2998
|
-
v_uv = position;
|
|
2999
|
-
gl_Position = vec4(position * 2.0 - 1.0, 0.0, 1.0);
|
|
3000
|
-
}
|
|
3001
|
-
`, "webgl2-ldr-postprocess");
|
|
3002
|
-
const fragment = this.compileShader(this.gl.FRAGMENT_SHADER, `#version 300 es
|
|
3003
|
-
precision highp float;
|
|
3004
|
-
uniform sampler2D u_source;
|
|
3005
|
-
uniform vec2 u_texelSize;
|
|
3006
|
-
uniform int u_hasToneMapping;
|
|
3007
|
-
uniform int u_toneOperator;
|
|
3008
|
-
uniform int u_inputColorSpace;
|
|
3009
|
-
uniform int u_outputColorSpace;
|
|
3010
|
-
uniform float u_exposure;
|
|
3011
|
-
uniform float u_whitePoint;
|
|
3012
|
-
uniform float u_gamma;
|
|
3013
|
-
uniform int u_hasColorGrade;
|
|
3014
|
-
uniform float u_contrast;
|
|
3015
|
-
uniform float u_temperature;
|
|
3016
|
-
uniform float u_tint;
|
|
3017
|
-
uniform float u_saturation;
|
|
3018
|
-
uniform float u_vibrance;
|
|
3019
|
-
uniform float u_vignette;
|
|
3020
|
-
uniform float u_sharpening;
|
|
3021
|
-
uniform int u_hasFxaa;
|
|
3022
|
-
uniform float u_edgeThreshold;
|
|
3023
|
-
uniform float u_subpixelBlend;
|
|
3024
|
-
in vec2 v_uv;
|
|
3025
|
-
out vec4 outColor;
|
|
3026
|
-
|
|
3027
|
-
float srgbToLinear(float value) {
|
|
3028
|
-
return value <= 0.04045 ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);
|
|
3029
|
-
}
|
|
3030
|
-
|
|
3031
|
-
float linearToSrgb(float value) {
|
|
3032
|
-
return value <= 0.0031308 ? value * 12.92 : 1.055 * pow(value, 1.0 / 2.4) - 0.055;
|
|
3033
|
-
}
|
|
3034
|
-
|
|
3035
|
-
vec3 decodeColor(vec3 color) {
|
|
3036
|
-
return u_inputColorSpace == 1 ? vec3(srgbToLinear(color.r), srgbToLinear(color.g), srgbToLinear(color.b)) : color;
|
|
3037
|
-
}
|
|
3038
|
-
|
|
3039
|
-
vec3 encodeColor(vec3 color) {
|
|
3040
|
-
vec3 linear = clamp(color, 0.0, 1.0);
|
|
3041
|
-
return u_outputColorSpace == 1 ? vec3(linearToSrgb(linear.r), linearToSrgb(linear.g), linearToSrgb(linear.b)) : linear;
|
|
3042
|
-
}
|
|
3043
|
-
|
|
3044
|
-
vec3 acesRrtAndOdtFit(vec3 value) {
|
|
3045
|
-
vec3 numerator = value * (value + 0.0245786) - 0.000090537;
|
|
3046
|
-
vec3 denominator = value * (0.983729 * value + 0.4329510) + 0.238081;
|
|
3047
|
-
return numerator / denominator;
|
|
3048
|
-
}
|
|
3049
|
-
|
|
3050
|
-
vec3 acesFilmic(vec3 color) {
|
|
3051
|
-
// Match current Three.js ACESFilmicToneMapping. ACES is a coupled RGB
|
|
3052
|
-
// transform; a scalar approximation shifts hue and washes saturated colors.
|
|
3053
|
-
const mat3 acesInput = mat3(
|
|
3054
|
-
vec3(0.59719, 0.07600, 0.02840),
|
|
3055
|
-
vec3(0.35458, 0.90834, 0.13383),
|
|
3056
|
-
vec3(0.04823, 0.01566, 0.83777)
|
|
3057
|
-
);
|
|
3058
|
-
const mat3 acesOutput = mat3(
|
|
3059
|
-
vec3(1.60475, -0.10208, -0.00327),
|
|
3060
|
-
vec3(-0.53108, 1.10813, -0.07276),
|
|
3061
|
-
vec3(-0.07367, -0.00605, 1.07602)
|
|
3062
|
-
);
|
|
3063
|
-
vec3 acesColor = acesInput * (color / 0.6);
|
|
3064
|
-
acesColor = acesRrtAndOdtFit(acesColor);
|
|
3065
|
-
return clamp(acesOutput * acesColor, 0.0, 1.0);
|
|
3066
|
-
}
|
|
3067
|
-
|
|
3068
|
-
float filmic(float value) {
|
|
3069
|
-
float x = max(0.0, value);
|
|
3070
|
-
float toe = max(0.0, x - 0.004);
|
|
3071
|
-
float curve = (toe * (6.2 * toe + 0.5)) / (toe * (6.2 * toe + 1.7) + 0.06);
|
|
3072
|
-
return min(curve, x * 1.08);
|
|
3073
|
-
}
|
|
3074
|
-
|
|
3075
|
-
float uncharted2(float value) {
|
|
3076
|
-
float a = 0.15;
|
|
3077
|
-
float b = 0.5;
|
|
3078
|
-
float c = 0.1;
|
|
3079
|
-
float d = 0.2;
|
|
3080
|
-
float e = 0.02;
|
|
3081
|
-
float f = 0.3;
|
|
3082
|
-
float w = 11.2;
|
|
3083
|
-
float x = value * 2.0;
|
|
3084
|
-
float curve = ((x * (a * x + c * b) + d * e) / (x * (a * x + b) + d * f)) - e / f;
|
|
3085
|
-
float wx = w;
|
|
3086
|
-
float white = ((wx * (a * wx + c * b) + d * e) / (wx * (a * wx + b) + d * f)) - e / f;
|
|
3087
|
-
return clamp(curve / white, 0.0, 1.0);
|
|
3088
|
-
}
|
|
3089
|
-
|
|
3090
|
-
float agx(float value) {
|
|
3091
|
-
float x = max(0.0, value);
|
|
3092
|
-
float encoded = log2(1.0 + x) / log2(17.0);
|
|
3093
|
-
return clamp(encoded * encoded * (3.0 - 2.0 * encoded), 0.0, 1.0);
|
|
3094
|
-
}
|
|
3095
|
-
|
|
3096
|
-
float neutral(float value) {
|
|
3097
|
-
float x = max(0.0, value);
|
|
3098
|
-
return min(1.0, (x * (1.0 + x / 7.5)) / (1.0 + x));
|
|
3099
|
-
}
|
|
3100
|
-
|
|
3101
|
-
float toneMapChannel(float value) {
|
|
3102
|
-
float exposed = max(0.0, value * u_exposure) / max(0.0001, u_whitePoint);
|
|
3103
|
-
if (u_toneOperator == 0) return min(1.0, exposed);
|
|
3104
|
-
if (u_toneOperator == 1) return exposed / (1.0 + exposed);
|
|
3105
|
-
if (u_toneOperator == 2) return exposed;
|
|
3106
|
-
if (u_toneOperator == 3) return filmic(exposed);
|
|
3107
|
-
if (u_toneOperator == 4) return uncharted2(exposed);
|
|
3108
|
-
if (u_toneOperator == 5) return agx(exposed);
|
|
3109
|
-
return neutral(exposed);
|
|
3110
|
-
}
|
|
3111
|
-
|
|
3112
|
-
vec3 applyToneMapping(vec3 color) {
|
|
3113
|
-
if (u_hasToneMapping == 0) return color;
|
|
3114
|
-
vec3 decoded = decodeColor(color);
|
|
3115
|
-
vec3 mapped = u_toneOperator == 2
|
|
3116
|
-
? acesFilmic(max(vec3(0.0), decoded * u_exposure) / max(0.0001, u_whitePoint))
|
|
3117
|
-
: vec3(toneMapChannel(decoded.r), toneMapChannel(decoded.g), toneMapChannel(decoded.b));
|
|
3118
|
-
return encodeColor(mapped);
|
|
3119
|
-
}
|
|
3120
|
-
|
|
3121
|
-
vec3 applyColorGrade(vec3 color, vec2 uv) {
|
|
3122
|
-
if (u_hasColorGrade == 0) return color;
|
|
3123
|
-
float contrastOffset = 0.5 - 0.5 * u_contrast;
|
|
3124
|
-
float redShift = u_temperature * 0.08 - u_tint * 0.02;
|
|
3125
|
-
float greenShift = u_tint * 0.06;
|
|
3126
|
-
float blueShift = -u_temperature * 0.08 - u_tint * 0.02;
|
|
3127
|
-
float luma = dot(color, vec3(0.2126, 0.7152, 0.0722));
|
|
3128
|
-
vec3 graded = color * u_contrast + vec3(contrastOffset + redShift, contrastOffset + greenShift, contrastOffset + blueShift);
|
|
3129
|
-
float distanceFromLuma = min(1.0, abs(graded.r - luma) + abs(graded.g - luma) + abs(graded.b - luma));
|
|
3130
|
-
float vibranceBoost = u_vibrance == 0.0 ? 0.0 : u_vibrance * (1.0 - distanceFromLuma);
|
|
3131
|
-
float saturation = u_saturation + vibranceBoost;
|
|
3132
|
-
graded = vec3(luma) + (graded - vec3(luma)) * saturation;
|
|
3133
|
-
vec2 centered = uv * 2.0 - 1.0;
|
|
3134
|
-
float vignette = 1.0 - u_vignette * clamp((length(centered) - 0.28) / 1.12, 0.0, 1.0);
|
|
3135
|
-
return clamp(graded * vignette, 0.0, 1.0);
|
|
3136
|
-
}
|
|
3137
|
-
|
|
3138
|
-
vec3 baseColorAt(vec2 uv) {
|
|
3139
|
-
vec2 clampedUv = clamp(uv, vec2(0.0), vec2(1.0));
|
|
3140
|
-
vec3 color = texture(u_source, clampedUv).rgb;
|
|
3141
|
-
return applyColorGrade(applyToneMapping(color), clampedUv);
|
|
3142
|
-
}
|
|
3143
|
-
|
|
3144
|
-
vec3 finalColorAt(vec2 uv) {
|
|
3145
|
-
vec3 center = baseColorAt(uv);
|
|
3146
|
-
if (u_hasColorGrade == 0 || u_sharpening <= 0.0) return center;
|
|
3147
|
-
vec3 blur = (
|
|
3148
|
-
baseColorAt(uv + vec2(-u_texelSize.x, 0.0)) +
|
|
3149
|
-
baseColorAt(uv + vec2(u_texelSize.x, 0.0)) +
|
|
3150
|
-
baseColorAt(uv + vec2(0.0, -u_texelSize.y)) +
|
|
3151
|
-
baseColorAt(uv + vec2(0.0, u_texelSize.y))
|
|
3152
|
-
) * 0.25;
|
|
3153
|
-
return clamp(center + (center - blur) * u_sharpening, 0.0, 1.0);
|
|
3154
|
-
}
|
|
3155
|
-
|
|
3156
|
-
float luma(vec3 color) {
|
|
3157
|
-
return dot(color, vec3(0.2126, 0.7152, 0.0722));
|
|
3158
|
-
}
|
|
3159
|
-
|
|
3160
|
-
void main() {
|
|
3161
|
-
vec3 center = finalColorAt(v_uv);
|
|
3162
|
-
float alpha = texture(u_source, clamp(v_uv, vec2(0.0), vec2(1.0))).a;
|
|
3163
|
-
if (u_hasFxaa == 0) {
|
|
3164
|
-
outColor = vec4(center, alpha);
|
|
3165
|
-
return;
|
|
3166
|
-
}
|
|
3167
|
-
vec3 north = finalColorAt(v_uv + vec2(0.0, -u_texelSize.y));
|
|
3168
|
-
vec3 south = finalColorAt(v_uv + vec2(0.0, u_texelSize.y));
|
|
3169
|
-
vec3 west = finalColorAt(v_uv + vec2(-u_texelSize.x, 0.0));
|
|
3170
|
-
vec3 east = finalColorAt(v_uv + vec2(u_texelSize.x, 0.0));
|
|
3171
|
-
float centerLuma = luma(center);
|
|
3172
|
-
float minLuma = min(centerLuma, min(min(luma(north), luma(south)), min(luma(west), luma(east))));
|
|
3173
|
-
float maxLuma = max(centerLuma, max(max(luma(north), luma(south)), max(luma(west), luma(east))));
|
|
3174
|
-
if (maxLuma - minLuma < u_edgeThreshold) {
|
|
3175
|
-
outColor = vec4(center, alpha);
|
|
3176
|
-
return;
|
|
3177
|
-
}
|
|
3178
|
-
vec3 average = (north + south + west + east) * 0.25;
|
|
3179
|
-
outColor = vec4(mix(center, average, clamp(u_subpixelBlend, 0.0, 1.0)), alpha);
|
|
3180
|
-
}
|
|
3181
|
-
`, "webgl2-ldr-postprocess");
|
|
3182
|
-
const program = this.gl.createProgram();
|
|
3183
|
-
if (!program) {
|
|
3184
|
-
this.gl.deleteShader(vertex);
|
|
3185
|
-
this.gl.deleteShader(fragment);
|
|
3186
|
-
throw new RenderDeviceError("Failed to allocate WebGL2 LDR postprocess shader", "WEBGL_ALLOCATION_FAILED");
|
|
3187
|
-
}
|
|
3188
|
-
this.gl.attachShader(program, vertex);
|
|
3189
|
-
this.gl.attachShader(program, fragment);
|
|
3190
|
-
this.gl.linkProgram(program);
|
|
3191
|
-
this.gl.deleteShader(vertex);
|
|
3192
|
-
this.gl.deleteShader(fragment);
|
|
3193
|
-
if (!this.gl.getProgramParameter(program, this.gl.LINK_STATUS)) {
|
|
3194
|
-
const log = this.gl.getProgramInfoLog(program) ?? "Unknown LDR postprocess shader link error";
|
|
3195
|
-
this.gl.deleteProgram(program);
|
|
3196
|
-
throw new RenderDeviceError("WebGL2 LDR postprocess shader link failed", "SHADER_LINK_FAILED", { log });
|
|
3197
|
-
}
|
|
3198
|
-
this.ldrPostprocessProgram = program;
|
|
3199
|
-
return program;
|
|
3200
|
-
}
|
|
3201
|
-
compileShader(type, source, label) {
|
|
3202
|
-
const shader = this.gl.createShader(type);
|
|
3203
|
-
if (!shader) {
|
|
3204
|
-
throw new RenderDeviceError("Failed to allocate WebGL shader", "WEBGL_ALLOCATION_FAILED", { label });
|
|
3205
|
-
}
|
|
3206
|
-
this.gl.shaderSource(shader, source);
|
|
3207
|
-
this.gl.compileShader(shader);
|
|
3208
|
-
if (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {
|
|
3209
|
-
const log = this.gl.getShaderInfoLog(shader) ?? "Unknown shader compile error";
|
|
3210
|
-
this.gl.deleteShader(shader);
|
|
3211
|
-
throw new RenderDeviceError("WebGL shader compile failed", "SHADER_COMPILE_FAILED", { label, log });
|
|
3212
|
-
}
|
|
3213
|
-
return shader;
|
|
3214
|
-
}
|
|
3215
|
-
reflectProgram(program) {
|
|
3216
|
-
const attributes = new Map();
|
|
3217
|
-
const uniforms = new Set();
|
|
3218
|
-
const attributeDetails = new Map();
|
|
3219
|
-
const uniformDetails = new Map();
|
|
3220
|
-
const activeAttributes = this.gl.getProgramParameter(program, this.gl.ACTIVE_ATTRIBUTES);
|
|
3221
|
-
const activeUniforms = this.gl.getProgramParameter(program, this.gl.ACTIVE_UNIFORMS);
|
|
3222
|
-
for (let i = 0; i < activeAttributes; i += 1) {
|
|
3223
|
-
const info = this.gl.getActiveAttrib(program, i);
|
|
3224
|
-
if (info) {
|
|
3225
|
-
const location = this.gl.getAttribLocation(program, info.name);
|
|
3226
|
-
attributes.set(info.name, location);
|
|
3227
|
-
attributeDetails.set(info.name, { name: info.name, type: String(info.type), location, source: "vertex", line: 0 });
|
|
3228
|
-
}
|
|
3229
|
-
}
|
|
3230
|
-
for (let i = 0; i < activeUniforms; i += 1) {
|
|
3231
|
-
const info = this.gl.getActiveUniform(program, i);
|
|
3232
|
-
if (info) {
|
|
3233
|
-
const name = info.name.replace(/\[0\]$/, "");
|
|
3234
|
-
uniforms.add(name);
|
|
3235
|
-
uniformDetails.set(name, { name, type: String(info.type), arraySize: info.size > 1 ? info.size : null, source: "fragment", line: 0 });
|
|
3236
|
-
}
|
|
3237
|
-
}
|
|
3238
|
-
return { attributes, uniforms, attributeDetails, uniformDetails };
|
|
3239
|
-
}
|
|
3240
|
-
uploadUniforms(shader, uniforms) {
|
|
3241
|
-
let textureUnit = 0;
|
|
3242
|
-
for (const [name, value] of uniforms) {
|
|
3243
|
-
if (!shader.reflection.uniforms.has(name)) {
|
|
3244
|
-
continue;
|
|
3245
|
-
}
|
|
3246
|
-
const location = this.getUniformLocation(shader, name);
|
|
3247
|
-
if (location === null) {
|
|
3248
|
-
throw new RenderDeviceError("Material tried to bind a missing shader uniform", "MISSING_UNIFORM", { name });
|
|
3249
|
-
}
|
|
3250
|
-
if (isTextureBinding(value)) {
|
|
3251
|
-
this.uploadTextureUniform(location, value, textureUnit);
|
|
3252
|
-
textureUnit += 1;
|
|
3253
|
-
}
|
|
3254
|
-
else if (typeof value === "number") {
|
|
3255
|
-
this.gl.uniform1f(location, value);
|
|
3256
|
-
}
|
|
3257
|
-
else if (Array.isArray(value) || ArrayBuffer.isView(value)) {
|
|
3258
|
-
const length = value.length;
|
|
3259
|
-
const floatData = value;
|
|
3260
|
-
if (length === 16 || (length > 16 && length % 16 === 0 && /(?:Matrix|Matrices)$/.test(name))) {
|
|
3261
|
-
this.gl.uniformMatrix4fv(location, false, floatData);
|
|
3262
|
-
}
|
|
3263
|
-
else if (length > 16 && length % 4 === 0) {
|
|
3264
|
-
this.gl.uniform4fv(location, floatData);
|
|
3265
|
-
}
|
|
3266
|
-
else if (length === 4) {
|
|
3267
|
-
this.gl.uniform4fv(location, floatData);
|
|
3268
|
-
}
|
|
3269
|
-
else if (length === 3) {
|
|
3270
|
-
this.gl.uniform3fv(location, floatData);
|
|
3271
|
-
}
|
|
3272
|
-
else if (length === 2) {
|
|
3273
|
-
this.gl.uniform2fv(location, floatData);
|
|
3274
|
-
}
|
|
3275
|
-
else {
|
|
3276
|
-
throw new RenderDeviceError("Unsupported uniform array length", "UNSUPPORTED_UNIFORM", { name, length });
|
|
3277
|
-
}
|
|
3278
|
-
}
|
|
3279
|
-
else {
|
|
3280
|
-
throw new RenderDeviceError("Unsupported uniform value", "UNSUPPORTED_UNIFORM", { name, valueType: typeof value });
|
|
3281
|
-
}
|
|
3282
|
-
if (this.errorCheckMode === "strict") {
|
|
3283
|
-
const uniformError = this.readError();
|
|
3284
|
-
if (uniformError) {
|
|
3285
|
-
throw new RenderDeviceError(`WebGL2 uniform upload failed for ${name}: ${uniformError}`, "WEBGL_DRAW_FAILED", {
|
|
3286
|
-
name,
|
|
3287
|
-
stage: "uniform",
|
|
3288
|
-
error: uniformError
|
|
3289
|
-
});
|
|
3290
|
-
}
|
|
3291
|
-
}
|
|
3292
|
-
}
|
|
3293
|
-
}
|
|
3294
|
-
getUniformLocation(shader, name) {
|
|
3295
|
-
let cache = this.uniformLocationCache.get(shader);
|
|
3296
|
-
if (!cache) {
|
|
3297
|
-
cache = new Map();
|
|
3298
|
-
this.uniformLocationCache.set(shader, cache);
|
|
3299
|
-
}
|
|
3300
|
-
if (!cache.has(name)) {
|
|
3301
|
-
this.uniformLocationLookupCount += 1;
|
|
3302
|
-
cache.set(name, this.gl.getUniformLocation(shader.handle, name) ?? this.gl.getUniformLocation(shader.handle, `${name}[0]`));
|
|
3303
|
-
}
|
|
3304
|
-
return cache.get(name) ?? null;
|
|
3305
|
-
}
|
|
3306
|
-
uploadTextureUniform(location, binding, textureUnit) {
|
|
3307
|
-
const validation = binding.validate();
|
|
3308
|
-
if (!validation.ok) {
|
|
3309
|
-
throw new RenderDeviceError("Texture binding validation failed", "INVALID_TEXTURE_BINDING", {
|
|
3310
|
-
diagnostics: validation.diagnostics,
|
|
3311
|
-
name: binding.name
|
|
3312
|
-
});
|
|
3313
|
-
}
|
|
3314
|
-
this.activateTextureUnit(textureUnit);
|
|
3315
|
-
const dimension = binding.texture?.dimension ?? (binding.name.toLowerCase().includes("cubemap") || binding.name.toLowerCase().includes("cube") ? "cube" : "2d");
|
|
3316
|
-
const target = dimension === "cube" ? this.gl.TEXTURE_CUBE_MAP : this.gl.TEXTURE_2D;
|
|
3317
|
-
const handle = binding.texture ? this.getTextureHandle(binding.texture) : dimension === "cube" ? this.getFallbackCubeTextureHandle() : this.getFallbackTextureHandle();
|
|
3318
|
-
if (binding.texture) {
|
|
3319
|
-
const lowerName = binding.name.toLowerCase();
|
|
3320
|
-
if (lowerName.includes("environment"))
|
|
3321
|
-
this.nativeEnvironmentBindings += 1;
|
|
3322
|
-
if (lowerName.includes("shadow"))
|
|
3323
|
-
this.nativeShadowMapBindings += 1;
|
|
3324
|
-
}
|
|
3325
|
-
this.bindTextureForUnit(textureUnit, target, handle);
|
|
3326
|
-
const samplerHandle = this.getSamplerHandle(binding.sampler, target);
|
|
3327
|
-
this.stateCache.bindSampler(textureUnit, samplerHandle, () => this.gl.bindSampler(textureUnit, samplerHandle));
|
|
3328
|
-
this.gl.uniform1i(location, textureUnit);
|
|
3329
|
-
}
|
|
3330
|
-
activateTextureUnit(textureUnit) {
|
|
3331
|
-
if (this.activeTextureUnitIndex === textureUnit)
|
|
3332
|
-
return;
|
|
3333
|
-
this.stateCache.activeTexture(textureUnit, () => this.gl.activeTexture(this.gl.TEXTURE0 + textureUnit));
|
|
3334
|
-
this.activeTextureUnitIndex = textureUnit;
|
|
3335
|
-
}
|
|
3336
|
-
bindTextureForUnit(textureUnit, target, handle) {
|
|
3337
|
-
const key = `${textureUnit}:${target}`;
|
|
3338
|
-
if (this.textureUnitBindings.get(key) === handle)
|
|
3339
|
-
return;
|
|
3340
|
-
this.stateCache.bindTexture(target, handle, () => this.gl.bindTexture(target, handle));
|
|
3341
|
-
this.textureUnitBindings.set(key, handle);
|
|
3342
|
-
this.textureBindCount += 1;
|
|
3343
|
-
}
|
|
3344
|
-
setTextureParameterIfNeeded(handle, target, parameter, value) {
|
|
3345
|
-
let parameters = this.textureSamplerParameterCache.get(handle);
|
|
3346
|
-
if (!parameters) {
|
|
3347
|
-
parameters = new Map();
|
|
3348
|
-
this.textureSamplerParameterCache.set(handle, parameters);
|
|
3349
|
-
}
|
|
3350
|
-
if (parameters.get(parameter) === value)
|
|
3351
|
-
return;
|
|
3352
|
-
this.gl.texParameteri(target, parameter, value);
|
|
3353
|
-
parameters.set(parameter, value);
|
|
3354
|
-
this.samplerParameterUploadCount += 1;
|
|
3355
|
-
}
|
|
3356
|
-
applySamplerAnisotropy(maxAnisotropy, target = this.gl.TEXTURE_2D) {
|
|
3357
|
-
if (maxAnisotropy <= 1)
|
|
3358
|
-
return;
|
|
3359
|
-
if (!this.anisotropicFilteringExtension)
|
|
3360
|
-
return;
|
|
3361
|
-
this.gl.texParameterf(target, this.anisotropicFilteringExtension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min(Math.max(1, maxAnisotropy), this.maxTextureAnisotropy));
|
|
3362
|
-
this.samplerAnisotropyUploadCount += 1;
|
|
3363
|
-
}
|
|
3364
|
-
getSamplerHandle(sampler, target) {
|
|
3365
|
-
const key = this.samplerKey(sampler, target);
|
|
3366
|
-
const cached = this.samplerObjectCache.get(key);
|
|
3367
|
-
if (cached)
|
|
3368
|
-
return cached;
|
|
3369
|
-
const handle = this.gl.createSampler();
|
|
3370
|
-
if (!handle) {
|
|
3371
|
-
throw new RenderDeviceError("Failed to allocate WebGL sampler", "WEBGL_ALLOCATION_FAILED");
|
|
3372
|
-
}
|
|
3373
|
-
this.gl.samplerParameteri(handle, this.gl.TEXTURE_MIN_FILTER, this.minFilter(sampler.minFilter));
|
|
3374
|
-
this.gl.samplerParameteri(handle, this.gl.TEXTURE_MAG_FILTER, this.magFilter(sampler.magFilter));
|
|
3375
|
-
this.gl.samplerParameteri(handle, this.gl.TEXTURE_WRAP_S, this.addressMode(sampler.addressU));
|
|
3376
|
-
this.gl.samplerParameteri(handle, this.gl.TEXTURE_WRAP_T, this.addressMode(sampler.addressV));
|
|
3377
|
-
this.samplerParameterUploadCount += 4;
|
|
3378
|
-
if (target === this.gl.TEXTURE_CUBE_MAP) {
|
|
3379
|
-
this.gl.samplerParameteri(handle, this.gl.TEXTURE_WRAP_R, this.addressMode(sampler.addressV));
|
|
3380
|
-
this.samplerParameterUploadCount += 1;
|
|
3381
|
-
}
|
|
3382
|
-
if (sampler.maxAnisotropy > 1 && this.anisotropicFilteringExtension) {
|
|
3383
|
-
this.gl.samplerParameterf(handle, this.anisotropicFilteringExtension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min(Math.max(1, sampler.maxAnisotropy), this.maxTextureAnisotropy));
|
|
3384
|
-
this.samplerAnisotropyUploadCount += 1;
|
|
3385
|
-
}
|
|
3386
|
-
this.samplerObjectCache.set(key, handle);
|
|
3387
|
-
return handle;
|
|
3388
|
-
}
|
|
3389
|
-
samplerKey(sampler, target) {
|
|
3390
|
-
return [
|
|
3391
|
-
sampler.minFilter,
|
|
3392
|
-
sampler.magFilter,
|
|
3393
|
-
sampler.addressU,
|
|
3394
|
-
sampler.addressV,
|
|
3395
|
-
sampler.maxAnisotropy,
|
|
3396
|
-
target === this.gl.TEXTURE_CUBE_MAP ? "cube" : "2d"
|
|
3397
|
-
].join("|");
|
|
3398
|
-
}
|
|
3399
|
-
getFallbackTextureHandle() {
|
|
3400
|
-
if (this.fallbackTexture) {
|
|
3401
|
-
return this.fallbackTexture;
|
|
3402
|
-
}
|
|
3403
|
-
const handle = this.gl.createTexture();
|
|
3404
|
-
if (!handle) {
|
|
3405
|
-
throw new RenderDeviceError("Failed to allocate WebGL fallback texture", "WEBGL_ALLOCATION_FAILED");
|
|
3406
|
-
}
|
|
3407
|
-
this.stateCache.invalidate();
|
|
3408
|
-
this.gl.bindTexture(this.gl.TEXTURE_2D, handle);
|
|
3409
|
-
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.NEAREST);
|
|
3410
|
-
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.NEAREST);
|
|
3411
|
-
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);
|
|
3412
|
-
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);
|
|
3413
|
-
this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, 1, 1, 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, new Uint8Array([255, 255, 255, 255]));
|
|
3414
|
-
this.fallbackTexture = handle;
|
|
3415
|
-
return handle;
|
|
3416
|
-
}
|
|
3417
|
-
getFallbackCubeTextureHandle() {
|
|
3418
|
-
if (this.fallbackCubeTexture) {
|
|
3419
|
-
return this.fallbackCubeTexture;
|
|
3420
|
-
}
|
|
3421
|
-
const handle = this.gl.createTexture();
|
|
3422
|
-
if (!handle) {
|
|
3423
|
-
throw new RenderDeviceError("Failed to allocate WebGL fallback cube texture", "WEBGL_ALLOCATION_FAILED");
|
|
3424
|
-
}
|
|
3425
|
-
this.stateCache.invalidate();
|
|
3426
|
-
this.gl.bindTexture(this.gl.TEXTURE_CUBE_MAP, handle);
|
|
3427
|
-
this.gl.texParameteri(this.gl.TEXTURE_CUBE_MAP, this.gl.TEXTURE_MIN_FILTER, this.gl.NEAREST);
|
|
3428
|
-
this.gl.texParameteri(this.gl.TEXTURE_CUBE_MAP, this.gl.TEXTURE_MAG_FILTER, this.gl.NEAREST);
|
|
3429
|
-
this.gl.texParameteri(this.gl.TEXTURE_CUBE_MAP, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);
|
|
3430
|
-
this.gl.texParameteri(this.gl.TEXTURE_CUBE_MAP, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);
|
|
3431
|
-
this.gl.texParameteri(this.gl.TEXTURE_CUBE_MAP, this.gl.TEXTURE_WRAP_R, this.gl.CLAMP_TO_EDGE);
|
|
3432
|
-
const pixel = new Uint8Array([255, 255, 255, 255]);
|
|
3433
|
-
for (const face of WEBGL_CUBE_FACES) {
|
|
3434
|
-
this.gl.texImage2D(this.cubeFaceTarget(face), 0, this.gl.RGBA, 1, 1, 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, pixel);
|
|
3435
|
-
}
|
|
3436
|
-
this.fallbackCubeTexture = handle;
|
|
3437
|
-
return handle;
|
|
3438
|
-
}
|
|
3439
|
-
getTextureHandle(texture) {
|
|
3440
|
-
this.releaseDisposedTextureHandles();
|
|
3441
|
-
if (texture.disposed) {
|
|
3442
|
-
throw new RenderDeviceError("Texture is disposed", "DISPOSED_RESOURCE", { label: texture.label });
|
|
3443
|
-
}
|
|
3444
|
-
const cached = this.textures.get(texture);
|
|
3445
|
-
if (cached) {
|
|
3446
|
-
return cached;
|
|
3447
|
-
}
|
|
3448
|
-
const handle = this.gl.createTexture();
|
|
3449
|
-
if (!handle) {
|
|
3450
|
-
throw new RenderDeviceError("Failed to allocate WebGL texture", "WEBGL_ALLOCATION_FAILED", { label: texture.label });
|
|
3451
|
-
}
|
|
3452
|
-
this.stateCache.invalidate();
|
|
3453
|
-
this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, false);
|
|
3454
|
-
this.gl.pixelStorei(this.gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
|
|
3455
|
-
this.gl.pixelStorei(this.gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, this.gl.NONE);
|
|
3456
|
-
if (texture.dimension === "cube") {
|
|
3457
|
-
this.uploadCubeTexture(texture, handle);
|
|
3458
|
-
this.textureUploadModes.set(texture, "cube");
|
|
3459
|
-
this.textures.set(texture, handle);
|
|
3460
|
-
return handle;
|
|
3461
|
-
}
|
|
3462
|
-
this.gl.bindTexture(this.gl.TEXTURE_2D, handle);
|
|
3463
|
-
if (isCompressedTextureFormat(texture.format)) {
|
|
3464
|
-
const compressed = this.resolveCompressedTextureFormat(texture.format);
|
|
3465
|
-
if (compressed) {
|
|
3466
|
-
const uploadLevels = completeUploadLevels(texture.textureLevels);
|
|
3467
|
-
for (const [levelIndex, level] of uploadLevels.entries()) {
|
|
3468
|
-
this.gl.compressedTexImage2D(this.gl.TEXTURE_2D, levelIndex, compressed.internalFormat, level.width, level.height, 0, level.data);
|
|
3469
|
-
}
|
|
3470
|
-
const compressedUploadError = this.readError();
|
|
3471
|
-
if (!compressedUploadError) {
|
|
3472
|
-
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_BASE_LEVEL, 0);
|
|
3473
|
-
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAX_LEVEL, uploadLevels.length - 1);
|
|
3474
|
-
this.textureUploadModes.set(texture, "compressed");
|
|
3475
|
-
this.textures.set(texture, handle);
|
|
3476
|
-
return handle;
|
|
3477
|
-
}
|
|
3478
|
-
}
|
|
3479
|
-
const fallbackLevels = completeUploadLevels(texture.fallbackTextureLevels);
|
|
3480
|
-
if (fallbackLevels.length === 0) {
|
|
3481
|
-
this.gl.deleteTexture(handle);
|
|
3482
|
-
throw new RenderDeviceError("Compressed texture format is not supported and no RGBA8 fallback data was provided", "COMPRESSED_TEXTURE_UNSUPPORTED", {
|
|
3483
|
-
label: texture.label,
|
|
3484
|
-
format: texture.format
|
|
3485
|
-
});
|
|
3486
|
-
}
|
|
3487
|
-
this.uploadRgba8FallbackTexture(texture, fallbackLevels);
|
|
3488
|
-
this.textureUploadModes.set(texture, "fallback");
|
|
3489
|
-
this.textures.set(texture, handle);
|
|
3490
|
-
return handle;
|
|
3491
|
-
}
|
|
3492
|
-
if (texture.format === "depth24") {
|
|
3493
|
-
throw new RenderDeviceError("Depth textures cannot be uploaded to WebGL2 color samplers", "UNSUPPORTED_TEXTURE_FORMAT", {
|
|
3494
|
-
label: texture.label,
|
|
3495
|
-
format: texture.format
|
|
3496
|
-
});
|
|
3497
|
-
}
|
|
3498
|
-
if (texture.source) {
|
|
3499
|
-
this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.rgba8TextureInternalFormat(texture), this.gl.RGBA, this.gl.UNSIGNED_BYTE, texture.source);
|
|
3500
|
-
this.gl.generateMipmap(this.gl.TEXTURE_2D);
|
|
3501
|
-
}
|
|
3502
|
-
else if (texture.mipLevels.length > 0) {
|
|
3503
|
-
const uploadFormat = this.textureUploadFormat(texture);
|
|
3504
|
-
const uploadLevels = completeUploadLevels(texture.textureLevels);
|
|
3505
|
-
for (const [levelIndex, level] of uploadLevels.entries()) {
|
|
3506
|
-
this.gl.texImage2D(this.gl.TEXTURE_2D, levelIndex, uploadFormat.internalFormat, level.width, level.height, 0, uploadFormat.format, uploadFormat.type, texturePixelUploadData(level.data, texture.format));
|
|
3507
|
-
}
|
|
3508
|
-
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_BASE_LEVEL, 0);
|
|
3509
|
-
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAX_LEVEL, uploadLevels.length - 1);
|
|
3510
|
-
}
|
|
3511
|
-
else {
|
|
3512
|
-
const uploadFormat = this.textureUploadFormat(texture);
|
|
3513
|
-
this.gl.texImage2D(this.gl.TEXTURE_2D, 0, uploadFormat.internalFormat, texture.width, texture.height, 0, uploadFormat.format, uploadFormat.type, texture.data ? texturePixelUploadData(texture.data, texture.format) : null);
|
|
3514
|
-
// Float colour formats are not guaranteed mipmap-filterable in WebGL2:
|
|
3515
|
-
// RGBA32F/RGBA16F are only linear-filterable with OES_texture_float_linear, and
|
|
3516
|
-
// generateMipmap on a non-filterable format raises INVALID_OPERATION. Data
|
|
3517
|
-
// textures such as joint palettes are point-sampled with texelFetch and never
|
|
3518
|
-
// need mips, so skip generation and pin the level range instead.
|
|
3519
|
-
if (isFloatColorTextureFormat(texture.format)) {
|
|
3520
|
-
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_BASE_LEVEL, 0);
|
|
3521
|
-
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAX_LEVEL, 0);
|
|
3522
|
-
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.NEAREST);
|
|
3523
|
-
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.NEAREST);
|
|
3524
|
-
}
|
|
3525
|
-
else {
|
|
3526
|
-
this.gl.generateMipmap(this.gl.TEXTURE_2D);
|
|
3527
|
-
}
|
|
3528
|
-
}
|
|
3529
|
-
this.textureUploadModes.set(texture, texture.format);
|
|
3530
|
-
this.textures.set(texture, handle);
|
|
3531
|
-
return handle;
|
|
3532
|
-
}
|
|
3533
|
-
uploadCubeTexture(texture, handle) {
|
|
3534
|
-
this.gl.bindTexture(this.gl.TEXTURE_CUBE_MAP, handle);
|
|
3535
|
-
const uploadFormat = this.textureUploadFormat(texture);
|
|
3536
|
-
for (const face of texture.cubeFaces) {
|
|
3537
|
-
const uploadLevels = completeUploadLevels(face.mipLevels);
|
|
3538
|
-
for (const [levelIndex, level] of uploadLevels.entries()) {
|
|
3539
|
-
this.gl.texImage2D(this.cubeFaceTarget(face.face), levelIndex, uploadFormat.internalFormat, level.width, level.height, 0, uploadFormat.format, uploadFormat.type, texturePixelUploadData(level.data, texture.format));
|
|
3540
|
-
}
|
|
3541
|
-
}
|
|
3542
|
-
const firstFaceLevels = completeUploadLevels(texture.cubeFaces[0]?.mipLevels ?? []);
|
|
3543
|
-
this.gl.texParameteri(this.gl.TEXTURE_CUBE_MAP, this.gl.TEXTURE_BASE_LEVEL, 0);
|
|
3544
|
-
this.gl.texParameteri(this.gl.TEXTURE_CUBE_MAP, this.gl.TEXTURE_MAX_LEVEL, Math.max(0, firstFaceLevels.length - 1));
|
|
3545
|
-
this.gl.texParameteri(this.gl.TEXTURE_CUBE_MAP, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);
|
|
3546
|
-
this.gl.texParameteri(this.gl.TEXTURE_CUBE_MAP, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);
|
|
3547
|
-
this.gl.texParameteri(this.gl.TEXTURE_CUBE_MAP, this.gl.TEXTURE_WRAP_R, this.gl.CLAMP_TO_EDGE);
|
|
3548
|
-
}
|
|
3549
|
-
uploadRgba8FallbackTexture(texture, fallbackLevels) {
|
|
3550
|
-
const internalFormat = this.rgba8TextureInternalFormat(texture);
|
|
3551
|
-
for (const [levelIndex, level] of fallbackLevels.entries()) {
|
|
3552
|
-
this.gl.texImage2D(this.gl.TEXTURE_2D, levelIndex, internalFormat, level.width, level.height, 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, texturePixelUploadData(level.data, "rgba8"));
|
|
3553
|
-
}
|
|
3554
|
-
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_BASE_LEVEL, 0);
|
|
3555
|
-
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAX_LEVEL, fallbackLevels.length - 1);
|
|
3556
|
-
}
|
|
3557
|
-
cubeFaceTarget(face) {
|
|
3558
|
-
switch (face) {
|
|
3559
|
-
case "px": return this.gl.TEXTURE_CUBE_MAP_POSITIVE_X;
|
|
3560
|
-
case "nx": return this.gl.TEXTURE_CUBE_MAP_NEGATIVE_X;
|
|
3561
|
-
case "py": return this.gl.TEXTURE_CUBE_MAP_POSITIVE_Y;
|
|
3562
|
-
case "ny": return this.gl.TEXTURE_CUBE_MAP_NEGATIVE_Y;
|
|
3563
|
-
case "pz": return this.gl.TEXTURE_CUBE_MAP_POSITIVE_Z;
|
|
3564
|
-
case "nz": return this.gl.TEXTURE_CUBE_MAP_NEGATIVE_Z;
|
|
3565
|
-
}
|
|
3566
|
-
}
|
|
3567
|
-
rgba8TextureInternalFormat(texture) {
|
|
3568
|
-
return texture.colorSpace === "srgb" ? this.gl.SRGB8_ALPHA8 : this.gl.RGBA;
|
|
3569
|
-
}
|
|
3570
|
-
textureUploadFormat(texture) {
|
|
3571
|
-
if (texture.format === "rgba8") {
|
|
3572
|
-
return { internalFormat: this.rgba8TextureInternalFormat(texture), format: this.gl.RGBA, type: this.gl.UNSIGNED_BYTE };
|
|
3573
|
-
}
|
|
3574
|
-
if (texture.colorSpace === "srgb") {
|
|
3575
|
-
throw new RenderDeviceError("Floating-point texture uploads must use linear colorSpace", "UNSUPPORTED_TEXTURE_FORMAT", {
|
|
3576
|
-
label: texture.label,
|
|
3577
|
-
format: texture.format,
|
|
3578
|
-
colorSpace: texture.colorSpace
|
|
3579
|
-
});
|
|
3580
|
-
}
|
|
3581
|
-
if (texture.format === "rgba16f") {
|
|
3582
|
-
return { internalFormat: this.gl.RGBA16F, format: this.gl.RGBA, type: this.gl.HALF_FLOAT };
|
|
3583
|
-
}
|
|
3584
|
-
if (texture.format === "rgba32f") {
|
|
3585
|
-
return { internalFormat: this.gl.RGBA32F, format: this.gl.RGBA, type: this.gl.FLOAT };
|
|
3586
|
-
}
|
|
3587
|
-
throw new RenderDeviceError("Unsupported texture upload format", "UNSUPPORTED_TEXTURE_FORMAT", {
|
|
3588
|
-
label: texture.label,
|
|
3589
|
-
format: texture.format
|
|
3590
|
-
});
|
|
3591
|
-
}
|
|
3592
|
-
resolveRenderTargetFormat(format) {
|
|
3593
|
-
if (format === "rgba8") {
|
|
3594
|
-
return { internalFormat: this.gl.RGBA, type: this.gl.UNSIGNED_BYTE };
|
|
3595
|
-
}
|
|
3596
|
-
if (!this.gl.getExtension("EXT_color_buffer_float")) {
|
|
3597
|
-
throw new RenderDeviceError("Floating-point color render targets require EXT_color_buffer_float", "HDR_RENDER_TARGET_UNSUPPORTED", { format });
|
|
3598
|
-
}
|
|
3599
|
-
if (format === "rgba16f") {
|
|
3600
|
-
return { internalFormat: this.gl.RGBA16F, type: this.gl.HALF_FLOAT };
|
|
3601
|
-
}
|
|
3602
|
-
return { internalFormat: this.gl.RGBA32F, type: this.gl.FLOAT };
|
|
3603
|
-
}
|
|
3604
|
-
releaseDisposedTextureHandles() {
|
|
3605
|
-
for (const [texture, handle] of [...this.textures]) {
|
|
3606
|
-
if (texture.disposed) {
|
|
3607
|
-
this.gl.deleteTexture(handle);
|
|
3608
|
-
this.textures.delete(texture);
|
|
3609
|
-
this.textureUploadModes.delete(texture);
|
|
3610
|
-
this.releasedTextureHandles += 1;
|
|
3611
|
-
}
|
|
3612
|
-
}
|
|
3613
|
-
}
|
|
3614
|
-
resolveCompressedTextureFormat(format) {
|
|
3615
|
-
switch (format) {
|
|
3616
|
-
case "bc1-rgba-unorm": {
|
|
3617
|
-
const extension = this.gl.getExtension("WEBGL_compressed_texture_s3tc");
|
|
3618
|
-
return extension ? { internalFormat: extension.COMPRESSED_RGBA_S3TC_DXT1_EXT } : null;
|
|
3619
|
-
}
|
|
3620
|
-
case "bc3-rgba-unorm": {
|
|
3621
|
-
const extension = this.gl.getExtension("WEBGL_compressed_texture_s3tc");
|
|
3622
|
-
return extension ? { internalFormat: extension.COMPRESSED_RGBA_S3TC_DXT5_EXT } : null;
|
|
3623
|
-
}
|
|
3624
|
-
case "etc2-rgba8unorm":
|
|
3625
|
-
return { internalFormat: 0x9278 };
|
|
3626
|
-
case "astc-4x4-rgba-unorm": {
|
|
3627
|
-
const extension = this.gl.getExtension("WEBGL_compressed_texture_astc");
|
|
3628
|
-
return extension ? { internalFormat: extension.COMPRESSED_RGBA_ASTC_4x4_KHR } : null;
|
|
3629
|
-
}
|
|
3630
|
-
}
|
|
3631
|
-
}
|
|
3632
|
-
magFilter(filter) {
|
|
3633
|
-
return filter === "nearest" ? this.gl.NEAREST : this.gl.LINEAR;
|
|
3634
|
-
}
|
|
3635
|
-
minFilter(filter) {
|
|
3636
|
-
switch (filter) {
|
|
3637
|
-
case "nearest":
|
|
3638
|
-
return this.gl.NEAREST;
|
|
3639
|
-
case "linear":
|
|
3640
|
-
return this.gl.LINEAR;
|
|
3641
|
-
case "nearest-mipmap-nearest":
|
|
3642
|
-
return this.gl.NEAREST_MIPMAP_NEAREST;
|
|
3643
|
-
case "linear-mipmap-nearest":
|
|
3644
|
-
return this.gl.LINEAR_MIPMAP_NEAREST;
|
|
3645
|
-
case "nearest-mipmap-linear":
|
|
3646
|
-
return this.gl.NEAREST_MIPMAP_LINEAR;
|
|
3647
|
-
case "linear-mipmap-linear":
|
|
3648
|
-
return this.gl.LINEAR_MIPMAP_LINEAR;
|
|
3649
|
-
}
|
|
3650
|
-
}
|
|
3651
|
-
addressMode(mode) {
|
|
3652
|
-
if (mode === "repeat")
|
|
3653
|
-
return this.gl.REPEAT;
|
|
3654
|
-
if (mode === "mirror-repeat")
|
|
3655
|
-
return this.gl.MIRRORED_REPEAT;
|
|
3656
|
-
return this.gl.CLAMP_TO_EDGE;
|
|
3657
|
-
}
|
|
3658
|
-
bindVertexFormat(shader, format) {
|
|
3659
|
-
const boundLocations = new Set();
|
|
3660
|
-
for (const attribute of format.attributes) {
|
|
3661
|
-
const location = this.resolveAttributeLocation(shader, attribute);
|
|
3662
|
-
if (location < 0) {
|
|
3663
|
-
continue;
|
|
3664
|
-
}
|
|
3665
|
-
if (attribute.type !== "float32") {
|
|
3666
|
-
throw new RenderDeviceError("Unsupported vertex attribute type", "UNSUPPORTED_VERTEX_ATTRIBUTE", {
|
|
3667
|
-
attribute: attribute.shaderName,
|
|
3668
|
-
type: attribute.type
|
|
3669
|
-
});
|
|
3670
|
-
}
|
|
3671
|
-
boundLocations.add(location);
|
|
3672
|
-
this.gl.enableVertexAttribArray(location);
|
|
3673
|
-
this.gl.vertexAttribDivisor(location, 0);
|
|
3674
|
-
this.gl.vertexAttribPointer(location, attribute.components, this.gl.FLOAT, attribute.normalized, format.stride, attribute.offset);
|
|
3675
|
-
}
|
|
3676
|
-
return boundLocations;
|
|
3677
|
-
}
|
|
3678
|
-
bindVertexArrayForCommand(command, shader, vertexBuffer) {
|
|
3679
|
-
const indexBuffer = command.indexBuffer ? this.requireBuffer(command.indexBuffer) : undefined;
|
|
3680
|
-
const key = this.vertexArrayCacheKey(command, shader, vertexBuffer, indexBuffer);
|
|
3681
|
-
const cached = this.vertexArrayCache.get(key);
|
|
3682
|
-
if (cached) {
|
|
3683
|
-
this.stateCache.bindVertexArray(cached.handle, () => this.gl.bindVertexArray(cached.handle));
|
|
3684
|
-
return cached;
|
|
3685
|
-
}
|
|
3686
|
-
const handle = this.gl.createVertexArray();
|
|
3687
|
-
if (!handle) {
|
|
3688
|
-
throw new RenderDeviceError("Failed to allocate WebGL vertex array", "WEBGL_ALLOCATION_FAILED");
|
|
3689
|
-
}
|
|
3690
|
-
this.vertexArrayCreateCount += 1;
|
|
3691
|
-
this.stateCache.bindVertexArray(handle, () => this.gl.bindVertexArray(handle));
|
|
3692
|
-
this.stateCache.bindBuffer(this.gl.ARRAY_BUFFER, vertexBuffer.handle, () => this.gl.bindBuffer(this.gl.ARRAY_BUFFER, vertexBuffer.handle));
|
|
3693
|
-
const boundLocations = this.bindVertexFormat(shader, command.vertexFormat);
|
|
3694
|
-
if (command.instanceAttributes && command.instanceAttributes.length > 0) {
|
|
3695
|
-
this.bindInstanceAttributes(shader, command.instanceAttributes, boundLocations);
|
|
3696
|
-
}
|
|
3697
|
-
if (indexBuffer) {
|
|
3698
|
-
this.stateCache.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, indexBuffer.handle, () => this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, indexBuffer.handle));
|
|
3699
|
-
}
|
|
3700
|
-
this.disableUnboundVertexAttributes(boundLocations);
|
|
3701
|
-
this.applyDefaultAttributes(shader, boundLocations);
|
|
3702
|
-
const entry = { key, handle, boundLocations };
|
|
3703
|
-
this.vertexArrayCache.set(key, entry);
|
|
3704
|
-
return entry;
|
|
3705
|
-
}
|
|
3706
|
-
bindNoVertexArray() {
|
|
3707
|
-
this.stateCache.bindVertexArray(null, () => this.gl.bindVertexArray(null));
|
|
3708
|
-
}
|
|
3709
|
-
vertexArrayCacheKey(command, shader, vertexBuffer, indexBuffer) {
|
|
3710
|
-
const instanceKey = (command.instanceAttributes ?? []).map((attribute) => {
|
|
3711
|
-
const buffer = this.requireBuffer(attribute.buffer);
|
|
3712
|
-
return `${attribute.shaderName}:${buffer.id}:${attribute.components}:${attribute.offset}:${attribute.stride}:${attribute.normalized === true ? 1 : 0}:${attribute.divisor ?? 1}`;
|
|
3713
|
-
}).join(",");
|
|
3714
|
-
return [
|
|
3715
|
-
shader.id,
|
|
3716
|
-
vertexBuffer.id,
|
|
3717
|
-
this.vertexFormatId(command.vertexFormat),
|
|
3718
|
-
indexBuffer?.id ?? 0,
|
|
3719
|
-
instanceKey
|
|
3720
|
-
].join("|");
|
|
3721
|
-
}
|
|
3722
|
-
vertexFormatId(format) {
|
|
3723
|
-
const existing = this.vertexFormatIds.get(format);
|
|
3724
|
-
if (existing !== undefined)
|
|
3725
|
-
return existing;
|
|
3726
|
-
const next = this.nextVertexFormatId;
|
|
3727
|
-
this.nextVertexFormatId += 1;
|
|
3728
|
-
this.vertexFormatIds.set(format, next);
|
|
3729
|
-
return next;
|
|
3730
|
-
}
|
|
3731
|
-
bindInstanceAttributes(shader, attributes, boundLocations) {
|
|
3732
|
-
for (const attribute of attributes) {
|
|
3733
|
-
const location = shader.reflection.attributes.get(attribute.shaderName);
|
|
3734
|
-
if (location === undefined || location < 0) {
|
|
3735
|
-
continue;
|
|
3736
|
-
}
|
|
3737
|
-
if (![1, 2, 3, 4].includes(attribute.components)) {
|
|
3738
|
-
throw new RenderDeviceError("Instance vertex attribute components must be 1, 2, 3, or 4", "INVALID_DRAW_COMMAND", {
|
|
3739
|
-
attribute: attribute.shaderName,
|
|
3740
|
-
components: attribute.components
|
|
3741
|
-
});
|
|
3742
|
-
}
|
|
3743
|
-
if (!Number.isInteger(attribute.offset) || attribute.offset < 0 || attribute.offset % 4 !== 0) {
|
|
3744
|
-
throw new RenderDeviceError("Instance vertex attribute offset must be non-negative and 4-byte aligned", "INVALID_DRAW_COMMAND", {
|
|
3745
|
-
attribute: attribute.shaderName,
|
|
3746
|
-
offset: attribute.offset
|
|
3747
|
-
});
|
|
3748
|
-
}
|
|
3749
|
-
if (!Number.isInteger(attribute.stride) || attribute.stride <= 0 || attribute.stride % 4 !== 0) {
|
|
3750
|
-
throw new RenderDeviceError("Instance vertex attribute stride must be positive and 4-byte aligned", "INVALID_DRAW_COMMAND", {
|
|
3751
|
-
attribute: attribute.shaderName,
|
|
3752
|
-
stride: attribute.stride
|
|
3753
|
-
});
|
|
3754
|
-
}
|
|
3755
|
-
if (attribute.offset + attribute.components * 4 > attribute.stride) {
|
|
3756
|
-
throw new RenderDeviceError("Instance vertex attribute range must fit inside its stride", "INVALID_DRAW_COMMAND", {
|
|
3757
|
-
attribute: attribute.shaderName,
|
|
3758
|
-
offset: attribute.offset,
|
|
3759
|
-
components: attribute.components,
|
|
3760
|
-
stride: attribute.stride
|
|
3761
|
-
});
|
|
3762
|
-
}
|
|
3763
|
-
const buffer = this.requireBuffer(attribute.buffer);
|
|
3764
|
-
boundLocations.add(location);
|
|
3765
|
-
this.stateCache.bindBuffer(this.gl.ARRAY_BUFFER, buffer.handle, () => this.gl.bindBuffer(this.gl.ARRAY_BUFFER, buffer.handle));
|
|
3766
|
-
this.gl.enableVertexAttribArray(location);
|
|
3767
|
-
this.gl.vertexAttribPointer(location, attribute.components, this.gl.FLOAT, attribute.normalized ?? false, attribute.stride, attribute.offset);
|
|
3768
|
-
this.gl.vertexAttribDivisor(location, attribute.divisor ?? 1);
|
|
3769
|
-
}
|
|
3770
|
-
}
|
|
3771
|
-
resolveAttributeLocation(shader, attribute) {
|
|
3772
|
-
const reflected = shader.reflection.attributes.get(attribute.shaderName);
|
|
3773
|
-
if (reflected !== undefined) {
|
|
3774
|
-
return reflected;
|
|
3775
|
-
}
|
|
3776
|
-
return shader.reflection.attributes.get(attribute.semantic) ?? -1;
|
|
3777
|
-
}
|
|
3778
|
-
applyDefaultAttributes(shader, boundLocations) {
|
|
3779
|
-
const colorLocation = shader.reflection.attributes.get("a_color") ?? shader.reflection.attributes.get("color");
|
|
3780
|
-
if (colorLocation !== undefined && colorLocation >= 0 && !boundLocations.has(colorLocation)) {
|
|
3781
|
-
this.gl.disableVertexAttribArray(colorLocation);
|
|
3782
|
-
this.gl.vertexAttribDivisor(colorLocation, 0);
|
|
3783
|
-
this.gl.vertexAttrib4f(colorLocation, 1, 1, 1, 1);
|
|
3784
|
-
}
|
|
3785
|
-
const tangentLocation = shader.reflection.attributes.get("a_tangent") ?? shader.reflection.attributes.get("tangent");
|
|
3786
|
-
if (tangentLocation !== undefined && tangentLocation >= 0 && !boundLocations.has(tangentLocation)) {
|
|
3787
|
-
this.gl.disableVertexAttribArray(tangentLocation);
|
|
3788
|
-
this.gl.vertexAttribDivisor(tangentLocation, 0);
|
|
3789
|
-
this.gl.vertexAttrib4f(tangentLocation, 1, 0, 0, 1);
|
|
3790
|
-
}
|
|
3791
|
-
const uv1Location = shader.reflection.attributes.get("a_uv1") ?? shader.reflection.attributes.get("uv1");
|
|
3792
|
-
if (uv1Location !== undefined && uv1Location >= 0 && !boundLocations.has(uv1Location)) {
|
|
3793
|
-
this.gl.disableVertexAttribArray(uv1Location);
|
|
3794
|
-
this.gl.vertexAttribDivisor(uv1Location, 0);
|
|
3795
|
-
this.gl.vertexAttrib2f(uv1Location, 0, 0);
|
|
3796
|
-
}
|
|
3797
|
-
const instanceColorLocation = shader.reflection.attributes.get("a_instanceColor") ?? shader.reflection.attributes.get("instanceColor");
|
|
3798
|
-
if (instanceColorLocation !== undefined && instanceColorLocation >= 0 && !boundLocations.has(instanceColorLocation)) {
|
|
3799
|
-
this.gl.disableVertexAttribArray(instanceColorLocation);
|
|
3800
|
-
this.gl.vertexAttribDivisor(instanceColorLocation, 0);
|
|
3801
|
-
this.gl.vertexAttrib4f(instanceColorLocation, 1, 1, 1, 1);
|
|
3802
|
-
}
|
|
3803
|
-
}
|
|
3804
|
-
disableUnboundVertexAttributes(boundLocations) {
|
|
3805
|
-
for (let location = 0; location < this.maxVertexAttributes; location += 1) {
|
|
3806
|
-
if (!boundLocations.has(location)) {
|
|
3807
|
-
this.gl.disableVertexAttribArray(location);
|
|
3808
|
-
this.gl.vertexAttribDivisor(location, 0);
|
|
3809
|
-
}
|
|
3810
|
-
}
|
|
3811
|
-
}
|
|
3812
|
-
primitive(topology) {
|
|
3813
|
-
if (topology === "lines")
|
|
3814
|
-
return this.gl.LINES;
|
|
3815
|
-
if (topology === "points")
|
|
3816
|
-
return this.gl.POINTS;
|
|
3817
|
-
return this.gl.TRIANGLES;
|
|
3818
|
-
}
|
|
3819
|
-
applyRenderState(state) {
|
|
3820
|
-
const renderState = state ?? {
|
|
3821
|
-
depthTest: true,
|
|
3822
|
-
depthWrite: true,
|
|
3823
|
-
cullMode: "back",
|
|
3824
|
-
blend: false,
|
|
3825
|
-
depthCompare: "less-equal",
|
|
3826
|
-
colorWrite: [true, true, true, true],
|
|
3827
|
-
scissor: null,
|
|
3828
|
-
polygonOffset: null,
|
|
3829
|
-
stencil: null
|
|
3830
|
-
};
|
|
3831
|
-
this.stateCache.setEnabled(this.gl.DEPTH_TEST, renderState.depthTest, () => {
|
|
3832
|
-
if (renderState.depthTest)
|
|
3833
|
-
this.gl.enable(this.gl.DEPTH_TEST);
|
|
3834
|
-
else
|
|
3835
|
-
this.gl.disable(this.gl.DEPTH_TEST);
|
|
3836
|
-
});
|
|
3837
|
-
this.stateCache.depthMask(renderState.depthWrite, () => this.gl.depthMask(renderState.depthWrite));
|
|
3838
|
-
this.stateCache.depthFunc(renderState.depthCompare === "always" ? this.gl.ALWAYS : this.gl.LEQUAL, () => this.gl.depthFunc(renderState.depthCompare === "always" ? this.gl.ALWAYS : this.gl.LEQUAL));
|
|
3839
|
-
const colorWrite = renderState.colorWrite ?? [true, true, true, true];
|
|
3840
|
-
this.stateCache.colorMask(colorWrite[0], colorWrite[1], colorWrite[2], colorWrite[3], () => this.gl.colorMask(colorWrite[0], colorWrite[1], colorWrite[2], colorWrite[3]));
|
|
3841
|
-
if (renderState.scissor) {
|
|
3842
|
-
this.stateCache.setEnabled(this.gl.SCISSOR_TEST, true, () => this.gl.enable(this.gl.SCISSOR_TEST));
|
|
3843
|
-
this.stateCache.scissor(renderState.scissor.x, renderState.scissor.y, renderState.scissor.width, renderState.scissor.height, () => {
|
|
3844
|
-
this.gl.scissor(renderState.scissor.x, renderState.scissor.y, renderState.scissor.width, renderState.scissor.height);
|
|
3845
|
-
});
|
|
3846
|
-
}
|
|
3847
|
-
else {
|
|
3848
|
-
this.stateCache.setEnabled(this.gl.SCISSOR_TEST, false, () => this.gl.disable(this.gl.SCISSOR_TEST));
|
|
3849
|
-
}
|
|
3850
|
-
if (renderState.polygonOffset) {
|
|
3851
|
-
this.stateCache.setEnabled(this.gl.POLYGON_OFFSET_FILL, true, () => this.gl.enable(this.gl.POLYGON_OFFSET_FILL));
|
|
3852
|
-
this.stateCache.polygonOffset(renderState.polygonOffset.factor, renderState.polygonOffset.units, () => this.gl.polygonOffset(renderState.polygonOffset.factor, renderState.polygonOffset.units));
|
|
3853
|
-
}
|
|
3854
|
-
else {
|
|
3855
|
-
this.stateCache.setEnabled(this.gl.POLYGON_OFFSET_FILL, false, () => this.gl.disable(this.gl.POLYGON_OFFSET_FILL));
|
|
3856
|
-
}
|
|
3857
|
-
if (renderState.stencil) {
|
|
3858
|
-
const stencil = renderState.stencil;
|
|
3859
|
-
const compare = this.stencilCompare(stencil.compare ?? "always");
|
|
3860
|
-
const reference = stencil.reference ?? 0;
|
|
3861
|
-
const readMask = stencil.readMask ?? 0xff;
|
|
3862
|
-
const writeMask = stencil.writeMask ?? 0xff;
|
|
3863
|
-
const fail = this.stencilOperation(stencil.fail ?? "keep");
|
|
3864
|
-
const depthFail = this.stencilOperation(stencil.depthFail ?? "keep");
|
|
3865
|
-
const depthPass = this.stencilOperation(stencil.depthPass ?? "keep");
|
|
3866
|
-
this.stateCache.setEnabled(this.gl.STENCIL_TEST, true, () => this.gl.enable(this.gl.STENCIL_TEST));
|
|
3867
|
-
this.stateCache.stencilFunc(compare, reference, readMask, () => this.gl.stencilFunc(compare, reference, readMask));
|
|
3868
|
-
this.stateCache.stencilMask(writeMask, () => this.gl.stencilMask(writeMask));
|
|
3869
|
-
this.stateCache.stencilOp(fail, depthFail, depthPass, () => this.gl.stencilOp(fail, depthFail, depthPass));
|
|
3870
|
-
}
|
|
3871
|
-
else {
|
|
3872
|
-
this.stateCache.setEnabled(this.gl.STENCIL_TEST, false, () => this.gl.disable(this.gl.STENCIL_TEST));
|
|
3873
|
-
}
|
|
3874
|
-
if (renderState.cullMode === "none") {
|
|
3875
|
-
this.stateCache.setEnabled(this.gl.CULL_FACE, false, () => this.gl.disable(this.gl.CULL_FACE));
|
|
3876
|
-
}
|
|
3877
|
-
else {
|
|
3878
|
-
this.stateCache.setEnabled(this.gl.CULL_FACE, true, () => this.gl.enable(this.gl.CULL_FACE));
|
|
3879
|
-
this.stateCache.cullFace(renderState.cullMode === "front" ? this.gl.FRONT : this.gl.BACK, () => this.gl.cullFace(renderState.cullMode === "front" ? this.gl.FRONT : this.gl.BACK));
|
|
3880
|
-
}
|
|
3881
|
-
if (renderState.blend) {
|
|
3882
|
-
this.stateCache.setEnabled(this.gl.BLEND, true, () => this.gl.enable(this.gl.BLEND));
|
|
3883
|
-
this.stateCache.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA, () => this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA));
|
|
3884
|
-
}
|
|
3885
|
-
else {
|
|
3886
|
-
this.stateCache.setEnabled(this.gl.BLEND, false, () => this.gl.disable(this.gl.BLEND));
|
|
3887
|
-
}
|
|
3888
|
-
}
|
|
3889
|
-
requireBuffer(buffer) {
|
|
3890
|
-
if (!(buffer instanceof WebGL2Buffer) || !this.buffers.has(buffer) || buffer.disposed) {
|
|
3891
|
-
throw new RenderDeviceError("Buffer is not a live WebGL2 resource owned by this device", "INVALID_RESOURCE", {
|
|
3892
|
-
bufferId: buffer.id
|
|
3893
|
-
});
|
|
3894
|
-
}
|
|
3895
|
-
return buffer;
|
|
3896
|
-
}
|
|
3897
|
-
stencilCompare(compare) {
|
|
3898
|
-
switch (compare) {
|
|
3899
|
-
case "never": return this.gl.NEVER;
|
|
3900
|
-
case "less": return this.gl.LESS;
|
|
3901
|
-
case "less-equal": return this.gl.LEQUAL;
|
|
3902
|
-
case "greater": return this.gl.GREATER;
|
|
3903
|
-
case "greater-equal": return this.gl.GEQUAL;
|
|
3904
|
-
case "equal": return this.gl.EQUAL;
|
|
3905
|
-
case "not-equal": return this.gl.NOTEQUAL;
|
|
3906
|
-
case "always": return this.gl.ALWAYS;
|
|
3907
|
-
}
|
|
3908
|
-
}
|
|
3909
|
-
stencilOperation(operation) {
|
|
3910
|
-
switch (operation) {
|
|
3911
|
-
case "keep": return this.gl.KEEP;
|
|
3912
|
-
case "zero": return this.gl.ZERO;
|
|
3913
|
-
case "replace": return this.gl.REPLACE;
|
|
3914
|
-
case "increment": return this.gl.INCR;
|
|
3915
|
-
case "decrement": return this.gl.DECR;
|
|
3916
|
-
case "invert": return this.gl.INVERT;
|
|
3917
|
-
case "increment-wrap": return this.gl.INCR_WRAP;
|
|
3918
|
-
case "decrement-wrap": return this.gl.DECR_WRAP;
|
|
3919
|
-
}
|
|
3920
|
-
}
|
|
3921
|
-
requireShader(shader) {
|
|
3922
|
-
if (!(shader instanceof WebGL2ShaderProgram) || !this.shaders.has(shader) || shader.disposed) {
|
|
3923
|
-
throw new RenderDeviceError("Shader is not a live WebGL2 resource owned by this device", "INVALID_RESOURCE", {
|
|
3924
|
-
shaderId: shader.id
|
|
3925
|
-
});
|
|
3926
|
-
}
|
|
3927
|
-
return shader;
|
|
3928
|
-
}
|
|
3929
|
-
assertAlive() {
|
|
3930
|
-
if (this.disposed) {
|
|
3931
|
-
throw new RenderDeviceError("Render device is disposed", "DISPOSED_DEVICE");
|
|
3932
|
-
}
|
|
3933
|
-
if (this.contextLost) {
|
|
3934
|
-
throw new RenderDeviceError("Render context is lost", "CONTEXT_LOST");
|
|
3935
|
-
}
|
|
3936
|
-
}
|
|
3937
|
-
assertFrame() {
|
|
3938
|
-
this.assertAlive();
|
|
3939
|
-
if (!this.frameActive) {
|
|
3940
|
-
throw new RenderDeviceError("No active frame", "NO_ACTIVE_FRAME");
|
|
3941
|
-
}
|
|
3942
|
-
}
|
|
3943
|
-
readError() {
|
|
3944
|
-
const error = this.gl.getError();
|
|
3945
|
-
return error === this.gl.NO_ERROR ? null : `0x${error.toString(16)}`;
|
|
3946
|
-
}
|
|
3947
|
-
}
|
|
3948
|
-
function numberOption(options, key, fallback) {
|
|
3949
|
-
const value = options[key];
|
|
3950
|
-
return typeof value === "number" && Number.isFinite(value) ? value : fallback;
|
|
3951
|
-
}
|
|
3952
|
-
function normalizeNativeBloomOptions(options) {
|
|
3953
|
-
const threshold = bloomNumberOption(options, "threshold", 0.75);
|
|
3954
|
-
const intensity = bloomNumberOption(options, "intensity", 0.35);
|
|
3955
|
-
const radius = bloomNumberOption(options, "radius", 1);
|
|
3956
|
-
if (threshold < 0 || threshold > 1) {
|
|
3957
|
-
throw new RenderDeviceError("Bloom threshold must be finite and in [0, 1].", "INVALID_POSTPROCESS_OPTIONS", { threshold });
|
|
3958
|
-
}
|
|
3959
|
-
if (intensity < 0) {
|
|
3960
|
-
throw new RenderDeviceError("Bloom intensity must be finite and non-negative.", "INVALID_POSTPROCESS_OPTIONS", { intensity });
|
|
3961
|
-
}
|
|
3962
|
-
if (!Number.isInteger(radius) || radius < 0 || radius > 16) {
|
|
3963
|
-
throw new RenderDeviceError("Bloom radius must be an integer in [0, 16].", "INVALID_POSTPROCESS_OPTIONS", { radius });
|
|
3964
|
-
}
|
|
3965
|
-
const softKnee = bloomNumberOption(options, "softKnee", 0);
|
|
3966
|
-
if (!(softKnee >= 0) || softKnee > 0.5) {
|
|
3967
|
-
throw new RenderDeviceError("Bloom softKnee must be finite and in [0, 0.5].", "INVALID_POSTPROCESS_OPTIONS", { softKnee });
|
|
3968
|
-
}
|
|
3969
|
-
const shoulder = bloomNumberOption(options, "shoulder", 0);
|
|
3970
|
-
if (!(shoulder >= 0) || shoulder > 1) {
|
|
3971
|
-
throw new RenderDeviceError("Bloom shoulder must be finite and in [0, 1].", "INVALID_POSTPROCESS_OPTIONS", { shoulder });
|
|
3972
|
-
}
|
|
3973
|
-
let quality;
|
|
3974
|
-
try {
|
|
3975
|
-
quality = normalizeBloomQualityPreset(options.quality);
|
|
3976
|
-
}
|
|
3977
|
-
catch {
|
|
3978
|
-
throw new RenderDeviceError("Bloom quality must be one of performance|balanced|cinematic.", "INVALID_POSTPROCESS_OPTIONS", { quality: options.quality });
|
|
3979
|
-
}
|
|
3980
|
-
return { threshold, intensity, radius, quality, softKnee, shoulder };
|
|
3981
|
-
}
|
|
3982
|
-
function normalizeNativeOutlineOptions(options) {
|
|
3983
|
-
const width = outlineNumberOption(options, "width", 1);
|
|
3984
|
-
const threshold = outlineNumberOption(options, "threshold", 0.22);
|
|
3985
|
-
const opacity = outlineNumberOption(options, "opacity", 0.85);
|
|
3986
|
-
const value = options.color;
|
|
3987
|
-
const sourceColor = value === undefined ? [255, 188, 64, 255] : value;
|
|
3988
|
-
if (!Array.isArray(sourceColor)
|
|
3989
|
-
|| (sourceColor.length !== 3 && sourceColor.length !== 4)
|
|
3990
|
-
|| sourceColor.some((channel) => typeof channel !== "number" || !Number.isFinite(channel) || channel < 0 || channel > 255)) {
|
|
3991
|
-
throw new RenderDeviceError("Outline color must contain three or four finite channels in [0, 255].", "INVALID_POSTPROCESS_OPTIONS", { color: value });
|
|
3992
|
-
}
|
|
3993
|
-
if (!Number.isInteger(width) || width < 1 || width > 6) {
|
|
3994
|
-
throw new RenderDeviceError("Outline width must be an integer in [1, 6].", "INVALID_POSTPROCESS_OPTIONS", { width });
|
|
3995
|
-
}
|
|
3996
|
-
if (threshold < 0 || threshold > 4) {
|
|
3997
|
-
throw new RenderDeviceError("Outline threshold must be finite and in [0, 4].", "INVALID_POSTPROCESS_OPTIONS", { threshold });
|
|
3998
|
-
}
|
|
3999
|
-
if (opacity < 0 || opacity > 1) {
|
|
4000
|
-
throw new RenderDeviceError("Outline opacity must be finite and in [0, 1].", "INVALID_POSTPROCESS_OPTIONS", { opacity });
|
|
4001
|
-
}
|
|
4002
|
-
const color = [
|
|
4003
|
-
sourceColor[0],
|
|
4004
|
-
sourceColor[1],
|
|
4005
|
-
sourceColor[2],
|
|
4006
|
-
(sourceColor[3] ?? 255)
|
|
4007
|
-
];
|
|
4008
|
-
return { width, threshold, opacity, color };
|
|
4009
|
-
}
|
|
4010
|
-
function normalizeNativeSsaoOptions(options) {
|
|
4011
|
-
const radius = ssaoNumberOption(options, "radius", 2);
|
|
4012
|
-
const intensity = ssaoNumberOption(options, "intensity", 0.38);
|
|
4013
|
-
const bias = ssaoNumberOption(options, "bias", 0.015);
|
|
4014
|
-
if (!Number.isInteger(radius) || radius < 1 || radius > 8) {
|
|
4015
|
-
throw new RenderDeviceError("SSAO radius must be an integer in [1, 8].", "INVALID_POSTPROCESS_OPTIONS", { radius });
|
|
4016
|
-
}
|
|
4017
|
-
if (intensity < 0 || intensity > 2) {
|
|
4018
|
-
throw new RenderDeviceError("SSAO intensity must be finite and in [0, 2].", "INVALID_POSTPROCESS_OPTIONS", { intensity });
|
|
4019
|
-
}
|
|
4020
|
-
if (bias < 0 || bias > 0.25) {
|
|
4021
|
-
throw new RenderDeviceError("SSAO bias must be finite and in [0, 0.25].", "INVALID_POSTPROCESS_OPTIONS", { bias });
|
|
4022
|
-
}
|
|
4023
|
-
return { radius, intensity, bias };
|
|
4024
1327
|
}
|
|
4025
1328
|
/**
|
|
4026
1329
|
* Camera depth range for linearizing sampleable GL depth in the native
|
|
@@ -4031,199 +1334,12 @@ function normalizeNativeSsaoOptions(options) {
|
|
|
4031
1334
|
* keep fixture-unit depth semantics (deterministic reference); the native
|
|
4032
1335
|
* programs document their GL-depth contract in-shader.
|
|
4033
1336
|
*/
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
const
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
const maxDistance = ssrNumberOption(options, "maxDistance", 16);
|
|
4042
|
-
if (intensity < 0 || intensity > 2) {
|
|
4043
|
-
throw new RenderDeviceError("SSR intensity must be finite and in [0, 2].", "INVALID_POSTPROCESS_OPTIONS", { intensity });
|
|
4044
|
-
}
|
|
4045
|
-
if (!Number.isInteger(maxDistance) || maxDistance < 1 || maxDistance > 64) {
|
|
4046
|
-
throw new RenderDeviceError("SSR maxDistance must be an integer in [1, 64].", "INVALID_POSTPROCESS_OPTIONS", { maxDistance });
|
|
4047
|
-
}
|
|
4048
|
-
const projection = options["projection"];
|
|
4049
|
-
if (!(projection instanceof Float32Array))
|
|
4050
|
-
throw new RenderDeviceError("Native SSR requires the actual frame projection or view-projection matrix.", "INVALID_POSTPROCESS_OPTIONS");
|
|
4051
|
-
const inverseProjection = invertSsrProjection(projection);
|
|
4052
|
-
return { intensity, maxDistance, projection, inverseProjection };
|
|
4053
|
-
}
|
|
4054
|
-
function normalizeNativeDepthOfFieldOptions(options) {
|
|
4055
|
-
const focusDepth = depthOfFieldNumberOption(options, "focusDepth", 0.5);
|
|
4056
|
-
const focusRange = depthOfFieldNumberOption(options, "focusRange", 0.12);
|
|
4057
|
-
const maxRadius = depthOfFieldNumberOption(options, "maxRadius", 2);
|
|
4058
|
-
if (focusDepth < 0 || focusDepth > 1) {
|
|
4059
|
-
throw new RenderDeviceError("Depth-of-field focusDepth must be finite and in [0, 1].", "INVALID_POSTPROCESS_OPTIONS", { focusDepth });
|
|
4060
|
-
}
|
|
4061
|
-
if (focusRange < 0.001 || focusRange > 1) {
|
|
4062
|
-
throw new RenderDeviceError("Depth-of-field focusRange must be finite and in [0.001, 1].", "INVALID_POSTPROCESS_OPTIONS", { focusRange });
|
|
4063
|
-
}
|
|
4064
|
-
if (!Number.isInteger(maxRadius) || maxRadius < 0 || maxRadius > 8) {
|
|
4065
|
-
throw new RenderDeviceError("Depth-of-field maxRadius must be an integer in [0, 8].", "INVALID_POSTPROCESS_OPTIONS", { maxRadius });
|
|
4066
|
-
}
|
|
4067
|
-
return { focusDepth, focusRange, maxRadius };
|
|
4068
|
-
}
|
|
4069
|
-
function normalizeNativeMotionBlurOptions(options, width, height) {
|
|
4070
|
-
const samples = motionBlurNumberOption(options, "samples", 5);
|
|
4071
|
-
const scale = motionBlurNumberOption(options, "scale", 1);
|
|
4072
|
-
if (options.temporal) {
|
|
4073
|
-
if (!Number.isInteger(samples) || samples < 2 || samples > 16 || scale < 0 || scale > 8)
|
|
4074
|
-
throw new RenderDeviceError("Invalid motion blur samples/scale", "INVALID_POSTPROCESS_OPTIONS");
|
|
4075
|
-
return { samples, scale, temporal: options.temporal };
|
|
4076
|
-
}
|
|
4077
|
-
const value = options.velocity;
|
|
4078
|
-
if (!(value instanceof Float32Array) && !Array.isArray(value)) {
|
|
4079
|
-
throw new RenderDeviceError("Motion blur requires a velocity Float32Array or number array.", "WEBGL_LDR_POSTPROCESS_VELOCITY_REQUIRED");
|
|
4080
|
-
}
|
|
4081
|
-
const velocity = value instanceof Float32Array ? value : new Float32Array(value);
|
|
4082
|
-
if (velocity.length !== width * height * 2) {
|
|
4083
|
-
throw new RenderDeviceError("Motion blur velocity must contain width * height * 2 float samples.", "INVALID_POSTPROCESS_OPTIONS", {
|
|
4084
|
-
expectedLength: width * height * 2,
|
|
4085
|
-
actualLength: velocity.length
|
|
4086
|
-
});
|
|
4087
|
-
}
|
|
4088
|
-
if (!Number.isInteger(samples) || samples < 2 || samples > 16) {
|
|
4089
|
-
throw new RenderDeviceError("Motion blur samples must be an integer in [2, 16].", "INVALID_POSTPROCESS_OPTIONS", { samples });
|
|
4090
|
-
}
|
|
4091
|
-
if (scale < 0 || scale > 8) {
|
|
4092
|
-
throw new RenderDeviceError("Motion blur scale must be finite and in [0, 8].", "INVALID_POSTPROCESS_OPTIONS", { scale });
|
|
4093
|
-
}
|
|
4094
|
-
return { samples, scale, velocity };
|
|
4095
|
-
}
|
|
4096
|
-
function normalizeNativeTaaOptions(options, width, height) {
|
|
4097
|
-
const blend = taaNumberOption(options, "blend", 0.18);
|
|
4098
|
-
if (options.temporal) {
|
|
4099
|
-
if (blend < 0 || blend > .95)
|
|
4100
|
-
throw new RenderDeviceError("Invalid TAA blend", "INVALID_POSTPROCESS_OPTIONS");
|
|
4101
|
-
return { blend, temporal: options.temporal };
|
|
4102
|
-
}
|
|
4103
|
-
const history = options.history;
|
|
4104
|
-
if (!(history instanceof Uint8Array)) {
|
|
4105
|
-
throw new RenderDeviceError("TAA requires a Uint8Array history buffer.", "WEBGL_LDR_POSTPROCESS_HISTORY_REQUIRED");
|
|
4106
|
-
}
|
|
4107
|
-
if (history.byteLength !== width * height * 4) {
|
|
4108
|
-
throw new RenderDeviceError("TAA history must contain width * height * 4 RGBA bytes.", "INVALID_POSTPROCESS_OPTIONS", {
|
|
4109
|
-
expectedLength: width * height * 4,
|
|
4110
|
-
actualLength: history.byteLength
|
|
4111
|
-
});
|
|
4112
|
-
}
|
|
4113
|
-
if (blend < 0 || blend > 0.95) {
|
|
4114
|
-
throw new RenderDeviceError("TAA blend must be finite and in [0, 0.95].", "INVALID_POSTPROCESS_OPTIONS", { blend });
|
|
4115
|
-
}
|
|
4116
|
-
return { blend, history };
|
|
4117
|
-
}
|
|
4118
|
-
function bloomNumberOption(options, key, fallback) {
|
|
4119
|
-
const value = options[key];
|
|
4120
|
-
if (value === undefined)
|
|
4121
|
-
return fallback;
|
|
4122
|
-
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
4123
|
-
throw new RenderDeviceError(`Bloom ${key} must be a finite number.`, "INVALID_POSTPROCESS_OPTIONS", { key, value });
|
|
4124
|
-
}
|
|
4125
|
-
return value;
|
|
4126
|
-
}
|
|
4127
|
-
function outlineNumberOption(options, key, fallback) {
|
|
4128
|
-
const value = options[key];
|
|
4129
|
-
if (value === undefined)
|
|
4130
|
-
return fallback;
|
|
4131
|
-
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
4132
|
-
throw new RenderDeviceError(`Outline ${key} must be a finite number.`, "INVALID_POSTPROCESS_OPTIONS", { key, value });
|
|
4133
|
-
}
|
|
4134
|
-
return value;
|
|
4135
|
-
}
|
|
4136
|
-
function ssaoNumberOption(options, key, fallback) {
|
|
4137
|
-
const value = options[key];
|
|
4138
|
-
if (value === undefined)
|
|
4139
|
-
return fallback;
|
|
4140
|
-
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
4141
|
-
throw new RenderDeviceError(`SSAO ${key} must be a finite number.`, "INVALID_POSTPROCESS_OPTIONS", { key, value });
|
|
4142
|
-
}
|
|
4143
|
-
return value;
|
|
4144
|
-
}
|
|
4145
|
-
function ssrNumberOption(options, key, fallback) {
|
|
4146
|
-
const value = options[key];
|
|
4147
|
-
if (value === undefined)
|
|
4148
|
-
return fallback;
|
|
4149
|
-
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
4150
|
-
throw new RenderDeviceError(`SSR ${key} must be a finite number.`, "INVALID_POSTPROCESS_OPTIONS", { key, value });
|
|
4151
|
-
}
|
|
4152
|
-
return value;
|
|
4153
|
-
}
|
|
4154
|
-
function depthOfFieldNumberOption(options, key, fallback) {
|
|
4155
|
-
const value = options[key];
|
|
4156
|
-
if (value === undefined)
|
|
4157
|
-
return fallback;
|
|
4158
|
-
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
4159
|
-
throw new RenderDeviceError(`Depth-of-field ${key} must be a finite number.`, "INVALID_POSTPROCESS_OPTIONS", { key, value });
|
|
4160
|
-
}
|
|
4161
|
-
return value;
|
|
4162
|
-
}
|
|
4163
|
-
function motionBlurNumberOption(options, key, fallback) {
|
|
4164
|
-
const value = options[key];
|
|
4165
|
-
if (value === undefined)
|
|
4166
|
-
return fallback;
|
|
4167
|
-
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
4168
|
-
throw new RenderDeviceError(`Motion blur ${key} must be a finite number.`, "INVALID_POSTPROCESS_OPTIONS", { key, value });
|
|
4169
|
-
}
|
|
4170
|
-
return value;
|
|
4171
|
-
}
|
|
4172
|
-
function taaNumberOption(options, key, fallback) {
|
|
4173
|
-
const value = options[key];
|
|
4174
|
-
if (value === undefined)
|
|
4175
|
-
return fallback;
|
|
4176
|
-
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
4177
|
-
throw new RenderDeviceError(`TAA ${key} must be a finite number.`, "INVALID_POSTPROCESS_OPTIONS", { key, value });
|
|
4178
|
-
}
|
|
4179
|
-
return value;
|
|
4180
|
-
}
|
|
4181
|
-
function stringOption(options, key, fallback) {
|
|
4182
|
-
const value = options[key];
|
|
4183
|
-
return typeof value === "string" ? value : fallback;
|
|
4184
|
-
}
|
|
4185
|
-
function colorSpaceId(value) {
|
|
4186
|
-
return value === "srgb" ? 1 : 0;
|
|
4187
|
-
}
|
|
4188
|
-
function toneMappingOperatorId(value) {
|
|
4189
|
-
if (value === "linear")
|
|
4190
|
-
return 0;
|
|
4191
|
-
if (value === "reinhard")
|
|
4192
|
-
return 1;
|
|
4193
|
-
if (value === "aces")
|
|
4194
|
-
return 2;
|
|
4195
|
-
if (value === "filmic")
|
|
4196
|
-
return 3;
|
|
4197
|
-
if (value === "uncharted2")
|
|
4198
|
-
return 4;
|
|
4199
|
-
if (value === "agx")
|
|
4200
|
-
return 5;
|
|
4201
|
-
return 6;
|
|
4202
|
-
}
|
|
4203
|
-
function completeUploadLevels(levels) {
|
|
4204
|
-
const uploadLevels = [];
|
|
4205
|
-
for (const level of levels) {
|
|
4206
|
-
if (uploadLevels.length === 0) {
|
|
4207
|
-
uploadLevels.push(level);
|
|
4208
|
-
continue;
|
|
4209
|
-
}
|
|
4210
|
-
const previous = uploadLevels[uploadLevels.length - 1];
|
|
4211
|
-
const expectedWidth = Math.max(1, Math.floor(previous.width / 2));
|
|
4212
|
-
const expectedHeight = Math.max(1, Math.floor(previous.height / 2));
|
|
4213
|
-
if (level.width !== expectedWidth || level.height !== expectedHeight) {
|
|
4214
|
-
break;
|
|
4215
|
-
}
|
|
4216
|
-
uploadLevels.push(level);
|
|
4217
|
-
}
|
|
4218
|
-
return uploadLevels;
|
|
4219
|
-
}
|
|
4220
|
-
function texturePixelUploadData(data, format) {
|
|
4221
|
-
if (format === "rgba16f" && data instanceof Uint16Array)
|
|
4222
|
-
return data;
|
|
4223
|
-
if (format === "rgba32f" && data instanceof Float32Array)
|
|
4224
|
-
return data;
|
|
4225
|
-
if (format === "rgba8" && (data instanceof Uint8Array || data instanceof Uint8ClampedArray))
|
|
4226
|
-
return data;
|
|
4227
|
-
throw new RenderDeviceError("Texture pixel data type does not match texture format", "UNSUPPORTED_TEXTURE_FORMAT", { format });
|
|
1337
|
+
/** Next animation frame when available (browser), else a macrotask. */
|
|
1338
|
+
function scheduleParallelCompilePoll(poll) {
|
|
1339
|
+
const raf = globalThis.requestAnimationFrame;
|
|
1340
|
+
if (typeof raf === "function")
|
|
1341
|
+
raf(poll);
|
|
1342
|
+
else
|
|
1343
|
+
setTimeout(poll, 0);
|
|
4228
1344
|
}
|
|
4229
1345
|
//# sourceMappingURL=WebGL2Device.js.map
|