diff options
| -rw-r--r-- | impostor.cginc | 92 |
1 files changed, 46 insertions, 46 deletions
diff --git a/impostor.cginc b/impostor.cginc index 5a923c5..3a479c8 100644 --- a/impostor.cginc +++ b/impostor.cginc @@ -38,13 +38,15 @@ float3 DirFromCell(float2 cell, float gridRes) { return HemiOctDecode(uv); } -// Branchless barycentric weights in a unit square split into two triangles -float4 GridCellBarycentric4(float2 p) { - float w00 = 1.0 - max(p.x, p.y); - float w11 = min(p.x, p.y); - float w01 = max(p.y - p.x, 0.0); - float w10 = max(p.x - p.y, 0.0); - return float4(w00, w01, w10, w11); +// Branchless barycentric weights for 3 points +float3 BarycentricWeights3(float2 gridFrac, bool isBottomRight) { + if (isBottomRight) { + // Bottom-Right Triangle: (0,0), (1,0), (1,1) + return float3(1.0 - gridFrac.x, gridFrac.x - gridFrac.y, gridFrac.y); + } else { + // Top-Left Triangle: (0,0), (0,1), (1,1) + return float3(1.0 - gridFrac.y, gridFrac.y - gridFrac.x, gridFrac.x); + } } // Compute UV on a virtual plane facing frameDir @@ -156,24 +158,23 @@ ImpostorSample SampleImpostorCellParallaxSafe( return baseS; } -ImpostorSample BlendImpostorSamples(ImpostorSample s00, ImpostorSample s01, ImpostorSample s10, ImpostorSample s11, float4 bw) { +ImpostorSample BlendImpostorSamples(ImpostorSample s0, ImpostorSample s1, ImpostorSample s2, float3 bw) { ImpostorSample result; - float4 alpha = float4(s00.albedo.a, s01.albedo.a, s10.albedo.a, s11.albedo.a); + float3 alpha = float3(s0.albedo.a, s1.albedo.a, s2.albedo.a); float alphaOut = dot(alpha, bw); float3 premul = - s00.albedo.rgb * (alpha.x * bw.x) + - s01.albedo.rgb * (alpha.y * bw.y) + - s10.albedo.rgb * (alpha.z * bw.z) + - s11.albedo.rgb * (alpha.w * bw.w); + s0.albedo.rgb * (alpha.x * bw.x) + + s1.albedo.rgb * (alpha.y * bw.y) + + s2.albedo.rgb * (alpha.z * bw.z); float3 rgbOut = premul / max(alphaOut, 1e-4); result.albedo = float4(rgbOut, alphaOut); // Weight normal/metallicGloss by alpha to avoid blending with transparent (zero) pixels - float4 alphaBw = float4(s00.albedo.a, s01.albedo.a, s10.albedo.a, s11.albedo.a) * bw; - alphaBw /= max(dot(alphaBw, 1), 0.001); + float3 alphaBw = alpha * bw; + alphaBw /= max(dot(alphaBw, 1.0), 0.001); - result.normal = s00.normal * alphaBw.x + s01.normal * alphaBw.y + s10.normal * alphaBw.z + s11.normal * alphaBw.w; - result.metallicGloss = s00.metallicGloss * alphaBw.x + s01.metallicGloss * alphaBw.y + s10.metallicGloss * alphaBw.z + s11.metallicGloss * alphaBw.w; + result.normal = s0.normal * alphaBw.x + s1.normal * alphaBw.y + s2.normal * alphaBw.z; + result.metallicGloss = s0.metallicGloss * alphaBw.x + s1.metallicGloss * alphaBw.y + s2.metallicGloss * alphaBw.z; return result; } @@ -227,55 +228,54 @@ ImpostorResult impostor_frag(float3 worldPos) { float3x3 worldToObject = (float3x3)unity_WorldToObject; float3 viewOS = normalize(mul(worldToObject, normalize(camPos - center))); - // Get continuous grid position and find the 4 frames + // Get continuous grid position and find the 3 nearest frames float gridRes = (float)_Impostors_Grid_Resolution; float2 grid = GridFromDir(viewOS, gridRes); float2 gridFloor = floor(grid); float2 gridFrac = frac(grid); + + // Determine triangle and weights + bool isBottomRight = gridFrac.x > gridFrac.y; + float3 bw = BarycentricWeights3(gridFrac, isBottomRight); - // Branchless barycentric blend weights - float4 bw = GridCellBarycentric4(gridFrac); - - // Frame cells (square corners) - float2 cell00 = clamp(gridFloor, 0, gridRes - 1); - float2 cell01 = clamp(gridFloor + float2(0,1), 0, gridRes - 1); - float2 cell10 = clamp(gridFloor + float2(1,0), 0, gridRes - 1); - float2 cell11 = clamp(gridFloor + float2(1,1), 0, gridRes - 1); + // Frame cells + float2 cell0 = clamp(gridFloor, 0, gridRes - 1); + float2 cell1 = clamp(gridFloor + (isBottomRight ? float2(1,0) : float2(0,1)), 0, gridRes - 1); + float2 cell2 = clamp(gridFloor + float2(1,1), 0, gridRes - 1); // Compute shared vectors for virtual plane UV calculation float3 pivotToCamOS = mul(worldToObject, camPos - center); float3 vertexPosOS = mul(worldToObject, worldPos - center); float3 vertexToCamOS = pivotToCamOS - vertexPosOS; - float3 frameDir00 = DirFromCell(cell00, gridRes); - float3 frameDir01 = DirFromCell(cell01, gridRes); - float3 frameDir10 = DirFromCell(cell10, gridRes); - float3 frameDir11 = DirFromCell(cell11, gridRes); + float3 frameDir0 = DirFromCell(cell0, gridRes); + float3 frameDir1 = DirFromCell(cell1, gridRes); + float3 frameDir2 = DirFromCell(cell2, gridRes); if (_Impostors_Debug_Depth > 0.5) { - float2 uvBase00 = ClampUvInCell(VirtualPlaneUV(frameDir00, pivotToCamOS, vertexToCamOS)); - float2 uvBase01 = ClampUvInCell(VirtualPlaneUV(frameDir01, pivotToCamOS, vertexToCamOS)); - float2 uvBase10 = ClampUvInCell(VirtualPlaneUV(frameDir10, pivotToCamOS, vertexToCamOS)); - float2 uvBase11 = ClampUvInCell(VirtualPlaneUV(frameDir11, pivotToCamOS, vertexToCamOS)); - float depth00 = SampleImpostorDepthCell(cell00, uvBase00, gridRes); - float depth01 = SampleImpostorDepthCell(cell01, uvBase01, gridRes); - float depth10 = SampleImpostorDepthCell(cell10, uvBase10, gridRes); - float depth11 = SampleImpostorDepthCell(cell11, uvBase11, gridRes); - float depthBlended = depth00 * bw.x + depth01 * bw.y + depth10 * bw.z + depth11 * bw.w; + float2 uvBase0 = ClampUvInCell(VirtualPlaneUV(frameDir0, pivotToCamOS, vertexToCamOS)); + float2 uvBase1 = ClampUvInCell(VirtualPlaneUV(frameDir1, pivotToCamOS, vertexToCamOS)); + float2 uvBase2 = ClampUvInCell(VirtualPlaneUV(frameDir2, pivotToCamOS, vertexToCamOS)); + + float depth0 = SampleImpostorDepthCell(cell0, uvBase0, gridRes); + float depth1 = SampleImpostorDepthCell(cell1, uvBase1, gridRes); + float depth2 = SampleImpostorDepthCell(cell2, uvBase2, gridRes); + + float depthBlended = depth0 * bw.x + depth1 * bw.y + depth2 * bw.z; result.albedo = float4(depthBlended.xxx, 1); return result; } - ImpostorSample s00 = SampleImpostorCellParallaxSafe(cell00, frameDir00, pivotToCamOS, vertexToCamOS, gridRes); - ImpostorSample s01 = SampleImpostorCellParallaxSafe(cell01, frameDir01, pivotToCamOS, vertexToCamOS, gridRes); - ImpostorSample s10 = SampleImpostorCellParallaxSafe(cell10, frameDir10, pivotToCamOS, vertexToCamOS, gridRes); - ImpostorSample s11 = SampleImpostorCellParallaxSafe(cell11, frameDir11, pivotToCamOS, vertexToCamOS, gridRes); + ImpostorSample s0 = SampleImpostorCellParallaxSafe(cell0, frameDir0, pivotToCamOS, vertexToCamOS, gridRes); + ImpostorSample s1 = SampleImpostorCellParallaxSafe(cell1, frameDir1, pivotToCamOS, vertexToCamOS, gridRes); + ImpostorSample s2 = SampleImpostorCellParallaxSafe(cell2, frameDir2, pivotToCamOS, vertexToCamOS, gridRes); - // Blend all samples - ImpostorSample blended = BlendImpostorSamples(s00, s01, s10, s11, bw); + // Blend 3 samples + ImpostorSample blended = BlendImpostorSamples(s0, s1, s2, bw); if (_Impostors_Debug_Mode > 0.5) { - result.albedo = float4(bw.yz, 0, 1); + // Debug view of weights + result.albedo = float4(bw, 1); return result; } |
