summaryrefslogtreecommitdiffstats
path: root/impostor.cginc
diff options
context:
space:
mode:
authoryum <yum.food.vr@gmail.com>2026-01-17 14:43:18 -0800
committeryum <yum.food.vr@gmail.com>2026-01-17 15:11:56 -0800
commitc6923a553c98da7805407fe1fbfdb6c69c8d7530 (patch)
treead4a46d220fbb210cf82ffbe83b14ed05bab0a28 /impostor.cginc
parent02c32fcc30e753da96f0aa072ed1d74ca300979c (diff)
Impostors: continue work on depth
Diffstat (limited to 'impostor.cginc')
-rw-r--r--impostor.cginc43
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;
}