diff options
| author | yum <yum.food.vr@gmail.com> | 2026-01-17 14:43:18 -0800 |
|---|---|---|
| committer | yum <yum.food.vr@gmail.com> | 2026-01-17 15:11:56 -0800 |
| commit | c6923a553c98da7805407fe1fbfdb6c69c8d7530 (patch) | |
| tree | ad4a46d220fbb210cf82ffbe83b14ed05bab0a28 /impostor.cginc | |
| parent | 02c32fcc30e753da96f0aa072ed1d74ca300979c (diff) | |
Impostors: continue work on depth
Diffstat (limited to 'impostor.cginc')
| -rw-r--r-- | impostor.cginc | 43 |
1 files changed, 27 insertions, 16 deletions
diff --git a/impostor.cginc b/impostor.cginc index b49dfce..184a8fe 100644 --- a/impostor.cginc +++ b/impostor.cginc @@ -67,6 +67,11 @@ float2 VirtualPlaneUV(float3 frameDir, float3 pivotToCam, float3 vertexToCam) { #if defined(_IMPOSTORS) +// Decode linear 0-1 depth (0=near clip, 1=far clip) to world space distance from camera +float DecodeImpostorDepth(float linearDepth) { + return _Impostors_Near_Clip + linearDepth * 2.0f * _Impostors_Sphere_Radius; +} + float2 ClampUvInCell(float2 uv) { uv = saturate(uv); float2 halfTexelInCell = 0.5 * _Impostors_Atlas_TexelSize.xy * (float)_Impostors_Grid_Resolution; @@ -93,6 +98,7 @@ float SampleImpostorDepthCell(float2 cell, float2 uvInCell, float gridRes) { float2 atlasUv = (cell + uvInCell) * invGridRes; float2 gradX = ddx(uvInCell) * invGridRes; float2 gradY = ddy(uvInCell) * invGridRes; + // 0 = near clip plane, 1 = far clip plane return _Impostors_Depth_Atlas.SampleGrad(bilinear_clamp_s, atlasUv, gradX, gradY).r; } @@ -119,7 +125,7 @@ ImpostorSample SampleImpostorCell(float2 cell, float2 uvInCell, float gridRes) { return s; } -float2 ImpostorParallaxOffsetForFrame(float3 frameDir, float3 pivotToCamOS, float2 uvBase, float depth01) { +float2 ImpostorParallaxOffsetForFrame(float3 frameDir, float3 pivotToCamOS, float2 uvBase, float encodedDepth) { float3 planeX, planeY, planeN; FrameBasis(frameDir, planeX, planeY, planeN); @@ -127,7 +133,9 @@ float2 ImpostorParallaxOffsetForFrame(float3 frameDir, float3 pivotToCamOS, floa float camZ = dot(pivotToCamOS, planeN); camZ = (abs(camZ) < 1e-4) ? (camZ < 0 ? -1e-4 : 1e-4) : camZ; - // Bake depth is linear in ortho: 0=near surface, 1=far surface. + // Decode depth to world space, then normalize to [0,1] range + float worldSpaceDepth = DecodeImpostorDepth(encodedDepth); + float depth01 = (worldSpaceDepth - _Impostors_Near_Clip) / (2.0 * _Impostors_Sphere_Radius); // Convert to signed "height" where nearer pixels shift more (matches typical bump-offset convention). float zSurface = (depth01 - 0.5); float2 planeCoord = 0.5 - uvBase; @@ -135,19 +143,19 @@ float2 ImpostorParallaxOffsetForFrame(float3 frameDir, float3 pivotToCamOS, floa return (planeCoord - camXY) * (zSurface / camZ); } -// Reconstruct object space position from frame UV and depth. -// UV encodes X,Y on the virtual plane (0.5 = center), depth encodes Z (0.5 = center). -// The baked orthographic view spans [-Radius, Radius] in each axis. -float3 ReconstructObjPosFromFrame(float3 frameDir, float2 uv, float depth) { +// Reconstruct object-space offset from impostor center. +// frameDir: object-space direction from center to baking camera (same space as UV computation) +// UV encodes X,Y on the virtual plane (0.5 = center), depth is linear 0-1 (near to far clip). +float3 ReconstructObjectOffsetFromFrame(float3 frameDir, float2 uv, float encodedDepth) { float3 planeX, planeY, planeN; FrameBasis(frameDir, planeX, planeY, planeN); - // Invert VirtualPlaneUV: offset = 0.5 - uv, scale by diameter + // UV offset from center, scaled to world units (baking camera spans [-Radius, Radius]) float2 offsetXY = (0.5 - uv) * 2.0 * _Impostors_Sphere_Radius; - // Depth 0 = front (toward camera), 0.5 = center, 1 = back (away from camera) - // planeN points toward camera, so positive Z = toward camera - float offsetZ = (0.5 - depth) * 2.0 * _Impostors_Sphere_Radius; + // Decode depth to world space, convert to offset from center along view direction + float worldSpaceDepth = DecodeImpostorDepth(encodedDepth); + float offsetZ = (_Impostors_Sphere_Radius + _Impostors_Near_Clip) - worldSpaceDepth; return offsetXY.x * planeX + offsetXY.y * planeY + offsetZ * planeN; } @@ -310,16 +318,19 @@ ImpostorResult impostor_frag(float3 worldPos) { result.metallic = blended.metallicGloss.r; result.smoothness = blended.metallicGloss.a; - // Reconstruct object space position from each frame's base UV and depth, then blend. - // Using base UVs and base depths ensures geometric consistency (same texel location). + // Reconstruct object-space position from each frame's UV and depth, then blend. float depth0Pos = SampleImpostorDepthCell(cell0, uv0Final, gridRes); float depth1Pos = SampleImpostorDepthCell(cell1, uv1Final, gridRes); float depth2Pos = SampleImpostorDepthCell(cell2, uv2Final, gridRes); - float3 objPos0 = ReconstructObjPosFromFrame(frameDir0, uv0Final, depth0Pos); - float3 objPos1 = ReconstructObjPosFromFrame(frameDir1, uv1Final, depth1Pos); - float3 objPos2 = ReconstructObjPosFromFrame(frameDir2, uv2Final, depth2Pos); - result.objPos = objPos0 * bw.x + objPos1 * bw.y + objPos2 * bw.z; + // Use object-space frame directions (same space as UV computation) + float3 offset0 = ReconstructObjectOffsetFromFrame(frameDir0, uv0Final, depth0Pos); + float3 offset1 = ReconstructObjectOffsetFromFrame(frameDir1, uv1Final, depth1Pos); + float3 offset2 = ReconstructObjectOffsetFromFrame(frameDir2, uv2Final, depth2Pos); + float3 objOffset = offset0 * bw.x + offset1 * bw.y + offset2 * bw.z; + + // Return object-space position (offset from origin) + result.objPos = objOffset; return result; } |
