Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions Sources/UntoldEngine/Systems/GaussianSystem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -121,14 +121,22 @@ public func executeGaussianFrustumCulling(_ commandBuffer: MTLCommandBuffer) {
profileTotals.dispatchCount += 1

let modelMatrix = simd_mul(worldTransformComponent.space, .identity)
let viewMatrix = cameraComponent.viewSpace
// Entity transforms are never modified when the scene root moves (SceneRootTransform
// applies its offset to the camera instead, as a "virtual camera" trick — see
// SceneRootTransform.swift). worldTransformComponent.space above is therefore in
// entity space, so the camera side of this product must go through
// effectiveViewMatrix, not the raw per-eye viewSpace — otherwise this cull silently
// drifts out of sync with where the draw pass (which already uses
// effectiveViewMatrix) actually renders the splats as soon as the scene root is
// translated/rotated (e.g. via SpatialManipulationSystem's pinch-drag).
let viewMatrix = SceneRootTransform.shared.effectiveViewMatrix(cameraComponent.viewSpace)
let modelViewMatrix = simd_mul(viewMatrix, modelMatrix)

var gaussianUniform = Uniforms()
gaussianUniform.modelViewMatrix = modelViewMatrix
gaussianUniform.viewMatrix = viewMatrix
gaussianUniform.modelMatrix = modelMatrix
gaussianUniform.cameraPosition = cameraComponent.localPosition
gaussianUniform.cameraPosition = SceneRootTransform.shared.effectiveCameraPosition(cameraComponent.localPosition)
gaussianUniform.projectionMatrix = renderInfo.perspectiveSpace

var totalSplats = UInt32(gaussianComponent.splatCount)
Expand Down Expand Up @@ -251,7 +259,10 @@ public func executeGaussianDepth(_ commandBuffer: MTLCommandBuffer) {

let modelMatrix = simd_mul(worldTransformComponent.space, .identity)

let viewMatrix: simd_float4x4 = cameraComponent.viewSpace
// See the matching comment in executeGaussianFrustumCulling: worldTransformComponent
// is in entity space, so this must be the scene-root-corrected view, not the raw
// per-eye viewSpace.
let viewMatrix: simd_float4x4 = SceneRootTransform.shared.effectiveViewMatrix(cameraComponent.viewSpace)

let modelViewMatrix = simd_mul(viewMatrix, modelMatrix)

Expand All @@ -269,7 +280,7 @@ public func executeGaussianDepth(_ commandBuffer: MTLCommandBuffer) {

gaussianUniform.modelMatrix = modelMatrix

gaussianUniform.cameraPosition = cameraComponent.localPosition
gaussianUniform.cameraPosition = SceneRootTransform.shared.effectiveCameraPosition(cameraComponent.localPosition)

gaussianUniform.projectionMatrix = renderInfo.perspectiveSpace

Expand Down
1 change: 1 addition & 0 deletions Sources/UntoldEngineXR/UntoldEngineXR.swift
Original file line number Diff line number Diff line change
Expand Up @@ -796,6 +796,7 @@
snapshot.timing.cullingMs += cullingMs
}
#endif
executeGaussianFrustumCulling(commandBuffer)
executeGaussianDepth(commandBuffer)
executeRadixSort(commandBuffer)
EngineProfiler.shared.endScope(.renderPrep)
Expand Down
Loading