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.
403 lines
13 KiB
403 lines
13 KiB
//VFXDefineSpace splice
|
|
$splice(VFXDefineSpace)
|
|
|
|
//VFXDefines splice
|
|
$splice(VFXDefines)
|
|
#define NULL_GEOMETRY_INPUT defined(HAVE_VFX_PLANAR_PRIMITIVE)
|
|
|
|
#if HAS_STRIPS
|
|
#define HAS_STRIPS_DATA 1
|
|
#endif
|
|
|
|
// Explicitly defined here for now (similar to how it was done in the previous VFX code-gen)
|
|
#define HAS_VFX_ATTRIBUTES 1
|
|
|
|
// VFX has some internal functions for strips or CustomBlockHLSL that assume the generically named "VFXAttributes" struct as input.
|
|
// For now, override it. TODO: Improve the generic struct name for VFX shader library.
|
|
#define VFXAttributes InternalAttributesElement
|
|
|
|
#define VFX_NEEDS_COLOR_INTERPOLATOR (VFX_USE_COLOR_CURRENT || VFX_USE_ALPHA_CURRENT)
|
|
#if HAS_STRIPS
|
|
#define VFX_OPTIONAL_INTERPOLATION
|
|
#else//
|
|
#define VFX_OPTIONAL_INTERPOLATION nointerpolation
|
|
#endif
|
|
|
|
ByteAddressBuffer attributeBuffer;
|
|
|
|
#if VFX_HAS_INDIRECT_DRAW
|
|
StructuredBuffer<uint> indirectBuffer;
|
|
#endif
|
|
|
|
#if USE_DEAD_LIST_COUNT
|
|
StructuredBuffer<uint> deadList;
|
|
#endif
|
|
|
|
#if HAS_STRIPS_DATA
|
|
StructuredBuffer<uint> stripDataBuffer;
|
|
#endif
|
|
|
|
#if VFX_FEATURE_MOTION_VECTORS_FORWARD || USE_MOTION_VECTORS_PASS
|
|
ByteAddressBuffer elementToVFXBufferPrevious;
|
|
#endif
|
|
|
|
CBUFFER_START(outputParams)
|
|
float4 instancingConstants;
|
|
float3 cameraXRSettings;
|
|
CBUFFER_END
|
|
|
|
UNITY_INSTANCING_BUFFER_START(PerInstance)
|
|
UNITY_DEFINE_INSTANCED_PROP(float, _InstanceIndex)
|
|
UNITY_DEFINE_INSTANCED_PROP(float, _InstanceActiveIndex)
|
|
UNITY_INSTANCING_BUFFER_END(PerInstance)
|
|
|
|
// Helper macros to always use a valid instanceID
|
|
#if defined(UNITY_STEREO_INSTANCING_ENABLED)
|
|
#define VFX_DECLARE_INSTANCE_ID UNITY_VERTEX_INPUT_INSTANCE_ID
|
|
#define VFX_GET_INSTANCE_ID(i) unity_InstanceID
|
|
#else
|
|
#define VFX_DECLARE_INSTANCE_ID uint instanceID : SV_InstanceID;
|
|
#define VFX_GET_INSTANCE_ID(i) input.instanceID
|
|
#endif
|
|
|
|
// These are supposed to be passed as a instanced constant property (unity_SpriteFlipArray) for sprites, but it doesn't work for VFX Shadergraph mesh outputs
|
|
// because the instancing constant arrays (UNITY_DEFINE_INSTANCED_PROP...) are used for per-effect instancing in VFX, not per-particle instancing.
|
|
// In any case, the value passed for VFX is always (1,1) currently, and not user-modifiable, so no need to get it from a constant buffer.
|
|
#define unity_SpriteProps float4(1,1,1,1)
|
|
#ifdef unity_SpriteColor
|
|
#undef unity_SpriteColor
|
|
#endif
|
|
#define unity_SpriteColor float4(1,1,1,1)
|
|
|
|
|
|
$splice(VFXPerBlockDefines)
|
|
|
|
$splice(VFXSRPCommonInclude)
|
|
#include "Packages/com.unity.visualeffectgraph/Shaders/VFXCommon.hlsl"
|
|
$splice(VFXPerBlockIncludes)
|
|
#include "Packages/com.unity.visualeffectgraph/Shaders/VFXCommonOutput.hlsl"
|
|
|
|
$splice(VFXParameterBuffer)
|
|
|
|
$splice(VFXGeneratedBlockFunction)
|
|
|
|
|
|
struct AttributesElement
|
|
{
|
|
uint index;
|
|
uint instanceIndex;
|
|
uint instanceActiveIndex;
|
|
// Internal attributes sub-struct used by VFX code-gen property mapping.
|
|
InternalAttributesElement attributes;
|
|
|
|
// Additional attribute information for particle strips.
|
|
#if HAS_STRIPS_DATA
|
|
uint relativeIndexInStrip;
|
|
StripData stripData;
|
|
#endif
|
|
|
|
// Additional parameter information for motion vectors
|
|
#if (VFX_FEATURE_MOTION_VECTORS_FORWARD || USE_MOTION_VECTORS_PASS)
|
|
uint currentFrameIndex;
|
|
#endif
|
|
};
|
|
|
|
bool ShouldCullElement(uint index, uint vfxInstanceIndex, uint nbMax)
|
|
{
|
|
uint deadCount = 0;
|
|
#if USE_DEAD_LIST_COUNT
|
|
deadCount = deadList[vfxInstanceIndex];
|
|
#endif
|
|
|
|
#if HAS_STRIPS && !VFX_HAS_INDIRECT_DRAW
|
|
// We render one particle less for each strip in this case
|
|
nbMax -= STRIP_COUNT;
|
|
#endif
|
|
|
|
return (index >= nbMax - deadCount);
|
|
}
|
|
|
|
float3 GetElementSize(InternalAttributesElement attributes)
|
|
{
|
|
float3 size3 = float3(attributes.size,attributes.size,attributes.size);
|
|
|
|
// TODO: Currently these do not get defined/generated.
|
|
#if VFX_USE_SCALEX_CURRENT
|
|
size3.x *= attributes.scaleX;
|
|
#endif
|
|
#if VFX_USE_SCALEY_CURRENT
|
|
size3.y *= attributes.scaleY;
|
|
#endif
|
|
#if VFX_USE_SCALEZ_CURRENT
|
|
size3.z *= attributes.scaleZ;
|
|
#endif
|
|
|
|
#if HAS_STRIPS
|
|
// Add an epsilon so that size is never 0 for strips
|
|
size3 += size3 < 0.0f ? -VFX_EPSILON : VFX_EPSILON;
|
|
#endif
|
|
|
|
return size3;
|
|
}
|
|
|
|
float3 GetElementSizeRT(InternalAttributesElement attributes
|
|
#if VFX_USE_GRAPH_VALUES
|
|
, GraphValues graphValues
|
|
#endif
|
|
)
|
|
{
|
|
float3 size3 = GetElementSize(attributes);
|
|
|
|
float3 rtScale = float3(1,1,1);
|
|
|
|
#if VFX_USE_RT_CUSTOM_SCALE
|
|
$splice(VFXLoadRayTracedScaling)
|
|
rtScale = float3(rayTracedScaling,1.0f);
|
|
#else
|
|
#ifdef VFX_RT_DEFAULT_SCALE
|
|
rtScale = VFX_RT_DEFAULT_SCALE;
|
|
#endif
|
|
#endif
|
|
|
|
size3 *= rtScale;
|
|
return size3;
|
|
}
|
|
|
|
#if HAS_STRIPS
|
|
float3 GetParticlePosition(uint index, uint instanceIndex)
|
|
{
|
|
InternalAttributesElement attributes;
|
|
ZERO_INITIALIZE(InternalAttributesElement, attributes);
|
|
|
|
// Here we have to explicitly splice in the position (ShaderGraph splice system lacks regex support etc. :(, unlike VFX's).
|
|
$splice(VFXLoadPositionAttribute)
|
|
|
|
return attributes.position;
|
|
}
|
|
|
|
float3 GetStripTangent(float3 currentPos, uint instanceIndex, uint relativeIndex, const StripData stripData)
|
|
{
|
|
float3 prevTangent = (float3)0.0f;
|
|
if (relativeIndex > 0)
|
|
{
|
|
uint prevIndex = GetParticleIndex(relativeIndex - 1, stripData);
|
|
float3 tangent = currentPos - GetParticlePosition(prevIndex, instanceIndex);
|
|
float sqrLength = dot(tangent, tangent);
|
|
if (sqrLength > VFX_EPSILON * VFX_EPSILON)
|
|
prevTangent = tangent * rsqrt(sqrLength);
|
|
}
|
|
|
|
float3 nextTangent = (float3)0.0f;
|
|
if (relativeIndex + 1 < stripData.nextIndex)
|
|
{
|
|
uint nextIndex = GetParticleIndex(relativeIndex + 1, stripData);
|
|
float3 tangent = GetParticlePosition(nextIndex, instanceIndex) - currentPos;
|
|
float sqrLength = dot(tangent, tangent);
|
|
if (sqrLength > VFX_EPSILON * VFX_EPSILON)
|
|
nextTangent = tangent * rsqrt(sqrLength);
|
|
}
|
|
|
|
return VFXSafeNormalize(prevTangent + nextTangent);
|
|
}
|
|
#endif
|
|
|
|
void GetElementData(inout AttributesElement element)
|
|
{
|
|
uint index = element.index;
|
|
uint instanceIndex = element.instanceIndex;
|
|
uint instanceActiveIndex = element.instanceActiveIndex;
|
|
#if VFX_USE_GRAPH_VALUES
|
|
$splice(VFXLoadGraphValues)
|
|
#endif
|
|
|
|
InternalAttributesElement attributes;
|
|
ZERO_INITIALIZE(InternalAttributesElement, attributes);
|
|
|
|
$splice(VFXLoadAttribute)
|
|
|
|
#if HAS_STRIPS_DATA
|
|
const StripData stripData = element.stripData;
|
|
const uint relativeIndexInStrip = element.relativeIndexInStrip;
|
|
InitStripAttributes(index, attributes, element.stripData);
|
|
#endif
|
|
|
|
#if (VFX_FEATURE_MOTION_VECTORS_FORWARD || USE_MOTION_VECTORS_PASS)
|
|
$splice(VFXLoadCurrentFrameIndexParameter)
|
|
element.currentFrameIndex = currentFrameIndex;
|
|
#endif
|
|
|
|
#if !VFX_HAS_INDIRECT_DRAW && !HAS_STRIPS
|
|
if (attributes.alive)
|
|
#endif
|
|
{
|
|
$splice(VFXProcessBlocks)
|
|
}
|
|
|
|
element.attributes = attributes;
|
|
}
|
|
|
|
// Configure the output type-spcific mesh definition and index calculation for the rest of the element data.
|
|
$OutputType.Mesh: $include("VFXConfigMesh.template.hlsl")
|
|
$OutputType.PlanarPrimitive: $include("VFXConfigPlanarPrimitive.template.hlsl")
|
|
|
|
#if !defined(SHADER_STAGE_RAY_TRACING)
|
|
|
|
// Loads the element-specific attribute data, as well as fills any interpolator.
|
|
bool GetInterpolatorAndElementData(inout VFX_SRP_ATTRIBUTES input, inout VFX_SRP_VARYINGS output, inout AttributesElement element)
|
|
{
|
|
GetElementData(element);
|
|
#if VFX_USE_GRAPH_VALUES
|
|
uint instanceActiveIndex = element.instanceActiveIndex;
|
|
$splice(VFXLoadGraphValues)
|
|
#endif
|
|
InternalAttributesElement attributes = element.attributes;
|
|
|
|
#if !HAS_STRIPS
|
|
if (!attributes.alive)
|
|
return false;
|
|
#endif
|
|
#ifdef ATTRIBUTES_NEED_NORMAL
|
|
float3 size3 = GetElementSize(element.attributes);
|
|
float normalFlip = (size3.x * size3.y * size3.z) < 0 ? -1 : 1;
|
|
input.normalOS *= normalFlip;
|
|
#endif
|
|
$splice(VFXInterpolantsGeneration)
|
|
|
|
return true;
|
|
}
|
|
|
|
// Reconstruct the VFX/World to Element matrix provided by interpolator.
|
|
void BuildWorldToElement(VFX_SRP_VARYINGS input)
|
|
{
|
|
#ifdef VARYINGS_NEED_WORLD_TO_ELEMENT
|
|
worldToElement[0] = input.worldToElement0;
|
|
worldToElement[1] = input.worldToElement1;
|
|
worldToElement[2] = input.worldToElement2;
|
|
worldToElement[3] = float4(0,0,0,1);
|
|
#endif
|
|
}
|
|
|
|
void BuildElementToWorld(VFX_SRP_VARYINGS input)
|
|
{
|
|
#ifdef VARYINGS_NEED_ELEMENT_TO_WORLD
|
|
elementToWorld[0] = input.elementToWorld0;
|
|
elementToWorld[1] = input.elementToWorld1;
|
|
elementToWorld[2] = input.elementToWorld2;
|
|
elementToWorld[3] = float4(0,0,0,1);
|
|
#endif
|
|
}
|
|
|
|
void SetupVFXMatrices(AttributesElement element, inout VFX_SRP_VARYINGS output)
|
|
{
|
|
// Due to a very stubborn compiler bug we cannot refer directly to the redefined UNITY_MATRIX_M / UNITY_MATRIX_I_M here, due to a rare case where the matrix alias
|
|
// is potentially still the constant object matrices (thus complaining about l-value specifying const object). Note even judicious use of preprocessors seems to
|
|
// fix it, so we instead we directly refer to the static matrices.
|
|
|
|
// Element -> World
|
|
elementToWorld = GetElementToVFXMatrix(
|
|
element.attributes.axisX,
|
|
element.attributes.axisY,
|
|
element.attributes.axisZ,
|
|
float3(element.attributes.angleX, element.attributes.angleY, element.attributes.angleZ),
|
|
float3(element.attributes.pivotX, element.attributes.pivotY, element.attributes.pivotZ),
|
|
GetElementSize(element.attributes),
|
|
element.attributes.position
|
|
);
|
|
|
|
#if VFX_LOCAL_SPACE
|
|
elementToWorld = mul(GetSGVFXUnityObjectToWorld(), elementToWorld);
|
|
#elif !defined(VFX_HAS_PICKING_MATRIX_CORRECTION)
|
|
elementToWorld = ApplyCameraTranslationToMatrix(elementToWorld);
|
|
#endif
|
|
|
|
// World -> Element
|
|
worldToElement = GetVFXToElementMatrix(
|
|
element.attributes.axisX,
|
|
element.attributes.axisY,
|
|
element.attributes.axisZ,
|
|
float3(element.attributes.angleX,element.attributes.angleY,element.attributes.angleZ),
|
|
float3(element.attributes.pivotX,element.attributes.pivotY,element.attributes.pivotZ),
|
|
GetElementSize(element.attributes),
|
|
element.attributes.position
|
|
);
|
|
|
|
#if VFX_LOCAL_SPACE
|
|
worldToElement = mul(worldToElement,GetSGVFXUnityWorldToObject());
|
|
#elif !defined(VFX_HAS_PICKING_MATRIX_CORRECTION)
|
|
worldToElement = ApplyCameraTranslationToInverseMatrix(worldToElement);
|
|
#endif
|
|
|
|
// Pack matrices into interpolator if requested by any node.
|
|
#ifdef VARYINGS_NEED_ELEMENT_TO_WORLD
|
|
output.elementToWorld0 = elementToWorld[0];
|
|
output.elementToWorld1 = elementToWorld[1];
|
|
output.elementToWorld2 = elementToWorld[2];
|
|
#endif
|
|
|
|
#ifdef VARYINGS_NEED_WORLD_TO_ELEMENT
|
|
output.worldToElement0 = worldToElement[0];
|
|
output.worldToElement1 = worldToElement[1];
|
|
output.worldToElement2 = worldToElement[2];
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
float4 VFXGetPreviousClipPosition(VFX_SRP_ATTRIBUTES input, AttributesElement element, float4 cPositionFallback)
|
|
{
|
|
float4 cPreviousPos = cPositionFallback;
|
|
|
|
#if (VFX_FEATURE_MOTION_VECTORS_FORWARD || USE_MOTION_VECTORS_PASS)
|
|
uint elementIndex = element.index;
|
|
uint vertexId = input.vertexID;
|
|
uint elementToVFXBaseIndex;
|
|
if (TryGetElementToVFXBaseIndex(elementIndex, element.instanceIndex, elementToVFXBaseIndex, element.currentFrameIndex))
|
|
{
|
|
cPreviousPos = VFXGetPreviousClipPosition(elementToVFXBaseIndex, vertexId);
|
|
}
|
|
#endif
|
|
|
|
return cPreviousPos;
|
|
}
|
|
|
|
VFX_SRP_ATTRIBUTES VFXTransformMeshToPreviousElement(VFX_SRP_ATTRIBUTES input, AttributesElement element)
|
|
{
|
|
#if (VFX_FEATURE_MOTION_VECTORS_FORWARD || USE_MOTION_VECTORS_PASS)
|
|
uint elementIndex = element.index;
|
|
uint elementToVFXBaseIndex;
|
|
if (TryGetElementToVFXBaseIndex(elementIndex, element.instanceIndex, elementToVFXBaseIndex, element.currentFrameIndex))
|
|
{
|
|
float4x4 previousElementToVFX = VFXGetPreviousElementToVFX(elementToVFXBaseIndex);
|
|
input.positionOS = mul(previousElementToVFX, float4(input.positionOS, 1.0f)).xyz;
|
|
}
|
|
else
|
|
#endif//WRITE_MOTION_VECTOR_IN_FORWARD || USE_MOTION_VECTORS_PASS
|
|
{
|
|
float4x4 elementToVFXMatrix = GetElementToVFXMatrix(
|
|
element.attributes.axisX,
|
|
element.attributes.axisY,
|
|
element.attributes.axisZ,
|
|
float3(element.attributes.angleX, element.attributes.angleY, element.attributes.angleZ),
|
|
float3(element.attributes.pivotX, element.attributes.pivotY, element.attributes.pivotZ),
|
|
GetElementSize(element.attributes),
|
|
element.attributes.position);
|
|
input.positionOS = mul(elementToVFXMatrix, float4(input.positionOS, 1.0f)).xyz;
|
|
}
|
|
|
|
return input;
|
|
}
|
|
|
|
// Vertex + Pixel Graph Properties Generation
|
|
void GetElementVertexProperties(AttributesElement element, inout GraphProperties properties)
|
|
{
|
|
#if VFX_USE_GRAPH_VALUES
|
|
uint instanceActiveIndex = element.instanceActiveIndex;
|
|
$splice(VFXLoadGraphValues)
|
|
#endif
|
|
InternalAttributesElement attributes = element.attributes;
|
|
$splice(VFXVertexPropertiesGeneration)
|
|
}
|
|
|
|
void GetElementPixelProperties(VFX_SRP_SURFACE_INPUTS fragInputs, inout GraphProperties properties)
|
|
{
|
|
$splice(VFXPixelPropertiesAssign)
|
|
}
|