@aura3d/rendering 1.3.3 → 1.4.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/ForwardPass.js +7 -1
- package/dist/ForwardPass.js.map +1 -1
- package/dist/MorphTarget.d.ts +1 -0
- package/dist/MorphTarget.d.ts.map +1 -1
- package/dist/MorphTarget.js.map +1 -1
- package/dist/Renderer.js +7 -1
- package/dist/Renderer.js.map +1 -1
- package/package.json +38 -4
- package/src/ArchitecturalLightingFixtures.ts +0 -241
- package/src/ArchitecturalMaterialCatalog.ts +0 -130
- package/src/ArchitecturalMeasurementFixtures.ts +0 -155
- package/src/BRDFLut.ts +0 -47
- package/src/CameraFraming.ts +0 -200
- package/src/CanonicalSceneFixtures.ts +0 -95
- package/src/CascadedShadowMaps.ts +0 -449
- package/src/ColorManagement.ts +0 -127
- package/src/CullingFixtures.ts +0 -280
- package/src/DecalGeometry.ts +0 -26
- package/src/DepthPass.ts +0 -110
- package/src/EnvironmentBackgroundPass.ts +0 -194
- package/src/EnvironmentBackgroundResources.ts +0 -309
- package/src/EnvironmentLighting.ts +0 -96
- package/src/EnvironmentMapResources.ts +0 -1026
- package/src/EnvironmentPipeline.ts +0 -69
- package/src/EnvironmentPlatform.ts +0 -1306
- package/src/EnvironmentPreset.ts +0 -155
- package/src/Exposure.ts +0 -66
- package/src/ExternalParityRenderPreset.ts +0 -725
- package/src/ForwardPass.ts +0 -1663
- package/src/FrameVisualMetrics.ts +0 -301
- package/src/Geometry.ts +0 -461
- package/src/GeometryPrimitives.ts +0 -2
- package/src/HDRRenderPipeline.ts +0 -94
- package/src/IBL.ts +0 -86
- package/src/IndexBuffer.ts +0 -57
- package/src/InstancedPBRMaterial.ts +0 -186
- package/src/InstancedUnlitMaterial.ts +0 -60
- package/src/Instancing.ts +0 -19
- package/src/LightCollector.ts +0 -82
- package/src/LightUniforms.ts +0 -47
- package/src/LightingDebug.ts +0 -80
- package/src/LightingDefaults.ts +0 -79
- package/src/LightingRig.ts +0 -301
- package/src/LineGeometry.ts +0 -2
- package/src/Material.ts +0 -209
- package/src/MaterialBinding.ts +0 -131
- package/src/MaterialInstance.ts +0 -59
- package/src/MaterialPresets.ts +0 -272
- package/src/MorphTarget.ts +0 -123
- package/src/MorphTargetPlan.ts +0 -178
- package/src/MorphUnlitMaterial.ts +0 -60
- package/src/NormalMappedPBRMaterial.ts +0 -188
- package/src/OceanFixtures.ts +0 -318
- package/src/PBRLightingDefaults.ts +0 -12
- package/src/PBRMaterial.ts +0 -442
- package/src/PMREM.ts +0 -53
- package/src/PbrReference.ts +0 -681
- package/src/PostProcessPass.ts +0 -2507
- package/src/ProceduralTextureFixtures.ts +0 -393
- package/src/ProductTurntableFixtures.ts +0 -815
- package/src/Raycaster.ts +0 -21
- package/src/ReflectionProbe.ts +0 -13
- package/src/ReflectionSurfaces.ts +0 -219
- package/src/RenderBackend.ts +0 -43
- package/src/RenderDebugViews.ts +0 -138
- package/src/RenderDevice.ts +0 -836
- package/src/RenderGraph.ts +0 -194
- package/src/RenderPass.ts +0 -27
- package/src/RenderPipeline.ts +0 -101
- package/src/RenderQueue.ts +0 -12
- package/src/RenderState.ts +0 -12
- package/src/Renderer.ts +0 -2626
- package/src/RendererDebugOverlay.ts +0 -80
- package/src/RendererFeatureGates.ts +0 -150
- package/src/RendererPostprocessPlan.ts +0 -279
- package/src/RendererTiming.ts +0 -251
- package/src/RendererVisualPipelineReport.ts +0 -836
- package/src/ResourceLifecycle.ts +0 -21
- package/src/Sampler.ts +0 -37
- package/src/SceneOptimization.ts +0 -518
- package/src/ShaderChunks.ts +0 -393
- package/src/ShaderLibrary.ts +0 -2766
- package/src/ShaderModule.ts +0 -36
- package/src/ShaderPreprocessor.ts +0 -260
- package/src/ShaderReflection.ts +0 -201
- package/src/ShadowMap.ts +0 -237
- package/src/ShadowPass.ts +0 -198
- package/src/ShadowProjection.ts +0 -115
- package/src/SkinnedLitMaterial.ts +0 -397
- package/src/SkinnedUnlitMaterial.ts +0 -63
- package/src/SkinningBounds.ts +0 -131
- package/src/SpaceEnvironmentFixtures.ts +0 -200
- package/src/SpriteGeometry.ts +0 -21
- package/src/StereoCameraRig.ts +0 -127
- package/src/StereoEffects.ts +0 -274
- package/src/TerrainFixtures.ts +0 -180
- package/src/Texture.ts +0 -307
- package/src/TextureBinding.ts +0 -91
- package/src/TexturedPBRMaterial.ts +0 -1112
- package/src/TexturedUnlitMaterial.ts +0 -67
- package/src/ToneMapping.ts +0 -105
- package/src/UniformBinder.ts +0 -16
- package/src/UniformLayout.ts +0 -129
- package/src/UnlitMaterial.ts +0 -75
- package/src/VegetationFixtures.ts +0 -314
- package/src/VertexBuffer.ts +0 -120
- package/src/VertexFormat.ts +0 -171
- package/src/VoxelWorldFixtures.ts +0 -280
- package/src/WeatherFixtures.ts +0 -223
- package/src/WebGL2Device.ts +0 -2280
- package/src/WebGL2StateCache.ts +0 -330
- package/src/WebGPUDevice.ts +0 -2877
- package/src/WebGPURenderToTextureProof.ts +0 -139
- package/src/advanced-runtime/AdvancedRenderer.ts +0 -73
- package/src/advanced-runtime/index.ts +0 -9
- package/src/animation/AnimationMaterialStyle.ts +0 -32
- package/src/animation/AnimationRenderPreset.ts +0 -45
- package/src/animation/AnimationToonMaterial.ts +0 -387
- package/src/animation/AnimationVisualQuality.ts +0 -71
- package/src/animation/applyAnimationRenderPreset.ts +0 -180
- package/src/animation/index.ts +0 -5
- package/src/cinematic/BloomPass.ts +0 -26
- package/src/cinematic/CinematicDepthComposition.ts +0 -30
- package/src/cinematic/CinematicEvidence.ts +0 -123
- package/src/cinematic/CinematicLightingRig.ts +0 -144
- package/src/cinematic/CinematicMaterialPresets.ts +0 -130
- package/src/cinematic/CinematicPostProcess.ts +0 -83
- package/src/cinematic/DepthHazePass.ts +0 -30
- package/src/cinematic/EmissivePracticalLightSystem.ts +0 -45
- package/src/cinematic/FilmGrainPass.ts +0 -24
- package/src/cinematic/FogVolumeSystem.ts +0 -30
- package/src/cinematic/GlowCardSystem.ts +0 -44
- package/src/cinematic/RainParticleSystem.ts +0 -151
- package/src/cinematic/VignettePass.ts +0 -25
- package/src/cinematic/WetReflectionApproximation.ts +0 -27
- package/src/cinematic/index.ts +0 -14
- package/src/effects/CollisionModule.ts +0 -64
- package/src/effects/ColorModule.ts +0 -60
- package/src/effects/ForceModule.ts +0 -25
- package/src/effects/GPUParticleBackend.ts +0 -569
- package/src/effects/Particle.ts +0 -108
- package/src/effects/ParticleDiagnostics.ts +0 -224
- package/src/effects/ParticleEffectPresets.ts +0 -147
- package/src/effects/ParticleEmitter.ts +0 -326
- package/src/effects/ParticleModule.ts +0 -26
- package/src/effects/ParticleRenderPass.ts +0 -117
- package/src/effects/ParticleRenderer.ts +0 -132
- package/src/effects/ParticleSystem.ts +0 -333
- package/src/effects/SizeModule.ts +0 -56
- package/src/effects/TrailModule.ts +0 -72
- package/src/effects/VelocityModule.ts +0 -75
- package/src/effects/index.ts +0 -15
- package/src/index.ts +0 -925
- package/src/materials/AlphaSorting.ts +0 -30
- package/src/materials/MaterialExtensions.ts +0 -42
- package/src/materials/PhysicalMaterial.ts +0 -133
- package/src/materials/TransmissionPass.ts +0 -51
- package/src/performance/BVH.ts +0 -18
- package/src/performance/Batcher.ts +0 -2
- package/src/performance/FrustumCuller.ts +0 -9
- package/src/performance/LOD.ts +0 -20
- package/src/performance/Octree.ts +0 -10
- package/src/performance/RenderItemSorting.ts +0 -170
- package/src/performance/RendererStats.ts +0 -43
- package/src/performance/ResourceBudget.ts +0 -44
- package/src/postprocess/BloomPass.ts +0 -28
- package/src/postprocess/CinematicDiagnostics.ts +0 -642
- package/src/postprocess/ColorGradingPass.ts +0 -24
- package/src/postprocess/DepthOfFieldPass.ts +0 -12
- package/src/postprocess/EffectComposer.ts +0 -349
- package/src/postprocess/SSAOPass.ts +0 -20
- package/src/postprocess/index.ts +0 -34
- package/src/production-runtime/AnimationControlsPipeline.ts +0 -77
- package/src/production-runtime/PBRHDRPipeline.ts +0 -381
- package/src/production-runtime/ProductionEffectsPipeline.ts +0 -85
- package/src/production-runtime/ProductionRendererTypes.ts +0 -136
- package/src/production-runtime/ProductionRuntimeRenderer.ts +0 -172
- package/src/production-runtime/ProductionWebGL2Renderer.ts +0 -313
- package/src/production-runtime/ProductionWebGPURenderer.ts +0 -396
- package/src/production-runtime/TransmissionBackdropCapture.ts +0 -130
- package/src/production-runtime/animation/MorphTargetRenderer.ts +0 -2
- package/src/production-runtime/animation/SkinningRenderer.ts +0 -2
- package/src/production-runtime/backends/RendererBackend.ts +0 -17
- package/src/production-runtime/backends/WebGL2RendererBackend.ts +0 -30
- package/src/production-runtime/backends/WebGPURendererBackend.ts +0 -24
- package/src/production-runtime/backends/webgl2/WebGL2Buffer.ts +0 -2
- package/src/production-runtime/backends/webgl2/WebGL2Capabilities.ts +0 -2
- package/src/production-runtime/backends/webgl2/WebGL2RenderTarget.ts +0 -2
- package/src/production-runtime/backends/webgl2/WebGL2Shader.ts +0 -2
- package/src/production-runtime/backends/webgl2/WebGL2StateCache.ts +0 -1
- package/src/production-runtime/backends/webgl2/WebGL2Texture.ts +0 -2
- package/src/production-runtime/backends/webgpu/WebGPUBuffer.ts +0 -2
- package/src/production-runtime/backends/webgpu/WebGPUCapabilities.ts +0 -2
- package/src/production-runtime/backends/webgpu/WebGPURenderTarget.ts +0 -2
- package/src/production-runtime/backends/webgpu/WebGPUShader.ts +0 -2
- package/src/production-runtime/backends/webgpu/WebGPUTexture.ts +0 -2
- package/src/production-runtime/color/ColorManagement.ts +0 -3
- package/src/production-runtime/color/ToneMapping.ts +0 -7
- package/src/production-runtime/diagnostics/FrameCapture.ts +0 -2
- package/src/production-runtime/diagnostics/GPUCapabilities.ts +0 -2
- package/src/production-runtime/diagnostics/RendererStats.ts +0 -2
- package/src/production-runtime/environment/EnvironmentMap.ts +0 -1
- package/src/production-runtime/environment/HDRLoader.ts +0 -57
- package/src/production-runtime/environment/PMREMGenerator.ts +0 -713
- package/src/production-runtime/framegraph/FrameGraph.ts +0 -18
- package/src/production-runtime/framegraph/RenderPass.ts +0 -15
- package/src/production-runtime/geometry/ProjectedDecalGeometry.ts +0 -439
- package/src/production-runtime/index.ts +0 -127
- package/src/production-runtime/lights/LightManager.ts +0 -7
- package/src/production-runtime/lights/ShadowMapRenderer.ts +0 -5
- package/src/production-runtime/materials/GLTFMaterialAdapter.ts +0 -6
- package/src/production-runtime/materials/GLTFPBRMaterialAdapter.ts +0 -2
- package/src/production-runtime/materials/MaterialCompiler.ts +0 -7
- package/src/production-runtime/materials/MaterialTextureBindings.ts +0 -5
- package/src/production-runtime/materials/PBRMaterial.ts +0 -2
- package/src/production-runtime/materials/PBRShaderFeatures.ts +0 -2
- package/src/production-runtime/passes/ContactShadowPass.ts +0 -184
- package/src/production-runtime/passes/DepthPrepass.ts +0 -7
- package/src/production-runtime/passes/OpaquePass.ts +0 -7
- package/src/production-runtime/passes/ShadowPass.ts +0 -7
- package/src/production-runtime/passes/SkyboxPass.ts +0 -7
- package/src/production-runtime/passes/ToneMappingPass.ts +0 -7
- package/src/production-runtime/passes/TransparentPass.ts +0 -7
- package/src/production-runtime/postprocess/BloomPass.ts +0 -51
- package/src/production-runtime/postprocess/ColorGradingPass.ts +0 -49
- package/src/production-runtime/postprocess/DOFPass.ts +0 -47
- package/src/production-runtime/postprocess/FXAAPass.ts +0 -53
- package/src/production-runtime/postprocess/ProductionEffectComposer.ts +0 -78
- package/src/production-runtime/postprocess/ProductionPostProcessTypes.ts +0 -174
- package/src/production-runtime/postprocess/SSAOPass.ts +0 -45
- package/src/production-runtime/resources/GPUBuffer.ts +0 -2
- package/src/production-runtime/resources/GPUTexture.ts +0 -2
- package/src/production-runtime/resources/RenderTarget.ts +0 -3
- package/src/production-runtime/resources/ResourceCache.ts +0 -7
- package/src/production-runtime/scene/Camera.ts +0 -1
- package/src/production-runtime/scene/Lights.ts +0 -2
- package/src/production-runtime/scene/RenderableMesh.ts +0 -2
- package/src/production-runtime/scene/RenderablePrimitive.ts +0 -1
- package/src/production-runtime/scene/RenderableScene.ts +0 -4
- package/src/production-runtime/shaders/ShaderProgramLibrary.ts +0 -7
- package/src/production-runtime/shaders/chunks/brdf.glsl +0 -2
- package/src/production-runtime/shaders/chunks/ibl.glsl +0 -3
- package/src/production-runtime/shaders/chunks/pbr.frag.glsl +0 -47
- package/src/production-runtime/shaders/chunks/pbr.vert.glsl +0 -8
- package/src/production-runtime/shaders/chunks/shadows.glsl +0 -2
- package/src/production-runtime/shaders/wgsl/pbr.wgsl +0 -3
- package/src/production-runtime/shaders/wgsl/postprocess.wgsl +0 -2
- package/src/production-runtime/shaders/wgsl/skybox.wgsl +0 -2
- package/src/shaders/depth.frag.glsl +0 -5
- package/src/shaders/depth.vert.glsl +0 -8
- package/src/shaders/pbr-direct.frag.glsl +0 -687
- package/src/shaders/pbr-direct.vert.glsl +0 -18
- package/src/shaders/unlit.frag.glsl +0 -18
- package/src/shaders/unlit.vert.glsl +0 -13
- package/src/shadows/CascadedShadowPipeline.ts +0 -53
- package/src/shadows/ContactShadows.ts +0 -106
- package/src/shadows/ShadowDebugViews.ts +0 -46
- package/src/threejs-compatibility/InstancingSystem.ts +0 -17
- package/src/threejs-compatibility/LightingSystem.ts +0 -22
- package/src/threejs-compatibility/MaterialSystem.ts +0 -9
- package/src/threejs-compatibility/RenderTargetSystem.ts +0 -35
- package/src/threejs-compatibility/RendererDiagnostics.ts +0 -61
- package/src/threejs-compatibility/SceneRenderer.ts +0 -34
- package/src/threejs-compatibility/ShadowSystem.ts +0 -19
- package/src/threejs-compatibility/TextureSystem.ts +0 -19
- package/src/threejs-compatibility/ThreeCompatRenderer.ts +0 -90
- package/src/threejs-compatibility/TransparencySystem.ts +0 -19
- package/src/threejs-compatibility/index.ts +0 -29
- package/src/threejs-compatibility/performance/BVH.ts +0 -14
- package/src/threejs-compatibility/performance/FrustumCulling.ts +0 -10
- package/src/threejs-compatibility/performance/Instancing.ts +0 -4
- package/src/threejs-compatibility/performance/LODSystem.ts +0 -16
- package/src/threejs-compatibility/performance/OcclusionCulling.ts +0 -6
- package/src/threejs-compatibility/performance/RaycastAcceleration.ts +0 -12
- package/src/threejs-compatibility/performance/RendererProfiler.ts +0 -19
- package/src/threejs-compatibility/performance/TextureStreaming.ts +0 -4
- package/src/threejs-compatibility/performance/index.ts +0 -12
- package/src/threejs-compatibility/postprocess/BloomPass.ts +0 -16
- package/src/threejs-compatibility/postprocess/ColorGradingPass.ts +0 -16
- package/src/threejs-compatibility/postprocess/DepthOfFieldPass.ts +0 -21
- package/src/threejs-compatibility/postprocess/EffectComposer.ts +0 -14
- package/src/threejs-compatibility/postprocess/FXAAPass.ts +0 -15
- package/src/threejs-compatibility/postprocess/MotionBlurPass.ts +0 -20
- package/src/threejs-compatibility/postprocess/OutlinePass.ts +0 -21
- package/src/threejs-compatibility/postprocess/PostProcessTypes.ts +0 -169
- package/src/threejs-compatibility/postprocess/RenderPass.ts +0 -9
- package/src/threejs-compatibility/postprocess/SMAAPass.ts +0 -15
- package/src/threejs-compatibility/postprocess/SSAOPass.ts +0 -21
- package/src/threejs-compatibility/postprocess/ShaderPass.ts +0 -7
- package/src/threejs-compatibility/postprocess/TAAPass.ts +0 -15
- package/src/threejs-compatibility/postprocess/VignettePass.ts +0 -16
- package/src/threejs-compatibility/postprocess/index.ts +0 -15
- package/src/threejs-compatibility/shaders/NodeMaterial.ts +0 -21
- package/src/threejs-compatibility/shaders/RawShaderMaterial.ts +0 -6
- package/src/threejs-compatibility/shaders/ShaderDiagnostics.ts +0 -17
- package/src/threejs-compatibility/shaders/ShaderMaterial.ts +0 -18
- package/src/threejs-compatibility/shaders/ThreeCompatShaderChunks.ts +0 -6
- package/src/threejs-compatibility/shaders/Uniforms.ts +0 -18
- package/src/threejs-compatibility/shaders/index.ts +0 -9
- package/src/threejs-compatibility/vfx/GPUPointCloud.ts +0 -7
- package/src/threejs-compatibility/vfx/LineRenderer.ts +0 -13
- package/src/threejs-compatibility/vfx/ParticleSystem.ts +0 -23
- package/src/threejs-compatibility/vfx/SpriteSystem.ts +0 -14
- package/src/threejs-compatibility/vfx/TrailRenderer.ts +0 -8
- package/src/threejs-compatibility/vfx/VFXDiagnostics.ts +0 -23
- package/src/threejs-compatibility/vfx/index.ts +0 -9
- package/src/threejs-example-parity/index.ts +0 -205
- package/src/webgpu/WebGPUBuffer.ts +0 -1
- package/src/webgpu/WebGPUCompute.ts +0 -2
- package/src/webgpu/WebGPUPipelineCache.ts +0 -15
- package/src/webgpu/WebGPUPostProcess.ts +0 -2
- package/src/webgpu/WebGPUTexture.ts +0 -2
- package/tsconfig.json +0 -26
- package/vitest.config.ts +0 -20
|
@@ -1,713 +0,0 @@
|
|
|
1
|
-
import type { LinearHdrEnvironmentMapSource } from "../../EnvironmentMapResources";
|
|
2
|
-
|
|
3
|
-
export type PMREMCubeFace = "px" | "nx" | "py" | "ny" | "pz" | "nz";
|
|
4
|
-
|
|
5
|
-
export interface PMREMLevel {
|
|
6
|
-
readonly mip: number;
|
|
7
|
-
readonly roughness: number;
|
|
8
|
-
readonly faceSize: number;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export interface CubemapPMREMFace {
|
|
12
|
-
readonly face: PMREMCubeFace;
|
|
13
|
-
readonly width: number;
|
|
14
|
-
readonly height: number;
|
|
15
|
-
readonly data: Uint16Array;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface CubemapPMREMLevel extends PMREMLevel {
|
|
19
|
-
readonly faces: readonly CubemapPMREMFace[];
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export interface CubemapPMREMResources {
|
|
23
|
-
readonly faceSize: number;
|
|
24
|
-
readonly mipCount: number;
|
|
25
|
-
readonly levels: readonly CubemapPMREMLevel[];
|
|
26
|
-
readonly diagnostics: {
|
|
27
|
-
readonly faceCount: 6;
|
|
28
|
-
readonly sourceProjection: "equirectangular-to-cubemap";
|
|
29
|
-
readonly filterModel: "ggx-importance-sampled-cubemap-prefilter";
|
|
30
|
-
readonly shaderSampling: "webgl2-sampler-cube";
|
|
31
|
-
readonly totalByteLength: number;
|
|
32
|
-
readonly maxLinearValue: number;
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export interface CubemapPMREMAudit {
|
|
37
|
-
readonly parity: "bounded-pmrem-audit-not-threejs-parity";
|
|
38
|
-
readonly completeMipPyramid: boolean;
|
|
39
|
-
readonly faceCount: number;
|
|
40
|
-
readonly mipCount: number;
|
|
41
|
-
readonly baseFaceSize: number;
|
|
42
|
-
readonly totalByteLength: number;
|
|
43
|
-
readonly maxEdgeMeanDelta: number;
|
|
44
|
-
readonly luminanceVarianceByMip: readonly number[];
|
|
45
|
-
readonly roughnessVarianceNonIncreasing: boolean;
|
|
46
|
-
readonly roughestVarianceReduced: boolean;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export interface CubemapPMREMShaderContract {
|
|
50
|
-
readonly sampling: "webgl2-sampler-cube";
|
|
51
|
-
readonly mipSelection: "roughness-scaled-textureLod";
|
|
52
|
-
readonly splitSumBRDF: true;
|
|
53
|
-
readonly bindableTextureDimension: "cube";
|
|
54
|
-
readonly requiredUniforms: readonly string[];
|
|
55
|
-
readonly materialVariantCoverage: readonly string[];
|
|
56
|
-
readonly faceCompleteness: boolean;
|
|
57
|
-
readonly mipCount: number;
|
|
58
|
-
readonly baseFaceSize: number;
|
|
59
|
-
readonly lodRange: readonly [number, number];
|
|
60
|
-
readonly fallback2DEnvironmentSpecularDisabled: true;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export interface CubemapPMREMOptions {
|
|
64
|
-
readonly faceSize?: number;
|
|
65
|
-
readonly mipCount?: number;
|
|
66
|
-
readonly sampleCount?: number;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export interface PMREMTransmissionProbeOptions {
|
|
70
|
-
readonly position: readonly [number, number, number];
|
|
71
|
-
readonly normal: readonly [number, number, number];
|
|
72
|
-
readonly viewDirection: readonly [number, number, number];
|
|
73
|
-
readonly ior?: number;
|
|
74
|
-
readonly roughness?: number;
|
|
75
|
-
readonly thickness?: number;
|
|
76
|
-
readonly attenuationDistance?: number;
|
|
77
|
-
readonly attenuationColor?: readonly [number, number, number];
|
|
78
|
-
readonly environmentBoxMin?: readonly [number, number, number];
|
|
79
|
-
readonly environmentBoxMax?: readonly [number, number, number];
|
|
80
|
-
readonly maxBounces?: number;
|
|
81
|
-
readonly mipCount?: number;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export interface PMREMTransmissionProbeBounce {
|
|
85
|
-
readonly bounce: number;
|
|
86
|
-
readonly direction: readonly [number, number, number];
|
|
87
|
-
readonly hitPosition: readonly [number, number, number];
|
|
88
|
-
readonly hitNormal: readonly [number, number, number];
|
|
89
|
-
readonly travelDistance: number;
|
|
90
|
-
readonly lod: number;
|
|
91
|
-
readonly attenuation: readonly [number, number, number];
|
|
92
|
-
readonly causticEnergy: number;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
export interface PMREMTransmissionProbe {
|
|
96
|
-
readonly projection: "box-parallax-corrected-cubemap";
|
|
97
|
-
readonly refractionModel: "ior-refract-with-reflection-fallback";
|
|
98
|
-
readonly multiBounce: boolean;
|
|
99
|
-
readonly bounces: readonly PMREMTransmissionProbeBounce[];
|
|
100
|
-
readonly totalTravelDistance: number;
|
|
101
|
-
readonly averageAttenuation: readonly [number, number, number];
|
|
102
|
-
readonly causticEnergy: number;
|
|
103
|
-
readonly recommendedLod: number;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const CUBE_FACES: readonly PMREMCubeFace[] = ["px", "nx", "py", "ny", "pz", "nz"];
|
|
107
|
-
|
|
108
|
-
export function generatePMREMLevels(faceSize = 256, mipCount = 9): readonly PMREMLevel[] {
|
|
109
|
-
validatePositiveInteger(faceSize, "PMREM faceSize");
|
|
110
|
-
validatePositiveInteger(mipCount, "PMREM mipCount");
|
|
111
|
-
return Array.from({ length: mipCount }, (_, mip) => ({
|
|
112
|
-
mip,
|
|
113
|
-
roughness: mip / Math.max(1, mipCount - 1),
|
|
114
|
-
faceSize: Math.max(1, faceSize >> mip)
|
|
115
|
-
}));
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
export function generateCubemapPMREMResources(
|
|
119
|
-
source: LinearHdrEnvironmentMapSource,
|
|
120
|
-
options: CubemapPMREMOptions = {}
|
|
121
|
-
): CubemapPMREMResources {
|
|
122
|
-
validateHdrSource(source);
|
|
123
|
-
const faceSize = options.faceSize ?? 128;
|
|
124
|
-
const mipCount = options.mipCount ?? Math.max(1, Math.floor(Math.log2(faceSize)) + 1);
|
|
125
|
-
const sampleCount = options.sampleCount ?? 32;
|
|
126
|
-
validatePositiveInteger(faceSize, "Cubemap PMREM faceSize");
|
|
127
|
-
validatePositiveInteger(mipCount, "Cubemap PMREM mipCount");
|
|
128
|
-
validatePositiveInteger(sampleCount, "Cubemap PMREM sampleCount");
|
|
129
|
-
|
|
130
|
-
const averageRadiance = sourceAverageRadiance(source);
|
|
131
|
-
const levels = generatePMREMLevels(faceSize, mipCount).map((level) => ({
|
|
132
|
-
...level,
|
|
133
|
-
faces: CUBE_FACES.map((face) => projectPrefilteredFace(source, face, level.faceSize, level.roughness, sampleCount, averageRadiance))
|
|
134
|
-
}));
|
|
135
|
-
const totalByteLength = levels.reduce((total, level) => total + level.faces.reduce((faceTotal, face) => faceTotal + face.data.byteLength, 0), 0);
|
|
136
|
-
return {
|
|
137
|
-
faceSize,
|
|
138
|
-
mipCount,
|
|
139
|
-
levels,
|
|
140
|
-
diagnostics: {
|
|
141
|
-
faceCount: 6,
|
|
142
|
-
sourceProjection: "equirectangular-to-cubemap",
|
|
143
|
-
filterModel: "ggx-importance-sampled-cubemap-prefilter",
|
|
144
|
-
shaderSampling: "webgl2-sampler-cube",
|
|
145
|
-
totalByteLength,
|
|
146
|
-
maxLinearValue: maxLinearValue(source.data)
|
|
147
|
-
}
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
export function auditCubemapPMREMResources(resources: CubemapPMREMResources): CubemapPMREMAudit {
|
|
152
|
-
const expectedLevels = generatePMREMLevels(resources.faceSize, resources.mipCount);
|
|
153
|
-
const completeMipPyramid = expectedLevels.every((expected) => {
|
|
154
|
-
const level = resources.levels.find((candidate) => candidate.mip === expected.mip);
|
|
155
|
-
return Boolean(level)
|
|
156
|
-
&& level!.faceSize === expected.faceSize
|
|
157
|
-
&& level!.faces.length === 6
|
|
158
|
-
&& CUBE_FACES.every((face) => {
|
|
159
|
-
const faceData = level!.faces.find((candidate) => candidate.face === face);
|
|
160
|
-
return Boolean(faceData)
|
|
161
|
-
&& faceData!.width === expected.faceSize
|
|
162
|
-
&& faceData!.height === expected.faceSize
|
|
163
|
-
&& faceData!.data.length === expected.faceSize * expected.faceSize * 4;
|
|
164
|
-
});
|
|
165
|
-
});
|
|
166
|
-
const luminanceVarianceByMip = resources.levels.map((level) => levelLuminanceVariance(level));
|
|
167
|
-
const roughnessVarianceNonIncreasing = luminanceVarianceByMip.every((variance, index) => {
|
|
168
|
-
if (index === 0) return true;
|
|
169
|
-
return variance <= (luminanceVarianceByMip[index - 1] ?? variance) + 0.0001;
|
|
170
|
-
});
|
|
171
|
-
const roughestVarianceReduced = (luminanceVarianceByMip.at(-1) ?? 0) < (luminanceVarianceByMip[0] ?? 0);
|
|
172
|
-
return {
|
|
173
|
-
parity: "bounded-pmrem-audit-not-threejs-parity",
|
|
174
|
-
completeMipPyramid,
|
|
175
|
-
faceCount: CUBE_FACES.length,
|
|
176
|
-
mipCount: resources.levels.length,
|
|
177
|
-
baseFaceSize: resources.faceSize,
|
|
178
|
-
totalByteLength: resources.diagnostics.totalByteLength,
|
|
179
|
-
maxEdgeMeanDelta: maxEdgeMeanDelta(resources.levels[0]),
|
|
180
|
-
luminanceVarianceByMip,
|
|
181
|
-
roughnessVarianceNonIncreasing,
|
|
182
|
-
roughestVarianceReduced
|
|
183
|
-
};
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
export function createCubemapPMREMShaderContract(resources: CubemapPMREMResources): CubemapPMREMShaderContract {
|
|
187
|
-
const audit = auditCubemapPMREMResources(resources);
|
|
188
|
-
return {
|
|
189
|
-
sampling: "webgl2-sampler-cube",
|
|
190
|
-
mipSelection: "roughness-scaled-textureLod",
|
|
191
|
-
splitSumBRDF: true,
|
|
192
|
-
bindableTextureDimension: "cube",
|
|
193
|
-
requiredUniforms: [
|
|
194
|
-
"u_environmentCubeMapTexture",
|
|
195
|
-
"u_environmentCubeMapTextureEnabled",
|
|
196
|
-
"u_environmentMapTextureMipCount",
|
|
197
|
-
"u_environmentBrdfLutTexture",
|
|
198
|
-
"u_environmentBrdfLutEnabled"
|
|
199
|
-
],
|
|
200
|
-
materialVariantCoverage: [
|
|
201
|
-
"PBRMaterial",
|
|
202
|
-
"TexturedPBRMaterial",
|
|
203
|
-
"SkinnedLitMaterial",
|
|
204
|
-
"NormalMappedPBRMaterial",
|
|
205
|
-
"InstancedPBRMaterial"
|
|
206
|
-
],
|
|
207
|
-
faceCompleteness: audit.completeMipPyramid,
|
|
208
|
-
mipCount: resources.mipCount,
|
|
209
|
-
baseFaceSize: resources.faceSize,
|
|
210
|
-
lodRange: [0, Math.max(0, resources.mipCount - 1)],
|
|
211
|
-
fallback2DEnvironmentSpecularDisabled: true
|
|
212
|
-
};
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
export function createPMREMTransmissionProbe(options: PMREMTransmissionProbeOptions): PMREMTransmissionProbe {
|
|
216
|
-
const position = finiteVec3(options.position, "PMREM transmission probe position");
|
|
217
|
-
const normal = normalize(finiteVec3(options.normal, "PMREM transmission probe normal"));
|
|
218
|
-
const viewDirection = normalize(finiteVec3(options.viewDirection, "PMREM transmission probe viewDirection"));
|
|
219
|
-
const ior = finitePositive(options.ior ?? 1.5, "PMREM transmission probe ior");
|
|
220
|
-
const roughness = clampFinite(options.roughness ?? 0, 0, 1, "PMREM transmission probe roughness");
|
|
221
|
-
const thickness = Math.max(0, finiteNumber(options.thickness ?? 0, "PMREM transmission probe thickness"));
|
|
222
|
-
const attenuationDistance = finitePositive(options.attenuationDistance ?? 1_000_000, "PMREM transmission probe attenuationDistance");
|
|
223
|
-
const attenuationColor = finiteColor(options.attenuationColor ?? [1, 1, 1], "PMREM transmission probe attenuationColor");
|
|
224
|
-
const boxMin = finiteVec3(options.environmentBoxMin ?? [-1, -1, -1], "PMREM transmission probe environmentBoxMin");
|
|
225
|
-
const boxMax = finiteVec3(options.environmentBoxMax ?? [1, 1, 1], "PMREM transmission probe environmentBoxMax");
|
|
226
|
-
validateBox(boxMin, boxMax);
|
|
227
|
-
const maxBounces = clampInteger(options.maxBounces ?? 2, 1, 4, "PMREM transmission probe maxBounces");
|
|
228
|
-
const mipCount = clampInteger(options.mipCount ?? 9, 1, 16, "PMREM transmission probe mipCount");
|
|
229
|
-
let origin = clampPointToBox(position, boxMin, boxMax);
|
|
230
|
-
let direction = refract(scale(normalize(viewDirection), -1), normal, 1 / ior);
|
|
231
|
-
if (length(direction) <= 1e-6) {
|
|
232
|
-
direction = reflect(scale(normalize(viewDirection), -1), normal);
|
|
233
|
-
}
|
|
234
|
-
direction = normalize(direction);
|
|
235
|
-
const bounces: PMREMTransmissionProbeBounce[] = [];
|
|
236
|
-
let totalTravelDistance = 0;
|
|
237
|
-
let attenuationProduct: readonly [number, number, number] = [1, 1, 1];
|
|
238
|
-
let causticEnergy = 0;
|
|
239
|
-
|
|
240
|
-
for (let bounce = 0; bounce < maxBounces; bounce += 1) {
|
|
241
|
-
const hit = intersectBox(origin, direction, boxMin, boxMax);
|
|
242
|
-
if (!hit) break;
|
|
243
|
-
const travelDistance = hit.distance;
|
|
244
|
-
totalTravelDistance += travelDistance;
|
|
245
|
-
const volumeTravel = thickness <= 0 ? 0 : (thickness * (bounce + 1) + travelDistance * 0.08) / attenuationDistance;
|
|
246
|
-
const attenuation: readonly [number, number, number] = [
|
|
247
|
-
attenuationProduct[0] * attenuationColor[0] ** volumeTravel,
|
|
248
|
-
attenuationProduct[1] * attenuationColor[1] ** volumeTravel,
|
|
249
|
-
attenuationProduct[2] * attenuationColor[2] ** volumeTravel
|
|
250
|
-
];
|
|
251
|
-
attenuationProduct = attenuation;
|
|
252
|
-
const lod = clamp((roughness + bounce * 0.08 + Math.min(0.24, travelDistance * 0.015)) * (mipCount - 1), 0, mipCount - 1);
|
|
253
|
-
const bounceCaustic = (1 - roughness) ** 2 * average3(attenuation) / (1 + travelDistance * 0.35) / (bounce + 1);
|
|
254
|
-
causticEnergy += bounceCaustic;
|
|
255
|
-
bounces.push({
|
|
256
|
-
bounce,
|
|
257
|
-
direction,
|
|
258
|
-
hitPosition: hit.position,
|
|
259
|
-
hitNormal: hit.normal,
|
|
260
|
-
travelDistance,
|
|
261
|
-
lod,
|
|
262
|
-
attenuation,
|
|
263
|
-
causticEnergy: bounceCaustic
|
|
264
|
-
});
|
|
265
|
-
origin = add(hit.position, scale(hit.normal, -0.001));
|
|
266
|
-
direction = normalize(reflect(direction, hit.normal));
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
const recommendedLod = bounces.length === 0 ? roughness * (mipCount - 1) : bounces.reduce((total, bounce) => total + bounce.lod, 0) / bounces.length;
|
|
270
|
-
return {
|
|
271
|
-
projection: "box-parallax-corrected-cubemap",
|
|
272
|
-
refractionModel: "ior-refract-with-reflection-fallback",
|
|
273
|
-
multiBounce: bounces.length > 1,
|
|
274
|
-
bounces,
|
|
275
|
-
totalTravelDistance,
|
|
276
|
-
averageAttenuation: attenuationProduct,
|
|
277
|
-
causticEnergy,
|
|
278
|
-
recommendedLod
|
|
279
|
-
};
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
function projectPrefilteredFace(
|
|
283
|
-
source: LinearHdrEnvironmentMapSource,
|
|
284
|
-
face: PMREMCubeFace,
|
|
285
|
-
faceSize: number,
|
|
286
|
-
roughness: number,
|
|
287
|
-
sampleCount: number,
|
|
288
|
-
averageRadiance: readonly [number, number, number]
|
|
289
|
-
): CubemapPMREMFace {
|
|
290
|
-
const data = new Uint16Array(faceSize * faceSize * 4);
|
|
291
|
-
for (let y = 0; y < faceSize; y += 1) {
|
|
292
|
-
const v = ((y + 0.5) / faceSize) * 2 - 1;
|
|
293
|
-
for (let x = 0; x < faceSize; x += 1) {
|
|
294
|
-
const u = ((x + 0.5) / faceSize) * 2 - 1;
|
|
295
|
-
const direction = normalize(faceDirection(face, u, v));
|
|
296
|
-
const color = samplePrefilteredDirection(source, direction, roughness, sampleCount, averageRadiance);
|
|
297
|
-
const offset = (y * faceSize + x) * 4;
|
|
298
|
-
data[offset] = numberToHalfFloat(color[0]);
|
|
299
|
-
data[offset + 1] = numberToHalfFloat(color[1]);
|
|
300
|
-
data[offset + 2] = numberToHalfFloat(color[2]);
|
|
301
|
-
data[offset + 3] = numberToHalfFloat(1);
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
return { face, width: faceSize, height: faceSize, data };
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
function samplePrefilteredDirection(
|
|
308
|
-
source: LinearHdrEnvironmentMapSource,
|
|
309
|
-
direction: readonly [number, number, number],
|
|
310
|
-
roughness: number,
|
|
311
|
-
sampleCount: number,
|
|
312
|
-
averageRadiance: readonly [number, number, number]
|
|
313
|
-
): readonly [number, number, number] {
|
|
314
|
-
if (roughness <= 0.0001 || sampleCount <= 1) {
|
|
315
|
-
return sampleEquirect(source, direction);
|
|
316
|
-
}
|
|
317
|
-
const normal = normalize(direction);
|
|
318
|
-
const view = normal;
|
|
319
|
-
let red = 0;
|
|
320
|
-
let green = 0;
|
|
321
|
-
let blue = 0;
|
|
322
|
-
let weightTotal = 0;
|
|
323
|
-
for (let sample = 0; sample < sampleCount; sample += 1) {
|
|
324
|
-
const halfVector = importanceSampleGGX(
|
|
325
|
-
[(sample + 0.5) / sampleCount, radicalInverseVdc(sample)],
|
|
326
|
-
normal,
|
|
327
|
-
roughness
|
|
328
|
-
);
|
|
329
|
-
const viewDotHalf = Math.max(0, dot(view, halfVector));
|
|
330
|
-
const light = normalize([
|
|
331
|
-
2 * viewDotHalf * halfVector[0] - view[0],
|
|
332
|
-
2 * viewDotHalf * halfVector[1] - view[1],
|
|
333
|
-
2 * viewDotHalf * halfVector[2] - view[2]
|
|
334
|
-
]);
|
|
335
|
-
const weight = Math.max(0, dot(normal, light));
|
|
336
|
-
if (weight <= 0) continue;
|
|
337
|
-
const color = sampleEquirect(source, light);
|
|
338
|
-
red += color[0] * weight;
|
|
339
|
-
green += color[1] * weight;
|
|
340
|
-
blue += color[2] * weight;
|
|
341
|
-
weightTotal += weight;
|
|
342
|
-
}
|
|
343
|
-
if (weightTotal <= 0) return averageRadiance;
|
|
344
|
-
const filtered: readonly [number, number, number] = [red / weightTotal, green / weightTotal, blue / weightTotal];
|
|
345
|
-
const wideLobeBlend = Math.min(0.82, roughness ** 4 * 0.82);
|
|
346
|
-
return [
|
|
347
|
-
filtered[0] * (1 - wideLobeBlend) + averageRadiance[0] * wideLobeBlend,
|
|
348
|
-
filtered[1] * (1 - wideLobeBlend) + averageRadiance[1] * wideLobeBlend,
|
|
349
|
-
filtered[2] * (1 - wideLobeBlend) + averageRadiance[2] * wideLobeBlend
|
|
350
|
-
];
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
function importanceSampleGGX(
|
|
354
|
-
xi: readonly [number, number],
|
|
355
|
-
normal: readonly [number, number, number],
|
|
356
|
-
roughness: number
|
|
357
|
-
): readonly [number, number, number] {
|
|
358
|
-
const alpha = Math.max(0.001, roughness * roughness);
|
|
359
|
-
const alphaSquared = alpha * alpha;
|
|
360
|
-
const phi = 2 * Math.PI * xi[0];
|
|
361
|
-
const cosTheta = Math.sqrt((1 - xi[1]) / Math.max(0.000001, 1 + (alphaSquared - 1) * xi[1]));
|
|
362
|
-
const sinTheta = Math.sqrt(Math.max(0, 1 - cosTheta * cosTheta));
|
|
363
|
-
const tangent = Math.abs(normal[1]) < 0.95
|
|
364
|
-
? normalize(cross([0, 1, 0], normal))
|
|
365
|
-
: normalize(cross([1, 0, 0], normal));
|
|
366
|
-
const bitangent = normalize(cross(normal, tangent));
|
|
367
|
-
return normalize([
|
|
368
|
-
tangent[0] * Math.cos(phi) * sinTheta + bitangent[0] * Math.sin(phi) * sinTheta + normal[0] * cosTheta,
|
|
369
|
-
tangent[1] * Math.cos(phi) * sinTheta + bitangent[1] * Math.sin(phi) * sinTheta + normal[1] * cosTheta,
|
|
370
|
-
tangent[2] * Math.cos(phi) * sinTheta + bitangent[2] * Math.sin(phi) * sinTheta + normal[2] * cosTheta
|
|
371
|
-
]);
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
function radicalInverseVdc(bits: number): number {
|
|
375
|
-
let value = bits >>> 0;
|
|
376
|
-
value = (value << 16) | (value >>> 16);
|
|
377
|
-
value = ((value & 0x55555555) << 1) | ((value & 0xaaaaaaaa) >>> 1);
|
|
378
|
-
value = ((value & 0x33333333) << 2) | ((value & 0xcccccccc) >>> 2);
|
|
379
|
-
value = ((value & 0x0f0f0f0f) << 4) | ((value & 0xf0f0f0f0) >>> 4);
|
|
380
|
-
value = ((value & 0x00ff00ff) << 8) | ((value & 0xff00ff00) >>> 8);
|
|
381
|
-
return value * 2.3283064365386963e-10;
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
function sampleEquirect(
|
|
385
|
-
source: LinearHdrEnvironmentMapSource,
|
|
386
|
-
direction: readonly [number, number, number]
|
|
387
|
-
): readonly [number, number, number] {
|
|
388
|
-
const u = 0.5 + Math.atan2(direction[2], direction[0]) / (Math.PI * 2);
|
|
389
|
-
const v = 0.5 - Math.asin(clamp(direction[1], -1, 1)) / Math.PI;
|
|
390
|
-
const sampleX = u * source.width - 0.5;
|
|
391
|
-
const sampleY = v * source.height - 0.5;
|
|
392
|
-
const x0 = Math.floor(sampleX);
|
|
393
|
-
const y0 = Math.floor(sampleY);
|
|
394
|
-
const x1 = x0 + 1;
|
|
395
|
-
const y1 = y0 + 1;
|
|
396
|
-
const tx = sampleX - x0;
|
|
397
|
-
const ty = sampleY - y0;
|
|
398
|
-
const topLeft = sampleEquirectTexel(source, x0, y0);
|
|
399
|
-
const topRight = sampleEquirectTexel(source, x1, y0);
|
|
400
|
-
const bottomLeft = sampleEquirectTexel(source, x0, y1);
|
|
401
|
-
const bottomRight = sampleEquirectTexel(source, x1, y1);
|
|
402
|
-
const top = mixRgb(topLeft, topRight, tx);
|
|
403
|
-
const bottom = mixRgb(bottomLeft, bottomRight, tx);
|
|
404
|
-
return mixRgb(top, bottom, ty);
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
function sampleEquirectTexel(
|
|
408
|
-
source: LinearHdrEnvironmentMapSource,
|
|
409
|
-
x: number,
|
|
410
|
-
y: number
|
|
411
|
-
): readonly [number, number, number] {
|
|
412
|
-
const pixelX = wrap(x, source.width);
|
|
413
|
-
const pixelY = clamp(y, 0, source.height - 1);
|
|
414
|
-
const offset = (pixelY * source.width + pixelX) * 4;
|
|
415
|
-
return [
|
|
416
|
-
Math.max(0, source.data[offset] ?? 0),
|
|
417
|
-
Math.max(0, source.data[offset + 1] ?? 0),
|
|
418
|
-
Math.max(0, source.data[offset + 2] ?? 0)
|
|
419
|
-
];
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
function mixRgb(
|
|
423
|
-
a: readonly [number, number, number],
|
|
424
|
-
b: readonly [number, number, number],
|
|
425
|
-
t: number
|
|
426
|
-
): readonly [number, number, number] {
|
|
427
|
-
return [
|
|
428
|
-
a[0] + (b[0] - a[0]) * t,
|
|
429
|
-
a[1] + (b[1] - a[1]) * t,
|
|
430
|
-
a[2] + (b[2] - a[2]) * t
|
|
431
|
-
];
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
function sourceAverageRadiance(source: LinearHdrEnvironmentMapSource): readonly [number, number, number] {
|
|
435
|
-
let red = 0;
|
|
436
|
-
let green = 0;
|
|
437
|
-
let blue = 0;
|
|
438
|
-
let count = 0;
|
|
439
|
-
for (let offset = 0; offset < source.data.length; offset += 4) {
|
|
440
|
-
red += Math.max(0, source.data[offset] ?? 0);
|
|
441
|
-
green += Math.max(0, source.data[offset + 1] ?? 0);
|
|
442
|
-
blue += Math.max(0, source.data[offset + 2] ?? 0);
|
|
443
|
-
count += 1;
|
|
444
|
-
}
|
|
445
|
-
return [red / Math.max(1, count), green / Math.max(1, count), blue / Math.max(1, count)];
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
function faceDirection(face: PMREMCubeFace, u: number, v: number): readonly [number, number, number] {
|
|
449
|
-
switch (face) {
|
|
450
|
-
case "px": return [1, -v, -u];
|
|
451
|
-
case "nx": return [-1, -v, u];
|
|
452
|
-
case "py": return [u, 1, v];
|
|
453
|
-
case "ny": return [u, -1, -v];
|
|
454
|
-
case "pz": return [u, -v, 1];
|
|
455
|
-
case "nz": return [-u, -v, -1];
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
function normalize(value: readonly [number, number, number]): readonly [number, number, number] {
|
|
460
|
-
const length = Math.hypot(value[0], value[1], value[2]);
|
|
461
|
-
if (!Number.isFinite(length) || length <= 0) return [0, 1, 0];
|
|
462
|
-
return [value[0] / length, value[1] / length, value[2] / length];
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
function cross(a: readonly [number, number, number], b: readonly [number, number, number]): readonly [number, number, number] {
|
|
466
|
-
return [
|
|
467
|
-
a[1] * b[2] - a[2] * b[1],
|
|
468
|
-
a[2] * b[0] - a[0] * b[2],
|
|
469
|
-
a[0] * b[1] - a[1] * b[0]
|
|
470
|
-
];
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
function dot(a: readonly [number, number, number], b: readonly [number, number, number]): number {
|
|
474
|
-
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
function wrap(value: number, size: number): number {
|
|
478
|
-
return ((value % size) + size) % size;
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
function clamp(value: number, min: number, max: number): number {
|
|
482
|
-
return Math.min(max, Math.max(min, value));
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
function maxLinearValue(data: Float32Array | readonly number[]): number {
|
|
486
|
-
let max = 0;
|
|
487
|
-
for (let offset = 0; offset < data.length; offset += 4) {
|
|
488
|
-
max = Math.max(max, data[offset] ?? 0, data[offset + 1] ?? 0, data[offset + 2] ?? 0);
|
|
489
|
-
}
|
|
490
|
-
return max;
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
function maxEdgeMeanDelta(level: CubemapPMREMLevel | undefined): number {
|
|
494
|
-
if (!level) return 0;
|
|
495
|
-
const edges = level.faces.flatMap((face) => [
|
|
496
|
-
edgeMean(face, "top"),
|
|
497
|
-
edgeMean(face, "right"),
|
|
498
|
-
edgeMean(face, "bottom"),
|
|
499
|
-
edgeMean(face, "left")
|
|
500
|
-
]);
|
|
501
|
-
let maxDelta = 0;
|
|
502
|
-
for (let a = 0; a < edges.length; a += 1) {
|
|
503
|
-
for (let b = a + 1; b < edges.length; b += 1) {
|
|
504
|
-
maxDelta = Math.max(maxDelta, colorDistance(edges[a]!, edges[b]!));
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
return Number(maxDelta.toFixed(6));
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
function edgeMean(face: CubemapPMREMFace, edge: "top" | "right" | "bottom" | "left"): readonly [number, number, number] {
|
|
511
|
-
let red = 0;
|
|
512
|
-
let green = 0;
|
|
513
|
-
let blue = 0;
|
|
514
|
-
let count = 0;
|
|
515
|
-
const size = face.width;
|
|
516
|
-
for (let i = 0; i < size; i += 1) {
|
|
517
|
-
const x = edge === "left" ? 0 : edge === "right" ? size - 1 : i;
|
|
518
|
-
const y = edge === "top" ? 0 : edge === "bottom" ? size - 1 : i;
|
|
519
|
-
const offset = (y * size + x) * 4;
|
|
520
|
-
red += halfFloatToNumber(face.data[offset] ?? 0);
|
|
521
|
-
green += halfFloatToNumber(face.data[offset + 1] ?? 0);
|
|
522
|
-
blue += halfFloatToNumber(face.data[offset + 2] ?? 0);
|
|
523
|
-
count += 1;
|
|
524
|
-
}
|
|
525
|
-
return [red / count, green / count, blue / count];
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
function levelLuminanceVariance(level: CubemapPMREMLevel): number {
|
|
529
|
-
const values: number[] = [];
|
|
530
|
-
for (const face of level.faces) {
|
|
531
|
-
for (let offset = 0; offset < face.data.length; offset += 4) {
|
|
532
|
-
values.push(
|
|
533
|
-
halfFloatToNumber(face.data[offset] ?? 0) * 0.2126
|
|
534
|
-
+ halfFloatToNumber(face.data[offset + 1] ?? 0) * 0.7152
|
|
535
|
-
+ halfFloatToNumber(face.data[offset + 2] ?? 0) * 0.0722
|
|
536
|
-
);
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
const mean = values.reduce((total, value) => total + value, 0) / Math.max(1, values.length);
|
|
540
|
-
const variance = values.reduce((total, value) => total + (value - mean) ** 2, 0) / Math.max(1, values.length);
|
|
541
|
-
return Number(variance.toFixed(6));
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
function colorDistance(a: readonly [number, number, number], b: readonly [number, number, number]): number {
|
|
545
|
-
return Math.hypot(a[0] - b[0], a[1] - b[1], a[2] - b[2]);
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
function halfFloatToNumber(bits: number): number {
|
|
549
|
-
const sign = bits & 0x8000 ? -1 : 1;
|
|
550
|
-
const exponent = (bits >>> 10) & 0x1f;
|
|
551
|
-
const fraction = bits & 0x03ff;
|
|
552
|
-
if (exponent === 0) return sign * 2 ** -14 * (fraction / 1024);
|
|
553
|
-
if (exponent === 0x1f) return fraction === 0 ? sign * Infinity : Number.NaN;
|
|
554
|
-
return sign * 2 ** (exponent - 15) * (1 + fraction / 1024);
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
function validateHdrSource(source: LinearHdrEnvironmentMapSource): void {
|
|
558
|
-
validatePositiveInteger(source.width, "Cubemap PMREM source width");
|
|
559
|
-
validatePositiveInteger(source.height, "Cubemap PMREM source height");
|
|
560
|
-
if (source.data.length !== source.width * source.height * 4) {
|
|
561
|
-
throw new RangeError("Cubemap PMREM source data must contain width * height * 4 linear RGBA values");
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
function validatePositiveInteger(value: number, label: string): void {
|
|
566
|
-
if (!Number.isInteger(value) || value <= 0) {
|
|
567
|
-
throw new RangeError(`${label} must be a positive integer`);
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
function finiteVec3(value: readonly [number, number, number], label: string): readonly [number, number, number] {
|
|
572
|
-
if (value.length !== 3 || value.some((component) => !Number.isFinite(component))) {
|
|
573
|
-
throw new RangeError(`${label} must contain three finite numbers`);
|
|
574
|
-
}
|
|
575
|
-
return [value[0], value[1], value[2]];
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
function finiteColor(value: readonly [number, number, number], label: string): readonly [number, number, number] {
|
|
579
|
-
const color = finiteVec3(value, label);
|
|
580
|
-
if (color.some((component) => component < 0 || component > 1)) {
|
|
581
|
-
throw new RangeError(`${label} must be in the [0, 1] range`);
|
|
582
|
-
}
|
|
583
|
-
return color;
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
function finiteNumber(value: number, label: string): number {
|
|
587
|
-
if (!Number.isFinite(value)) {
|
|
588
|
-
throw new RangeError(`${label} must be finite`);
|
|
589
|
-
}
|
|
590
|
-
return value;
|
|
591
|
-
}
|
|
592
|
-
|
|
593
|
-
function finitePositive(value: number, label: string): number {
|
|
594
|
-
if (!Number.isFinite(value) || value <= 0) {
|
|
595
|
-
throw new RangeError(`${label} must be a positive finite number`);
|
|
596
|
-
}
|
|
597
|
-
return value;
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
function clampFinite(value: number, min: number, max: number, label: string): number {
|
|
601
|
-
return clamp(finiteNumber(value, label), min, max);
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
function clampInteger(value: number, min: number, max: number, label: string): number {
|
|
605
|
-
if (!Number.isInteger(value)) {
|
|
606
|
-
throw new RangeError(`${label} must be an integer`);
|
|
607
|
-
}
|
|
608
|
-
return Math.max(min, Math.min(max, value));
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
function validateBox(min: readonly [number, number, number], max: readonly [number, number, number]): void {
|
|
612
|
-
if (min.some((component, index) => component >= max[index]!)) {
|
|
613
|
-
throw new RangeError("PMREM transmission probe environment box min values must be lower than max values");
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
function clampPointToBox(point: readonly [number, number, number], min: readonly [number, number, number], max: readonly [number, number, number]): readonly [number, number, number] {
|
|
618
|
-
return [
|
|
619
|
-
clamp(point[0], min[0] + 0.0001, max[0] - 0.0001),
|
|
620
|
-
clamp(point[1], min[1] + 0.0001, max[1] - 0.0001),
|
|
621
|
-
clamp(point[2], min[2] + 0.0001, max[2] - 0.0001)
|
|
622
|
-
];
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
function intersectBox(
|
|
626
|
-
origin: readonly [number, number, number],
|
|
627
|
-
direction: readonly [number, number, number],
|
|
628
|
-
min: readonly [number, number, number],
|
|
629
|
-
max: readonly [number, number, number]
|
|
630
|
-
): { readonly position: readonly [number, number, number]; readonly normal: readonly [number, number, number]; readonly distance: number } | undefined {
|
|
631
|
-
let bestDistance = Number.POSITIVE_INFINITY;
|
|
632
|
-
let bestNormal: readonly [number, number, number] | undefined;
|
|
633
|
-
for (let axis = 0; axis < 3; axis += 1) {
|
|
634
|
-
const component = direction[axis]!;
|
|
635
|
-
if (Math.abs(component) <= 1e-8) continue;
|
|
636
|
-
const plane = component > 0 ? max[axis]! : min[axis]!;
|
|
637
|
-
const distance = (plane - origin[axis]!) / component;
|
|
638
|
-
if (distance <= 1e-6 || distance >= bestDistance) continue;
|
|
639
|
-
const hit: readonly [number, number, number] = [
|
|
640
|
-
origin[0] + direction[0] * distance,
|
|
641
|
-
origin[1] + direction[1] * distance,
|
|
642
|
-
origin[2] + direction[2] * distance
|
|
643
|
-
];
|
|
644
|
-
if (
|
|
645
|
-
hit[0] < min[0] - 1e-5 || hit[0] > max[0] + 1e-5 ||
|
|
646
|
-
hit[1] < min[1] - 1e-5 || hit[1] > max[1] + 1e-5 ||
|
|
647
|
-
hit[2] < min[2] - 1e-5 || hit[2] > max[2] + 1e-5
|
|
648
|
-
) {
|
|
649
|
-
continue;
|
|
650
|
-
}
|
|
651
|
-
bestDistance = distance;
|
|
652
|
-
bestNormal = axis === 0
|
|
653
|
-
? [component > 0 ? 1 : -1, 0, 0]
|
|
654
|
-
: axis === 1
|
|
655
|
-
? [0, component > 0 ? 1 : -1, 0]
|
|
656
|
-
: [0, 0, component > 0 ? 1 : -1];
|
|
657
|
-
}
|
|
658
|
-
if (!bestNormal || !Number.isFinite(bestDistance)) return undefined;
|
|
659
|
-
return {
|
|
660
|
-
position: [
|
|
661
|
-
origin[0] + direction[0] * bestDistance,
|
|
662
|
-
origin[1] + direction[1] * bestDistance,
|
|
663
|
-
origin[2] + direction[2] * bestDistance
|
|
664
|
-
],
|
|
665
|
-
normal: bestNormal,
|
|
666
|
-
distance: bestDistance
|
|
667
|
-
};
|
|
668
|
-
}
|
|
669
|
-
|
|
670
|
-
function length(vector: readonly [number, number, number]): number {
|
|
671
|
-
return Math.hypot(vector[0], vector[1], vector[2]);
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
function scale(vector: readonly [number, number, number], scalar: number): readonly [number, number, number] {
|
|
675
|
-
return [vector[0] * scalar, vector[1] * scalar, vector[2] * scalar];
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
function reflect(vector: readonly [number, number, number], normal: readonly [number, number, number]): readonly [number, number, number] {
|
|
679
|
-
return subtract(vector, scale(normal, 2 * dot(vector, normal)));
|
|
680
|
-
}
|
|
681
|
-
|
|
682
|
-
function refract(vector: readonly [number, number, number], normal: readonly [number, number, number], eta: number): readonly [number, number, number] {
|
|
683
|
-
const cosi = clamp(dot(scale(vector, -1), normal), -1, 1);
|
|
684
|
-
const k = 1 - eta * eta * (1 - cosi * cosi);
|
|
685
|
-
if (k < 0) return [0, 0, 0];
|
|
686
|
-
return add(scale(vector, eta), scale(normal, eta * cosi - Math.sqrt(k)));
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
function add(left: readonly [number, number, number], right: readonly [number, number, number]): readonly [number, number, number] {
|
|
690
|
-
return [left[0] + right[0], left[1] + right[1], left[2] + right[2]];
|
|
691
|
-
}
|
|
692
|
-
|
|
693
|
-
function subtract(left: readonly [number, number, number], right: readonly [number, number, number]): readonly [number, number, number] {
|
|
694
|
-
return [left[0] - right[0], left[1] - right[1], left[2] - right[2]];
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
function average3(value: readonly [number, number, number]): number {
|
|
698
|
-
return (value[0] + value[1] + value[2]) / 3;
|
|
699
|
-
}
|
|
700
|
-
|
|
701
|
-
function numberToHalfFloat(value: number): number {
|
|
702
|
-
const clamped = Math.max(0, value);
|
|
703
|
-
if (Number.isNaN(clamped)) return 0x7e00;
|
|
704
|
-
if (clamped === Infinity) return 0x7c00;
|
|
705
|
-
if (clamped >= 65504) return 0x7bff;
|
|
706
|
-
if (clamped === 0) return 0;
|
|
707
|
-
if (clamped < 2 ** -14) {
|
|
708
|
-
return Math.round(clamped / 2 ** -24);
|
|
709
|
-
}
|
|
710
|
-
const exponent = Math.floor(Math.log2(clamped));
|
|
711
|
-
const mantissa = Math.round((clamped / 2 ** exponent - 1) * 1024);
|
|
712
|
-
return ((exponent + 15) << 10) | (mantissa & 0x03ff);
|
|
713
|
-
}
|