mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-15 05:04:15 +01:00
Fix float imprecision on blend weights
This commit is contained in:
parent
46a111d152
commit
7553b5da8a
1 changed files with 21 additions and 1 deletions
|
|
@ -138,7 +138,27 @@ public class VertexAttribute
|
|||
|
||||
return new VertexAttribute(
|
||||
element,
|
||||
index => BuildNByte4(values[index])
|
||||
index => {
|
||||
// Blend weights are _very_ sensitive to float imprecision - a vertex sum being off
|
||||
// by one, such as 256, is enough to cause a visible defect. To avoid this, we tweak
|
||||
// the converted values to have the expected sum, preferencing values with minimal differences.
|
||||
var originalValues = values[index];
|
||||
var byteValues = BuildNByte4(originalValues);
|
||||
|
||||
var adjustment = 255 - byteValues.Select(value => (int)value).Sum();
|
||||
while (adjustment != 0)
|
||||
{
|
||||
var convertedValues = byteValues.Select(value => value * (1f / 255f)).ToArray();
|
||||
var closestIndex = Enumerable.Range(0, 4)
|
||||
.Select(index => (index, delta: Math.Abs(originalValues[index] - convertedValues[index])))
|
||||
.MinBy(x => x.delta)
|
||||
.index;
|
||||
byteValues[closestIndex] = (byte)(byteValues[closestIndex] + Math.CopySign(1, adjustment));
|
||||
adjustment = 255 - byteValues.Select(value => (int)value).Sum();
|
||||
}
|
||||
|
||||
return byteValues;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue