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.
 
 
 
 

393 lines
12 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
$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)
}