Ejemplo n.º 1
0
        public static CameraMatricesExpressions GetMatricesExpressions(IEnumerable <VFXNamedExpression> expressions, VFXCoordinateSpace cameraSpace, VFXCoordinateSpace outputSpace)
        {
            var fov          = expressions.First(e => e.name == "Camera_fieldOfView");
            var aspect       = expressions.First(e => e.name == "Camera_aspectRatio");
            var near         = expressions.First(e => e.name == "Camera_nearPlane");
            var far          = expressions.First(e => e.name == "Camera_farPlane");
            var cameraMatrix = expressions.First(e => e.name == "Camera_transform");
            var isOrtho      = expressions.First(e => e.name == "Camera_orthographic");
            var orthoSize    = expressions.First(e => e.name == "Camera_orthographicSize");
            var lensShift    = expressions.First(e => e.name == "Camera_lensShift");

            VFXExpression ViewToVFX = cameraMatrix.exp;

            if (cameraSpace == VFXCoordinateSpace.World && outputSpace == VFXCoordinateSpace.Local)
            {
                ViewToVFX = new VFXExpressionTransformMatrix(VFXBuiltInExpression.WorldToLocal, cameraMatrix.exp);
            }
            else if (cameraSpace == VFXCoordinateSpace.Local && outputSpace == VFXCoordinateSpace.World)
            {
                ViewToVFX = new VFXExpressionTransformMatrix(VFXBuiltInExpression.LocalToWorld, cameraMatrix.exp);
            }

            VFXExpression VFXToView  = new VFXExpressionInverseTRSMatrix(ViewToVFX);
            VFXExpression ViewToClip = new VFXExpressionBranch(isOrtho.exp,
                                                               VFXOperatorUtility.GetOrthographicMatrix(orthoSize.exp, aspect.exp, near.exp, far.exp),
                                                               VFXOperatorUtility.GetPerspectiveMatrix(fov.exp, aspect.exp, near.exp, far.exp, lensShift.exp));
            VFXExpression ClipToView = new VFXExpressionInverseMatrix(ViewToClip);

            return(new CameraMatricesExpressions()
            {
                ViewToVFX = new VFXNamedExpression(ViewToVFX, "ViewToVFX"),
                VFXToView = new VFXNamedExpression(VFXToView, "VFXToView"),
                ViewToClip = new VFXNamedExpression(ViewToClip, "ViewToClip"),
                ClipToView = new VFXNamedExpression(ClipToView, "ClipToView"),
            });
        }
        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());
        }