private static void TestConditions(float f0, float f1) { var f0Exp = VFXValue.Constant(f0); var f1Exp = VFXValue.Constant(f1); var equalExp = new VFXExpressionCondition(VFXCondition.Equal, f0Exp, f1Exp); var notEqualExp = new VFXExpressionCondition(VFXCondition.NotEqual, f0Exp, f1Exp); var lessExp = new VFXExpressionCondition(VFXCondition.Less, f0Exp, f1Exp); var lessOrEqualExp = new VFXExpressionCondition(VFXCondition.LessOrEqual, f0Exp, f1Exp); var greater = new VFXExpressionCondition(VFXCondition.Greater, f0Exp, f1Exp); var greaterOrEqual = new VFXExpressionCondition(VFXCondition.GreaterOrEqual, f0Exp, f1Exp); var context = new VFXExpression.Context(VFXExpressionContextOption.CPUEvaluation); var resultA = context.Compile(equalExp); var resultB = context.Compile(notEqualExp); var resultC = context.Compile(lessExp); var resultD = context.Compile(lessOrEqualExp); var resultE = context.Compile(greater); var resultF = context.Compile(greaterOrEqual); Assert.AreEqual(f0 == f1, resultA.Get <bool>()); Assert.AreEqual(f0 != f1, resultB.Get <bool>()); Assert.AreEqual(f0 < f1, resultC.Get <bool>()); Assert.AreEqual(f0 <= f1, resultD.Get <bool>()); Assert.AreEqual(f0 > f1, resultE.Get <bool>()); Assert.AreEqual(f0 >= f1, resultF.Get <bool>()); }
public static IEnumerable <VFXExpression> SampleEdgeAttribute(VFXExpression source, VFXExpression index, VFXExpression lerp, IEnumerable <VertexAttribute> vertexAttributes) { bool skinnedMesh = source.valueType == UnityEngine.VFX.VFXValueType.SkinnedMeshRenderer; var mesh = !skinnedMesh ? source : new VFXExpressionMeshFromSkinnedMeshRenderer(source); var meshIndexFormat = new VFXExpressionMeshIndexFormat(mesh); var oneInt = VFXOperatorUtility.OneExpression[UnityEngine.VFX.VFXValueType.Int32]; var oneUint = VFXOperatorUtility.OneExpression[UnityEngine.VFX.VFXValueType.Uint32]; var threeUint = VFXOperatorUtility.ThreeExpression[UnityEngine.VFX.VFXValueType.Uint32]; var nextIndex = index + oneUint; //Loop triangle var loop = VFXOperatorUtility.Modulo(nextIndex, threeUint); var predicat = new VFXExpressionCondition(UnityEngine.VFX.VFXValueType.Uint32, VFXCondition.NotEqual, loop, VFXOperatorUtility.ZeroExpression[UnityEngine.VFX.VFXValueType.Uint32]); nextIndex = new VFXExpressionBranch(predicat, nextIndex, nextIndex - threeUint); var sampledIndex_A = new VFXExpressionSampleIndex(mesh, index, meshIndexFormat); var sampledIndex_B = new VFXExpressionSampleIndex(mesh, nextIndex, meshIndexFormat); var sampling_A = SampleVertexAttribute(source, sampledIndex_A, vertexAttributes).ToArray(); var sampling_B = SampleVertexAttribute(source, sampledIndex_B, vertexAttributes).ToArray(); for (int i = 0; i < vertexAttributes.Count(); ++i) { var outputValueType = sampling_A[i].valueType; var s = VFXOperatorUtility.CastFloat(lerp, outputValueType); yield return(VFXOperatorUtility.Lerp(sampling_A[i], sampling_B[i], s)); } }
protected sealed override VFXExpression[] BuildExpression(VFXExpression[] inputExpression) { var expressionCountPerUniqueSlot = this.expressionCountPerUniqueSlot; if (!m_CustomCaseValue) { //Insert Case (0,1,..) entries manually var newInputExpression = new VFXExpression[1 /* entry */ + m_EntryCount * (expressionCountPerUniqueSlot + 1 /* case */) + expressionCountPerUniqueSlot /* default */]; newInputExpression[0] = inputExpression[0]; int offsetWrite = 1; int offsetRead = 1; for (int i = 0; i < m_EntryCount + 1; ++i) { if (i != m_EntryCount) { newInputExpression[offsetWrite++] = new VFXValue <int>(i); } for (int sub = 0; sub < expressionCountPerUniqueSlot; ++sub) { newInputExpression[offsetWrite++] = inputExpression[offsetRead++]; } } inputExpression = newInputExpression; } var referenceValue = inputExpression.First(); referenceValue = new VFXExpressionCastIntToFloat(referenceValue); var startCaseOffset = 1; var stride = expressionCountPerUniqueSlot + 1; var compare = new VFXExpression[m_EntryCount]; int offsetCase = startCaseOffset; var valueStartIndex = new int[m_EntryCount + 1]; for (uint i = 0; i < m_EntryCount; i++) { valueStartIndex[i] = offsetCase + 1; compare[i] = new VFXExpressionCondition(VFXCondition.Equal, referenceValue, new VFXExpressionCastIntToFloat(inputExpression[offsetCase])); offsetCase += stride; } valueStartIndex[m_EntryCount] = inputExpression.Length - expressionCountPerUniqueSlot; //Last is default value, without a case return(ChainedBranchResult(compare, inputExpression, valueStartIndex)); }
protected sealed override VFXExpression[] BuildExpression(VFXExpression[] inputExpression) { VFXExpression rand = null; if (m_IntegratedRandom) { if (m_Constant) { rand = VFXOperatorUtility.FixedRandom(inputExpression.Last(), m_Seed); } else { rand = new VFXExpressionRandom(m_Seed == VFXSeedMode.PerParticle, new RandId(this)); } } else { rand = inputExpression.Last(); } var expressionCountPerUniqueSlot = this.expressionCountPerUniqueSlot; var stride = expressionCountPerUniqueSlot + 1; var prefixedProbablities = new VFXExpression[m_EntryCount]; int offsetProbabilities = 0; prefixedProbablities[0] = inputExpression[offsetProbabilities]; for (uint i = 1; i < m_EntryCount; i++) { offsetProbabilities += stride; prefixedProbablities[i] = prefixedProbablities[i - 1] + inputExpression[offsetProbabilities]; } rand = rand * prefixedProbablities.Last(); var compare = new VFXExpression[m_EntryCount - 1]; for (int i = 0; i < m_EntryCount - 1; i++) { compare[i] = new VFXExpressionCondition(VFXValueType.Float, VFXCondition.GreaterOrEqual, prefixedProbablities[i], rand); } ; var startValueIndex = Enumerable.Range(0, (int)m_EntryCount).Select(o => o * stride + 1).ToArray(); return(ChainedBranchResult(compare, inputExpression, startValueIndex)); }
protected override VFXExpression[] BuildExpression(VFXExpression[] inputExpression) { // Offset to compensate for the numerous custom camera generated expressions _customCameraOffset = 0; // Get the extra number of expressions if a custom camera input is used if (camera == CameraMode.Custom) { _customCameraOffset = GetInputSlot(0).children.Count() - 1; } // List to gather all output expressions as their number can vary List <VFXExpression> outputs = new List <VFXExpression>(); // Camera expressions var expressions = Block.CameraHelper.AddCameraExpressions(GetExpressionsFromSlots(this), camera); Block.CameraMatricesExpressions camMatrices = Block.CameraHelper.GetMatricesExpressions(expressions); var Camera_depthBuffer = expressions.First(e => e.name == "Camera_depthBuffer").exp; var CamPixDim = expressions.First(e => e.name == "Camera_pixelDimensions").exp; // Set uvs VFXExpression uv = VFXValue.Constant <Vector2>(); // Determine how the particles are spawned on the screen switch (mode) { case PositionMode.Random: // Random UVs uv = new VFXExpressionCombine(VFXOperatorUtility.FixedRandom(0, VFXSeedMode.PerParticle), VFXOperatorUtility.FixedRandom(1, VFXSeedMode.PerParticle)); break; case PositionMode.Sequential: // Pixel perfect spawn VFXExpression gridStep = inputExpression[inputSlots.IndexOf(inputSlots.First(o => o.name == "GridStep")) + _customCameraOffset]; VFXExpression sSizeX = new VFXExpressionCastFloatToUint(CamPixDim.x / new VFXExpressionCastUintToFloat(gridStep)); VFXExpression sSizeY = new VFXExpressionCastFloatToUint(CamPixDim.y / new VFXExpressionCastUintToFloat(gridStep)); VFXExpression nbPixels = sSizeX * sSizeY; VFXExpression particleID = new VFXAttributeExpression(VFXAttribute.ParticleId); VFXExpression id = VFXOperatorUtility.Modulo(particleID, nbPixels); VFXExpression shift = new VFXExpressionBitwiseRightShift(gridStep, VFXValue.Constant <uint>(1)); VFXExpression U = VFXOperatorUtility.Modulo(id, sSizeX) * gridStep + shift; VFXExpression V = id / sSizeX * gridStep + shift; VFXExpression ids = new VFXExpressionCombine(new VFXExpressionCastUintToFloat(U), new VFXExpressionCastUintToFloat(V)); uv = new VFXExpressionDivide(ids + VFXOperatorUtility.CastFloat(VFXValue.Constant(0.5f), VFXValueType.Float2), CamPixDim); break; case PositionMode.Custom: // Custom UVs uv = inputExpression[inputSlots.IndexOf(inputSlots.FirstOrDefault(o => o.name == "UVSpawn")) + _customCameraOffset]; break; } VFXExpression projpos = uv * VFXValue.Constant <Vector2>(new Vector2(2f, 2f)) - VFXValue.Constant <Vector2>(Vector2.one); VFXExpression uvs = new VFXExpressionCombine(uv.x * CamPixDim.x, uv.y * CamPixDim.y, VFXValue.Constant(0f), VFXValue.Constant(0f)); // Get depth VFXExpression depth = new VFXExpressionExtractComponent(new VFXExpressionLoadTexture2DArray(Camera_depthBuffer, uvs), 0); if (SystemInfo.usesReversedZBuffer) { depth = VFXOperatorUtility.OneExpression[depth.valueType] - depth; } VFXExpression isAlive = VFXValue.Constant(true); // Determine how the particles are culled switch (cullMode) { case CullMode.None: // do nothing break; case CullMode.Range: VFXExpression depthRange = inputExpression[inputSlots.IndexOf(inputSlots.LastOrDefault(o => o.name == "DepthRange")) + _customCameraOffset]; VFXExpression nearRangeCheck = new VFXExpressionCondition(VFXCondition.Less, depth, depthRange.x); VFXExpression farRangeCheck = new VFXExpressionCondition(VFXCondition.Greater, depth, depthRange.y); VFXExpression logicOr = new VFXExpressionLogicalOr(nearRangeCheck, farRangeCheck); isAlive = new VFXExpressionBranch(logicOr, VFXValue.Constant(false), VFXValue.Constant(true)); break; case CullMode.FarPlane: VFXExpression farPlaneCheck = new VFXExpressionCondition(VFXCondition.GreaterOrEqual, depth, VFXValue.Constant(1f) - VFXValue.Constant(Mathf.Epsilon)); isAlive = new VFXExpressionBranch(farPlaneCheck, VFXValue.Constant(false), VFXValue.Constant(true)); break; } VFXExpression zMultiplier = inputExpression[inputSlots.IndexOf(inputSlots.First(o => o.name == "ZMultiplier")) + _customCameraOffset]; VFXExpression clipPos = new VFXExpressionCombine(projpos.x, projpos.y, depth * zMultiplier * VFXValue.Constant(2f) - VFXValue.Constant(1f), VFXValue.Constant(1f) ); VFXExpression clipToVFX = new VFXExpressionTransformMatrix(camMatrices.ViewToVFX.exp, camMatrices.ClipToView.exp); VFXExpression vfxPos = new VFXExpressionTransformVector4(clipToVFX, clipPos); VFXExpression position = new VFXExpressionCombine(vfxPos.x, vfxPos.y, vfxPos.z) / VFXOperatorUtility.CastFloat(vfxPos.w, VFXValueType.Float3); VFXExpression color = VFXValue.Constant <Vector4>(); // Assigning the color output to the corresponding color buffer value if (inheritSceneColor) { VFXExpression Camera_colorBuffer = expressions.First(e => e.name == "Camera_colorBuffer").exp; VFXExpression tempColor = new VFXExpressionLoadTexture2DArray(Camera_colorBuffer, uvs); color = new VFXExpressionCombine(tempColor.x, tempColor.y, tempColor.z, VFXValue.Constant(1.0f)); } // Add expressions in the right output order outputs.Add(position); if (inheritSceneColor) { outputs.Add(color); } if (cullMode != CullMode.None) { outputs.Add(isAlive); } return(outputs.ToArray()); }
public static IEnumerable <VFXExpression> SampleTriangleAttribute(VFXExpression source, VFXExpression triangleIndex, VFXExpression coord, SurfaceCoordinates coordMode, IEnumerable <VertexAttribute> vertexAttributes) { bool skinnedMesh = source.valueType == UnityEngine.VFX.VFXValueType.SkinnedMeshRenderer; var mesh = !skinnedMesh ? source : new VFXExpressionMeshFromSkinnedMeshRenderer(source); var meshIndexCount = new VFXExpressionMeshIndexCount(mesh); var meshIndexFormat = new VFXExpressionMeshIndexFormat(mesh); var threeUint = VFXOperatorUtility.ThreeExpression[UnityEngine.VFX.VFXValueType.Uint32]; var baseIndex = triangleIndex * threeUint; var sampledIndex_A = new VFXExpressionSampleIndex(mesh, baseIndex, meshIndexFormat); var sampledIndex_B = new VFXExpressionSampleIndex(mesh, baseIndex + VFXValue.Constant <uint>(1u), meshIndexFormat); var sampledIndex_C = new VFXExpressionSampleIndex(mesh, baseIndex + VFXValue.Constant <uint>(2u), meshIndexFormat); var allInputValues = new List <VFXExpression>(); var sampling_A = SampleVertexAttribute(source, sampledIndex_A, vertexAttributes).ToArray(); var sampling_B = SampleVertexAttribute(source, sampledIndex_B, vertexAttributes).ToArray(); var sampling_C = SampleVertexAttribute(source, sampledIndex_C, vertexAttributes).ToArray(); VFXExpression barycentricCoordinates = null; var one = VFXOperatorUtility.OneExpression[UnityEngine.VFX.VFXValueType.Float]; if (coordMode == SurfaceCoordinates.Barycentric) { var barycentricCoordinateInput = coord; barycentricCoordinates = new VFXExpressionCombine(barycentricCoordinateInput.x, barycentricCoordinateInput.y, one - barycentricCoordinateInput.x - barycentricCoordinateInput.y); } else if (coordMode == SurfaceCoordinates.Uniform) { //https://hal.archives-ouvertes.fr/hal-02073696v2/document var input = coord; var half2 = VFXOperatorUtility.HalfExpression[UnityEngine.VFX.VFXValueType.Float2]; var zero = VFXOperatorUtility.ZeroExpression[UnityEngine.VFX.VFXValueType.Float]; var t = input * half2; var offset = t.y - t.x; var pred = new VFXExpressionCondition(UnityEngine.VFX.VFXValueType.Float, VFXCondition.Greater, offset, zero); var t2 = new VFXExpressionBranch(pred, t.y + offset, t.y); var t1 = new VFXExpressionBranch(pred, t.x, t.x - offset); var t3 = one - t2 - t1; barycentricCoordinates = new VFXExpressionCombine(t1, t2, t3); /* Possible variant See http://inis.jinr.ru/sl/vol1/CMC/Graphics_Gems_1,ed_A.Glassner.pdf (p24) uniform distribution from two numbers in triangle generating barycentric coordinate * var input = VFXOperatorUtility.Saturate(inputExpression[2]); * var s = input.x; * var t = VFXOperatorUtility.Sqrt(input.y); * var a = one - t; * var b = (one - s) * t; * var c = s * t; * barycentricCoordinates = new VFXExpressionCombine(a, b, c); */ } else { throw new InvalidOperationException("No supported surfaceCoordinates : " + coord); } for (int i = 0; i < vertexAttributes.Count(); ++i) { var outputValueType = sampling_A[i].valueType; var barycentricCoordinateX = VFXOperatorUtility.CastFloat(barycentricCoordinates.x, outputValueType); var barycentricCoordinateY = VFXOperatorUtility.CastFloat(barycentricCoordinates.y, outputValueType); var barycentricCoordinateZ = VFXOperatorUtility.CastFloat(barycentricCoordinates.z, outputValueType); var r = sampling_A[i] * barycentricCoordinateX + sampling_B[i] * barycentricCoordinateY + sampling_C[i] * barycentricCoordinateZ; yield return(r); } }