summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--impostor.cginc92
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;
}