@onerjs/core 8.56.4 → 9.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/Animations/animatable.core.js +36 -0
- package/Animations/animatable.core.js.map +1 -1
- package/Animations/animationGroup.pure.d.ts +61 -1
- package/Animations/animationGroup.pure.js +191 -2
- package/Animations/animationGroup.pure.js.map +1 -1
- package/Animations/index.d.ts +1 -0
- package/Animations/index.js +1 -0
- package/Animations/index.js.map +1 -1
- package/Animations/pure.d.ts +1 -0
- package/Animations/pure.js +1 -0
- package/Animations/pure.js.map +1 -1
- package/Animations/rootMotion.d.ts +560 -0
- package/Animations/rootMotion.js +1709 -0
- package/Animations/rootMotion.js.map +1 -0
- package/Animations/runtimeAnimation.d.ts +57 -0
- package/Animations/runtimeAnimation.js +127 -3
- package/Animations/runtimeAnimation.js.map +1 -1
- package/Cameras/arcRotateCamera.pure.d.ts +2 -0
- package/Cameras/arcRotateCamera.pure.js +2 -0
- package/Cameras/arcRotateCamera.pure.js.map +1 -1
- package/Cameras/targetCamera.pure.d.ts +2 -0
- package/Cameras/targetCamera.pure.js +13 -2
- package/Cameras/targetCamera.pure.js.map +1 -1
- package/Collisions/gpuPicker.js +5 -5
- package/Collisions/gpuPicker.js.map +1 -1
- package/Engines/AbstractEngine/abstractEngine.query.pure.js +4 -2
- package/Engines/AbstractEngine/abstractEngine.query.pure.js.map +1 -1
- package/Engines/AbstractEngine/abstractEngine.query.types.d.ts +11 -2
- package/Engines/AbstractEngine/abstractEngine.query.types.js.map +1 -1
- package/Engines/AbstractEngine/abstractEngine.renderPass.pure.js +1 -0
- package/Engines/AbstractEngine/abstractEngine.renderPass.pure.js.map +1 -1
- package/Engines/Extensions/engine.multiRender.pure.js +63 -0
- package/Engines/Extensions/engine.multiRender.pure.js.map +1 -1
- package/Engines/Extensions/engine.multiRender.types.d.ts +13 -0
- package/Engines/Extensions/engine.multiRender.types.js.map +1 -1
- package/Engines/Extensions/engine.prefilteredCubeTexture.pure.js +2 -2
- package/Engines/Extensions/engine.prefilteredCubeTexture.pure.js.map +1 -1
- package/Engines/Extensions/engine.prefilteredCubeTexture.types.d.ts +2 -1
- package/Engines/Extensions/engine.prefilteredCubeTexture.types.js.map +1 -1
- package/Engines/Extensions/index.d.ts +1 -0
- package/Engines/Extensions/index.js +1 -0
- package/Engines/Extensions/index.js.map +1 -1
- package/Engines/Extensions/pure.d.ts +1 -1
- package/Engines/Extensions/pure.js +1 -1
- package/Engines/Extensions/pure.js.map +1 -1
- package/Engines/Native/Extensions/nativeEngine.cubeTexture.pure.js +88 -39
- package/Engines/Native/Extensions/nativeEngine.cubeTexture.pure.js.map +1 -1
- package/Engines/Native/Extensions/nativeEngine.cubeTexture.types.d.ts +20 -2
- package/Engines/Native/Extensions/nativeEngine.cubeTexture.types.js.map +1 -1
- package/Engines/Native/nativeHardwareTexture.d.ts +8 -1
- package/Engines/Native/nativeHardwareTexture.js +7 -0
- package/Engines/Native/nativeHardwareTexture.js.map +1 -1
- package/Engines/Native/nativeHelpers.js +56 -1
- package/Engines/Native/nativeHelpers.js.map +1 -1
- package/Engines/Native/nativeInterfaces.d.ts +37 -8
- package/Engines/Native/nativeInterfaces.js.map +1 -1
- package/Engines/Native/nativeRenderTargetWrapper.d.ts +40 -0
- package/Engines/Native/nativeRenderTargetWrapper.js +265 -5
- package/Engines/Native/nativeRenderTargetWrapper.js.map +1 -1
- package/Engines/Processors/shaderCodeCursor.d.ts +1 -0
- package/Engines/Processors/shaderCodeCursor.js +40 -3
- package/Engines/Processors/shaderCodeCursor.js.map +1 -1
- package/Engines/WebGPU/Extensions/engine.multiRender.pure.js +4 -0
- package/Engines/WebGPU/Extensions/engine.multiRender.pure.js.map +1 -1
- package/Engines/WebGPU/Extensions/engine.multiRender.types.d.ts +13 -0
- package/Engines/WebGPU/Extensions/engine.multiRender.types.js.map +1 -1
- package/Engines/WebGPU/Extensions/engine.query.pure.js +11 -3
- package/Engines/WebGPU/Extensions/engine.query.pure.js.map +1 -1
- package/Engines/WebGPU/Extensions/engine.renderTarget.pure.js +1 -0
- package/Engines/WebGPU/Extensions/engine.renderTarget.pure.js.map +1 -1
- package/Engines/WebGPU/Extensions/index.d.ts +1 -0
- package/Engines/WebGPU/Extensions/index.js +1 -0
- package/Engines/WebGPU/Extensions/index.js.map +1 -1
- package/Engines/WebGPU/Extensions/pure.d.ts +1 -1
- package/Engines/WebGPU/Extensions/pure.js +1 -1
- package/Engines/WebGPU/Extensions/pure.js.map +1 -1
- package/Engines/WebGPU/webgpuBundleList.d.ts +2 -0
- package/Engines/WebGPU/webgpuBundleList.js +4 -0
- package/Engines/WebGPU/webgpuBundleList.js.map +1 -1
- package/Engines/WebGPU/webgpuCacheRenderPipeline.js +5 -2
- package/Engines/WebGPU/webgpuCacheRenderPipeline.js.map +1 -1
- package/Engines/WebGPU/webgpuHardwareTexture.js +3 -1
- package/Engines/WebGPU/webgpuHardwareTexture.js.map +1 -1
- package/Engines/WebGPU/webgpuOcclusionQuery.js +1 -1
- package/Engines/WebGPU/webgpuOcclusionQuery.js.map +1 -1
- package/Engines/WebGPU/webgpuSnapshotRendering.d.ts +4 -0
- package/Engines/WebGPU/webgpuSnapshotRendering.js +40 -7
- package/Engines/WebGPU/webgpuSnapshotRendering.js.map +1 -1
- package/Engines/WebGPU/webgpuTextureHelper.d.ts +1 -1
- package/Engines/WebGPU/webgpuTextureHelper.js +2 -2
- package/Engines/WebGPU/webgpuTextureHelper.js.map +1 -1
- package/Engines/WebGPU/webgpuTextureManager.d.ts +2 -0
- package/Engines/WebGPU/webgpuTextureManager.js +286 -13
- package/Engines/WebGPU/webgpuTextureManager.js.map +1 -1
- package/Engines/abstractEngine.pure.d.ts +17 -1
- package/Engines/abstractEngine.pure.js +17 -5
- package/Engines/abstractEngine.pure.js.map +1 -1
- package/Engines/constants.d.ts +4 -0
- package/Engines/constants.js +4 -0
- package/Engines/constants.js.map +1 -1
- package/Engines/engine.pure.d.ts +0 -1
- package/Engines/engine.pure.js +0 -7
- package/Engines/engine.pure.js.map +1 -1
- package/Engines/nativeEngine.pure.js +1 -1
- package/Engines/nativeEngine.pure.js.map +1 -1
- package/Engines/thinEngine.pure.d.ts +15 -0
- package/Engines/thinEngine.pure.js +61 -14
- package/Engines/thinEngine.pure.js.map +1 -1
- package/Engines/thinNativeEngine.pure.d.ts +218 -17
- package/Engines/thinNativeEngine.pure.js +1438 -165
- package/Engines/thinNativeEngine.pure.js.map +1 -1
- package/Engines/thinWebGPUEngine.d.ts +4 -0
- package/Engines/thinWebGPUEngine.js +16 -2
- package/Engines/thinWebGPUEngine.js.map +1 -1
- package/Engines/webgpuEngine.pure.d.ts +17 -3
- package/Engines/webgpuEngine.pure.js +56 -13
- package/Engines/webgpuEngine.pure.js.map +1 -1
- package/FlowGraph/Blocks/Data/Math/flowGraphMathBlocks.pure.js +2 -2
- package/FlowGraph/Blocks/Data/Math/flowGraphMathBlocks.pure.js.map +1 -1
- package/FlowGraph/Blocks/Data/Transformers/flowGraphJsonPointerParserBlock.pure.d.ts +10 -0
- package/FlowGraph/Blocks/Data/Transformers/flowGraphJsonPointerParserBlock.pure.js +24 -12
- package/FlowGraph/Blocks/Data/Transformers/flowGraphJsonPointerParserBlock.pure.js.map +1 -1
- package/FlowGraph/Blocks/Data/Utils/flowGraphArrayIndexBlock.pure.d.ts +11 -2
- package/FlowGraph/Blocks/Data/Utils/flowGraphArrayIndexBlock.pure.js +1 -1
- package/FlowGraph/Blocks/Data/Utils/flowGraphArrayIndexBlock.pure.js.map +1 -1
- package/FlowGraph/Blocks/Data/flowGraphGetPropertyBlock.pure.d.ts +7 -0
- package/FlowGraph/Blocks/Data/flowGraphGetPropertyBlock.pure.js +43 -0
- package/FlowGraph/Blocks/Data/flowGraphGetPropertyBlock.pure.js.map +1 -1
- package/FlowGraph/Blocks/Event/flowGraphMeshPickEventBlock.pure.d.ts +9 -1
- package/FlowGraph/Blocks/Event/flowGraphMeshPickEventBlock.pure.js +6 -8
- package/FlowGraph/Blocks/Event/flowGraphMeshPickEventBlock.pure.js.map +1 -1
- package/FlowGraph/Blocks/Event/flowGraphPointerOutEventBlock.pure.d.ts +2 -0
- package/FlowGraph/Blocks/Event/flowGraphPointerOutEventBlock.pure.js +5 -1
- package/FlowGraph/Blocks/Event/flowGraphPointerOutEventBlock.pure.js.map +1 -1
- package/FlowGraph/Blocks/Event/flowGraphPointerOverEventBlock.pure.d.ts +2 -0
- package/FlowGraph/Blocks/Event/flowGraphPointerOverEventBlock.pure.js +5 -1
- package/FlowGraph/Blocks/Event/flowGraphPointerOverEventBlock.pure.js.map +1 -1
- package/FlowGraph/Blocks/Event/flowGraphReceiveCustomEventBlock.pure.d.ts +9 -0
- package/FlowGraph/Blocks/Event/flowGraphReceiveCustomEventBlock.pure.js +34 -9
- package/FlowGraph/Blocks/Event/flowGraphReceiveCustomEventBlock.pure.js.map +1 -1
- package/FlowGraph/Blocks/Event/flowGraphSceneReadyEventBlock.pure.d.ts +2 -0
- package/FlowGraph/Blocks/Event/flowGraphSceneReadyEventBlock.pure.js +4 -0
- package/FlowGraph/Blocks/Event/flowGraphSceneReadyEventBlock.pure.js.map +1 -1
- package/FlowGraph/Blocks/Event/flowGraphSceneTickEventBlock.pure.d.ts +18 -4
- package/FlowGraph/Blocks/Event/flowGraphSceneTickEventBlock.pure.js +24 -6
- package/FlowGraph/Blocks/Event/flowGraphSceneTickEventBlock.pure.js.map +1 -1
- package/FlowGraph/Blocks/Event/flowGraphSendCustomEventBlock.pure.js +19 -7
- package/FlowGraph/Blocks/Event/flowGraphSendCustomEventBlock.pure.js.map +1 -1
- package/FlowGraph/Blocks/Execution/Animation/flowGraphInterpolationBlock.pure.js +3 -3
- package/FlowGraph/Blocks/Execution/Animation/flowGraphInterpolationBlock.pure.js.map +1 -1
- package/FlowGraph/Blocks/Execution/Animation/flowGraphPlayAnimationBlock.pure.d.ts +20 -2
- package/FlowGraph/Blocks/Execution/Animation/flowGraphPlayAnimationBlock.pure.js +85 -25
- package/FlowGraph/Blocks/Execution/Animation/flowGraphPlayAnimationBlock.pure.js.map +1 -1
- package/FlowGraph/Blocks/Execution/Animation/flowGraphStopAnimationBlock.pure.d.ts +16 -1
- package/FlowGraph/Blocks/Execution/Animation/flowGraphStopAnimationBlock.pure.js +64 -14
- package/FlowGraph/Blocks/Execution/Animation/flowGraphStopAnimationBlock.pure.js.map +1 -1
- package/FlowGraph/Blocks/Execution/ControlFlow/flowGraphCancelDelayBlock.pure.d.ts +12 -1
- package/FlowGraph/Blocks/Execution/ControlFlow/flowGraphCancelDelayBlock.pure.js +8 -0
- package/FlowGraph/Blocks/Execution/ControlFlow/flowGraphCancelDelayBlock.pure.js.map +1 -1
- package/FlowGraph/Blocks/Execution/ControlFlow/flowGraphForLoopBlock.pure.js +4 -1
- package/FlowGraph/Blocks/Execution/ControlFlow/flowGraphForLoopBlock.pure.js.map +1 -1
- package/FlowGraph/Blocks/Execution/ControlFlow/flowGraphThrottleBlock.pure.d.ts +12 -1
- package/FlowGraph/Blocks/Execution/ControlFlow/flowGraphThrottleBlock.pure.js +5 -1
- package/FlowGraph/Blocks/Execution/ControlFlow/flowGraphThrottleBlock.pure.js.map +1 -1
- package/FlowGraph/Blocks/Execution/flowGraphConsoleLogBlock.pure.js +64 -16
- package/FlowGraph/Blocks/Execution/flowGraphConsoleLogBlock.pure.js.map +1 -1
- package/FlowGraph/Blocks/Execution/flowGraphSetPropertyBlock.pure.d.ts +2 -0
- package/FlowGraph/Blocks/Execution/flowGraphSetPropertyBlock.pure.js +14 -2
- package/FlowGraph/Blocks/Execution/flowGraphSetPropertyBlock.pure.js.map +1 -1
- package/FlowGraph/Blocks/Execution/flowGraphSetVariableBlock.pure.d.ts +5 -1
- package/FlowGraph/Blocks/Execution/flowGraphSetVariableBlock.pure.js +23 -8
- package/FlowGraph/Blocks/Execution/flowGraphSetVariableBlock.pure.js.map +1 -1
- package/FlowGraph/CustomTypes/flowGraphInteger.pure.d.ts +5 -0
- package/FlowGraph/CustomTypes/flowGraphInteger.pure.js +7 -0
- package/FlowGraph/CustomTypes/flowGraphInteger.pure.js.map +1 -1
- package/FlowGraph/CustomTypes/flowGraphMatrix.d.ts +10 -0
- package/FlowGraph/CustomTypes/flowGraphMatrix.js +14 -0
- package/FlowGraph/CustomTypes/flowGraphMatrix.js.map +1 -1
- package/FlowGraph/flowGraph.d.ts +6 -1
- package/FlowGraph/flowGraph.js +41 -9
- package/FlowGraph/flowGraph.js.map +1 -1
- package/FlowGraph/flowGraphAnimationHelpers.d.ts +24 -0
- package/FlowGraph/flowGraphAnimationHelpers.js +21 -0
- package/FlowGraph/flowGraphAnimationHelpers.js.map +1 -0
- package/FlowGraph/flowGraphBlock.js +3 -0
- package/FlowGraph/flowGraphBlock.js.map +1 -1
- package/FlowGraph/flowGraphConnection.d.ts +7 -0
- package/FlowGraph/flowGraphConnection.js +7 -0
- package/FlowGraph/flowGraphConnection.js.map +1 -1
- package/FlowGraph/flowGraphContext.d.ts +2 -1
- package/FlowGraph/flowGraphContext.js +5 -3
- package/FlowGraph/flowGraphContext.js.map +1 -1
- package/FlowGraph/flowGraphCoordinator.d.ts +15 -1
- package/FlowGraph/flowGraphCoordinator.js +47 -16
- package/FlowGraph/flowGraphCoordinator.js.map +1 -1
- package/FlowGraph/flowGraphEventBlock.d.ts +5 -0
- package/FlowGraph/flowGraphEventBlock.js +7 -0
- package/FlowGraph/flowGraphEventBlock.js.map +1 -1
- package/FlowGraph/flowGraphHostResolver.d.ts +2 -1
- package/FlowGraph/flowGraphHostResolver.js.map +1 -1
- package/FlowGraph/flowGraphParser.js +60 -2
- package/FlowGraph/flowGraphParser.js.map +1 -1
- package/FlowGraph/flowGraphValidator.js +0 -4
- package/FlowGraph/flowGraphValidator.js.map +1 -1
- package/FlowGraph/index.d.ts +2 -0
- package/FlowGraph/index.js +2 -0
- package/FlowGraph/index.js.map +1 -1
- package/FlowGraph/pure.d.ts +2 -0
- package/FlowGraph/pure.js +2 -0
- package/FlowGraph/pure.js.map +1 -1
- package/FlowGraph/serialization.d.ts +4 -2
- package/FlowGraph/serialization.js +12 -24
- package/FlowGraph/serialization.js.map +1 -1
- package/FlowGraph/typeDefinitions.d.ts +9 -1
- package/FlowGraph/typeDefinitions.js.map +1 -1
- package/FrameGraph/Node/Blocks/PostProcesses/meshBlendingPostProcessBlock.d.ts +5 -0
- package/FrameGraph/Node/Blocks/PostProcesses/meshBlendingPostProcessBlock.js +8 -0
- package/FrameGraph/Node/Blocks/PostProcesses/meshBlendingPostProcessBlock.js.map +1 -0
- package/FrameGraph/Node/Blocks/PostProcesses/meshBlendingPostProcessBlock.pure.d.ts +87 -0
- package/FrameGraph/Node/Blocks/PostProcesses/meshBlendingPostProcessBlock.pure.js +295 -0
- package/FrameGraph/Node/Blocks/PostProcesses/meshBlendingPostProcessBlock.pure.js.map +1 -0
- package/FrameGraph/Node/Blocks/PostProcesses/pure.d.ts +1 -0
- package/FrameGraph/Node/Blocks/PostProcesses/pure.js +1 -0
- package/FrameGraph/Node/Blocks/PostProcesses/pure.js.map +1 -1
- package/FrameGraph/Node/Blocks/Rendering/baseObjectRendererBlock.js +4 -4
- package/FrameGraph/Node/Blocks/Rendering/baseObjectRendererBlock.js.map +1 -1
- package/FrameGraph/Node/Blocks/Rendering/geometryRendererBlock.pure.d.ts +5 -1
- package/FrameGraph/Node/Blocks/Rendering/geometryRendererBlock.pure.js +13 -1
- package/FrameGraph/Node/Blocks/Rendering/geometryRendererBlock.pure.js.map +1 -1
- package/FrameGraph/Node/Blocks/Textures/minMaxReducerBlock.d.ts +1 -0
- package/FrameGraph/Node/Blocks/Textures/minMaxReducerBlock.js +4 -0
- package/FrameGraph/Node/Blocks/Textures/minMaxReducerBlock.js.map +1 -0
- package/FrameGraph/Node/Blocks/Textures/minMaxReducerBlock.pure.d.ts +54 -0
- package/FrameGraph/Node/Blocks/Textures/minMaxReducerBlock.pure.js +155 -0
- package/FrameGraph/Node/Blocks/Textures/minMaxReducerBlock.pure.js.map +1 -0
- package/FrameGraph/Node/Blocks/Textures/pure.d.ts +1 -0
- package/FrameGraph/Node/Blocks/Textures/pure.js +1 -0
- package/FrameGraph/Node/Blocks/Textures/pure.js.map +1 -1
- package/FrameGraph/Node/Blocks/allBlocks.pure.js +4 -0
- package/FrameGraph/Node/Blocks/allBlocks.pure.js.map +1 -1
- package/FrameGraph/Node/Blocks/index.d.ts +2 -0
- package/FrameGraph/Node/Blocks/index.js +2 -0
- package/FrameGraph/Node/Blocks/index.js.map +1 -1
- package/FrameGraph/Node/Blocks/inputBlock.pure.js +20 -1
- package/FrameGraph/Node/Blocks/inputBlock.pure.js.map +1 -1
- package/FrameGraph/Node/Blocks/pure.d.ts +2 -0
- package/FrameGraph/Node/Blocks/pure.js +2 -0
- package/FrameGraph/Node/Blocks/pure.js.map +1 -1
- package/FrameGraph/Node/Types/nodeRenderGraphTypes.d.ts +4 -2
- package/FrameGraph/Node/Types/nodeRenderGraphTypes.js +4 -2
- package/FrameGraph/Node/Types/nodeRenderGraphTypes.js.map +1 -1
- package/FrameGraph/Node/nodeRenderGraph.js +1 -1
- package/FrameGraph/Node/nodeRenderGraph.js.map +1 -1
- package/FrameGraph/Tasks/Layers/selectionOutlineTask.js +1 -0
- package/FrameGraph/Tasks/Layers/selectionOutlineTask.js.map +1 -1
- package/FrameGraph/Tasks/Misc/cullObjectsTask.js +5 -1
- package/FrameGraph/Tasks/Misc/cullObjectsTask.js.map +1 -1
- package/FrameGraph/Tasks/Misc/lightingVolumeTask.js +1 -0
- package/FrameGraph/Tasks/Misc/lightingVolumeTask.js.map +1 -1
- package/FrameGraph/Tasks/Misc/minMaxReducerTask.d.ts +62 -0
- package/FrameGraph/Tasks/Misc/minMaxReducerTask.js +159 -0
- package/FrameGraph/Tasks/Misc/minMaxReducerTask.js.map +1 -0
- package/FrameGraph/Tasks/PostProcesses/meshBlendingTask.d.ts +69 -0
- package/FrameGraph/Tasks/PostProcesses/meshBlendingTask.js +223 -0
- package/FrameGraph/Tasks/PostProcesses/meshBlendingTask.js.map +1 -0
- package/FrameGraph/Tasks/Rendering/geometryRendererTask.d.ts +25 -3
- package/FrameGraph/Tasks/Rendering/geometryRendererTask.js +72 -34
- package/FrameGraph/Tasks/Rendering/geometryRendererTask.js.map +1 -1
- package/FrameGraph/Tasks/Rendering/objectRendererTask.js +3 -1
- package/FrameGraph/Tasks/Rendering/objectRendererTask.js.map +1 -1
- package/FrameGraph/frameGraph.d.ts +4 -0
- package/FrameGraph/frameGraph.js +14 -0
- package/FrameGraph/frameGraph.js.map +1 -1
- package/FrameGraph/frameGraphObjectList.d.ts +6 -1
- package/FrameGraph/frameGraphObjectList.js.map +1 -1
- package/FrameGraph/frameGraphRenderContext.d.ts +3 -1
- package/FrameGraph/frameGraphRenderContext.js +5 -5
- package/FrameGraph/frameGraphRenderContext.js.map +1 -1
- package/FrameGraph/index.d.ts +2 -0
- package/FrameGraph/index.js +2 -0
- package/FrameGraph/index.js.map +1 -1
- package/FrameGraph/pure.d.ts +2 -0
- package/FrameGraph/pure.js +2 -0
- package/FrameGraph/pure.js.map +1 -1
- package/Inputs/scene.inputManager.d.ts +4 -0
- package/Inputs/scene.inputManager.js +50 -8
- package/Inputs/scene.inputManager.js.map +1 -1
- package/Lights/Clustered/clusteredLightingSceneComponent.pure.d.ts +5 -0
- package/Lights/Clustered/clusteredLightingSceneComponent.pure.js +22 -1
- package/Lights/Clustered/clusteredLightingSceneComponent.pure.js.map +1 -1
- package/Lights/Shadows/cascadedShadowGenerator.pure.js +7 -3
- package/Lights/Shadows/cascadedShadowGenerator.pure.js.map +1 -1
- package/Materials/GaussianSplatting/gaussianPointSplattingBlitMaterial.d.ts +7 -0
- package/Materials/GaussianSplatting/gaussianPointSplattingBlitMaterial.js +8 -0
- package/Materials/GaussianSplatting/gaussianPointSplattingBlitMaterial.js.map +1 -0
- package/Materials/GaussianSplatting/gaussianPointSplattingBlitMaterial.pure.d.ts +54 -0
- package/Materials/GaussianSplatting/gaussianPointSplattingBlitMaterial.pure.js +81 -0
- package/Materials/GaussianSplatting/gaussianPointSplattingBlitMaterial.pure.js.map +1 -0
- package/Materials/GaussianSplatting/gaussianPointSplattingDepthBlitMaterial.d.ts +7 -0
- package/Materials/GaussianSplatting/gaussianPointSplattingDepthBlitMaterial.js +8 -0
- package/Materials/GaussianSplatting/gaussianPointSplattingDepthBlitMaterial.js.map +1 -0
- package/Materials/GaussianSplatting/gaussianPointSplattingDepthBlitMaterial.pure.d.ts +60 -0
- package/Materials/GaussianSplatting/gaussianPointSplattingDepthBlitMaterial.pure.js +90 -0
- package/Materials/GaussianSplatting/gaussianPointSplattingDepthBlitMaterial.pure.js.map +1 -0
- package/Materials/GaussianSplatting/gaussianSplattingDebugMaterialPlugin.pure.d.ts +31 -0
- package/Materials/GaussianSplatting/gaussianSplattingDebugMaterialPlugin.pure.js +103 -5
- package/Materials/GaussianSplatting/gaussianSplattingDebugMaterialPlugin.pure.js.map +1 -1
- package/Materials/GaussianSplatting/gaussianSplattingGpuPickingMaterialPlugin.pure.js +6 -6
- package/Materials/GaussianSplatting/gaussianSplattingGpuPickingMaterialPlugin.pure.js.map +1 -1
- package/Materials/GaussianSplatting/gaussianSplattingMaterial.pure.d.ts +26 -1
- package/Materials/GaussianSplatting/gaussianSplattingMaterial.pure.js +153 -49
- package/Materials/GaussianSplatting/gaussianSplattingMaterial.pure.js.map +1 -1
- package/Materials/GaussianSplatting/gaussianSplattingOverdrawMaterialPlugin.d.ts +1 -0
- package/Materials/GaussianSplatting/gaussianSplattingOverdrawMaterialPlugin.js +4 -0
- package/Materials/GaussianSplatting/gaussianSplattingOverdrawMaterialPlugin.js.map +1 -0
- package/Materials/GaussianSplatting/gaussianSplattingOverdrawMaterialPlugin.pure.d.ts +83 -0
- package/Materials/GaussianSplatting/gaussianSplattingOverdrawMaterialPlugin.pure.js +191 -0
- package/Materials/GaussianSplatting/gaussianSplattingOverdrawMaterialPlugin.pure.js.map +1 -0
- package/Materials/GaussianSplatting/gaussianSplattingSizeMaterialPlugin.d.ts +1 -0
- package/Materials/GaussianSplatting/gaussianSplattingSizeMaterialPlugin.js +4 -0
- package/Materials/GaussianSplatting/gaussianSplattingSizeMaterialPlugin.js.map +1 -0
- package/Materials/GaussianSplatting/gaussianSplattingSizeMaterialPlugin.pure.d.ts +62 -0
- package/Materials/GaussianSplatting/gaussianSplattingSizeMaterialPlugin.pure.js +125 -0
- package/Materials/GaussianSplatting/gaussianSplattingSizeMaterialPlugin.pure.js.map +1 -0
- package/Materials/GaussianSplatting/gaussianSplattingSolidColorMaterialPlugin.pure.js +5 -5
- package/Materials/GaussianSplatting/gaussianSplattingSolidColorMaterialPlugin.pure.js.map +1 -1
- package/Materials/GaussianSplatting/pure.d.ts +4 -0
- package/Materials/GaussianSplatting/pure.js +4 -0
- package/Materials/GaussianSplatting/pure.js.map +1 -1
- package/Materials/Node/Blocks/Dual/imageSourceBlock.pure.d.ts +1 -0
- package/Materials/Node/Blocks/Dual/imageSourceBlock.pure.js +12 -0
- package/Materials/Node/Blocks/Dual/imageSourceBlock.pure.js.map +1 -1
- package/Materials/Node/Blocks/Fragment/fragmentOutputBlock.pure.js +11 -1
- package/Materials/Node/Blocks/Fragment/fragmentOutputBlock.pure.js.map +1 -1
- package/Materials/Node/Blocks/Fragment/prePassOutputBlock.pure.js +17 -2
- package/Materials/Node/Blocks/Fragment/prePassOutputBlock.pure.js.map +1 -1
- package/Materials/Node/Blocks/GaussianSplatting/gaussianSplattingBlock.pure.js +2 -2
- package/Materials/Node/Blocks/GaussianSplatting/gaussianSplattingBlock.pure.js.map +1 -1
- package/Materials/Node/nodeMaterial.pure.d.ts +4 -0
- package/Materials/Node/nodeMaterial.pure.js +4 -0
- package/Materials/Node/nodeMaterial.pure.js.map +1 -1
- package/Materials/Node/nodeMaterialBuildState.d.ts +1 -1
- package/Materials/Node/nodeMaterialBuildState.js +25 -3
- package/Materials/Node/nodeMaterialBuildState.js.map +1 -1
- package/Materials/PBR/openpbrMaterial.pure.d.ts +2 -0
- package/Materials/PBR/pbrBaseMaterial.pure.d.ts +2 -0
- package/Materials/Textures/Procedurals/proceduralTexture.pure.d.ts +14 -14
- package/Materials/Textures/Procedurals/proceduralTexture.pure.js +37 -13
- package/Materials/Textures/Procedurals/proceduralTexture.pure.js.map +1 -1
- package/Materials/Textures/baseTexture.pure.js +3 -0
- package/Materials/Textures/baseTexture.pure.js.map +1 -1
- package/Materials/Textures/cubeTexture.pure.js +1 -1
- package/Materials/Textures/cubeTexture.pure.js.map +1 -1
- package/Materials/Textures/internalTexture.d.ts +8 -1
- package/Materials/Textures/internalTexture.js +9 -2
- package/Materials/Textures/internalTexture.js.map +1 -1
- package/Materials/Textures/mirrorTexture.pure.js +3 -1
- package/Materials/Textures/mirrorTexture.pure.js.map +1 -1
- package/Materials/Textures/rawTexture2DArray.functions.d.ts +3 -3
- package/Materials/Textures/rawTexture2DArray.functions.js.map +1 -1
- package/Materials/Textures/rawTexture3D.d.ts +1 -1
- package/Materials/Textures/rawTexture3D.js +1 -1
- package/Materials/Textures/rawTexture3D.js.map +1 -1
- package/Materials/Textures/texture.pure.js +1 -1
- package/Materials/Textures/texture.pure.js.map +1 -1
- package/Materials/Textures/textureHelper.functions.d.ts +14 -0
- package/Materials/Textures/textureHelper.functions.js +24 -0
- package/Materials/Textures/textureHelper.functions.js.map +1 -1
- package/Materials/ditheredTileFadeMaterialPlugin.d.ts +210 -0
- package/Materials/ditheredTileFadeMaterialPlugin.js +509 -0
- package/Materials/ditheredTileFadeMaterialPlugin.js.map +1 -0
- package/Materials/effectRenderer.pure.d.ts +4 -0
- package/Materials/effectRenderer.pure.js +3 -2
- package/Materials/effectRenderer.pure.js.map +1 -1
- package/Materials/index.d.ts +5 -0
- package/Materials/index.js +5 -0
- package/Materials/index.js.map +1 -1
- package/Materials/material.pure.js +25 -12
- package/Materials/material.pure.js.map +1 -1
- package/Materials/materialHelper.geometryrendering.d.ts +46 -1
- package/Materials/materialHelper.geometryrendering.js +105 -8
- package/Materials/materialHelper.geometryrendering.js.map +1 -1
- package/Materials/prepass.defines.d.ts +2 -0
- package/Materials/prepass.defines.js +2 -0
- package/Materials/prepass.defines.js.map +1 -1
- package/Materials/pure.d.ts +5 -0
- package/Materials/pure.js +5 -0
- package/Materials/pure.js.map +1 -1
- package/Materials/standardMaterial.pure.d.ts +10 -0
- package/Materials/standardMaterial.pure.js +30 -5
- package/Materials/standardMaterial.pure.js.map +1 -1
- package/Meshes/Builders/polygonBuilder.pure.d.ts +4 -0
- package/Meshes/Builders/polygonBuilder.pure.js +3 -0
- package/Meshes/Builders/polygonBuilder.pure.js.map +1 -1
- package/Meshes/GaussianSplatting/gaussianPointSplattingController.d.ts +8 -0
- package/Meshes/GaussianSplatting/gaussianPointSplattingController.js +11 -0
- package/Meshes/GaussianSplatting/gaussianPointSplattingController.js.map +1 -0
- package/Meshes/GaussianSplatting/gaussianPointSplattingController.pure.d.ts +231 -0
- package/Meshes/GaussianSplatting/gaussianPointSplattingController.pure.js +1212 -0
- package/Meshes/GaussianSplatting/gaussianPointSplattingController.pure.js.map +1 -0
- package/Meshes/GaussianSplatting/gaussianPointSplattingRenderer.d.ts +14 -0
- package/Meshes/GaussianSplatting/gaussianPointSplattingRenderer.js +15 -0
- package/Meshes/GaussianSplatting/gaussianPointSplattingRenderer.js.map +1 -0
- package/Meshes/GaussianSplatting/gaussianPointSplattingRenderer.pure.d.ts +285 -0
- package/Meshes/GaussianSplatting/gaussianPointSplattingRenderer.pure.js +812 -0
- package/Meshes/GaussianSplatting/gaussianPointSplattingRenderer.pure.js.map +1 -0
- package/Meshes/GaussianSplatting/gaussianSplatting.functions.d.ts +19 -0
- package/Meshes/GaussianSplatting/gaussianSplatting.functions.js +23 -0
- package/Meshes/GaussianSplatting/gaussianSplatting.functions.js.map +1 -0
- package/Meshes/GaussianSplatting/gaussianSplattingMesh.d.ts +1 -0
- package/Meshes/GaussianSplatting/gaussianSplattingMesh.js +2 -0
- package/Meshes/GaussianSplatting/gaussianSplattingMesh.js.map +1 -1
- package/Meshes/GaussianSplatting/gaussianSplattingMesh.pure.d.ts +163 -14
- package/Meshes/GaussianSplatting/gaussianSplattingMesh.pure.js +239 -24
- package/Meshes/GaussianSplatting/gaussianSplattingMesh.pure.js.map +1 -1
- package/Meshes/GaussianSplatting/gaussianSplattingMeshBase.pure.d.ts +34 -4
- package/Meshes/GaussianSplatting/gaussianSplattingMeshBase.pure.js +125 -25
- package/Meshes/GaussianSplatting/gaussianSplattingMeshBase.pure.js.map +1 -1
- package/Meshes/GaussianSplatting/pure.d.ts +2 -0
- package/Meshes/GaussianSplatting/pure.js +2 -0
- package/Meshes/GaussianSplatting/pure.js.map +1 -1
- package/Meshes/Node/Blocks/booleanGeometryBlock.pure.js +25 -11
- package/Meshes/Node/Blocks/booleanGeometryBlock.pure.js.map +1 -1
- package/Meshes/abstractMesh.pure.d.ts +30 -0
- package/Meshes/abstractMesh.pure.js +54 -0
- package/Meshes/abstractMesh.pure.js.map +1 -1
- package/Meshes/index.d.ts +2 -0
- package/Meshes/index.js +2 -0
- package/Meshes/index.js.map +1 -1
- package/Meshes/instancedMesh.pure.d.ts +5 -0
- package/Meshes/instancedMesh.pure.js +12 -0
- package/Meshes/instancedMesh.pure.js.map +1 -1
- package/Meshes/mesh.pure.js +23 -8
- package/Meshes/mesh.pure.js.map +1 -1
- package/Meshes/meshBlendingTag.d.ts +47 -0
- package/Meshes/meshBlendingTag.js +64 -0
- package/Meshes/meshBlendingTag.js.map +1 -0
- package/Meshes/polygonMesh.js +2 -2
- package/Meshes/polygonMesh.js.map +1 -1
- package/Meshes/pure.d.ts +2 -0
- package/Meshes/pure.js +2 -0
- package/Meshes/pure.js.map +1 -1
- package/Meshes/subMesh.pure.d.ts +11 -2
- package/Meshes/subMesh.pure.js +20 -5
- package/Meshes/subMesh.pure.js.map +1 -1
- package/Meshes/thinInstanceMesh.pure.js +1 -0
- package/Meshes/thinInstanceMesh.pure.js.map +1 -1
- package/Misc/andOrNotEvaluator.js +4 -0
- package/Misc/andOrNotEvaluator.js.map +1 -1
- package/Misc/fileTools.pure.js +21 -0
- package/Misc/fileTools.pure.js.map +1 -1
- package/Misc/minMaxReducer.pure.d.ts +6 -0
- package/Misc/minMaxReducer.pure.js +10 -0
- package/Misc/minMaxReducer.pure.js.map +1 -1
- package/Misc/snapshotRenderingHelper.js +2 -2
- package/Misc/snapshotRenderingHelper.js.map +1 -1
- package/Misc/thinMinMaxReducer.d.ts +19 -2
- package/Misc/thinMinMaxReducer.js +74 -21
- package/Misc/thinMinMaxReducer.js.map +1 -1
- package/Misc/tools.pure.js +1 -1
- package/Misc/tools.pure.js.map +1 -1
- package/Particles/Node/Blocks/Update/updateNoiseBlock.pure.js +19 -7
- package/Particles/Node/Blocks/Update/updateNoiseBlock.pure.js.map +1 -1
- package/Particles/Node/Blocks/particleSourceTextureBlock.pure.js +3 -2
- package/Particles/Node/Blocks/particleSourceTextureBlock.pure.js.map +1 -1
- package/Particles/gpuParticleSystem.pure.d.ts +4 -0
- package/Particles/gpuParticleSystem.pure.js +101 -32
- package/Particles/gpuParticleSystem.pure.js.map +1 -1
- package/Particles/particle.js +3 -2
- package/Particles/particle.js.map +1 -1
- package/Particles/solidParticleSystem.js +7 -1
- package/Particles/solidParticleSystem.js.map +1 -1
- package/Particles/thinParticleSystem.function.d.ts +6 -0
- package/Particles/thinParticleSystem.function.js +144 -88
- package/Particles/thinParticleSystem.function.js.map +1 -1
- package/Particles/thinParticleSystem.pure.d.ts +8 -0
- package/Particles/thinParticleSystem.pure.js +154 -28
- package/Particles/thinParticleSystem.pure.js.map +1 -1
- package/Particles/webgl2ParticleSystem.pure.d.ts +1 -0
- package/Particles/webgl2ParticleSystem.pure.js +12 -4
- package/Particles/webgl2ParticleSystem.pure.js.map +1 -1
- package/Physics/v2/ragdoll.d.ts +2 -4
- package/Physics/v2/ragdoll.js +11 -4
- package/Physics/v2/ragdoll.js.map +1 -1
- package/PostProcesses/RenderPipeline/Pipelines/lensRenderingPipeline.pure.js +7 -0
- package/PostProcesses/RenderPipeline/Pipelines/lensRenderingPipeline.pure.js.map +1 -1
- package/PostProcesses/index.d.ts +2 -0
- package/PostProcesses/index.js +2 -0
- package/PostProcesses/index.js.map +1 -1
- package/PostProcesses/meshBlendingBlueNoise.d.ts +15 -0
- package/PostProcesses/meshBlendingBlueNoise.js +77 -0
- package/PostProcesses/meshBlendingBlueNoise.js.map +1 -0
- package/PostProcesses/meshBlendingPostProcess.d.ts +131 -0
- package/PostProcesses/meshBlendingPostProcess.js +315 -0
- package/PostProcesses/meshBlendingPostProcess.js.map +1 -0
- package/PostProcesses/pure.d.ts +2 -0
- package/PostProcesses/pure.js +2 -0
- package/PostProcesses/pure.js.map +1 -1
- package/PostProcesses/thinMeshBlendingPostProcess.d.ts +339 -0
- package/PostProcesses/thinMeshBlendingPostProcess.js +771 -0
- package/PostProcesses/thinMeshBlendingPostProcess.js.map +1 -0
- package/Rendering/IBLShadows/iblShadowsRenderPipeline.pure.js +6 -6
- package/Rendering/IBLShadows/iblShadowsRenderPipeline.pure.js.map +1 -1
- package/Rendering/IBLShadows/iblShadowsVoxelRenderer.pure.d.ts +12 -0
- package/Rendering/IBLShadows/iblShadowsVoxelRenderer.pure.js +50 -25
- package/Rendering/IBLShadows/iblShadowsVoxelRenderer.pure.js.map +1 -1
- package/Rendering/boundingBoxRenderer.pure.js +2 -1
- package/Rendering/boundingBoxRenderer.pure.js.map +1 -1
- package/Rendering/depthRenderer.pure.d.ts +9 -0
- package/Rendering/depthRenderer.pure.js +15 -4
- package/Rendering/depthRenderer.pure.js.map +1 -1
- package/Rendering/edgesRenderer.pure.d.ts +4 -2
- package/Rendering/edgesRenderer.pure.js +11 -2
- package/Rendering/edgesRenderer.pure.js.map +1 -1
- package/Rendering/fluidRenderer/fluidRenderingObject.d.ts +14 -0
- package/Rendering/fluidRenderer/fluidRenderingObject.js +26 -0
- package/Rendering/fluidRenderer/fluidRenderingObject.js.map +1 -1
- package/Rendering/fluidRenderer/fluidRenderingObjectParticleSystem.d.ts +13 -3
- package/Rendering/fluidRenderer/fluidRenderingObjectParticleSystem.js +22 -9
- package/Rendering/fluidRenderer/fluidRenderingObjectParticleSystem.js.map +1 -1
- package/Rendering/fluidRenderer/fluidRenderingTargetRenderer.js +3 -0
- package/Rendering/fluidRenderer/fluidRenderingTargetRenderer.js.map +1 -1
- package/Rendering/geometryBufferRenderer.pure.d.ts +38 -4
- package/Rendering/geometryBufferRenderer.pure.js +130 -18
- package/Rendering/geometryBufferRenderer.pure.js.map +1 -1
- package/Rendering/objectRenderer.d.ts +7 -1
- package/Rendering/objectRenderer.js +45 -7
- package/Rendering/objectRenderer.js.map +1 -1
- package/Rendering/outlineRenderer.pure.js +6 -2
- package/Rendering/outlineRenderer.pure.js.map +1 -1
- package/Rendering/prePassRenderer.pure.js +3 -3
- package/Rendering/prePassRenderer.pure.js.map +1 -1
- package/Rendering/renderingManager.d.ts +1 -1
- package/Rendering/renderingManager.js +5 -4
- package/Rendering/renderingManager.js.map +1 -1
- package/Shaders/ShadersInclude/defaultFragmentAlpha.d.ts +5 -0
- package/Shaders/ShadersInclude/defaultFragmentAlpha.js +34 -0
- package/Shaders/ShadersInclude/defaultFragmentAlpha.js.map +1 -0
- package/Shaders/ShadersInclude/gaussianSplatting.js +3 -1
- package/Shaders/ShadersInclude/gaussianSplatting.js.map +1 -1
- package/Shaders/ShadersInclude/gaussianSplattingVertexDeclaration.js +5 -1
- package/Shaders/ShadersInclude/gaussianSplattingVertexDeclaration.js.map +1 -1
- package/Shaders/ShadersInclude/geometryRenderingFragment.d.ts +5 -0
- package/Shaders/ShadersInclude/geometryRenderingFragment.js +74 -0
- package/Shaders/ShadersInclude/geometryRenderingFragment.js.map +1 -0
- package/Shaders/ShadersInclude/lightsFragmentFunctions.js +27 -3
- package/Shaders/ShadersInclude/lightsFragmentFunctions.js.map +1 -1
- package/Shaders/ShadersInclude/mrtFragmentDeclaration.js +89 -0
- package/Shaders/ShadersInclude/mrtFragmentDeclaration.js.map +1 -1
- package/Shaders/ShadersInclude/oitDeclaration.js +1 -1
- package/Shaders/ShadersInclude/oitDeclaration.js.map +1 -1
- package/Shaders/ShadersInclude/openpbrBlockPrePass.js +24 -17
- package/Shaders/ShadersInclude/openpbrBlockPrePass.js.map +1 -1
- package/Shaders/ShadersInclude/pbrBlockPrePass.js +27 -20
- package/Shaders/ShadersInclude/pbrBlockPrePass.js.map +1 -1
- package/Shaders/ShadersInclude/pbrDebug.js +6 -2
- package/Shaders/ShadersInclude/pbrDebug.js.map +1 -1
- package/Shaders/ShadersInclude/prePassDeclaration.js +95 -2
- package/Shaders/ShadersInclude/prePassDeclaration.js.map +1 -1
- package/Shaders/default.fragment.js +31 -40
- package/Shaders/default.fragment.js.map +1 -1
- package/Shaders/depthOfField.fragment.js +13 -9
- package/Shaders/depthOfField.fragment.js.map +1 -1
- package/Shaders/fluidRenderingParticleDepth.vertex.js +16 -1
- package/Shaders/fluidRenderingParticleDepth.vertex.js.map +1 -1
- package/Shaders/fluidRenderingParticleThickness.vertex.js +16 -1
- package/Shaders/fluidRenderingParticleThickness.vertex.js.map +1 -1
- package/Shaders/gaussianSplatting.fragment.js +63 -3
- package/Shaders/gaussianSplatting.fragment.js.map +1 -1
- package/Shaders/gaussianSplatting.vertex.js +80 -0
- package/Shaders/gaussianSplatting.vertex.js.map +1 -1
- package/Shaders/geometry.fragment.js +17 -11
- package/Shaders/geometry.fragment.js.map +1 -1
- package/Shaders/gpuRenderParticles.fragment.js +43 -1
- package/Shaders/gpuRenderParticles.fragment.js.map +1 -1
- package/Shaders/gpuRenderParticles.vertex.js +96 -16
- package/Shaders/gpuRenderParticles.vertex.js.map +1 -1
- package/Shaders/meshBlending.fragment.d.ts +5 -0
- package/Shaders/meshBlending.fragment.js +519 -0
- package/Shaders/meshBlending.fragment.js.map +1 -0
- package/Shaders/minmaxRedux.fragment.js +6 -1
- package/Shaders/minmaxRedux.fragment.js.map +1 -1
- package/Shaders/particles.fragment.js +43 -1
- package/Shaders/particles.fragment.js.map +1 -1
- package/Shaders/particles.vertex.js +84 -3
- package/Shaders/particles.vertex.js.map +1 -1
- package/Shaders/sprites.fragment.js +52 -2
- package/Shaders/sprites.fragment.js.map +1 -1
- package/Shaders/sprites.vertex.js +62 -1
- package/Shaders/sprites.vertex.js.map +1 -1
- package/ShadersWGSL/ShadersInclude/defaultFragmentAlpha.d.ts +5 -0
- package/ShadersWGSL/ShadersInclude/defaultFragmentAlpha.js +33 -0
- package/ShadersWGSL/ShadersInclude/defaultFragmentAlpha.js.map +1 -0
- package/ShadersWGSL/ShadersInclude/gaussianPointSplatting.d.ts +5 -0
- package/ShadersWGSL/ShadersInclude/gaussianPointSplatting.js +65 -0
- package/ShadersWGSL/ShadersInclude/gaussianPointSplatting.js.map +1 -0
- package/ShadersWGSL/ShadersInclude/gaussianPointSplattingScan.d.ts +5 -0
- package/ShadersWGSL/ShadersInclude/gaussianPointSplattingScan.js +17 -0
- package/ShadersWGSL/ShadersInclude/gaussianPointSplattingScan.js.map +1 -0
- package/ShadersWGSL/ShadersInclude/gaussianSplatting.d.ts +1 -0
- package/ShadersWGSL/ShadersInclude/gaussianSplatting.js +6 -78
- package/ShadersWGSL/ShadersInclude/gaussianSplatting.js.map +1 -1
- package/ShadersWGSL/ShadersInclude/gaussianSplattingFragmentDeclaration.js +2 -2
- package/ShadersWGSL/ShadersInclude/gaussianSplattingFragmentDeclaration.js.map +1 -1
- package/ShadersWGSL/ShadersInclude/gaussianSplattingShared.d.ts +5 -0
- package/ShadersWGSL/ShadersInclude/gaussianSplattingShared.js +79 -0
- package/ShadersWGSL/ShadersInclude/gaussianSplattingShared.js.map +1 -0
- package/ShadersWGSL/ShadersInclude/geometryRenderingFragment.d.ts +6 -0
- package/ShadersWGSL/ShadersInclude/geometryRenderingFragment.js +76 -0
- package/ShadersWGSL/ShadersInclude/geometryRenderingFragment.js.map +1 -0
- package/ShadersWGSL/ShadersInclude/lightFragment.js +1 -1
- package/ShadersWGSL/ShadersInclude/lightFragment.js.map +1 -1
- package/ShadersWGSL/ShadersInclude/lightsFragmentFunctions.js +27 -3
- package/ShadersWGSL/ShadersInclude/lightsFragmentFunctions.js.map +1 -1
- package/ShadersWGSL/ShadersInclude/meshBlendTagFragmentOutput.d.ts +5 -0
- package/ShadersWGSL/ShadersInclude/meshBlendTagFragmentOutput.js +18 -0
- package/ShadersWGSL/ShadersInclude/meshBlendTagFragmentOutput.js.map +1 -0
- package/ShadersWGSL/ShadersInclude/openpbrBlockPrePass.d.ts +1 -0
- package/ShadersWGSL/ShadersInclude/openpbrBlockPrePass.js +11 -25
- package/ShadersWGSL/ShadersInclude/openpbrBlockPrePass.js.map +1 -1
- package/ShadersWGSL/ShadersInclude/pbrBlockPrePass.d.ts +1 -0
- package/ShadersWGSL/ShadersInclude/pbrBlockPrePass.js +11 -25
- package/ShadersWGSL/ShadersInclude/pbrBlockPrePass.js.map +1 -1
- package/ShadersWGSL/ShadersInclude/pbrDebug.js +5 -1
- package/ShadersWGSL/ShadersInclude/pbrDebug.js.map +1 -1
- package/ShadersWGSL/ShadersInclude/prePassDeclaration.js +6 -1
- package/ShadersWGSL/ShadersInclude/prePassDeclaration.js.map +1 -1
- package/ShadersWGSL/default.fragment.js +17 -48
- package/ShadersWGSL/default.fragment.js.map +1 -1
- package/ShadersWGSL/fluidRenderingParticleDepth.vertex.js +15 -2
- package/ShadersWGSL/fluidRenderingParticleDepth.vertex.js.map +1 -1
- package/ShadersWGSL/fluidRenderingParticleThickness.vertex.js +15 -2
- package/ShadersWGSL/fluidRenderingParticleThickness.vertex.js.map +1 -1
- package/ShadersWGSL/gaussianPointSplattingBlit.fragment.d.ts +5 -0
- package/ShadersWGSL/gaussianPointSplattingBlit.fragment.js +22 -0
- package/ShadersWGSL/gaussianPointSplattingBlit.fragment.js.map +1 -0
- package/ShadersWGSL/gaussianPointSplattingBlit.vertex.d.ts +5 -0
- package/ShadersWGSL/gaussianPointSplattingBlit.vertex.js +19 -0
- package/ShadersWGSL/gaussianPointSplattingBlit.vertex.js.map +1 -0
- package/ShadersWGSL/gaussianPointSplattingDepthBlit.fragment.d.ts +5 -0
- package/ShadersWGSL/gaussianPointSplattingDepthBlit.fragment.js +21 -0
- package/ShadersWGSL/gaussianPointSplattingDepthBlit.fragment.js.map +1 -0
- package/ShadersWGSL/gaussianSplatting.fragment.js +63 -2
- package/ShadersWGSL/gaussianSplatting.fragment.js.map +1 -1
- package/ShadersWGSL/gaussianSplatting.vertex.js +82 -1
- package/ShadersWGSL/gaussianSplatting.vertex.js.map +1 -1
- package/ShadersWGSL/gaussianSplattingDepth.vertex.js +2 -1
- package/ShadersWGSL/gaussianSplattingDepth.vertex.js.map +1 -1
- package/ShadersWGSL/gaussianSplattingVoxel.vertex.js +2 -1
- package/ShadersWGSL/gaussianSplattingVoxel.vertex.js.map +1 -1
- package/ShadersWGSL/geometry.fragment.js +37 -2
- package/ShadersWGSL/geometry.fragment.js.map +1 -1
- package/ShadersWGSL/gpsHiZBuild.compute.d.ts +5 -0
- package/ShadersWGSL/gpsHiZBuild.compute.js +16 -0
- package/ShadersWGSL/gpsHiZBuild.compute.js.map +1 -0
- package/ShadersWGSL/gpsPartition.compute.d.ts +5 -0
- package/ShadersWGSL/gpsPartition.compute.js +27 -0
- package/ShadersWGSL/gpsPartition.compute.js.map +1 -0
- package/ShadersWGSL/gpsPreprocess.compute.d.ts +5 -0
- package/ShadersWGSL/gpsPreprocess.compute.js +86 -0
- package/ShadersWGSL/gpsPreprocess.compute.js.map +1 -0
- package/ShadersWGSL/gpsResolve.compute.d.ts +5 -0
- package/ShadersWGSL/gpsResolve.compute.js +41 -0
- package/ShadersWGSL/gpsResolve.compute.js.map +1 -0
- package/ShadersWGSL/gpsScanAdd.compute.d.ts +5 -0
- package/ShadersWGSL/gpsScanAdd.compute.js +22 -0
- package/ShadersWGSL/gpsScanAdd.compute.js.map +1 -0
- package/ShadersWGSL/gpsScanBlocks.compute.d.ts +5 -0
- package/ShadersWGSL/gpsScanBlocks.compute.js +23 -0
- package/ShadersWGSL/gpsScanBlocks.compute.js.map +1 -0
- package/ShadersWGSL/gpsScanSums.compute.d.ts +5 -0
- package/ShadersWGSL/gpsScanSums.compute.js +30 -0
- package/ShadersWGSL/gpsScanSums.compute.js.map +1 -0
- package/ShadersWGSL/gpsSplat.compute.d.ts +5 -0
- package/ShadersWGSL/gpsSplat.compute.js +37 -0
- package/ShadersWGSL/gpsSplat.compute.js.map +1 -0
- package/ShadersWGSL/gpuRenderParticles.fragment.js +47 -2
- package/ShadersWGSL/gpuRenderParticles.fragment.js.map +1 -1
- package/ShadersWGSL/gpuRenderParticles.vertex.js +110 -7
- package/ShadersWGSL/gpuRenderParticles.vertex.js.map +1 -1
- package/ShadersWGSL/meshBlending.fragment.d.ts +5 -0
- package/ShadersWGSL/meshBlending.fragment.js +576 -0
- package/ShadersWGSL/meshBlending.fragment.js.map +1 -0
- package/ShadersWGSL/minmaxRedux.fragment.js +20 -3
- package/ShadersWGSL/minmaxRedux.fragment.js.map +1 -1
- package/ShadersWGSL/openpbr.fragment.js +2 -1
- package/ShadersWGSL/openpbr.fragment.js.map +1 -1
- package/ShadersWGSL/particles.fragment.js +45 -1
- package/ShadersWGSL/particles.fragment.js.map +1 -1
- package/ShadersWGSL/particles.vertex.js +86 -4
- package/ShadersWGSL/particles.vertex.js.map +1 -1
- package/ShadersWGSL/pbr.fragment.js +2 -1
- package/ShadersWGSL/pbr.fragment.js.map +1 -1
- package/ShadersWGSL/sprites.fragment.js +56 -2
- package/ShadersWGSL/sprites.fragment.js.map +1 -1
- package/ShadersWGSL/sprites.vertex.js +62 -1
- package/ShadersWGSL/sprites.vertex.js.map +1 -1
- package/Sprites/spriteManager.d.ts +13 -0
- package/Sprites/spriteManager.js +15 -0
- package/Sprites/spriteManager.js.map +1 -1
- package/Sprites/spriteRenderer.d.ts +24 -1
- package/Sprites/spriteRenderer.js +368 -50
- package/Sprites/spriteRenderer.js.map +1 -1
- package/Sprites/thinSprite.d.ts +4 -0
- package/Sprites/thinSprite.js +4 -0
- package/Sprites/thinSprite.js.map +1 -1
- package/States/alphaCullingState.d.ts +3 -1
- package/States/alphaCullingState.js +18 -3
- package/States/alphaCullingState.js.map +1 -1
- package/XR/features/WebXRSpaceWarp.pure.js +2 -1
- package/XR/features/WebXRSpaceWarp.pure.js.map +1 -1
- package/XR/webXRDefaultExperience.d.ts +5 -1
- package/XR/webXRDefaultExperience.js.map +1 -1
- package/XR/webXREnterExitUI.d.ts +2 -1
- package/XR/webXREnterExitUI.js.map +1 -1
- package/assetContainer.d.ts +1 -0
- package/assetContainer.js +5 -1
- package/assetContainer.js.map +1 -1
- package/package.json +1 -1
- package/scene.pure.d.ts +36 -2
- package/scene.pure.js +63 -4
- package/scene.pure.js.map +1 -1
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/** This file must only contain pure code and pure imports */
|
|
2
2
|
import { RegisterBufferAlign } from "../Buffers/buffer.align.pure.js";
|
|
3
3
|
import { InternalTexture } from "../Materials/Textures/internalTexture.js";
|
|
4
|
+
import { HasStencilAspect } from "../Materials/Textures/textureHelper.functions.js";
|
|
5
|
+
import { _IESTextureLoader } from "../Materials/Textures/Loaders/iesTextureLoader.js";
|
|
4
6
|
import { DataBuffer } from "../Buffers/dataBuffer.js";
|
|
5
7
|
import { Observable } from "../Misc/observable.pure.js";
|
|
6
8
|
import { Logger } from "../Misc/logger.js";
|
|
@@ -117,6 +119,16 @@ class CommandBufferEncoder {
|
|
|
117
119
|
}
|
|
118
120
|
}
|
|
119
121
|
const remappedAttributesNames = [];
|
|
122
|
+
// Reused by bindFramebuffer(forceFullscreenViewport) to avoid allocating a viewport per bind.
|
|
123
|
+
const _FullscreenViewport = { x: 0, y: 0, width: 1, height: 1 };
|
|
124
|
+
// Render-target textures created with mip storage (createMipMaps or generateMipMaps). Tracked separately from
|
|
125
|
+
// generateMipMaps so sample-count changes and context-loss rebuilds keep an explicitly authored mip chain.
|
|
126
|
+
const _TexturesWithMipStorage = /*#__PURE__*/ new WeakSet();
|
|
127
|
+
/**
|
|
128
|
+
* Sentinel for "no attachment masking": every color attachment of the bound framebuffer takes part in
|
|
129
|
+
* the clear. Native treats this value specially and skips the bgfx color-palette clear path.
|
|
130
|
+
*/
|
|
131
|
+
const _AllAttachmentsMask = 0xff;
|
|
120
132
|
/** @internal */
|
|
121
133
|
export class ThinNativeEngine extends ThinEngine {
|
|
122
134
|
/** @internal */
|
|
@@ -124,7 +136,9 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
124
136
|
return new NativeDataStream();
|
|
125
137
|
}
|
|
126
138
|
constructor(options = {}) {
|
|
127
|
-
super(null, false,
|
|
139
|
+
super(null, false, options, options.adaptToDeviceRatio);
|
|
140
|
+
this._transformFeedbackBuffer = null;
|
|
141
|
+
this._transformFeedbackActive = false;
|
|
128
142
|
this._initializeNativeEngine(options.adaptToDeviceRatio ?? false);
|
|
129
143
|
}
|
|
130
144
|
//////////////////////////////////////////////////////////////////////
|
|
@@ -145,8 +159,24 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
145
159
|
});
|
|
146
160
|
this._camera = _native.Camera ? new _native.Camera() : null;
|
|
147
161
|
this._commandBufferEncoder = new CommandBufferEncoder(this._engine);
|
|
162
|
+
this._frameGraphFramebufferRefCount = new Map();
|
|
148
163
|
this._frameStats = { gpuTimeNs: Number.NaN };
|
|
164
|
+
// There is no DOM canvas to draw the default loading screen into, so install a no-op one; this keeps
|
|
165
|
+
// the loading-UI accessors (loadingUIText, loadingUIBackgroundColor, display/hide) usable on native.
|
|
166
|
+
let loadingScreenWarningDisplayed = false;
|
|
167
|
+
this._loadingScreen = {
|
|
168
|
+
displayLoadingUI: () => {
|
|
169
|
+
if (!loadingScreenWarningDisplayed) {
|
|
170
|
+
Logger.Warn("NativeEngine is unable to display the loading screen UI.");
|
|
171
|
+
loadingScreenWarningDisplayed = true;
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
hideLoadingUI: () => { },
|
|
175
|
+
loadingUIBackgroundColor: "",
|
|
176
|
+
loadingUIText: "",
|
|
177
|
+
};
|
|
149
178
|
this._boundBuffersVertexArray = null;
|
|
179
|
+
this._clearAttachmentMask = _AllAttachmentsMask;
|
|
150
180
|
this._currentDepthTest = _native.Engine.DEPTH_TEST_LEQUAL;
|
|
151
181
|
this._depthTestEnabled = true;
|
|
152
182
|
this._stencilTest = false;
|
|
@@ -167,6 +197,9 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
167
197
|
this._depthWrite = true;
|
|
168
198
|
// warning for non supported fill mode has already been displayed
|
|
169
199
|
this._fillModeWarningDisplayed = false;
|
|
200
|
+
this._int2Scratch = new Int32Array(2);
|
|
201
|
+
this._int3Scratch = new Int32Array(3);
|
|
202
|
+
this._int4Scratch = new Int32Array(4);
|
|
170
203
|
this._drawCalls = new PerfCounter();
|
|
171
204
|
if (_native.Engine.PROTOCOL_VERSION !== ThinNativeEngine.PROTOCOL_VERSION) {
|
|
172
205
|
throw new Error(`Protocol version mismatch: ${_native.Engine.PROTOCOL_VERSION} (Native) !== ${ThinNativeEngine.PROTOCOL_VERSION} (JS)`);
|
|
@@ -241,12 +274,12 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
241
274
|
canUseGLVertexID: true,
|
|
242
275
|
supportComputeShaders: false,
|
|
243
276
|
supportSRGBBuffers: true,
|
|
244
|
-
supportTransformFeedbacks:
|
|
277
|
+
supportTransformFeedbacks: !!_native.Engine.COMMAND_DRAWTRANSFORMFEEDBACK,
|
|
245
278
|
textureMaxLevel: false,
|
|
246
279
|
texture2DArrayMaxLayerCount: _native.Engine.CAPS_LIMITS_MAX_TEXTURE_LAYERS,
|
|
247
280
|
disableMorphTargetTexture: false,
|
|
248
281
|
parallelShaderCompile: { COMPLETION_STATUS_KHR: 0 },
|
|
249
|
-
textureNorm16:
|
|
282
|
+
textureNorm16: true,
|
|
250
283
|
blendParametersPerTarget: false,
|
|
251
284
|
dualSourceBlending: false,
|
|
252
285
|
supportReadWriteStorageTextures: false,
|
|
@@ -254,13 +287,23 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
254
287
|
this._features = {
|
|
255
288
|
forceBitmapOverHTMLImageElement: true,
|
|
256
289
|
supportRenderAndCopyToLodForFloatTextures: false,
|
|
257
|
-
|
|
258
|
-
|
|
290
|
+
// Native can attach an explicit depth/stencil texture to a render target (see
|
|
291
|
+
// _createDepthStencilTexture) and sample it afterwards. Hardware comparison samplers are
|
|
292
|
+
// available through bgfx BGFX_SAMPLER_COMPARE_* (set via updateTextureComparisonFunction),
|
|
293
|
+
// which is what ShadowGenerator needs for FILTER_PCF / FILTER_PCSS (incl. cascaded shadows).
|
|
294
|
+
// Both are optional runtime extensions, so only advertise them when the runtime provides them.
|
|
295
|
+
supportDepthStencilTexture: !!this._engine.createMultiFrameBuffer,
|
|
296
|
+
supportShadowSamplers: !!this._engine.createMultiFrameBuffer && !!this._engine.setTextureComparisonFunction,
|
|
259
297
|
uniformBufferHardCheckMatrix: false,
|
|
260
|
-
|
|
298
|
+
// Native supports GPU cube prefiltering (HDRFiltering / HDRIrradianceFiltering): the render path
|
|
299
|
+
// binds a specific cube-face + mip via bindFramebuffer(faceIndex, lodLevel) and convolves the
|
|
300
|
+
// environment per-roughness. Required so OpenPBR/PBR IBL scenes get real prefiltered radiance
|
|
301
|
+
// (and irradiance) instead of black/energy-lossy CPU-SH fallbacks.
|
|
302
|
+
allowTexturePrefiltering: true,
|
|
261
303
|
trackUbosInFrame: false,
|
|
262
304
|
checkUbosContentBeforeUpload: false,
|
|
263
|
-
|
|
305
|
+
// Cascaded shadow maps render into 2D-array render targets, one framebuffer per layer.
|
|
306
|
+
supportCSM: true,
|
|
264
307
|
basisNeedsPOT: false,
|
|
265
308
|
support3DTextures: false,
|
|
266
309
|
needTypeSuffixInShaderConstants: false,
|
|
@@ -275,7 +318,7 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
275
318
|
needShaderCodeInlining: true,
|
|
276
319
|
needToAlwaysBindUniformBuffers: false,
|
|
277
320
|
supportRenderPasses: true,
|
|
278
|
-
supportSpriteInstancing:
|
|
321
|
+
supportSpriteInstancing: true,
|
|
279
322
|
forceVertexBufferStrideAndOffsetMultiple4Bytes: true,
|
|
280
323
|
_checkNonFloatVertexBuffersDontRecreatePipelineContext: false,
|
|
281
324
|
};
|
|
@@ -413,6 +456,12 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
413
456
|
}
|
|
414
457
|
_restoreEngineAfterContextLost() {
|
|
415
458
|
this._clearEmptyResources();
|
|
459
|
+
// The frame graph framebuffers of the lost context are invalid: forget their bookkeeping (without deleting
|
|
460
|
+
// the stale native handles) so each reset does not leave another generation of entries behind.
|
|
461
|
+
for (const shared of this._frameGraphFramebufferRefCount.values()) {
|
|
462
|
+
shared.hardwareTexture._frameGraphFramebuffer = null;
|
|
463
|
+
}
|
|
464
|
+
this._frameGraphFramebufferRefCount.clear();
|
|
416
465
|
const depthTest = this._depthCullingState.depthTest; // backup those values because the call to initEngine / wipeCaches will reset them
|
|
417
466
|
const depthFunc = this._depthCullingState.depthFunc;
|
|
418
467
|
const depthMask = this._depthCullingState.depthMask;
|
|
@@ -441,6 +490,9 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
441
490
|
this._commandBufferEncoder.finishEncodingCommand();
|
|
442
491
|
}
|
|
443
492
|
this._currentFramebuffer = framebuffer;
|
|
493
|
+
// drawBuffers state is per-framebuffer on WebGL, so a framebuffer switch resets the
|
|
494
|
+
// attachment selection back to "every attachment".
|
|
495
|
+
this._clearAttachmentMask = _AllAttachmentsMask;
|
|
444
496
|
}
|
|
445
497
|
}
|
|
446
498
|
/**
|
|
@@ -462,16 +514,24 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
462
514
|
this._depthCullingState.depthFunc = 518;
|
|
463
515
|
this.setDepthFunction(518);
|
|
464
516
|
}
|
|
465
|
-
|
|
466
|
-
this._commandBufferEncoder.
|
|
517
|
+
const clear2 = _native.Engine.COMMAND_CLEAR2;
|
|
518
|
+
this._commandBufferEncoder.startEncodingCommand(clear2 ?? _native.Engine.COMMAND_CLEAR);
|
|
519
|
+
this._commandBufferEncoder.encodeCommandArgAsUInt32(backBuffer && color && this._clearAttachmentMask !== 0 ? 1 : 0);
|
|
467
520
|
this._commandBufferEncoder.encodeCommandArgAsFloat32(color ? color.r : 0);
|
|
468
521
|
this._commandBufferEncoder.encodeCommandArgAsFloat32(color ? color.g : 0);
|
|
469
522
|
this._commandBufferEncoder.encodeCommandArgAsFloat32(color ? color.b : 0);
|
|
470
|
-
|
|
523
|
+
// Playgrounds often assign Color3 to scene.clearColor; Color3 has no .a, so
|
|
524
|
+
// `color.a` is undefined and was encoded as 0 → transparent clear. PNG
|
|
525
|
+
// screenshots then show black sky on dark HTML backgrounds while RGB still
|
|
526
|
+
// matches (pixel compare ignores alpha). Default missing alpha to opaque.
|
|
527
|
+
this._commandBufferEncoder.encodeCommandArgAsFloat32(color ? (color.a ?? 1) : 1);
|
|
471
528
|
this._commandBufferEncoder.encodeCommandArgAsUInt32(depth ? 1 : 0);
|
|
472
529
|
this._commandBufferEncoder.encodeCommandArgAsFloat32(depth && this.useReverseDepthBuffer ? 0 : 1);
|
|
473
530
|
this._commandBufferEncoder.encodeCommandArgAsUInt32(stencil ? 1 : 0);
|
|
474
531
|
this._commandBufferEncoder.encodeCommandArgAsUInt32(stencilClearValue);
|
|
532
|
+
if (clear2) {
|
|
533
|
+
this._commandBufferEncoder.encodeCommandArgAsUInt32(this._clearAttachmentMask);
|
|
534
|
+
}
|
|
475
535
|
this._commandBufferEncoder.finishEncodingCommand();
|
|
476
536
|
}
|
|
477
537
|
createIndexBuffer(indices, updateable, _label) {
|
|
@@ -545,6 +605,8 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
545
605
|
this._commandBufferEncoder.encodeCommandArgAsNativeData(vertexArray);
|
|
546
606
|
this._commandBufferEncoder.finishEncodingCommand();
|
|
547
607
|
}
|
|
608
|
+
/** @internal Native vertex arrays capture their buffers when recorded; there is no bound array buffer. */
|
|
609
|
+
bindArrayBuffer(_buffer) { }
|
|
548
610
|
releaseVertexArrayObject(vertexArray) {
|
|
549
611
|
this._deleteVertexArray(vertexArray);
|
|
550
612
|
}
|
|
@@ -560,12 +622,15 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
560
622
|
return this._engine.getAttributes(nativePipelineContext.program, remappedAttributesNames);
|
|
561
623
|
}
|
|
562
624
|
/**
|
|
563
|
-
*
|
|
625
|
+
* Check whether the runtime can expand primitive modes unavailable in modern rendering APIs.
|
|
564
626
|
* @param fillMode defines the primitive to use
|
|
565
627
|
* @returns true if supported
|
|
566
628
|
*/
|
|
567
629
|
_checkSupportedFillMode(fillMode) {
|
|
568
630
|
if (fillMode == 5 || fillMode == 8) {
|
|
631
|
+
if (this._engine.supportsPrimitiveModeExpansion) {
|
|
632
|
+
return true;
|
|
633
|
+
}
|
|
569
634
|
if (!this._fillModeWarningDisplayed) {
|
|
570
635
|
Logger.Warn("Line Loop and Triangle Fan are not supported fill modes with Babylon Native. Elements with these fill mode will not be visible.");
|
|
571
636
|
this._fillModeWarningDisplayed = true;
|
|
@@ -611,6 +676,20 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
611
676
|
* @param instancesCount defines the number of instances to draw (if instantiation is enabled)
|
|
612
677
|
*/
|
|
613
678
|
drawArraysType(fillMode, verticesStart, verticesCount, instancesCount) {
|
|
679
|
+
if (this._transformFeedbackActive) {
|
|
680
|
+
// The native engine runs the transform feedback program over the bound vertex array
|
|
681
|
+
// and writes the captured varyings into the bound feedback buffer.
|
|
682
|
+
const target = this._transformFeedbackBuffer?.nativeVertexBuffer;
|
|
683
|
+
if (!target) {
|
|
684
|
+
throw new Error("Transform feedback requires a bound native vertex buffer.");
|
|
685
|
+
}
|
|
686
|
+
this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_DRAWTRANSFORMFEEDBACK);
|
|
687
|
+
this._commandBufferEncoder.encodeCommandArgAsNativeData(target);
|
|
688
|
+
this._commandBufferEncoder.encodeCommandArgAsUInt32(verticesStart);
|
|
689
|
+
this._commandBufferEncoder.encodeCommandArgAsUInt32(verticesCount);
|
|
690
|
+
this._commandBufferEncoder.finishEncodingCommand();
|
|
691
|
+
return;
|
|
692
|
+
}
|
|
614
693
|
if (!this._checkSupportedFillMode(fillMode)) {
|
|
615
694
|
return;
|
|
616
695
|
}
|
|
@@ -632,6 +711,41 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
632
711
|
}
|
|
633
712
|
this._commandBufferEncoder.finishEncodingCommand();
|
|
634
713
|
}
|
|
714
|
+
/** @internal Transform feedback objects are implicit on native; state lives on the engine. */
|
|
715
|
+
createTransformFeedback() {
|
|
716
|
+
return {};
|
|
717
|
+
}
|
|
718
|
+
/** @internal */
|
|
719
|
+
deleteTransformFeedback(_value) { }
|
|
720
|
+
/** @internal */
|
|
721
|
+
bindTransformFeedback(_value) { }
|
|
722
|
+
/** @internal */
|
|
723
|
+
bindTransformFeedbackBuffer(value) {
|
|
724
|
+
this._transformFeedbackBuffer = value;
|
|
725
|
+
}
|
|
726
|
+
/** @internal Varyings are passed to the native program when it is created. */
|
|
727
|
+
setTranformFeedbackVaryings(_program, _value) { }
|
|
728
|
+
/** @internal */
|
|
729
|
+
beginTransformFeedback(_usePoints = true) {
|
|
730
|
+
this._transformFeedbackActive = true;
|
|
731
|
+
}
|
|
732
|
+
/** @internal */
|
|
733
|
+
endTransformFeedback() {
|
|
734
|
+
this._transformFeedbackActive = false;
|
|
735
|
+
}
|
|
736
|
+
/** @internal */
|
|
737
|
+
readTransformFeedbackBuffer(target) {
|
|
738
|
+
const buffer = this._transformFeedbackBuffer?.nativeVertexBuffer;
|
|
739
|
+
if (!buffer) {
|
|
740
|
+
throw new Error("Reading transform feedback requires a bound native vertex buffer.");
|
|
741
|
+
}
|
|
742
|
+
if (!this._engine.readTransformFeedbackBuffer) {
|
|
743
|
+
throw new Error("This native engine build does not support reading transform feedback buffers.");
|
|
744
|
+
}
|
|
745
|
+
this._engine.readTransformFeedbackBuffer(buffer, target.buffer, target.byteOffset, target.byteLength);
|
|
746
|
+
}
|
|
747
|
+
/** @internal Transform feedback draws never rasterize on native. */
|
|
748
|
+
setRasterizerState(_value) { }
|
|
635
749
|
createPipelineContext(shaderProcessingContext) {
|
|
636
750
|
const isAsync = !!this._caps.parallelShaderCompile;
|
|
637
751
|
return new NativePipelineContext(this, isAsync, shaderProcessingContext);
|
|
@@ -647,19 +761,22 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
647
761
|
* @internal
|
|
648
762
|
*/
|
|
649
763
|
// eslint-disable-next-line no-restricted-syntax
|
|
650
|
-
_preparePipelineContextAsync(pipelineContext, vertexSourceCode, fragmentSourceCode, createAsRaw, _rawVertexSourceCode, _rawFragmentSourceCode, _rebuildRebind, defines,
|
|
764
|
+
_preparePipelineContextAsync(pipelineContext, vertexSourceCode, fragmentSourceCode, createAsRaw, _rawVertexSourceCode, _rawFragmentSourceCode, _rebuildRebind, defines, transformFeedbackVaryings, _key, onReady) {
|
|
651
765
|
if (createAsRaw) {
|
|
652
766
|
this.createRawShaderProgram();
|
|
653
767
|
}
|
|
654
768
|
else {
|
|
655
|
-
this.createShaderProgram(pipelineContext, vertexSourceCode, fragmentSourceCode, defines);
|
|
769
|
+
this.createShaderProgram(pipelineContext, vertexSourceCode, fragmentSourceCode, defines, undefined, transformFeedbackVaryings);
|
|
656
770
|
}
|
|
657
771
|
onReady();
|
|
658
772
|
}
|
|
659
773
|
/**
|
|
660
774
|
* @internal
|
|
661
775
|
*/
|
|
662
|
-
_getShaderProcessingContext(
|
|
776
|
+
_getShaderProcessingContext(shaderLanguage) {
|
|
777
|
+
if (shaderLanguage === 1 /* ShaderLanguage.WGSL */) {
|
|
778
|
+
throw new Error("NativeEngine does not support WGSL graphics shaders.");
|
|
779
|
+
}
|
|
663
780
|
return new NativeShaderProcessingContext();
|
|
664
781
|
}
|
|
665
782
|
/**
|
|
@@ -686,7 +803,11 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
686
803
|
createRawShaderProgram() {
|
|
687
804
|
throw new Error("Not Supported");
|
|
688
805
|
}
|
|
689
|
-
createShaderProgram(pipelineContext, vertexCode, fragmentCode, defines) {
|
|
806
|
+
createShaderProgram(pipelineContext, vertexCode, fragmentCode, defines, _context, transformFeedbackVaryings = null) {
|
|
807
|
+
const varyings = transformFeedbackVaryings?.length ? transformFeedbackVaryings : undefined;
|
|
808
|
+
if (varyings && !_native.Engine.COMMAND_DRAWTRANSFORMFEEDBACK) {
|
|
809
|
+
throw new Error("This native engine build does not support transform feedback.");
|
|
810
|
+
}
|
|
690
811
|
const nativePipelineContext = pipelineContext;
|
|
691
812
|
this.onBeforeShaderCompilationObservable.notifyObservers(this);
|
|
692
813
|
const vertexInliner = new ShaderCodeInliner(vertexCode);
|
|
@@ -705,11 +826,11 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
705
826
|
if (pipelineContext.isAsync) {
|
|
706
827
|
nativePipelineContext.program = this._engine.createProgramAsync(vertexCode, fragmentCode, onSuccess, (error) => {
|
|
707
828
|
nativePipelineContext.compilationError = error;
|
|
708
|
-
});
|
|
829
|
+
}, varyings);
|
|
709
830
|
}
|
|
710
831
|
else {
|
|
711
832
|
try {
|
|
712
|
-
nativePipelineContext.program = this._engine.createProgram(vertexCode, fragmentCode);
|
|
833
|
+
nativePipelineContext.program = this._engine.createProgram(vertexCode, fragmentCode, varyings);
|
|
713
834
|
onSuccess();
|
|
714
835
|
}
|
|
715
836
|
catch (e) {
|
|
@@ -906,23 +1027,19 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
906
1027
|
// Unlike the WebGL engine, the native engine does not call applyStates() before
|
|
907
1028
|
// a draw, so depth-test toggles made directly on engine.depthCullingState are
|
|
908
1029
|
// flushed here to match the cross-engine contract.
|
|
1030
|
+
// Reconcile the depth compare function too: features that set it directly on
|
|
1031
|
+
// depthCullingState (e.g. reverse depth buffer -> GEQUAL) never go through
|
|
1032
|
+
// setDepthFunction, so push any divergence to the native side here. setDepthFunction
|
|
1033
|
+
// also re-encodes the depth-test enable, so no separate enable flush is needed after.
|
|
1034
|
+
const targetFunc = this._depthCullingState.depthFunc;
|
|
1035
|
+
if (targetFunc && targetFunc !== this.getDepthFunction()) {
|
|
1036
|
+
this.setDepthFunction(targetFunc);
|
|
1037
|
+
return;
|
|
1038
|
+
}
|
|
909
1039
|
if (this._depthCullingState.depthTest !== this._depthTestEnabled) {
|
|
910
1040
|
this._encodeDepthTest(this._depthCullingState.depthTest);
|
|
911
1041
|
}
|
|
912
1042
|
}
|
|
913
|
-
applyStates() {
|
|
914
|
-
// The base ThinEngine.applyStates() drives the WebGL context (this._gl) directly, which is null on
|
|
915
|
-
// Native. Flush the depth-culling state through the native command path instead, so callers that
|
|
916
|
-
// mutate engine.depthCullingState directly and then call applyStates() (e.g. the depth-peeling / OIT
|
|
917
|
-
// renderer) take effect. Alpha and stencil state are applied on Native via their dedicated setters
|
|
918
|
-
// (setAlphaMode / setStencil*), which encode their commands when called.
|
|
919
|
-
const depthCullingState = this._depthCullingState;
|
|
920
|
-
if (depthCullingState.depthFunc !== null && depthCullingState.depthFunc !== undefined) {
|
|
921
|
-
this.setDepthFunction(depthCullingState.depthFunc);
|
|
922
|
-
}
|
|
923
|
-
this.setDepthBuffer(depthCullingState.depthTest);
|
|
924
|
-
this.setDepthWrite(depthCullingState.depthMask);
|
|
925
|
-
}
|
|
926
1043
|
/**
|
|
927
1044
|
* Gets a boolean indicating if depth writing is enabled
|
|
928
1045
|
* @returns the current depth writing state
|
|
@@ -952,6 +1069,10 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
952
1069
|
return null;
|
|
953
1070
|
}
|
|
954
1071
|
setDepthFunction(depthFunc) {
|
|
1072
|
+
// Keep the shared depth-culling state in sync (the base impl sets this) so the
|
|
1073
|
+
// per-draw reconcile in _flushDepthTestState treats material-driven changes as a
|
|
1074
|
+
// no-op and only pushes divergences that bypass this method (e.g. reverse depth).
|
|
1075
|
+
this._depthCullingState.depthFunc = depthFunc;
|
|
955
1076
|
let nativeDepthFunc = 0;
|
|
956
1077
|
switch (depthFunc) {
|
|
957
1078
|
case 512:
|
|
@@ -994,6 +1115,13 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
994
1115
|
*/
|
|
995
1116
|
setDepthWrite(enable) {
|
|
996
1117
|
this._depthWrite = enable;
|
|
1118
|
+
// Keep depthCullingState.depthMask in sync. applyStates() reconciles native depth write
|
|
1119
|
+
// from depthMask; if it stays true after setDepthWrite(false), the next applyStates()
|
|
1120
|
+
// (e.g. during particle/material draws) silently turns WRITE_Z back on. Coplanar
|
|
1121
|
+
// triangle-strip particle quads then lose the second tri to DEPTH_LESS.
|
|
1122
|
+
if (this._depthCullingState) {
|
|
1123
|
+
this._depthCullingState.depthMask = enable;
|
|
1124
|
+
}
|
|
997
1125
|
this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_SETDEPTHWRITE);
|
|
998
1126
|
this._commandBufferEncoder.encodeCommandArgAsUInt32(Number(enable));
|
|
999
1127
|
this._commandBufferEncoder.finishEncodingCommand();
|
|
@@ -1015,17 +1143,49 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
1015
1143
|
getColorWrite() {
|
|
1016
1144
|
return this._colorWrite;
|
|
1017
1145
|
}
|
|
1146
|
+
/**
|
|
1147
|
+
* Apply the currently pending engine states.
|
|
1148
|
+
*
|
|
1149
|
+
* The base ThinEngine.applyStates() flushes state by calling
|
|
1150
|
+
* this._depthCullingState.apply(this._gl) (and similar for alpha/stencil), but the
|
|
1151
|
+
* native engine has no WebGL context (_gl is undefined), so inheriting that path
|
|
1152
|
+
* throws "Cannot read properties of undefined (reading 'depthMask')". Callers such
|
|
1153
|
+
* as the depth-peeling (OIT) renderer mutate engine.depthCullingState directly and
|
|
1154
|
+
* then call applyStates() expecting the change to be flushed, so reconcile the shared
|
|
1155
|
+
* depth-culling state into the native command buffer here instead. Alpha and stencil
|
|
1156
|
+
* states are already encoded immediately on the native side (setAlphaMode /
|
|
1157
|
+
* setStencil* emit commands directly), so only the depth state needs reconciling.
|
|
1158
|
+
*/
|
|
1159
|
+
applyStates() {
|
|
1160
|
+
// Depth test (the native command conflates enable + compare function).
|
|
1161
|
+
this._flushDepthTestState();
|
|
1162
|
+
// Depth write (depthMask).
|
|
1163
|
+
if (this._depthCullingState.depthMask !== this._depthWrite) {
|
|
1164
|
+
this.setDepthWrite(this._depthCullingState.depthMask);
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1018
1167
|
applyStencil() {
|
|
1019
|
-
|
|
1168
|
+
if (!this._stencilTest) {
|
|
1169
|
+
return;
|
|
1170
|
+
}
|
|
1171
|
+
this._setStencil(this._stencilMask, getNativeStencilOpFail(this._stencilOpStencilFail), getNativeStencilDepthFail(this._stencilOpDepthFail), getNativeStencilDepthPass(this._stencilOpStencilDepthPass), getNativeStencilFunc(this._stencilFunc), this._stencilFuncRef, this._stencilFuncMask);
|
|
1020
1172
|
}
|
|
1021
|
-
_setStencil(mask, stencilOpFail, depthOpFail, depthOpPass, func, ref) {
|
|
1022
|
-
|
|
1173
|
+
_setStencil(mask, stencilOpFail, depthOpFail, depthOpPass, func, ref, funcMask = 0xff) {
|
|
1174
|
+
const setStencil2 = _native.Engine.COMMAND_SETSTENCIL2;
|
|
1175
|
+
this._commandBufferEncoder.startEncodingCommand(setStencil2 ?? _native.Engine.COMMAND_SETSTENCIL);
|
|
1023
1176
|
this._commandBufferEncoder.encodeCommandArgAsUInt32(mask);
|
|
1024
1177
|
this._commandBufferEncoder.encodeCommandArgAsUInt32(stencilOpFail);
|
|
1025
1178
|
this._commandBufferEncoder.encodeCommandArgAsUInt32(depthOpFail);
|
|
1026
1179
|
this._commandBufferEncoder.encodeCommandArgAsUInt32(depthOpPass);
|
|
1027
1180
|
this._commandBufferEncoder.encodeCommandArgAsUInt32(func);
|
|
1028
1181
|
this._commandBufferEncoder.encodeCommandArgAsUInt32(ref);
|
|
1182
|
+
// Stencil function mask (gl.stencilFunc mask / BGFX_STENCIL_FUNC_RMASK). Required for
|
|
1183
|
+
// HighlightLayer, which compares only the glowing-mesh reference bits while ignoring
|
|
1184
|
+
// lower reserved bits. Without this, Native always used 0xFF and the outer/inner glow
|
|
1185
|
+
// stencil tests matched the wrong fragments.
|
|
1186
|
+
if (setStencil2) {
|
|
1187
|
+
this._commandBufferEncoder.encodeCommandArgAsUInt32(funcMask & 0xff);
|
|
1188
|
+
}
|
|
1029
1189
|
this._commandBufferEncoder.finishEncodingCommand();
|
|
1030
1190
|
}
|
|
1031
1191
|
/**
|
|
@@ -1088,11 +1248,12 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
1088
1248
|
this.applyStencil();
|
|
1089
1249
|
}
|
|
1090
1250
|
/**
|
|
1091
|
-
* Sets the current stencil mask
|
|
1092
|
-
* @param mask defines the new stencil mask to use
|
|
1251
|
+
* Sets the current stencil function mask
|
|
1252
|
+
* @param mask defines the new stencil function mask to use
|
|
1093
1253
|
*/
|
|
1094
1254
|
setStencilFunctionMask(mask) {
|
|
1095
1255
|
this._stencilFuncMask = mask;
|
|
1256
|
+
this.applyStencil();
|
|
1096
1257
|
}
|
|
1097
1258
|
/**
|
|
1098
1259
|
* Sets the stencil operation to use when stencil fails
|
|
@@ -1182,6 +1343,29 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
1182
1343
|
}
|
|
1183
1344
|
this._alphaMode[targetIndex] = mode;
|
|
1184
1345
|
}
|
|
1346
|
+
/**
|
|
1347
|
+
* Sets the current alpha blend equation (ADD / SUB / MAX / MIN / ...).
|
|
1348
|
+
* Dual depth peeling (OIT) requires ALPHA_EQUATION_MAX so peel passes accumulate
|
|
1349
|
+
* farthest/nearest depths. Native previously only wired blend *factors*; equations
|
|
1350
|
+
* stayed at bgfx's default ADD and transparent peels never wrote useful depth.
|
|
1351
|
+
* @param equation one of undefined*
|
|
1352
|
+
* @param targetIndex MRT attachment index (Native applies equation globally; kept for API parity)
|
|
1353
|
+
*/
|
|
1354
|
+
setAlphaEquation(equation, targetIndex = 0) {
|
|
1355
|
+
if (this._alphaEquation[targetIndex] === equation) {
|
|
1356
|
+
return;
|
|
1357
|
+
}
|
|
1358
|
+
this._alphaEquation[targetIndex] = equation;
|
|
1359
|
+
const command = _native.Engine.COMMAND_SETBLENDEQUATION;
|
|
1360
|
+
if (!command) {
|
|
1361
|
+
// Older Babylon Native binaries predating blend-equation support.
|
|
1362
|
+
return;
|
|
1363
|
+
}
|
|
1364
|
+
this._commandBufferEncoder.startEncodingCommand(command);
|
|
1365
|
+
// Pass the Babylon undefined* value; NativeEngine::SetBlendEquation maps it to bgfx.
|
|
1366
|
+
this._commandBufferEncoder.encodeCommandArgAsUInt32(equation);
|
|
1367
|
+
this._commandBufferEncoder.finishEncodingCommand();
|
|
1368
|
+
}
|
|
1185
1369
|
setInt(uniform, int) {
|
|
1186
1370
|
if (!uniform) {
|
|
1187
1371
|
return false;
|
|
@@ -1192,6 +1376,36 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
1192
1376
|
this._commandBufferEncoder.finishEncodingCommand();
|
|
1193
1377
|
return true;
|
|
1194
1378
|
}
|
|
1379
|
+
setInt2(uniform, x, y) {
|
|
1380
|
+
if (!uniform) {
|
|
1381
|
+
return false;
|
|
1382
|
+
}
|
|
1383
|
+
const values = this._int2Scratch;
|
|
1384
|
+
values[0] = x;
|
|
1385
|
+
values[1] = y;
|
|
1386
|
+
return this.setIntArray2(uniform, values);
|
|
1387
|
+
}
|
|
1388
|
+
setInt3(uniform, x, y, z) {
|
|
1389
|
+
if (!uniform) {
|
|
1390
|
+
return false;
|
|
1391
|
+
}
|
|
1392
|
+
const values = this._int3Scratch;
|
|
1393
|
+
values[0] = x;
|
|
1394
|
+
values[1] = y;
|
|
1395
|
+
values[2] = z;
|
|
1396
|
+
return this.setIntArray3(uniform, values);
|
|
1397
|
+
}
|
|
1398
|
+
setInt4(uniform, x, y, z, w) {
|
|
1399
|
+
if (!uniform) {
|
|
1400
|
+
return false;
|
|
1401
|
+
}
|
|
1402
|
+
const values = this._int4Scratch;
|
|
1403
|
+
values[0] = x;
|
|
1404
|
+
values[1] = y;
|
|
1405
|
+
values[2] = z;
|
|
1406
|
+
values[3] = w;
|
|
1407
|
+
return this.setIntArray4(uniform, values);
|
|
1408
|
+
}
|
|
1195
1409
|
setIntArray(uniform, array) {
|
|
1196
1410
|
if (!uniform) {
|
|
1197
1411
|
return false;
|
|
@@ -1497,13 +1711,176 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
1497
1711
|
this._internalTexturesCache.push(texture);
|
|
1498
1712
|
return texture;
|
|
1499
1713
|
}
|
|
1714
|
+
createRawTexture3D(data, width, height, depth, format, generateMipMaps, invertY, samplingMode, compression = null, textureType = 0) {
|
|
1715
|
+
if (compression) {
|
|
1716
|
+
throw new Error(`NativeEngine.createRawTexture3D: compressed raw volume uploads are not supported (${compression}).`);
|
|
1717
|
+
}
|
|
1718
|
+
const texture = new InternalTexture(this, 10 /* InternalTextureSource.Raw3D */);
|
|
1719
|
+
texture.baseWidth = width;
|
|
1720
|
+
texture.baseHeight = height;
|
|
1721
|
+
texture.baseDepth = depth;
|
|
1722
|
+
texture.width = width;
|
|
1723
|
+
texture.height = height;
|
|
1724
|
+
texture.depth = depth;
|
|
1725
|
+
texture.format = format;
|
|
1726
|
+
texture.type = textureType;
|
|
1727
|
+
texture.generateMipMaps = generateMipMaps;
|
|
1728
|
+
texture.samplingMode = samplingMode;
|
|
1729
|
+
texture.is3D = true;
|
|
1730
|
+
texture.invertY = invertY;
|
|
1731
|
+
texture._compression = compression;
|
|
1732
|
+
if (!this._doNotHandleContextLost) {
|
|
1733
|
+
texture._bufferView = data;
|
|
1734
|
+
}
|
|
1735
|
+
if (texture._hardwareTexture) {
|
|
1736
|
+
const nativeTexture = texture._hardwareTexture.underlyingResource;
|
|
1737
|
+
this._engine.loadRawTexture3D(nativeTexture, data, width, height, depth, getNativeTextureFormat(format, textureType), generateMipMaps, invertY);
|
|
1738
|
+
const filter = getNativeSamplingMode(samplingMode);
|
|
1739
|
+
this._setTextureSampling(nativeTexture, filter);
|
|
1740
|
+
}
|
|
1741
|
+
texture.isReady = true;
|
|
1742
|
+
this._internalTexturesCache.push(texture);
|
|
1743
|
+
return texture;
|
|
1744
|
+
}
|
|
1745
|
+
updateRawTexture3D(texture, bufferView, format, invertY, compression = null, textureType = 0) {
|
|
1746
|
+
if (!texture) {
|
|
1747
|
+
return;
|
|
1748
|
+
}
|
|
1749
|
+
if (compression) {
|
|
1750
|
+
throw new Error(`NativeEngine.updateRawTexture3D: compressed raw volume uploads are not supported (${compression}).`);
|
|
1751
|
+
}
|
|
1752
|
+
texture.format = format;
|
|
1753
|
+
texture.type = textureType;
|
|
1754
|
+
texture.invertY = invertY;
|
|
1755
|
+
texture._compression = compression;
|
|
1756
|
+
if (!this._doNotHandleContextLost) {
|
|
1757
|
+
texture._bufferView = bufferView;
|
|
1758
|
+
}
|
|
1759
|
+
if (bufferView && texture._hardwareTexture) {
|
|
1760
|
+
const nativeTexture = texture._hardwareTexture.underlyingResource;
|
|
1761
|
+
this._engine.loadRawTexture3D(nativeTexture, bufferView, texture.width, texture.height, texture.depth, getNativeTextureFormat(format, textureType), texture.generateMipMaps, invertY);
|
|
1762
|
+
}
|
|
1763
|
+
texture.isReady = true;
|
|
1764
|
+
}
|
|
1500
1765
|
updateRawTexture(texture, bufferView, format, invertY, compression = null, type = 0, useSRGBBuffer = false) {
|
|
1501
1766
|
if (!texture) {
|
|
1502
1767
|
return;
|
|
1503
1768
|
}
|
|
1504
1769
|
if (bufferView && texture._hardwareTexture) {
|
|
1505
1770
|
const underlyingResource = texture._hardwareTexture.underlyingResource;
|
|
1506
|
-
this._engine.loadRawTexture(underlyingResource, bufferView, texture.width, texture.height, getNativeTextureFormat(format, type), texture.generateMipMaps, texture.invertY);
|
|
1771
|
+
this._engine.loadRawTexture(underlyingResource, bufferView, texture.width, texture.height, getNativeTextureFormat(format, type), texture.generateMipMaps, texture.invertY, useSRGBBuffer);
|
|
1772
|
+
}
|
|
1773
|
+
texture.isReady = true;
|
|
1774
|
+
}
|
|
1775
|
+
/**
|
|
1776
|
+
* Creates a raw cube texture on the native engine.
|
|
1777
|
+
*
|
|
1778
|
+
* The WebGL implementation (engine.rawTexture) drives the whole upload through `this._gl`, which is null
|
|
1779
|
+
* on Native, so loading an HDR/`.env` cube via `createRawCubeTextureFromUrl` used to throw
|
|
1780
|
+
* `Cannot read properties of undefined (reading 'FLOAT')`. This override allocates a native cube texture
|
|
1781
|
+
* and uploads its faces through the bgfx `updateTextureData` path instead.
|
|
1782
|
+
*
|
|
1783
|
+
* Native has no 3-component float texture format, so an RGB float/half-float source (what HDRCubeTexture
|
|
1784
|
+
* requests) is allocated and uploaded as RGBA; the per-face RGB->RGBA expansion happens in
|
|
1785
|
+
* `updateRawCubeTexture`.
|
|
1786
|
+
* @param data defines the data used to create the texture (6 faces, +X +Y +Z -X -Y -Z) or null
|
|
1787
|
+
* @param size defines the size of the textures (each face is size x size)
|
|
1788
|
+
* @param format defines the format of the data
|
|
1789
|
+
* @param type defines the type of the data
|
|
1790
|
+
* @param generateMipMaps defines if the engine should generate the mip levels
|
|
1791
|
+
* @param invertY defines if data must be stored with Y axis inverted
|
|
1792
|
+
* @param samplingMode defines the required sampling mode (like Texture.NEAREST_SAMPLINGMODE)
|
|
1793
|
+
* @param compression defines the compression used (null by default)
|
|
1794
|
+
* @returns the cube texture as an InternalTexture
|
|
1795
|
+
*/
|
|
1796
|
+
createRawCubeTexture(data, size, format, type, generateMipMaps, invertY, samplingMode, compression = null) {
|
|
1797
|
+
if (compression) {
|
|
1798
|
+
throw new Error(`NativeEngine.createRawCubeTexture: compressed raw cube uploads are not supported (${compression}).`);
|
|
1799
|
+
}
|
|
1800
|
+
const texture = new InternalTexture(this, 8 /* InternalTextureSource.CubeRaw */);
|
|
1801
|
+
texture.isCube = true;
|
|
1802
|
+
texture.format = format;
|
|
1803
|
+
texture.type = type;
|
|
1804
|
+
texture.width = size;
|
|
1805
|
+
texture.height = size;
|
|
1806
|
+
texture.baseWidth = size;
|
|
1807
|
+
texture.baseHeight = size;
|
|
1808
|
+
texture.invertY = invertY;
|
|
1809
|
+
texture._compression = compression;
|
|
1810
|
+
// Match the WebGL raw-cube path and createRenderTargetCubeTexture: float/half-float formats that the
|
|
1811
|
+
// platform cannot linearly filter fall back to NEAREST and drop mip generation.
|
|
1812
|
+
if (type === 1 && !this._caps.textureFloatLinearFiltering) {
|
|
1813
|
+
generateMipMaps = false;
|
|
1814
|
+
samplingMode = 1;
|
|
1815
|
+
}
|
|
1816
|
+
else if (type === 2 && !this._caps.textureHalfFloatLinearFiltering) {
|
|
1817
|
+
generateMipMaps = false;
|
|
1818
|
+
samplingMode = 1;
|
|
1819
|
+
}
|
|
1820
|
+
texture.generateMipMaps = generateMipMaps;
|
|
1821
|
+
texture.samplingMode = samplingMode;
|
|
1822
|
+
const nativeTexture = texture._hardwareTexture.underlyingResource;
|
|
1823
|
+
this._engine.initializeTexture(nativeTexture, size, size, generateMipMaps, getNativeTextureFormat(format, type),
|
|
1824
|
+
/*renderTarget*/ false,
|
|
1825
|
+
/*srgb*/ false,
|
|
1826
|
+
/*samples*/ 1,
|
|
1827
|
+
/*isCube*/ true);
|
|
1828
|
+
this._setTextureSampling(nativeTexture, getNativeSamplingMode(samplingMode));
|
|
1829
|
+
if (data) {
|
|
1830
|
+
this.updateRawCubeTexture(texture, data, format, type, invertY, compression);
|
|
1831
|
+
}
|
|
1832
|
+
else {
|
|
1833
|
+
texture.isReady = true;
|
|
1834
|
+
}
|
|
1835
|
+
// Like WebGL, the cache registration is owned by the caller (e.g. createRawCubeTextureFromUrl).
|
|
1836
|
+
return texture;
|
|
1837
|
+
}
|
|
1838
|
+
/**
|
|
1839
|
+
* Updates a raw cube texture on the native engine.
|
|
1840
|
+
* @param texture defines the texture to update
|
|
1841
|
+
* @param data defines the data to store (6 faces, +X +Y +Z -X -Y -Z)
|
|
1842
|
+
* @param format defines the data format
|
|
1843
|
+
* @param type defines the type of the data
|
|
1844
|
+
* @param invertY defines if data must be stored with Y axis inverted
|
|
1845
|
+
* @param compression defines the compression used (null by default)
|
|
1846
|
+
* @param level defines which mip level of the texture to update (0 by default)
|
|
1847
|
+
*/
|
|
1848
|
+
updateRawCubeTexture(texture, data, format, type, invertY, compression = null, level = 0) {
|
|
1849
|
+
if (compression) {
|
|
1850
|
+
throw new Error(`NativeEngine.updateRawCubeTexture: compressed raw cube uploads are not supported (${compression}).`);
|
|
1851
|
+
}
|
|
1852
|
+
const descriptorChanged = texture.format !== format || texture.type !== type;
|
|
1853
|
+
if (descriptorChanged && level !== 0) {
|
|
1854
|
+
throw new Error("NativeEngine.updateRawCubeTexture: changing the format or type is only supported when updating level 0.");
|
|
1855
|
+
}
|
|
1856
|
+
const nativeTexture = texture._hardwareTexture?.underlyingResource;
|
|
1857
|
+
const nativeTextureFormat = descriptorChanged ? getNativeTextureFormat(format, type) : undefined;
|
|
1858
|
+
if (descriptorChanged && nativeTexture) {
|
|
1859
|
+
this._engine.initializeTexture(nativeTexture, texture.width, texture.height, texture.generateMipMaps, nativeTextureFormat,
|
|
1860
|
+
/*renderTarget*/ false, texture._useSRGBBuffer,
|
|
1861
|
+
/*samples*/ 1,
|
|
1862
|
+
/*isCube*/ true);
|
|
1863
|
+
this._setTextureSampling(nativeTexture, getNativeSamplingMode(texture.samplingMode));
|
|
1864
|
+
}
|
|
1865
|
+
// NativeEngine.updateTextureData honors invertY directly on cubes (no D3D origin
|
|
1866
|
+
// compensation). That matches WebGL: HDRCubeTexture uploads with invertY=false and
|
|
1867
|
+
// UNPACK_FLIP_Y_WEBGL=false. Forcing invertY here double-flipped float/half faces and
|
|
1868
|
+
// made the -Y cubemap a hard brown cap on OpenPBR IBL (513/514). Byte RGBD .env
|
|
1869
|
+
// uploads already pass invertY=true and are unchanged.
|
|
1870
|
+
texture.format = format;
|
|
1871
|
+
texture.type = type;
|
|
1872
|
+
texture.invertY = invertY;
|
|
1873
|
+
texture._compression = compression;
|
|
1874
|
+
if (level === 0 && !this._doNotHandleContextLost) {
|
|
1875
|
+
texture._bufferViewArray = data;
|
|
1876
|
+
}
|
|
1877
|
+
// Data are in +X +Y +Z -X -Y -Z order, which matches the bgfx cube sides. Like gl.generateMipmap in the
|
|
1878
|
+
// WebGL path, Native rebuilds the rest of each face's mip chain from a full level 0 upload.
|
|
1879
|
+
const width = Math.max(1, texture.width >> level);
|
|
1880
|
+
const height = Math.max(1, texture.height >> level);
|
|
1881
|
+
const generateMipMaps = level === 0 && texture.generateMipMaps;
|
|
1882
|
+
for (let faceIndex = 0; faceIndex < 6; faceIndex++) {
|
|
1883
|
+
this.updateTextureData(texture, data[faceIndex], 0, 0, width, height, faceIndex, level, generateMipMaps);
|
|
1507
1884
|
}
|
|
1508
1885
|
texture.isReady = true;
|
|
1509
1886
|
}
|
|
@@ -1547,8 +1924,14 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
1547
1924
|
// some formats are already supported by bimg, no need to try to load them with JS
|
|
1548
1925
|
// leaving TextureLoader extension check for future use
|
|
1549
1926
|
let loaderPromise = null;
|
|
1550
|
-
if (extension.endsWith(".
|
|
1551
|
-
|
|
1927
|
+
if (extension.endsWith(".ies")) {
|
|
1928
|
+
// The UMD/global build (used by Babylon Native) stubs dynamic import(), so
|
|
1929
|
+
// AbstractEngine.GetCompatibleTextureLoader cannot resolve the loader module. Instantiate the
|
|
1930
|
+
// statically-bundled IES loader directly instead.
|
|
1931
|
+
loaderPromise = Promise.resolve(new _IESTextureLoader());
|
|
1932
|
+
}
|
|
1933
|
+
else if (extension.endsWith(".basis") || extension.endsWith(".ktx") || extension.endsWith(".ktx2") || mimeType === "image/ktx" || mimeType === "image/ktx2") {
|
|
1934
|
+
loaderPromise = AbstractEngine.GetCompatibleTextureLoader(extension, mimeType);
|
|
1552
1935
|
}
|
|
1553
1936
|
if (scene) {
|
|
1554
1937
|
scene.addPendingData(texture);
|
|
@@ -1570,6 +1953,7 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
1570
1953
|
this._internalTexturesCache.push(texture);
|
|
1571
1954
|
}
|
|
1572
1955
|
const onInternalError = (message, exception) => {
|
|
1956
|
+
texture.isReady = false;
|
|
1573
1957
|
if (scene) {
|
|
1574
1958
|
scene.removePendingData(texture);
|
|
1575
1959
|
}
|
|
@@ -1580,8 +1964,10 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
1580
1964
|
if (EngineStore.UseFallbackTexture) {
|
|
1581
1965
|
this.createTexture(EngineStore.FallbackTexture, noMipmap, texture.invertY, scene, samplingMode, null, onError, buffer, texture);
|
|
1582
1966
|
}
|
|
1967
|
+
const errorMessage = (message || "Unknown error") + (EngineStore.UseFallbackTexture ? " - Fallback texture was used" : "");
|
|
1968
|
+
texture._setError(errorMessage, exception);
|
|
1583
1969
|
if (onError) {
|
|
1584
|
-
onError(
|
|
1970
|
+
onError(errorMessage, exception);
|
|
1585
1971
|
}
|
|
1586
1972
|
}
|
|
1587
1973
|
else {
|
|
@@ -1592,7 +1978,78 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
1592
1978
|
};
|
|
1593
1979
|
// processing for non-image formats
|
|
1594
1980
|
if (loaderPromise) {
|
|
1595
|
-
|
|
1981
|
+
// These formats (e.g. .ies) are decoded on the JS side by an IInternalTextureLoader and then
|
|
1982
|
+
// uploaded to the native texture as raw pixel data. bimg cannot decode them directly.
|
|
1983
|
+
const texLoaderPromise = loaderPromise;
|
|
1984
|
+
const callbackAsync = async (data) => {
|
|
1985
|
+
const loader = await texLoaderPromise;
|
|
1986
|
+
loader.loadData(data, texture, (width, height, loadMipmap, isCompressed, done, loadFailed) => {
|
|
1987
|
+
if (loadFailed) {
|
|
1988
|
+
onInternalError("TextureLoader failed to load data");
|
|
1989
|
+
return;
|
|
1990
|
+
}
|
|
1991
|
+
const baseWidth = texture.baseWidth || width;
|
|
1992
|
+
const baseHeight = texture.baseHeight || height;
|
|
1993
|
+
texture.baseWidth = baseWidth;
|
|
1994
|
+
texture.baseHeight = baseHeight;
|
|
1995
|
+
texture.width = baseWidth;
|
|
1996
|
+
texture.height = baseHeight;
|
|
1997
|
+
// The loader-supplied done() performs the actual GPU upload (e.g. via
|
|
1998
|
+
// _uploadDataToTextureDirectly), so texture dimensions must be set beforehand.
|
|
1999
|
+
try {
|
|
2000
|
+
done();
|
|
2001
|
+
}
|
|
2002
|
+
finally {
|
|
2003
|
+
// Some loaders temporarily publish each mip's dimensions through width/height.
|
|
2004
|
+
// Restore the level-zero dimensions even when a later mip upload fails.
|
|
2005
|
+
texture.baseWidth = baseWidth;
|
|
2006
|
+
texture.baseHeight = baseHeight;
|
|
2007
|
+
texture.width = baseWidth;
|
|
2008
|
+
texture.height = baseHeight;
|
|
2009
|
+
}
|
|
2010
|
+
if (texture._hardwareTexture) {
|
|
2011
|
+
const filter = getNativeSamplingMode(samplingMode);
|
|
2012
|
+
this._setTextureSampling(texture._hardwareTexture.underlyingResource, filter);
|
|
2013
|
+
}
|
|
2014
|
+
texture.isReady = true;
|
|
2015
|
+
if (scene) {
|
|
2016
|
+
scene.removePendingData(texture);
|
|
2017
|
+
}
|
|
2018
|
+
texture.onLoadedObservable.notifyObservers(texture);
|
|
2019
|
+
texture.onLoadedObservable.clear();
|
|
2020
|
+
}, loaderOptions);
|
|
2021
|
+
};
|
|
2022
|
+
if (buffer) {
|
|
2023
|
+
const processBufferAsync = async (data) => {
|
|
2024
|
+
try {
|
|
2025
|
+
await callbackAsync(data);
|
|
2026
|
+
}
|
|
2027
|
+
catch (reason) {
|
|
2028
|
+
onInternalError("Failed to parse texture data", reason);
|
|
2029
|
+
}
|
|
2030
|
+
};
|
|
2031
|
+
if (buffer instanceof ArrayBuffer) {
|
|
2032
|
+
void processBufferAsync(new Uint8Array(buffer));
|
|
2033
|
+
}
|
|
2034
|
+
else if (ArrayBuffer.isView(buffer)) {
|
|
2035
|
+
void processBufferAsync(buffer);
|
|
2036
|
+
}
|
|
2037
|
+
else {
|
|
2038
|
+
onInternalError("Unable to load: only ArrayBuffer or ArrayBufferView is supported");
|
|
2039
|
+
}
|
|
2040
|
+
}
|
|
2041
|
+
else {
|
|
2042
|
+
this._loadFile(url, async (data) => {
|
|
2043
|
+
try {
|
|
2044
|
+
await callbackAsync(new Uint8Array(data));
|
|
2045
|
+
}
|
|
2046
|
+
catch (reason) {
|
|
2047
|
+
onInternalError("Failed to parse texture data", reason);
|
|
2048
|
+
}
|
|
2049
|
+
}, undefined, undefined, true, (request, exception) => {
|
|
2050
|
+
onInternalError("Unable to load " + (request ? request.responseURL : url), exception);
|
|
2051
|
+
});
|
|
2052
|
+
}
|
|
1596
2053
|
}
|
|
1597
2054
|
else {
|
|
1598
2055
|
const onload = (data) => {
|
|
@@ -1738,16 +2195,51 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
1738
2195
|
continue;
|
|
1739
2196
|
}
|
|
1740
2197
|
const nativeRTWrapper = rtWrapper;
|
|
2198
|
+
if (nativeRTWrapper._framebuffers && !rtWrapper.isCube) {
|
|
2199
|
+
// Wrapped 2D-array color attachment with one framebuffer per layer: rebuild every layer
|
|
2200
|
+
// against the new handle. The _framebuffers setter releases the stale handles.
|
|
2201
|
+
const { generateDepth, generateStencil } = this._getLayerFramebufferDepthStencil(rtWrapper);
|
|
2202
|
+
nativeRTWrapper._framebuffers = this._createLayerFramebuffers(texture, rtWrapper.width, rtWrapper.height, nativeRTWrapper._framebuffers.length, generateStencil, generateDepth, rtWrapper.samples ?? 1, rtWrapper.texture?.generateMipMaps);
|
|
2203
|
+
continue;
|
|
2204
|
+
}
|
|
1741
2205
|
// NativeRenderTargetWrapper._framebuffer setter releases the old framebuffer before assigning,
|
|
1742
2206
|
// so no manual _releaseFramebufferObjects call is needed (and would double-delete the handle).
|
|
1743
2207
|
nativeRTWrapper._framebuffer = this._engine.createFrameBuffer(texture, rtWrapper.width, rtWrapper.height, rtWrapper._generateStencilBuffer, rtWrapper._generateDepthBuffer, rtWrapper.samples ?? 1);
|
|
1744
2208
|
}
|
|
1745
2209
|
}
|
|
2210
|
+
/**
|
|
2211
|
+
* Creates a depth/stencil texture for a render target wrapper.
|
|
2212
|
+
* @param size The size of the depth texture
|
|
2213
|
+
* @param options The options defining the depth texture
|
|
2214
|
+
* @param rtWrapper The render target wrapper the depth texture belongs to
|
|
2215
|
+
* @returns The depth/stencil texture
|
|
2216
|
+
*/
|
|
2217
|
+
createDepthStencilTexture(size, options, rtWrapper) {
|
|
2218
|
+
// AbstractEngine routes cube render targets (point-light shadow maps) to _createDepthStencilCubeTexture,
|
|
2219
|
+
// which only exists on the WebGL engine and drives gl.TEXTURE_CUBE_MAP directly. Native already handles
|
|
2220
|
+
// cube and 2D-array targets in _createDepthStencilTexture through the wrapper's per-face framebuffers,
|
|
2221
|
+
// so route every request there instead of throwing on an undefined GL context.
|
|
2222
|
+
return this._createDepthStencilTexture(size, options, rtWrapper);
|
|
2223
|
+
}
|
|
1746
2224
|
_createDepthStencilTexture(size, options, rtWrapper) {
|
|
1747
2225
|
// TODO: handle other options?
|
|
1748
|
-
const
|
|
2226
|
+
const requestedFormat = options.depthTextureFormat;
|
|
2227
|
+
// Native allocates either D32F (depth only) or D24S8 (depth + stencil). Requested depth formats map onto
|
|
2228
|
+
// whichever of those matches their stencil aspect, and texture.format records what was actually allocated.
|
|
2229
|
+
const requestedStencil = requestedFormat === 13 ||
|
|
2230
|
+
requestedFormat === 17 ||
|
|
2231
|
+
requestedFormat === 18;
|
|
2232
|
+
if (requestedFormat !== undefined &&
|
|
2233
|
+
!requestedStencil &&
|
|
2234
|
+
requestedFormat !== 15 &&
|
|
2235
|
+
requestedFormat !== 16 &&
|
|
2236
|
+
requestedFormat !== 14) {
|
|
2237
|
+
throw new Error(`NativeEngine: depth texture format ${requestedFormat} is not supported.`);
|
|
2238
|
+
}
|
|
2239
|
+
const generateStencil = !!options.generateStencil || requestedStencil;
|
|
1749
2240
|
const samples = options.samples || 1;
|
|
1750
2241
|
const nativeRTWrapper = rtWrapper;
|
|
2242
|
+
this._assertDepthAttachmentCompatible(nativeRTWrapper, samples);
|
|
1751
2243
|
const texture = new InternalTexture(this, 12 /* InternalTextureSource.DepthStencil */);
|
|
1752
2244
|
const width = size.width ?? size;
|
|
1753
2245
|
const height = size.height ?? size;
|
|
@@ -1763,27 +2255,367 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
1763
2255
|
texture.width = width;
|
|
1764
2256
|
texture.height = height;
|
|
1765
2257
|
texture.is2DArray = layers > 0;
|
|
2258
|
+
texture.isCube = !!options.isCube;
|
|
1766
2259
|
texture.depth = layers || depth;
|
|
1767
2260
|
texture.isReady = true;
|
|
1768
2261
|
texture.samples = samples;
|
|
1769
2262
|
texture.generateMipMaps = false;
|
|
1770
2263
|
texture.samplingMode = options.bilinearFiltering ? 2 : 1;
|
|
1771
2264
|
texture.type = 0;
|
|
2265
|
+
texture.format = generateStencil ? 13 : 14;
|
|
1772
2266
|
texture._comparisonFunction = options.comparisonFunction ?? 0;
|
|
1773
|
-
|
|
1774
|
-
nativeRTWrapper
|
|
2267
|
+
nativeRTWrapper._depthStencilTextureWithStencil = generateStencil;
|
|
2268
|
+
this._attachDepthStencilTexture(nativeRTWrapper, texture, width, height, generateStencil, samples);
|
|
1775
2269
|
return texture;
|
|
1776
2270
|
}
|
|
2271
|
+
/**
|
|
2272
|
+
* Builds the framebuffer(s) of a render target so they carry its sampleable depth/stencil texture. The depth
|
|
2273
|
+
* texture's native handle must not be allocated yet: the first framebuffer creation allocates it.
|
|
2274
|
+
* @internal
|
|
2275
|
+
*/
|
|
2276
|
+
_attachDepthStencilTexture(nativeRTWrapper, texture, width, height, generateStencil, samples) {
|
|
2277
|
+
if (nativeRTWrapper.is3D) {
|
|
2278
|
+
this._assertVolumeDepthAttachmentSupported(texture.samples, samples);
|
|
2279
|
+
// Volume slices bind lazily built framebuffers; drop cached slices so the next bind attaches the new depth.
|
|
2280
|
+
nativeRTWrapper._releaseLayerFramebuffers();
|
|
2281
|
+
return;
|
|
2282
|
+
}
|
|
2283
|
+
if (nativeRTWrapper._framebuffers) {
|
|
2284
|
+
// Layered (2D array) or cube render target: the color framebuffers were created one-per-layer
|
|
2285
|
+
// (see createRenderTargetTexture / createRenderTargetCubeTexture). When the color RTT was built
|
|
2286
|
+
// without a depth buffer (e.g. cascaded shadow maps create the RTT with generateDepthBuffer=false
|
|
2287
|
+
// and then call createDepthStencilTexture), rebuild each per-layer framebuffer so it carries a
|
|
2288
|
+
// *shared sampleable* depth/stencil array attachment. PCF binds the whole array as
|
|
2289
|
+
// sampler2DArrayShadow; each cascade layer framebuffer writes into its own depth slice.
|
|
2290
|
+
// A single shared _framebufferDepthStencil would be ignored because bindFramebuffer selects
|
|
2291
|
+
// _framebuffers[layer] first.
|
|
2292
|
+
const colorTexture = nativeRTWrapper.texture;
|
|
2293
|
+
if (colorTexture && colorTexture._hardwareTexture) {
|
|
2294
|
+
const nativeColor = colorTexture._hardwareTexture.underlyingResource;
|
|
2295
|
+
const nativeDepth = texture._hardwareTexture.underlyingResource;
|
|
2296
|
+
const layerCount = nativeRTWrapper._framebuffers.length;
|
|
2297
|
+
const framebuffers = [];
|
|
2298
|
+
for (let layer = 0; layer < layerCount; layer++) {
|
|
2299
|
+
// First call creates the multi-layer sampleable depth and aliases it into nativeDepth;
|
|
2300
|
+
// subsequent calls borrow the same depth array and attach the matching layer.
|
|
2301
|
+
framebuffers.push(this._createNativeMultiFrameBuffer([nativeColor], width, height, generateStencil, true, samples, [layer], nativeDepth));
|
|
2302
|
+
}
|
|
2303
|
+
// The _framebuffers setter releases the previous handles.
|
|
2304
|
+
nativeRTWrapper._framebuffers = framebuffers;
|
|
2305
|
+
this._setTextureSampling(nativeDepth, getNativeSamplingMode(texture.samplingMode));
|
|
2306
|
+
this.updateTextureComparisonFunction(texture, texture._comparisonFunction);
|
|
2307
|
+
}
|
|
2308
|
+
return;
|
|
2309
|
+
}
|
|
2310
|
+
// Plain 2D render target: build a framebuffer that carries BOTH the render target's color attachment
|
|
2311
|
+
// and the standalone depth/stencil texture. bindFramebuffer prefers _framebufferDepthStencil over
|
|
2312
|
+
// _framebuffer, so attaching depth alone would silently drop the color target -- shadow maps would
|
|
2313
|
+
// render their packed depth into nothing. The depth texture's bgfx handle is still invalid at this
|
|
2314
|
+
// point, which is how CreateFrameBufferImpl recognizes a request for a readable depth attachment that
|
|
2315
|
+
// it aliases back into the supplied texture so it can be sampled afterwards.
|
|
2316
|
+
const colorResources = [];
|
|
2317
|
+
for (const colorTexture of nativeRTWrapper.textures ?? []) {
|
|
2318
|
+
const colorResource = colorTexture?._hardwareTexture?.underlyingResource;
|
|
2319
|
+
if (colorResource) {
|
|
2320
|
+
colorResources.push(colorResource);
|
|
2321
|
+
}
|
|
2322
|
+
}
|
|
2323
|
+
const nativeDepth = texture._hardwareTexture.underlyingResource;
|
|
2324
|
+
const framebuffer = this._createNativeMultiFrameBuffer(colorResources, width, height, generateStencil, true, samples, undefined, nativeDepth);
|
|
2325
|
+
nativeRTWrapper._framebufferDepthStencil = framebuffer;
|
|
2326
|
+
this._setTextureSampling(nativeDepth, getNativeSamplingMode(texture.samplingMode));
|
|
2327
|
+
this.updateTextureComparisonFunction(texture, texture._comparisonFunction);
|
|
2328
|
+
}
|
|
2329
|
+
// Reallocates a render target's sampleable depth/stencil texture with a new sample count and reattaches it to
|
|
2330
|
+
// the (already rebuilt) color framebuffer(s), so rendering and later depth sampling keep using the same resource.
|
|
2331
|
+
_recreateDepthStencilTexture(nativeRTWrapper, samples) {
|
|
2332
|
+
const depthTexture = nativeRTWrapper._depthStencilTexture;
|
|
2333
|
+
if (!depthTexture?._hardwareTexture) {
|
|
2334
|
+
return;
|
|
2335
|
+
}
|
|
2336
|
+
const previous = depthTexture._hardwareTexture;
|
|
2337
|
+
depthTexture._hardwareTexture = this._createHardwareTexture();
|
|
2338
|
+
depthTexture.samples = samples;
|
|
2339
|
+
if (nativeRTWrapper.isMulti) {
|
|
2340
|
+
nativeRTWrapper._framebufferDepthStencil = null;
|
|
2341
|
+
}
|
|
2342
|
+
else {
|
|
2343
|
+
this._attachDepthStencilTexture(nativeRTWrapper, depthTexture, depthTexture.width, depthTexture.height, nativeRTWrapper._depthStencilTextureWithStencil, samples);
|
|
2344
|
+
}
|
|
2345
|
+
previous.release();
|
|
2346
|
+
}
|
|
2347
|
+
/**
|
|
2348
|
+
* Returns whether a render-target texture was created with mip storage, independently of generateMipMaps.
|
|
2349
|
+
* @internal
|
|
2350
|
+
*/
|
|
2351
|
+
_hasMipStorage(texture) {
|
|
2352
|
+
return _TexturesWithMipStorage.has(texture) || texture.generateMipMaps;
|
|
2353
|
+
}
|
|
2354
|
+
_setHasMipStorage(texture, hasMipStorage) {
|
|
2355
|
+
if (hasMipStorage) {
|
|
2356
|
+
_TexturesWithMipStorage.add(texture);
|
|
2357
|
+
}
|
|
2358
|
+
else {
|
|
2359
|
+
_TexturesWithMipStorage.delete(texture);
|
|
2360
|
+
}
|
|
2361
|
+
}
|
|
2362
|
+
/**
|
|
2363
|
+
* Ensures a cloned render-target texture retains allocation-only mip storage.
|
|
2364
|
+
* @internal
|
|
2365
|
+
*/
|
|
2366
|
+
_ensureRenderTargetMipStorage(texture) {
|
|
2367
|
+
if (this._hasMipStorage(texture)) {
|
|
2368
|
+
return false;
|
|
2369
|
+
}
|
|
2370
|
+
this._setHasMipStorage(texture, true);
|
|
2371
|
+
if (!texture._hardwareTexture) {
|
|
2372
|
+
return false;
|
|
2373
|
+
}
|
|
2374
|
+
this._engine.initializeTexture(texture._hardwareTexture.underlyingResource, texture.baseWidth, texture.baseHeight, this._getRenderTargetHasMips(true, texture.samples), getNativeTextureFormat(texture.format, texture.type),
|
|
2375
|
+
/*renderTarget*/ true, texture._useSRGBBuffer, texture.samples, texture.isCube, texture.is2DArray || texture.is3D ? texture.depth : 0, texture.is3D);
|
|
2376
|
+
return true;
|
|
2377
|
+
}
|
|
2378
|
+
/**
|
|
2379
|
+
* Rebuilds native framebuffer objects after a wrapper's explicit depth attachment changes.
|
|
2380
|
+
* @internal
|
|
2381
|
+
*/
|
|
2382
|
+
_rebuildRenderTargetFramebuffersAfterDepthChange(nativeRTWrapper) {
|
|
2383
|
+
nativeRTWrapper._releaseLayerFramebuffers();
|
|
2384
|
+
nativeRTWrapper._framebufferDepthStencil = null;
|
|
2385
|
+
if (nativeRTWrapper._usesLayeredFramebuffer) {
|
|
2386
|
+
nativeRTWrapper._invalidateLayeredFramebuffer();
|
|
2387
|
+
return;
|
|
2388
|
+
}
|
|
2389
|
+
if (nativeRTWrapper.isMulti) {
|
|
2390
|
+
if (nativeRTWrapper._framebuffer && this._isFrameGraphFramebuffer(nativeRTWrapper._framebuffer)) {
|
|
2391
|
+
nativeRTWrapper._framebuffer = null;
|
|
2392
|
+
}
|
|
2393
|
+
else if (nativeRTWrapper._framebuffer) {
|
|
2394
|
+
this._createMultiRenderTargetFramebuffer(nativeRTWrapper);
|
|
2395
|
+
}
|
|
2396
|
+
return;
|
|
2397
|
+
}
|
|
2398
|
+
const texture = nativeRTWrapper.texture;
|
|
2399
|
+
const nativeTexture = texture?._hardwareTexture?.underlyingResource;
|
|
2400
|
+
const depthTexture = nativeRTWrapper._depthStencilTexture;
|
|
2401
|
+
const nativeDepth = depthTexture?._hardwareTexture?.underlyingResource;
|
|
2402
|
+
if (nativeRTWrapper._framebuffers && nativeTexture) {
|
|
2403
|
+
if (nativeDepth) {
|
|
2404
|
+
this._attachDepthStencilTexture(nativeRTWrapper, depthTexture, nativeRTWrapper.width, nativeRTWrapper.height, nativeRTWrapper._depthStencilTextureWithStencil, nativeRTWrapper.samples);
|
|
2405
|
+
}
|
|
2406
|
+
else {
|
|
2407
|
+
nativeRTWrapper._framebuffers = this._createLayerFramebuffers(nativeTexture, nativeRTWrapper.width, nativeRTWrapper.height, nativeRTWrapper.isCube ? 6 : nativeRTWrapper.layers, nativeRTWrapper._generateStencilBuffer, nativeRTWrapper._generateDepthBuffer, nativeRTWrapper.samples, nativeRTWrapper.texture?.generateMipMaps);
|
|
2408
|
+
}
|
|
2409
|
+
return;
|
|
2410
|
+
}
|
|
2411
|
+
if (nativeDepth) {
|
|
2412
|
+
this._attachDepthStencilTexture(nativeRTWrapper, depthTexture, nativeRTWrapper.width, nativeRTWrapper.height, nativeRTWrapper._depthStencilTextureWithStencil, nativeRTWrapper.samples);
|
|
2413
|
+
}
|
|
2414
|
+
else {
|
|
2415
|
+
nativeRTWrapper._framebuffer = this._engine.createFrameBuffer(nativeTexture ?? null, nativeRTWrapper.width, nativeRTWrapper.height, nativeRTWrapper._generateStencilBuffer, nativeRTWrapper._generateDepthBuffer, nativeRTWrapper.samples);
|
|
2416
|
+
}
|
|
2417
|
+
}
|
|
2418
|
+
/**
|
|
2419
|
+
* Rejects an explicit depth attachment the render target cannot use, before any attachment state is mutated.
|
|
2420
|
+
* bgfx requires every framebuffer attachment to share one sample count.
|
|
2421
|
+
* @internal
|
|
2422
|
+
*/
|
|
2423
|
+
_assertDepthAttachmentCompatible(rtWrapper, depthSamples) {
|
|
2424
|
+
if (rtWrapper.is3D) {
|
|
2425
|
+
this._assertVolumeDepthAttachmentSupported();
|
|
2426
|
+
}
|
|
2427
|
+
if ((depthSamples || 1) !== (rtWrapper.samples || 1)) {
|
|
2428
|
+
throw new Error(`NativeEngine: explicit depth attachments must use the render target's sample count (depth: ${depthSamples || 1}, color: ${rtWrapper.samples || 1}).`);
|
|
2429
|
+
}
|
|
2430
|
+
}
|
|
2431
|
+
/**
|
|
2432
|
+
* Whether the depth attachment carries stencil: an explicit depth texture decides from its own format (its handle
|
|
2433
|
+
* may be unallocated after a sample-count change), otherwise the automatic depth buffer request does.
|
|
2434
|
+
* @internal
|
|
2435
|
+
*/
|
|
2436
|
+
_getDepthAttachmentStencil(rtWrapper) {
|
|
2437
|
+
const depthTexture = rtWrapper._depthStencilTexture;
|
|
2438
|
+
return depthTexture ? HasStencilAspect(depthTexture.format) : rtWrapper._generateStencilBuffer;
|
|
2439
|
+
}
|
|
2440
|
+
/** @internal */
|
|
2441
|
+
_assertVolumeDepthAttachmentSupported(depthSamples, colorSamples) {
|
|
2442
|
+
if (!this._engine.createMultiFrameBuffer) {
|
|
2443
|
+
throw new Error("NativeEngine: explicit depth attachments on volume render targets require createMultiFrameBuffer support.");
|
|
2444
|
+
}
|
|
2445
|
+
if (depthSamples !== undefined && colorSamples !== undefined && depthSamples !== colorSamples) {
|
|
2446
|
+
throw new Error("NativeEngine: explicit depth and color attachments on volume render targets must use the same sample count.");
|
|
2447
|
+
}
|
|
2448
|
+
}
|
|
2449
|
+
/**
|
|
2450
|
+
* Updates a depth texture Comparison Mode and Function.
|
|
2451
|
+
* @param texture The texture to set the comparison function for
|
|
2452
|
+
* @param comparisonFunction The comparison function to set, 0 if no comparison required
|
|
2453
|
+
*/
|
|
2454
|
+
updateTextureComparisonFunction(texture, comparisonFunction) {
|
|
2455
|
+
texture._comparisonFunction = comparisonFunction;
|
|
2456
|
+
// Drive bgfx BGFX_SAMPLER_COMPARE_* so PCF/PCSS shaders (sampler2DShadow / sampler2DArrayShadow)
|
|
2457
|
+
// get hardware depth compares. Engine-agnostic callers (LightingVolume) also toggle this around
|
|
2458
|
+
// a copy and expect the recorded value to stay in sync even when the hardware texture is missing.
|
|
2459
|
+
const nativeTexture = texture._hardwareTexture?.underlyingResource;
|
|
2460
|
+
if (nativeTexture && this._engine.setTextureComparisonFunction) {
|
|
2461
|
+
this._engine.setTextureComparisonFunction(nativeTexture, comparisonFunction);
|
|
2462
|
+
}
|
|
2463
|
+
}
|
|
2464
|
+
/**
|
|
2465
|
+
* Generates mipmaps for the given texture.
|
|
2466
|
+
* @param _texture The texture to generate the mipmaps for.
|
|
2467
|
+
*/
|
|
2468
|
+
generateMipmaps(_texture) {
|
|
2469
|
+
// The WebGL implementation binds the texture and calls gl.generateMipmap; there is no equivalent
|
|
2470
|
+
// standalone command on Babylon Native, and none is needed: a render target whose mip chain must be
|
|
2471
|
+
// rebuilt is attached to its framebuffer with BGFX_RESOLVE_AUTO_GEN_MIPS (see CreateFrameBufferImpl),
|
|
2472
|
+
// so bgfx regenerates the chain when the view resolves. Without this override the inherited WebGL path
|
|
2473
|
+
// dereferenced a non-existent GL context (frame graph tasks call generateMipMaps explicitly).
|
|
2474
|
+
}
|
|
2475
|
+
/**
|
|
2476
|
+
* Creates one framebuffer per layer (or cube face) of a native texture.
|
|
2477
|
+
* @internal
|
|
2478
|
+
*/
|
|
2479
|
+
_createLayerFramebuffers(nativeTexture, width, height, layerCount, generateStencilBuffer, generateDepthBuffer, samples, autoGenerateMips = true) {
|
|
2480
|
+
const framebuffers = [];
|
|
2481
|
+
for (let layer = 0; layer < layerCount; layer++) {
|
|
2482
|
+
framebuffers.push(this._engine.createFrameBuffer(nativeTexture, width, height, generateStencilBuffer, generateDepthBuffer, samples, layer, 0, autoGenerateMips));
|
|
2483
|
+
}
|
|
2484
|
+
return framebuffers;
|
|
2485
|
+
}
|
|
2486
|
+
/**
|
|
2487
|
+
* Per-layer framebuffers carry their own depth/stencil attachment, either requested at creation or added by
|
|
2488
|
+
* createDepthStencilTexture (see _createDepthStencilTexture), so recreate them with the same attachments.
|
|
2489
|
+
* @internal
|
|
2490
|
+
*/
|
|
2491
|
+
_getLayerFramebufferDepthStencil(rtWrapper) {
|
|
2492
|
+
const hasDepthStencilTexture = !!rtWrapper._depthStencilTexture;
|
|
2493
|
+
return {
|
|
2494
|
+
generateDepth: rtWrapper._generateDepthBuffer || hasDepthStencilTexture,
|
|
2495
|
+
generateStencil: rtWrapper._generateStencilBuffer || (hasDepthStencilTexture && rtWrapper._depthStencilTextureWithStencil),
|
|
2496
|
+
};
|
|
2497
|
+
}
|
|
1777
2498
|
/**
|
|
1778
2499
|
* @internal
|
|
1779
2500
|
*/
|
|
1780
2501
|
_releaseFramebufferObjects(framebuffer) {
|
|
1781
2502
|
if (framebuffer) {
|
|
2503
|
+
// Frame graph framebuffers are shared across several render-target wrappers (see
|
|
2504
|
+
// _buildFrameGraphFramebuffer). Each wrapper releases its reference on dispose/reassignment, so
|
|
2505
|
+
// reference-count the shared framebuffer and only delete the underlying bgfx handle once.
|
|
2506
|
+
const shared = this._frameGraphFramebufferRefCount.get(framebuffer);
|
|
2507
|
+
if (shared !== undefined) {
|
|
2508
|
+
if (shared.count > 1) {
|
|
2509
|
+
shared.count--;
|
|
2510
|
+
return;
|
|
2511
|
+
}
|
|
2512
|
+
this._frameGraphFramebufferRefCount.delete(framebuffer);
|
|
2513
|
+
if (shared.hardwareTexture._frameGraphFramebuffer === framebuffer) {
|
|
2514
|
+
shared.hardwareTexture._frameGraphFramebuffer = null;
|
|
2515
|
+
}
|
|
2516
|
+
}
|
|
1782
2517
|
this._commandBufferEncoder.startEncodingCommand(_native.Engine.COMMAND_DELETEFRAMEBUFFER);
|
|
1783
2518
|
this._commandBufferEncoder.encodeCommandArgAsNativeData(framebuffer);
|
|
1784
2519
|
this._commandBufferEncoder.finishEncodingCommand();
|
|
1785
2520
|
}
|
|
1786
2521
|
}
|
|
2522
|
+
/**
|
|
2523
|
+
* Returns true when the given framebuffer was built by the frame graph path (_buildFrameGraphFramebuffer),
|
|
2524
|
+
* i.e. it is reference-counted, shared between wrappers and rebuilt lazily on bind.
|
|
2525
|
+
* @param framebuffer The framebuffer to test
|
|
2526
|
+
* @returns true if the framebuffer is a frame graph framebuffer
|
|
2527
|
+
* @internal
|
|
2528
|
+
*/
|
|
2529
|
+
_isFrameGraphFramebuffer(framebuffer) {
|
|
2530
|
+
return this._frameGraphFramebufferRefCount.has(framebuffer);
|
|
2531
|
+
}
|
|
2532
|
+
// Reference counts + metadata for framebuffers shared across frame graph render-target wrappers
|
|
2533
|
+
// are stored in _frameGraphFramebufferRefCount (declared with the other engine fields).
|
|
2534
|
+
/**
|
|
2535
|
+
* Lazily builds (or reuses a shared) bgfx framebuffer for a frame graph render-target wrapper whose
|
|
2536
|
+
* textures were attached after creation (dontCreateTextures). All wrappers that reference the same
|
|
2537
|
+
* underlying color texture share a single framebuffer, cached on that texture's hardware wrapper, so that
|
|
2538
|
+
* successive passes (clear, object render, post) accumulate into the same target instead of each fresh
|
|
2539
|
+
* framebuffer/view clearing it.
|
|
2540
|
+
* @internal
|
|
2541
|
+
*/
|
|
2542
|
+
_buildFrameGraphFramebuffer(nativeRTWrapper) {
|
|
2543
|
+
const textures = nativeRTWrapper.textures;
|
|
2544
|
+
if (!textures || textures.length === 0) {
|
|
2545
|
+
// Depth-only frame graph render target: 0 color attachments plus a shared depth-stencil texture.
|
|
2546
|
+
// The FrameGraph schedules a standalone depth-clear pass against the geometry buffer's depth texture,
|
|
2547
|
+
// separately from the geometry MRT render. Build a depth-only framebuffer that BORROWS the shared
|
|
2548
|
+
// depth texture (its bgfx handle is already valid, created up-front by _createInternalTexture) so the
|
|
2549
|
+
// clear hits the exact buffer the geometry MRT later depth-tests against. Without this the clear is
|
|
2550
|
+
// misdirected to the back buffer and the geometry prepass depth is never cleared, leaving the geometry
|
|
2551
|
+
// buffer empty (breaks SSR / motion blur / curvature / SSAO).
|
|
2552
|
+
const depthOnlyTexture = nativeRTWrapper._depthStencilTexture;
|
|
2553
|
+
const depthOnlyResource = depthOnlyTexture?._hardwareTexture?.underlyingResource;
|
|
2554
|
+
if (depthOnlyResource && !nativeRTWrapper._framebufferDepthStencil) {
|
|
2555
|
+
nativeRTWrapper._framebufferDepthStencil = this._createNativeMultiFrameBuffer([], nativeRTWrapper.width, nativeRTWrapper.height, nativeRTWrapper._generateStencilBuffer, true, depthOnlyTexture.samples || nativeRTWrapper.samples || 1, undefined, depthOnlyResource);
|
|
2556
|
+
}
|
|
2557
|
+
return;
|
|
2558
|
+
}
|
|
2559
|
+
const textureCount = textures.length;
|
|
2560
|
+
for (let i = 0; i < textureCount; i++) {
|
|
2561
|
+
if (!textures[i]?._hardwareTexture?.underlyingResource) {
|
|
2562
|
+
// A color texture is not yet backed by a hardware texture; leave the wrapper unbuilt (the base
|
|
2563
|
+
// path will bind the back buffer). This wrapper will be retried on its next bind.
|
|
2564
|
+
return;
|
|
2565
|
+
}
|
|
2566
|
+
}
|
|
2567
|
+
const hardwareTexture = textures[0]._hardwareTexture;
|
|
2568
|
+
const depthStencilTexture = nativeRTWrapper._depthStencilTexture;
|
|
2569
|
+
const generateDepthBuffer = !!depthStencilTexture || nativeRTWrapper._generateDepthBuffer;
|
|
2570
|
+
const generateStencilBuffer = this._getDepthAttachmentStencil(nativeRTWrapper);
|
|
2571
|
+
const samples = textures[0].samples || nativeRTWrapper.samples || 1;
|
|
2572
|
+
// Like a GL framebuffer, an explicit depth-stencil texture is always attached as-is, so every pass that
|
|
2573
|
+
// references it (clears, geometry, overlays, later samplers) sees the same real depth buffer.
|
|
2574
|
+
const sharedDepthResource = depthStencilTexture?._hardwareTexture?.underlyingResource;
|
|
2575
|
+
const cached = hardwareTexture._frameGraphFramebuffer;
|
|
2576
|
+
const cachedMeta = cached ? this._frameGraphFramebufferRefCount.get(cached) : undefined;
|
|
2577
|
+
// Reuse the cached framebuffer when it is compatible: the same ordered color attachments (a swap of any
|
|
2578
|
+
// attachment, not only the primary one, needs a new framebuffer), the same sample count, depth/stencil
|
|
2579
|
+
// buffers when this pass needs them (a pass that does not need them can safely reuse a framebuffer that
|
|
2580
|
+
// has them), and the same shared depth texture (so a shared-depth pass never reuses an auto-depth
|
|
2581
|
+
// framebuffer, and vice versa). History-texture swaps invalidate these wrappers every frame, so this check
|
|
2582
|
+
// runs in the render loop: compare in place and only allocate the color list for a new framebuffer.
|
|
2583
|
+
let sameColors = !!cachedMeta && cachedMeta.colorResources.length === textureCount;
|
|
2584
|
+
for (let i = 0; sameColors && i < textureCount; i++) {
|
|
2585
|
+
sameColors = cachedMeta.colorResources[i] === textures[i]._hardwareTexture.underlyingResource;
|
|
2586
|
+
}
|
|
2587
|
+
if (cached &&
|
|
2588
|
+
cachedMeta &&
|
|
2589
|
+
sameColors &&
|
|
2590
|
+
cachedMeta.samples === samples &&
|
|
2591
|
+
(cachedMeta.hasDepth || !generateDepthBuffer) &&
|
|
2592
|
+
(cachedMeta.hasStencil || !generateStencilBuffer) &&
|
|
2593
|
+
cachedMeta.sharedDepthResource === sharedDepthResource) {
|
|
2594
|
+
cachedMeta.count++;
|
|
2595
|
+
nativeRTWrapper._framebuffer = cached;
|
|
2596
|
+
return;
|
|
2597
|
+
}
|
|
2598
|
+
const colorTextures = new Array(textureCount);
|
|
2599
|
+
for (let i = 0; i < textureCount; i++) {
|
|
2600
|
+
colorTextures[i] = textures[i]._hardwareTexture.underlyingResource;
|
|
2601
|
+
}
|
|
2602
|
+
const framebuffer = sharedDepthResource
|
|
2603
|
+
? this._createNativeMultiFrameBuffer(colorTextures, nativeRTWrapper.width, nativeRTWrapper.height, generateStencilBuffer, true, samples, undefined, sharedDepthResource)
|
|
2604
|
+
: colorTextures.length === 1
|
|
2605
|
+
? this._engine.createFrameBuffer(colorTextures[0], nativeRTWrapper.width, nativeRTWrapper.height, generateStencilBuffer, generateDepthBuffer, samples)
|
|
2606
|
+
: this._createNativeMultiFrameBuffer(colorTextures, nativeRTWrapper.width, nativeRTWrapper.height, generateStencilBuffer, generateDepthBuffer, samples);
|
|
2607
|
+
this._frameGraphFramebufferRefCount.set(framebuffer, {
|
|
2608
|
+
count: 1,
|
|
2609
|
+
hardwareTexture,
|
|
2610
|
+
colorResources: colorTextures,
|
|
2611
|
+
hasDepth: generateDepthBuffer,
|
|
2612
|
+
hasStencil: generateStencilBuffer,
|
|
2613
|
+
samples,
|
|
2614
|
+
sharedDepthResource,
|
|
2615
|
+
});
|
|
2616
|
+
hardwareTexture._frameGraphFramebuffer = framebuffer;
|
|
2617
|
+
nativeRTWrapper._framebuffer = framebuffer;
|
|
2618
|
+
}
|
|
1787
2619
|
/**
|
|
1788
2620
|
* @internal Engine abstraction for loading and creating an image bitmap from a given source string.
|
|
1789
2621
|
* @param imageSource source to load the image from.
|
|
@@ -1851,9 +2683,19 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
1851
2683
|
this._renderTargetWrapperCache.push(rtWrapper);
|
|
1852
2684
|
return rtWrapper;
|
|
1853
2685
|
}
|
|
2686
|
+
/**
|
|
2687
|
+
* Older bgfx D3D11/D3D12/Vulkan backends share one texture descriptor between the MSAA render target and its
|
|
2688
|
+
* resolve target, so requesting mips together with samples > 1 fails texture creation (BabylonNative#1714).
|
|
2689
|
+
* Only keep the mip chain of a multisampled render target when the runtime reports that it supports it.
|
|
2690
|
+
* @internal
|
|
2691
|
+
*/
|
|
2692
|
+
_getRenderTargetHasMips(generateMipMaps, samples) {
|
|
2693
|
+
return generateMipMaps && (samples <= 1 || !!this._engine.supportsMultisampledMipmaps);
|
|
2694
|
+
}
|
|
1854
2695
|
/** @internal */
|
|
1855
2696
|
_createInternalTexture(size, options, _delayGPUTextureCreation = true, source = 0 /* InternalTextureSource.Unknown */) {
|
|
1856
2697
|
let generateMipMaps;
|
|
2698
|
+
let createMipMaps = false;
|
|
1857
2699
|
let type = 0;
|
|
1858
2700
|
let samplingMode = 3;
|
|
1859
2701
|
let format = 5;
|
|
@@ -1862,6 +2704,7 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
1862
2704
|
let label;
|
|
1863
2705
|
if (options !== undefined && typeof options === "object") {
|
|
1864
2706
|
generateMipMaps = !!options.generateMipMaps;
|
|
2707
|
+
createMipMaps = !!options.createMipMaps;
|
|
1865
2708
|
type = options.type === undefined ? 0 : options.type;
|
|
1866
2709
|
samplingMode = options.samplingMode === undefined ? 3 : options.samplingMode;
|
|
1867
2710
|
format = options.format === undefined ? 5 : options.format;
|
|
@@ -1885,37 +2728,49 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
1885
2728
|
type = 0;
|
|
1886
2729
|
Logger.Warn("Float textures are not supported. Type forced to TEXTURETYPE_UNSIGNED_BYTE");
|
|
1887
2730
|
}
|
|
2731
|
+
// A cube render-target attachment routed through _createInternalTexture (e.g. a frame-graph MRT cube
|
|
2732
|
+
// target: the texture manager creates each attachment via _createInternalTexture and sets isCube for a
|
|
2733
|
+
// TEXTURE_CUBE_MAP target) must be created as a real bgfx cube texture. This path otherwise only
|
|
2734
|
+
// produces 2D / 2D-array textures (isCube was silently dropped), so a samplerCube read it back as a
|
|
2735
|
+
// plain 2D texture and the cube attachment rendered/sampled wrong. Delegate to the cube path so its
|
|
2736
|
+
// per-face layers (layer*6+face) are addressable.
|
|
2737
|
+
if (typeof options === "object" && options.isCube) {
|
|
2738
|
+
const cubeSize = size.width ?? size;
|
|
2739
|
+
return this._createInternalCubeTexture(cubeSize, options, source);
|
|
2740
|
+
}
|
|
1888
2741
|
const texture = new InternalTexture(this, source);
|
|
1889
2742
|
const width = size.width ?? size;
|
|
1890
2743
|
const height = size.height ?? size;
|
|
1891
2744
|
const layers = size.layers || 0;
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
}
|
|
2745
|
+
// Like WebGL, a depth (without layers) requests a volume texture (e.g. a TEXTURE_3D MRT attachment).
|
|
2746
|
+
const depth = layers ? 0 : size.depth || 0;
|
|
1895
2747
|
const nativeTexture = texture._hardwareTexture.underlyingResource;
|
|
1896
2748
|
const nativeTextureFormat = getNativeTextureFormat(format, type);
|
|
1897
|
-
//
|
|
1898
|
-
|
|
1899
|
-
// both mips > 1 and samples > 1 makes the API (D3D11 E_INVALIDARG, Vulkan VUID-02257, ...) reject the
|
|
1900
|
-
// MSAA texture creation. Force hasMips = false here to keep the combo from reaching bgfx. The fix
|
|
1901
|
-
// belongs in bgfx (separate descs per target, like OpenGL/WebGL do with a non-mipped renderbuffer);
|
|
1902
|
-
// this guard should be removed once a fixed bgfx ships in a stable BabylonNative npm release. Tracked
|
|
1903
|
-
// in BabylonNative#1714. Cost: MSAA RTs on Native lose post-resolve auto-mipgen and diverge from
|
|
1904
|
-
// WebGL/WebGPU semantics -- texture.generateMipMaps stays true on the InternalTexture but the
|
|
1905
|
-
// underlying bgfx resource has 1 mip.
|
|
1906
|
-
const hasMips = samples > 1 ? false : generateMipMaps;
|
|
2749
|
+
// createMipMaps allocates mip storage (e.g. FrameGraph textures) without requesting automatic generation.
|
|
2750
|
+
const hasMips = this._getRenderTargetHasMips(generateMipMaps || createMipMaps, samples);
|
|
1907
2751
|
// REVIEW: We are always setting the renderTarget flag as we don't know whether the texture will be used as a render target.
|
|
1908
|
-
|
|
2752
|
+
// A layers > 0 request creates a 2D texture array (e.g. a cascaded-shadow-map render target); the
|
|
2753
|
+
// matching per-layer framebuffers are built by createRenderTargetTexture and bound via bindFramebuffer(layer).
|
|
2754
|
+
this._engine.initializeTexture(nativeTexture, width, height, hasMips, nativeTextureFormat, true, useSRGBBuffer, samples, false, layers || depth, depth > 0);
|
|
1909
2755
|
this._setTextureSampling(nativeTexture, getNativeSamplingMode(samplingMode));
|
|
1910
2756
|
texture._useSRGBBuffer = useSRGBBuffer;
|
|
1911
2757
|
texture.baseWidth = width;
|
|
1912
2758
|
texture.baseHeight = height;
|
|
1913
2759
|
texture.width = width;
|
|
1914
2760
|
texture.height = height;
|
|
1915
|
-
texture.depth = layers;
|
|
2761
|
+
texture.depth = layers || depth;
|
|
2762
|
+
if (layers > 0) {
|
|
2763
|
+
texture.is2DArray = true;
|
|
2764
|
+
texture.baseDepth = layers;
|
|
2765
|
+
}
|
|
2766
|
+
else if (depth > 0) {
|
|
2767
|
+
texture.is3D = true;
|
|
2768
|
+
texture.baseDepth = depth;
|
|
2769
|
+
}
|
|
1916
2770
|
texture.isReady = true;
|
|
1917
2771
|
texture.samples = samples;
|
|
1918
2772
|
texture.generateMipMaps = generateMipMaps;
|
|
2773
|
+
this._setHasMipStorage(texture, generateMipMaps || createMipMaps);
|
|
1919
2774
|
texture.samplingMode = samplingMode;
|
|
1920
2775
|
texture.type = type;
|
|
1921
2776
|
texture.format = format;
|
|
@@ -1923,6 +2778,52 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
1923
2778
|
this._internalTexturesCache.push(texture);
|
|
1924
2779
|
return texture;
|
|
1925
2780
|
}
|
|
2781
|
+
// Creates a standalone, sampleable cube InternalTexture usable as a mixed-type MRT color attachment (a
|
|
2782
|
+
// single face is targeted per attachment via the framebuffer's per-attachment layer). Mirrors
|
|
2783
|
+
// _createInternalTexture's float/half-float linear-filter fallbacks + cache registration, but initializes
|
|
2784
|
+
// the bgfx texture as a cube render target (there is no cube path through _createInternalTexture, which
|
|
2785
|
+
// only produces 2D / 2D-array textures).
|
|
2786
|
+
_createInternalCubeTexture(size, options, source) {
|
|
2787
|
+
let type = options.type ?? 0;
|
|
2788
|
+
let samplingMode = options.samplingMode ?? 3;
|
|
2789
|
+
const format = options.format ?? 5;
|
|
2790
|
+
const generateMipMaps = !!options.generateMipMaps;
|
|
2791
|
+
const samples = options.samples ?? 1;
|
|
2792
|
+
const useSRGBBuffer = this._getUseSRGBBuffer(!!options.useSRGBBuffer, !generateMipMaps);
|
|
2793
|
+
if (type === 1 && !this._caps.textureFloatLinearFiltering) {
|
|
2794
|
+
samplingMode = 1;
|
|
2795
|
+
}
|
|
2796
|
+
else if (type === 2 && !this._caps.textureHalfFloatLinearFiltering) {
|
|
2797
|
+
samplingMode = 1;
|
|
2798
|
+
}
|
|
2799
|
+
if (type === 1 && !this._caps.textureFloat) {
|
|
2800
|
+
type = 0;
|
|
2801
|
+
Logger.Warn("Float textures are not supported. Type forced to TEXTURETYPE_UNSIGNED_BYTE");
|
|
2802
|
+
}
|
|
2803
|
+
const texture = new InternalTexture(this, source);
|
|
2804
|
+
texture.isCube = true;
|
|
2805
|
+
texture.baseWidth = size;
|
|
2806
|
+
texture.baseHeight = size;
|
|
2807
|
+
texture.width = size;
|
|
2808
|
+
texture.height = size;
|
|
2809
|
+
texture.isReady = true;
|
|
2810
|
+
texture.samples = samples;
|
|
2811
|
+
texture.generateMipMaps = generateMipMaps;
|
|
2812
|
+
this._setHasMipStorage(texture, generateMipMaps || !!options.createMipMaps);
|
|
2813
|
+
texture.samplingMode = samplingMode;
|
|
2814
|
+
texture.type = type;
|
|
2815
|
+
texture.format = format;
|
|
2816
|
+
texture.label = options.label;
|
|
2817
|
+
texture._useSRGBBuffer = useSRGBBuffer;
|
|
2818
|
+
const nativeTexture = texture._hardwareTexture.underlyingResource;
|
|
2819
|
+
const nativeTextureFormat = getNativeTextureFormat(format, type);
|
|
2820
|
+
// createMipMaps allocates mip storage (e.g. FrameGraph textures) without requesting automatic generation.
|
|
2821
|
+
const hasMips = this._getRenderTargetHasMips(generateMipMaps || !!options.createMipMaps, samples);
|
|
2822
|
+
this._engine.initializeTexture(nativeTexture, size, size, hasMips, nativeTextureFormat, /*renderTarget*/ true, useSRGBBuffer, samples, /*isCube*/ true);
|
|
2823
|
+
this._setTextureSampling(nativeTexture, getNativeSamplingMode(samplingMode));
|
|
2824
|
+
this._internalTexturesCache.push(texture);
|
|
2825
|
+
return texture;
|
|
2826
|
+
}
|
|
1926
2827
|
createRenderTargetTexture(size, options) {
|
|
1927
2828
|
const rtWrapper = this._createHardwareRenderTargetWrapper(false, false, size);
|
|
1928
2829
|
let generateDepthBuffer = true;
|
|
@@ -1937,9 +2838,27 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
1937
2838
|
colorAttachment = options.colorAttachment;
|
|
1938
2839
|
samples = options.samples ?? 1;
|
|
1939
2840
|
}
|
|
2841
|
+
const width = typeof size === "number" ? size : size.width;
|
|
2842
|
+
const height = typeof size === "number" ? size : size.height;
|
|
2843
|
+
const layers = typeof size === "number" ? 0 : size.layers || 0;
|
|
2844
|
+
const depth = typeof size === "number" ? 0 : size.depth || 0;
|
|
2845
|
+
// 3D render target (IBL voxel grid + its procedural mip chain): create a real volume texture and
|
|
2846
|
+
// render to each Z-slice / mip through its own lazily-built framebuffer (see _get3DLayerFramebuffer).
|
|
2847
|
+
if (depth > 0 && !noColorAttachment && !colorAttachment) {
|
|
2848
|
+
return this._createRenderTargetTexture3D(rtWrapper, options, width, height, depth, generateDepthBuffer, generateStencilBuffer);
|
|
2849
|
+
}
|
|
1940
2850
|
const texture = colorAttachment || (noColorAttachment ? null : this._createInternalTexture(size, options, true, 5 /* InternalTextureSource.RenderTarget */));
|
|
1941
|
-
|
|
1942
|
-
|
|
2851
|
+
if (layers > 0 && texture) {
|
|
2852
|
+
// 2D texture array render target (e.g. cascaded shadow maps): the native engine renders each
|
|
2853
|
+
// array layer through its own framebuffer bound to that layer (mirroring the cube per-face path);
|
|
2854
|
+
// bindFramebuffer(layerIndex) then selects the right one.
|
|
2855
|
+
rtWrapper._framebuffers = this._createLayerFramebuffers(texture._hardwareTexture.underlyingResource, width, height, layers, generateStencilBuffer, generateDepthBuffer, samples, texture.generateMipMaps);
|
|
2856
|
+
rtWrapper._generateDepthBuffer = generateDepthBuffer;
|
|
2857
|
+
rtWrapper._generateStencilBuffer = generateStencilBuffer;
|
|
2858
|
+
rtWrapper._samples = samples;
|
|
2859
|
+
rtWrapper.setTextures(texture);
|
|
2860
|
+
return rtWrapper;
|
|
2861
|
+
}
|
|
1943
2862
|
const framebuffer = this._engine.createFrameBuffer(texture ? texture._hardwareTexture.underlyingResource : null, width, height, generateStencilBuffer, generateDepthBuffer, samples);
|
|
1944
2863
|
rtWrapper._framebuffer = framebuffer;
|
|
1945
2864
|
rtWrapper._generateDepthBuffer = generateDepthBuffer;
|
|
@@ -1948,11 +2867,22 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
1948
2867
|
rtWrapper.setTextures(texture);
|
|
1949
2868
|
return rtWrapper;
|
|
1950
2869
|
}
|
|
2870
|
+
// Builds a 3D (volume) render-target texture. bgfx renders to individual Z-slices/mips through per-slice
|
|
2871
|
+
// framebuffers created on demand in _get3DLayerFramebuffer; the volume is sampled as a sampler3D.
|
|
2872
|
+
_createRenderTargetTexture3D(rtWrapper, options, width, height, depth, generateDepthBuffer, generateStencilBuffer) {
|
|
2873
|
+
const texture = this._createInternalTexture({ width, height, depth }, options, true, 5 /* InternalTextureSource.RenderTarget */);
|
|
2874
|
+
rtWrapper._generateDepthBuffer = generateDepthBuffer;
|
|
2875
|
+
rtWrapper._generateStencilBuffer = generateStencilBuffer;
|
|
2876
|
+
rtWrapper._samples = texture.samples;
|
|
2877
|
+
rtWrapper.setTextures(texture);
|
|
2878
|
+
return rtWrapper;
|
|
2879
|
+
}
|
|
1951
2880
|
createRenderTargetCubeTexture(size, options) {
|
|
1952
2881
|
const rtWrapper = this._createHardwareRenderTargetWrapper(false, true, size);
|
|
1953
2882
|
let generateDepthBuffer = true;
|
|
1954
2883
|
let generateStencilBuffer = false;
|
|
1955
2884
|
let generateMipMaps = false;
|
|
2885
|
+
let createMipMaps;
|
|
1956
2886
|
let type = 0;
|
|
1957
2887
|
let samplingMode = 3;
|
|
1958
2888
|
let format = 5;
|
|
@@ -1962,12 +2892,17 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
1962
2892
|
generateDepthBuffer = options.generateDepthBuffer ?? true;
|
|
1963
2893
|
generateStencilBuffer = !!options.generateStencilBuffer;
|
|
1964
2894
|
generateMipMaps = !!options.generateMipMaps;
|
|
2895
|
+
createMipMaps = options.createMipMaps;
|
|
1965
2896
|
type = options.type ?? 0;
|
|
1966
2897
|
samplingMode = options.samplingMode ?? 3;
|
|
1967
2898
|
format = options.format ?? 5;
|
|
1968
2899
|
samples = options.samples ?? 1;
|
|
1969
2900
|
label = options.label;
|
|
1970
2901
|
}
|
|
2902
|
+
// Storage for a full mip chain is requested via createMipMaps (falling back to generateMipMaps when
|
|
2903
|
+
// unspecified). HDR prefiltering passes createMipMaps:true + generateMipMaps:false because it renders
|
|
2904
|
+
// each roughness mip explicitly and must NOT have them auto-regenerated on unbind.
|
|
2905
|
+
const allocateMips = createMipMaps ?? generateMipMaps;
|
|
1971
2906
|
// Match _createInternalTexture: float/half-float RTTs that the platform can't linearly filter fall
|
|
1972
2907
|
// back to NEAREST so the cube RTT never carries an unsupported sampling mode.
|
|
1973
2908
|
if (type === 1 && !this._caps.textureFloatLinearFiltering) {
|
|
@@ -1989,6 +2924,7 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
1989
2924
|
texture.isReady = true;
|
|
1990
2925
|
texture.samples = samples;
|
|
1991
2926
|
texture.generateMipMaps = generateMipMaps;
|
|
2927
|
+
this._setHasMipStorage(texture, allocateMips);
|
|
1992
2928
|
texture.samplingMode = samplingMode;
|
|
1993
2929
|
texture.type = type;
|
|
1994
2930
|
texture.format = format;
|
|
@@ -1996,15 +2932,19 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
1996
2932
|
const nativeTexture = texture._hardwareTexture.underlyingResource;
|
|
1997
2933
|
const nativeTextureFormat = getNativeTextureFormat(format, type);
|
|
1998
2934
|
// See the createRenderTargetTexture MSAA/mips note: avoid the mips + samples combo on bgfx.
|
|
1999
|
-
const hasMips = samples
|
|
2935
|
+
const hasMips = this._getRenderTargetHasMips(allocateMips, samples);
|
|
2000
2936
|
this._engine.initializeTexture(nativeTexture, size, size, hasMips, nativeTextureFormat, /*renderTarget*/ true, /*srgb*/ false, samples, /*isCube*/ true);
|
|
2001
2937
|
this._setTextureSampling(nativeTexture, getNativeSamplingMode(samplingMode));
|
|
2002
2938
|
// The native engine cannot render to all six faces through one framebuffer, so create one
|
|
2003
2939
|
// framebuffer per face (the C++ side binds the matching cube layer); bindFramebuffer(faceIndex)
|
|
2004
2940
|
// then selects the right one.
|
|
2941
|
+
// generateMipMaps is forwarded as autoGenerateMips: a cube RTT that authors its own mip levels
|
|
2942
|
+
// (HDR radiance prefiltering passes createMipMaps:true + generateMipMaps:false and renders one
|
|
2943
|
+
// convolution per face+mip) must not have the chain regenerated from mip 0 when a face resolves,
|
|
2944
|
+
// which would wipe every explicitly rendered roughness level.
|
|
2005
2945
|
const framebuffers = [];
|
|
2006
2946
|
for (let face = 0; face < 6; face++) {
|
|
2007
|
-
framebuffers.push(this._engine.createFrameBuffer(nativeTexture, size, size, generateStencilBuffer, generateDepthBuffer, samples, face));
|
|
2947
|
+
framebuffers.push(this._engine.createFrameBuffer(nativeTexture, size, size, generateStencilBuffer, generateDepthBuffer, samples, face, 0, generateMipMaps));
|
|
2008
2948
|
}
|
|
2009
2949
|
rtWrapper._framebuffers = framebuffers;
|
|
2010
2950
|
rtWrapper._generateDepthBuffer = generateDepthBuffer;
|
|
@@ -2016,91 +2956,130 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
2016
2956
|
this._internalTexturesCache.push(texture);
|
|
2017
2957
|
return rtWrapper;
|
|
2018
2958
|
}
|
|
2959
|
+
// The Native engine renders a multi render target through a single bgfx framebuffer with several color
|
|
2960
|
+
// attachments (see NativeEngine.cpp CreateMultiFrameBuffer / CreateFrameBufferImpl). Plain 2D color
|
|
2961
|
+
// attachments (the WebGL prepass / geometry-buffer path) build their framebuffer eagerly here; mixed-type
|
|
2962
|
+
// attachments (specific cube faces / 2D-array layers) and 3D voxelization MRTs build a layered
|
|
2963
|
+
// multi-attachment framebuffer lazily on first bind. Sampleable depth textures (generateDepthTexture)
|
|
2964
|
+
// are not supported. Attachments swapped after creation (e.g. the OIT depth-peeling renderer) rebuild the
|
|
2965
|
+
// framebuffer via _createMultiRenderTargetFramebuffer (called from NativeRenderTargetWrapper.setTexture).
|
|
2019
2966
|
createMultipleRenderTarget(size, options, _initializeBuffers = true) {
|
|
2020
|
-
const rtWrapper = this._createHardwareRenderTargetWrapper(true, false, size);
|
|
2021
2967
|
let generateMipMaps = false;
|
|
2968
|
+
let createMipMaps = false;
|
|
2022
2969
|
let generateDepthBuffer = true;
|
|
2023
2970
|
let generateStencilBuffer = false;
|
|
2024
2971
|
let generateDepthTexture = false;
|
|
2025
2972
|
let textureCount = 1;
|
|
2026
2973
|
let samples = 1;
|
|
2974
|
+
const defaultType = 0;
|
|
2975
|
+
const defaultSamplingMode = 3;
|
|
2976
|
+
const defaultFormat = 5;
|
|
2027
2977
|
let types = [];
|
|
2028
2978
|
let samplingModes = [];
|
|
2979
|
+
let useSRGBBuffers = [];
|
|
2029
2980
|
let formats = [];
|
|
2030
2981
|
let targets = [];
|
|
2031
|
-
let faceIndex = [];
|
|
2032
|
-
let layerIndex = [];
|
|
2033
2982
|
let labels = [];
|
|
2034
2983
|
let dontCreateTextures = false;
|
|
2984
|
+
const rtWrapper = this._createHardwareRenderTargetWrapper(true, false, size);
|
|
2035
2985
|
if (options !== undefined) {
|
|
2036
2986
|
generateMipMaps = options.generateMipMaps ?? false;
|
|
2987
|
+
createMipMaps = options.createMipMaps ?? generateMipMaps;
|
|
2037
2988
|
generateDepthBuffer = options.generateDepthBuffer ?? true;
|
|
2038
2989
|
generateStencilBuffer = options.generateStencilBuffer ?? false;
|
|
2039
2990
|
generateDepthTexture = options.generateDepthTexture ?? false;
|
|
2040
2991
|
textureCount = options.textureCount ?? 1;
|
|
2041
|
-
samples = options.samples ??
|
|
2992
|
+
samples = options.samples ?? samples;
|
|
2042
2993
|
types = options.types || types;
|
|
2043
2994
|
samplingModes = options.samplingModes || samplingModes;
|
|
2995
|
+
useSRGBBuffers = options.useSRGBBuffers || useSRGBBuffers;
|
|
2044
2996
|
formats = options.formats || formats;
|
|
2045
2997
|
targets = options.targetTypes || targets;
|
|
2046
|
-
faceIndex = options.faceIndex || faceIndex;
|
|
2047
|
-
layerIndex = options.layerIndex || layerIndex;
|
|
2048
2998
|
labels = options.labels || labels;
|
|
2049
2999
|
dontCreateTextures = options.dontCreateTextures ?? false;
|
|
2050
3000
|
}
|
|
2051
|
-
rtWrapper.label = options?.label ?? "MultiRenderTargetWrapper";
|
|
2052
3001
|
const width = size.width ?? size;
|
|
2053
3002
|
const height = size.height ?? size;
|
|
3003
|
+
// MRT whose color attachments are distinct layers of one shared 3D texture (IBL voxelization: N draw
|
|
3004
|
+
// buffers → N Z-slices of the voxel grid). The shared texture is assigned later via setInternalTexture,
|
|
3005
|
+
// so the layered multi-attachment framebuffer is (re)built lazily on first bind (_bindLayeredMultiFramebuffer).
|
|
3006
|
+
const layerIndex = options?.layerIndex;
|
|
3007
|
+
const faceIndex = options?.faceIndex;
|
|
3008
|
+
const layerCounts = options?.layerCounts;
|
|
3009
|
+
const is3DLayeredMRT = targets.some((t) => t === 32879);
|
|
3010
|
+
// A mixed-type MRT renders each color attachment into a specific layer of a 2D-array texture or a
|
|
3011
|
+
// specific face of a cube texture (alongside plain 2D targets). Detect it so each color texture is
|
|
3012
|
+
// created with the correct dimensionality and the multi-attachment framebuffer is built lazily with
|
|
3013
|
+
// per-attachment layer/face (setInternalTexture may swap a shared texture in after creation, e.g. the
|
|
3014
|
+
// MRT that renders two different layers of one 2D-array via a -1 target + setInternalTexture).
|
|
3015
|
+
const isLayeredMRT = is3DLayeredMRT || targets.some((t) => t === 35866 || t === 34067);
|
|
2054
3016
|
const textures = [];
|
|
2055
3017
|
const attachments = [];
|
|
3018
|
+
rtWrapper.label = options?.label ?? "MultiRenderTargetWrapper";
|
|
3019
|
+
// Without a sampleable depth attachment on Native, a generateDepthTexture request still needs depth testing.
|
|
3020
|
+
rtWrapper._generateDepthBuffer = generateDepthBuffer || generateDepthTexture;
|
|
3021
|
+
rtWrapper._generateStencilBuffer = generateStencilBuffer;
|
|
3022
|
+
rtWrapper._attachments = attachments;
|
|
2056
3023
|
for (let i = 0; i < textureCount; i++) {
|
|
2057
|
-
const samplingMode = samplingModes[i] ||
|
|
2058
|
-
|
|
2059
|
-
const format = formats[i] ||
|
|
2060
|
-
const
|
|
2061
|
-
|
|
2062
|
-
//
|
|
3024
|
+
const samplingMode = samplingModes[i] || defaultSamplingMode;
|
|
3025
|
+
const type = types[i] || defaultType;
|
|
3026
|
+
const format = formats[i] || defaultFormat;
|
|
3027
|
+
const useSRGBBuffer = (useSRGBBuffers[i] || false) && this._caps.supportSRGBBuffers;
|
|
3028
|
+
const target = targets[i];
|
|
3029
|
+
// Attachment index i+1 mirrors the WebGL COLOR_ATTACHMENTi convention consumers rely on.
|
|
3030
|
+
attachments.push(i + 1);
|
|
2063
3031
|
if (target === -1 || dontCreateTextures) {
|
|
2064
3032
|
continue;
|
|
2065
3033
|
}
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
3034
|
+
// _createInternalTexture initializes the bgfx texture as a sampleable render target and applies
|
|
3035
|
+
// the float/half-float linear-filter fallbacks + cache registration, matching createRenderTargetTexture.
|
|
3036
|
+
// The color attachments must carry the same MSAA sample count as the framebuffer's depth attachment
|
|
3037
|
+
// (created with `samples` below): bgfx rejects a framebuffer that mixes single-sample color targets
|
|
3038
|
+
// with a multisample depth target, which surfaced as "Failed to create frame buffer" for MSAA MRTs
|
|
3039
|
+
// (e.g. the SSAO prepass). _createInternalTexture already drops mips when samples > 1.
|
|
3040
|
+
// A mixed-type MRT creates the attachment with the dimensionality requested by targetTypes: a cube
|
|
3041
|
+
// texture (one face targeted per attachment) or a 2D-array texture with layerCounts layers (one
|
|
3042
|
+
// layer targeted per attachment). The framebuffer selects the specific face/layer per attachment.
|
|
3043
|
+
const textureLabel = labels[i] ?? rtWrapper.label + "-Texture" + i;
|
|
3044
|
+
const textureOptions = { generateMipMaps, createMipMaps, type, format, samplingMode, useSRGBBuffer, samples, label: textureLabel };
|
|
3045
|
+
let texture;
|
|
3046
|
+
if (target === 34067) {
|
|
3047
|
+
texture = this._createInternalCubeTexture(width, textureOptions, 6 /* InternalTextureSource.MultiRenderTarget */);
|
|
2069
3048
|
}
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
// Native multi render targets currently only attach 2D color textures; cube / 2D-array
|
|
2074
|
-
// attachments are created as 2D so the attachment still exists and mrt.textures[i] is populated.
|
|
2075
|
-
Logger.Warn("Multi render target attachment target " + target + " is not supported on Native; using a 2D texture.");
|
|
3049
|
+
else if (target === 35866) {
|
|
3050
|
+
const layerCount = Math.max(1, layerCounts?.[i] ?? 1);
|
|
3051
|
+
texture = this._createInternalTexture({ width, height, layers: layerCount }, textureOptions, true, 6 /* InternalTextureSource.MultiRenderTarget */);
|
|
2076
3052
|
}
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
texture.
|
|
2085
|
-
texture.
|
|
2086
|
-
texture.samples = samples;
|
|
2087
|
-
texture.generateMipMaps = generateMipMaps;
|
|
2088
|
-
texture.samplingMode = samplingMode;
|
|
2089
|
-
texture.type = type;
|
|
2090
|
-
texture.format = format;
|
|
2091
|
-
texture.label = labels[i] ?? rtWrapper.label + "-Texture" + i;
|
|
3053
|
+
else if (target === 32879) {
|
|
3054
|
+
const depth = Math.max(1, layerCounts?.[i] || size.depth || 1);
|
|
3055
|
+
texture = this._createInternalTexture({ width, height, depth }, textureOptions, true, 6 /* InternalTextureSource.MultiRenderTarget */);
|
|
3056
|
+
}
|
|
3057
|
+
else {
|
|
3058
|
+
texture = this._createInternalTexture({ width, height }, textureOptions, true, 6 /* InternalTextureSource.MultiRenderTarget */);
|
|
3059
|
+
}
|
|
3060
|
+
texture._cachedWrapU = 0;
|
|
3061
|
+
texture._cachedWrapV = 0;
|
|
2092
3062
|
textures[i] = texture;
|
|
2093
|
-
this._internalTexturesCache.push(texture);
|
|
2094
3063
|
}
|
|
2095
|
-
|
|
2096
|
-
|
|
3064
|
+
if (generateDepthTexture && !dontCreateTextures) {
|
|
3065
|
+
// The multi-framebuffer path allocates its own (non-sampleable) depth/stencil buffer; a separate
|
|
3066
|
+
// sampleable depth texture attachment is not wired up on Native.
|
|
3067
|
+
Logger.Warn("NativeEngine.createMultipleRenderTarget: generateDepthTexture is not supported; using a non-sampleable depth buffer.");
|
|
3068
|
+
}
|
|
3069
|
+
if (isLayeredMRT || layerIndex) {
|
|
3070
|
+
rtWrapper.setLayerAndFaceIndices(layerIndex ?? [], faceIndex ?? []);
|
|
3071
|
+
}
|
|
3072
|
+
// Layered MRTs (3D / 2D-array / cube attachments, possibly mixed with 2D) build their multi-attachment
|
|
3073
|
+
// framebuffer lazily on first bind. The flag selects that path in bindFramebuffer so per-attachment
|
|
3074
|
+
// layer/face and post-creation setInternalTexture are honored, even when the size carries no depth.
|
|
3075
|
+
if (isLayeredMRT) {
|
|
3076
|
+
rtWrapper._isMixedTypeMRT = true;
|
|
3077
|
+
}
|
|
2097
3078
|
rtWrapper._samples = samples;
|
|
2098
|
-
rtWrapper._attachments = attachments;
|
|
2099
3079
|
rtWrapper.setTextures(textures);
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
this._createMultiRenderTargetFramebuffer(rtWrapper);
|
|
3080
|
+
if (!dontCreateTextures && !isLayeredMRT) {
|
|
3081
|
+
this._createMultiRenderTargetFramebuffer(rtWrapper);
|
|
3082
|
+
}
|
|
2104
3083
|
return rtWrapper;
|
|
2105
3084
|
}
|
|
2106
3085
|
/**
|
|
@@ -2135,16 +3114,34 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
2135
3114
|
}
|
|
2136
3115
|
const width = rtWrapper.width;
|
|
2137
3116
|
const height = rtWrapper.height;
|
|
2138
|
-
|
|
2139
|
-
|
|
3117
|
+
// Prefer an explicit shared depth texture when present (OIT depth peeling shareDepth, FG depth
|
|
3118
|
+
// attached after dontCreateTextures). Otherwise fall back to auto depth from _generateDepthBuffer.
|
|
3119
|
+
const explicitDepth = rtWrapper._depthStencilTexture?._hardwareTexture?.underlyingResource;
|
|
3120
|
+
const generateDepthBuffer = !!explicitDepth || rtWrapper._generateDepthBuffer;
|
|
3121
|
+
rtWrapper._framebuffer = this._createNativeMultiFrameBuffer(colorHandles, width, height, this._getDepthAttachmentStencil(rtWrapper), generateDepthBuffer, rtWrapper._samples, undefined, explicitDepth);
|
|
3122
|
+
this._applyDepthTextureSampling(rtWrapper);
|
|
3123
|
+
}
|
|
3124
|
+
_applyDepthTextureSampling(rtWrapper) {
|
|
3125
|
+
const depthTexture = rtWrapper._depthStencilTexture;
|
|
3126
|
+
const nativeDepth = depthTexture?._hardwareTexture?.underlyingResource;
|
|
3127
|
+
if (!depthTexture || !nativeDepth) {
|
|
3128
|
+
return;
|
|
2140
3129
|
}
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
3130
|
+
this._setTextureSampling(nativeDepth, getNativeSamplingMode(depthTexture.samplingMode));
|
|
3131
|
+
this.updateTextureComparisonFunction(depthTexture, depthTexture._comparisonFunction);
|
|
3132
|
+
}
|
|
3133
|
+
/**
|
|
3134
|
+
* Creates a multi-attachment framebuffer, falling back to a single-attachment framebuffer bound to the first
|
|
3135
|
+
* color target (and its first requested layer) on older Babylon Native runtimes without createMultiFrameBuffer.
|
|
3136
|
+
* @internal
|
|
3137
|
+
*/
|
|
3138
|
+
_createNativeMultiFrameBuffer(colorTextures, width, height, generateStencilBuffer, generateDepthBuffer, samples, layers, explicitDepthTexture) {
|
|
3139
|
+
if (this._engine.createMultiFrameBuffer) {
|
|
3140
|
+
return this._engine.createMultiFrameBuffer(colorTextures, width, height, generateStencilBuffer, generateDepthBuffer, samples, layers, explicitDepthTexture);
|
|
2147
3141
|
}
|
|
3142
|
+
// Warn once (limit 1): the framebuffer can be rebuilt many times during attachment setup/swaps.
|
|
3143
|
+
Logger.Warn("createMultiFrameBuffer is not supported by this version of Babylon Native; multi render targets are unavailable. Falling back to a single-attachment framebuffer bound to the first color target.", 1);
|
|
3144
|
+
return this._engine.createFrameBuffer(colorTextures[0] ?? null, width, height, generateStencilBuffer, generateDepthBuffer, samples, layers?.[0]);
|
|
2148
3145
|
}
|
|
2149
3146
|
generateMipMapsForCubemap(_texture, _unbind = true) {
|
|
2150
3147
|
// The WebGL path rebinds gl.TEXTURE_CUBE_MAP and calls gl.generateMipmap; both deref _gl, which is
|
|
@@ -2152,13 +3149,31 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
2152
3149
|
// resolved (the same way 2D RTTs get their mips here -- unBindFramebuffer issues no explicit mipgen),
|
|
2153
3150
|
// so this is a no-op on Native.
|
|
2154
3151
|
}
|
|
2155
|
-
bindAttachments(
|
|
2156
|
-
//
|
|
2157
|
-
//
|
|
3152
|
+
bindAttachments(attachments) {
|
|
3153
|
+
// bgfx has no gl.drawBuffers equivalent, so draw calls always write to every color attachment of
|
|
3154
|
+
// the bound framebuffer. Clears, however, can be masked per attachment (bgfx clear color palette),
|
|
3155
|
+
// and code such as PrePassRenderer._clear() / ThinDepthPeelingRenderer relies on that.
|
|
3156
|
+
//
|
|
3157
|
+
// attachments[i] is the attachment index to enable, or -1 to skip (see buildTextureLayout).
|
|
3158
|
+
// Do NOT promote "every entry in this array is enabled" to 0xff: OIT passes layout [0] (only
|
|
3159
|
+
// the depth attachment) as a length-1 array, and treating that as "all attachments" would
|
|
3160
|
+
// clear the shared front/back color MRTs with the depth clear value (-99999).
|
|
3161
|
+
let mask = 0;
|
|
3162
|
+
for (let i = 0; i < attachments.length; i++) {
|
|
3163
|
+
const attachmentIndex = attachments[i];
|
|
3164
|
+
if (attachmentIndex >= 0) {
|
|
3165
|
+
mask |= 1 << attachmentIndex;
|
|
3166
|
+
}
|
|
3167
|
+
}
|
|
3168
|
+
// An empty layout disables color clears; it must not clear every attachment instead.
|
|
3169
|
+
this._clearAttachmentMask = mask;
|
|
3170
|
+
}
|
|
3171
|
+
clearAttachments(color, attachments, clearColor, clearDepth, clearStencil = false, stencilClearValue = 0) {
|
|
3172
|
+
this.bindAttachments(attachments);
|
|
3173
|
+
this.clear(color, clearColor, clearDepth, clearStencil, stencilClearValue);
|
|
2158
3174
|
}
|
|
2159
3175
|
buildTextureLayout(textureStatus, _backBufferLayout = false) {
|
|
2160
|
-
// Native
|
|
2161
|
-
// length/order, and bindAttachments is a no-op).
|
|
3176
|
+
// Native layouts use attachment indices instead of WebGL draw-buffer enums.
|
|
2162
3177
|
const result = [];
|
|
2163
3178
|
for (let i = 0; i < textureStatus.length; i++) {
|
|
2164
3179
|
result.push(textureStatus[i] ? i : -1);
|
|
@@ -2166,10 +3181,12 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
2166
3181
|
return result;
|
|
2167
3182
|
}
|
|
2168
3183
|
restoreSingleAttachment() {
|
|
2169
|
-
//
|
|
3184
|
+
// Back to the single-attachment back buffer: no masking (see bindAttachments).
|
|
3185
|
+
this._clearAttachmentMask = _AllAttachmentsMask;
|
|
2170
3186
|
}
|
|
2171
3187
|
restoreSingleAttachmentForRenderTarget() {
|
|
2172
|
-
//
|
|
3188
|
+
// Back to a single-attachment render target: no masking (see bindAttachments).
|
|
3189
|
+
this._clearAttachmentMask = _AllAttachmentsMask;
|
|
2173
3190
|
}
|
|
2174
3191
|
generateMipMapsMultiFramebuffer(_texture) {
|
|
2175
3192
|
// No-op on Native: bgfx auto-generates mips on render-target resolve (as for 2D/cube RTTs).
|
|
@@ -2193,26 +3210,42 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
2193
3210
|
return rtWrapper.samples;
|
|
2194
3211
|
}
|
|
2195
3212
|
const nativeRTWrapper = rtWrapper;
|
|
3213
|
+
const depthTexture = nativeRTWrapper._depthStencilTexture;
|
|
3214
|
+
if (depthTexture?._hardwareTexture && depthTexture.samples !== samples && depthTexture._references > 1) {
|
|
3215
|
+
throw new Error("updateMultipleRenderTargetTextureSampleCount: cannot change samples while using a shared depth texture.");
|
|
3216
|
+
}
|
|
2196
3217
|
// bgfx couples MSAA to the texture creation flags (see updateRenderTargetTextureSampleCount), so
|
|
2197
3218
|
// changing the sample count after the fact requires reissuing every color attachment's underlying
|
|
2198
3219
|
// bgfx handle with the new MSAA flag. initializeTexture disposes the old handle and allocates a fresh
|
|
2199
3220
|
// one while preserving the InternalTexture / Graphics::Texture identity; only the internal bgfx handle
|
|
2200
3221
|
// rotates. Afterwards the framebuffer is recreated so its attachment list refers to the new handles.
|
|
3222
|
+
const reinitialized = new Set();
|
|
2201
3223
|
for (const texture of textures) {
|
|
2202
3224
|
// Wrapped (External-source) textures own an opaque external handle (format=-1); reinitializing
|
|
2203
3225
|
// would destroy it and getNativeTextureFormat would throw, so leave those attachments untouched.
|
|
2204
|
-
|
|
3226
|
+
// A texture shared by several attachments (different layers/faces) is reinitialized only once.
|
|
3227
|
+
if (!texture?._hardwareTexture || texture.source === 15 /* InternalTextureSource.External */ || reinitialized.has(texture)) {
|
|
2205
3228
|
continue;
|
|
2206
3229
|
}
|
|
3230
|
+
reinitialized.add(texture);
|
|
3231
|
+
// Keep the full descriptor so cube / 2D-array / 3D attachments keep their dimensionality.
|
|
2207
3232
|
const nativeTexture = texture._hardwareTexture.underlyingResource;
|
|
2208
|
-
|
|
2209
|
-
const hasMips = samples > 1 ? false : texture.generateMipMaps;
|
|
3233
|
+
const hasMips = this._getRenderTargetHasMips(this._hasMipStorage(texture), samples);
|
|
2210
3234
|
this._engine.initializeTexture(nativeTexture, texture.baseWidth, texture.baseHeight, hasMips, getNativeTextureFormat(texture.format, texture.type),
|
|
2211
|
-
/*renderTarget*/ true, texture._useSRGBBuffer, samples);
|
|
3235
|
+
/*renderTarget*/ true, texture._useSRGBBuffer, samples, texture.isCube, texture.is2DArray || texture.is3D ? texture.depth : 0, texture.is3D);
|
|
2212
3236
|
texture.samples = samples;
|
|
2213
3237
|
}
|
|
2214
3238
|
nativeRTWrapper._samples = samples;
|
|
2215
|
-
|
|
3239
|
+
if (depthTexture?._hardwareTexture && depthTexture.samples !== samples) {
|
|
3240
|
+
this._recreateDepthStencilTexture(nativeRTWrapper, samples);
|
|
3241
|
+
}
|
|
3242
|
+
if (nativeRTWrapper._usesLayeredFramebuffer) {
|
|
3243
|
+
// Rebuilt on the next bind with the per-attachment layers/faces (the layout key includes samples).
|
|
3244
|
+
nativeRTWrapper._invalidateLayeredFramebuffer();
|
|
3245
|
+
}
|
|
3246
|
+
else {
|
|
3247
|
+
this._createMultiRenderTargetFramebuffer(nativeRTWrapper);
|
|
3248
|
+
}
|
|
2216
3249
|
return samples;
|
|
2217
3250
|
}
|
|
2218
3251
|
updateRenderTargetTextureSampleCount(rtWrapper, samples) {
|
|
@@ -2231,6 +3264,10 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
2231
3264
|
throw new Error("updateRenderTargetTextureSampleCount: changing MSAA samples is not supported on wrapped (External-source) textures. Dispose and re-wrap with the desired samples.");
|
|
2232
3265
|
}
|
|
2233
3266
|
const nativeRTWrapper = rtWrapper;
|
|
3267
|
+
const depthTexture = nativeRTWrapper._depthStencilTexture;
|
|
3268
|
+
if (depthTexture?._hardwareTexture && depthTexture.samples !== samples && depthTexture._references > 1) {
|
|
3269
|
+
throw new Error("updateRenderTargetTextureSampleCount: cannot change samples while using a shared depth texture.");
|
|
3270
|
+
}
|
|
2234
3271
|
const nativeTexture = texture._hardwareTexture.underlyingResource;
|
|
2235
3272
|
// bgfx couples MSAA to the texture creation flags, so changing samples after the fact requires
|
|
2236
3273
|
// recreating the underlying bgfx texture handle with the new MSAA flag. initializeTexture on the
|
|
@@ -2239,41 +3276,40 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
2239
3276
|
// only the internal bgfx handle rotates. After the texture is reissued we also recreate the
|
|
2240
3277
|
// framebuffer so its attachment list refers to the new handle.
|
|
2241
3278
|
//
|
|
2242
|
-
|
|
2243
|
-
// multisampled textures (E_INVALIDARG on CreateTexture2D); D3D12/Vulkan have equivalent rules. bgfx's
|
|
2244
|
-
// D3D11 backend uses one D3D11_TEXTURE2D_DESC for both the MSAA render texture (m_rt2d) and the
|
|
2245
|
-
// non-MSAA sample target (m_texture2d) and doesn't reset desc.MipLevels between them -- so requesting
|
|
2246
|
-
// samples > 1 with hasMips = true crashes at m_rt2d creation. The trigger in practice is the glTF
|
|
2247
|
-
// transmission helper, which creates an `opaqueSceneTexture` RTT with generateMipmaps: true and
|
|
2248
|
-
// immediately sets samples = 4. WebGL2 sidesteps this with a separate non-mipped multisample
|
|
2249
|
-
// renderbuffer; bgfx D3D11 conflates the two-stage pattern. The proper fix lives in bgfx (per-backend
|
|
2250
|
-
// patches reset MipLevels=1 for the MSAA target). Tracked in BabylonNative#1714. Until that ships
|
|
2251
|
-
// through bgfx -> bgfx.cmake -> BabylonNative -> stable npm, force hasMips = false here so the bad
|
|
2252
|
-
// combo never reaches bgfx. Cost: MSAA RTs on Native lose post-resolve auto-mipgen and diverge from
|
|
2253
|
-
// WebGL/WebGPU semantics -- texture.generateMipMaps still reads true on the JS side, but the
|
|
2254
|
-
// underlying bgfx resource has 1 mip level. Remove this guard once a fixed bgfx is in stable BN npm.
|
|
2255
|
-
const hasMips = samples > 1 ? false : texture.generateMipMaps;
|
|
3279
|
+
const hasMips = this._getRenderTargetHasMips(this._hasMipStorage(texture), samples);
|
|
2256
3280
|
const nativeTextureFormat = getNativeTextureFormat(texture.format, texture.type);
|
|
2257
3281
|
const isCube = texture.isCube;
|
|
3282
|
+
const is3D = texture.is3D;
|
|
3283
|
+
const layers = texture.is2DArray || is3D ? texture.depth : 0;
|
|
3284
|
+
// Lazily-built per-(mip, layer/face) framebuffers reference the texture about to be recreated.
|
|
3285
|
+
nativeRTWrapper._releaseLayerFramebuffers();
|
|
2258
3286
|
this._engine.initializeTexture(nativeTexture, texture.baseWidth, texture.baseHeight, hasMips, nativeTextureFormat,
|
|
2259
|
-
/*renderTarget*/ true, texture._useSRGBBuffer, samples, isCube);
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
3287
|
+
/*renderTarget*/ true, texture._useSRGBBuffer, samples, isCube, layers, is3D);
|
|
3288
|
+
rtWrapper._samples = samples;
|
|
3289
|
+
texture.samples = samples;
|
|
3290
|
+
const hasDepthStencilTexture = !!rtWrapper._depthStencilTexture?._hardwareTexture;
|
|
3291
|
+
if (is3D) {
|
|
3292
|
+
// 3D render targets render through the per-(mip, layer) framebuffers released above.
|
|
3293
|
+
if (hasDepthStencilTexture) {
|
|
3294
|
+
this._recreateDepthStencilTexture(nativeRTWrapper, samples);
|
|
2267
3295
|
}
|
|
2268
|
-
|
|
3296
|
+
return samples;
|
|
3297
|
+
}
|
|
3298
|
+
if (layers > 0 || isCube) {
|
|
3299
|
+
// 2D-array RTTs render through one framebuffer per layer and cube RTTs through one per face (see
|
|
3300
|
+
// createRenderTargetTexture / createRenderTargetCubeTexture). The _framebuffers setter releases the stale
|
|
3301
|
+
// handles and keeps _framebuffer aliased to the first one for single-target paths.
|
|
3302
|
+
nativeRTWrapper._framebuffers = this._createLayerFramebuffers(nativeTexture, texture.baseWidth, texture.baseHeight, isCube ? 6 : layers, rtWrapper._generateStencilBuffer, rtWrapper._generateDepthBuffer && !hasDepthStencilTexture, samples, texture.generateMipMaps);
|
|
2269
3303
|
}
|
|
2270
3304
|
else {
|
|
2271
3305
|
// NativeRenderTargetWrapper._framebuffer setter releases the old framebuffer before assigning,
|
|
2272
3306
|
// so no manual _releaseFramebufferObjects call is needed (and would double-delete the handle).
|
|
2273
3307
|
nativeRTWrapper._framebuffer = this._engine.createFrameBuffer(nativeTexture, texture.baseWidth, texture.baseHeight, rtWrapper._generateStencilBuffer, rtWrapper._generateDepthBuffer, samples);
|
|
2274
3308
|
}
|
|
2275
|
-
|
|
2276
|
-
|
|
3309
|
+
// A sampleable depth texture must match the new sample count and stay attached to every framebuffer.
|
|
3310
|
+
if (hasDepthStencilTexture) {
|
|
3311
|
+
this._recreateDepthStencilTexture(nativeRTWrapper, samples);
|
|
3312
|
+
}
|
|
2277
3313
|
return samples;
|
|
2278
3314
|
}
|
|
2279
3315
|
updateTextureSamplingMode(samplingMode, texture) {
|
|
@@ -2283,18 +3319,75 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
2283
3319
|
}
|
|
2284
3320
|
texture.samplingMode = samplingMode;
|
|
2285
3321
|
}
|
|
2286
|
-
|
|
3322
|
+
updateTextureWrappingMode(texture, wrapU, wrapV = null, wrapR = null) {
|
|
3323
|
+
if (wrapU !== null) {
|
|
3324
|
+
texture._cachedWrapU = wrapU;
|
|
3325
|
+
}
|
|
3326
|
+
if (wrapV !== null) {
|
|
3327
|
+
texture._cachedWrapV = wrapV;
|
|
3328
|
+
}
|
|
3329
|
+
if ((texture.is2DArray || texture.is3D) && wrapR !== null) {
|
|
3330
|
+
texture._cachedWrapR = wrapR;
|
|
3331
|
+
}
|
|
3332
|
+
// Apply to the native texture too; axes that were not specified keep their cached (or default) mode.
|
|
3333
|
+
const nativeTexture = texture._hardwareTexture?.underlyingResource;
|
|
3334
|
+
if (nativeTexture) {
|
|
3335
|
+
this._setTextureWrapMode(nativeTexture, getNativeAddressMode(texture._cachedWrapU ?? 1), getNativeAddressMode(texture._cachedWrapV ?? 1), getNativeAddressMode(texture._cachedWrapR ?? 1));
|
|
3336
|
+
}
|
|
3337
|
+
}
|
|
3338
|
+
bindFramebuffer(texture, faceIndex, requiredWidth, requiredHeight, forceFullscreenViewport, lodLevel, layer) {
|
|
2287
3339
|
const nativeRTWrapper = texture;
|
|
2288
3340
|
if (this._currentRenderTarget) {
|
|
2289
3341
|
this.unBindFramebuffer(this._currentRenderTarget);
|
|
2290
3342
|
}
|
|
2291
3343
|
this._currentRenderTarget = texture;
|
|
3344
|
+
// Multi render target whose color attachments each target a specific layer/face of a texture: the IBL
|
|
3345
|
+
// voxelization MRTs (several Z-slices of one shared 3D texture, routed via is3D) and mixed-type MRTs
|
|
3346
|
+
// (2D-array layer / cube face / 2D attachments, routed via _isMixedTypeMRT). The color textures may be
|
|
3347
|
+
// swapped in via setInternalTexture after creation, so (re)build the layered multi-attachment
|
|
3348
|
+
// framebuffer here from the current textures + their per-attachment layer/face indices.
|
|
3349
|
+
if (nativeRTWrapper.isMulti && (nativeRTWrapper.is3D || nativeRTWrapper._isMixedTypeMRT || this._isLayeredFrameGraphMRT(nativeRTWrapper))) {
|
|
3350
|
+
this._bindLayeredMultiFramebuffer(nativeRTWrapper);
|
|
3351
|
+
this._applyBoundViewport(forceFullscreenViewport);
|
|
3352
|
+
return;
|
|
3353
|
+
}
|
|
3354
|
+
// Single 3D render target (IBL voxel grid + its procedural mip chain): render to the requested
|
|
3355
|
+
// (mip, layer) through a lazily-built, cached per-slice framebuffer. requiredWidth/Height carry the
|
|
3356
|
+
// mip dimensions for the voxel mip-copy pass (forceFullscreenViewport is always set by that caller).
|
|
3357
|
+
if (nativeRTWrapper.is3D) {
|
|
3358
|
+
this._bindUnboundFramebuffer(this._get3DLayerFramebuffer(nativeRTWrapper, lodLevel ?? 0, layer ?? 0, requiredWidth, requiredHeight));
|
|
3359
|
+
this._applyBoundViewport(forceFullscreenViewport);
|
|
3360
|
+
return;
|
|
3361
|
+
}
|
|
2292
3362
|
if (requiredWidth || requiredHeight) {
|
|
2293
3363
|
throw new Error("Required width/height for frame buffers not yet supported in NativeEngine.");
|
|
2294
3364
|
}
|
|
3365
|
+
// Frame graph render targets are created via createMultipleRenderTarget({ dontCreateTextures: true }),
|
|
3366
|
+
// so no bgfx framebuffer is built up-front; the externally-allocated color/depth textures are attached
|
|
3367
|
+
// afterwards via setTexture/setDepthStencilTexture. Lazily build a framebuffer from those textures the
|
|
3368
|
+
// first time the wrapper is bound. Several wrappers can reference the same underlying texture(s), so the
|
|
3369
|
+
// framebuffer is cached on (and shared through) the first color texture's hardware wrapper to avoid each
|
|
3370
|
+
// fresh framebuffer/view clearing the texture and clobbering earlier passes.
|
|
3371
|
+
if (!nativeRTWrapper._framebuffers && !nativeRTWrapper._framebufferDepthStencil && !nativeRTWrapper._framebuffer) {
|
|
3372
|
+
this._buildFrameGraphFramebuffer(nativeRTWrapper);
|
|
3373
|
+
}
|
|
2295
3374
|
if (nativeRTWrapper._framebuffers) {
|
|
2296
|
-
//
|
|
2297
|
-
|
|
3375
|
+
// _framebuffers is indexed by cube face for cube render targets, but by array layer for 2D-array
|
|
3376
|
+
// render targets (cascaded shadow maps, the atmosphere aerial-perspective LUT). Callers pass the
|
|
3377
|
+
// face in `faceIndex` and the array slice in `layer`, so pick whichever applies to this wrapper;
|
|
3378
|
+
// indexing a layered target by `faceIndex` bound slice 0 for every layer and left slices 1..N-1
|
|
3379
|
+
// unwritten.
|
|
3380
|
+
const isCubeTarget = nativeRTWrapper.isCube;
|
|
3381
|
+
const framebufferIndex = isCubeTarget ? (faceIndex ?? 0) : layer || faceIndex || 0;
|
|
3382
|
+
// Cube render target: bind the framebuffer for the requested face. HDR prefiltering renders each
|
|
3383
|
+
// roughness level into its own mip, so for lodLevel > 0 lazily build/cache a per-(face, mip)
|
|
3384
|
+
// framebuffer; the pre-built _framebuffers array only targets mip 0.
|
|
3385
|
+
if (lodLevel && isCubeTarget) {
|
|
3386
|
+
this._bindUnboundFramebuffer(this._getCubeFaceMipFramebuffer(nativeRTWrapper, faceIndex ?? 0, lodLevel));
|
|
3387
|
+
}
|
|
3388
|
+
else {
|
|
3389
|
+
this._bindUnboundFramebuffer(nativeRTWrapper._framebuffers[Math.min(framebufferIndex, nativeRTWrapper._framebuffers.length - 1)]);
|
|
3390
|
+
}
|
|
2298
3391
|
}
|
|
2299
3392
|
else if (faceIndex) {
|
|
2300
3393
|
throw new Error("Cuboid frame buffers are not yet supported in NativeEngine.");
|
|
@@ -2305,6 +3398,156 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
2305
3398
|
else {
|
|
2306
3399
|
this._bindUnboundFramebuffer(nativeRTWrapper._framebuffer);
|
|
2307
3400
|
}
|
|
3401
|
+
// Match ThinEngine: re-apply the cached viewport (or the fullscreen override) after a framebuffer bind.
|
|
3402
|
+
this._applyBoundViewport(forceFullscreenViewport);
|
|
3403
|
+
}
|
|
3404
|
+
// Re-apply the engine's cached viewport onto the newly bound framebuffer (WebGL/WebGPU behaviour).
|
|
3405
|
+
// forceFullscreenViewport paints 0..1 without clobbering _cachedViewport, matching ThinEngine's
|
|
3406
|
+
// use of _viewport() for the fullscreen path.
|
|
3407
|
+
_applyBoundViewport(forceFullscreenViewport) {
|
|
3408
|
+
if (this._cachedViewport && !forceFullscreenViewport) {
|
|
3409
|
+
this.setViewport(this._cachedViewport);
|
|
3410
|
+
return;
|
|
3411
|
+
}
|
|
3412
|
+
if (forceFullscreenViewport) {
|
|
3413
|
+
const cached = this._cachedViewport;
|
|
3414
|
+
this.setViewport(_FullscreenViewport);
|
|
3415
|
+
this._cachedViewport = cached;
|
|
3416
|
+
}
|
|
3417
|
+
}
|
|
3418
|
+
// Returns (building + caching on first use) the bgfx framebuffer that targets a single (mip, layer)
|
|
3419
|
+
// slice of a 3D render-target texture. Used by the IBL voxel grid + procedural mip chain, whose
|
|
3420
|
+
// ProceduralTexture / mip-copy passes render one Z-slice at a time via bindFramebuffer(lodLevel, layer).
|
|
3421
|
+
_get3DLayerFramebuffer(nativeRTWrapper, mip, layer, requiredWidth, requiredHeight) {
|
|
3422
|
+
if (!nativeRTWrapper._layerFramebuffers) {
|
|
3423
|
+
nativeRTWrapper._layerFramebuffers = new Map();
|
|
3424
|
+
}
|
|
3425
|
+
const key = mip * nativeRTWrapper.depth + layer;
|
|
3426
|
+
let framebuffer = nativeRTWrapper._layerFramebuffers.get(key);
|
|
3427
|
+
if (!framebuffer) {
|
|
3428
|
+
const nativeTexture = nativeRTWrapper.texture._hardwareTexture.underlyingResource;
|
|
3429
|
+
const depthTexture = nativeRTWrapper._depthStencilTexture;
|
|
3430
|
+
const nativeDepth = depthTexture?._hardwareTexture?.underlyingResource;
|
|
3431
|
+
const width = requiredWidth || Math.max(1, nativeRTWrapper.width >> mip);
|
|
3432
|
+
const height = requiredHeight || Math.max(1, nativeRTWrapper.height >> mip);
|
|
3433
|
+
if (nativeDepth) {
|
|
3434
|
+
this._assertVolumeDepthAttachmentSupported();
|
|
3435
|
+
// createMultiFrameBuffer has no mip selector and the explicit depth texture only covers mip 0.
|
|
3436
|
+
if (mip !== 0) {
|
|
3437
|
+
throw new Error("NativeEngine: explicit depth attachments on volume render targets only support rendering to mip 0.");
|
|
3438
|
+
}
|
|
3439
|
+
// generateDepth must be set so a depth texture without a native handle yet (created directly on this
|
|
3440
|
+
// volume) is allocated and aliased by the first slice; later slices borrow the existing handle.
|
|
3441
|
+
framebuffer = this._engine.createMultiFrameBuffer([nativeTexture], width, height, HasStencilAspect(depthTexture.format), true, nativeRTWrapper.samples, [layer], nativeDepth);
|
|
3442
|
+
this._setTextureSampling(nativeDepth, getNativeSamplingMode(depthTexture.samplingMode));
|
|
3443
|
+
this.updateTextureComparisonFunction(depthTexture, depthTexture._comparisonFunction);
|
|
3444
|
+
}
|
|
3445
|
+
else {
|
|
3446
|
+
framebuffer = this._engine.createFrameBuffer(nativeTexture, width, height, nativeRTWrapper._generateStencilBuffer, nativeRTWrapper._generateDepthBuffer, nativeRTWrapper.samples, layer, mip);
|
|
3447
|
+
}
|
|
3448
|
+
nativeRTWrapper._layerFramebuffers.set(key, framebuffer);
|
|
3449
|
+
}
|
|
3450
|
+
return framebuffer;
|
|
3451
|
+
}
|
|
3452
|
+
// Returns (building + caching on first use) the bgfx framebuffer that targets a single (face, mip) of a
|
|
3453
|
+
// cube render-target texture. Used by HDR radiance/irradiance prefiltering, whose face×mip loop renders
|
|
3454
|
+
// an increasingly-rough convolution of the environment into each mip via bindFramebuffer(faceIndex, lod).
|
|
3455
|
+
// The pre-built _framebuffers array only covers mip 0, so mips > 0 are built here on demand.
|
|
3456
|
+
_getCubeFaceMipFramebuffer(nativeRTWrapper, face, mip) {
|
|
3457
|
+
// An explicit (sampleable) depth texture only covers mip 0 and native framebuffers cannot select a depth mip,
|
|
3458
|
+
// so a per-mip framebuffer would silently render against unrelated depth instead of the attached texture.
|
|
3459
|
+
if (nativeRTWrapper._depthStencilTexture) {
|
|
3460
|
+
throw new Error("NativeEngine: explicit depth attachments on cube render targets only support rendering to mip 0.");
|
|
3461
|
+
}
|
|
3462
|
+
if (!nativeRTWrapper._layerFramebuffers) {
|
|
3463
|
+
nativeRTWrapper._layerFramebuffers = new Map();
|
|
3464
|
+
}
|
|
3465
|
+
const key = mip * 6 + face;
|
|
3466
|
+
let framebuffer = nativeRTWrapper._layerFramebuffers.get(key);
|
|
3467
|
+
if (!framebuffer) {
|
|
3468
|
+
const nativeTexture = nativeRTWrapper.texture._hardwareTexture.underlyingResource;
|
|
3469
|
+
const width = Math.max(1, nativeRTWrapper.width >> mip);
|
|
3470
|
+
const height = Math.max(1, nativeRTWrapper.height >> mip);
|
|
3471
|
+
framebuffer = this._engine.createFrameBuffer(nativeTexture, width, height, nativeRTWrapper._generateStencilBuffer, nativeRTWrapper._generateDepthBuffer, nativeRTWrapper.samples, face, mip, nativeRTWrapper.texture.generateMipMaps);
|
|
3472
|
+
nativeRTWrapper._layerFramebuffers.set(key, framebuffer);
|
|
3473
|
+
}
|
|
3474
|
+
return framebuffer;
|
|
3475
|
+
}
|
|
3476
|
+
// A frame-graph multi-render-target wrapper is created via createMultipleRenderTarget({dontCreateTextures:
|
|
3477
|
+
// true}) WITHOUT targetTypes/layerIndex/faceIndex, so it is never flagged _isMixedTypeMRT at creation: its
|
|
3478
|
+
// color textures (setTexture) and per-attachment layer/face indices (setLayerAndFaceIndex, from the render
|
|
3479
|
+
// pass's setOutputLayerAndFaceIndices) are assigned afterwards. Detect the layered case at bind time so it
|
|
3480
|
+
// routes through _bindLayeredMultiFramebuffer (which renders each draw buffer into the correct 2D-array
|
|
3481
|
+
// layer / cube face) instead of the flat _buildFrameGraphFramebuffer (which would bind layer 0 of every
|
|
3482
|
+
// attachment and duplicate a shared array/cube resource, leaving the extra targets unwritten).
|
|
3483
|
+
_isLayeredFrameGraphMRT(wrapper) {
|
|
3484
|
+
const textures = wrapper.textures;
|
|
3485
|
+
if (!textures || textures.length === 0) {
|
|
3486
|
+
return false;
|
|
3487
|
+
}
|
|
3488
|
+
for (const tex of textures) {
|
|
3489
|
+
if (tex && (tex.isCube || tex.is2DArray || tex.is3D)) {
|
|
3490
|
+
return true;
|
|
3491
|
+
}
|
|
3492
|
+
}
|
|
3493
|
+
const faceIndices = wrapper.faceIndices;
|
|
3494
|
+
if (faceIndices) {
|
|
3495
|
+
for (const face of faceIndices) {
|
|
3496
|
+
if (face) {
|
|
3497
|
+
return true;
|
|
3498
|
+
}
|
|
3499
|
+
}
|
|
3500
|
+
}
|
|
3501
|
+
const layerIndices = wrapper.layerIndices;
|
|
3502
|
+
if (layerIndices) {
|
|
3503
|
+
for (const layer of layerIndices) {
|
|
3504
|
+
if (layer) {
|
|
3505
|
+
return true;
|
|
3506
|
+
}
|
|
3507
|
+
}
|
|
3508
|
+
}
|
|
3509
|
+
return false;
|
|
3510
|
+
}
|
|
3511
|
+
// (Re)builds and binds the multi-attachment framebuffer for a layered MRT: either an IBL voxelization MRT
|
|
3512
|
+
// (color attachments are distinct Z-slices of one shared 3D texture) or a mixed-type MRT (color attachments
|
|
3513
|
+
// are specific layers of 2D-array textures and/or faces of cube textures, plus plain 2D). Textures may be
|
|
3514
|
+
// assigned via setInternalTexture and layers/faces retargeted via setLayerAndFaceIndex after creation, so the
|
|
3515
|
+
// framebuffer is built lazily here and rebuilt whenever its attachment layout changes.
|
|
3516
|
+
_bindLayeredMultiFramebuffer(nativeRTWrapper) {
|
|
3517
|
+
const textures = nativeRTWrapper.textures;
|
|
3518
|
+
const layerIndices = nativeRTWrapper.layerIndices;
|
|
3519
|
+
const expectedCount = nativeRTWrapper._attachments?.length ?? textures?.length ?? 0;
|
|
3520
|
+
if (!textures || textures.length < expectedCount) {
|
|
3521
|
+
throw new Error("NativeEngine: cannot bind a layered MRT until every color attachment is assigned.");
|
|
3522
|
+
}
|
|
3523
|
+
const depth = nativeRTWrapper._depthStencilTexture?._hardwareTexture?.underlyingResource;
|
|
3524
|
+
const samples = nativeRTWrapper.samples;
|
|
3525
|
+
const key = nativeRTWrapper._layeredFramebufferKey;
|
|
3526
|
+
let upToDate = !!nativeRTWrapper._framebuffer && !!key && key.depth === depth && key.samples === samples && key.colors.length === expectedCount;
|
|
3527
|
+
for (let i = 0; i < expectedCount; i++) {
|
|
3528
|
+
const tex = textures[i];
|
|
3529
|
+
const nativeTexture = tex?._hardwareTexture?.underlyingResource;
|
|
3530
|
+
if (!nativeTexture) {
|
|
3531
|
+
throw new Error("NativeEngine: cannot bind a layered MRT until every color attachment is assigned.");
|
|
3532
|
+
}
|
|
3533
|
+
const attachmentLayer = tex.is3D ? (layerIndices?.[i] ?? i) : nativeRTWrapper.getBaseArrayLayer(i);
|
|
3534
|
+
if (upToDate && (key.colors[i] !== nativeTexture || key.layers[i] !== attachmentLayer)) {
|
|
3535
|
+
upToDate = false;
|
|
3536
|
+
}
|
|
3537
|
+
}
|
|
3538
|
+
if (!upToDate) {
|
|
3539
|
+
const colorTextures = new Array(expectedCount);
|
|
3540
|
+
const layers = new Array(expectedCount);
|
|
3541
|
+
for (let i = 0; i < expectedCount; i++) {
|
|
3542
|
+
const tex = textures[i];
|
|
3543
|
+
colorTextures[i] = tex._hardwareTexture.underlyingResource;
|
|
3544
|
+
layers[i] = tex.is3D ? (layerIndices?.[i] ?? i) : nativeRTWrapper.getBaseArrayLayer(i);
|
|
3545
|
+
}
|
|
3546
|
+
nativeRTWrapper._framebuffer = this._createNativeMultiFrameBuffer(colorTextures, nativeRTWrapper.width, nativeRTWrapper.height, this._getDepthAttachmentStencil(nativeRTWrapper), !!depth || nativeRTWrapper._generateDepthBuffer, samples, layers, depth);
|
|
3547
|
+
nativeRTWrapper._layeredFramebufferKey = { colors: colorTextures, layers, depth, samples };
|
|
3548
|
+
this._applyDepthTextureSampling(nativeRTWrapper);
|
|
3549
|
+
}
|
|
3550
|
+
this._bindUnboundFramebuffer(nativeRTWrapper._framebuffer);
|
|
2308
3551
|
}
|
|
2309
3552
|
unBindFramebuffer(texture, disableGenerateMipMaps = false, onBeforeUnbind) {
|
|
2310
3553
|
// NOTE: Disabling mipmap generation is not yet supported in NativeEngine.
|
|
@@ -2444,6 +3687,14 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
2444
3687
|
this._unsetNativeTexture(uniform);
|
|
2445
3688
|
}
|
|
2446
3689
|
}
|
|
3690
|
+
/**
|
|
3691
|
+
* @internal
|
|
3692
|
+
*/
|
|
3693
|
+
_bindTextureDirectly(_target, _texture, _forTextureDataUpdate = false, _force = false) {
|
|
3694
|
+
// Generic texture loaders use this WebGL-shaped method around direct uploads. Native upload commands
|
|
3695
|
+
// already receive the destination texture explicitly, so there is no bind operation to perform.
|
|
3696
|
+
return false;
|
|
3697
|
+
}
|
|
2447
3698
|
/**
|
|
2448
3699
|
* Unbind all textures
|
|
2449
3700
|
*/
|
|
@@ -2524,9 +3775,10 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
2524
3775
|
}
|
|
2525
3776
|
// bgfx updates the requested sub-rectangle of the existing texture (faceIndex selects the cube
|
|
2526
3777
|
// face / array layer, lod selects the mip level). invertY is forwarded so the native side can match
|
|
2527
|
-
// the vertical orientation the base texture upload uses.
|
|
2528
|
-
//
|
|
2529
|
-
|
|
3778
|
+
// the vertical orientation the base texture upload uses. Native rebuilds mips from a full level only, so
|
|
3779
|
+
// generateMipMaps is ignored for partial updates.
|
|
3780
|
+
const fullLevel = xOffset === 0 && yOffset === 0 && width === Math.max(1, texture.width >> lod) && height === Math.max(1, texture.height >> lod);
|
|
3781
|
+
this._engine.updateTextureData(texture._hardwareTexture.underlyingResource, imageData, xOffset, yOffset, width, height, faceIndex, lod, texture.invertY, generateMipMaps && fullLevel);
|
|
2530
3782
|
}
|
|
2531
3783
|
/**
|
|
2532
3784
|
* @internal
|
|
@@ -2538,7 +3790,27 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
2538
3790
|
* @internal
|
|
2539
3791
|
*/
|
|
2540
3792
|
_uploadDataToTextureDirectly(texture, imageData, faceIndex = 0, lod = 0) {
|
|
2541
|
-
|
|
3793
|
+
if (!texture._hardwareTexture) {
|
|
3794
|
+
return;
|
|
3795
|
+
}
|
|
3796
|
+
const underlyingResource = texture._hardwareTexture.underlyingResource;
|
|
3797
|
+
// Per-mip uploads (e.g. KTX2 decoded mip levels, called with that mip's dimensions in texture.width/height)
|
|
3798
|
+
// update only the requested level of the texture allocated by the lod 0 upload. Older runtimes without
|
|
3799
|
+
// updateTextureData cannot preserve authored mip content, so fail the load instead of silently
|
|
3800
|
+
// substituting a chain generated from lod 0.
|
|
3801
|
+
if (lod > 0) {
|
|
3802
|
+
if (!this._engine.updateTextureData) {
|
|
3803
|
+
throw new Error("NativeEngine._uploadDataToTextureDirectly: uploading mip levels above 0 requires a Babylon Native runtime with updateTextureData.");
|
|
3804
|
+
}
|
|
3805
|
+
this._engine.updateTextureData(underlyingResource, imageData, 0, 0, texture.width, texture.height, faceIndex, lod, texture.invertY, false);
|
|
3806
|
+
return;
|
|
3807
|
+
}
|
|
3808
|
+
texture.baseWidth = texture.width;
|
|
3809
|
+
texture.baseHeight = texture.height;
|
|
3810
|
+
// Upload raw pixel data (e.g. the decoded IES profile: a single-channel FLOAT texture) into the
|
|
3811
|
+
// native texture. Mirrors updateRawTexture. Like texImage2D, Native reads only the texels it needs from a
|
|
3812
|
+
// larger buffer.
|
|
3813
|
+
this._engine.loadRawTexture(underlyingResource, imageData, texture.width, texture.height, getNativeTextureFormat(texture.format, texture.type), texture.generateMipMaps, texture.invertY, texture._useSRGBBuffer);
|
|
2542
3814
|
}
|
|
2543
3815
|
/**
|
|
2544
3816
|
* @internal
|
|
@@ -2557,15 +3829,16 @@ export class ThinNativeEngine extends ThinEngine {
|
|
|
2557
3829
|
flushFramebuffer() { }
|
|
2558
3830
|
// eslint-disable-next-line @typescript-eslint/promise-function-async
|
|
2559
3831
|
_readTexturePixels(texture, width, height, faceIndex, level, buffer, _flushRenderer, _noDataConversion, x, y) {
|
|
2560
|
-
if (faceIndex !== undefined && faceIndex !== -1) {
|
|
2561
|
-
throw new Error(`
|
|
3832
|
+
if (faceIndex !== undefined && faceIndex !== -1 && (faceIndex < 0 || faceIndex > 5)) {
|
|
3833
|
+
throw new Error(`Invalid cubemap face index ${faceIndex}; expected 0-5 or -1.`);
|
|
2562
3834
|
}
|
|
2563
|
-
return (this._engine
|
|
2564
|
-
.
|
|
3835
|
+
return ((this._engine.readTexture2 ?? this._engine.readTexture)
|
|
3836
|
+
.call(this._engine, texture._hardwareTexture?.underlyingResource, level ?? 0, x ?? 0, y ?? 0, width, height, buffer?.buffer ?? null, buffer?.byteOffset ?? 0, buffer?.byteLength ?? 0, faceIndex ?? -1)
|
|
2565
3837
|
// eslint-disable-next-line github/no-then
|
|
2566
3838
|
.then((rawBuffer) => {
|
|
2567
3839
|
if (!buffer) {
|
|
2568
|
-
|
|
3840
|
+
// Legacy readTexture returns RGBA8; readTexture2 preserves float sources as RGBA32F.
|
|
3841
|
+
buffer = rawBuffer.byteLength === 16 * width * height ? new Float32Array(rawBuffer) : new Uint8Array(rawBuffer);
|
|
2569
3842
|
}
|
|
2570
3843
|
return buffer;
|
|
2571
3844
|
}));
|