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>());
        }
Exemplo n.º 2
0
        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));
            }
        }
Exemplo n.º 3
0
        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());
        }
Exemplo n.º 6
0
        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);
            }
        }