@aura3d/rendering 2.0.4 → 3.0.1
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/AtmosphereWetness.d.ts +61 -0
- package/dist/AtmosphereWetness.d.ts.map +1 -0
- package/dist/AtmosphereWetness.js +99 -0
- package/dist/AtmosphereWetness.js.map +1 -0
- package/dist/CascadedShadowMaps.d.ts.map +1 -1
- package/dist/CascadedShadowMaps.js +3 -1
- package/dist/CascadedShadowMaps.js.map +1 -1
- package/dist/ClusteredForwardLighting.d.ts +25 -1
- package/dist/ClusteredForwardLighting.d.ts.map +1 -1
- package/dist/ClusteredForwardLighting.js +80 -3
- package/dist/ClusteredForwardLighting.js.map +1 -1
- package/dist/DayNightSky.d.ts +63 -0
- package/dist/DayNightSky.d.ts.map +1 -0
- package/dist/DayNightSky.js +156 -0
- package/dist/DayNightSky.js.map +1 -0
- package/dist/EnvironmentPresetPack.d.ts +30 -0
- package/dist/EnvironmentPresetPack.d.ts.map +1 -0
- package/dist/EnvironmentPresetPack.js +49 -0
- package/dist/EnvironmentPresetPack.js.map +1 -0
- package/dist/ExtensionScalarAtlas.d.ts +18 -0
- package/dist/ExtensionScalarAtlas.d.ts.map +1 -0
- package/dist/ExtensionScalarAtlas.js +107 -0
- package/dist/ExtensionScalarAtlas.js.map +1 -0
- package/dist/ForwardPass.d.ts +65 -0
- package/dist/ForwardPass.d.ts.map +1 -1
- package/dist/ForwardPass.js +196 -2
- package/dist/ForwardPass.js.map +1 -1
- package/dist/InstancedPBRMaterial.d.ts +1 -0
- package/dist/InstancedPBRMaterial.d.ts.map +1 -1
- package/dist/InstancedPBRMaterial.js +3 -0
- package/dist/InstancedPBRMaterial.js.map +1 -1
- package/dist/InstancingDiagnostics.d.ts +69 -0
- package/dist/InstancingDiagnostics.d.ts.map +1 -0
- package/dist/InstancingDiagnostics.js +98 -0
- package/dist/InstancingDiagnostics.js.map +1 -0
- package/dist/LeanWebGL2Device.d.ts +265 -0
- package/dist/LeanWebGL2Device.d.ts.map +1 -0
- package/dist/LeanWebGL2Device.js +4001 -0
- package/dist/LeanWebGL2Device.js.map +1 -0
- package/dist/LightingRig.d.ts +19 -1
- package/dist/LightingRig.d.ts.map +1 -1
- package/dist/LightingRig.js +61 -1
- package/dist/LightingRig.js.map +1 -1
- package/dist/MaterialBinding.js +1 -1
- package/dist/MaterialBinding.js.map +1 -1
- package/dist/MeshConsolidation.d.ts +12 -0
- package/dist/MeshConsolidation.d.ts.map +1 -1
- package/dist/MeshConsolidation.js +28 -0
- package/dist/MeshConsolidation.js.map +1 -1
- package/dist/MorphTargetPlan.d.ts +29 -2
- package/dist/MorphTargetPlan.d.ts.map +1 -1
- package/dist/MorphTargetPlan.js +23 -4
- package/dist/MorphTargetPlan.js.map +1 -1
- package/dist/NormalMappedPBRMaterial.d.ts.map +1 -1
- package/dist/NormalMappedPBRMaterial.js +22 -2
- package/dist/NormalMappedPBRMaterial.js.map +1 -1
- package/dist/OceanSurface.d.ts +75 -0
- package/dist/OceanSurface.d.ts.map +1 -1
- package/dist/OceanSurface.js +211 -0
- package/dist/OceanSurface.js.map +1 -1
- package/dist/PBRMaterial.d.ts +1 -0
- package/dist/PBRMaterial.d.ts.map +1 -1
- package/dist/PBRMaterial.js +23 -2
- package/dist/PBRMaterial.js.map +1 -1
- package/dist/PbrReference.d.ts +48 -0
- package/dist/PbrReference.d.ts.map +1 -1
- package/dist/PbrReference.js +126 -0
- package/dist/PbrReference.js.map +1 -1
- package/dist/PlanarReflection.d.ts +221 -0
- package/dist/PlanarReflection.d.ts.map +1 -0
- package/dist/PlanarReflection.js +541 -0
- package/dist/PlanarReflection.js.map +1 -0
- package/dist/PostProcessPass.d.ts +32 -0
- package/dist/PostProcessPass.d.ts.map +1 -1
- package/dist/PostProcessPass.js +79 -36
- package/dist/PostProcessPass.js.map +1 -1
- package/dist/ProjectionMath.d.ts +3 -0
- package/dist/ProjectionMath.d.ts.map +1 -0
- package/dist/ProjectionMath.js +26 -0
- package/dist/ProjectionMath.js.map +1 -0
- package/dist/ReflectionSurfaces.d.ts +17 -0
- package/dist/ReflectionSurfaces.d.ts.map +1 -1
- package/dist/ReflectionSurfaces.js +103 -1
- package/dist/ReflectionSurfaces.js.map +1 -1
- package/dist/RenderDevice.d.ts +92 -0
- package/dist/RenderDevice.d.ts.map +1 -1
- package/dist/RenderDevice.js +85 -0
- package/dist/RenderDevice.js.map +1 -1
- package/dist/Renderer.d.ts +9 -0
- package/dist/Renderer.d.ts.map +1 -1
- package/dist/Renderer.js +97 -9
- package/dist/Renderer.js.map +1 -1
- package/dist/RendererPostprocessPlan.d.ts +64 -3
- package/dist/RendererPostprocessPlan.d.ts.map +1 -1
- package/dist/RendererPostprocessPlan.js +116 -12
- package/dist/RendererPostprocessPlan.js.map +1 -1
- package/dist/RendererVisualPipelineReport.d.ts.map +1 -1
- package/dist/RendererVisualPipelineReport.js +3 -1
- package/dist/RendererVisualPipelineReport.js.map +1 -1
- package/dist/Sampler.d.ts +29 -0
- package/dist/Sampler.d.ts.map +1 -1
- package/dist/Sampler.js +47 -0
- package/dist/Sampler.js.map +1 -1
- package/dist/ScreenSpaceReflectionPass.d.ts +43 -0
- package/dist/ScreenSpaceReflectionPass.d.ts.map +1 -0
- package/dist/ScreenSpaceReflectionPass.js +58 -0
- package/dist/ScreenSpaceReflectionPass.js.map +1 -0
- package/dist/SdfText.d.ts +250 -0
- package/dist/SdfText.d.ts.map +1 -0
- package/dist/SdfText.js +551 -0
- package/dist/SdfText.js.map +1 -0
- package/dist/ShaderChunks.d.ts.map +1 -1
- package/dist/ShaderChunks.js +30 -12
- package/dist/ShaderChunks.js.map +1 -1
- package/dist/ShaderLibrary.d.ts.map +1 -1
- package/dist/ShaderLibrary.js +601 -186
- package/dist/ShaderLibrary.js.map +1 -1
- package/dist/ShaderLibraryCore.d.ts +3 -0
- package/dist/ShaderLibraryCore.d.ts.map +1 -1
- package/dist/ShaderLibraryCore.js +73 -12
- package/dist/ShaderLibraryCore.js.map +1 -1
- package/dist/ShadowMap.d.ts +24 -0
- package/dist/ShadowMap.d.ts.map +1 -1
- package/dist/ShadowMap.js +43 -0
- package/dist/ShadowMap.js.map +1 -1
- package/dist/SkinnedLitMaterial.d.ts.map +1 -1
- package/dist/SkinnedLitMaterial.js +2 -0
- package/dist/SkinnedLitMaterial.js.map +1 -1
- package/dist/SkinningBounds.d.ts +10 -0
- package/dist/SkinningBounds.d.ts.map +1 -1
- package/dist/SkinningBounds.js +27 -0
- package/dist/SkinningBounds.js.map +1 -1
- package/dist/SpriteFlipbook.d.ts +60 -0
- package/dist/SpriteFlipbook.d.ts.map +1 -0
- package/dist/SpriteFlipbook.js +128 -0
- package/dist/SpriteFlipbook.js.map +1 -0
- package/dist/TemporalHistory.d.ts +37 -0
- package/dist/TemporalHistory.d.ts.map +1 -0
- package/dist/TemporalHistory.js +135 -0
- package/dist/TemporalHistory.js.map +1 -0
- package/dist/TemporalMath.d.ts +3 -0
- package/dist/TemporalMath.d.ts.map +1 -0
- package/dist/TemporalMath.js +9 -0
- package/dist/TemporalMath.js.map +1 -0
- package/dist/TerrainTiles.d.ts +120 -0
- package/dist/TerrainTiles.d.ts.map +1 -0
- package/dist/TerrainTiles.js +221 -0
- package/dist/TerrainTiles.js.map +1 -0
- package/dist/TexturedPBRMaterial.d.ts +4 -0
- package/dist/TexturedPBRMaterial.d.ts.map +1 -1
- package/dist/TexturedPBRMaterial.js +88 -5
- package/dist/TexturedPBRMaterial.js.map +1 -1
- package/dist/TexturedUnlitMaterial.d.ts.map +1 -1
- package/dist/TexturedUnlitMaterial.js +20 -2
- package/dist/TexturedUnlitMaterial.js.map +1 -1
- package/dist/UnlitMaterial.d.ts.map +1 -1
- package/dist/UnlitMaterial.js +20 -2
- package/dist/UnlitMaterial.js.map +1 -1
- package/dist/VertexFormat.d.ts +6 -0
- package/dist/VertexFormat.d.ts.map +1 -1
- package/dist/VertexFormat.js +12 -0
- package/dist/VertexFormat.js.map +1 -1
- package/dist/VolumetricFog.d.ts +55 -0
- package/dist/VolumetricFog.d.ts.map +1 -0
- package/dist/VolumetricFog.js +91 -0
- package/dist/VolumetricFog.js.map +1 -0
- package/dist/WaterSurface.d.ts +77 -0
- package/dist/WaterSurface.d.ts.map +1 -0
- package/dist/WaterSurface.js +133 -0
- package/dist/WaterSurface.js.map +1 -0
- package/dist/WebGL2Device.d.ts +73 -0
- package/dist/WebGL2Device.d.ts.map +1 -1
- package/dist/WebGL2Device.js +836 -79
- package/dist/WebGL2Device.js.map +1 -1
- package/dist/WebGPUDevice.d.ts +62 -1
- package/dist/WebGPUDevice.d.ts.map +1 -1
- package/dist/WebGPUDevice.js +844 -51
- package/dist/WebGPUDevice.js.map +1 -1
- package/dist/WebGPUExtensionAtlas.d.ts +6 -0
- package/dist/WebGPUExtensionAtlas.d.ts.map +1 -0
- package/dist/WebGPUExtensionAtlas.js +225 -0
- package/dist/WebGPUExtensionAtlas.js.map +1 -0
- package/dist/WebGPUSkinningLimits.d.ts +40 -0
- package/dist/WebGPUSkinningLimits.d.ts.map +1 -1
- package/dist/WebGPUSkinningLimits.js +32 -0
- package/dist/WebGPUSkinningLimits.js.map +1 -1
- package/dist/effects/CollisionModule.d.ts +9 -0
- package/dist/effects/CollisionModule.d.ts.map +1 -1
- package/dist/effects/CollisionModule.js +10 -0
- package/dist/effects/CollisionModule.js.map +1 -1
- package/dist/effects/ColorModule.d.ts +7 -0
- package/dist/effects/ColorModule.d.ts.map +1 -1
- package/dist/effects/ColorModule.js +23 -0
- package/dist/effects/ColorModule.js.map +1 -1
- package/dist/effects/ForceModule.d.ts +35 -0
- package/dist/effects/ForceModule.d.ts.map +1 -1
- package/dist/effects/ForceModule.js +49 -0
- package/dist/effects/ForceModule.js.map +1 -1
- package/dist/effects/GPUParticleBackend.d.ts +188 -0
- package/dist/effects/GPUParticleBackend.d.ts.map +1 -1
- package/dist/effects/GPUParticleBackend.js +710 -1
- package/dist/effects/GPUParticleBackend.js.map +1 -1
- package/dist/effects/HeightfieldModule.d.ts +58 -0
- package/dist/effects/HeightfieldModule.d.ts.map +1 -0
- package/dist/effects/HeightfieldModule.js +129 -0
- package/dist/effects/HeightfieldModule.js.map +1 -0
- package/dist/effects/LightingModule.d.ts +34 -0
- package/dist/effects/LightingModule.d.ts.map +1 -0
- package/dist/effects/LightingModule.js +54 -0
- package/dist/effects/LightingModule.js.map +1 -0
- package/dist/effects/ParticleDiagnostics.d.ts +8 -0
- package/dist/effects/ParticleDiagnostics.d.ts.map +1 -1
- package/dist/effects/ParticleDiagnostics.js +3 -0
- package/dist/effects/ParticleDiagnostics.js.map +1 -1
- package/dist/effects/ParticleModule.d.ts +8 -0
- package/dist/effects/ParticleModule.d.ts.map +1 -1
- package/dist/effects/ParticleModule.js.map +1 -1
- package/dist/effects/ParticleRenderer.d.ts +20 -0
- package/dist/effects/ParticleRenderer.d.ts.map +1 -1
- package/dist/effects/ParticleRenderer.js +57 -7
- package/dist/effects/ParticleRenderer.js.map +1 -1
- package/dist/effects/ParticleSystem.d.ts +45 -1
- package/dist/effects/ParticleSystem.d.ts.map +1 -1
- package/dist/effects/ParticleSystem.js +373 -4
- package/dist/effects/ParticleSystem.js.map +1 -1
- package/dist/effects/ResidentGPUParticleRenderer.d.ts +158 -0
- package/dist/effects/ResidentGPUParticleRenderer.d.ts.map +1 -0
- package/dist/effects/ResidentGPUParticleRenderer.js +576 -0
- package/dist/effects/ResidentGPUParticleRenderer.js.map +1 -0
- package/dist/effects/SizeModule.d.ts +4 -0
- package/dist/effects/SizeModule.d.ts.map +1 -1
- package/dist/effects/SizeModule.js +16 -0
- package/dist/effects/SizeModule.js.map +1 -1
- package/dist/effects/SubEmitterModule.d.ts +61 -0
- package/dist/effects/SubEmitterModule.d.ts.map +1 -0
- package/dist/effects/SubEmitterModule.js +119 -0
- package/dist/effects/SubEmitterModule.js.map +1 -0
- package/dist/effects/TrailModule.d.ts +38 -0
- package/dist/effects/TrailModule.d.ts.map +1 -1
- package/dist/effects/TrailModule.js +95 -2
- package/dist/effects/TrailModule.js.map +1 -1
- package/dist/effects/TurbulenceModule.d.ts +43 -0
- package/dist/effects/TurbulenceModule.d.ts.map +1 -0
- package/dist/effects/TurbulenceModule.js +130 -0
- package/dist/effects/TurbulenceModule.js.map +1 -0
- package/dist/effects/index.d.ts +4 -0
- package/dist/effects/index.d.ts.map +1 -1
- package/dist/effects/index.js +4 -0
- package/dist/effects/index.js.map +1 -1
- package/dist/extension-scalar-atlas.d.ts +3 -0
- package/dist/extension-scalar-atlas.d.ts.map +1 -0
- package/dist/extension-scalar-atlas.js +2 -0
- package/dist/extension-scalar-atlas.js.map +1 -0
- package/dist/index.d.ts +58 -19
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +32 -10
- package/dist/index.js.map +1 -1
- package/dist/lean/LeanProductionRenderer.d.ts.map +1 -1
- package/dist/lean/LeanProductionRenderer.js +2 -2
- package/dist/lean/LeanProductionRenderer.js.map +1 -1
- package/dist/lean-core-runtime.d.ts +13 -0
- package/dist/lean-core-runtime.d.ts.map +1 -0
- package/dist/lean-core-runtime.js +10 -0
- package/dist/lean-core-runtime.js.map +1 -0
- package/dist/materials/MaterialExtensions.js +3 -3
- package/dist/materials/MaterialExtensions.js.map +1 -1
- package/dist/postprocess/NativeBloomPyramid.d.ts +44 -0
- package/dist/postprocess/NativeBloomPyramid.d.ts.map +1 -0
- package/dist/postprocess/NativeBloomPyramid.js +84 -0
- package/dist/postprocess/NativeBloomPyramid.js.map +1 -0
- package/dist/postprocess/NativeLdrEffectLuts.d.ts +10 -1
- package/dist/postprocess/NativeLdrEffectLuts.d.ts.map +1 -1
- package/dist/postprocess/NativeLdrEffectLuts.js +19 -2
- package/dist/postprocess/NativeLdrEffectLuts.js.map +1 -1
- package/dist/postprocess/index.d.ts +2 -0
- package/dist/postprocess/index.d.ts.map +1 -1
- package/dist/postprocess/index.js +1 -0
- package/dist/postprocess/index.js.map +1 -1
- package/dist/production-runtime/PBRHDRPipeline.d.ts +22 -0
- package/dist/production-runtime/PBRHDRPipeline.d.ts.map +1 -1
- package/dist/production-runtime/PBRHDRPipeline.js +125 -0
- package/dist/production-runtime/PBRHDRPipeline.js.map +1 -1
- package/dist/production-runtime/ProductionRendererTypes.d.ts +1 -0
- package/dist/production-runtime/ProductionRendererTypes.d.ts.map +1 -1
- package/dist/production-runtime/ProductionRendererTypes.js.map +1 -1
- package/dist/production-runtime/ProductionRuntimeRenderer.d.ts +3 -0
- package/dist/production-runtime/ProductionRuntimeRenderer.d.ts.map +1 -1
- package/dist/production-runtime/ProductionRuntimeRenderer.js +8 -1
- package/dist/production-runtime/ProductionRuntimeRenderer.js.map +1 -1
- package/dist/production-runtime/ProductionWebGL2Renderer.d.ts +4 -0
- package/dist/production-runtime/ProductionWebGL2Renderer.d.ts.map +1 -1
- package/dist/production-runtime/ProductionWebGL2Renderer.js +15 -0
- package/dist/production-runtime/ProductionWebGL2Renderer.js.map +1 -1
- package/dist/production-runtime/ProductionWebGPURenderer.d.ts +58 -0
- package/dist/production-runtime/ProductionWebGPURenderer.d.ts.map +1 -1
- package/dist/production-runtime/ProductionWebGPURenderer.js +127 -0
- package/dist/production-runtime/ProductionWebGPURenderer.js.map +1 -1
- package/dist/production-runtime/framegraph/FrameGraph.d.ts +4 -2
- package/dist/production-runtime/framegraph/FrameGraph.d.ts.map +1 -1
- package/dist/production-runtime/framegraph/FrameGraph.js +62 -4
- package/dist/production-runtime/framegraph/FrameGraph.js.map +1 -1
- package/dist/production-runtime/framegraph/NativeFrameGraphBindings.d.ts +32 -0
- package/dist/production-runtime/framegraph/NativeFrameGraphBindings.d.ts.map +1 -0
- package/dist/production-runtime/framegraph/NativeFrameGraphBindings.js +111 -0
- package/dist/production-runtime/framegraph/NativeFrameGraphBindings.js.map +1 -0
- package/dist/production-runtime/framegraph/RenderPass.d.ts +23 -0
- package/dist/production-runtime/framegraph/RenderPass.d.ts.map +1 -1
- package/dist/production-runtime/framegraph/RenderPass.js +87 -1
- package/dist/production-runtime/framegraph/RenderPass.js.map +1 -1
- package/dist/production-runtime/index.d.ts +7 -4
- package/dist/production-runtime/index.d.ts.map +1 -1
- package/dist/production-runtime/index.js +4 -2
- package/dist/production-runtime/index.js.map +1 -1
- package/dist/production-runtime/passes/DepthPrepass.d.ts +18 -1
- package/dist/production-runtime/passes/DepthPrepass.d.ts.map +1 -1
- package/dist/production-runtime/passes/DepthPrepass.js +41 -2
- package/dist/production-runtime/passes/DepthPrepass.js.map +1 -1
- package/dist/production-runtime/passes/FramegraphTopology.d.ts +13 -0
- package/dist/production-runtime/passes/FramegraphTopology.d.ts.map +1 -0
- package/dist/production-runtime/passes/FramegraphTopology.js +59 -0
- package/dist/production-runtime/passes/FramegraphTopology.js.map +1 -0
- package/dist/production-runtime/passes/OpaquePass.d.ts +19 -1
- package/dist/production-runtime/passes/OpaquePass.d.ts.map +1 -1
- package/dist/production-runtime/passes/OpaquePass.js +43 -2
- package/dist/production-runtime/passes/OpaquePass.js.map +1 -1
- package/dist/production-runtime/passes/ShadowPass.d.ts +19 -1
- package/dist/production-runtime/passes/ShadowPass.d.ts.map +1 -1
- package/dist/production-runtime/passes/ShadowPass.js +45 -2
- package/dist/production-runtime/passes/ShadowPass.js.map +1 -1
- package/dist/production-runtime/passes/SkyboxPass.d.ts +17 -1
- package/dist/production-runtime/passes/SkyboxPass.d.ts.map +1 -1
- package/dist/production-runtime/passes/SkyboxPass.js +41 -2
- package/dist/production-runtime/passes/SkyboxPass.js.map +1 -1
- package/dist/production-runtime/passes/ToneMappingPass.d.ts +26 -1
- package/dist/production-runtime/passes/ToneMappingPass.d.ts.map +1 -1
- package/dist/production-runtime/passes/ToneMappingPass.js +62 -2
- package/dist/production-runtime/passes/ToneMappingPass.js.map +1 -1
- package/dist/production-runtime/passes/TransparentPass.d.ts +19 -1
- package/dist/production-runtime/passes/TransparentPass.d.ts.map +1 -1
- package/dist/production-runtime/passes/TransparentPass.js +47 -2
- package/dist/production-runtime/passes/TransparentPass.js.map +1 -1
- package/dist/reflection-surfaces.d.ts +5 -0
- package/dist/reflection-surfaces.d.ts.map +1 -0
- package/dist/reflection-surfaces.js +3 -0
- package/dist/reflection-surfaces.js.map +1 -0
- package/dist/shadows/CascadeHysteresis.d.ts +67 -0
- package/dist/shadows/CascadeHysteresis.d.ts.map +1 -0
- package/dist/shadows/CascadeHysteresis.js +104 -0
- package/dist/shadows/CascadeHysteresis.js.map +1 -0
- package/dist/shadows/ContactShadows.d.ts +52 -0
- package/dist/shadows/ContactShadows.d.ts.map +1 -1
- package/dist/shadows/ContactShadows.js +122 -0
- package/dist/shadows/ContactShadows.js.map +1 -1
- package/dist/shadows/SpotShadowMaps.d.ts +77 -0
- package/dist/shadows/SpotShadowMaps.d.ts.map +1 -0
- package/dist/shadows/SpotShadowMaps.js +106 -0
- package/dist/shadows/SpotShadowMaps.js.map +1 -0
- package/dist/webgpu/WebGPUPostProcess.d.ts +2 -0
- package/dist/webgpu/WebGPUPostProcess.d.ts.map +1 -1
- package/dist/webgpu/WebGPUPostProcess.js +1 -0
- package/dist/webgpu/WebGPUPostProcess.js.map +1 -1
- package/dist/webgpu/WebGPUPostShaders.d.ts +77 -0
- package/dist/webgpu/WebGPUPostShaders.d.ts.map +1 -0
- package/dist/webgpu/WebGPUPostShaders.js +261 -0
- package/dist/webgpu/WebGPUPostShaders.js.map +1 -0
- package/dist/webgpu/WebGPUTemporal.d.ts +17 -0
- package/dist/webgpu/WebGPUTemporal.d.ts.map +1 -0
- package/dist/webgpu/WebGPUTemporal.js +64 -0
- package/dist/webgpu/WebGPUTemporal.js.map +1 -0
- package/dist/webgpu.d.ts +6 -0
- package/dist/webgpu.d.ts.map +1 -1
- package/dist/webgpu.js +4 -0
- package/dist/webgpu.js.map +1 -1
- package/package.json +15 -3
package/dist/ShaderLibrary.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { SHADER_CHUNKS, validateShaderChunks } from "./ShaderChunks.js";
|
|
2
2
|
import { registerAnimationToonShader } from "./animation/AnimationToonMaterial.js";
|
|
3
|
-
import { ShaderLibrary, registerLeanUnlitShader, registerLeanPbrShader, registerLeanDepthShader, registerLeanEnvironmentBackgroundShader, DEFAULT_DEPTH_SHADER_MARKER, DEFAULT_DEPTH_SHADER_NAME, DEFAULT_ENVIRONMENT_BACKGROUND_SHADER_MARKER, DEFAULT_ENVIRONMENT_BACKGROUND_SHADER_NAME, DEFAULT_INSTANCED_PBR_SHADER_MARKER, DEFAULT_INSTANCED_PBR_SHADER_NAME, DEFAULT_INSTANCED_UNLIT_SHADER_MARKER, DEFAULT_INSTANCED_UNLIT_SHADER_NAME, DEFAULT_MORPH_UNLIT_SHADER_MARKER, DEFAULT_MORPH_UNLIT_SHADER_NAME, DEFAULT_NORMAL_MAPPED_PBR_SHADER_MARKER, DEFAULT_NORMAL_MAPPED_PBR_SHADER_NAME, DEFAULT_PBR_SHADER_MARKER, DEFAULT_PBR_SHADER_NAME, DEFAULT_SCREEN_SPACE_LINE_SHADER_MARKER, DEFAULT_SCREEN_SPACE_LINE_SHADER_NAME, DEFAULT_SKINNED_LIT_EIGHT_INFLUENCE_SHADER_MARKER, DEFAULT_SKINNED_LIT_EIGHT_INFLUENCE_SHADER_NAME, DEFAULT_SKINNED_LIT_SHADER_MARKER, DEFAULT_SKINNED_LIT_SHADER_NAME, DEFAULT_SKINNED_UNLIT_EIGHT_INFLUENCE_SHADER_MARKER, DEFAULT_SKINNED_UNLIT_EIGHT_INFLUENCE_SHADER_NAME, DEFAULT_SKINNED_UNLIT_SHADER_MARKER, DEFAULT_SKINNED_UNLIT_SHADER_NAME, DEFAULT_TEXTURED_PBR_CLEARCOAT_SPECULAR_TEXTURES_VARIANT, DEFAULT_TEXTURED_PBR_CLEARCOAT_TEXTURES_VARIANT, DEFAULT_TEXTURED_PBR_CLEARCOAT_TRANSMISSION_VOLUME_TEXTURES_VARIANT, DEFAULT_TEXTURED_PBR_IRIDESCENCE_TEXTURES_VARIANT, DEFAULT_TEXTURED_PBR_SHADER_MARKER, DEFAULT_TEXTURED_PBR_SHADER_NAME, DEFAULT_TEXTURED_PBR_SPECULAR_SHEEN_ANISOTROPY_IRIDESCENCE_TEXTURES_VARIANT, DEFAULT_TEXTURED_PBR_SPECULAR_SHEEN_ANISOTROPY_TEXTURES_VARIANT, DEFAULT_TEXTURED_PBR_TRANSMISSION_VOLUME_TEXTURES_VARIANT, DEFAULT_TEXTURED_UNLIT_SHADER_MARKER, DEFAULT_TEXTURED_UNLIT_SHADER_NAME, DEFAULT_UNLIT_SHADER_MARKER, DEFAULT_UNLIT_SHADER_NAME, } from "./ShaderLibraryCore.js";
|
|
3
|
+
import { ShaderLibrary, registerLeanUnlitShader, registerLeanPbrShader, registerLeanDepthShader, registerLeanEnvironmentBackgroundShader, DEFAULT_DEPTH_SHADER_MARKER, DEFAULT_DEPTH_SHADER_NAME, DEFAULT_ENVIRONMENT_BACKGROUND_SHADER_MARKER, DEFAULT_ENVIRONMENT_BACKGROUND_SHADER_NAME, DEFAULT_INSTANCED_PBR_SHADER_MARKER, DEFAULT_INSTANCED_PBR_SHADER_NAME, DEFAULT_INSTANCED_UNLIT_SHADER_MARKER, DEFAULT_INSTANCED_UNLIT_SHADER_NAME, DEFAULT_MORPH_UNLIT_SHADER_MARKER, DEFAULT_MORPH_UNLIT_SHADER_NAME, DEFAULT_NORMAL_MAPPED_PBR_SHADER_MARKER, DEFAULT_NORMAL_MAPPED_PBR_SHADER_NAME, DEFAULT_PBR_SHADER_MARKER, DEFAULT_PBR_SHADER_NAME, DEFAULT_SCREEN_SPACE_LINE_SHADER_MARKER, DEFAULT_SCREEN_SPACE_LINE_SHADER_NAME, DEFAULT_SKINNED_LIT_EIGHT_INFLUENCE_SHADER_MARKER, DEFAULT_SKINNED_LIT_EIGHT_INFLUENCE_SHADER_NAME, DEFAULT_SKINNED_LIT_SHADER_MARKER, DEFAULT_SKINNED_LIT_SHADER_NAME, DEFAULT_SKINNED_UNLIT_EIGHT_INFLUENCE_SHADER_MARKER, DEFAULT_SKINNED_UNLIT_EIGHT_INFLUENCE_SHADER_NAME, DEFAULT_SKINNED_UNLIT_SHADER_MARKER, DEFAULT_SKINNED_UNLIT_SHADER_NAME, DEFAULT_TEXTURED_PBR_CLEARCOAT_SHEEN_ANISOTROPY_TEXTURES_VARIANT, DEFAULT_TEXTURED_PBR_CLEARCOAT_IRIDESCENCE_TEXTURES_VARIANT, DEFAULT_TEXTURED_PBR_EXTENSION_ATLAS_VARIANT, DEFAULT_TEXTURED_PBR_CLEARCOAT_SPECULAR_TEXTURES_VARIANT, DEFAULT_TEXTURED_PBR_CLEARCOAT_TEXTURES_VARIANT, DEFAULT_TEXTURED_PBR_CLEARCOAT_TRANSMISSION_VOLUME_TEXTURES_VARIANT, DEFAULT_TEXTURED_PBR_IRIDESCENCE_TEXTURES_VARIANT, DEFAULT_TEXTURED_PBR_SHADER_MARKER, DEFAULT_TEXTURED_PBR_SHADER_NAME, DEFAULT_TEXTURED_PBR_SPECULAR_SHEEN_ANISOTROPY_IRIDESCENCE_TEXTURES_VARIANT, DEFAULT_TEXTURED_PBR_SPECULAR_SHEEN_ANISOTROPY_TEXTURES_VARIANT, DEFAULT_TEXTURED_PBR_TRANSMISSION_VOLUME_TEXTURES_VARIANT, DEFAULT_TEXTURED_UNLIT_SHADER_MARKER, DEFAULT_TEXTURED_UNLIT_SHADER_NAME, DEFAULT_UNLIT_SHADER_MARKER, DEFAULT_UNLIT_SHADER_NAME, } from "./ShaderLibraryCore.js";
|
|
4
4
|
export * from "./ShaderLibraryCore.js";
|
|
5
5
|
export function createDefaultShaderLibrary() {
|
|
6
6
|
const library = new ShaderLibrary();
|
|
@@ -94,6 +94,7 @@ uniform float u_metallic;
|
|
|
94
94
|
uniform float u_roughness;
|
|
95
95
|
uniform vec3 u_environmentColor;
|
|
96
96
|
uniform float u_environmentIntensity;
|
|
97
|
+
uniform float u_materialEnvironmentIntensity;
|
|
97
98
|
uniform vec3 u_environmentSkyColor;
|
|
98
99
|
uniform vec3 u_environmentHorizonColor;
|
|
99
100
|
uniform vec3 u_environmentGroundColor;
|
|
@@ -141,6 +142,19 @@ uniform float u_pointShadowSlopeBias;
|
|
|
141
142
|
uniform vec2 u_pointShadowTexelSize;
|
|
142
143
|
uniform float u_pointShadowPcfSampleCount;
|
|
143
144
|
uniform vec4 u_pointShadowPcfSamples[32];
|
|
145
|
+
uniform sampler2D u_spotShadowMapTexture;
|
|
146
|
+
uniform float u_spotShadowMapEnabled;
|
|
147
|
+
uniform vec3 u_spotShadowLightPosition;
|
|
148
|
+
uniform vec3 u_spotShadowLightDirection;
|
|
149
|
+
uniform mat4 u_spotShadowMatrix;
|
|
150
|
+
uniform vec2 u_spotShadowCone;
|
|
151
|
+
uniform float u_spotShadowRange;
|
|
152
|
+
uniform float u_spotShadowStrength;
|
|
153
|
+
uniform float u_spotShadowBias;
|
|
154
|
+
uniform float u_spotShadowSlopeBias;
|
|
155
|
+
uniform vec2 u_spotShadowTexelSize;
|
|
156
|
+
uniform float u_spotShadowPcfSampleCount;
|
|
157
|
+
uniform vec4 u_spotShadowPcfSamples[32];
|
|
144
158
|
uniform float u_outputColorSpace;
|
|
145
159
|
uniform vec3 u_cameraPosition;
|
|
146
160
|
uniform float u_environmentFogEnabled;
|
|
@@ -150,6 +164,9 @@ uniform float u_environmentFogNear;
|
|
|
150
164
|
uniform float u_environmentFogFar;
|
|
151
165
|
uniform float u_environmentFogDensity;
|
|
152
166
|
uniform float u_environmentFogHeightFalloff;
|
|
167
|
+
uniform float u_volumetricIntensity;
|
|
168
|
+
uniform vec3 u_volumetricLightDirection;
|
|
169
|
+
uniform vec3 u_volumetricLightColor;
|
|
153
170
|
uniform float u_environmentFogHeightReference;
|
|
154
171
|
uniform float u_environmentFogMaxOpacity;
|
|
155
172
|
in vec3 v_normal;
|
|
@@ -166,15 +183,6 @@ float a3dForwardShadowFactor(vec3 worldPosition, vec3 normal, vec3 lightDirectio
|
|
|
166
183
|
vec3 receiverNormal = normalize(normal);
|
|
167
184
|
vec3 receiverLightDirection = lightDirection / max(length(lightDirection), 0.0001);
|
|
168
185
|
float normalDotLight = clamp(abs(dot(receiverNormal, receiverLightDirection)), 0.0, 1.0);
|
|
169
|
-
// Slope-scaled depth bias must be evaluated per PCF sample, not once for the kernel
|
|
170
|
-
// centre. A sample offset N texels away on a receiver sloped relative to the light sees a
|
|
171
|
-
// depth difference proportional to N, so a centre-only bias under-compensates every outer
|
|
172
|
-
// tap and the receiver shadows itself. Scaling by each sample's own texel distance keeps
|
|
173
|
-
// wide kernels acne-free without inflating the constant bias into peter-panning.
|
|
174
|
-
// The depth gradient across one shadow texel is tan(angle between receiver normal and
|
|
175
|
-
// light), not (1 - N.L). The linear form collapses toward zero far faster than the real
|
|
176
|
-
// gradient grows, so it under-biases exactly the grazing angles that need the most
|
|
177
|
-
// compensation. Clamped so a near-perpendicular receiver cannot demand unbounded bias.
|
|
178
186
|
float slopeTangent = min(sqrt(max(1.0 - normalDotLight * normalDotLight, 0.0)) / max(normalDotLight, 0.05), 8.0);
|
|
179
187
|
float slopeTexelBias = slopeTangent * u_shadowMapSlopeBias * max(u_shadowMapTexelSize.x, u_shadowMapTexelSize.y);
|
|
180
188
|
float projectedDepth = projected.z * 0.5 + 0.5;
|
|
@@ -207,9 +215,6 @@ float a3dPointShadowFactor(vec3 worldPosition, vec3 normal, vec3 lightDirection)
|
|
|
207
215
|
vec4 rect = u_pointShadowFaceRects[faceIndex];
|
|
208
216
|
vec2 uv = rect.xy + localUv * rect.zw;
|
|
209
217
|
float normalDotLight = clamp(abs(dot(normalize(normal), normalize(lightDirection))), 0.0, 1.0);
|
|
210
|
-
// Same per-sample, tangent-scaled slope bias as the directional and atlas paths. These
|
|
211
|
-
// cubemap-face variants inline the sample fetch, but they share the identical acne
|
|
212
|
-
// mechanism: a centre-only, (1 - N.L)-scaled bias under-compensates every outer tap.
|
|
213
218
|
float slopeTangent = min(sqrt(max(1.0 - normalDotLight * normalDotLight, 0.0)) / max(normalDotLight, 0.05), 8.0);
|
|
214
219
|
float slopeTexelBias = slopeTangent * u_pointShadowSlopeBias * max(u_pointShadowTexelSize.x, u_pointShadowTexelSize.y);
|
|
215
220
|
float projectedDepth = projected.z * 0.5 + 0.5;
|
|
@@ -228,6 +233,44 @@ float a3dPointShadowFactor(vec3 worldPosition, vec3 normal, vec3 lightDirection)
|
|
|
228
233
|
float occlusion = totalWeight > 0.0 ? shadowed / totalWeight : 0.0;
|
|
229
234
|
return mix(1.0, 1.0 - occlusion, clamp(u_pointShadowStrength, 0.0, 1.0));
|
|
230
235
|
}
|
|
236
|
+
float a3dSpotShadowFactor(vec3 worldPosition, vec3 normal, vec3 lightDirection) {
|
|
237
|
+
if (u_spotShadowMapEnabled < 0.5) return 1.0;
|
|
238
|
+
vec3 toFragment = worldPosition - u_spotShadowLightPosition;
|
|
239
|
+
float distanceToLight = max(length(toFragment), 0.0001);
|
|
240
|
+
if (distanceToLight > u_spotShadowRange) return 1.0;
|
|
241
|
+
vec3 coneAxis = u_spotShadowLightDirection / max(length(u_spotShadowLightDirection), 0.0001);
|
|
242
|
+
if (dot(toFragment / distanceToLight, coneAxis) < cos(u_spotShadowCone.x)) return 1.0;
|
|
243
|
+
vec4 lightPosition = u_spotShadowMatrix * vec4(worldPosition, 1.0);
|
|
244
|
+
vec3 projected = lightPosition.xyz / max(lightPosition.w, 0.0001);
|
|
245
|
+
vec2 uv = projected.xy * 0.5 + 0.5;
|
|
246
|
+
if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) return 1.0;
|
|
247
|
+
vec3 receiverNormal = normalize(normal);
|
|
248
|
+
vec3 receiverLightDirection = lightDirection / max(length(lightDirection), 0.0001);
|
|
249
|
+
float normalDotLight = clamp(abs(dot(receiverNormal, receiverLightDirection)), 0.0, 1.0);
|
|
250
|
+
float slopeTangent = min(sqrt(max(1.0 - normalDotLight * normalDotLight, 0.0)) / max(normalDotLight, 0.05), 8.0);
|
|
251
|
+
float slopeTexelBias = slopeTangent * u_spotShadowSlopeBias * max(u_spotShadowTexelSize.x, u_spotShadowTexelSize.y);
|
|
252
|
+
float projectedDepth = projected.z * 0.5 + 0.5;
|
|
253
|
+
float shadowed = 0.0;
|
|
254
|
+
float totalWeight = 0.0;
|
|
255
|
+
int sampleCount = clamp(int(u_spotShadowPcfSampleCount), 1, 32);
|
|
256
|
+
for (int i = 0; i < 32; ++i) {
|
|
257
|
+
if (i >= sampleCount) break;
|
|
258
|
+
vec4 sampleData = u_spotShadowPcfSamples[i];
|
|
259
|
+
float weight = max(sampleData.z, 0.0);
|
|
260
|
+
vec2 offset = sampleData.xy * u_spotShadowTexelSize;
|
|
261
|
+
float storedDepth = texture(u_spotShadowMapTexture, uv + offset).r;
|
|
262
|
+
float sampleTexelDistance = max(1.0, length(sampleData.xy));
|
|
263
|
+
float receiverDepth = projectedDepth - u_spotShadowBias - slopeTexelBias * sampleTexelDistance;
|
|
264
|
+
shadowed += (receiverDepth > storedDepth ? 1.0 : 0.0) * weight;
|
|
265
|
+
totalWeight += weight;
|
|
266
|
+
}
|
|
267
|
+
float occlusion = totalWeight > 0.0 ? shadowed / totalWeight : 0.0;
|
|
268
|
+
return mix(1.0, 1.0 - occlusion, clamp(u_spotShadowStrength, 0.0, 1.0));
|
|
269
|
+
}
|
|
270
|
+
float a3dResolveSpotShadowOverride(float baseFactor, float kind, float shadowFlag, vec3 worldPosition, vec3 normal, vec3 lightDirection) {
|
|
271
|
+
float spotGate = step(1.5, kind) * (1.0 - step(2.5, kind)) * step(0.5, u_spotShadowMapEnabled) * step(0.5, shadowFlag);
|
|
272
|
+
return mix(baseFactor, a3dSpotShadowFactor(worldPosition, normal, lightDirection), spotGate);
|
|
273
|
+
}
|
|
231
274
|
vec2 a3dEnvironmentEquirectUv(vec3 direction, float rotation) {
|
|
232
275
|
vec3 d = normalize(direction);
|
|
233
276
|
float u = atan(d.z, d.x) / 6.28318530718 + 0.5 + rotation;
|
|
@@ -273,16 +316,11 @@ vec3 a3dPbrEnvironmentDiffuseInput(vec3 normal) {
|
|
|
273
316
|
float horizonBlend = 1.0 - abs(normal.y);
|
|
274
317
|
vec3 proceduralDiffuse = mix(u_environmentGroundColor, u_environmentSkyColor, skyBlend);
|
|
275
318
|
proceduralDiffuse = mix(proceduralDiffuse, u_environmentHorizonColor, clamp(horizonBlend, 0.0, 1.0) * 0.55);
|
|
276
|
-
// The ambient term must be added to the procedural contribution, not replaced by it. A mix
|
|
277
|
-
// here discarded u_environmentColor * u_environmentIntensity entirely whenever a procedural
|
|
278
|
-
// map was present, which is the normal case: raising ambient intensity from 0.18 to 3.0 on
|
|
279
|
-
// the product-turntable kit produced a byte-identical frame. Ambient and a sky gradient are
|
|
280
|
-
// separate physical contributions, so they sum.
|
|
281
319
|
vec3 environmentDiffuse = ambientEnvironment + proceduralDiffuse * u_environmentMapIntensity * proceduralEnvironmentWeight;
|
|
282
320
|
float sampledEnvironmentWeight = step(0.0001, u_environmentMapTextureEnabled * u_environmentMapTextureIntensity);
|
|
283
321
|
float diffuseEnvironmentLod = max(u_environmentMapTextureMipCount - 1.0, 0.0);
|
|
284
322
|
vec3 sampledDiffuse = a3dPbrDecodeEnvironmentSample(a3dPbrEnvironmentSampleRaw(normal, diffuseEnvironmentLod));
|
|
285
|
-
return mix(environmentDiffuse, ambientEnvironment + sampledDiffuse * u_environmentMapTextureIntensity, sampledEnvironmentWeight);
|
|
323
|
+
return mix(environmentDiffuse, ambientEnvironment + sampledDiffuse * u_environmentMapTextureIntensity * u_materialEnvironmentIntensity, sampledEnvironmentWeight);
|
|
286
324
|
}
|
|
287
325
|
vec3 a3dPbrEnvironmentSpecularInput(vec3 normal, vec3 viewDirection, float roughness) {
|
|
288
326
|
float proceduralEnvironmentWeight = step(0.0001, u_environmentMapIntensity);
|
|
@@ -304,7 +342,7 @@ vec3 a3dPbrEnvironmentSpecularInput(vec3 normal, vec3 viewDirection, float rough
|
|
|
304
342
|
vec3 sampledSpecular = a3dPbrBoundHdrSpecularRadiance(a3dPbrDecodeEnvironmentSample(a3dPbrEnvironmentSampleRaw(reflectionDirection, environmentLod)));
|
|
305
343
|
float nDotV = clamp(dot(normal, viewDirection), 0.0, 1.0);
|
|
306
344
|
sampledSpecular = a3dPbrClampSampledSpecularEdgeEnergy(sampledSpecular, nDotV, clampedRoughness);
|
|
307
|
-
sampledSpecular *= u_environmentMapTextureSpecularIntensity * sampledEnvironmentWeight * mix(0.84, 0.58, clampedRoughness);
|
|
345
|
+
sampledSpecular *= u_environmentMapTextureSpecularIntensity * u_materialEnvironmentIntensity * sampledEnvironmentWeight * mix(0.84, 0.58, clampedRoughness);
|
|
308
346
|
return proceduralSpecular + sampledSpecular;
|
|
309
347
|
}
|
|
310
348
|
vec2 a3dPbrEnvironmentBrdfInput(vec3 normal, vec3 viewDirection, float roughness) {
|
|
@@ -312,10 +350,16 @@ vec2 a3dPbrEnvironmentBrdfInput(vec3 normal, vec3 viewDirection, float roughness
|
|
|
312
350
|
vec2 lut = texture(u_environmentBrdfLutTexture, vec2(nDotV, clamp(roughness, 0.0, 1.0))).rg;
|
|
313
351
|
return mix(vec2(1.0, 0.0), lut, step(0.0001, u_environmentBrdfLutEnabled));
|
|
314
352
|
}
|
|
353
|
+
vec3 a3dLinearToSrgb(vec3 linear) {
|
|
354
|
+
vec3 clamped = max(linear, vec3(0.0));
|
|
355
|
+
vec3 low = clamped * 12.92;
|
|
356
|
+
vec3 high = 1.055 * pow(clamped, vec3(1.0 / 2.4)) - 0.055;
|
|
357
|
+
return mix(low, high, step(vec3(0.0031308), clamped));
|
|
358
|
+
}
|
|
315
359
|
vec3 a3dPbrEncodeOutput(vec3 linearColor) {
|
|
316
360
|
vec3 color = max(linearColor, vec3(0.0));
|
|
317
361
|
vec3 filmic = clamp((color * (2.51 * color + 0.03)) / (color * (2.43 * color + 0.59) + 0.14), vec3(0.0), vec3(1.0));
|
|
318
|
-
vec3 srgb =
|
|
362
|
+
vec3 srgb = a3dLinearToSrgb(filmic);
|
|
319
363
|
return mix(color, srgb, step(0.5, u_outputColorSpace));
|
|
320
364
|
}
|
|
321
365
|
void main() {
|
|
@@ -376,7 +420,7 @@ void main() {
|
|
|
376
420
|
float inner = cos(spotShadowLayer.x * max(1.0 - spotShadowLayer.y, 0.001));
|
|
377
421
|
attenuation *= smoothstep(outer, inner, cone);
|
|
378
422
|
}
|
|
379
|
-
float shadowFactor = mix(1.0, kind > 0.5 && kind < 1.5 ? a3dPointShadowFactor(v_worldPosition, normal, lightDirection) : a3dForwardShadowFactor(v_worldPosition, normal, lightDirection), step(0.5, spotShadowLayer.z));
|
|
423
|
+
float shadowFactor = a3dResolveSpotShadowOverride(mix(1.0, kind > 0.5 && kind < 1.5 ? a3dPointShadowFactor(v_worldPosition, normal, lightDirection) : a3dForwardShadowFactor(v_worldPosition, normal, lightDirection), step(0.5, spotShadowLayer.z)), kind, spotShadowLayer.z, v_worldPosition, normal, lightDirection);
|
|
380
424
|
shaded += a3dPbrDirectLight(normal, viewDirection, lightDirection, colorIntensity.rgb, colorIntensity.a * attenuation * shadowFactor, base, u_metallic, u_roughness, 1.0, vec3(1.0));
|
|
381
425
|
}
|
|
382
426
|
float alpha = u_baseColor.a * v_instanceColor.a;
|
|
@@ -395,10 +439,18 @@ precision highp float;
|
|
|
395
439
|
layout(location = 0) in vec3 a_position;
|
|
396
440
|
layout(location = 2) in vec2 a_uv;
|
|
397
441
|
layout(location = 4) in vec4 a_color;
|
|
442
|
+
layout(location = 8) in vec4 a_instanceMatrix0;
|
|
443
|
+
layout(location = 9) in vec4 a_instanceMatrix1;
|
|
444
|
+
layout(location = 10) in vec4 a_instanceMatrix2;
|
|
445
|
+
layout(location = 11) in vec4 a_instanceMatrix3;
|
|
446
|
+
layout(location = 12) in vec4 a_instanceColor;
|
|
398
447
|
uniform mat4 u_modelViewProjection;
|
|
399
448
|
uniform vec2 u_baseColorTextureOffset;
|
|
400
449
|
uniform vec2 u_baseColorTextureScale;
|
|
401
450
|
uniform float u_baseColorTextureRotation;
|
|
451
|
+
uniform mat4 u_instanceMatrices[64];
|
|
452
|
+
uniform float u_instanceCount;
|
|
453
|
+
uniform float u_instanceAttributeMode;
|
|
402
454
|
out vec2 v_uv;
|
|
403
455
|
out vec4 v_vertexColor;
|
|
404
456
|
void main() {
|
|
@@ -406,8 +458,16 @@ void main() {
|
|
|
406
458
|
float c = cos(u_baseColorTextureRotation);
|
|
407
459
|
float s = sin(u_baseColorTextureRotation);
|
|
408
460
|
v_uv = vec2(scaledUv.x * c - scaledUv.y * s, scaledUv.x * s + scaledUv.y * c) + u_baseColorTextureOffset;
|
|
409
|
-
|
|
410
|
-
|
|
461
|
+
if (u_instanceCount > 0.5) {
|
|
462
|
+
int instanceIndex = clamp(gl_InstanceID, 0, max(int(u_instanceCount) - 1, 0));
|
|
463
|
+
mat4 attributeMatrix = mat4(a_instanceMatrix0, a_instanceMatrix1, a_instanceMatrix2, a_instanceMatrix3);
|
|
464
|
+
mat4 instanceMatrix = u_instanceAttributeMode > 0.5 ? attributeMatrix : u_instanceMatrices[instanceIndex];
|
|
465
|
+
v_vertexColor = a_color * a_instanceColor;
|
|
466
|
+
gl_Position = u_modelViewProjection * instanceMatrix * vec4(a_position, 1.0);
|
|
467
|
+
} else {
|
|
468
|
+
v_vertexColor = a_color;
|
|
469
|
+
gl_Position = u_modelViewProjection * vec4(a_position, 1.0);
|
|
470
|
+
}
|
|
411
471
|
}
|
|
412
472
|
`,
|
|
413
473
|
fragment: `#version 300 es
|
|
@@ -508,6 +568,7 @@ uniform float u_baseColorTextureEnabled;
|
|
|
508
568
|
uniform sampler2D u_normalTexture;
|
|
509
569
|
uniform float u_normalTextureEnabled;
|
|
510
570
|
uniform float u_normalScale;
|
|
571
|
+
uniform float u_wrinkleStrength;
|
|
511
572
|
uniform sampler2D u_metallicRoughnessTexture;
|
|
512
573
|
uniform float u_metallicRoughnessTextureEnabled;
|
|
513
574
|
uniform sampler2D u_occlusionTexture;
|
|
@@ -520,6 +581,7 @@ uniform float u_metallic;
|
|
|
520
581
|
uniform float u_roughness;
|
|
521
582
|
uniform vec3 u_environmentColor;
|
|
522
583
|
uniform float u_environmentIntensity;
|
|
584
|
+
uniform float u_materialEnvironmentIntensity;
|
|
523
585
|
uniform vec3 u_environmentSkyColor;
|
|
524
586
|
uniform vec3 u_environmentHorizonColor;
|
|
525
587
|
uniform vec3 u_environmentGroundColor;
|
|
@@ -593,6 +655,19 @@ uniform float u_pointShadowSlopeBias;
|
|
|
593
655
|
uniform vec2 u_pointShadowTexelSize;
|
|
594
656
|
uniform float u_pointShadowPcfSampleCount;
|
|
595
657
|
uniform vec4 u_pointShadowPcfSamples[32];
|
|
658
|
+
uniform sampler2D u_spotShadowMapTexture;
|
|
659
|
+
uniform float u_spotShadowMapEnabled;
|
|
660
|
+
uniform vec3 u_spotShadowLightPosition;
|
|
661
|
+
uniform vec3 u_spotShadowLightDirection;
|
|
662
|
+
uniform mat4 u_spotShadowMatrix;
|
|
663
|
+
uniform vec2 u_spotShadowCone;
|
|
664
|
+
uniform float u_spotShadowRange;
|
|
665
|
+
uniform float u_spotShadowStrength;
|
|
666
|
+
uniform float u_spotShadowBias;
|
|
667
|
+
uniform float u_spotShadowSlopeBias;
|
|
668
|
+
uniform vec2 u_spotShadowTexelSize;
|
|
669
|
+
uniform float u_spotShadowPcfSampleCount;
|
|
670
|
+
uniform vec4 u_spotShadowPcfSamples[32];
|
|
596
671
|
uniform float u_outputColorSpace;
|
|
597
672
|
uniform vec3 u_cameraPosition;
|
|
598
673
|
uniform float u_environmentFogEnabled;
|
|
@@ -602,6 +677,9 @@ uniform float u_environmentFogNear;
|
|
|
602
677
|
uniform float u_environmentFogFar;
|
|
603
678
|
uniform float u_environmentFogDensity;
|
|
604
679
|
uniform float u_environmentFogHeightFalloff;
|
|
680
|
+
uniform float u_volumetricIntensity;
|
|
681
|
+
uniform vec3 u_volumetricLightDirection;
|
|
682
|
+
uniform vec3 u_volumetricLightColor;
|
|
605
683
|
uniform float u_environmentFogHeightReference;
|
|
606
684
|
uniform float u_environmentFogMaxOpacity;
|
|
607
685
|
in vec3 v_normal;
|
|
@@ -649,6 +727,17 @@ vec4 a3dPbrEnvironmentSampleRaw(vec3 direction, float lod) {
|
|
|
649
727
|
vec4 cubeSample = textureLod(u_environmentCubeMapTexture, a3dEnvironmentCubeDirection(direction, u_environmentMapTextureRotation), lod);
|
|
650
728
|
return mix(equirectSample, cubeSample, step(0.5, u_environmentCubeMapTextureEnabled));
|
|
651
729
|
}
|
|
730
|
+
/**
|
|
731
|
+
* Procedural wrinkle detail (E1 face-rig demo): high-frequency normal perturbation driven
|
|
732
|
+
* by u_wrinkleStrength, which the engine resolves per frame from live morph weights
|
|
733
|
+
* (resolveWrinkleMapStrength). Stable in world space (no time input); strength 0 uploads
|
|
734
|
+
* 0 and the guarded call site below leaves the normal bit-identical.
|
|
735
|
+
*/
|
|
736
|
+
vec3 a3dWrinkleDetail(vec3 p) {
|
|
737
|
+
float f = sin(p.x * 230.0) * sin(p.y * 197.0 + 1.7) * sin(p.z * 211.0 + 0.6);
|
|
738
|
+
float g = sin(p.x * 97.0 + 0.4) * sin(p.y * 113.0 + 2.1) * sin(p.z * 103.0 + 1.2);
|
|
739
|
+
return vec3(f, g, f * g) * 0.35;
|
|
740
|
+
}
|
|
652
741
|
vec3 a3dSkinnedPbrNormal(vec3 baseNormal, vec4 tangentFrame, vec2 uv) {
|
|
653
742
|
vec3 sampled = texture(u_normalTexture, uv).xyz * 2.0 - 1.0;
|
|
654
743
|
vec3 n = normalize(baseNormal);
|
|
@@ -665,15 +754,6 @@ float a3dForwardShadowFactor(vec3 worldPosition, vec3 normal, vec3 lightDirectio
|
|
|
665
754
|
vec3 receiverNormal = normalize(normal);
|
|
666
755
|
vec3 receiverLightDirection = lightDirection / max(length(lightDirection), 0.0001);
|
|
667
756
|
float normalDotLight = clamp(abs(dot(receiverNormal, receiverLightDirection)), 0.0, 1.0);
|
|
668
|
-
// Slope-scaled depth bias must be evaluated per PCF sample, not once for the kernel
|
|
669
|
-
// centre. A sample offset N texels away on a receiver sloped relative to the light sees a
|
|
670
|
-
// depth difference proportional to N, so a centre-only bias under-compensates every outer
|
|
671
|
-
// tap and the receiver shadows itself. Scaling by each sample's own texel distance keeps
|
|
672
|
-
// wide kernels acne-free without inflating the constant bias into peter-panning.
|
|
673
|
-
// The depth gradient across one shadow texel is tan(angle between receiver normal and
|
|
674
|
-
// light), not (1 - N.L). The linear form collapses toward zero far faster than the real
|
|
675
|
-
// gradient grows, so it under-biases exactly the grazing angles that need the most
|
|
676
|
-
// compensation. Clamped so a near-perpendicular receiver cannot demand unbounded bias.
|
|
677
757
|
float slopeTangent = min(sqrt(max(1.0 - normalDotLight * normalDotLight, 0.0)) / max(normalDotLight, 0.05), 8.0);
|
|
678
758
|
float slopeTexelBias = slopeTangent * u_shadowMapSlopeBias * max(u_shadowMapTexelSize.x, u_shadowMapTexelSize.y);
|
|
679
759
|
float projectedDepth = projected.z * 0.5 + 0.5;
|
|
@@ -715,15 +795,6 @@ float a3dPointShadowFactor(vec3 worldPosition, vec3 normal, vec3 lightDirection)
|
|
|
715
795
|
vec3 receiverNormal = normalize(normal);
|
|
716
796
|
vec3 receiverLightDirection = lightDirection / max(length(lightDirection), 0.0001);
|
|
717
797
|
float normalDotLight = clamp(abs(dot(receiverNormal, receiverLightDirection)), 0.0, 1.0);
|
|
718
|
-
// Slope-scaled depth bias must be evaluated per PCF sample, not once for the kernel
|
|
719
|
-
// centre. A sample offset N texels away on a receiver sloped relative to the light sees a
|
|
720
|
-
// depth difference proportional to N, so a centre-only bias under-compensates every outer
|
|
721
|
-
// tap and the receiver shadows itself. Scaling by each sample's own texel distance keeps
|
|
722
|
-
// wide kernels acne-free without inflating the constant bias into peter-panning.
|
|
723
|
-
// The depth gradient across one shadow texel is tan(angle between receiver normal and
|
|
724
|
-
// light), not (1 - N.L). The linear form collapses toward zero far faster than the real
|
|
725
|
-
// gradient grows, so it under-biases exactly the grazing angles that need the most
|
|
726
|
-
// compensation. Clamped so a near-perpendicular receiver cannot demand unbounded bias.
|
|
727
798
|
float slopeTangent = min(sqrt(max(1.0 - normalDotLight * normalDotLight, 0.0)) / max(normalDotLight, 0.05), 8.0);
|
|
728
799
|
float slopeTexelBias = slopeTangent * u_pointShadowSlopeBias * max(u_pointShadowTexelSize.x, u_pointShadowTexelSize.y);
|
|
729
800
|
float projectedDepth = projected.z * 0.5 + 0.5;
|
|
@@ -744,15 +815,62 @@ float a3dPointShadowFactor(vec3 worldPosition, vec3 normal, vec3 lightDirection)
|
|
|
744
815
|
float occlusion = totalWeight > 0.0 ? shadowed / totalWeight : 0.0;
|
|
745
816
|
return mix(1.0, 1.0 - occlusion, clamp(u_pointShadowStrength, 0.0, 1.0));
|
|
746
817
|
}
|
|
818
|
+
float a3dSpotShadowFactor(vec3 worldPosition, vec3 normal, vec3 lightDirection) {
|
|
819
|
+
if (u_spotShadowMapEnabled < 0.5) return 1.0;
|
|
820
|
+
vec3 toFragment = worldPosition - u_spotShadowLightPosition;
|
|
821
|
+
float distanceToLight = max(length(toFragment), 0.0001);
|
|
822
|
+
if (distanceToLight > u_spotShadowRange) return 1.0;
|
|
823
|
+
vec3 coneAxis = u_spotShadowLightDirection / max(length(u_spotShadowLightDirection), 0.0001);
|
|
824
|
+
if (dot(toFragment / distanceToLight, coneAxis) < cos(u_spotShadowCone.x)) return 1.0;
|
|
825
|
+
vec4 lightPosition = u_spotShadowMatrix * vec4(worldPosition, 1.0);
|
|
826
|
+
vec3 projected = lightPosition.xyz / max(lightPosition.w, 0.0001);
|
|
827
|
+
vec2 uv = projected.xy * 0.5 + 0.5;
|
|
828
|
+
if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) return 1.0;
|
|
829
|
+
vec3 receiverNormal = normalize(normal);
|
|
830
|
+
vec3 receiverLightDirection = lightDirection / max(length(lightDirection), 0.0001);
|
|
831
|
+
float normalDotLight = clamp(abs(dot(receiverNormal, receiverLightDirection)), 0.0, 1.0);
|
|
832
|
+
float slopeTangent = min(sqrt(max(1.0 - normalDotLight * normalDotLight, 0.0)) / max(normalDotLight, 0.05), 8.0);
|
|
833
|
+
float slopeTexelBias = slopeTangent * u_spotShadowSlopeBias * max(u_spotShadowTexelSize.x, u_spotShadowTexelSize.y);
|
|
834
|
+
float projectedDepth = projected.z * 0.5 + 0.5;
|
|
835
|
+
float shadowed = 0.0;
|
|
836
|
+
float totalWeight = 0.0;
|
|
837
|
+
int sampleCount = clamp(int(u_spotShadowPcfSampleCount), 1, 32);
|
|
838
|
+
for (int i = 0; i < 32; ++i) {
|
|
839
|
+
if (i >= sampleCount) break;
|
|
840
|
+
vec4 sampleData = u_spotShadowPcfSamples[i];
|
|
841
|
+
float weight = max(sampleData.z, 0.0);
|
|
842
|
+
vec2 offset = sampleData.xy * u_spotShadowTexelSize;
|
|
843
|
+
float storedDepth = texture(u_spotShadowMapTexture, uv + offset).r;
|
|
844
|
+
float sampleTexelDistance = max(1.0, length(sampleData.xy));
|
|
845
|
+
float receiverDepth = projectedDepth - u_spotShadowBias - slopeTexelBias * sampleTexelDistance;
|
|
846
|
+
shadowed += (receiverDepth > storedDepth ? 1.0 : 0.0) * weight;
|
|
847
|
+
totalWeight += weight;
|
|
848
|
+
}
|
|
849
|
+
float occlusion = totalWeight > 0.0 ? shadowed / totalWeight : 0.0;
|
|
850
|
+
return mix(1.0, 1.0 - occlusion, clamp(u_spotShadowStrength, 0.0, 1.0));
|
|
851
|
+
}
|
|
852
|
+
float a3dResolveSpotShadowOverride(float baseFactor, float kind, float shadowFlag, vec3 worldPosition, vec3 normal, vec3 lightDirection) {
|
|
853
|
+
float spotGate = step(1.5, kind) * (1.0 - step(2.5, kind)) * step(0.5, u_spotShadowMapEnabled) * step(0.5, shadowFlag);
|
|
854
|
+
return mix(baseFactor, a3dSpotShadowFactor(worldPosition, normal, lightDirection), spotGate);
|
|
855
|
+
}
|
|
856
|
+
vec3 a3dLinearToSrgb(vec3 linear) {
|
|
857
|
+
vec3 clamped = max(linear, vec3(0.0));
|
|
858
|
+
vec3 low = clamped * 12.92;
|
|
859
|
+
vec3 high = 1.055 * pow(clamped, vec3(1.0 / 2.4)) - 0.055;
|
|
860
|
+
return mix(low, high, step(vec3(0.0031308), clamped));
|
|
861
|
+
}
|
|
747
862
|
vec3 a3dPbrEncodeOutput(vec3 linearColor) {
|
|
748
863
|
vec3 color = max(linearColor, vec3(0.0));
|
|
749
864
|
vec3 filmic = clamp((color * (2.51 * color + 0.03)) / (color * (2.43 * color + 0.59) + 0.14), vec3(0.0), vec3(1.0));
|
|
750
|
-
vec3 srgb =
|
|
865
|
+
vec3 srgb = a3dLinearToSrgb(filmic);
|
|
751
866
|
return mix(color, srgb, step(0.5, u_outputColorSpace));
|
|
752
867
|
}
|
|
753
868
|
void main() {
|
|
754
869
|
vec3 normal = normalize(v_normal);
|
|
755
870
|
normal = mix(normal, a3dSkinnedPbrNormal(v_normal, v_tangent, v_uv), step(0.5, u_normalTextureEnabled));
|
|
871
|
+
if (u_wrinkleStrength > 0.0) {
|
|
872
|
+
normal = normalize(normal + u_wrinkleStrength * a3dWrinkleDetail(v_worldPosition));
|
|
873
|
+
}
|
|
756
874
|
if (!gl_FrontFacing) normal = -normal;
|
|
757
875
|
vec3 viewDirection = normalize(u_cameraPosition - v_worldPosition);
|
|
758
876
|
vec4 sampledBaseColor = texture(u_baseColorTexture, v_uv);
|
|
@@ -795,11 +913,6 @@ void main() {
|
|
|
795
913
|
float horizonBlend = 1.0 - abs(normal.y);
|
|
796
914
|
vec3 proceduralDiffuse = mix(u_environmentGroundColor, u_environmentSkyColor, skyBlend);
|
|
797
915
|
proceduralDiffuse = mix(proceduralDiffuse, u_environmentHorizonColor, clamp(horizonBlend, 0.0, 1.0) * 0.55);
|
|
798
|
-
// The ambient term must be added to the procedural contribution, not replaced by it. A mix
|
|
799
|
-
// here discarded u_environmentColor * u_environmentIntensity entirely whenever a procedural
|
|
800
|
-
// map was present, which is the normal case: raising ambient intensity from 0.18 to 3.0 on
|
|
801
|
-
// the product-turntable kit produced a byte-identical frame. Ambient and a sky gradient are
|
|
802
|
-
// separate physical contributions, so they sum.
|
|
803
916
|
vec3 environmentDiffuse = ambientEnvironment + proceduralDiffuse * u_environmentMapIntensity * proceduralEnvironmentWeight;
|
|
804
917
|
vec3 reflectionDirection = reflect(-viewDirection, normal);
|
|
805
918
|
float sampledEnvironmentWeight = step(0.0001, u_environmentMapTextureEnabled * u_environmentMapTextureIntensity);
|
|
@@ -822,11 +935,11 @@ void main() {
|
|
|
822
935
|
float nDotV = clamp(dot(normal, viewDirection), 0.0, 1.0);
|
|
823
936
|
vec2 brdfLut = texture(u_environmentBrdfLutTexture, vec2(nDotV, clampedRoughness)).rg;
|
|
824
937
|
sampledSpecular = a3dPbrClampSampledSpecularEdgeEnergy(sampledSpecular, nDotV, clampedRoughness);
|
|
825
|
-
sampledSpecular *= u_environmentMapTextureSpecularIntensity * sampledEnvironmentWeight * mix(1.1, 0.65, roughness);
|
|
938
|
+
sampledSpecular *= u_environmentMapTextureSpecularIntensity * u_materialEnvironmentIntensity * sampledEnvironmentWeight * mix(1.1, 0.65, roughness);
|
|
826
939
|
vec3 shaded = a3dPbrEnvironmentLightSplitSum(
|
|
827
940
|
normal,
|
|
828
941
|
viewDirection,
|
|
829
|
-
mix(environmentDiffuse, ambientEnvironment + sampledDiffuse * u_environmentMapTextureIntensity, sampledEnvironmentWeight),
|
|
942
|
+
mix(environmentDiffuse, ambientEnvironment + sampledDiffuse * u_environmentMapTextureIntensity * u_materialEnvironmentIntensity, sampledEnvironmentWeight),
|
|
830
943
|
proceduralSpecular + sampledSpecular,
|
|
831
944
|
mix(vec2(1.0, 0.0), brdfLut, step(0.0001, u_environmentBrdfLutEnabled)),
|
|
832
945
|
materialBase,
|
|
@@ -881,7 +994,7 @@ void main() {
|
|
|
881
994
|
viewDirection,
|
|
882
995
|
lightDirection,
|
|
883
996
|
colorIntensity.rgb,
|
|
884
|
-
colorIntensity.a * attenuation * mix(1.0, kind > 0.5 && kind < 1.5 ? a3dPointShadowFactor(v_worldPosition, normal, lightDirection) : a3dForwardShadowFactor(v_worldPosition, normal, lightDirection), step(0.5, spotShadowLayer.z)),
|
|
997
|
+
colorIntensity.a * attenuation * a3dResolveSpotShadowOverride(mix(1.0, kind > 0.5 && kind < 1.5 ? a3dPointShadowFactor(v_worldPosition, normal, lightDirection) : a3dForwardShadowFactor(v_worldPosition, normal, lightDirection), step(0.5, spotShadowLayer.z)), kind, spotShadowLayer.z, v_worldPosition, normal, lightDirection),
|
|
885
998
|
materialBase,
|
|
886
999
|
metallic,
|
|
887
1000
|
roughness,
|
|
@@ -966,8 +1079,6 @@ void main() {
|
|
|
966
1079
|
a_weights.x + a_weights.y + a_weights.z + a_weights.w +
|
|
967
1080
|
a_weights1.x + a_weights1.y + a_weights1.z + a_weights1.w;
|
|
968
1081
|
vec4 skinnedPosition = v_weightSum > 0.0001 ? skin * vec4(a_position, 1.0) : vec4(a_position, 1.0);
|
|
969
|
-
// Normals and tangents use the same skin matrix with w = 0 so translation is
|
|
970
|
-
// excluded; renormalizing happens in the fragment stage.
|
|
971
1082
|
vec3 skinnedNormal = (v_weightSum > 0.0001 ? skin * vec4(a_normal, 0.0) : vec4(a_normal, 0.0)).xyz;
|
|
972
1083
|
vec3 skinnedTangent = (v_weightSum > 0.0001 ? skin * vec4(a_tangent.xyz, 0.0) : vec4(a_tangent.xyz, 0.0)).xyz;
|
|
973
1084
|
v_normal = mat3(u_normalMatrix) * skinnedNormal;
|
|
@@ -987,6 +1098,7 @@ uniform float u_baseColorTextureEnabled;
|
|
|
987
1098
|
uniform sampler2D u_normalTexture;
|
|
988
1099
|
uniform float u_normalTextureEnabled;
|
|
989
1100
|
uniform float u_normalScale;
|
|
1101
|
+
uniform float u_wrinkleStrength;
|
|
990
1102
|
uniform sampler2D u_metallicRoughnessTexture;
|
|
991
1103
|
uniform float u_metallicRoughnessTextureEnabled;
|
|
992
1104
|
uniform sampler2D u_occlusionTexture;
|
|
@@ -999,6 +1111,7 @@ uniform float u_metallic;
|
|
|
999
1111
|
uniform float u_roughness;
|
|
1000
1112
|
uniform vec3 u_environmentColor;
|
|
1001
1113
|
uniform float u_environmentIntensity;
|
|
1114
|
+
uniform float u_materialEnvironmentIntensity;
|
|
1002
1115
|
uniform vec3 u_environmentSkyColor;
|
|
1003
1116
|
uniform vec3 u_environmentHorizonColor;
|
|
1004
1117
|
uniform vec3 u_environmentGroundColor;
|
|
@@ -1072,6 +1185,19 @@ uniform float u_pointShadowSlopeBias;
|
|
|
1072
1185
|
uniform vec2 u_pointShadowTexelSize;
|
|
1073
1186
|
uniform float u_pointShadowPcfSampleCount;
|
|
1074
1187
|
uniform vec4 u_pointShadowPcfSamples[32];
|
|
1188
|
+
uniform sampler2D u_spotShadowMapTexture;
|
|
1189
|
+
uniform float u_spotShadowMapEnabled;
|
|
1190
|
+
uniform vec3 u_spotShadowLightPosition;
|
|
1191
|
+
uniform vec3 u_spotShadowLightDirection;
|
|
1192
|
+
uniform mat4 u_spotShadowMatrix;
|
|
1193
|
+
uniform vec2 u_spotShadowCone;
|
|
1194
|
+
uniform float u_spotShadowRange;
|
|
1195
|
+
uniform float u_spotShadowStrength;
|
|
1196
|
+
uniform float u_spotShadowBias;
|
|
1197
|
+
uniform float u_spotShadowSlopeBias;
|
|
1198
|
+
uniform vec2 u_spotShadowTexelSize;
|
|
1199
|
+
uniform float u_spotShadowPcfSampleCount;
|
|
1200
|
+
uniform vec4 u_spotShadowPcfSamples[32];
|
|
1075
1201
|
uniform float u_outputColorSpace;
|
|
1076
1202
|
uniform vec3 u_cameraPosition;
|
|
1077
1203
|
uniform float u_environmentFogEnabled;
|
|
@@ -1081,6 +1207,9 @@ uniform float u_environmentFogNear;
|
|
|
1081
1207
|
uniform float u_environmentFogFar;
|
|
1082
1208
|
uniform float u_environmentFogDensity;
|
|
1083
1209
|
uniform float u_environmentFogHeightFalloff;
|
|
1210
|
+
uniform float u_volumetricIntensity;
|
|
1211
|
+
uniform vec3 u_volumetricLightDirection;
|
|
1212
|
+
uniform vec3 u_volumetricLightColor;
|
|
1084
1213
|
uniform float u_environmentFogHeightReference;
|
|
1085
1214
|
uniform float u_environmentFogMaxOpacity;
|
|
1086
1215
|
in vec3 v_normal;
|
|
@@ -1128,6 +1257,17 @@ vec4 a3dPbrEnvironmentSampleRaw(vec3 direction, float lod) {
|
|
|
1128
1257
|
vec4 cubeSample = textureLod(u_environmentCubeMapTexture, a3dEnvironmentCubeDirection(direction, u_environmentMapTextureRotation), lod);
|
|
1129
1258
|
return mix(equirectSample, cubeSample, step(0.5, u_environmentCubeMapTextureEnabled));
|
|
1130
1259
|
}
|
|
1260
|
+
/**
|
|
1261
|
+
* Procedural wrinkle detail (E1 face-rig demo): high-frequency normal perturbation driven
|
|
1262
|
+
* by u_wrinkleStrength, which the engine resolves per frame from live morph weights
|
|
1263
|
+
* (resolveWrinkleMapStrength). Stable in world space (no time input); strength 0 uploads
|
|
1264
|
+
* 0 and the guarded call site below leaves the normal bit-identical.
|
|
1265
|
+
*/
|
|
1266
|
+
vec3 a3dWrinkleDetail(vec3 p) {
|
|
1267
|
+
float f = sin(p.x * 230.0) * sin(p.y * 197.0 + 1.7) * sin(p.z * 211.0 + 0.6);
|
|
1268
|
+
float g = sin(p.x * 97.0 + 0.4) * sin(p.y * 113.0 + 2.1) * sin(p.z * 103.0 + 1.2);
|
|
1269
|
+
return vec3(f, g, f * g) * 0.35;
|
|
1270
|
+
}
|
|
1131
1271
|
vec3 a3dSkinnedPbrNormal(vec3 baseNormal, vec4 tangentFrame, vec2 uv) {
|
|
1132
1272
|
vec3 sampled = texture(u_normalTexture, uv).xyz * 2.0 - 1.0;
|
|
1133
1273
|
vec3 n = normalize(baseNormal);
|
|
@@ -1144,15 +1284,6 @@ float a3dForwardShadowFactor(vec3 worldPosition, vec3 normal, vec3 lightDirectio
|
|
|
1144
1284
|
vec3 receiverNormal = normalize(normal);
|
|
1145
1285
|
vec3 receiverLightDirection = lightDirection / max(length(lightDirection), 0.0001);
|
|
1146
1286
|
float normalDotLight = clamp(abs(dot(receiverNormal, receiverLightDirection)), 0.0, 1.0);
|
|
1147
|
-
// Slope-scaled depth bias must be evaluated per PCF sample, not once for the kernel
|
|
1148
|
-
// centre. A sample offset N texels away on a receiver sloped relative to the light sees a
|
|
1149
|
-
// depth difference proportional to N, so a centre-only bias under-compensates every outer
|
|
1150
|
-
// tap and the receiver shadows itself. Scaling by each sample's own texel distance keeps
|
|
1151
|
-
// wide kernels acne-free without inflating the constant bias into peter-panning.
|
|
1152
|
-
// The depth gradient across one shadow texel is tan(angle between receiver normal and
|
|
1153
|
-
// light), not (1 - N.L). The linear form collapses toward zero far faster than the real
|
|
1154
|
-
// gradient grows, so it under-biases exactly the grazing angles that need the most
|
|
1155
|
-
// compensation. Clamped so a near-perpendicular receiver cannot demand unbounded bias.
|
|
1156
1287
|
float slopeTangent = min(sqrt(max(1.0 - normalDotLight * normalDotLight, 0.0)) / max(normalDotLight, 0.05), 8.0);
|
|
1157
1288
|
float slopeTexelBias = slopeTangent * u_shadowMapSlopeBias * max(u_shadowMapTexelSize.x, u_shadowMapTexelSize.y);
|
|
1158
1289
|
float projectedDepth = projected.z * 0.5 + 0.5;
|
|
@@ -1194,15 +1325,6 @@ float a3dPointShadowFactor(vec3 worldPosition, vec3 normal, vec3 lightDirection)
|
|
|
1194
1325
|
vec3 receiverNormal = normalize(normal);
|
|
1195
1326
|
vec3 receiverLightDirection = lightDirection / max(length(lightDirection), 0.0001);
|
|
1196
1327
|
float normalDotLight = clamp(abs(dot(receiverNormal, receiverLightDirection)), 0.0, 1.0);
|
|
1197
|
-
// Slope-scaled depth bias must be evaluated per PCF sample, not once for the kernel
|
|
1198
|
-
// centre. A sample offset N texels away on a receiver sloped relative to the light sees a
|
|
1199
|
-
// depth difference proportional to N, so a centre-only bias under-compensates every outer
|
|
1200
|
-
// tap and the receiver shadows itself. Scaling by each sample's own texel distance keeps
|
|
1201
|
-
// wide kernels acne-free without inflating the constant bias into peter-panning.
|
|
1202
|
-
// The depth gradient across one shadow texel is tan(angle between receiver normal and
|
|
1203
|
-
// light), not (1 - N.L). The linear form collapses toward zero far faster than the real
|
|
1204
|
-
// gradient grows, so it under-biases exactly the grazing angles that need the most
|
|
1205
|
-
// compensation. Clamped so a near-perpendicular receiver cannot demand unbounded bias.
|
|
1206
1328
|
float slopeTangent = min(sqrt(max(1.0 - normalDotLight * normalDotLight, 0.0)) / max(normalDotLight, 0.05), 8.0);
|
|
1207
1329
|
float slopeTexelBias = slopeTangent * u_pointShadowSlopeBias * max(u_pointShadowTexelSize.x, u_pointShadowTexelSize.y);
|
|
1208
1330
|
float projectedDepth = projected.z * 0.5 + 0.5;
|
|
@@ -1223,15 +1345,62 @@ float a3dPointShadowFactor(vec3 worldPosition, vec3 normal, vec3 lightDirection)
|
|
|
1223
1345
|
float occlusion = totalWeight > 0.0 ? shadowed / totalWeight : 0.0;
|
|
1224
1346
|
return mix(1.0, 1.0 - occlusion, clamp(u_pointShadowStrength, 0.0, 1.0));
|
|
1225
1347
|
}
|
|
1348
|
+
float a3dSpotShadowFactor(vec3 worldPosition, vec3 normal, vec3 lightDirection) {
|
|
1349
|
+
if (u_spotShadowMapEnabled < 0.5) return 1.0;
|
|
1350
|
+
vec3 toFragment = worldPosition - u_spotShadowLightPosition;
|
|
1351
|
+
float distanceToLight = max(length(toFragment), 0.0001);
|
|
1352
|
+
if (distanceToLight > u_spotShadowRange) return 1.0;
|
|
1353
|
+
vec3 coneAxis = u_spotShadowLightDirection / max(length(u_spotShadowLightDirection), 0.0001);
|
|
1354
|
+
if (dot(toFragment / distanceToLight, coneAxis) < cos(u_spotShadowCone.x)) return 1.0;
|
|
1355
|
+
vec4 lightPosition = u_spotShadowMatrix * vec4(worldPosition, 1.0);
|
|
1356
|
+
vec3 projected = lightPosition.xyz / max(lightPosition.w, 0.0001);
|
|
1357
|
+
vec2 uv = projected.xy * 0.5 + 0.5;
|
|
1358
|
+
if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) return 1.0;
|
|
1359
|
+
vec3 receiverNormal = normalize(normal);
|
|
1360
|
+
vec3 receiverLightDirection = lightDirection / max(length(lightDirection), 0.0001);
|
|
1361
|
+
float normalDotLight = clamp(abs(dot(receiverNormal, receiverLightDirection)), 0.0, 1.0);
|
|
1362
|
+
float slopeTangent = min(sqrt(max(1.0 - normalDotLight * normalDotLight, 0.0)) / max(normalDotLight, 0.05), 8.0);
|
|
1363
|
+
float slopeTexelBias = slopeTangent * u_spotShadowSlopeBias * max(u_spotShadowTexelSize.x, u_spotShadowTexelSize.y);
|
|
1364
|
+
float projectedDepth = projected.z * 0.5 + 0.5;
|
|
1365
|
+
float shadowed = 0.0;
|
|
1366
|
+
float totalWeight = 0.0;
|
|
1367
|
+
int sampleCount = clamp(int(u_spotShadowPcfSampleCount), 1, 32);
|
|
1368
|
+
for (int i = 0; i < 32; ++i) {
|
|
1369
|
+
if (i >= sampleCount) break;
|
|
1370
|
+
vec4 sampleData = u_spotShadowPcfSamples[i];
|
|
1371
|
+
float weight = max(sampleData.z, 0.0);
|
|
1372
|
+
vec2 offset = sampleData.xy * u_spotShadowTexelSize;
|
|
1373
|
+
float storedDepth = texture(u_spotShadowMapTexture, uv + offset).r;
|
|
1374
|
+
float sampleTexelDistance = max(1.0, length(sampleData.xy));
|
|
1375
|
+
float receiverDepth = projectedDepth - u_spotShadowBias - slopeTexelBias * sampleTexelDistance;
|
|
1376
|
+
shadowed += (receiverDepth > storedDepth ? 1.0 : 0.0) * weight;
|
|
1377
|
+
totalWeight += weight;
|
|
1378
|
+
}
|
|
1379
|
+
float occlusion = totalWeight > 0.0 ? shadowed / totalWeight : 0.0;
|
|
1380
|
+
return mix(1.0, 1.0 - occlusion, clamp(u_spotShadowStrength, 0.0, 1.0));
|
|
1381
|
+
}
|
|
1382
|
+
float a3dResolveSpotShadowOverride(float baseFactor, float kind, float shadowFlag, vec3 worldPosition, vec3 normal, vec3 lightDirection) {
|
|
1383
|
+
float spotGate = step(1.5, kind) * (1.0 - step(2.5, kind)) * step(0.5, u_spotShadowMapEnabled) * step(0.5, shadowFlag);
|
|
1384
|
+
return mix(baseFactor, a3dSpotShadowFactor(worldPosition, normal, lightDirection), spotGate);
|
|
1385
|
+
}
|
|
1386
|
+
vec3 a3dLinearToSrgb(vec3 linear) {
|
|
1387
|
+
vec3 clamped = max(linear, vec3(0.0));
|
|
1388
|
+
vec3 low = clamped * 12.92;
|
|
1389
|
+
vec3 high = 1.055 * pow(clamped, vec3(1.0 / 2.4)) - 0.055;
|
|
1390
|
+
return mix(low, high, step(vec3(0.0031308), clamped));
|
|
1391
|
+
}
|
|
1226
1392
|
vec3 a3dPbrEncodeOutput(vec3 linearColor) {
|
|
1227
1393
|
vec3 color = max(linearColor, vec3(0.0));
|
|
1228
1394
|
vec3 filmic = clamp((color * (2.51 * color + 0.03)) / (color * (2.43 * color + 0.59) + 0.14), vec3(0.0), vec3(1.0));
|
|
1229
|
-
vec3 srgb =
|
|
1395
|
+
vec3 srgb = a3dLinearToSrgb(filmic);
|
|
1230
1396
|
return mix(color, srgb, step(0.5, u_outputColorSpace));
|
|
1231
1397
|
}
|
|
1232
1398
|
void main() {
|
|
1233
1399
|
vec3 normal = normalize(v_normal);
|
|
1234
1400
|
normal = mix(normal, a3dSkinnedPbrNormal(v_normal, v_tangent, v_uv), step(0.5, u_normalTextureEnabled));
|
|
1401
|
+
if (u_wrinkleStrength > 0.0) {
|
|
1402
|
+
normal = normalize(normal + u_wrinkleStrength * a3dWrinkleDetail(v_worldPosition));
|
|
1403
|
+
}
|
|
1235
1404
|
if (!gl_FrontFacing) normal = -normal;
|
|
1236
1405
|
vec3 viewDirection = normalize(u_cameraPosition - v_worldPosition);
|
|
1237
1406
|
vec4 sampledBaseColor = texture(u_baseColorTexture, v_uv);
|
|
@@ -1274,11 +1443,6 @@ void main() {
|
|
|
1274
1443
|
float horizonBlend = 1.0 - abs(normal.y);
|
|
1275
1444
|
vec3 proceduralDiffuse = mix(u_environmentGroundColor, u_environmentSkyColor, skyBlend);
|
|
1276
1445
|
proceduralDiffuse = mix(proceduralDiffuse, u_environmentHorizonColor, clamp(horizonBlend, 0.0, 1.0) * 0.55);
|
|
1277
|
-
// The ambient term must be added to the procedural contribution, not replaced by it. A mix
|
|
1278
|
-
// here discarded u_environmentColor * u_environmentIntensity entirely whenever a procedural
|
|
1279
|
-
// map was present, which is the normal case: raising ambient intensity from 0.18 to 3.0 on
|
|
1280
|
-
// the product-turntable kit produced a byte-identical frame. Ambient and a sky gradient are
|
|
1281
|
-
// separate physical contributions, so they sum.
|
|
1282
1446
|
vec3 environmentDiffuse = ambientEnvironment + proceduralDiffuse * u_environmentMapIntensity * proceduralEnvironmentWeight;
|
|
1283
1447
|
vec3 reflectionDirection = reflect(-viewDirection, normal);
|
|
1284
1448
|
float sampledEnvironmentWeight = step(0.0001, u_environmentMapTextureEnabled * u_environmentMapTextureIntensity);
|
|
@@ -1301,11 +1465,11 @@ void main() {
|
|
|
1301
1465
|
float nDotV = clamp(dot(normal, viewDirection), 0.0, 1.0);
|
|
1302
1466
|
vec2 brdfLut = texture(u_environmentBrdfLutTexture, vec2(nDotV, clampedRoughness)).rg;
|
|
1303
1467
|
sampledSpecular = a3dPbrClampSampledSpecularEdgeEnergy(sampledSpecular, nDotV, clampedRoughness);
|
|
1304
|
-
sampledSpecular *= u_environmentMapTextureSpecularIntensity * sampledEnvironmentWeight * mix(1.1, 0.65, roughness);
|
|
1468
|
+
sampledSpecular *= u_environmentMapTextureSpecularIntensity * u_materialEnvironmentIntensity * sampledEnvironmentWeight * mix(1.1, 0.65, roughness);
|
|
1305
1469
|
vec3 shaded = a3dPbrEnvironmentLightSplitSum(
|
|
1306
1470
|
normal,
|
|
1307
1471
|
viewDirection,
|
|
1308
|
-
mix(environmentDiffuse, ambientEnvironment + sampledDiffuse * u_environmentMapTextureIntensity, sampledEnvironmentWeight),
|
|
1472
|
+
mix(environmentDiffuse, ambientEnvironment + sampledDiffuse * u_environmentMapTextureIntensity * u_materialEnvironmentIntensity, sampledEnvironmentWeight),
|
|
1309
1473
|
proceduralSpecular + sampledSpecular,
|
|
1310
1474
|
mix(vec2(1.0, 0.0), brdfLut, step(0.0001, u_environmentBrdfLutEnabled)),
|
|
1311
1475
|
materialBase,
|
|
@@ -1360,7 +1524,7 @@ void main() {
|
|
|
1360
1524
|
viewDirection,
|
|
1361
1525
|
lightDirection,
|
|
1362
1526
|
colorIntensity.rgb,
|
|
1363
|
-
colorIntensity.a * attenuation * mix(1.0, kind > 0.5 && kind < 1.5 ? a3dPointShadowFactor(v_worldPosition, normal, lightDirection) : a3dForwardShadowFactor(v_worldPosition, normal, lightDirection), step(0.5, spotShadowLayer.z)),
|
|
1527
|
+
colorIntensity.a * attenuation * a3dResolveSpotShadowOverride(mix(1.0, kind > 0.5 && kind < 1.5 ? a3dPointShadowFactor(v_worldPosition, normal, lightDirection) : a3dForwardShadowFactor(v_worldPosition, normal, lightDirection), step(0.5, spotShadowLayer.z)), kind, spotShadowLayer.z, v_worldPosition, normal, lightDirection),
|
|
1364
1528
|
materialBase,
|
|
1365
1529
|
metallic,
|
|
1366
1530
|
roughness,
|
|
@@ -1382,18 +1546,15 @@ void main() {
|
|
|
1382
1546
|
precision highp float;
|
|
1383
1547
|
layout(location = 0) in vec3 a_position;
|
|
1384
1548
|
uniform mat4 u_modelViewProjection;
|
|
1385
|
-
// Uniform fast path (<= 4 targets / 64 verts):
|
|
1386
1549
|
uniform vec4 u_morphPositionDeltas[256];
|
|
1387
1550
|
uniform vec4 u_morphWeights;
|
|
1388
1551
|
uniform float u_morphTargetCount;
|
|
1389
|
-
// Texture-backed path (lifts the 4/64 cap; see MorphTargetPlan.ts createMorphTargetPlan):
|
|
1390
1552
|
uniform sampler2D u_morphDeltaTexture;
|
|
1391
|
-
uniform float u_morphUsesTexture;
|
|
1392
|
-
uniform float u_morphTextureWidth;
|
|
1393
|
-
uniform float u_morphRowsPerTarget;
|
|
1394
|
-
uniform float u_morphWeightArray[64];
|
|
1553
|
+
uniform float u_morphUsesTexture;
|
|
1554
|
+
uniform float u_morphTextureWidth;
|
|
1555
|
+
uniform float u_morphRowsPerTarget;
|
|
1556
|
+
uniform float u_morphWeightArray[64];
|
|
1395
1557
|
vec3 sampleMorphTexel(float row, float vertex) {
|
|
1396
|
-
// Fetch RGBA float texel at (x=vertex, y=row) using normalized coords + nearest filtering.
|
|
1397
1558
|
float u = (vertex + 0.5) / max(1.0, u_morphTextureWidth);
|
|
1398
1559
|
float height = u_morphTargetCount * u_morphRowsPerTarget;
|
|
1399
1560
|
float v = (row + 0.5) / max(1.0, height);
|
|
@@ -1443,21 +1604,42 @@ layout(location = 2) in vec2 a_uv;
|
|
|
1443
1604
|
layout(location = 3) in vec4 a_tangent;
|
|
1444
1605
|
layout(location = 4) in vec4 a_color;
|
|
1445
1606
|
layout(location = 7) in vec2 a_uv1;
|
|
1607
|
+
layout(location = 8) in vec4 a_instanceMatrix0;
|
|
1608
|
+
layout(location = 9) in vec4 a_instanceMatrix1;
|
|
1609
|
+
layout(location = 10) in vec4 a_instanceMatrix2;
|
|
1610
|
+
layout(location = 11) in vec4 a_instanceMatrix3;
|
|
1611
|
+
layout(location = 12) in vec4 a_instanceColor;
|
|
1446
1612
|
uniform mat4 u_modelViewProjection;
|
|
1447
1613
|
uniform mat4 u_modelMatrix;
|
|
1448
1614
|
uniform mat4 u_normalMatrix;
|
|
1615
|
+
uniform mat4 u_instanceMatrices[64];
|
|
1616
|
+
uniform float u_instanceCount;
|
|
1617
|
+
uniform float u_instanceAttributeMode;
|
|
1449
1618
|
out vec3 v_normal;
|
|
1450
1619
|
out vec4 v_tangent;
|
|
1451
1620
|
out vec3 v_worldPosition;
|
|
1452
1621
|
out vec2 v_uv;
|
|
1453
1622
|
out vec4 v_vertexColor;
|
|
1454
1623
|
void main() {
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1624
|
+
if (u_instanceCount > 0.5) {
|
|
1625
|
+
int instanceIndex = clamp(gl_InstanceID, 0, max(int(u_instanceCount) - 1, 0));
|
|
1626
|
+
mat4 attributeMatrix = mat4(a_instanceMatrix0, a_instanceMatrix1, a_instanceMatrix2, a_instanceMatrix3);
|
|
1627
|
+
mat4 instanceMatrix = u_instanceAttributeMode > 0.5 ? attributeMatrix : u_instanceMatrices[instanceIndex];
|
|
1628
|
+
vec4 worldPosition = u_modelMatrix * instanceMatrix * vec4(a_position, 1.0);
|
|
1629
|
+
v_normal = mat3(u_normalMatrix) * transpose(inverse(mat3(instanceMatrix))) * a_normal;
|
|
1630
|
+
v_tangent = vec4(mat3(u_normalMatrix) * (mat3(instanceMatrix) * a_tangent.xyz), a_tangent.w);
|
|
1631
|
+
v_worldPosition = worldPosition.xyz;
|
|
1632
|
+
v_uv = a_uv;
|
|
1633
|
+
v_vertexColor = a_color * a_instanceColor;
|
|
1634
|
+
gl_Position = u_modelViewProjection * instanceMatrix * vec4(a_position, 1.0);
|
|
1635
|
+
} else {
|
|
1636
|
+
v_normal = mat3(u_normalMatrix) * a_normal;
|
|
1637
|
+
v_tangent = vec4(mat3(u_normalMatrix) * a_tangent.xyz, a_tangent.w);
|
|
1638
|
+
v_worldPosition = (u_modelMatrix * vec4(a_position, 1.0)).xyz;
|
|
1639
|
+
v_uv = a_uv;
|
|
1640
|
+
v_vertexColor = a_color;
|
|
1641
|
+
gl_Position = u_modelViewProjection * vec4(a_position, 1.0);
|
|
1642
|
+
}
|
|
1461
1643
|
}
|
|
1462
1644
|
`,
|
|
1463
1645
|
fragment: `#version 300 es
|
|
@@ -1471,6 +1653,7 @@ uniform float u_metallic;
|
|
|
1471
1653
|
uniform float u_roughness;
|
|
1472
1654
|
uniform vec3 u_environmentColor;
|
|
1473
1655
|
uniform float u_environmentIntensity;
|
|
1656
|
+
uniform float u_materialEnvironmentIntensity;
|
|
1474
1657
|
uniform vec3 u_environmentSkyColor;
|
|
1475
1658
|
uniform vec3 u_environmentHorizonColor;
|
|
1476
1659
|
uniform vec3 u_environmentGroundColor;
|
|
@@ -1539,6 +1722,19 @@ uniform float u_pointShadowSlopeBias;
|
|
|
1539
1722
|
uniform vec2 u_pointShadowTexelSize;
|
|
1540
1723
|
uniform float u_pointShadowPcfSampleCount;
|
|
1541
1724
|
uniform vec4 u_pointShadowPcfSamples[32];
|
|
1725
|
+
uniform sampler2D u_spotShadowMapTexture;
|
|
1726
|
+
uniform float u_spotShadowMapEnabled;
|
|
1727
|
+
uniform vec3 u_spotShadowLightPosition;
|
|
1728
|
+
uniform vec3 u_spotShadowLightDirection;
|
|
1729
|
+
uniform mat4 u_spotShadowMatrix;
|
|
1730
|
+
uniform vec2 u_spotShadowCone;
|
|
1731
|
+
uniform float u_spotShadowRange;
|
|
1732
|
+
uniform float u_spotShadowStrength;
|
|
1733
|
+
uniform float u_spotShadowBias;
|
|
1734
|
+
uniform float u_spotShadowSlopeBias;
|
|
1735
|
+
uniform vec2 u_spotShadowTexelSize;
|
|
1736
|
+
uniform float u_spotShadowPcfSampleCount;
|
|
1737
|
+
uniform vec4 u_spotShadowPcfSamples[32];
|
|
1542
1738
|
uniform float u_outputColorSpace;
|
|
1543
1739
|
uniform vec3 u_cameraPosition;
|
|
1544
1740
|
uniform float u_environmentFogEnabled;
|
|
@@ -1548,6 +1744,9 @@ uniform float u_environmentFogNear;
|
|
|
1548
1744
|
uniform float u_environmentFogFar;
|
|
1549
1745
|
uniform float u_environmentFogDensity;
|
|
1550
1746
|
uniform float u_environmentFogHeightFalloff;
|
|
1747
|
+
uniform float u_volumetricIntensity;
|
|
1748
|
+
uniform vec3 u_volumetricLightDirection;
|
|
1749
|
+
uniform vec3 u_volumetricLightColor;
|
|
1551
1750
|
uniform float u_environmentFogHeightReference;
|
|
1552
1751
|
uniform float u_environmentFogMaxOpacity;
|
|
1553
1752
|
in vec3 v_normal;
|
|
@@ -1573,15 +1772,6 @@ float a3dForwardShadowFactor(vec3 worldPosition, vec3 normal, vec3 lightDirectio
|
|
|
1573
1772
|
vec3 receiverNormal = normalize(normal);
|
|
1574
1773
|
vec3 receiverLightDirection = lightDirection / max(length(lightDirection), 0.0001);
|
|
1575
1774
|
float normalDotLight = clamp(abs(dot(receiverNormal, receiverLightDirection)), 0.0, 1.0);
|
|
1576
|
-
// Slope-scaled depth bias must be evaluated per PCF sample, not once for the kernel
|
|
1577
|
-
// centre. A sample offset N texels away on a receiver sloped relative to the light sees a
|
|
1578
|
-
// depth difference proportional to N, so a centre-only bias under-compensates every outer
|
|
1579
|
-
// tap and the receiver shadows itself. Scaling by each sample's own texel distance keeps
|
|
1580
|
-
// wide kernels acne-free without inflating the constant bias into peter-panning.
|
|
1581
|
-
// The depth gradient across one shadow texel is tan(angle between receiver normal and
|
|
1582
|
-
// light), not (1 - N.L). The linear form collapses toward zero far faster than the real
|
|
1583
|
-
// gradient grows, so it under-biases exactly the grazing angles that need the most
|
|
1584
|
-
// compensation. Clamped so a near-perpendicular receiver cannot demand unbounded bias.
|
|
1585
1775
|
float slopeTangent = min(sqrt(max(1.0 - normalDotLight * normalDotLight, 0.0)) / max(normalDotLight, 0.05), 8.0);
|
|
1586
1776
|
float slopeTexelBias = slopeTangent * u_shadowMapSlopeBias * max(u_shadowMapTexelSize.x, u_shadowMapTexelSize.y);
|
|
1587
1777
|
float projectedDepth = projected.z * 0.5 + 0.5;
|
|
@@ -1614,9 +1804,6 @@ float a3dPointShadowFactor(vec3 worldPosition, vec3 normal, vec3 lightDirection)
|
|
|
1614
1804
|
vec4 rect = u_pointShadowFaceRects[faceIndex];
|
|
1615
1805
|
vec2 uv = rect.xy + localUv * rect.zw;
|
|
1616
1806
|
float normalDotLight = clamp(abs(dot(normalize(normal), normalize(lightDirection))), 0.0, 1.0);
|
|
1617
|
-
// Same per-sample, tangent-scaled slope bias as the directional and atlas paths. These
|
|
1618
|
-
// cubemap-face variants inline the sample fetch, but they share the identical acne
|
|
1619
|
-
// mechanism: a centre-only, (1 - N.L)-scaled bias under-compensates every outer tap.
|
|
1620
1807
|
float slopeTangent = min(sqrt(max(1.0 - normalDotLight * normalDotLight, 0.0)) / max(normalDotLight, 0.05), 8.0);
|
|
1621
1808
|
float slopeTexelBias = slopeTangent * u_pointShadowSlopeBias * max(u_pointShadowTexelSize.x, u_pointShadowTexelSize.y);
|
|
1622
1809
|
float projectedDepth = projected.z * 0.5 + 0.5;
|
|
@@ -1635,6 +1822,44 @@ float a3dPointShadowFactor(vec3 worldPosition, vec3 normal, vec3 lightDirection)
|
|
|
1635
1822
|
float occlusion = totalWeight > 0.0 ? shadowed / totalWeight : 0.0;
|
|
1636
1823
|
return mix(1.0, 1.0 - occlusion, clamp(u_pointShadowStrength, 0.0, 1.0));
|
|
1637
1824
|
}
|
|
1825
|
+
float a3dSpotShadowFactor(vec3 worldPosition, vec3 normal, vec3 lightDirection) {
|
|
1826
|
+
if (u_spotShadowMapEnabled < 0.5) return 1.0;
|
|
1827
|
+
vec3 toFragment = worldPosition - u_spotShadowLightPosition;
|
|
1828
|
+
float distanceToLight = max(length(toFragment), 0.0001);
|
|
1829
|
+
if (distanceToLight > u_spotShadowRange) return 1.0;
|
|
1830
|
+
vec3 coneAxis = u_spotShadowLightDirection / max(length(u_spotShadowLightDirection), 0.0001);
|
|
1831
|
+
if (dot(toFragment / distanceToLight, coneAxis) < cos(u_spotShadowCone.x)) return 1.0;
|
|
1832
|
+
vec4 lightPosition = u_spotShadowMatrix * vec4(worldPosition, 1.0);
|
|
1833
|
+
vec3 projected = lightPosition.xyz / max(lightPosition.w, 0.0001);
|
|
1834
|
+
vec2 uv = projected.xy * 0.5 + 0.5;
|
|
1835
|
+
if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) return 1.0;
|
|
1836
|
+
vec3 receiverNormal = normalize(normal);
|
|
1837
|
+
vec3 receiverLightDirection = lightDirection / max(length(lightDirection), 0.0001);
|
|
1838
|
+
float normalDotLight = clamp(abs(dot(receiverNormal, receiverLightDirection)), 0.0, 1.0);
|
|
1839
|
+
float slopeTangent = min(sqrt(max(1.0 - normalDotLight * normalDotLight, 0.0)) / max(normalDotLight, 0.05), 8.0);
|
|
1840
|
+
float slopeTexelBias = slopeTangent * u_spotShadowSlopeBias * max(u_spotShadowTexelSize.x, u_spotShadowTexelSize.y);
|
|
1841
|
+
float projectedDepth = projected.z * 0.5 + 0.5;
|
|
1842
|
+
float shadowed = 0.0;
|
|
1843
|
+
float totalWeight = 0.0;
|
|
1844
|
+
int sampleCount = clamp(int(u_spotShadowPcfSampleCount), 1, 32);
|
|
1845
|
+
for (int i = 0; i < 32; ++i) {
|
|
1846
|
+
if (i >= sampleCount) break;
|
|
1847
|
+
vec4 sampleData = u_spotShadowPcfSamples[i];
|
|
1848
|
+
float weight = max(sampleData.z, 0.0);
|
|
1849
|
+
vec2 offset = sampleData.xy * u_spotShadowTexelSize;
|
|
1850
|
+
float storedDepth = texture(u_spotShadowMapTexture, uv + offset).r;
|
|
1851
|
+
float sampleTexelDistance = max(1.0, length(sampleData.xy));
|
|
1852
|
+
float receiverDepth = projectedDepth - u_spotShadowBias - slopeTexelBias * sampleTexelDistance;
|
|
1853
|
+
shadowed += (receiverDepth > storedDepth ? 1.0 : 0.0) * weight;
|
|
1854
|
+
totalWeight += weight;
|
|
1855
|
+
}
|
|
1856
|
+
float occlusion = totalWeight > 0.0 ? shadowed / totalWeight : 0.0;
|
|
1857
|
+
return mix(1.0, 1.0 - occlusion, clamp(u_spotShadowStrength, 0.0, 1.0));
|
|
1858
|
+
}
|
|
1859
|
+
float a3dResolveSpotShadowOverride(float baseFactor, float kind, float shadowFlag, vec3 worldPosition, vec3 normal, vec3 lightDirection) {
|
|
1860
|
+
float spotGate = step(1.5, kind) * (1.0 - step(2.5, kind)) * step(0.5, u_spotShadowMapEnabled) * step(0.5, shadowFlag);
|
|
1861
|
+
return mix(baseFactor, a3dSpotShadowFactor(worldPosition, normal, lightDirection), spotGate);
|
|
1862
|
+
}
|
|
1638
1863
|
vec2 a3dEnvironmentEquirectUv(vec3 direction, float rotation) {
|
|
1639
1864
|
vec3 d = normalize(direction);
|
|
1640
1865
|
float u = atan(d.z, d.x) / 6.28318530718 + 0.5 + rotation;
|
|
@@ -1680,16 +1905,11 @@ vec3 a3dPbrEnvironmentDiffuseInput(vec3 normal) {
|
|
|
1680
1905
|
float horizonBlend = 1.0 - abs(normal.y);
|
|
1681
1906
|
vec3 proceduralDiffuse = mix(u_environmentGroundColor, u_environmentSkyColor, skyBlend);
|
|
1682
1907
|
proceduralDiffuse = mix(proceduralDiffuse, u_environmentHorizonColor, clamp(horizonBlend, 0.0, 1.0) * 0.55);
|
|
1683
|
-
// The ambient term must be added to the procedural contribution, not replaced by it. A mix
|
|
1684
|
-
// here discarded u_environmentColor * u_environmentIntensity entirely whenever a procedural
|
|
1685
|
-
// map was present, which is the normal case: raising ambient intensity from 0.18 to 3.0 on
|
|
1686
|
-
// the product-turntable kit produced a byte-identical frame. Ambient and a sky gradient are
|
|
1687
|
-
// separate physical contributions, so they sum.
|
|
1688
1908
|
vec3 environmentDiffuse = ambientEnvironment + proceduralDiffuse * u_environmentMapIntensity * proceduralEnvironmentWeight;
|
|
1689
1909
|
float sampledEnvironmentWeight = step(0.0001, u_environmentMapTextureEnabled * u_environmentMapTextureIntensity);
|
|
1690
1910
|
float diffuseEnvironmentLod = max(u_environmentMapTextureMipCount - 1.0, 0.0);
|
|
1691
1911
|
vec3 sampledDiffuse = a3dPbrDecodeEnvironmentSample(a3dPbrEnvironmentSampleRaw(normal, diffuseEnvironmentLod));
|
|
1692
|
-
return mix(environmentDiffuse, ambientEnvironment + sampledDiffuse * u_environmentMapTextureIntensity, sampledEnvironmentWeight);
|
|
1912
|
+
return mix(environmentDiffuse, ambientEnvironment + sampledDiffuse * u_environmentMapTextureIntensity * u_materialEnvironmentIntensity, sampledEnvironmentWeight);
|
|
1693
1913
|
}
|
|
1694
1914
|
vec3 a3dPbrEnvironmentSpecularInput(vec3 normal, vec3 viewDirection, float roughness) {
|
|
1695
1915
|
float proceduralEnvironmentWeight = step(0.0001, u_environmentMapIntensity);
|
|
@@ -1704,7 +1924,7 @@ vec3 a3dPbrEnvironmentSpecularInput(vec3 normal, vec3 viewDirection, float rough
|
|
|
1704
1924
|
vec3 sampledSpecular = a3dPbrBoundHdrSpecularRadiance(a3dPbrDecodeEnvironmentSample(a3dPbrEnvironmentSampleRaw(reflectionDirection, environmentLod)));
|
|
1705
1925
|
float nDotV = clamp(dot(normal, viewDirection), 0.0, 1.0);
|
|
1706
1926
|
sampledSpecular = a3dPbrClampSampledSpecularEdgeEnergy(sampledSpecular, nDotV, clampedRoughness);
|
|
1707
|
-
sampledSpecular *= u_environmentMapTextureSpecularIntensity * sampledEnvironmentWeight * mix(0.84, 0.58, clampedRoughness);
|
|
1927
|
+
sampledSpecular *= u_environmentMapTextureSpecularIntensity * u_materialEnvironmentIntensity * sampledEnvironmentWeight * mix(0.84, 0.58, clampedRoughness);
|
|
1708
1928
|
return proceduralSpecular + sampledSpecular;
|
|
1709
1929
|
}
|
|
1710
1930
|
vec2 a3dPbrEnvironmentBrdfInput(vec3 normal, vec3 viewDirection, float roughness) {
|
|
@@ -1712,10 +1932,16 @@ vec2 a3dPbrEnvironmentBrdfInput(vec3 normal, vec3 viewDirection, float roughness
|
|
|
1712
1932
|
vec2 lut = texture(u_environmentBrdfLutTexture, vec2(nDotV, clamp(roughness, 0.0, 1.0))).rg;
|
|
1713
1933
|
return mix(vec2(1.0, 0.0), lut, step(0.0001, u_environmentBrdfLutEnabled));
|
|
1714
1934
|
}
|
|
1935
|
+
vec3 a3dLinearToSrgb(vec3 linear) {
|
|
1936
|
+
vec3 clamped = max(linear, vec3(0.0));
|
|
1937
|
+
vec3 low = clamped * 12.92;
|
|
1938
|
+
vec3 high = 1.055 * pow(clamped, vec3(1.0 / 2.4)) - 0.055;
|
|
1939
|
+
return mix(low, high, step(vec3(0.0031308), clamped));
|
|
1940
|
+
}
|
|
1715
1941
|
vec3 a3dPbrEncodeOutput(vec3 linearColor) {
|
|
1716
1942
|
vec3 color = max(linearColor, vec3(0.0));
|
|
1717
1943
|
vec3 filmic = clamp((color * (2.51 * color + 0.03)) / (color * (2.43 * color + 0.59) + 0.14), vec3(0.0), vec3(1.0));
|
|
1718
|
-
vec3 srgb =
|
|
1944
|
+
vec3 srgb = a3dLinearToSrgb(filmic);
|
|
1719
1945
|
return mix(color, srgb, step(0.5, u_outputColorSpace));
|
|
1720
1946
|
}
|
|
1721
1947
|
void main() {
|
|
@@ -1776,7 +2002,7 @@ void main() {
|
|
|
1776
2002
|
float inner = cos(spotShadowLayer.x * max(1.0 - spotShadowLayer.y, 0.001));
|
|
1777
2003
|
attenuation *= smoothstep(outer, inner, cone);
|
|
1778
2004
|
}
|
|
1779
|
-
float shadowFactor = mix(1.0, kind > 0.5 && kind < 1.5 ? a3dPointShadowFactor(v_worldPosition, mappedNormal, lightDirection) : a3dForwardShadowFactor(v_worldPosition, mappedNormal, lightDirection), step(0.5, spotShadowLayer.z));
|
|
2005
|
+
float shadowFactor = a3dResolveSpotShadowOverride(mix(1.0, kind > 0.5 && kind < 1.5 ? a3dPointShadowFactor(v_worldPosition, mappedNormal, lightDirection) : a3dForwardShadowFactor(v_worldPosition, mappedNormal, lightDirection), step(0.5, spotShadowLayer.z)), kind, spotShadowLayer.z, v_worldPosition, mappedNormal, lightDirection);
|
|
1780
2006
|
shaded += a3dPbrDirectLight(mappedNormal, viewDirection, lightDirection, colorIntensity.rgb, colorIntensity.a * attenuation * shadowFactor, materialBase, u_metallic, u_roughness, u_specularFactor, u_specularColorFactor);
|
|
1781
2007
|
}
|
|
1782
2008
|
float alpha = u_baseColor.a * v_vertexColor.a;
|
|
@@ -1790,13 +2016,16 @@ void main() {
|
|
|
1790
2016
|
name: DEFAULT_TEXTURED_PBR_SHADER_NAME,
|
|
1791
2017
|
marker: DEFAULT_TEXTURED_PBR_SHADER_MARKER,
|
|
1792
2018
|
variants: [
|
|
2019
|
+
{ name: DEFAULT_TEXTURED_PBR_EXTENSION_ATLAS_VARIANT, defines: { A3D_PBR_EXTENSION_ATLAS: true, A3D_PBR_CLEARCOAT_TEXTURES: true, A3D_PBR_SPECULAR_SHEEN_ANISOTROPY_TEXTURES: true, A3D_PBR_IRIDESCENCE_TEXTURES: true, A3D_PBR_DISABLE_TRANSMISSION_BACKDROP: true, A3D_PBR_DISABLE_CLUSTERED_LIGHTING: true } },
|
|
2020
|
+
{ name: DEFAULT_TEXTURED_PBR_CLEARCOAT_SHEEN_ANISOTROPY_TEXTURES_VARIANT, defines: { A3D_PBR_CLEARCOAT_TEXTURES: true, A3D_PBR_SPECULAR_SHEEN_ANISOTROPY_TEXTURES: true, A3D_PBR_DISABLE_TRANSMISSION_BACKDROP: true, A3D_PBR_DISABLE_CLUSTERED_LIGHTING: true, A3D_PBR_NO_SPOT_SHADOW: true } },
|
|
2021
|
+
{ name: DEFAULT_TEXTURED_PBR_CLEARCOAT_IRIDESCENCE_TEXTURES_VARIANT, defines: { A3D_PBR_CLEARCOAT_TEXTURES: true, A3D_PBR_IRIDESCENCE_TEXTURES: true, A3D_PBR_DISABLE_TRANSMISSION_BACKDROP: true, A3D_PBR_DISABLE_CLUSTERED_LIGHTING: true } },
|
|
1793
2022
|
{ name: DEFAULT_TEXTURED_PBR_CLEARCOAT_TEXTURES_VARIANT, defines: { A3D_PBR_CLEARCOAT_TEXTURES: true, A3D_PBR_DISABLE_TRANSMISSION_BACKDROP: true, A3D_PBR_DISABLE_CLUSTERED_LIGHTING: true } },
|
|
1794
2023
|
{ name: DEFAULT_TEXTURED_PBR_TRANSMISSION_VOLUME_TEXTURES_VARIANT, defines: { A3D_PBR_TRANSMISSION_VOLUME_TEXTURES: true, A3D_PBR_DISABLE_TRANSMISSION_BACKDROP: true, A3D_PBR_DISABLE_CLUSTERED_LIGHTING: true } },
|
|
1795
2024
|
{ name: DEFAULT_TEXTURED_PBR_SPECULAR_SHEEN_ANISOTROPY_TEXTURES_VARIANT, defines: { A3D_PBR_SPECULAR_TEXTURES: true, A3D_PBR_SPECULAR_SHEEN_ANISOTROPY_TEXTURES: true, A3D_PBR_DISABLE_TRANSMISSION_BACKDROP: true, A3D_PBR_DISABLE_CLUSTERED_LIGHTING: true } },
|
|
1796
2025
|
{ name: DEFAULT_TEXTURED_PBR_IRIDESCENCE_TEXTURES_VARIANT, defines: { A3D_PBR_IRIDESCENCE_TEXTURES: true, A3D_PBR_DISABLE_TRANSMISSION_BACKDROP: true, A3D_PBR_DISABLE_CLUSTERED_LIGHTING: true } },
|
|
1797
|
-
{ name: DEFAULT_TEXTURED_PBR_CLEARCOAT_TRANSMISSION_VOLUME_TEXTURES_VARIANT, defines: { A3D_PBR_CLEARCOAT_TEXTURES: true, A3D_PBR_TRANSMISSION_VOLUME_TEXTURES: true, A3D_PBR_DISABLE_TRANSMISSION_BACKDROP: true, A3D_PBR_DISABLE_CLUSTERED_LIGHTING: true } },
|
|
2026
|
+
{ name: DEFAULT_TEXTURED_PBR_CLEARCOAT_TRANSMISSION_VOLUME_TEXTURES_VARIANT, defines: { A3D_PBR_CLEARCOAT_TEXTURES: true, A3D_PBR_TRANSMISSION_VOLUME_TEXTURES: true, A3D_PBR_DISABLE_TRANSMISSION_BACKDROP: true, A3D_PBR_DISABLE_CLUSTERED_LIGHTING: true, A3D_PBR_NO_SPOT_SHADOW: true } },
|
|
1798
2027
|
{ name: DEFAULT_TEXTURED_PBR_CLEARCOAT_SPECULAR_TEXTURES_VARIANT, defines: { A3D_PBR_CLEARCOAT_TEXTURES: true, A3D_PBR_SPECULAR_TEXTURES: true, A3D_PBR_DISABLE_TRANSMISSION_BACKDROP: true, A3D_PBR_DISABLE_CLUSTERED_LIGHTING: true } },
|
|
1799
|
-
{ name: DEFAULT_TEXTURED_PBR_SPECULAR_SHEEN_ANISOTROPY_IRIDESCENCE_TEXTURES_VARIANT, defines: { A3D_PBR_SPECULAR_TEXTURES: true, A3D_PBR_SPECULAR_SHEEN_ANISOTROPY_TEXTURES: true, A3D_PBR_IRIDESCENCE_TEXTURES: true, A3D_PBR_DISABLE_TRANSMISSION_BACKDROP: true, A3D_PBR_DISABLE_CLUSTERED_LIGHTING: true } }
|
|
2028
|
+
{ name: DEFAULT_TEXTURED_PBR_SPECULAR_SHEEN_ANISOTROPY_IRIDESCENCE_TEXTURES_VARIANT, defines: { A3D_PBR_SPECULAR_TEXTURES: true, A3D_PBR_SPECULAR_SHEEN_ANISOTROPY_TEXTURES: true, A3D_PBR_IRIDESCENCE_TEXTURES: true, A3D_PBR_DISABLE_TRANSMISSION_BACKDROP: true, A3D_PBR_DISABLE_CLUSTERED_LIGHTING: true, A3D_PBR_NO_SPOT_SHADOW: true } },
|
|
1800
2029
|
],
|
|
1801
2030
|
vertex: `#version 300 es
|
|
1802
2031
|
// ${DEFAULT_TEXTURED_PBR_SHADER_MARKER}
|
|
@@ -1807,9 +2036,17 @@ layout(location = 2) in vec2 a_uv;
|
|
|
1807
2036
|
layout(location = 3) in vec4 a_tangent;
|
|
1808
2037
|
layout(location = 4) in vec4 a_color;
|
|
1809
2038
|
layout(location = 7) in vec2 a_uv1;
|
|
2039
|
+
layout(location = 8) in vec4 a_instanceMatrix0;
|
|
2040
|
+
layout(location = 9) in vec4 a_instanceMatrix1;
|
|
2041
|
+
layout(location = 10) in vec4 a_instanceMatrix2;
|
|
2042
|
+
layout(location = 11) in vec4 a_instanceMatrix3;
|
|
2043
|
+
layout(location = 12) in vec4 a_instanceColor;
|
|
1810
2044
|
uniform mat4 u_modelViewProjection;
|
|
1811
2045
|
uniform mat4 u_modelMatrix;
|
|
1812
2046
|
uniform mat4 u_normalMatrix;
|
|
2047
|
+
uniform mat4 u_instanceMatrices[64];
|
|
2048
|
+
uniform float u_instanceCount;
|
|
2049
|
+
uniform float u_instanceAttributeMode;
|
|
1813
2050
|
out vec3 v_normal;
|
|
1814
2051
|
out vec4 v_tangent;
|
|
1815
2052
|
out vec3 v_worldPosition;
|
|
@@ -1819,11 +2056,23 @@ out vec4 v_vertexColor;
|
|
|
1819
2056
|
void main() {
|
|
1820
2057
|
v_uv = a_uv;
|
|
1821
2058
|
v_uv1 = a_uv1;
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
2059
|
+
if (u_instanceCount > 0.5) {
|
|
2060
|
+
int instanceIndex = clamp(gl_InstanceID, 0, max(int(u_instanceCount) - 1, 0));
|
|
2061
|
+
mat4 attributeMatrix = mat4(a_instanceMatrix0, a_instanceMatrix1, a_instanceMatrix2, a_instanceMatrix3);
|
|
2062
|
+
mat4 instanceMatrix = u_instanceAttributeMode > 0.5 ? attributeMatrix : u_instanceMatrices[instanceIndex];
|
|
2063
|
+
vec4 worldPosition = u_modelMatrix * instanceMatrix * vec4(a_position, 1.0);
|
|
2064
|
+
v_normal = mat3(u_normalMatrix) * transpose(inverse(mat3(instanceMatrix))) * a_normal;
|
|
2065
|
+
v_tangent = vec4(mat3(u_normalMatrix) * (mat3(instanceMatrix) * a_tangent.xyz), a_tangent.w);
|
|
2066
|
+
v_worldPosition = worldPosition.xyz;
|
|
2067
|
+
v_vertexColor = a_color * a_instanceColor;
|
|
2068
|
+
gl_Position = u_modelViewProjection * instanceMatrix * vec4(a_position, 1.0);
|
|
2069
|
+
} else {
|
|
2070
|
+
v_normal = mat3(u_normalMatrix) * a_normal;
|
|
2071
|
+
v_tangent = vec4(mat3(u_normalMatrix) * a_tangent.xyz, a_tangent.w);
|
|
2072
|
+
v_worldPosition = (u_modelMatrix * vec4(a_position, 1.0)).xyz;
|
|
2073
|
+
v_vertexColor = a_color;
|
|
2074
|
+
gl_Position = u_modelViewProjection * vec4(a_position, 1.0);
|
|
2075
|
+
}
|
|
1827
2076
|
}
|
|
1828
2077
|
`,
|
|
1829
2078
|
fragment: `#version 300 es
|
|
@@ -1837,6 +2086,7 @@ uniform float u_metallic;
|
|
|
1837
2086
|
uniform float u_roughness;
|
|
1838
2087
|
uniform vec3 u_environmentColor;
|
|
1839
2088
|
uniform float u_environmentIntensity;
|
|
2089
|
+
uniform float u_materialEnvironmentIntensity;
|
|
1840
2090
|
uniform vec3 u_environmentSkyColor;
|
|
1841
2091
|
uniform vec3 u_environmentHorizonColor;
|
|
1842
2092
|
uniform vec3 u_environmentGroundColor;
|
|
@@ -1921,6 +2171,21 @@ uniform float u_pointShadowSlopeBias;
|
|
|
1921
2171
|
uniform vec2 u_pointShadowTexelSize;
|
|
1922
2172
|
uniform float u_pointShadowPcfSampleCount;
|
|
1923
2173
|
uniform vec4 u_pointShadowPcfSamples[32];
|
|
2174
|
+
#ifndef A3D_PBR_NO_SPOT_SHADOW
|
|
2175
|
+
uniform sampler2D u_spotShadowMapTexture;
|
|
2176
|
+
uniform float u_spotShadowMapEnabled;
|
|
2177
|
+
uniform vec3 u_spotShadowLightPosition;
|
|
2178
|
+
uniform vec3 u_spotShadowLightDirection;
|
|
2179
|
+
uniform mat4 u_spotShadowMatrix;
|
|
2180
|
+
uniform vec2 u_spotShadowCone;
|
|
2181
|
+
uniform float u_spotShadowRange;
|
|
2182
|
+
uniform float u_spotShadowStrength;
|
|
2183
|
+
uniform float u_spotShadowBias;
|
|
2184
|
+
uniform float u_spotShadowSlopeBias;
|
|
2185
|
+
uniform vec2 u_spotShadowTexelSize;
|
|
2186
|
+
uniform float u_spotShadowPcfSampleCount;
|
|
2187
|
+
uniform vec4 u_spotShadowPcfSamples[32];
|
|
2188
|
+
#endif
|
|
1924
2189
|
uniform sampler2D u_baseColorTexture;
|
|
1925
2190
|
uniform float u_baseColorTextureEnabled;
|
|
1926
2191
|
uniform vec2 u_baseColorTextureOffset;
|
|
@@ -1959,14 +2224,26 @@ uniform vec2 u_occlusionTextureWrap;
|
|
|
1959
2224
|
uniform float u_occlusionStrength;
|
|
1960
2225
|
uniform float u_clearcoatNormalScale;
|
|
1961
2226
|
#ifdef A3D_PBR_CLEARCOAT_TEXTURES
|
|
2227
|
+
#ifndef A3D_PBR_EXTENSION_ATLAS
|
|
1962
2228
|
uniform sampler2D u_clearcoatTexture;
|
|
2229
|
+
#else
|
|
2230
|
+
uniform vec4 u_clearcoatAtlasRect;
|
|
2231
|
+
uniform float u_clearcoatAtlasY;
|
|
2232
|
+
uniform vec4 u_clearcoatAtlasFilter;
|
|
2233
|
+
#endif
|
|
1963
2234
|
uniform float u_clearcoatTextureEnabled;
|
|
1964
2235
|
uniform vec2 u_clearcoatTextureOffset;
|
|
1965
2236
|
uniform vec2 u_clearcoatTextureScale;
|
|
1966
2237
|
uniform float u_clearcoatTextureRotation;
|
|
1967
2238
|
uniform float u_clearcoatTextureTexCoord;
|
|
1968
2239
|
uniform vec2 u_clearcoatTextureWrap;
|
|
2240
|
+
#ifndef A3D_PBR_EXTENSION_ATLAS
|
|
1969
2241
|
uniform sampler2D u_clearcoatRoughnessTexture;
|
|
2242
|
+
#else
|
|
2243
|
+
uniform vec4 u_clearcoatRoughnessAtlasRect;
|
|
2244
|
+
uniform float u_clearcoatRoughnessAtlasY;
|
|
2245
|
+
uniform vec4 u_clearcoatRoughnessAtlasFilter;
|
|
2246
|
+
#endif
|
|
1970
2247
|
uniform float u_clearcoatRoughnessTextureEnabled;
|
|
1971
2248
|
uniform vec2 u_clearcoatRoughnessTextureOffset;
|
|
1972
2249
|
uniform vec2 u_clearcoatRoughnessTextureScale;
|
|
@@ -2035,7 +2312,13 @@ uniform vec2 u_sheenColorTextureScale;
|
|
|
2035
2312
|
uniform float u_sheenColorTextureRotation;
|
|
2036
2313
|
uniform float u_sheenColorTextureTexCoord;
|
|
2037
2314
|
uniform vec2 u_sheenColorTextureWrap;
|
|
2315
|
+
#ifndef A3D_PBR_EXTENSION_ATLAS
|
|
2038
2316
|
uniform sampler2D u_sheenRoughnessTexture;
|
|
2317
|
+
#else
|
|
2318
|
+
uniform vec4 u_sheenRoughnessAtlasRect;
|
|
2319
|
+
uniform float u_sheenRoughnessAtlasY;
|
|
2320
|
+
uniform vec4 u_sheenRoughnessAtlasFilter;
|
|
2321
|
+
#endif
|
|
2039
2322
|
uniform float u_sheenRoughnessTextureEnabled;
|
|
2040
2323
|
uniform vec2 u_sheenRoughnessTextureOffset;
|
|
2041
2324
|
uniform vec2 u_sheenRoughnessTextureScale;
|
|
@@ -2051,14 +2334,26 @@ uniform float u_anisotropyTextureTexCoord;
|
|
|
2051
2334
|
uniform vec2 u_anisotropyTextureWrap;
|
|
2052
2335
|
#endif
|
|
2053
2336
|
#ifdef A3D_PBR_IRIDESCENCE_TEXTURES
|
|
2337
|
+
#ifndef A3D_PBR_EXTENSION_ATLAS
|
|
2054
2338
|
uniform sampler2D u_iridescenceTexture;
|
|
2339
|
+
#else
|
|
2340
|
+
uniform vec4 u_iridescenceAtlasRect;
|
|
2341
|
+
uniform float u_iridescenceAtlasY;
|
|
2342
|
+
uniform vec4 u_iridescenceAtlasFilter;
|
|
2343
|
+
#endif
|
|
2055
2344
|
uniform float u_iridescenceTextureEnabled;
|
|
2056
2345
|
uniform vec2 u_iridescenceTextureOffset;
|
|
2057
2346
|
uniform vec2 u_iridescenceTextureScale;
|
|
2058
2347
|
uniform float u_iridescenceTextureRotation;
|
|
2059
2348
|
uniform float u_iridescenceTextureTexCoord;
|
|
2060
2349
|
uniform vec2 u_iridescenceTextureWrap;
|
|
2350
|
+
#ifndef A3D_PBR_EXTENSION_ATLAS
|
|
2061
2351
|
uniform sampler2D u_iridescenceThicknessTexture;
|
|
2352
|
+
#else
|
|
2353
|
+
uniform vec4 u_iridescenceThicknessAtlasRect;
|
|
2354
|
+
uniform float u_iridescenceThicknessAtlasY;
|
|
2355
|
+
uniform vec4 u_iridescenceThicknessAtlasFilter;
|
|
2356
|
+
#endif
|
|
2062
2357
|
uniform float u_iridescenceThicknessTextureEnabled;
|
|
2063
2358
|
uniform vec2 u_iridescenceThicknessTextureOffset;
|
|
2064
2359
|
uniform vec2 u_iridescenceThicknessTextureScale;
|
|
@@ -2076,6 +2371,9 @@ uniform float u_environmentFogNear;
|
|
|
2076
2371
|
uniform float u_environmentFogFar;
|
|
2077
2372
|
uniform float u_environmentFogDensity;
|
|
2078
2373
|
uniform float u_environmentFogHeightFalloff;
|
|
2374
|
+
uniform float u_volumetricIntensity;
|
|
2375
|
+
uniform vec3 u_volumetricLightDirection;
|
|
2376
|
+
uniform vec3 u_volumetricLightColor;
|
|
2079
2377
|
uniform float u_environmentFogHeightReference;
|
|
2080
2378
|
uniform float u_environmentFogMaxOpacity;
|
|
2081
2379
|
in vec3 v_normal;
|
|
@@ -2110,10 +2408,16 @@ vec2 a3dTexturedPbrWrapUv(vec2 uv, vec2 wrapMode) {
|
|
|
2110
2408
|
a3dTexturedPbrWrapCoordinate(uv.y, wrapMode.y)
|
|
2111
2409
|
);
|
|
2112
2410
|
}
|
|
2411
|
+
vec3 a3dTexturedPbrEncodeLinearToSrgb(vec3 linear) {
|
|
2412
|
+
vec3 clamped = max(linear, vec3(0.0));
|
|
2413
|
+
vec3 low = clamped * 12.92;
|
|
2414
|
+
vec3 high = 1.055 * pow(clamped, vec3(1.0 / 2.4)) - 0.055;
|
|
2415
|
+
return mix(low, high, step(vec3(0.0031308), clamped));
|
|
2416
|
+
}
|
|
2113
2417
|
vec3 a3dTexturedPbrEncodeOutput(vec3 linearColor) {
|
|
2114
2418
|
vec3 color = max(linearColor, vec3(0.0));
|
|
2115
2419
|
vec3 filmic = clamp((color * (2.51 * color + 0.03)) / (color * (2.43 * color + 0.59) + 0.14), vec3(0.0), vec3(1.0));
|
|
2116
|
-
vec3 srgb =
|
|
2420
|
+
vec3 srgb = a3dTexturedPbrEncodeLinearToSrgb(filmic);
|
|
2117
2421
|
return mix(color, srgb, step(0.5, u_outputColorSpace));
|
|
2118
2422
|
}
|
|
2119
2423
|
vec3 a3dTexturedPbrDecodeSrgb(vec3 encodedColor) {
|
|
@@ -2158,15 +2462,6 @@ float a3dTexturedPbrShadowFactor(vec3 worldPosition, vec3 normal, vec3 lightDire
|
|
|
2158
2462
|
vec3 receiverNormal = normalize(normal);
|
|
2159
2463
|
vec3 receiverLightDirection = lightDirection / max(length(lightDirection), 0.0001);
|
|
2160
2464
|
float normalDotLight = clamp(abs(dot(receiverNormal, receiverLightDirection)), 0.0, 1.0);
|
|
2161
|
-
// Slope-scaled depth bias must be evaluated per PCF sample, not once for the kernel
|
|
2162
|
-
// centre. A sample offset N texels away on a receiver sloped relative to the light sees a
|
|
2163
|
-
// depth difference proportional to N, so a centre-only bias under-compensates every outer
|
|
2164
|
-
// tap and the receiver shadows itself. Scaling by each sample's own texel distance keeps
|
|
2165
|
-
// wide kernels acne-free without inflating the constant bias into peter-panning.
|
|
2166
|
-
// The depth gradient across one shadow texel is tan(angle between receiver normal and
|
|
2167
|
-
// light), not (1 - N.L). The linear form collapses toward zero far faster than the real
|
|
2168
|
-
// gradient grows, so it under-biases exactly the grazing angles that need the most
|
|
2169
|
-
// compensation. Clamped so a near-perpendicular receiver cannot demand unbounded bias.
|
|
2170
2465
|
float slopeTangent = min(sqrt(max(1.0 - normalDotLight * normalDotLight, 0.0)) / max(normalDotLight, 0.05), 8.0);
|
|
2171
2466
|
float slopeTexelBias = slopeTangent * u_shadowMapSlopeBias * max(u_shadowMapTexelSize.x, u_shadowMapTexelSize.y);
|
|
2172
2467
|
float projectedDepth = projected.z * 0.5 + 0.5;
|
|
@@ -2199,9 +2494,6 @@ float a3dTexturedPbrPointShadowFactor(vec3 worldPosition, vec3 normal, vec3 ligh
|
|
|
2199
2494
|
vec4 rect = u_pointShadowFaceRects[faceIndex];
|
|
2200
2495
|
vec2 uv = rect.xy + localUv * rect.zw;
|
|
2201
2496
|
float normalDotLight = clamp(abs(dot(normalize(normal), normalize(lightDirection))), 0.0, 1.0);
|
|
2202
|
-
// Same per-sample, tangent-scaled slope bias as the directional and atlas paths. These
|
|
2203
|
-
// cubemap-face variants inline the sample fetch, but they share the identical acne
|
|
2204
|
-
// mechanism: a centre-only, (1 - N.L)-scaled bias under-compensates every outer tap.
|
|
2205
2497
|
float slopeTangent = min(sqrt(max(1.0 - normalDotLight * normalDotLight, 0.0)) / max(normalDotLight, 0.05), 8.0);
|
|
2206
2498
|
float slopeTexelBias = slopeTangent * u_pointShadowSlopeBias * max(u_pointShadowTexelSize.x, u_pointShadowTexelSize.y);
|
|
2207
2499
|
float projectedDepth = projected.z * 0.5 + 0.5;
|
|
@@ -2220,6 +2512,46 @@ float a3dTexturedPbrPointShadowFactor(vec3 worldPosition, vec3 normal, vec3 ligh
|
|
|
2220
2512
|
float occlusion = totalWeight > 0.0 ? shadowed / totalWeight : 0.0;
|
|
2221
2513
|
return mix(1.0, 1.0 - occlusion, clamp(u_pointShadowStrength, 0.0, 1.0));
|
|
2222
2514
|
}
|
|
2515
|
+
#ifndef A3D_PBR_NO_SPOT_SHADOW
|
|
2516
|
+
float a3dTexturedPbrSpotShadowFactor(vec3 worldPosition, vec3 normal, vec3 lightDirection) {
|
|
2517
|
+
if (u_spotShadowMapEnabled < 0.5) return 1.0;
|
|
2518
|
+
vec3 toFragment = worldPosition - u_spotShadowLightPosition;
|
|
2519
|
+
float distanceToLight = max(length(toFragment), 0.0001);
|
|
2520
|
+
if (distanceToLight > u_spotShadowRange) return 1.0;
|
|
2521
|
+
vec3 coneAxis = u_spotShadowLightDirection / max(length(u_spotShadowLightDirection), 0.0001);
|
|
2522
|
+
if (dot(toFragment / distanceToLight, coneAxis) < cos(u_spotShadowCone.x)) return 1.0;
|
|
2523
|
+
vec4 lightPosition = u_spotShadowMatrix * vec4(worldPosition, 1.0);
|
|
2524
|
+
vec3 projected = lightPosition.xyz / max(lightPosition.w, 0.0001);
|
|
2525
|
+
vec2 uv = projected.xy * 0.5 + 0.5;
|
|
2526
|
+
if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) return 1.0;
|
|
2527
|
+
vec3 receiverNormal = normalize(normal);
|
|
2528
|
+
vec3 receiverLightDirection = lightDirection / max(length(lightDirection), 0.0001);
|
|
2529
|
+
float normalDotLight = clamp(abs(dot(receiverNormal, receiverLightDirection)), 0.0, 1.0);
|
|
2530
|
+
float slopeTangent = min(sqrt(max(1.0 - normalDotLight * normalDotLight, 0.0)) / max(normalDotLight, 0.05), 8.0);
|
|
2531
|
+
float slopeTexelBias = slopeTangent * u_spotShadowSlopeBias * max(u_spotShadowTexelSize.x, u_spotShadowTexelSize.y);
|
|
2532
|
+
float projectedDepth = projected.z * 0.5 + 0.5;
|
|
2533
|
+
float shadowed = 0.0;
|
|
2534
|
+
float totalWeight = 0.0;
|
|
2535
|
+
int sampleCount = clamp(int(u_spotShadowPcfSampleCount), 1, 32);
|
|
2536
|
+
for (int i = 0; i < 32; ++i) {
|
|
2537
|
+
if (i >= sampleCount) break;
|
|
2538
|
+
vec4 sampleData = u_spotShadowPcfSamples[i];
|
|
2539
|
+
float weight = max(sampleData.z, 0.0);
|
|
2540
|
+
vec2 offset = sampleData.xy * u_spotShadowTexelSize;
|
|
2541
|
+
float storedDepth = texture(u_spotShadowMapTexture, uv + offset).r;
|
|
2542
|
+
float sampleTexelDistance = max(1.0, length(sampleData.xy));
|
|
2543
|
+
float receiverDepth = projectedDepth - u_spotShadowBias - slopeTexelBias * sampleTexelDistance;
|
|
2544
|
+
shadowed += (receiverDepth > storedDepth ? 1.0 : 0.0) * weight;
|
|
2545
|
+
totalWeight += weight;
|
|
2546
|
+
}
|
|
2547
|
+
float occlusion = totalWeight > 0.0 ? shadowed / totalWeight : 0.0;
|
|
2548
|
+
return mix(1.0, 1.0 - occlusion, clamp(u_spotShadowStrength, 0.0, 1.0));
|
|
2549
|
+
}
|
|
2550
|
+
float a3dTexturedPbrResolveSpotShadowOverride(float baseFactor, float kind, float shadowFlag, vec3 worldPosition, vec3 normal, vec3 lightDirection) {
|
|
2551
|
+
float spotGate = step(1.5, kind) * (1.0 - step(2.5, kind)) * step(0.5, u_spotShadowMapEnabled) * step(0.5, shadowFlag);
|
|
2552
|
+
return mix(baseFactor, a3dTexturedPbrSpotShadowFactor(worldPosition, normal, lightDirection), spotGate);
|
|
2553
|
+
}
|
|
2554
|
+
#endif
|
|
2223
2555
|
vec2 a3dTexturedPbrEnvironmentUv(vec3 direction, float rotation) {
|
|
2224
2556
|
vec3 d = normalize(direction);
|
|
2225
2557
|
float u = atan(d.z, d.x) / 6.28318530718 + 0.5 + rotation;
|
|
@@ -2259,16 +2591,11 @@ vec3 a3dTexturedPbrEnvironmentDiffuseInput(vec3 normal) {
|
|
|
2259
2591
|
float horizonBlend = 1.0 - abs(normal.y);
|
|
2260
2592
|
vec3 proceduralDiffuse = mix(u_environmentGroundColor, u_environmentSkyColor, skyBlend);
|
|
2261
2593
|
proceduralDiffuse = mix(proceduralDiffuse, u_environmentHorizonColor, clamp(horizonBlend, 0.0, 1.0) * 0.55);
|
|
2262
|
-
// The ambient term must be added to the procedural contribution, not replaced by it. A mix
|
|
2263
|
-
// here discarded u_environmentColor * u_environmentIntensity entirely whenever a procedural
|
|
2264
|
-
// map was present, which is the normal case: raising ambient intensity from 0.18 to 3.0 on
|
|
2265
|
-
// the product-turntable kit produced a byte-identical frame. Ambient and a sky gradient are
|
|
2266
|
-
// separate physical contributions, so they sum.
|
|
2267
2594
|
vec3 environmentDiffuse = ambientEnvironment + proceduralDiffuse * u_environmentMapIntensity * proceduralEnvironmentWeight;
|
|
2268
2595
|
float sampledEnvironmentWeight = step(0.0001, u_environmentMapTextureEnabled * u_environmentMapTextureIntensity);
|
|
2269
2596
|
float diffuseEnvironmentLod = max(u_environmentMapTextureMipCount - 1.0, 0.0);
|
|
2270
2597
|
vec3 sampledDiffuse = a3dTexturedPbrDecodeEnvironmentSample(a3dTexturedPbrEnvironmentSampleRaw(normal, diffuseEnvironmentLod));
|
|
2271
|
-
return mix(environmentDiffuse, ambientEnvironment + sampledDiffuse * u_environmentMapTextureIntensity, sampledEnvironmentWeight);
|
|
2598
|
+
return mix(environmentDiffuse, ambientEnvironment + sampledDiffuse * u_environmentMapTextureIntensity * u_materialEnvironmentIntensity, sampledEnvironmentWeight);
|
|
2272
2599
|
}
|
|
2273
2600
|
vec3 a3dTexturedPbrEnvironmentSpecularInput(vec3 normal, vec3 viewDirection, float roughness) {
|
|
2274
2601
|
float materialEnvironmentSpecularScale = clamp(u_materialEnvironmentSpecularScale, 0.0, 1.0);
|
|
@@ -2278,11 +2605,6 @@ vec3 a3dTexturedPbrEnvironmentSpecularInput(vec3 normal, vec3 viewDirection, flo
|
|
|
2278
2605
|
float clampedRoughness = clamp(roughness, 0.0, 1.0);
|
|
2279
2606
|
float nDotV = clamp(dot(normal, viewDirection), 0.0, 1.0);
|
|
2280
2607
|
float reflectionBand = pow(clamp(reflectionDirection.y * 0.5 + 0.5, 0.0, 1.0), mix(18.0, 2.0, clampedRoughness));
|
|
2281
|
-
// Keep the procedural environment from becoming a uniform white veil on
|
|
2282
|
-
// saturated textured base colors. A high roughness floor spread neutral
|
|
2283
|
-
// specular over every fragment, while image-based lighting and Three.js keep
|
|
2284
|
-
// the strongest neutral energy in reflection bands and glancing highlights.
|
|
2285
|
-
// The lower floor preserves ambient readability without erasing texture chroma.
|
|
2286
2608
|
float roughEnvironmentFloor = mix(0.012, 0.16, clampedRoughness);
|
|
2287
2609
|
float proceduralSpecularResponse = max(reflectionBand, roughEnvironmentFloor);
|
|
2288
2610
|
float horizonStripe = pow(clamp(1.0 - abs(reflectionDirection.y), 0.0, 1.0), mix(14.0, 3.0, clampedRoughness));
|
|
@@ -2297,18 +2619,30 @@ vec3 a3dTexturedPbrEnvironmentSpecularInput(vec3 normal, vec3 viewDirection, flo
|
|
|
2297
2619
|
float environmentLod = clampedRoughness * max(u_environmentMapTextureMipCount - 1.0, 0.0);
|
|
2298
2620
|
vec3 sampledSpecular = a3dTexturedPbrBoundHdrSpecularRadiance(a3dTexturedPbrDecodeEnvironmentSample(a3dTexturedPbrEnvironmentSampleRaw(reflectionDirection, environmentLod)));
|
|
2299
2621
|
sampledSpecular = a3dTexturedPbrClampSampledSpecularEdgeEnergy(sampledSpecular, nDotV, clampedRoughness);
|
|
2300
|
-
sampledSpecular *= u_environmentMapTextureSpecularIntensity * sampledEnvironmentWeight * mix(1.1, 0.65, clampedRoughness);
|
|
2622
|
+
sampledSpecular *= u_environmentMapTextureSpecularIntensity * u_materialEnvironmentIntensity * sampledEnvironmentWeight * mix(1.1, 0.65, clampedRoughness);
|
|
2301
2623
|
float proceduralSpecularScale = materialFiniteSpecularScale;
|
|
2302
2624
|
float sampledSpecularScale = materialEnvironmentSpecularScale;
|
|
2303
2625
|
return proceduralSpecular * proceduralSpecularScale + sampledSpecular * sampledSpecularScale;
|
|
2304
2626
|
}
|
|
2305
|
-
vec3
|
|
2306
|
-
float
|
|
2307
|
-
|
|
2308
|
-
float
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2627
|
+
vec3 a3dTexturedPbrThinFilmFresnel(vec3 substrateF0, float filmIor, float thickness, float cosine) {
|
|
2628
|
+
float c1 = clamp(cosine, 0.0001, 1.0);
|
|
2629
|
+
if (thickness <= 0.0) return a3dFresnelSchlick(substrateF0, c1);
|
|
2630
|
+
float n2 = max(filmIor, 1.0001);
|
|
2631
|
+
vec3 rootF0 = sqrt(clamp(substrateF0, vec3(0.0), vec3(0.98)));
|
|
2632
|
+
vec3 n3 = (vec3(1.0) + rootF0) / max(vec3(1.0) - rootF0, vec3(0.0001));
|
|
2633
|
+
float sinSquared = 1.0 - c1 * c1;
|
|
2634
|
+
float c2 = sqrt(max(0.0, 1.0 - sinSquared / (n2 * n2)));
|
|
2635
|
+
vec3 c3 = sqrt(max(vec3(0.0), vec3(1.0) - sinSquared / (n3 * n3)));
|
|
2636
|
+
float r12s = (c1 - n2 * c2) / max(c1 + n2 * c2, 0.0001);
|
|
2637
|
+
float r12p = (n2 * c1 - c2) / max(n2 * c1 + c2, 0.0001);
|
|
2638
|
+
vec3 r23s = (n2 * c2 - n3 * c3) / max(n2 * c2 + n3 * c3, vec3(0.0001));
|
|
2639
|
+
vec3 r23p = (n3 * c2 - n2 * c3) / max(n3 * c2 + n2 * c3, vec3(0.0001));
|
|
2640
|
+
vec3 phase = 4.0 * A3D_PI * n2 * max(thickness, 0.0) * c2 / vec3(650.0, 510.0, 475.0);
|
|
2641
|
+
vec3 crossS = 2.0 * r12s * r23s * cos(phase);
|
|
2642
|
+
vec3 crossP = 2.0 * r12p * r23p * cos(phase);
|
|
2643
|
+
vec3 Rs = (r12s * r12s + r23s * r23s + crossS) / max(vec3(1.0) + r12s * r12s * r23s * r23s + crossS, vec3(0.0001));
|
|
2644
|
+
vec3 Rp = (r12p * r12p + r23p * r23p + crossP) / max(vec3(1.0) + r12p * r12p * r23p * r23p + crossP, vec3(0.0001));
|
|
2645
|
+
return clamp((Rs + Rp) * 0.5, vec3(0.0), vec3(1.0));
|
|
2312
2646
|
}
|
|
2313
2647
|
float a3dTexturedPbrCharlieSheen(float nDotH, float sheenRoughness) {
|
|
2314
2648
|
float alpha = max(0.07, sheenRoughness * sheenRoughness);
|
|
@@ -2359,7 +2693,10 @@ vec3 a3dTexturedPbrExtensionDirectLight(
|
|
|
2359
2693
|
float iridescence,
|
|
2360
2694
|
float iridescenceIor,
|
|
2361
2695
|
float iridescenceThicknessMinimum,
|
|
2362
|
-
float iridescenceThicknessMaximum
|
|
2696
|
+
float iridescenceThicknessMaximum,
|
|
2697
|
+
vec3 substrateF0,
|
|
2698
|
+
vec3 substrateNormal,
|
|
2699
|
+
float substrateRoughness
|
|
2363
2700
|
) {
|
|
2364
2701
|
vec3 N = normalize(normal);
|
|
2365
2702
|
vec3 V = normalize(viewDirection);
|
|
@@ -2382,9 +2719,14 @@ vec3 a3dTexturedPbrExtensionDirectLight(
|
|
|
2382
2719
|
float anisotropicDistribution = a3dTexturedPbrAnisotropicDistribution(N, H, tangentFrame, clearcoatRough, anisotropy, anisotropyRotation);
|
|
2383
2720
|
float anisotropyShape = anisotropicDistribution / (anisotropicDistribution + 3.0);
|
|
2384
2721
|
vec3 anisotropyLobe = vec3(clamp(anisotropy, 0.0, 1.0) * anisotropyShape * 0.72);
|
|
2385
|
-
vec3
|
|
2386
|
-
vec3
|
|
2387
|
-
|
|
2722
|
+
vec3 filmF = a3dTexturedPbrThinFilmFresnel(substrateF0, iridescenceIor, (iridescenceThicknessMinimum + iridescenceThicknessMaximum) * 0.5, vDotH);
|
|
2723
|
+
vec3 filmN = normalize(substrateNormal);
|
|
2724
|
+
float filmNdotV = max(a3dSaturate(dot(filmN, V)), A3D_EPSILON);
|
|
2725
|
+
float filmNdotL = a3dSaturate(dot(filmN, L));
|
|
2726
|
+
float filmD = a3dDistributionGGX(a3dSaturate(dot(filmN, H)), substrateRoughness);
|
|
2727
|
+
float filmG = a3dGeometrySmithGGXCorrelated(filmNdotV, filmNdotL, substrateRoughness);
|
|
2728
|
+
vec3 iridescenceLobe = (filmF - a3dFresnelSchlick(substrateF0, vDotH)) * clamp(iridescence, 0.0, 1.0) * filmD * filmG;
|
|
2729
|
+
return ((clearcoatLobe + sheenLobe + anisotropyLobe) * nDotL + iridescenceLobe * filmNdotL) * lightColor * lightIntensity;
|
|
2388
2730
|
}
|
|
2389
2731
|
vec3 a3dTexturedPbrExtensionEnvironmentLight(
|
|
2390
2732
|
vec3 normal,
|
|
@@ -2400,7 +2742,10 @@ vec3 a3dTexturedPbrExtensionEnvironmentLight(
|
|
|
2400
2742
|
float iridescence,
|
|
2401
2743
|
float iridescenceIor,
|
|
2402
2744
|
float iridescenceThicknessMinimum,
|
|
2403
|
-
float iridescenceThicknessMaximum
|
|
2745
|
+
float iridescenceThicknessMaximum,
|
|
2746
|
+
vec3 substrateF0,
|
|
2747
|
+
vec3 substrateNormal,
|
|
2748
|
+
vec3 substrateSpecularRadiance
|
|
2404
2749
|
) {
|
|
2405
2750
|
float nDotV = max(a3dSaturate(dot(normalize(normal), normalize(viewDirection))), A3D_EPSILON);
|
|
2406
2751
|
vec3 clearcoatF = a3dFresnelSchlickRoughness(vec3(0.04), nDotV, clamp(clearcoatRoughness, 0.18, 1.0));
|
|
@@ -2417,10 +2762,66 @@ vec3 a3dTexturedPbrExtensionEnvironmentLight(
|
|
|
2417
2762
|
float anisotropicDistribution = a3dTexturedPbrAnisotropicDistribution(N, environmentHalf, tangentFrame, clearcoatRoughness, anisotropy, anisotropyRotation);
|
|
2418
2763
|
float anisotropyShape = anisotropicDistribution / (anisotropicDistribution + 3.0);
|
|
2419
2764
|
vec3 anisotropyLobe = boundedSpecularRadiance * clamp(anisotropy, 0.0, 1.0) * anisotropyShape * 0.72;
|
|
2420
|
-
|
|
2421
|
-
vec3
|
|
2765
|
+
float filmNdotV = max(a3dSaturate(dot(normalize(substrateNormal), normalize(viewDirection))), A3D_EPSILON);
|
|
2766
|
+
vec3 filmF = a3dTexturedPbrThinFilmFresnel(substrateF0, iridescenceIor, (iridescenceThicknessMinimum + iridescenceThicknessMaximum) * 0.5, filmNdotV);
|
|
2767
|
+
vec3 iridescenceLobe = substrateSpecularRadiance * (filmF - a3dFresnelSchlick(substrateF0, filmNdotV)) * clamp(iridescence, 0.0, 1.0);
|
|
2422
2768
|
return clearcoatLobe + sheenLobe + anisotropyLobe + iridescenceLobe;
|
|
2423
2769
|
}
|
|
2770
|
+
|
|
2771
|
+
#ifdef A3D_PBR_EXTENSION_ATLAS
|
|
2772
|
+
uniform sampler2D u_extensionScalarAtlas;
|
|
2773
|
+
int a3dAtlasWrapIndex(int x, int size, float mode) {
|
|
2774
|
+
if (mode < 0.5) return clamp(x, 0, size - 1);
|
|
2775
|
+
int period = mode < 1.5 ? size : 2 * size;
|
|
2776
|
+
int index = ((x % period) + period) % period;
|
|
2777
|
+
return mode < 1.5 ? index : (index < size ? index : period - 1 - index);
|
|
2778
|
+
}
|
|
2779
|
+
vec4 a3dAtlasFetch(ivec2 point, ivec2 size, ivec2 origin, vec2 wrapMode) {
|
|
2780
|
+
ivec2 wrapped = ivec2(a3dAtlasWrapIndex(point.x,size.x,wrapMode.x), a3dAtlasWrapIndex(point.y,size.y,wrapMode.y));
|
|
2781
|
+
return texelFetch(u_extensionScalarAtlas, origin + wrapped, 0);
|
|
2782
|
+
}
|
|
2783
|
+
vec4 a3dAtlasLevel(vec2 uv, vec4 rect, float originY, vec2 wrapMode, int level, bool nearestFilter) {
|
|
2784
|
+
ivec2 size = ivec2(rect.yz);
|
|
2785
|
+
ivec2 origin = ivec2(int(rect.x),int(originY));
|
|
2786
|
+
for (int i=0; i<16; i++) {
|
|
2787
|
+
if (i >= level) break;
|
|
2788
|
+
origin.y += size.y;
|
|
2789
|
+
size = max(size / 2, ivec2(1));
|
|
2790
|
+
}
|
|
2791
|
+
vec2 pixel = uv * vec2(size) - 0.5;
|
|
2792
|
+
if (nearestFilter) return a3dAtlasFetch(ivec2(floor(pixel + 0.5)),size,origin,wrapMode);
|
|
2793
|
+
ivec2 low = ivec2(floor(pixel));
|
|
2794
|
+
vec2 fraction = fract(pixel);
|
|
2795
|
+
return mix(mix(a3dAtlasFetch(low,size,origin,wrapMode),a3dAtlasFetch(low+ivec2(1,0),size,origin,wrapMode),fraction.x),
|
|
2796
|
+
mix(a3dAtlasFetch(low+ivec2(0,1),size,origin,wrapMode),a3dAtlasFetch(low+ivec2(1,1),size,origin,wrapMode),fraction.x),fraction.y);
|
|
2797
|
+
}
|
|
2798
|
+
vec4 a3dAtlasSample(vec2 uv, vec4 rect, float originY, vec2 wrapMode, vec4 filterMode) {
|
|
2799
|
+
vec2 dx=dFdx(uv), dy=dFdy(uv);
|
|
2800
|
+
float lx=length(dx*rect.yz), ly=length(dy*rect.yz);
|
|
2801
|
+
float major=max(lx,ly), minor=max(min(lx,ly),0.000001);
|
|
2802
|
+
bool magnify=major<=1.0;
|
|
2803
|
+
float taps=magnify ? 1.0 : clamp(ceil(major/max(minor,1.0)),1.0,floor(filterMode.w));
|
|
2804
|
+
vec2 axis=lx>=ly ? dx : dy;
|
|
2805
|
+
float lod=clamp(log2(max(major/taps,1.0)),0.0,rect.w);
|
|
2806
|
+
if (filterMode.z<0.5) lod=0.0;
|
|
2807
|
+
else if (filterMode.z<1.5) lod=floor(lod+0.5);
|
|
2808
|
+
int low=int(floor(lod)), high=min(low+1,int(rect.w));
|
|
2809
|
+
bool nearestFilter=magnify ? filterMode.x>0.5 : filterMode.y>0.5;
|
|
2810
|
+
vec4 total=vec4(0.0);
|
|
2811
|
+
for (int i=0;i<16;i++) {
|
|
2812
|
+
if (float(i)>=taps) break;
|
|
2813
|
+
vec2 sampleUv=uv+axis*((float(i)+0.5)/taps-0.5);
|
|
2814
|
+
total+=mix(a3dAtlasLevel(sampleUv,rect,originY,wrapMode,low,nearestFilter),a3dAtlasLevel(sampleUv,rect,originY,wrapMode,high,nearestFilter),fract(lod));
|
|
2815
|
+
}
|
|
2816
|
+
return total/taps;
|
|
2817
|
+
}
|
|
2818
|
+
#endif
|
|
2819
|
+
|
|
2820
|
+
|
|
2821
|
+
|
|
2822
|
+
|
|
2823
|
+
|
|
2824
|
+
|
|
2424
2825
|
void main() {
|
|
2425
2826
|
vec2 baseColorUv = a3dTexturedPbrUv(u_baseColorTextureTexCoord, u_baseColorTextureOffset, u_baseColorTextureScale, u_baseColorTextureRotation);
|
|
2426
2827
|
vec2 normalUv = a3dTexturedPbrUv(u_normalTextureTexCoord, u_normalTextureOffset, u_normalTextureScale, u_normalTextureRotation);
|
|
@@ -2534,10 +2935,18 @@ void main() {
|
|
|
2534
2935
|
float anisotropy = clamp(u_anisotropyStrength, 0.0, 1.0);
|
|
2535
2936
|
float anisotropyRotation = u_anisotropyRotation;
|
|
2536
2937
|
float iridescence = clamp(u_iridescenceFactor, 0.0, 1.0);
|
|
2537
|
-
float iridescenceThickness =
|
|
2938
|
+
float iridescenceThickness = u_iridescenceThicknessMaximum;
|
|
2538
2939
|
#ifdef A3D_PBR_CLEARCOAT_TEXTURES
|
|
2940
|
+
#ifdef A3D_PBR_EXTENSION_ATLAS
|
|
2941
|
+
clearcoat = clamp(clearcoat * mix(1.0, a3dAtlasSample(clearcoatUv, u_clearcoatAtlasRect, u_clearcoatAtlasY, u_clearcoatTextureWrap, u_clearcoatAtlasFilter).r, step(0.5, u_clearcoatTextureEnabled)), 0.0, 1.0);
|
|
2942
|
+
#else
|
|
2539
2943
|
clearcoat = clamp(clearcoat * mix(1.0, texture(u_clearcoatTexture, a3dTexturedPbrWrapUv(clearcoatUv, u_clearcoatTextureWrap)).r, step(0.5, u_clearcoatTextureEnabled)), 0.0, 1.0);
|
|
2944
|
+
#endif
|
|
2945
|
+
#ifdef A3D_PBR_EXTENSION_ATLAS
|
|
2946
|
+
clearcoatRoughness = clamp(clearcoatRoughness * mix(1.0, a3dAtlasSample(clearcoatRoughnessUv, u_clearcoatRoughnessAtlasRect, u_clearcoatRoughnessAtlasY, u_clearcoatRoughnessTextureWrap, u_clearcoatRoughnessAtlasFilter).g, step(0.5, u_clearcoatRoughnessTextureEnabled)), 0.0, 1.0);
|
|
2947
|
+
#else
|
|
2540
2948
|
clearcoatRoughness = clamp(clearcoatRoughness * mix(1.0, texture(u_clearcoatRoughnessTexture, a3dTexturedPbrWrapUv(clearcoatRoughnessUv, u_clearcoatRoughnessTextureWrap)).g, step(0.5, u_clearcoatRoughnessTextureEnabled)), 0.0, 1.0);
|
|
2949
|
+
#endif
|
|
2541
2950
|
clearcoatRoughness = max(clearcoatRoughness, 0.19 + (1.0 - clearcoatNormalBoost) * 0.12);
|
|
2542
2951
|
#endif
|
|
2543
2952
|
#ifdef A3D_PBR_TRANSMISSION_VOLUME_TEXTURES
|
|
@@ -2552,12 +2961,29 @@ void main() {
|
|
|
2552
2961
|
#endif
|
|
2553
2962
|
#ifdef A3D_PBR_SPECULAR_SHEEN_ANISOTROPY_TEXTURES
|
|
2554
2963
|
sheenColor *= mix(vec3(1.0), a3dTexturedPbrDecodeSrgb(texture(u_sheenColorTexture, a3dTexturedPbrWrapUv(sheenColorUv, u_sheenColorTextureWrap)).rgb), step(0.5, u_sheenColorTextureEnabled));
|
|
2964
|
+
#ifdef A3D_PBR_EXTENSION_ATLAS
|
|
2965
|
+
sheenRoughness = clamp(sheenRoughness * mix(1.0, a3dAtlasSample(sheenRoughnessUv, u_sheenRoughnessAtlasRect, u_sheenRoughnessAtlasY, u_sheenRoughnessTextureWrap, u_sheenRoughnessAtlasFilter).a, step(0.5, u_sheenRoughnessTextureEnabled)), 0.0, 1.0);
|
|
2966
|
+
#else
|
|
2555
2967
|
sheenRoughness = clamp(sheenRoughness * mix(1.0, texture(u_sheenRoughnessTexture, a3dTexturedPbrWrapUv(sheenRoughnessUv, u_sheenRoughnessTextureWrap)).a, step(0.5, u_sheenRoughnessTextureEnabled)), 0.0, 1.0);
|
|
2556
|
-
|
|
2968
|
+
#endif
|
|
2969
|
+
vec3 anisotropySample = texture(u_anisotropyTexture, a3dTexturedPbrWrapUv(anisotropyUv, u_anisotropyTextureWrap)).rgb;
|
|
2970
|
+
anisotropy = clamp(anisotropy * mix(1.0, anisotropySample.b, step(0.5, u_anisotropyTextureEnabled)), 0.0, 1.0);
|
|
2971
|
+
vec2 anisotropyDirection = anisotropySample.rg * 2.0 - 1.0;
|
|
2972
|
+
if (u_anisotropyTextureEnabled > 0.5 && dot(anisotropyDirection, anisotropyDirection) > 0.000001) {
|
|
2973
|
+
anisotropyRotation += atan(anisotropyDirection.y, anisotropyDirection.x);
|
|
2974
|
+
}
|
|
2557
2975
|
#endif
|
|
2558
2976
|
#ifdef A3D_PBR_IRIDESCENCE_TEXTURES
|
|
2977
|
+
#ifdef A3D_PBR_EXTENSION_ATLAS
|
|
2978
|
+
iridescence = clamp(iridescence * mix(1.0, a3dAtlasSample(iridescenceUv, u_iridescenceAtlasRect, u_iridescenceAtlasY, u_iridescenceTextureWrap, u_iridescenceAtlasFilter).r, step(0.5, u_iridescenceTextureEnabled)), 0.0, 1.0);
|
|
2979
|
+
#else
|
|
2559
2980
|
iridescence = clamp(iridescence * mix(1.0, texture(u_iridescenceTexture, a3dTexturedPbrWrapUv(iridescenceUv, u_iridescenceTextureWrap)).r, step(0.5, u_iridescenceTextureEnabled)), 0.0, 1.0);
|
|
2981
|
+
#endif
|
|
2982
|
+
#ifdef A3D_PBR_EXTENSION_ATLAS
|
|
2983
|
+
iridescenceThickness = mix(iridescenceThickness, mix(u_iridescenceThicknessMinimum, u_iridescenceThicknessMaximum, a3dAtlasSample(iridescenceThicknessUv, u_iridescenceThicknessAtlasRect, u_iridescenceThicknessAtlasY, u_iridescenceThicknessTextureWrap, u_iridescenceThicknessAtlasFilter).g), step(0.5, u_iridescenceThicknessTextureEnabled));
|
|
2984
|
+
#else
|
|
2560
2985
|
iridescenceThickness = mix(iridescenceThickness, mix(u_iridescenceThicknessMinimum, u_iridescenceThicknessMaximum, texture(u_iridescenceThicknessTexture, a3dTexturedPbrWrapUv(iridescenceThicknessUv, u_iridescenceThicknessTextureWrap)).g), step(0.5, u_iridescenceThicknessTextureEnabled));
|
|
2986
|
+
#endif
|
|
2561
2987
|
#endif
|
|
2562
2988
|
vec3 base = a3dApplyAdvancedPbrLobes(
|
|
2563
2989
|
texturedBase.rgb,
|
|
@@ -2577,13 +3003,14 @@ void main() {
|
|
|
2577
3003
|
sheenRoughness,
|
|
2578
3004
|
anisotropy,
|
|
2579
3005
|
anisotropyRotation,
|
|
2580
|
-
|
|
3006
|
+
0.0,
|
|
2581
3007
|
u_iridescenceIor,
|
|
2582
3008
|
iridescenceThickness,
|
|
2583
3009
|
iridescenceThickness,
|
|
2584
3010
|
u_dispersion
|
|
2585
3011
|
);
|
|
2586
3012
|
vec3 viewDirection = normalize(u_cameraPosition - v_worldPosition);
|
|
3013
|
+
vec3 iridescenceSubstrateF0 = mix(vec3(pow((u_ior - 1.0) / max(u_ior + 1.0, 0.0001), 2.0)) * specularColor * specular, texturedBase.rgb, metallic);
|
|
2587
3014
|
float materialRedPaintGate = smoothstep(0.28, 0.72, texturedBase.r)
|
|
2588
3015
|
* (1.0 - smoothstep(0.05, 0.18, max(texturedBase.g, texturedBase.b)))
|
|
2589
3016
|
* smoothstep(0.015, 0.07, u_materialEnvironmentSpecularScale);
|
|
@@ -2618,7 +3045,10 @@ void main() {
|
|
|
2618
3045
|
iridescence,
|
|
2619
3046
|
u_iridescenceIor,
|
|
2620
3047
|
iridescenceThickness,
|
|
2621
|
-
iridescenceThickness
|
|
3048
|
+
iridescenceThickness,
|
|
3049
|
+
iridescenceSubstrateF0,
|
|
3050
|
+
mappedNormal,
|
|
3051
|
+
a3dTexturedPbrEnvironmentSpecularInput(mappedNormal, viewDirection, roughness)
|
|
2622
3052
|
);
|
|
2623
3053
|
float texturedTransmissionAmount = clamp(max(transmission, diffuseTransmission), 0.0, 1.0);
|
|
2624
3054
|
float texturedSampledEnvironmentWeight = step(0.0001, u_environmentMapTextureEnabled * u_environmentMapTextureIntensity);
|
|
@@ -2651,10 +3081,6 @@ void main() {
|
|
|
2651
3081
|
vec2 backdropOffset = normalize(texturedRefractionDirection.xy + vec2(0.0001)) * u_transmissionBackdropRefractionScale * mix(1.25, 0.55, roughness) * clamp(u_ior - 1.0, 0.0, 2.5);
|
|
2652
3082
|
float backdropLod = clamp((roughness + volumeThickness * 0.08) * max(u_transmissionBackdropMipCount - 1.0, 0.0), 0.0, max(u_transmissionBackdropMipCount - 1.0, 0.0));
|
|
2653
3083
|
vec3 backdropRadiance = a3dTexturedPbrDecodeSrgb(textureLod(u_transmissionBackdropTexture, clamp(backdropUv + backdropOffset, vec2(0.001), vec2(0.999)), backdropLod).rgb);
|
|
2654
|
-
// Scene-color refraction travels through the same participating volume as
|
|
2655
|
-
// environment refraction. Omitting texturedVolumeTint here made thickness,
|
|
2656
|
-
// attenuationDistance, and attenuationColor byte-identical whenever the
|
|
2657
|
-
// renderer-owned backdrop path was active.
|
|
2658
3084
|
texturedRefractionRadiance = mix(
|
|
2659
3085
|
texturedRefractionRadiance,
|
|
2660
3086
|
backdropRadiance * texturedVolumeTint * texturedTransmissionAmount * mix(1.0, 1.22, texturedBackdropWeight),
|
|
@@ -2720,6 +3146,9 @@ void main() {
|
|
|
2720
3146
|
attenuation *= smoothstep(outer, inner, cone);
|
|
2721
3147
|
}
|
|
2722
3148
|
float shadowFactor = mix(1.0, kind > 0.5 && kind < 1.5 ? a3dTexturedPbrPointShadowFactor(v_worldPosition, mappedNormal, lightDirection) : a3dTexturedPbrShadowFactor(v_worldPosition, mappedNormal, lightDirection), step(0.5, spotShadowLayer.z));
|
|
3149
|
+
#ifndef A3D_PBR_NO_SPOT_SHADOW
|
|
3150
|
+
shadowFactor = a3dTexturedPbrResolveSpotShadowOverride(shadowFactor, kind, spotShadowLayer.z, v_worldPosition, mappedNormal, lightDirection);
|
|
3151
|
+
#endif
|
|
2723
3152
|
float directLightIntensity = colorIntensity.a
|
|
2724
3153
|
* attenuation
|
|
2725
3154
|
* shadowFactor
|
|
@@ -2746,7 +3175,10 @@ void main() {
|
|
|
2746
3175
|
iridescence,
|
|
2747
3176
|
u_iridescenceIor,
|
|
2748
3177
|
iridescenceThickness,
|
|
2749
|
-
iridescenceThickness
|
|
3178
|
+
iridescenceThickness,
|
|
3179
|
+
iridescenceSubstrateF0,
|
|
3180
|
+
mappedNormal,
|
|
3181
|
+
roughness
|
|
2750
3182
|
) * directExtensionSpecularScale;
|
|
2751
3183
|
}
|
|
2752
3184
|
float alpha = texturedBase.a;
|
|
@@ -2781,28 +3213,18 @@ out float v_lineDistance;
|
|
|
2781
3213
|
out float v_halfWidthPixels;
|
|
2782
3214
|
|
|
2783
3215
|
void main() {
|
|
2784
|
-
// a_position holds this vertex's anchor endpoint in world space. It is referenced
|
|
2785
|
-
// with zero weight so the attribute is not optimized out of the linked program:
|
|
2786
|
-
// bounds computation, frustum culling, and the material's attribute contract all
|
|
2787
|
-
// depend on the geometry declaring a real position stream.
|
|
2788
3216
|
vec3 anchorWorld = a_position;
|
|
2789
3217
|
vec4 clipStart = u_modelViewProjection * vec4(a_lineStart + anchorWorld * 0.0, 1.0);
|
|
2790
3218
|
vec4 clipEnd = u_modelViewProjection * vec4(a_lineEnd, 1.0);
|
|
2791
3219
|
|
|
2792
|
-
// Guard against a zero or negative w: a vertex behind the eye would otherwise
|
|
2793
|
-
// produce a wildly wrong NDC position and a smeared quad.
|
|
2794
3220
|
float wStart = max(abs(clipStart.w), 1e-5);
|
|
2795
3221
|
float wEnd = max(abs(clipEnd.w), 1e-5);
|
|
2796
3222
|
|
|
2797
|
-
// Project to device pixels. Expansion happens here, so the resulting width is a
|
|
2798
|
-
// pixel quantity and is therefore independent of depth, FOV, and viewport size.
|
|
2799
3223
|
vec2 pixelStart = (clipStart.xy / wStart) * 0.5 * u_lineResolution;
|
|
2800
3224
|
vec2 pixelEnd = (clipEnd.xy / wEnd) * 0.5 * u_lineResolution;
|
|
2801
3225
|
|
|
2802
3226
|
vec2 pixelDirection = pixelEnd - pixelStart;
|
|
2803
3227
|
float pixelLength = length(pixelDirection);
|
|
2804
|
-
// A segment that projects to a single pixel has no screen direction; pick an
|
|
2805
|
-
// arbitrary axis so the cap still renders instead of collapsing.
|
|
2806
3228
|
vec2 direction = pixelLength > 1e-4 ? pixelDirection / pixelLength : vec2(1.0, 0.0);
|
|
2807
3229
|
vec2 normal = vec2(-direction.y, direction.x);
|
|
2808
3230
|
|
|
@@ -2811,14 +3233,10 @@ void main() {
|
|
|
2811
3233
|
|
|
2812
3234
|
float along = a_lineCorner.y;
|
|
2813
3235
|
vec2 anchorPixel = mix(pixelStart, pixelEnd, along);
|
|
2814
|
-
// Square caps push the quad outward along the segment direction so the stroke
|
|
2815
|
-
// extends half a width past each endpoint, matching Three.js LineMaterial behaviour.
|
|
2816
3236
|
float capExtension = u_lineSquareCaps > 0.5 ? halfWidth : 0.0;
|
|
2817
3237
|
vec2 capOffset = direction * (along > 0.5 ? capExtension : -capExtension);
|
|
2818
3238
|
vec2 pixelPosition = anchorPixel + normal * (a_lineCorner.x * halfWidth) + capOffset;
|
|
2819
3239
|
|
|
2820
|
-
// Back to clip space, preserving the anchor endpoint's own depth so the line
|
|
2821
|
-
// depth-sorts against the rest of the scene correctly.
|
|
2822
3240
|
vec4 anchorClip = along > 0.5 ? clipEnd : clipStart;
|
|
2823
3241
|
float anchorW = along > 0.5 ? wEnd : wStart;
|
|
2824
3242
|
vec2 ndc = pixelPosition / (0.5 * u_lineResolution);
|
|
@@ -2847,12 +3265,9 @@ void main() {
|
|
|
2847
3265
|
if (u_lineDashSize > 0.0) {
|
|
2848
3266
|
float period = u_lineDashSize + max(u_lineGapSize, 0.0);
|
|
2849
3267
|
float phase = mod(v_lineDistance + u_lineDashOffset, period);
|
|
2850
|
-
// Discard the gap portion of each dash period.
|
|
2851
3268
|
if (phase > u_lineDashSize) discard;
|
|
2852
3269
|
}
|
|
2853
3270
|
if (u_lineRoundCaps > 0.5) {
|
|
2854
|
-
// Round caps: reject fragments outside the unit half-disc at each end. The
|
|
2855
|
-
// corner's x component already spans -1..1 across the stroke width.
|
|
2856
3271
|
float acrossStroke = v_lineCorner.x;
|
|
2857
3272
|
if (abs(acrossStroke) > 1.0) discard;
|
|
2858
3273
|
}
|