summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryum <yum.food.vr@gmail.com>2026-01-14 16:22:27 -0800
committeryum <yum.food.vr@gmail.com>2026-01-14 16:22:27 -0800
commitdcae38bf23fb8c10902d90958d26b230c326b3d4 (patch)
treed1a056eabf3daed907441556adc6e4c1e326b347
parenta3bbff866fe4d0a4b5875dd5dd33dd1cb5411a48 (diff)
Impostors: rephrase to clarify barycentric interpolation
-rw-r--r--impostor.cginc45
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);