4 using SiliconStudio.Core.Mathematics;
5 using SiliconStudio.Paradox.Assets.Materials.Nodes;
7 namespace SiliconStudio.
Paradox.Assets.Materials.Processor.Visitors
9 internal class MaterialReductionUtils
22 case MaterialBinaryOperand.Add:
23 return leftValue + rightValue;
24 case MaterialBinaryOperand.Average:
25 return 0.5f * (leftValue + rightValue);
26 case MaterialBinaryOperand.Divide:
27 return leftValue / rightValue;
28 case MaterialBinaryOperand.Multiply:
29 return leftValue * rightValue;
30 case MaterialBinaryOperand.None:
31 case MaterialBinaryOperand.Opaque:
33 case MaterialBinaryOperand.Subtract:
34 return leftValue - rightValue;
36 throw new ArgumentOutOfRangeException(
"Operand not supported between two floats");
51 case MaterialBinaryOperand.Add:
52 return Add(leftValue, rightValue);
53 case MaterialBinaryOperand.Average:
54 return Average(leftValue, rightValue);
55 case MaterialBinaryOperand.Color:
56 return Color(leftValue, rightValue);
57 case MaterialBinaryOperand.ColorBurn:
59 case MaterialBinaryOperand.ColorDodge:
61 case MaterialBinaryOperand.Darken:
62 return Darken(leftValue, rightValue);
63 case MaterialBinaryOperand.Desaturate:
65 case MaterialBinaryOperand.Difference:
67 case MaterialBinaryOperand.Divide:
68 return Divide(leftValue, rightValue);
69 case MaterialBinaryOperand.Exclusion:
71 case MaterialBinaryOperand.HardLight:
73 case MaterialBinaryOperand.HardMix:
74 return HardMix(leftValue, rightValue);
75 case MaterialBinaryOperand.Hue:
76 return Hue(leftValue, rightValue);
77 case MaterialBinaryOperand.Illuminate:
79 case MaterialBinaryOperand.In:
80 return In(leftValue, rightValue);
81 case MaterialBinaryOperand.Lighten:
82 return Lighten(leftValue, rightValue);
83 case MaterialBinaryOperand.LinearBurn:
85 case MaterialBinaryOperand.LinearDodge:
87 case MaterialBinaryOperand.Mask:
88 return Mask(leftValue, rightValue);
89 case MaterialBinaryOperand.Multiply:
90 return Multiply(leftValue, rightValue);
91 case MaterialBinaryOperand.None:
92 return None(leftValue, rightValue);
93 case MaterialBinaryOperand.Opaque:
94 return Opaque(leftValue, rightValue);
95 case MaterialBinaryOperand.Out:
96 return Out(leftValue, rightValue);
97 case MaterialBinaryOperand.Over:
98 return Over(leftValue, rightValue);
99 case MaterialBinaryOperand.Overlay:
100 return Overlay(leftValue, rightValue);
101 case MaterialBinaryOperand.PinLight:
102 return PinLight(leftValue, rightValue);
103 case MaterialBinaryOperand.Saturate:
104 return Saturate(leftValue, rightValue);
105 case MaterialBinaryOperand.Saturation:
107 case MaterialBinaryOperand.Screen:
108 return Screen(leftValue, rightValue);
109 case MaterialBinaryOperand.SoftLight:
111 case MaterialBinaryOperand.Subtract:
112 return Subtract(leftValue, rightValue);
113 case MaterialBinaryOperand.SubstituteAlpha:
116 throw new ArgumentOutOfRangeException(
"operand");
129 Vector4 res = MixFloat4(leftValue.
ToVector4(), rightValue.ToVector4(), operand);
141 return frontColor.W * backColor.W * interColor + frontColor.W * (1.0f - backColor.W) * frontColor + (1.0f - frontColor.
W) * backColor.W * backColor;
144 private static float BasicAlphaBlend(
float ba,
float fa)
146 return fa * (1.0f - ba) + ba;
151 var temp = BasicColorBlend(backColor, frontColor, interColor);
152 temp.W = BasicAlphaBlend(backColor.
W, frontColor.
W);
156 private static float GetSaturation(
Vector4 tex)
158 float max = Math.Max(Math.Max(tex.X, tex.Y), tex.
Z);
163 return 1.0f - Math.Min(Math.Min(tex.X, tex.Y), tex.Z) / max;
166 private static float GetValue(
Vector4 tex)
168 return Math.Max(Math.Max(tex.X, tex.Y), tex.
Z);
171 private static float GetHue(
Vector4 tex)
173 float max = Math.Max(Math.Max(tex.X, tex.Y), tex.
Z);
174 float delta = max - Math.Min(Math.Min(tex.X, tex.Y), tex.Z);
179 return (tex.Y - tex.Z) / (6.0f * delta);
181 return 1.0f / 3.0f + (tex.Z - tex.X) / (6.0f * delta);
183 return 2.0f / 3.0f + (tex.X - tex.Y) / (6.0f * delta);
186 private static Vector4 HSVToRGB(
float hue,
float saturation,
float value)
188 var ti = (int)Math.Floor(1.0f - hue < 1.0e-10 ? 0.0f : hue * 6.0f);
189 var f = hue * 6.0f - ti;
190 var l = value * (1.0f - saturation);
191 var m = value * (1.0f - f * saturation);
192 var n = value * (1.0f - (1.0f - f) * saturation);
197 return new Vector4(value, n, l, 0.0f);
199 return new Vector4(m, value, l, 0.0f);
201 return new Vector4(l, value, n, 0.0f);
203 return new Vector4(l, m, value, 0.0f);
205 return new Vector4(n, l, value, 0.0f);
207 return new Vector4(value, l, m, 0.0f);
209 throw new Exception(
"Unable to convert HSV to RGB");
213 private static float ColorDivide(
float t1,
float t2)
227 return new Vector4(v1.
X * v2.
X, v1.
Y * v2.
Y, v1.
Z * v2.
Z, v1.
W * v2.
W);
233 ColorDivide(v1.
X, v2.
X),
234 ColorDivide(v1.
Y, v2.
Y),
235 ColorDivide(v1.
Z, v2.
Z),
236 ColorDivide(v1.
W, v2.
W)
242 return v1 + coeff * (v2 - v1);
247 return Math.Max(0.0f, Math.Min(
a, 1.0f));
260 var interColor = backColor + frontColor;
261 return BasicBlend(backColor, frontColor, interColor);
271 var interColor = 0.5f * (backColor + frontColor);
272 return BasicBlend(backColor, frontColor, interColor);
278 var frontSaturation = GetSaturation(frontColor);
279 if (frontSaturation < 1.0e-10)
281 interColor = GetValue(backColor) * Vector4.One;
285 interColor = HSVToRGB(GetHue(frontColor), GetSaturation(frontColor), GetValue(backColor));
287 interColor.W = BasicAlphaBlend(backColor.
W, frontColor.
W);
294 1.0f - ColorDivide(1.0f - backColor.
X, frontColor.
X),
295 1.0f - ColorDivide(1.0f - backColor.
Y, frontColor.
Y),
296 1.0f - ColorDivide(1.0f - backColor.
Z, frontColor.
Z),
297 1.0f - ColorDivide(1.0f - backColor.
W, frontColor.
W)
303 var frontColor3 =
new Vector3(frontColor.
X, frontColor.
Y, frontColor.
Z);
304 var interColor =
new Vector4();
307 interColor.X = backColor.X == 1.0f ? 1.0f : 0.0f;
308 interColor.Y = backColor.Y == 1.0f ? 1.0f : 0.0f;
309 interColor.Z = backColor.Z == 1.0f ? 1.0f : 0.0f;
313 interColor = TermDivide(backColor,
Vector4.
One - frontColor);
314 interColor.X =
Saturate(interColor.X);
315 interColor.Y =
Saturate(interColor.Y);
316 interColor.Z =
Saturate(interColor.Z);
318 return BasicBlend(backColor, frontColor, interColor);
324 var alphaBack = backColor.W * backColor;
325 var alphaFront = frontColor.W * frontColor;
326 var interColor0 = Lerp(alphaBack, frontColor, frontColor.W);
327 var interColor1 = Lerp(alphaFront, backColor, backColor.W);
329 Math.Min(interColor0.X, interColor1.X),
330 Math.Min(interColor0.Y, interColor1.Y),
331 Math.Min(interColor0.Z, interColor1.Z),
332 BasicAlphaBlend(backColor.W, frontColor.W)
349 var interColor = TermMultiply(backColor,
Vector4.
One - frontColor.
W * frontColor);
350 interColor.W = backColor.W;
357 var interColor = frontColor - backColor;
358 interColor.X = Math.Abs(interColor.X);
359 interColor.Y = Math.Abs(interColor.Y);
360 interColor.Z = Math.Abs(interColor.Z);
362 return BasicBlend(backColor, frontColor, interColor);
379 ColorDivide(backColor.
X, frontColor.
X),
380 ColorDivide(backColor.
Y, frontColor.
Y),
381 ColorDivide(backColor.
Z, frontColor.
Z),
384 interColor.W = BasicAlphaBlend(backColor.
W, frontColor.
W);
390 var interColor = backColor + frontColor - 2.0f * TermMultiply(backColor, frontColor);
391 return BasicBlend(backColor, frontColor, interColor);
397 frontColor.
X < 0.5f ? 0.0f : 1.0f,
398 frontColor.
Y < 0.5f ? 0.0f : 1.0f,
399 frontColor.
Z < 0.5f ? 0.0f : 1.0f,
402 var v1 = 2.0f * TermMultiply(frontColor, backColor);
404 var interColor = v1 - TermMultiply(step, v2 - v1);
405 return BasicBlend(backColor, frontColor, interColor);
411 frontColor.
X + backColor.
X < 1.0f ? 0.0f : 1.0f,
412 frontColor.
Y + backColor.
Y < 1.0f ? 0.0f : 1.0f,
413 frontColor.
Z + backColor.
Z < 1.0f ? 0.0f : 1.0f,
416 return BasicBlend(backColor, frontColor,
Vector4.
One - step);
422 if (GetSaturation(frontColor) < 1.0e-10)
424 interColor = GetValue(backColor) * Vector4.One;
428 interColor = HSVToRGB(GetHue(frontColor), GetSaturation(backColor), GetValue(backColor));
430 interColor.W = BasicAlphaBlend(backColor.
W, frontColor.
W);
436 var interColor = TermMultiply(backColor, 2.0f * frontColor.
W * frontColor + (1.0f - frontColor.
W) *
Vector4.
One);
437 interColor.W = backColor.W;
443 return backColor * frontColor.W;
449 var v1 = Lerp(backColor * backColor.
W, frontColor, frontColor.
W);
450 var v2 = Lerp(frontColor * frontColor.
W, backColor, backColor.
W);
452 Math.Max(v1.X, v2.X),
453 Math.Max(v1.Y, v2.Y),
454 Math.Max(v1.Z, v2.Z),
455 BasicAlphaBlend(backColor.
W, frontColor.
W)
472 var sum = frontColor + backColor;
474 sum.X > 1.0f ? sum.X - 1.0f : 0.0f,
475 sum.Y > 1.0f ? sum.Y - 1.0f : 0.0f,
476 sum.Z > 1.0f ? sum.Z - 1.0f : 0.0f,
479 return BasicBlend(backColor, frontColor, interColor);
490 return BasicBlend(backColor, frontColor, interColor);
495 return new Vector4(backColor.
X, backColor.
Y, backColor.
Z, backColor.
W * (frontColor.
X + frontColor.
Y + frontColor.
Z) / 3.0f);
501 var interColor = TermMultiply(backColor, frontColor);
502 return BasicBlend(backColor, frontColor, interColor);
517 return new Vector4(backColor.
X, backColor.
Y, backColor.
Z, 1.0f);
522 return backColor * (1.0f - frontColor.W);
528 return BasicBlend(backColor, frontColor, frontColor);
539 var lerp0 = 2.0f * TermMultiply(backColor, frontColor);
540 var lerp1 = Vector4.One - 2.0f * TermMultiply(
Vector4.
One - backColor,
Vector4.
One - frontColor);
542 var stepX = frontColor.X < 0.5f ? 0.0f : 1.0f;
543 var stepY = frontColor.Y < 0.5f ? 0.0f : 1.0f;
544 var stepZ = frontColor.Z < 0.5f ? 0.0f : 1.0f;
545 var stepW = frontColor.W < 0.5f ? 0.0f : 1.0f;
548 lerp0.X + stepX * (lerp1.X - lerp0.X),
549 lerp0.Y + stepY * (lerp1.Y - lerp0.Y),
550 lerp0.Z + stepZ * (lerp1.Z - lerp0.Z),
551 lerp0.W + stepW * (lerp1.W - lerp0.W)
557 var v1 = 2.0f * frontColor;
559 Math.Max(backColor.
X, v1.X - 1.0f),
560 Math.Max(backColor.Y, v1.Y - 1.0f),
561 Math.Max(backColor.
Z, v1.Z - 1.0f),
565 Math.Min(backColor.
X, v1.X),
566 Math.Min(backColor.Y, v1.Y),
567 Math.Min(backColor.
Z, v1.Z),
571 frontColor.
X < 0.5f ? 1.0f : 0.0f,
572 frontColor.
Y < 0.5f ? 1.0f : 0.0f,
573 frontColor.
Z < 0.5f ? 1.0f : 0.0f,
576 var interColor = max + TermMultiply(step, min - max);
577 return BasicBlend(backColor, frontColor, interColor);
582 var interColor = TermMultiply(backColor,
Vector4.
One + (frontColor * frontColor.
W));
583 interColor.W = backColor.W;
590 if (GetSaturation(backColor) < 1.0e-10)
592 interColor = GetValue(backColor) * Vector4.One;
596 interColor = HSVToRGB(GetHue(backColor), GetSaturation(frontColor), GetValue(backColor));
598 interColor.W = BasicAlphaBlend(backColor.
W, frontColor.
W);
604 var v1 = backColor.W * backColor;
605 var interColor = TermMultiply(frontColor * frontColor.
W,
Vector4.
One - v1) + v1;
606 interColor.W = BasicAlphaBlend(backColor.W, frontColor.
W);
610 private static float SoftLightTest(
float bc,
float fc)
613 return bc * (1.0f + (1.0f - bc) * (2.0f * fc - 1.0f));
614 if (bc < 9.0f / 64.0f)
615 return bc * (bc * (9.0f - 18.0f * fc) + 5.76f * fc - 1.88f);
616 return bc + ((float)Math.Sqrt(bc) - bc) * (2.0f * fc - 1.0f);
622 SoftLightTest(backColor.
X, frontColor.
X),
623 SoftLightTest(backColor.
Y, frontColor.
Y),
624 SoftLightTest(backColor.
Z, frontColor.
Z),
625 BasicAlphaBlend(backColor.
W, frontColor.
W));
631 var interColor = backColor - frontColor;
632 return BasicBlend(backColor, frontColor, interColor);
642 var interColor = backColor;
643 interColor.W = frontColor.W;
650 if (GetSaturation(backColor) < 1.0e-10)
651 interColor = GetValue(backColor) * Vector4.One;
654 interColor = HSVToRGB(GetHue(backColor), GetValue(backColor), GetValue(frontColor));
656 interColor.W = BasicAlphaBlend(backColor.
W, frontColor.
W);
Hue effect from the two textures.
float W
The W component of the vector.
Screen effect from the two textures.
Average of the two textures.
Illuminate effect from the two textures.
Subtract the two textures.
float X
The X component of the vector.
Apply mask from second texture to the first one.
Over effect from the two textures.
Color burn effect from the two textures.
Represents a three dimensional mathematical vector.
Take color for the first texture but alpha from the second
static readonly Vector3 One
A SiliconStudio.Core.Mathematics.Vector3 with all of its components set to one.
Take color for the first texture and use alpha = 1
Represents a color in the form of rgba.
Saturation effect from the two textures.
MaterialBinaryOperand
Operands of the MaterialNode.
Represents a four dimensional mathematical vector.
SiliconStudio.Core.Mathematics.Color Color
Search for out only dependencies.
Saturate effect from the two textures.
Exclusion effect from the two textures.
Vector4 ToVector4()
Converts the color into a four component vector.
Overlay effect from the two textures.
Soft light effect from the two textures.
Hard light effect from the two textures.
Linear dodge effect from the two textures.
float Y
The Y component of the vector.
Desaturate effect from the two textures.
Linear burn effect from the two textures.
SiliconStudio.Core.Mathematics.Vector3 Vector3
Search for in only dependencies.
float Z
The Z component of the vector.
Difference of the two textures.
hard mix effect from the two textures.
Pin light effect from the two textures.
static readonly Vector4 One
A SiliconStudio.Core.Mathematics.Vector4 with all of its components set to one.
Color dodge effect from the two textures.
Darken effect from the two textures.
Lighten effect from the two textures.