diff options
| author | yum <yum.food.vr@gmail.com> | 2026-01-17 17:35:13 -0800 |
|---|---|---|
| committer | yum <yum.food.vr@gmail.com> | 2026-01-17 17:37:06 -0800 |
| commit | b925b4b1bf79e3d6f930a4d799a7194673b62bde (patch) | |
| tree | 1c45dbf95f66c4948ef6bcf64d9622b259fce624 | |
| parent | c6923a553c98da7805407fe1fbfdb6c69c8d7530 (diff) | |
Impostors: continue work on depth, getting closer
| -rw-r--r-- | 3ner.cginc | 15 | ||||
| -rw-r--r-- | DepthBlit.shader | 11 | ||||
| -rw-r--r-- | Scripts/Impostors.cs | 17 | ||||
| -rw-r--r-- | impostor.cginc | 26 | ||||
| -rw-r--r-- | pbr.cginc | 2 |
5 files changed, 44 insertions, 27 deletions
@@ -258,7 +258,7 @@ float4 frag(v2f i, uint facing : SV_IsFrontFace #endif ) : SV_Target { UNITY_SETUP_INSTANCE_ID(i); -#if defined(SHADOW_CASTER_PASS) +#if defined(SHADOW_CASTER_PASS) && !(_IMPOSTORS) return 0; #endif @@ -281,18 +281,9 @@ float4 frag(v2f i, uint facing : SV_IsFrontFace i.normal = pbr.normal; i.objPos = pbr.objPos; propagateObjPos(i); + 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) @@ -304,7 +295,6 @@ float4 frag(v2f i, uint facing : SV_IsFrontFace #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; @@ -323,4 +313,3 @@ float4 frag(v2f i, uint facing : SV_IsFrontFace } #endif // __3NER_INC - diff --git a/DepthBlit.shader b/DepthBlit.shader index 4094fe5..b2a512f 100644 --- a/DepthBlit.shader +++ b/DepthBlit.shader @@ -20,7 +20,7 @@ Shader "Hidden/yum_food/DepthBlit" #include "UnityCG.cginc" - sampler2D _DepthTex; + UNITY_DECLARE_DEPTH_TEXTURE(_DepthTex); float _Near; float _Far; @@ -41,7 +41,14 @@ Shader "Hidden/yum_food/DepthBlit" float4 frag(v2f i) : SV_Target { // 0 = near clip plane, 1 = far clip plane. - return tex2D(_DepthTex, i.uv).r; + float rawDepth = SAMPLE_DEPTH_TEXTURE(_DepthTex, i.uv); + // Unity uses reversed-Z on most platforms: 1 at near, 0 at far. + // Flip to get linear 0-1 (0=near, 1=far) for orthographic cameras. + #if defined(UNITY_REVERSED_Z) + return 1.0 - rawDepth; + #else + return rawDepth; + #endif } ENDCG } diff --git a/Scripts/Impostors.cs b/Scripts/Impostors.cs index e1447b6..9769aa1 100644 --- a/Scripts/Impostors.cs +++ b/Scripts/Impostors.cs @@ -298,17 +298,25 @@ public class Impostors : MonoBehaviour Color[] origAlpha = preserveAlpha ? (Color[])alpha.Clone() : null; Color[] buffer = (Color[])pixels.Clone(); + bool[] filled = new bool[pixels.Length]; + for (int i = 0; i < pixels.Length; i++) + filled[i] = alpha[i].a > 0.01f; + bool[] filledNext = new bool[filled.Length]; + int[] dx = { -1, 1, 0, 0 }; int[] dy = { 0, 0, -1, 1 }; for (int iter = 0; iter < iterations; iter++) { + System.Array.Copy(pixels, buffer, pixels.Length); + System.Array.Copy(filled, filledNext, filled.Length); + for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { int i = y * w + x; - if (alpha[i].a > 0.01f) continue; + if (filled[i]) continue; Color sum = Color.clear; int count = 0; @@ -317,7 +325,7 @@ public class Impostors : MonoBehaviour int nx = x + dx[d], ny = y + dy[d]; if (nx < 0 || nx >= w || ny < 0 || ny >= h) continue; int ni = ny * w + nx; - if (alpha[ni].a > 0.01f || (iter > 0 && pixels[ni].a > 0)) + if (filled[ni]) { sum += pixels[ni]; count++; @@ -327,10 +335,12 @@ public class Impostors : MonoBehaviour { buffer[i] = sum / count; buffer[i].a = 1; + filledNext[i] = true; } } } - var tmp = pixels; pixels = buffer; buffer = tmp; + var tmpFilled = filled; filled = filledNext; filledNext = tmpFilled; + var tmpPixels = pixels; pixels = buffer; buffer = tmpPixels; } if (preserveAlpha) @@ -488,6 +498,7 @@ public class Impostors : MonoBehaviour impostorMaterial.SetFloat("_Impostors_Sphere_Radius", sphere_radius_); impostorMaterial.SetFloat("_Impostors_Near_Clip", nearClippingDistance); impostorMaterial.SetFloat("_Impostors_Far_Clip", sphere_radius_ * 2f + nearClippingDistance); + impostorMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.LessEqual); impostorMaterial.SetFloat("_Impostors_Enabled", 1); impostorMaterial.SetFloat("_Impostors_Parallax", 1); impostorMaterial.SetFloat("_Cull", (float)UnityEngine.Rendering.CullMode.Front); diff --git a/impostor.cginc b/impostor.cginc index 184a8fe..e84f9db 100644 --- a/impostor.cginc +++ b/impostor.cginc @@ -67,9 +67,9 @@ 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 +// 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; + return lerp(_Impostors_Near_Clip, _Impostors_Far_Clip, linearDepth); } float2 ClampUvInCell(float2 uv) { @@ -90,6 +90,8 @@ struct ImpostorResult { float metallic; float smoothness; float3 objPos; + // TODO rm + float debug; }; float SampleImpostorDepthCell(float2 cell, float2 uvInCell, float gridRes) { @@ -133,9 +135,13 @@ float2 ImpostorParallaxOffsetForFrame(float3 frameDir, float3 pivotToCamOS, floa float camZ = dot(pivotToCamOS, planeN); camZ = (abs(camZ) < 1e-4) ? (camZ < 0 ? -1e-4 : 1e-4) : camZ; - // Decode depth to world space, then normalize to [0,1] range + // Convert world-space depth to object space to match scaled impostor. + float objScale = max(2.0 * _Impostors_Sphere_Radius, 1e-4); + float objRadius = _Impostors_Sphere_Radius / objScale; + float objNear = _Impostors_Near_Clip / objScale; float worldSpaceDepth = DecodeImpostorDepth(encodedDepth); - float depth01 = (worldSpaceDepth - _Impostors_Near_Clip) / (2.0 * _Impostors_Sphere_Radius); + float objectSpaceDepth = worldSpaceDepth / objScale; + float depth01 = (objectSpaceDepth - objNear) / (2.0 * objRadius); // Convert to signed "height" where nearer pixels shift more (matches typical bump-offset convention). float zSurface = (depth01 - 0.5); float2 planeCoord = 0.5 - uvBase; @@ -150,12 +156,14 @@ float3 ReconstructObjectOffsetFromFrame(float3 frameDir, float2 uv, float encode float3 planeX, planeY, planeN; FrameBasis(frameDir, planeX, planeY, planeN); - // UV offset from center, scaled to world units (baking camera spans [-Radius, Radius]) - float2 offsetXY = (0.5 - uv) * 2.0 * _Impostors_Sphere_Radius; + float objScale = max(2.0f * _Impostors_Sphere_Radius, 1e-4); + float objRadius = _Impostors_Sphere_Radius / objScale; + float objNear = _Impostors_Near_Clip / objScale; + float objFar = _Impostors_Far_Clip / objScale; - // 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; + float2 offsetXY = (0.5f - uv) * 2.0f * objRadius; + float objectSpaceDepth = lerp(objNear, objFar, encodedDepth); + float offsetZ = (objRadius + objNear) - objectSpaceDepth; return offsetXY.x * planeX + offsetXY.y * planeY + offsetZ * planeN; } @@ -26,6 +26,7 @@ struct Pbr { #endif #if defined(_IMPOSTORS) float3 objPos; + float debug; // TODO rm #endif }; @@ -170,6 +171,7 @@ Pbr getPbr(v2f i) { pbr.smoothness = imp.smoothness; pbr.metallic = imp.metallic; pbr.objPos = imp.objPos; + pbr.debug = imp.debug; #else pbr.albedo = _MainTex.Sample(aniso16_trilinear_repeat_s, uv_parallax * _MainTex_ST.xy + _MainTex_ST.zw); pbr.albedo *= _Color; |
