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.
156 lines
6.4 KiB
156 lines
6.4 KiB
using System;
|
|
using System.Linq;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using UnityEngine;
|
|
|
|
namespace UnityEditor.VFX.Block
|
|
{
|
|
class PositionSDF : PositionShapeBase
|
|
{
|
|
public class InputProperties
|
|
{
|
|
[Tooltip("Sets the Signed Distance Field to sample from.")]
|
|
public Texture3D SDF = VFXResources.defaultResources.signedDistanceField;
|
|
[Tooltip("Sets the transform with which to position, scale, or rotate the field.")]
|
|
public OrientedBox FieldTransform = OrientedBox.defaultValue;
|
|
}
|
|
|
|
public class CustomProperties
|
|
{
|
|
[Range(0, 1), Tooltip("When using customized emission, control the position around the arc to emit particles from.")]
|
|
public float ArcSequencer = 0.0f;
|
|
}
|
|
|
|
public override IEnumerable<VFXNamedExpression> GetParameters(PositionShape positionBase, List<VFXNamedExpression> allSlots)
|
|
{
|
|
VFXExpression transform = null, sdf = null;
|
|
foreach (var e in allSlots)
|
|
{
|
|
if (e.name == "FieldTransform")
|
|
{
|
|
transform = e.exp;
|
|
yield return e;
|
|
}
|
|
|
|
if (e.name == "SDF")
|
|
{
|
|
sdf = e.exp;
|
|
yield return e;
|
|
}
|
|
|
|
if (e.name == "ArcSequencer" ||
|
|
e.name == "Thickness")
|
|
yield return e;
|
|
}
|
|
|
|
var extents = new VFXNamedExpression(new VFXExpressionExtractScaleFromMatrix(transform), "extents");
|
|
yield return new VFXNamedExpression(VFX.VFXOperatorUtility.Max3(extents.exp), "scalingFactor");
|
|
yield return new VFXNamedExpression(new VFXExpressionInverseTRSMatrix(transform), "inverseTransform");
|
|
var minDim = new VFXExpressionCastUintToFloat(VFX.VFXOperatorUtility.Min3(new VFXExpressionTextureHeight(sdf), new VFXExpressionTextureWidth(sdf), new VFXExpressionTextureDepth(sdf)));
|
|
var gradStep = VFXValue.Constant(0.01f); //kStep used in SampleSDFDerivativesFast and SampleSDFDerivatives
|
|
var margin = VFXValue.Constant(0.5f) / minDim + gradStep + VFXValue.Constant(0.001f);
|
|
yield return new VFXNamedExpression(VFXValue.Constant(0.5f) - margin, "projectionRayWithMargin");
|
|
yield return new VFXNamedExpression(VFXValue.Constant(positionBase.projectionSteps), "n_steps");
|
|
}
|
|
|
|
public override string GetSource(PositionShape positionBase)
|
|
{
|
|
var outSource = new StringBuilder(@"float cosPhi = 2.0f * RAND - 1.0f;");
|
|
if (positionBase.spawnMode == PositionBase.SpawnMode.Random)
|
|
outSource.AppendLine(@"float theta = TWO_PI * RAND;");
|
|
else
|
|
outSource.AppendLine(@"float theta = TWO_PI * ArcSequencer;");
|
|
switch (positionBase.positionMode)
|
|
{
|
|
case (PositionBase.PositionMode.Surface):
|
|
outSource.AppendLine(@" float Thickness = 0.0f;");
|
|
break;
|
|
case (PositionBase.PositionMode.Volume):
|
|
outSource.AppendLine(@" float Thickness = scalingFactor;");
|
|
break;
|
|
case (PositionBase.PositionMode.ThicknessRelative):
|
|
outSource.AppendLine(@" Thickness *= scalingFactor * 0.5f;");
|
|
break;
|
|
}
|
|
|
|
outSource.Append(@"
|
|
//Initialize position within texture bounds
|
|
float2 sincosTheta;
|
|
sincos(theta, sincosTheta.x, sincosTheta.y);
|
|
sincosTheta *= sqrt(1.0f - cosPhi * cosPhi);
|
|
float3 currentAxisY = float3(sincosTheta, cosPhi) * sqrt(3)/2;
|
|
float maxDir = max(0.5f, max(abs(currentAxisY.x), max(abs(currentAxisY.y), abs(currentAxisY.z))));
|
|
currentAxisY = currentAxisY * (projectionRayWithMargin/maxDir);
|
|
float3 tPos = currentAxisY * pow(RAND, 1.0f/3.0f);
|
|
float3 coord = tPos + 0.5f;
|
|
float3 wPos, n, worldNormal;
|
|
|
|
for(uint proj_step=0; proj_step < n_steps; proj_step++){
|
|
|
|
float dist = SampleSDF(SDF, coord);
|
|
n = -normalize(SampleSDFDerivativesFast(SDF, coord, dist));
|
|
dist *= scalingFactor;
|
|
|
|
//Projection on surface/volume
|
|
float3 delta;
|
|
worldNormal = VFXSafeNormalize(mul(float4(n, 0), inverseTransform).xyz);
|
|
if (dist > 0)
|
|
delta = dist * worldNormal;
|
|
else
|
|
{
|
|
delta = min(dist + Thickness, 0) * worldNormal;
|
|
}
|
|
|
|
wPos = mul(FieldTransform, float4(tPos,1)).xyz + delta;
|
|
tPos = mul(inverseTransform, float4(wPos, 1)).xyz;
|
|
coord = tPos + 0.5f;
|
|
|
|
}");
|
|
outSource.AppendFormat(positionBase.composePositionFormatString, "wPos");
|
|
|
|
if (positionBase.applyOrientation != PositionBase.Orientation.None)
|
|
outSource.Append(@"currentAxisY = -worldNormal;");
|
|
|
|
if (positionBase.applyOrientation.HasFlag(PositionBase.Orientation.Axes))
|
|
outSource.Append(@"
|
|
float3 AxisZCandidateA = float3(-sincosTheta.y, sincosTheta.x, 0);
|
|
float3 AxisZCandidateB = float3(sign(cosPhi), 0, 0);
|
|
AxisZCandidateA = mul(float4(AxisZCandidateA, 0), inverseTransform).xyz;
|
|
AxisZCandidateB = mul(float4(AxisZCandidateB, 0), inverseTransform).xyz;
|
|
|
|
float3 currentAxisZ = AxisZCandidateA;
|
|
float3 currentAxisX = cross(currentAxisZ, currentAxisY);
|
|
if (dot(currentAxisX, currentAxisX) < 0.00001f)
|
|
{
|
|
currentAxisZ = AxisZCandidateB;
|
|
currentAxisX = cross(currentAxisZ, currentAxisY);
|
|
}
|
|
|
|
currentAxisX = normalize(currentAxisX);
|
|
currentAxisZ = normalize(cross(currentAxisX, currentAxisY));");
|
|
|
|
if (positionBase.applyOrientation.HasFlag(PositionBase.Orientation.Direction))
|
|
{
|
|
outSource.AppendFormat(positionBase.composeDirectionFormatString, "currentAxisY");
|
|
}
|
|
|
|
if (positionBase.applyOrientation.HasFlag(PositionBase.Orientation.Axes))
|
|
{
|
|
outSource.AppendFormat(VFXBlockUtility.GetComposeString(positionBase.compositionAxes, "axisX", "currentAxisX", "blendAxes"));
|
|
outSource.AppendFormat(VFXBlockUtility.GetComposeString(positionBase.compositionAxes, "axisY", "currentAxisY", "blendAxes"));
|
|
outSource.AppendFormat(VFXBlockUtility.GetComposeString(positionBase.compositionAxes, "axisZ", "currentAxisZ", "blendAxes"));
|
|
}
|
|
|
|
if (positionBase.killOutliers)
|
|
{
|
|
outSource.Append(@"
|
|
float dist = SampleSDF(SDF, coord);
|
|
if (dist * scalingFactor > 0.01)
|
|
alive = false;");
|
|
}
|
|
|
|
return outSource.ToString();
|
|
}
|
|
}
|
|
}
|