Untitled
// This is a copy of the source shader. Modifying this file will not affect the original shader. #pragma kernel CSMain #pragma only_renderers d3d11 glcore gles3 metal vulkan xboxone xboxone xboxseries playstation ps5 switch #define NB_THREADS_PER_GROUP 64 #define HAS_VFX_ATTRIBUTES 1 #define VFX_PASSDEPTH_ACTUAL (0) #define VFX_PASSDEPTH_MOTION_VECTOR (1) #define VFX_PASSDEPTH_SELECTION (2) #define VFX_PASSDEPTH_PICKING (3) #define VFX_PASSDEPTH_SHADOW (4) #define VFX_USE_POSITION_CURRENT 1 #define VFX_USE_SEED_CURRENT 1 #define VFX_USE_LIFETIME_CURRENT 1 #define VFX_USE_TEXINDEX_CURRENT 1 #define VFX_USE_ALIVE_CURRENT 1 #define VFX_USE_AXISX_CURRENT 1 #define VFX_USE_AXISY_CURRENT 1 #define VFX_USE_AXISZ_CURRENT 1 #define VFX_USE_ANGLEX_CURRENT 1 #define VFX_USE_ANGLEY_CURRENT 1 #define VFX_USE_ANGLEZ_CURRENT 1 #define VFX_USE_PIVOTX_CURRENT 1 #define VFX_USE_PIVOTY_CURRENT 1 #define VFX_USE_PIVOTZ_CURRENT 1 #define VFX_USE_SIZE_CURRENT 1 #define VFX_USE_SCALEX_CURRENT 1 #define VFX_USE_SCALEY_CURRENT 1 #define VFX_USE_SCALEZ_CURRENT 1 #define VFX_USE_ALPHA_CURRENT 1 #define VFX_USE_AGE_CURRENT 1 #define RAW_CAPACITY 4000u #define HAVE_VFX_MODIFICATION 1 #define INDIRECT_BUFFER_COUNT 1 #define VFX_FEATURE_SORT 1 #define SORTING_SIGN 1 #define VFX_DISTANCE_SORT_KEY 1 #define VFX_FEATURE_FRUSTUM_CULL 1 #define VFX_WORLD_SPACE 1 #include_with_pragmas "Packages/com.unity.render-pipelines.universal/Runtime/VFXGraph/Shaders/VFXDefines.hlsl" #define VFX_USE_GRAPH_VALUES 1 #define VFX_USE_INSTANCING 1 #define VFX_INSTANCING_FIXED_SIZE 4032 #define VFX_INSTANCING_ACTIVE_INDIRECTION 1 #define VFX_INSTANCING_BATCH_INDIRECTION 1 struct GraphValues { bool _vfx_enabled_i; bool _vfx_enabled_j; float uniform_b; float uniform_c; bool _vfx_enabled_k; float3 Color_a; bool _vfx_enabled_l; float4 Size_a; float invSoftParticlesFadeDistance_a; float2 flipBookSize_a; float2 invFlipBookSize_a; }; ByteAddressBuffer graphValuesBuffer; Texture2D mainTexture; SamplerState samplermainTexture; float4 mainTexture_TexelSize; struct VFXAttributes { float3 position; uint seed; float lifetime; float texIndex; bool alive; float3 axisX; float3 axisY; float3 axisZ; float angleX; float angleY; float angleZ; float pivotX; float pivotY; float pivotZ; float size; float scaleX; float scaleY; float scaleZ; float alpha; float age; }; struct VFXSourceAttributes { }; #if HAS_STRIPS RWStructuredBuffer<uint> stripDataBuffer; #endif // Strips tangent computation ByteAddressBuffer attributeBuffer; #if VFX_FEATURE_MOTION_VECTORS RWByteAddressBuffer elementToVFXBuffer; #endif #if VFX_FEATURE_SORT struct Kvp { float sortKey; uint index; }; #define IndirectOutputType Kvp #else #define IndirectOutputType uint #endif #if INDIRECT_BUFFER_COUNT > 0 RWStructuredBuffer<IndirectOutputType> outputBuffer0; #endif #if INDIRECT_BUFFER_COUNT > 1 RWStructuredBuffer<IndirectOutputType> outputBuffer1; #endif #if INDIRECT_BUFFER_COUNT > 2 RWStructuredBuffer<IndirectOutputType> outputBuffer2; #endif #if INDIRECT_BUFFER_COUNT > 3 RWStructuredBuffer<IndirectOutputType> outputBuffer3; #endif #if INDIRECT_BUFFER_COUNT > 4 #error Too many indirect buffers defined. #endif CBUFFER_START(updateParamsConst) uint dispatchWidth; float4 instancingConstants; float3 cameraXRSettings; CBUFFER_END #include "Packages/com.unity.render-pipelines.universal/Runtime/VFXGraph/Shaders/VFXCommon.hlsl" #include "Packages/com.unity.visualeffectgraph/Shaders/VFXCommon.hlsl" void Orient_4(inout float3 axisX, inout float3 axisY, inout float3 axisZ) /*mode:FaceCameraPlane axes:ZY */ { float3x3 viewRot = GetVFXToViewRotMatrix(); axisX = viewRot[0].xyz; axisY = viewRot[1].xyz; axisZ = -viewRot[2].xyz; #if VFX_LOCAL_SPACE // Need to remove potential scale in local transform axisX = normalize(axisX); axisY = normalize(axisY); axisZ = normalize(axisZ); #endif } void SetAttribute_CA10063D(inout float texIndex, float TexIndex) /*attribute:texIndex Composition:Overwrite Source:Slot Random:Off channels:XYZ */ { texIndex = TexIndex; } void AttributeFromCurve_48A85FDC(inout float alpha, float age, float lifetime, float3 Color) /*attribute:color Composition:Overwrite AlphaComposition:Overwrite SampleMode:OverLife Mode:PerComponent ColorMode:Alpha channels:XYZ */ { float t = age / lifetime; float4 value = 0.0f; value = SampleGradient(Color, t); alpha = value.a; } void AttributeFromCurve_45ABB90F(inout float size, float age, float lifetime, float4 Size) /*attribute:size Composition:Overwrite AlphaComposition:Overwrite SampleMode:OverLife Mode:PerComponent ColorMode:ColorAndAlpha channels:X */ { float t = age / lifetime; float value = 0.0f; value = SampleCurve(Size, t); size = value; } #if VFX_FEATURE_FRUSTUM_CULL || VFX_FEATURE_LOD #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/GeometricTools.hlsl" bool IsSphereOutsideFrustum(float3 pos, float radius, float4 frustumPlanes[6]) { bool outside = false; [unroll] for (int i = 0; i < 6; ++i) outside = outside || DistanceFromPlane(pos, frustumPlanes[i]) < -radius; return outside; } #endif #if HAS_STRIPS float3 GetParticlePosition(uint index, uint instanceIndex) { VFXAttributes attributes = (VFXAttributes)0; attributes.position = asfloat(attributeBuffer.Load3(((instanceIndex * 0xEC40) + (index * 0x8 + 0x0)) << 2)); 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) prevTangent = tangent * rsqrt(sqrLength); } float3 nextTangent = (float3)0.0f; if (relativeIndex < stripData.nextIndex - 1) { uint nextIndex = GetParticleIndex(relativeIndex + 1,stripData); float3 tangent = GetParticlePosition(nextIndex, instanceIndex) - currentPos; float sqrLength = dot(tangent, tangent); if (sqrLength > VFX_EPSILON) nextTangent = tangent * rsqrt(sqrLength); } return normalize(prevTangent + nextTangent); } #endif void AppendOutputBuffer(RWStructuredBuffer<IndirectOutputType> outputBuffer, IndirectOutputType output, uint instanceActiveIndex) { uint indirectIndex; #if VFX_FEATURE_SORT InterlockedAdd(outputBuffer[instanceActiveIndex].index, 1, indirectIndex); #else InterlockedAdd(outputBuffer[instanceActiveIndex], 1, indirectIndex); #endif indirectIndex += instancingBatchSize + instanceActiveIndex * RAW_CAPACITY; outputBuffer[indirectIndex] = output; } [numthreads(NB_THREADS_PER_GROUP,1,1)] void CSMain(uint3 groupId : SV_GroupID, uint3 groupThreadId : SV_GroupThreadID) { uint id = GetThreadId(groupId, groupThreadId, dispatchWidth); uint instanceIndex, instanceActiveIndex, instanceCurrentIndex; #if defined(VFX_INSTANCING_FIXED_SIZE) uint index = GetThreadId(groupId, 0, dispatchWidth); index = VFXInitInstancing(index, instanceIndex, instanceActiveIndex, instanceCurrentIndex); index += groupThreadId.x; #else uint index = VFXInitInstancing(id, instanceIndex, instanceActiveIndex, instanceCurrentIndex); #endif ContextData contextData = instancingContextData[instanceActiveIndex]; uint systemSeed = contextData.systemSeed; uint nbMax = contextData.maxParticleCount; if (index < nbMax) { GraphValues graphValues; graphValues.Size_a = asfloat(graphValuesBuffer.Load4(instanceActiveIndex * 160 + 0)); graphValues.Color_a = asfloat(graphValuesBuffer.Load3(instanceActiveIndex * 160 + 64)); graphValues.flipBookSize_a = asfloat(graphValuesBuffer.Load2(instanceActiveIndex * 160 + 80)); graphValues.invFlipBookSize_a = asfloat(graphValuesBuffer.Load2(instanceActiveIndex * 160 + 88)); graphValues._vfx_enabled_i = (bool)graphValuesBuffer.Load(instanceActiveIndex * 160 + 128); graphValues._vfx_enabled_j = (bool)graphValuesBuffer.Load(instanceActiveIndex * 160 + 132); graphValues.uniform_b = asfloat(graphValuesBuffer.Load(instanceActiveIndex * 160 + 136)); graphValues.uniform_c = asfloat(graphValuesBuffer.Load(instanceActiveIndex * 160 + 140)); graphValues._vfx_enabled_k = (bool)graphValuesBuffer.Load(instanceActiveIndex * 160 + 144); graphValues._vfx_enabled_l = (bool)graphValuesBuffer.Load(instanceActiveIndex * 160 + 148); graphValues.invSoftParticlesFadeDistance_a = asfloat(graphValuesBuffer.Load(instanceActiveIndex * 160 + 152)); #if VFX_LOCAL_SPACE vfxLocalToWorld = localToWorld; vfxWorldToLocal = worldToLocal; #else vfxWorldToLocal = k_identity4x4; vfxLocalToWorld = k_identity4x4; #endif VFXAttributes attributes = (VFXAttributes)0; VFXSourceAttributes sourceAttributes = (VFXSourceAttributes)0; attributes.alive = (attributeBuffer.Load(((instanceIndex * 0xEC40) + (index * 0x8 + 0x3)) << 2)); if (attributes.alive) { attributes.position = asfloat(attributeBuffer.Load3(((instanceIndex * 0xEC40) + (index * 0x8 + 0x0)) << 2)); attributes.seed = (attributeBuffer.Load(((instanceIndex * 0xEC40) + (index * 0x1 + 0xBD00)) << 2)); attributes.lifetime = asfloat(attributeBuffer.Load(((instanceIndex * 0xEC40) + (index * 0x1 + 0xCCC0)) << 2)); attributes.texIndex = asfloat(attributeBuffer.Load(((instanceIndex * 0xEC40) + (index * 0x1 + 0xDC80)) << 2)); attributes.axisX = float3(1, 0, 0); attributes.axisY = float3(0, 1, 0); attributes.axisZ = float3(0, 0, 1); attributes.angleX = (float)0; attributes.angleY = (float)0; attributes.angleZ = (float)0; attributes.pivotX = (float)0; attributes.pivotY = (float)0; attributes.pivotZ = (float)0; attributes.size = (float)0.100000001; attributes.scaleX = (float)1; attributes.scaleY = (float)1; attributes.scaleZ = (float)1; attributes.alpha = (float)1; attributes.age = asfloat(attributeBuffer.Load(((instanceIndex * 0xEC40) + (index * 0x8 + 0x4)) << 2)); #if HAS_STRIPS const StripData stripData = GetStripDataFromParticleIndex(index, instanceIndex); InitStripAttributes(index, attributes, stripData); uint relativeIndexInStrip = GetRelativeIndex(index, stripData); #endif if (graphValues._vfx_enabled_i) { Orient_4( /*inout */attributes.axisX, /*inout */attributes.axisY, /*inout */attributes.axisZ); } if (graphValues._vfx_enabled_j) { float tmp_bl = Rand(attributes.seed); float tmp_bm = tmp_bl * graphValues.uniform_c; float tmp_bn = graphValues.uniform_b + tmp_bm; SetAttribute_CA10063D( /*inout */attributes.texIndex, tmp_bn); } if (graphValues._vfx_enabled_k) { AttributeFromCurve_48A85FDC( /*inout */attributes.alpha, attributes.age, attributes.lifetime, graphValues.Color_a); } if (graphValues._vfx_enabled_l) { AttributeFromCurve_45ABB90F( /*inout */attributes.size, attributes.age, attributes.lifetime, graphValues.Size_a); } // Recheck alive as blocks can set it to false for manual culling. // Test will be stripped if it's not the case anyway. if (attributes.alive) { float3 size3 = float3(attributes.size,attributes.size,attributes.size); #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.x += size3.x < 0.0f ? -VFX_EPSILON : VFX_EPSILON; size3.y += size3.y < 0.0f ? -VFX_EPSILON : VFX_EPSILON; size3.z += size3.z < 0.0f ? -VFX_EPSILON : VFX_EPSILON; #endif float4x4 elementToVFX = GetElementToVFXMatrix( attributes.axisX, attributes.axisY, attributes.axisZ, float3(attributes.angleX,attributes.angleY,attributes.angleZ), float3(attributes.pivotX,attributes.pivotY,attributes.pivotZ), size3, attributes.position); #if VFX_FEATURE_FRUSTUM_CULL || VFX_FEATURE_LOD #if VFX_WORLD_SPACE float4x4 elementToWorld = elementToVFX; elementToWorld._m03_m13_m23 = GetCameraRelativePositionWS(elementToWorld._m03_m13_m23); #else float4x4 elementToWorld = mul(GetObjectToWorldMatrix(),elementToVFX); #endif float xAxisSqrLength = dot(elementToWorld._m00_m10_m20, elementToWorld._m00_m10_m20); float yAxisSqrLength = dot(elementToWorld._m01_m11_m21, elementToWorld._m01_m11_m21); float zAxisSqrLength = dot(elementToWorld._m02_m12_m22, elementToWorld._m02_m12_m22); float radius = 0.5f * sqrt(xAxisSqrLength + yAxisSqrLength + zAxisSqrLength); float radiusScale = (float)0; { radiusScale = (float)1; } radius *= radiusScale; #if VFX_FEATURE_FRUSTUM_CULL if (IsSphereOutsideFrustum(elementToWorld._m03_m13_m23, radius, _FrustumPlanes)) return; #endif #endif #if INDIRECT_BUFFER_COUNT > 0 #if VFX_FEATURE_LOD uint outputIndex = ~0u; #if !VFX_FEATURE_FRUSTUM_CULL // If particle is out of frustum and frustum culling is disabled, use the lowest LOD // This is useful for shadow passes for instance to avoid out of frustum particles to be culled from shadows if (IsSphereOutsideFrustum(elementToWorld._m03_m13_m23, radius, _FrustumPlanes)) outputIndex = INDIRECT_BUFFER_COUNT - 1; else #endif { float viewZ = mul(GetWorldToViewMatrix(), float4(elementToWorld._m03_m13_m23, 1)).z; float4x4 centeredProjMatrix = GetViewToHClipMatrix(); centeredProjMatrix._13_14_23_24 = 0.0f; //Cancels the jittering and/or the eye offset when in VR float4 clip = mul(centeredProjMatrix, float4(radius, radius, viewZ, 1)); float lodValue = max(abs(clip.x),abs(clip.y)) * rcp(max(VFX_EPSILON, clip.w)); for (uint i = 0; i < INDIRECT_BUFFER_COUNT; ++i) if (lodValue > lodValues[i]) { outputIndex = i; break; } } #elif INDIRECT_BUFFER_COUNT == 1 uint outputIndex = 0; #else uint outputIndex = attributes.meshIndex; #endif if (outputIndex >= INDIRECT_BUFFER_COUNT) return; #if VFX_FEATURE_SORT Kvp output; #if VFX_CUSTOM_SORT_KEY output.sortKey = -1.0f * sortKey; //Lowest values are rendered first #elif VFX_DISTANCE_SORT_KEY #if VFX_LOCAL_SPACE float3 posRWS = TransformObjectToWorld(attributes.position); #else float3 posRWS = GetCameraRelativePositionWS(attributes.position); #endif float3 camToPos = posRWS - GetCurrentViewPosition(); output.sortKey = dot(camToPos,camToPos); // sqr distance to the camera #elif VFX_DEPTH_SORT_KEY #if VFX_LOCAL_SPACE float3 posRWS = TransformObjectToWorld(attributes.position); #else float3 posRWS = GetCameraRelativePositionWS(attributes.position); #endif float3 zAxisCam = -GetWorldToViewMatrix()[2].xyz; float depth = dot(posRWS, zAxisCam); output.sortKey = depth; #elif VFX_YOUNGEST_SORT_KEY attributes.age = asfloat(attributeBuffer.Load(((instanceIndex * 0xEC40) + (index * 0x8 + 0x4)) << 2)); output.sortKey = attributes.age; #endif //VFX_[CRITERION]_SORT_KEY output.index = index; output.sortKey *= SORTING_SIGN; #else uint output = index; #endif if (outputIndex == 0) { AppendOutputBuffer(outputBuffer0, output, instanceActiveIndex); } #if INDIRECT_BUFFER_COUNT > 1 else if (outputIndex == 1) { AppendOutputBuffer(outputBuffer1, output, instanceActiveIndex); } #if INDIRECT_BUFFER_COUNT > 2 else if (outputIndex == 2) { AppendOutputBuffer(outputBuffer2, output, instanceActiveIndex); } #if INDIRECT_BUFFER_COUNT > 3 else if (outputIndex == 3) { AppendOutputBuffer(outputBuffer3, output, instanceActiveIndex); } #endif #endif #endif #endif #if VFX_FEATURE_MOTION_VECTORS uint offsetedIndex = (RAW_CAPACITY * instanceIndex) + index; #ifdef VFX_FEATURE_MOTION_VECTORS_VERTS uint viewTotal = asuint(cameraXRSettings.x); uint viewCount = asuint(cameraXRSettings.y); uint viewOffset = asuint(cameraXRSettings.z); uint elementToVFXIndex = offsetedIndex * (VFX_FEATURE_MOTION_VECTORS_VERTS * 2 * viewTotal + 1); #else uint elementToVFXIndex = offsetedIndex * 13; #endif elementToVFXBuffer.Store(elementToVFXIndex++ << 2, attributes.alive ? asuint(currentFrameIndex) : 0u); #ifdef VFX_FEATURE_MOTION_VECTORS_VERTS elementToVFXIndex += viewOffset * viewCount * VFX_FEATURE_MOTION_VECTORS_VERTS * 2; #ifdef USING_STEREO_MATRICES if (viewCount == 2) { float4 stereoOffset = float4(GetWorldStereoOffset(), 0.0f); UNITY_UNROLL for (int itIndexVert = 0; itIndexVert < VFX_FEATURE_MOTION_VECTORS_VERTS; ++itIndexVert) { float4 vertPosWorld = float4(TransformPositionVFXToWorld(verts[itIndexVert]), 1.0f); vertPosWorld.xyz = VFXTransformPositionWorldToCameraRelative(vertPosWorld.xyz); float4 vertPosA = mul(_XRNonJitteredViewProjMatrix[0], vertPosWorld); float4 vertPosB = mul(_XRNonJitteredViewProjMatrix[1], vertPosWorld + stereoOffset); elementToVFXBuffer.Store4(elementToVFXIndex << 2, asuint(float4(vertPosA.xy / vertPosA.w, vertPosB.xy / vertPosB.w))); elementToVFXIndex += 4; // 1 vert * 2 floats * 2 views } } else #endif { UNITY_UNROLL for (int itIndexVert = 0; itIndexVert < VFX_FEATURE_MOTION_VECTORS_VERTS - 1; itIndexVert += 2) { float4 vertPosA = TransformPositionVFXToNonJitteredClip(verts[itIndexVert]); float4 vertPosB = TransformPositionVFXToNonJitteredClip(verts[itIndexVert + 1]); elementToVFXBuffer.Store4(elementToVFXIndex << 2, asuint(float4(vertPosA.xy / vertPosA.w, vertPosB.xy / vertPosB.w))); elementToVFXIndex += 4; // 2 verts * 2 floats } if (VFX_FEATURE_MOTION_VECTORS_VERTS % 2 == 1) { int itIndexVert = VFX_FEATURE_MOTION_VECTORS_VERTS - 1; float4 vertPos = TransformPositionVFXToNonJitteredClip(verts[itIndexVert]); elementToVFXBuffer.Store2(elementToVFXIndex << 2, asuint(vertPos.xy / vertPos.w)); elementToVFXIndex += 2; // 1 verts * 2 floats } } #else UNITY_UNROLL for (int itIndexMatrixRow = 0; itIndexMatrixRow < 3; ++itIndexMatrixRow) { float4 value = elementToVFX[itIndexMatrixRow] * attributes.alive; elementToVFXBuffer.Store4(elementToVFXIndex << 2, asuint(value)); elementToVFXIndex += 4; // 1 row * 4 floats } #endif #endif } } } }
Leave a Comment