You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

806 lines
34 KiB

using System;
using System.Linq;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.VFX;
namespace UnityEditor.VFX
{
static class VFXOperatorUtility
{
public static Dictionary<VFXValueType, VFXExpression> GenerateExpressionConstant(float baseValue)
{
return new Dictionary<VFXValueType, VFXExpression>()
{
{ VFXValueType.Float, VFXValue.Constant(baseValue) },
{ VFXValueType.Float2, VFXValue.Constant(Vector2.one * baseValue) },
{ VFXValueType.Float3, VFXValue.Constant(Vector3.one * baseValue) },
{ VFXValueType.Float4, VFXValue.Constant(Vector4.one * baseValue) },
{ VFXValueType.Int32, VFXValue.Constant((int)baseValue) },
{ VFXValueType.Uint32, VFXValue.Constant((uint)baseValue) }
};
}
public static readonly VFXExpression TrueExpression = VFXValue.Constant(true);
public static readonly VFXExpression FalseExpression = VFXValue.Constant(false);
public static readonly Dictionary<VFXValueType, VFXExpression> OneExpression = GenerateExpressionConstant(1.0f);
public static readonly Dictionary<VFXValueType, VFXExpression> MinusOneExpression = GenerateExpressionConstant(-1.0f);
public static readonly Dictionary<VFXValueType, VFXExpression> HalfExpression = GenerateExpressionConstant(0.5f);
public static readonly Dictionary<VFXValueType, VFXExpression> ZeroExpression = GenerateExpressionConstant(0.0f);
public static readonly Dictionary<VFXValueType, VFXExpression> NaNExpression = GenerateExpressionConstant(float.NaN);
public static readonly Dictionary<VFXValueType, VFXExpression> TwoExpression = GenerateExpressionConstant(2.0f);
public static readonly Dictionary<VFXValueType, VFXExpression> ThreeExpression = GenerateExpressionConstant(3.0f);
public static readonly Dictionary<VFXValueType, VFXExpression> TenExpression = GenerateExpressionConstant(10.0f);
public static readonly Dictionary<VFXValueType, VFXExpression> PiExpression = GenerateExpressionConstant(Mathf.PI);
public static readonly Dictionary<VFXValueType, VFXExpression> TauExpression = GenerateExpressionConstant(2.0f * Mathf.PI);
public static readonly Dictionary<VFXValueType, VFXExpression> E_NapierConstantExpression = GenerateExpressionConstant(Mathf.Exp(1));
public static readonly Dictionary<VFXValueType, VFXExpression> EpsilonExpression = GenerateExpressionConstant(1e-5f);
public static readonly Dictionary<VFXValueType, VFXExpression> EpsilonSqrExpression = GenerateExpressionConstant(1e-10f);
public enum Base
{
Base2,
Base10,
BaseE,
}
static private VFXExpression BaseToConstant(Base _base, VFXValueType type)
{
switch (_base)
{
case Base.Base2: return TwoExpression[type];
case Base.Base10: return TenExpression[type];
case Base.BaseE: return E_NapierConstantExpression[type];
default:
throw new NotImplementedException();
}
}
static public VFXExpression Negate(VFXExpression input)
{
var minusOne = MinusOneExpression[input.valueType];
return (minusOne * input);
}
static public VFXExpression Reciprocal(VFXExpression input)
{
return OneExpression[input.valueType] / input;
}
static public VFXExpression Mad(VFXExpression input, VFXExpression scale, VFXExpression bias)
{
return input * scale + bias;
}
static public VFXExpression Clamp(VFXExpression input, VFXExpression min, VFXExpression max)
{
return Clamp(input, min, max, true);
}
static public VFXExpression Clamp(VFXExpression input, VFXExpression min, VFXExpression max, bool autoCast)
{
//Max(Min(x, max), min))
if (autoCast)
{
min = CastFloat(min, input.valueType);
max = CastFloat(max, input.valueType);
}
var maxExp = new VFXExpressionMax(input, min);
return new VFXExpressionMin(maxExp, max);
}
static public VFXExpression Saturate(VFXExpression input)
{
//Max(Min(x, 1.0f), 0.0f))
return new VFXExpressionSaturate(input);
}
static public VFXExpression Frac(VFXExpression input)
{
//x - floor(x)
return new VFXExpressionFrac(input);
}
static public VFXExpression Ceil(VFXExpression input)
{
// ceil(x) = -floor(-x)
return new VFXExpressionCeil(input);
}
static public VFXExpression Round(VFXExpression input)
{
//x = floor(x + 0.5)
return new VFXExpressionRound(input);
}
static public VFXExpression Log(VFXExpression input, VFXExpression _base)
{
//log2(x)/log2(b)
return new VFXExpressionLog2(input) / new VFXExpressionLog2(_base);
}
static public VFXExpression Log(VFXExpression input, Base _base)
{
return Log(input, BaseToConstant(_base, input.valueType));
}
static public VFXExpression Exp(VFXExpression input, Base _base)
{
return new VFXExpressionPow(BaseToConstant(_base, input.valueType), input);
}
static public VFXExpression SnapToClosestPowerOfBase(VFXExpression input, VFXExpression _base)
{
var exactPower = Log(input, _base);
var nextPower = Round(exactPower);
return new VFXExpressionPow(_base, nextPower);
}
static public VFXExpression Atanh(VFXExpression input)
{
//0.5*Log((1+x)/(1-x), e)
var half = HalfExpression[input.valueType];
var one = OneExpression[input.valueType];
var e = E_NapierConstantExpression[input.valueType];
return half * Log((one + input) / (one - input), e);
}
static public VFXExpression SinH(VFXExpression input)
{
//0.5*(e^x - e^-x)
var half = HalfExpression[input.valueType];
var minusOne = MinusOneExpression[input.valueType];
var e = E_NapierConstantExpression[input.valueType];
return half * (new VFXExpressionPow(e, input) - new VFXExpressionPow(e, minusOne * input));
}
static public VFXExpression CosH(VFXExpression input)
{
//0.5*(e^x + e^-x)
var half = HalfExpression[input.valueType];
var minusOne = MinusOneExpression[input.valueType];
var e = E_NapierConstantExpression[input.valueType];
return half * (new VFXExpressionPow(e, input) + new VFXExpressionPow(e, minusOne * input));
}
static public VFXExpression TanH(VFXExpression input)
{
//(1-e^2x)/(1+e^2x)
var two = TwoExpression[input.valueType];
var one = OneExpression[input.valueType];
var minusOne = MinusOneExpression[input.valueType];
var e = E_NapierConstantExpression[input.valueType];
var E_minusTwoX = new VFXExpressionPow(e, minusOne * two * input);
return (one - E_minusTwoX) / (one + E_minusTwoX);
}
static public VFXExpression VanDerCorputSequence(VFXExpression bits) //expect an uint return a float
{
bits = bits << 16 | bits >> 16;
bits = ((bits & 0x55555555u) << 1) | ((bits & 0xAAAAAAAA) >> 1);
bits = ((bits & 0x33333333u) << 2) | ((bits & 0xCCCCCCCC) >> 2);
bits = ((bits & 0x0F0F0F0Fu) << 4) | ((bits & 0xF0F0F0F0) >> 4);
bits = ((bits & 0x00FF00FFu) << 8) | ((bits & 0xFF00FF00) >> 8);
return new VFXExpressionCastUintToFloat(bits) * new VFXValue<float>(2.3283064365386963e-10f); // / 0x100000000;
}
static public VFXExpression Sqrt(VFXExpression input)
{
//pow(x, 0.5f)
return new VFXExpressionPow(input, HalfExpression[input.valueType]);
}
static public VFXExpression Dot(VFXExpression a, VFXExpression b)
{
//a.x*b.x + a.y*b.y + ...
var size = VFXExpression.TypeToSize(a.valueType);
if (a.valueType != b.valueType)
{
throw new ArgumentException(string.Format("Invalid Dot type input : {0} and {1}", a.valueType, b.valueType));
}
var mul = (a * b);
var sum = new Stack<VFXExpression>();
if (size == 1)
{
sum.Push(mul);
}
else
{
for (int iChannel = 0; iChannel < size; ++iChannel)
{
sum.Push(mul[iChannel]);
}
}
while (sum.Count > 1)
{
var top = sum.Pop();
var bottom = sum.Pop();
sum.Push(top + bottom);
}
return sum.Pop();
}
static public VFXExpression Cross(VFXExpression lhs, VFXExpression rhs)
{
return new VFXExpressionCombine(new[]
{
lhs.y * rhs.z - lhs.z * rhs.y,
lhs.z * rhs.x - lhs.x * rhs.z,
lhs.x * rhs.y - lhs.y * rhs.x,
});
}
static public VFXExpression Distance(VFXExpression x, VFXExpression y)
{
//length(a - b)
return Length(x - y);
}
static public VFXExpression SqrDistance(VFXExpression x, VFXExpression y)
{
//dot(a - b)
var delta = (x - y);
return Dot(delta, delta);
}
static public VFXExpression InverseLerp(VFXExpression x, VFXExpression y, VFXExpression s)
{
//(s - x)/(y - x)
return (s - x) / (y - x);
}
static public VFXExpression Lerp(VFXExpression x, VFXExpression y, VFXExpression s)
{
//x + s(y - x)
return (x + s * (y - x));
}
static public VFXExpression Length(VFXExpression v)
{
//sqrt(dot(v, v))
var dot = Dot(v, v);
return Sqrt(dot);
}
static public VFXExpression Normalize(VFXExpression v)
{
var invLength = (OneExpression[VFXValueType.Float] / Length(v));
var invLengthVector = CastFloat(invLength, v.valueType);
return (v * invLengthVector);
}
static public VFXExpression SafeNormalize(VFXExpression v)
{
var sqrDist = Dot(v, v);
var condition = new VFXExpressionCondition(VFXValueType.Float, VFXCondition.Less, sqrDist, VFXOperatorUtility.EpsilonSqrExpression[VFXValueType.Float]);
return new VFXExpressionBranch(condition, VFXOperatorUtility.ZeroExpression[v.valueType], Normalize(v));
}
static public VFXExpression Modulo(VFXExpression x, VFXExpression y)
{
if (VFXExpression.IsFloatValueType(x.valueType))
{
//fmod : frac(x / y) * y
return Frac(x / y) * y;
}
else
{
//Std 1152 If the quotient a/b is representable, the expression (a/b)*b + a%b shall equal a.
return x - (x / y) * y;
}
}
static public VFXExpression Fit(VFXExpression value, VFXExpression oldRangeMin, VFXExpression oldRangeMax, VFXExpression newRangeMin, VFXExpression newRangeMax)
{
//percent = (value - oldRangeMin) / (oldRangeMax - oldRangeMin)
//lerp(newRangeMin, newRangeMax, percent)
VFXExpression percent = (value - oldRangeMin) / (oldRangeMax - oldRangeMin);
return Lerp(newRangeMin, newRangeMax, percent);
}
static public VFXExpression Smoothstep(VFXExpression x, VFXExpression y, VFXExpression s)
{
var type = x.valueType;
var t = (s - x) / (y - x);
t = Clamp(t, ZeroExpression[type], OneExpression[type]);
var result = (ThreeExpression[type] - TwoExpression[type] * t);
result = (result * t);
result = (result * t);
return result;
}
static public VFXExpression Discretize(VFXExpression value, VFXExpression granularity)
{
return new VFXExpressionFloor(value / granularity) * granularity;
}
static public VFXExpression ColorLuma(VFXExpression color)
{
//(0.299*R + 0.587*G + 0.114*B)
var coefficients = VFXValue.Constant(new Vector4(0.299f, 0.587f, 0.114f, 0.0f));
return Dot(color, coefficients);
}
static public VFXExpression DegToRad(VFXExpression degrees)
{
return (degrees * CastFloat(VFXValue.Constant(Mathf.PI / 180.0f), degrees.valueType));
}
static public VFXExpression RadToDeg(VFXExpression radians)
{
return (radians * CastFloat(VFXValue.Constant(180.0f / Mathf.PI), radians.valueType));
}
static public VFXExpression PolarToRectangular(VFXExpression theta, VFXExpression distance)
{
//x = cos(angle) * distance
//y = sin(angle) * distance
var result = new VFXExpressionCombine(new VFXExpression[] { new VFXExpressionCos(theta), new VFXExpressionSin(theta) });
return (result * CastFloat(distance, VFXValueType.Float2));
}
static public VFXExpression[] RectangularToPolar(VFXExpression coord)
{
//theta = atan2(coord.y, coord.x)
//distance = length(coord)
var theta = Atan2(coord);
var distance = Length(coord);
return new VFXExpression[] { theta, distance };
}
static public VFXExpression SphericalToRectangular(VFXExpression distance, VFXExpression theta, VFXExpression phi)
{
//x = cos(theta) * cos(phi) * distance
//y = sin(theta) * cos(phi) * distance
//z = sin(phi) * distance
var cosTheta = new VFXExpressionCos(theta);
var cosPhi = new VFXExpressionCos(phi);
var sinTheta = new VFXExpressionSin(theta);
var sinPhi = new VFXExpressionSin(phi);
var x = (cosTheta * cosPhi);
var y = sinPhi;
var z = (sinTheta * cosPhi);
var result = new VFXExpressionCombine(new VFXExpression[] { x, y, z });
return (result * CastFloat(distance, VFXValueType.Float3));
}
static public VFXExpression[] RectangularToSpherical(VFXExpression coord)
{
//distance = length(coord)
//theta = atan2(z, x)
//phi = asin(y / distance)
var components = ExtractComponents(coord).ToArray();
var distance = Length(coord);
var theta = new VFXExpressionATan2(components[2], components[0]);
var phi = new VFXExpressionASin(components[1] / distance);
return new VFXExpression[] { distance, theta, phi };
}
static public VFXExpression CircleArea(VFXExpression radius, VFXExpression scale = null)
{
//pi * r * r
var pi = VFXValue.Constant(Mathf.PI);
var area = pi * radius * radius;
if (scale != null) //Circle are inside z=0 plane
{
scale = new VFXExpressionAbs(scale);
area = area * scale.x * scale.y;
}
return area;
}
static public VFXExpression CircleCircumference(VFXExpression radius)
{
//2 * pi * r
var two = VFXValue.Constant(2.0f);
var pi = VFXValue.Constant(Mathf.PI);
return (two * pi * radius);
}
static public VFXExpression BoxVolume(VFXExpression dimensions)
{
//x * y * z
var components = ExtractComponents(dimensions).ToArray();
return (components[0] * components[1] * components[2]);
}
static public VFXExpression SphereVolume(VFXExpression radius, VFXExpression scale = null)
{
//(4 / 3) * pi * r * r * r
var multiplier = VFXValue.Constant((4.0f / 3.0f) * Mathf.PI);
var volume = (multiplier * radius * radius * radius);
if (scale != null)
{
scale = new VFXExpressionAbs(scale);
volume = volume * scale.x * scale.y * scale.z;
}
return volume;
}
static public VFXExpression ConeVolume(VFXExpression radius0, VFXExpression radius1, VFXExpression height, VFXExpression scale = null)
{
//pi/3 * (r0 * r0 + r0 * r1 + r1 * r1) * h
var piOver3 = VFXValue.Constant(Mathf.PI / 3.0f);
var r0r0 = (radius0 * radius0);
var r0r1 = (radius0 * radius1);
var r1r1 = (radius1 * radius1);
var result = (r0r0 + r0r1 + r1r1);
var volume = (piOver3 * result * height);
if (scale != null)
{
scale = new VFXExpressionAbs(scale);
volume = volume * scale.x * scale.y * scale.z;
}
return volume;
}
static public VFXExpression TorusVolume(VFXExpression majorRadius, VFXExpression minorRadius, VFXExpression scale = null)
{
//(pi * r * r) * (2 * pi * R)
var volume = CircleArea(minorRadius) * CircleCircumference(majorRadius);
if (scale != null)
{
scale = new VFXExpressionAbs(scale);
volume = volume * scale.x * scale.y * scale.z;
}
return volume;
}
static public VFXExpression SignedDistanceToPlane(VFXExpression planePosition, VFXExpression planeNormal, VFXExpression position)
{
VFXExpression d = Dot(planePosition, planeNormal);
return Dot(position, planeNormal) - d;
}
static public VFXExpression GammaToLinear(VFXExpression gamma)
{
var components = ExtractComponents(gamma).ToArray();
if (components.Length != 3 && components.Length != 4)
throw new ArgumentException("input expression must be a 3 or 4 components vector");
VFXExpression exp = VFXValue.Constant(2.2f);
for (int i = 0; i < 3; ++i)
components[i] = new VFXExpressionPow(components[i], exp);
return new VFXExpressionCombine(components);
}
static public VFXExpression LinearToGamma(VFXExpression linear)
{
var components = ExtractComponents(linear).ToArray();
if (components.Length != 3 && components.Length != 4)
throw new ArgumentException("input expression must be a 3 or 4 components vector");
VFXExpression exp = VFXValue.Constant(1.0f / 2.2f);
for (int i = 0; i < 3; ++i)
components[i] = new VFXExpressionBranch(
new VFXExpressionCondition(VFXValueType.Float, VFXCondition.Greater,components[i], ZeroExpression[VFXValueType.Float]),
new VFXExpressionPow(components[i], exp),
ZeroExpression[VFXValueType.Float]);
return new VFXExpressionCombine(components);
}
static public IEnumerable<VFXExpression> ExtractComponents(VFXExpression expression)
{
if (expression.valueType == VFXValueType.Float)
{
return new[] { expression };
}
var components = new List<VFXExpression>();
for (int i = 0; i < VFXExpression.TypeToSize(expression.valueType); ++i)
{
components.Add(expression[i]);
}
return components;
}
static public VFXExpression CastFloat(VFXExpression from, VFXValueType toValueType, float defaultValue = 0.0f)
{
if (!VFXExpressionNumericOperation.IsFloatValueType(from.valueType) || !VFXExpressionNumericOperation.IsFloatValueType(toValueType))
{
throw new ArgumentException(string.Format("Invalid CastFloat : {0} to {1}", from, toValueType));
}
if (from.valueType == toValueType)
{
return from;
}
var fromValueType = from.valueType;
var fromValueTypeSize = VFXExpression.TypeToSize(fromValueType);
var toValueTypeSize = VFXExpression.TypeToSize(toValueType);
var inputComponent = new VFXExpression[fromValueTypeSize];
var outputComponent = new VFXExpression[toValueTypeSize];
if (inputComponent.Length == 1)
{
inputComponent[0] = from;
}
else
{
for (int iChannel = 0; iChannel < fromValueTypeSize; ++iChannel)
{
inputComponent[iChannel] = from[iChannel];
}
}
for (int iChannel = 0; iChannel < toValueTypeSize; ++iChannel)
{
if (iChannel < fromValueTypeSize)
{
outputComponent[iChannel] = inputComponent[iChannel];
}
else if (fromValueTypeSize == 1)
{
//Manage same logic behavior for float => floatN in HLSL
outputComponent[iChannel] = inputComponent[0];
}
else
{
outputComponent[iChannel] = VFXValue.Constant(defaultValue);
}
}
if (toValueTypeSize == 1)
{
return outputComponent[0];
}
var combine = new VFXExpressionCombine(outputComponent);
return combine;
}
static public VFXExpression BuildRandom(VFXSeedMode seedMode, bool constant, RandId randId, VFXExpression seed = null)
{
if (seedMode == VFXSeedMode.PerParticleStrip || constant)
{
if (seed == null)
throw new ArgumentNullException("seed");
return FixedRandom(seed, seedMode);
}
return new VFXExpressionRandom(seedMode == VFXSeedMode.PerParticle, randId);
}
static public VFXExpression FixedRandom(uint hash, VFXSeedMode mode)
{
return FixedRandom(VFXValue.Constant<uint>(hash), mode);
}
static public VFXExpression FixedRandom(VFXExpression hash, VFXSeedMode mode)
{
VFXExpression seed = new VFXExpressionBitwiseXor(hash, VFXBuiltInExpression.SystemSeed);
if (mode != VFXSeedMode.PerVFXComponent)
seed = new VFXExpressionBitwiseXor(new VFXAttributeExpression(mode == VFXSeedMode.PerParticle ? VFXAttribute.ParticleId : VFXAttribute.StripIndex), seed);
return new VFXExpressionFixedRandom(seed);
}
public enum SequentialAddressingMode
{
Wrap,
Clamp,
Mirror
};
static public VFXExpression ApplyAddressingMode(VFXExpression index, VFXExpression count, SequentialAddressingMode mode)
{
VFXExpression r = null;
count = new VFXExpressionMax(count, OneExpression[VFXValueType.Uint32]);
if (mode == SequentialAddressingMode.Wrap)
{
r = Modulo(index, count);
}
else if (mode == SequentialAddressingMode.Clamp)
{
var countMinusOne = count - OneExpression[VFXValueType.Uint32];
r = new VFXExpressionMin(index, countMinusOne);
}
else if (mode == SequentialAddressingMode.Mirror)
{
var two = TwoExpression[VFXValueType.Uint32];
var cycle = count * two - two;
cycle = new VFXExpressionMax(cycle, OneExpression[VFXValueType.Uint32]);
var modulo = Modulo(index, cycle);
//var compare = new VFXExpressionCondition(VFXCondition.Less, new VFXExpressionCastUintToFloat(modulo), new VFXExpressionCastUintToFloat(count)); <= Use this line for 7.x.x/8.x.x/9.x.x backport
var compare = new VFXExpressionCondition(VFXValueType.Uint32, VFXCondition.Less, modulo, count);
r = new VFXExpressionBranch(compare, modulo, cycle - modulo);
}
return r;
}
static public VFXExpression SequentialLine(VFXExpression start, VFXExpression end, VFXExpression index, VFXExpression count, SequentialAddressingMode mode)
{
VFXExpression dt = ApplyAddressingMode(index, count, mode);
dt = new VFXExpressionCastUintToFloat(dt);
var size = new VFXExpressionCastUintToFloat(count) - VFXOperatorUtility.OneExpression[VFXValueType.Float];
size = new VFXExpressionMax(size, VFXOperatorUtility.OneExpression[VFXValueType.Float]);
dt = dt / size;
dt = new VFXExpressionCombine(dt, dt, dt);
return VFXOperatorUtility.Lerp(start, end, dt);
}
static public VFXExpression SequentialCircle(VFXExpression center, VFXExpression radius, VFXExpression normal, VFXExpression up, VFXExpression index, VFXExpression count, SequentialAddressingMode mode)
{
VFXExpression countForAddressing = count;
if (mode == SequentialAddressingMode.Clamp || mode == SequentialAddressingMode.Mirror)
{
//Explicitly close the circle loop, if `index` equals to `count`, adds an extra step.
countForAddressing = count + OneExpression[VFXValueType.Uint32];
}
VFXExpression dt = ApplyAddressingMode(index, countForAddressing, mode);
dt = new VFXExpressionCastUintToFloat(dt);
dt = dt / new VFXExpressionCastUintToFloat(count);
var cos = new VFXExpressionCos(dt * VFXOperatorUtility.TauExpression[VFXValueType.Float]) as VFXExpression;
var sin = new VFXExpressionSin(dt * VFXOperatorUtility.TauExpression[VFXValueType.Float]) as VFXExpression;
var left = VFXOperatorUtility.Normalize(VFXOperatorUtility.Cross(normal, up));
radius = new VFXExpressionCombine(radius, radius, radius);
sin = new VFXExpressionCombine(sin, sin, sin);
cos = new VFXExpressionCombine(cos, cos, cos);
return center + (cos * up + sin * left) * radius;
}
static public VFXExpression Sequential3D(VFXExpression origin, VFXExpression axisX, VFXExpression axisY, VFXExpression axisZ, VFXExpression index, VFXExpression countX, VFXExpression countY, VFXExpression countZ, SequentialAddressingMode mode)
{
index = ApplyAddressingMode(index, countX * countY * countZ, mode);
var z = new VFXExpressionCastUintToFloat(VFXOperatorUtility.Modulo(index, countZ));
var y = new VFXExpressionCastUintToFloat(VFXOperatorUtility.Modulo(index / countZ, countY));
var x = new VFXExpressionCastUintToFloat(index / (countY * countZ));
VFXExpression volumeSize = new VFXExpressionCombine(new VFXExpressionCastUintToFloat(countX), new VFXExpressionCastUintToFloat(countY), new VFXExpressionCastUintToFloat(countZ));
volumeSize = volumeSize - VFXOperatorUtility.OneExpression[VFXValueType.Float3];
var scaleAxisZero = Saturate(volumeSize); //Handle special case for one count => lead to be centered on origin (instead of -axis)
volumeSize = new VFXExpressionMax(volumeSize, VFXOperatorUtility.OneExpression[VFXValueType.Float3]);
var dt = new VFXExpressionCombine(x, y, z) / volumeSize;
dt = dt * VFXOperatorUtility.TwoExpression[VFXValueType.Float3] - VFXOperatorUtility.OneExpression[VFXValueType.Float3];
var r = origin;
r += dt.xxx * scaleAxisZero.xxx * axisX;
r += dt.yyy * scaleAxisZero.yyy * axisY;
r += dt.zzz * scaleAxisZero.zzz * axisZ;
return r;
}
static public VFXExpression GetPerspectiveMatrix(VFXExpression fov, VFXExpression aspect, VFXExpression zNear, VFXExpression zFar, VFXExpression lensShift)
{
var fovHalf = fov / TwoExpression[VFXValueType.Float];
var cotangent = new VFXExpressionCos(fovHalf) / new VFXExpressionSin(fovHalf);
var deltaZ = zNear - zFar;
var minusTwoExp = MinusOneExpression[VFXValueType.Float] * TwoExpression[VFXValueType.Float];
var zero = ZeroExpression[VFXValueType.Float];
var r0 = new VFXExpressionCombine(cotangent / aspect, zero, minusTwoExp * lensShift.x, zero);
var r1 = new VFXExpressionCombine(zero, cotangent, minusTwoExp * lensShift.y, zero);
var r2 = new VFXExpressionCombine(zero, zero, MinusOneExpression[VFXValueType.Float] * (zFar + zNear) / deltaZ, TwoExpression[VFXValueType.Float] * zNear * zFar / deltaZ);
var r3 = new VFXExpressionCombine(zero, zero, OneExpression[VFXValueType.Float], zero);
return new VFXExpressionRowToMatrix(r0, r1, r2, r3);
}
static public VFXExpression GetOrthographicMatrix(VFXExpression orthoSize, VFXExpression aspect, VFXExpression zNear, VFXExpression zFar)
{
var deltaZ = zNear - zFar;
var oneOverSize = OneExpression[VFXValueType.Float] / orthoSize;
var zero = ZeroExpression[VFXValueType.Float];
var r0 = new VFXExpressionCombine(oneOverSize / aspect, zero, zero, zero);
var r1 = new VFXExpressionCombine(zero, oneOverSize, zero, zero);
var r2 = new VFXExpressionCombine(zero, zero, MinusOneExpression[VFXValueType.Float] * TwoExpression[VFXValueType.Float] / deltaZ, (zFar + zNear) / deltaZ);
var r3 = new VFXExpressionCombine(zero, zero, zero, OneExpression[VFXValueType.Float]);
return new VFXExpressionRowToMatrix(r0, r1, r2, r3);
}
static public VFXExpression InverseTransposeTRS(VFXExpression matrix)
{
return new VFXExpressionTransposeMatrix(new VFXExpressionInverseTRSMatrix(matrix));
}
static public VFXExpression IsTRSMatrixZeroScaled(VFXExpression matrix)
{
var i = new VFXExpressionMatrixToAxis(matrix, VFXValue.Constant(0));
var j = new VFXExpressionMatrixToAxis(matrix, VFXValue.Constant(1));
var k = new VFXExpressionMatrixToAxis(matrix, VFXValue.Constant(2));
var sqrLengthI = Dot(i, i);
var sqrLengthJ = Dot(j, j);
var sqrLengthK = Dot(k, k);
var epsilon = EpsilonSqrExpression[VFXValueType.Float];
var compareI = new VFXExpressionCondition(VFXValueType.Float, VFXCondition.Less, sqrLengthI, epsilon);
var compareJ = new VFXExpressionCondition(VFXValueType.Float, VFXCondition.Less, sqrLengthJ, epsilon);
var compareK = new VFXExpressionCondition(VFXValueType.Float, VFXCondition.Less, sqrLengthK, epsilon);
var condition = new VFXExpressionLogicalOr(compareI, new VFXExpressionLogicalOr(compareJ, compareK));
return condition;
}
static public VFXExpression IsTRSMatrixUniformScaled(VFXExpression matrix)
{
var i = new VFXExpressionMatrixToAxis(matrix, VFXValue.Constant(0));
var j = new VFXExpressionMatrixToAxis(matrix, VFXValue.Constant(1));
var k = new VFXExpressionMatrixToAxis(matrix, VFXValue.Constant(2));
var sqrLengthI = Dot(i, i);
var sqrLengthJ = Dot(j, j);
var sqrLengthK = Dot(k, k);
// Same check as in Matrix4x4.cpp
var maxSqrLength = Max3(sqrLengthI, sqrLengthJ, sqrLengthK);
var minSqrLength = Min3(sqrLengthI, sqrLengthJ, sqrLengthK);
var ratio = Sqrt(maxSqrLength) / Sqrt(minSqrLength);
var condition = new VFXExpressionCondition(VFXValueType.Float, VFXCondition.Less, ratio, VFXValue.Constant(1.0f) + EpsilonExpression[VFXValueType.Float]);
return condition;
}
static public VFXExpression Atan2(VFXExpression coord)
{
var components = ExtractComponents(coord).ToArray();
var theta = new VFXExpressionATan2(components[1], components[0]);
return theta;
}
static public VFXExpression Max3(VFXExpression x, VFXExpression y, VFXExpression z)
{
return new VFXExpressionMax(new VFXExpressionMax(x, y), z);
}
static public VFXExpression Max3(VFXExpression vector3)
{
var x = new VFXExpressionExtractComponent(vector3, 0);
var y = new VFXExpressionExtractComponent(vector3, 1);
var z = new VFXExpressionExtractComponent(vector3, 2);
return Max3(x, y, z);
}
static public VFXExpression Min3(VFXExpression x, VFXExpression y, VFXExpression z)
{
return new VFXExpressionMin(new VFXExpressionMin(x, y), z);
}
static public VFXExpression Min3(VFXExpression vector3)
{
var x = new VFXExpressionExtractComponent(vector3, 0);
var y = new VFXExpressionExtractComponent(vector3, 1);
var z = new VFXExpressionExtractComponent(vector3, 2);
return Min3(x, y, z);
}
static public VFXExpression UniformScaleMatrix(VFXExpression scale)
{
var scale3 = new VFXExpressionCombine(scale, scale, scale);
var zero = ZeroExpression[VFXValueType.Float3];
return new VFXExpressionTRSToMatrix(zero, zero, scale3);
}
static public VFXExpression TextureFormatEquals(VFXExpression texture, TextureFormat format)
{
var textureFormat = new VFXExpressionTextureFormat(texture);
return new VFXExpressionCondition(VFXValueType.Uint32, VFXCondition.Equal,
textureFormat, VFXValue.Constant((uint)format));
}
}
}