summaryrefslogtreecommitdiffstats
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
parent02c32fcc30e753da96f0aa072ed1d74ca300979c (diff)
Impostors: continue work on depth
-rw-r--r--3ner.cginc51
-rw-r--r--3ner.shader3
-rw-r--r--DepthBlit.shader15
-rw-r--r--Scripts/Impostors.cs8
-rw-r--r--cnlohr.cginc8
-rw-r--r--features.cginc4
-rw-r--r--globals.cginc2
-rw-r--r--impostor.cginc43
8 files changed, 85 insertions, 49 deletions
diff --git a/3ner.cginc b/3ner.cginc
index 1788116..ab80a8d 100644
--- a/3ner.cginc
+++ b/3ner.cginc
@@ -9,6 +9,7 @@
#include "AutoLight.cginc"
#include "brdf.cginc"
+#include "cnlohr.cginc"
#include "geometry.cginc"
#include "pbr.cginc"
#include "lighting.cginc"
@@ -251,19 +252,14 @@ void geom(triangle v2f tri_in[3],
}
//endex
-struct FragOut {
- float4 color;
+float4 frag(v2f i, uint facing : SV_IsFrontFace
#if defined(_IMPOSTORS)
- float depth : SV_DepthLessEqual;
+ , out float depth : SV_DepthLessEqual
#endif
-};
-
-FragOut frag(v2f i, uint facing : SV_IsFrontFace) : SV_Target {
- FragOut result = (FragOut) 0;
-
+ ) : SV_Target {
UNITY_SETUP_INSTANCE_ID(i);
#if defined(SHADOW_CASTER_PASS)
- return result;
+ return 0;
#endif
#if defined(_RAY_MARCHING)
@@ -285,18 +281,35 @@ FragOut frag(v2f i, uint facing : SV_IsFrontFace) : SV_Target {
i.normal = pbr.normal;
i.objPos = pbr.objPos;
propagateObjPos(i);
- result.depth = i.pos.z;
+ float4 imp_clip_pos = UnityObjectToClipPos(i.objPos);
+ depth = imp_clip_pos.z / imp_clip_pos.w;
+ if (false) {
+ depth *= 100;
+ depth *= depth;
+ depth *= depth;
+ depth *= 100;
+ return float4(depth, depth, depth, 1);
+ }
+ if (false) {
+ return float4(i.objPos, 1);
+ }
#endif
#if defined(_DEBUG_VIEW_UNLIT)
- result.color = pbr.albedo;
- return result;
+ return pbr.albedo;
#elif defined(_DEBUG_VIEW_WORLD_SPACE_NORMALS)
- result.color = float4((pbr.normal + 1.0f) * 0.5f, 1);
- return result;
+ return float4((pbr.normal + 1.0f) * 0.5f, 1);
#elif defined(_DEBUG_VIEW_METALLIC_GLOSS)
- result.color = float4(pbr.metallic, pbr.smoothness, 0, 1);
- return result;
+ return float4(pbr.metallic, pbr.smoothness, 0, 1);
+#elif defined(_DEBUG_VIEW_DEPTH)
+ float2 screen_uv = i.pos.xy / _ScreenParams.xy;
+ float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, screen_uv);
+ depth = 1.0f - depth;
+ depth *= 100;
+ depth *= depth;
+ depth *= depth;
+ depth *= 100;
+ return float4(depth, depth, depth, 1);
#endif
LightData light_data;
@@ -304,11 +317,9 @@ FragOut frag(v2f i, uint facing : SV_IsFrontFace) : SV_Target {
#if 0
float c = light_data.common.NoV;
- result.color = float4(c,c,c,1);
- return result;
+ return float4(c,c,c,1);
#endif
- result.color = brdf(pbr, light_data);
- return result;
+ return brdf(pbr, light_data);
}
#endif // __3NER_INC
diff --git a/3ner.shader b/3ner.shader
index 94a41e1..c2ece89 100644
--- a/3ner.shader
+++ b/3ner.shader
@@ -386,6 +386,8 @@ Shader "yum_food/3ner"
_Impostors_Depth_Atlas("Depth Atlas", 2D) = "white" {}
_Impostors_Grid_Resolution("Grid Resolution", Int) = 5
_Impostors_Sphere_Radius("Sphere Radius", Float) = 1.0
+ _Impostors_Near_Clip("Near clip distance", Float) = 0.01
+ _Impostors_Far_Clip("Far clip distance", Float) = 1.0
_Impostors_Cutoff("Alpha Cutoff", Range(0, 1)) = 0.5
_Impostors_Parallax("Parallax Strength", Range(0, 1)) = 1
@@ -416,6 +418,7 @@ Shader "yum_food/3ner"
[ThryToggle(_DEBUG_VIEW_UNLIT)] _Debug_View_Unlit("Unlit", Float) = 0
[ThryToggle(_DEBUG_VIEW_WORLD_SPACE_NORMALS)] _Debug_View_World_Space_Normals("World space normals", Float) = 0
[ThryToggle(_DEBUG_VIEW_METALLIC_GLOSS)] _Debug_View_Metallic_Gloss("Metallic gloss", Float) = 0
+ [ThryToggle(_DEBUG_VIEW_DEPTH)] _Debug_View_Depth("Depth", Float) = 0
[HideInInspector] m_end_Debug_Views("Debug Views", Float) = 0
[DoNotAnimate][HideInInspector] Instancing ("Instancing", Float) = 0
diff --git a/DepthBlit.shader b/DepthBlit.shader
index 04187c2..4094fe5 100644
--- a/DepthBlit.shader
+++ b/DepthBlit.shader
@@ -4,6 +4,8 @@ Shader "Hidden/yum_food/DepthBlit"
Properties
{
_MainTex ("", 2D) = "white" {}
+ _Near ("Near Plane", Float) = 0.01
+ _Far ("Far Plane", Float) = 1.0
}
SubShader
@@ -19,6 +21,8 @@ Shader "Hidden/yum_food/DepthBlit"
#include "UnityCG.cginc"
sampler2D _DepthTex;
+ float _Near;
+ float _Far;
struct v2f
{
@@ -36,15 +40,8 @@ Shader "Hidden/yum_food/DepthBlit"
float4 frag(v2f i) : SV_Target
{
- float rawDepth = tex2D(_DepthTex, i.uv).r;
-
- // Orthographic depth is already linear.
- // We just need to handle the platform-specific Z-buffer direction.
- #if defined(UNITY_REVERSED_Z)
- return 1.0 - rawDepth;
- #else
- return rawDepth;
- #endif
+ // 0 = near clip plane, 1 = far clip plane.
+ return tex2D(_DepthTex, i.uv).r;
}
ENDCG
}
diff --git a/Scripts/Impostors.cs b/Scripts/Impostors.cs
index e52452b..e1447b6 100644
--- a/Scripts/Impostors.cs
+++ b/Scripts/Impostors.cs
@@ -161,6 +161,8 @@ public class Impostors : MonoBehaviour
if (isDepth)
{
depthBlitMat.SetTexture("_DepthTex", depthOnlyRT);
+ depthBlitMat.SetFloat("_Near", cam.nearClipPlane);
+ depthBlitMat.SetFloat("_Far", cam.farClipPlane);
Graphics.Blit(null, linearDepthRT, depthBlitMat);
RenderTexture.active = linearDepthRT;
}
@@ -437,7 +439,7 @@ public class Impostors : MonoBehaviour
(new TextureExportSettings("albedo", mipmaps: true, sRGB: true, alphaTransparency: true), "_Impostors_Atlas"),
(new TextureExportSettings("normal", mipmaps: true, sRGB: false), "_Impostors_Normal_Atlas"),
(new TextureExportSettings("metallic_gloss", mipmaps: true, sRGB: false), "_Impostors_Metallic_Gloss_Atlas"),
- (new TextureExportSettings("depth", isEXR: true, mipmaps: false, sRGB: false, filter: FilterMode.Bilinear, uncompressed: true), "_Impostors_Depth_Atlas")
+ (new TextureExportSettings("depth", isEXR: false, mipmaps: false, sRGB: false, filter: FilterMode.Bilinear, uncompressed: true), "_Impostors_Depth_Atlas")
};
// Dilate RGB to prevent dark halos from texture filtering
@@ -484,6 +486,8 @@ public class Impostors : MonoBehaviour
impostorMaterial.SetTexture(exportSettings[i].materialProp, textures[i]);
impostorMaterial.SetInt("_Impostors_Grid_Resolution", gridResolution);
impostorMaterial.SetFloat("_Impostors_Sphere_Radius", sphere_radius_);
+ impostorMaterial.SetFloat("_Impostors_Near_Clip", nearClippingDistance);
+ impostorMaterial.SetFloat("_Impostors_Far_Clip", sphere_radius_ * 2f + nearClippingDistance);
impostorMaterial.SetFloat("_Impostors_Enabled", 1);
impostorMaterial.SetFloat("_Impostors_Parallax", 1);
impostorMaterial.SetFloat("_Cull", (float)UnityEngine.Rendering.CullMode.Front);
@@ -492,7 +496,7 @@ public class Impostors : MonoBehaviour
impostorObject = GameObject.CreatePrimitive(PrimitiveType.Quad);
impostorObject.name = "Impostor";
impostorObject.transform.SetParent(transform, false);
- impostorObject.transform.localScale = Vector3.one;
+ impostorObject.transform.localScale = Vector3.one * sphere_radius_ * 2.0f;
DestroyImmediate(impostorObject.GetComponent<Collider>());
impostorObject.GetComponent<MeshRenderer>().sharedMaterial = impostorMaterial;
diff --git a/cnlohr.cginc b/cnlohr.cginc
index 4962805..709c7ac 100644
--- a/cnlohr.cginc
+++ b/cnlohr.cginc
@@ -37,6 +37,11 @@
* SOFTWARE.
*/
+UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture);
+float _VRChatMirrorMode;
+float3 _VRChatMirrorCameraPos;
+
+
// Source:
// https://github.com/cnlohr/shadertrixx?tab=readme-ov-file#eye-center-position
bool isMirror() { return _VRChatMirrorMode != 0; }
@@ -82,7 +87,7 @@ void GetScreenUVAndPerspectiveFactor(float3 worldPos, float4 clipPos, out float2
}
#if defined(_SSAO)
-float GetDepthOfWorldPos(float3 worldPos, out float2 debug)
+float GetDepthOfWorldPos(float3 worldPos)
{
float3 objPos = mul(unity_WorldToObject, float4(worldPos, 1));
float4 clipPos = UnityObjectToClipPos(objPos);
@@ -94,7 +99,6 @@ float GetDepthOfWorldPos(float3 worldPos, out float2 debug)
GetLinearZFromZDepth_WorksWithMirrors(zDepthFromMap, screen_uv);
linearZ = min(1E3, linearZ);
- debug = screen_uv;
return linearZ;
}
#endif
diff --git a/features.cginc b/features.cginc
index 36ee2bf..8ebd19a 100644
--- a/features.cginc
+++ b/features.cginc
@@ -49,6 +49,10 @@
#pragma shader_feature_local _DEBUG_VIEW_METALLIC_GLOSS
//endex
+//ifex _Debug_View_Depth==0
+#pragma shader_feature_local _DEBUG_VIEW_DEPTH
+//endex
+
//ifex _Instance_Distance_Culling_Enabled==0
#pragma shader_feature_local _INSTANCE_DISTANCE_CULLING
//endex
diff --git a/globals.cginc b/globals.cginc
index 6387c7e..c50e7fc 100644
--- a/globals.cginc
+++ b/globals.cginc
@@ -189,6 +189,8 @@ Texture2D _Impostors_Metallic_Gloss_Atlas;
Texture2D _Impostors_Depth_Atlas;
int _Impostors_Grid_Resolution;
float _Impostors_Sphere_Radius;
+float _Impostors_Near_Clip;
+float _Impostors_Far_Clip;
float _Impostors_Cutoff;
float _Impostors_Parallax;
float _Impostors_Debug_Mode;
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;
}