protected override sealed VFXExpression[] BuildExpression(VFXExpression[] inputExpression) { var expressions = Block.CameraHelper.AddCameraExpressions(GetExpressionsFromSlots(this), camera); // camera matrix is already in world even in custom mode due to GetOutputSpaceFromSlot returning world space Block.CameraMatricesExpressions matricesExpressions = Block.CameraHelper.GetMatricesExpressions(expressions, VFXCoordinateSpace.World, VFXCoordinateSpace.World); // result = position * VFXToView * ViewToClip VFXExpression positionExpression = inputExpression[0]; VFXExpression viewPosExpression = new VFXExpressionTransformPosition(matricesExpressions.VFXToView.exp, positionExpression); VFXExpression clipPosExpression = new VFXExpressionTransformVector4(matricesExpressions.ViewToClip.exp, VFXOperatorUtility.CastFloat(viewPosExpression, VFXValueType.Float4, 1.0f)); // normalize using w component and renormalize to range [0, 1] VFXExpression halfExpression = VFXValue.Constant(0.5f); VFXExpression normalizedExpression = new VFXExpressionCombine(new VFXExpression[] { (clipPosExpression.x / clipPosExpression.w) * halfExpression + halfExpression, (clipPosExpression.y / clipPosExpression.w) * halfExpression + halfExpression, viewPosExpression.z // The z position is in world units from the camera }); return(new VFXExpression[] { normalizedExpression }); }
protected override sealed VFXExpression[] BuildExpression(VFXExpression[] inputExpression) { var expressions = Block.CameraHelper.AddCameraExpressions(GetExpressionsFromSlots(this), camera); // camera matrix is already in world even in custom mode due to GetOutputSpaceFromSlot returning world space Block.CameraMatricesExpressions matricesExpressions = Block.CameraHelper.GetMatricesExpressions(expressions, VFXCoordinateSpace.World, VFXCoordinateSpace.World); // renormalize XY from viewport position [0, 1] to clip position [-1, 1] VFXExpression viewportPosExpression = inputExpression[0]; VFXExpression oneExpression = VFXValue.Constant(1.0f); VFXExpression twoExpression = VFXValue.Constant(2.0f); VFXExpression clipPosExpression = new VFXExpressionCombine(viewportPosExpression.x * twoExpression - oneExpression, viewportPosExpression.y * twoExpression - oneExpression, oneExpression, oneExpression); // result = clipPos * ClipToView * ViewToVFX VFXExpression viewPosExpression = new VFXExpressionTransformVector4(matricesExpressions.ClipToView.exp, clipPosExpression); viewPosExpression = new VFXExpressionCombine(viewPosExpression.x, viewPosExpression.y, viewPosExpression.z) * viewportPosExpression.zzz; VFXExpression positionExpression = new VFXExpressionTransformPosition(matricesExpressions.ViewToVFX.exp, viewPosExpression); return(new VFXExpression[] { positionExpression }); }
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()); }