diff options
| author | yum <yum.food.vr@gmail.com> | 2026-01-14 16:22:27 -0800 |
|---|---|---|
| committer | yum <yum.food.vr@gmail.com> | 2026-01-14 16:22:27 -0800 |
| commit | dcae38bf23fb8c10902d90958d26b230c326b3d4 (patch) | |
| tree | d1a056eabf3daed907441556adc6e4c1e326b347 | |
| parent | a3bbff866fe4d0a4b5875dd5dd33dd1cb5411a48 (diff) | |
Impostors: rephrase to clarify barycentric interpolation
| -rw-r--r-- | impostor.cginc | 45 |
1 files changed, 23 insertions, 22 deletions
diff --git a/impostor.cginc b/impostor.cginc index d328223..a60c9ca 100644 --- a/impostor.cginc +++ b/impostor.cginc @@ -45,15 +45,20 @@ float4 SampleAtlas(float2 uv, float2 cell) { return _ImpostorAtlas.Sample(bilinear_clamp_s, (cell + uv) / _GridResolution); } -// Compute blend weights for 3 frames in a grid cell triangle -// .xyz = weights for frames 1,2,3 -// .w = which triangle (0 = lower-left, 1 = upper-right) -float4 QuadBlendWeights(float2 frac) { +// Compute barycentric weights for a point within a grid cell. +// The cell is a unit square split into two triangles along the (0,0)-(1,1) diagonal: +// Triangle 0 (lower-left): vertices at (0,0), (0,1), (1,1) +// Triangle 1 (upper-right): vertices at (0,0), (1,0), (1,1) +// Returns: +// .xyz = barycentric weights for the 3 triangle vertices +// .w = which triangle (0 or 1) +float4 GridCellBarycentric(float2 p) { float4 res; - res.x = min(1.0 - frac.x, 1.0 - frac.y); - res.y = abs(frac.x - frac.y); - res.z = min(frac.x, frac.y); - res.w = ceil(frac.x - frac.y); + // Branchless barycentric weights (works for both triangles due to symmetry) + res.x = min(1.0 - p.x, 1.0 - p.y); // weight for (0,0) vertex + res.y = abs(p.x - p.y); // weight for (0,1) or (1,0) vertex + res.z = min(p.x, p.y); // weight for (1,1) vertex + res.w = ceil(p.x - p.y); // triangle select: 0 if p.y >= p.x, 1 otherwise return res; } @@ -98,7 +103,7 @@ struct v2f { nointerpolation float2 cell1 : TEXCOORD4; nointerpolation float2 cell2 : TEXCOORD5; nointerpolation float2 cell3 : TEXCOORD6; - float3 blendWeights : TEXCOORD8; + nointerpolation float3 blendWeights : TEXCOORD8; UNITY_VERTEX_OUTPUT_STEREO }; @@ -128,19 +133,17 @@ v2f vert(appdata v) { float2 gridFloor = floor(grid); float2 gridFrac = frac(grid); - // Compute blend weights and determine which triangle - float4 weights = QuadBlendWeights(gridFrac); - o.blendWeights = weights.xyz; + // Compute barycentric weights and determine which triangle + float4 bary = GridCellBarycentric(gridFrac); + o.blendWeights = bary.xyz; - // Frame 1: base corner + // Frame 1: (0,0) corner of cell o.cell1 = gridFloor; - // Frame 2: depends on which triangle (lower-left vs upper-right) - // weights.w = 0: lower-left triangle -> (0,1) offset - // weights.w = 1: upper-right triangle -> (1,0) offset - o.cell2 = clamp(gridFloor + lerp(float2(0,1), float2(1,0), weights.w), 0, gridRes - 1); + // Frame 2: (0,1) or (1,0) corner depending on which triangle + o.cell2 = clamp(gridFloor + lerp(float2(0,1), float2(1,0), bary.w), 0, gridRes - 1); - // Frame 3: diagonal corner + // Frame 3: (1,1) corner of cell o.cell3 = clamp(gridFloor + float2(1,1), 0, gridRes - 1); // Get directions for each frame @@ -148,7 +151,7 @@ v2f vert(appdata v) { float3 dir2 = DirFromCell(o.cell2, gridRes); float3 dir3 = DirFromCell(o.cell3, gridRes); - // Billboard facing the camera direction (not snapped) + // Billboard facing the camera direction float3 viewWS = normalize(camPos - center); float3 right, up; BillboardBasis(viewWS, right, up); @@ -164,12 +167,10 @@ v2f vert(appdata v) { #endif // Compute virtual plane UVs for all 3 frames - // pivotToCam and vertexToCam in object space - float3 pivotToCamOS = mul((float3x3)unity_WorldToObject, camPos - center); + float3 pivotToCamOS = mul((float3x3)unity_WorldToObject, camPos - center) * 100.0; float3 vertexPosOS = mul((float3x3)unity_WorldToObject, worldPos - center); float3 vertexToCamOS = pivotToCamOS - vertexPosOS; - // size = 0.5 because the mesh is a unit quad (-0.5 to 0.5) o.uv1 = VirtualPlaneUV(dir1, pivotToCamOS, vertexToCamOS, 0.5); o.uv2 = VirtualPlaneUV(dir2, pivotToCamOS, vertexToCamOS, 0.5); o.uv3 = VirtualPlaneUV(dir3, pivotToCamOS, vertexToCamOS, 0.5); |
