CultMath: Burn cases with a divisor of exactly 0, and tests for what the film hides (guards returning 0) and for rgb_to_hsv's primaries
Stryker's survivors in math.Cycles.cs that were not equivalent: Burn's divisor <= 0 boundary, Logarithm's a <= 0 guard, and rgb_to_hsv's h < 0 wrap. mix.json is regenerated in a later commit, so FamilyMatchesBlender is unchanged here and the new Burn rows are absent. Builds. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
cf6354584f
commit
3a83ee361a
2 changed files with 37 additions and 1 deletions
|
|
@ -216,6 +216,39 @@ public sealed class CyclesOracleTests
|
|||
Assert.True(worst <= Math.ScaleB(1.0, -22), $"a lookup is {worst} from (index + weight) / (size - 1), more than 2^-22");
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(Targets))]
|
||||
public void ResultsTheFilmCannotShowFollowTheCyclesSource(string target)
|
||||
{
|
||||
// Cycles' film writes 0 for an infinite or NaN result, so the fixtures cannot tell the guards that return 0
|
||||
// from the division that would return an infinity. These are the guards in svm_math (util/math_base.h):
|
||||
// safe_logf, safe_divide and inversesqrtf return 0 where the plain operation is not finite.
|
||||
float One(string function, params float[] arguments) => (float)Call(target, function, arguments.Cast<object>().ToArray());
|
||||
Assert.Equal(0.0f, One("cycles_logarithm", 0.0f, 2.0f));
|
||||
Assert.Equal(0.0f, One("cycles_logarithm", -1.0f, 2.0f));
|
||||
Assert.Equal(0.0f, One("cycles_logarithm", 2.0f, 0.0f));
|
||||
Assert.Equal(0.0f, One("cycles_logarithm", 2.0f, -1.0f));
|
||||
Assert.Equal(0.0f, One("cycles_divide", 1.0f, 0.0f));
|
||||
Assert.Equal(0.0f, One("cycles_inverse_sqrt", 0.0f));
|
||||
Assert.Equal(0.0f, One("cycles_modulo", 1.0f, 0.0f));
|
||||
Assert.Equal(0.0f, One("cycles_floored_modulo", 1.0f, 0.0f));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(Targets))]
|
||||
public void HueSaturationAndValueOfThePrimariesFollowCycles(string target)
|
||||
{
|
||||
// util/color.h rgb_to_hsv: hue 0 for red, 1/3 for green, 2/3 for blue, saturation 1, value 1; a grey has
|
||||
// hue 0 and saturation 0. Red's hue is exactly 0 and not 1, which hsv_to_rgb would read the same.
|
||||
float[] Hsv(float r, float g, float b) => Flatten(Call(target, "cycles_rgb_to_hsv", new float3(r, g, b)));
|
||||
Assert.Equal(new[] { 0.0f, 1.0f, 1.0f }, Hsv(1.0f, 0.0f, 0.0f));
|
||||
Assert.Equal(new[] { 0.0f, 0.0f, 0.5f }, Hsv(0.5f, 0.5f, 0.5f));
|
||||
Assert.Equal(1.0f / 3.0f, Hsv(0.0f, 1.0f, 0.0f)[0], 6);
|
||||
Assert.Equal(2.0f / 3.0f, Hsv(0.0f, 0.0f, 1.0f)[0], 6);
|
||||
var back = Flatten(Call(target, "cycles_hsv_to_rgb", new float3(0.0f, 1.0f, 1.0f)));
|
||||
Assert.Equal(new[] { 1.0f, 0.0f, 0.0f }, back);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RgbToBwCoefficientsAreTheOnesBlenderReads()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -241,6 +241,9 @@ EXTRA_ROWS = {
|
|||
# A base of -1 keeps a finite result for any exponent, so the film shows the exponent past the int range.
|
||||
(-1.0, 3.0e9), (-1.0, -3.0e9), (-1.0, 2147483648.0), (-1.0, 16777216.0), (-1.0, 16777215.0)],
|
||||
"cycles_compare": [(0.0, 1.0e-7, 0.0), (1.0, 1.0000001, 0.0), (1.0, 1.0000002, 0.0), (0.0, 1.0e-7, 1.0e-8), (5.0, 5.0, 0.0), (0.0, 2.0e-7, 1.0e-7)],
|
||||
# Burn with a divisor of exactly 0 (tm + t col2 = 0) and a colour above 1: the result is 1 for the channel Cycles reads
|
||||
# as 0, and an infinity the film would hide for the others.
|
||||
"cycles_mix_burn": [(2.0, 1.5, 0.5, 1.0, 0.5, 0.5, 0.5), (0.5, 1.5, 2.0, 1.0, -1.0, -1.0, -1.0)],
|
||||
"cycles_modulo": [(0.3, 0.1), (-0.3, 0.1), (5.5, -2.0), (-5.5, -2.0), (1.0, 0.0), (1.0e7, 3.0), (7.0, 7.0), (-7.0, 7.0)],
|
||||
}
|
||||
|
||||
|
|
@ -405,7 +408,7 @@ def family_mix():
|
|||
functions.append({"function": "cycles_mix_vector", "node": "ShaderNodeMix VECTOR UNIFORM", "cases": encode_cases(columns, vector_bake("mix_vector", images, build_vector))})
|
||||
|
||||
for function, blend in MIX_MODES:
|
||||
columns = mix_columns(function, blend)
|
||||
columns = with_extra(function, mix_columns(function, blend), 7)
|
||||
images = pack_operands(columns)
|
||||
|
||||
def build(tree, imgs, blend=blend):
|
||||
|
|
|
|||
Loading…
Reference in a new issue