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 | |
| parent | 02c32fcc30e753da96f0aa072ed1d74ca300979c (diff) | |
Impostors: continue work on depth
| -rw-r--r-- | 3ner.cginc | 51 | ||||
| -rw-r--r-- | 3ner.shader | 3 | ||||
| -rw-r--r-- | DepthBlit.shader | 15 | ||||
| -rw-r--r-- | Scripts/Impostors.cs | 8 | ||||
| -rw-r--r-- | cnlohr.cginc | 8 | ||||
| -rw-r--r-- | features.cginc | 4 | ||||
| -rw-r--r-- | globals.cginc | 2 | ||||
| -rw-r--r-- | impostor.cginc | 43 |
8 files changed, 85 insertions, 49 deletions
@@ -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; } |
