Untitled
// This is a copy of the source shader. Modifying this file will not affect the original shader. Shader "Hidden/VFX/SmokeTest/System/Output Particle Quad" { SubShader { Cull Off Tags { "Queue"="Transparent+0" "IgnoreProjector"="True" "RenderType"="Transparent" } // Strips tangent computation Blend SrcAlpha OneMinusSrcAlpha ZTest LEqual ZWrite Off Cull Off HLSLINCLUDE #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 VFX_USE_COLOR_CURRENT 1 #define RAW_CAPACITY 4000u #define VFX_COLORMAPPING_DEFAULT 1 #define IS_TRANSPARENT_PARTICLE 1 #define USE_SOFT_PARTICLE 1 #define VFX_BLENDMODE_ALPHA 1 #define VFX_HAS_INDIRECT_DRAW 1 #define USE_FLIPBOOK 1 #define USE_DEAD_LIST_COUNT 1 #define VFX_PRIMITIVE_QUAD 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 4000 #pragma multi_compile_instancing #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; float3 color; }; struct VFXSourceAttributes { }; #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 #if VFX_USE_INSTANCING #define VFX_VERTEX_OUTPUT_INSTANCE_INDEX nointerpolation uint2 instanceIndices : INDEX0; //instanceCurrentIndex, instanceActiveIndex #define VFX_VARYINGS_INSTANCE_CURRENT_INDEX instanceIndices.x #define VFX_VARYINGS_INSTANCE_ACTIVE_INDEX instanceIndices.y #ifdef UNITY_INSTANCING_ENABLED #define VFX_FRAG_SETUP_INSTANCE_ID(i) unity_InstanceID = i.VFX_VARYINGS_INSTANCE_CURRENT_INDEX #else #define VFX_FRAG_SETUP_INSTANCE_ID(i) #endif #else #define VFX_VERTEX_OUTPUT_INSTANCE_INDEX #endif ByteAddressBuffer attributeBuffer; #if VFX_HAS_INDIRECT_DRAW StructuredBuffer<uint> indirectBuffer; #endif #if USE_DEAD_LIST_COUNT StructuredBuffer<uint> deadListCount; #endif #if HAS_STRIPS StructuredBuffer<uint> stripDataBuffer; #endif #if VFX_FEATURE_MOTION_VECTORS ByteAddressBuffer elementToVFXBufferPrevious; #if defined(VFX_FEATURE_MOTION_VECTORS_VERTS) #define VFX_DECLARE_MOTION_VECTORS_STORAGE(coordA, coordB)\ noperspective float4 cPosPreviousAndNonJiterred : TEXCOORD##coordA; #define VFX_DECLARE_MOTION_VECTORS_VARYING_PREVIOUS cPosPreviousAndNonJiterred.xy #define VFX_DECLARE_MOTION_VECTORS_VARYING_NONJITTER cPosPreviousAndNonJiterred.zw #else #define VFX_DECLARE_MOTION_VECTORS_STORAGE(coordA, coordB)\ float4 cPosPrevious : TEXCOORD##coordA;\ float4 cPosNonJiterred : TEXCOORD##coordB; #define VFX_DECLARE_MOTION_VECTORS_VARYING_PREVIOUS cPosPrevious #define VFX_DECLARE_MOTION_VECTORS_VARYING_NONJITTER cPosNonJiterred #endif #endif CBUFFER_START(outputParamsConst) 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) i.instanceID #endif ENDHLSL Pass { Tags { "LightMode"="SceneSelectionPass" } ZWrite On Blend Off HLSLPROGRAM #define VFX_PASSDEPTH VFX_PASSDEPTH_SELECTION #pragma target 4.5 #if SHADERGRAPH_NEEDS_NORMAL_DEPTHONLY || defined(WRITE_NORMAL_BUFFER) || FORCE_NORMAL_OUTPUT_UNLIT_VERTEX_SHADER #define NEEDS_NORMAL 1 #endif #if SHADERGRAPH_NEEDS_TANGENT_DEPTHONLY #define NEEDS_TANGENT 1 #endif struct ps_input { float4 pos : SV_POSITION; #if USE_FLIPBOOK_INTERPOLATION float4 uv : TEXCOORD0; #else #if USE_FLIPBOOK_ARRAY_LAYOUT float3 uv : TEXCOORD0; #else float2 uv : TEXCOORD0; #endif #endif #if USE_ALPHA_TEST || USE_FLIPBOOK_INTERPOLATION || VFX_USE_ALPHA_CURRENT // x: alpha threshold // y: frame blending factor // z: alpha VFX_OPTIONAL_INTERPOLATION float3 builtInInterpolants : TEXCOORD1; #endif #if USE_FLIPBOOK_MOTIONVECTORS // x: motion vectors scale X // y: motion vectors scale Y VFX_OPTIONAL_INTERPOLATION float2 builtInInterpolants2 : TEXCOORD2; #endif #if VFX_PASSDEPTH == VFX_PASSDEPTH_MOTION_VECTOR VFX_DECLARE_MOTION_VECTORS_STORAGE(3,4) #endif #if VFX_NEEDS_POSWS_INTERPOLATOR float3 posWS : TEXCOORD5; #endif #if NEEDS_NORMAL float3 normal : TEXCOORD6; #endif #if NEEDS_TANGENT float4 tangent : TEXCOORD7; #endif UNITY_VERTEX_OUTPUT_STEREO VFX_VERTEX_OUTPUT_INSTANCE_INDEX }; #define VFX_VARYING_PS_INPUTS ps_input #define VFX_VARYING_POSCS pos #define VFX_VARYING_ALPHA builtInInterpolants.z #define VFX_VARYING_ALPHATHRESHOLD builtInInterpolants.x #define VFX_VARYING_FRAMEBLEND builtInInterpolants.y #define VFX_VARYING_MOTIONVECTORSCALE builtInInterpolants2.xy #define VFX_VARYING_UV uv #if VFX_NEEDS_POSWS_INTERPOLATOR #define VFX_VARYING_POSWS posWS #endif #if NEEDS_NORMAL #define VFX_VARYING_NORMAL normal #endif #if NEEDS_TANGENT #define VFX_VARYING_TANGENT tangent #endif #if VFX_PASSDEPTH == VFX_PASSDEPTH_MOTION_VECTOR #define VFX_VARYING_VELOCITY_CPOS VFX_DECLARE_MOTION_VECTORS_VARYING_NONJITTER #define VFX_VARYING_VELOCITY_CPOS_PREVIOUS VFX_DECLARE_MOTION_VECTORS_VARYING_PREVIOUS #endif #if VFX_PASSDEPTH == VFX_PASSDEPTH_MOTION_VECTOR #define SHADERPASS SHADERPASS_MOTION_VECTORS #elif VFX_PASSDEPTH == VFX_PASSDEPTH_SHADOW #define SHADERPASS SHADERPASS_SHADOWS #elif VFX_PASSDEPTH == VFX_PASSDEPTH_ACTUAL || VFX_PASSDEPTH == VFX_PASSDEPTH_SELECTION || VFX_PASSDEPTH == VFX_PASSDEPTH_PICKING #if defined(WRITE_NORMAL_BUFFER) #define SHADERPASS SHADERPASS_DEPTHNORMALSONLY #else #define SHADERPASS SHADERPASS_DEPTHONLY #endif #endif #if !(defined(VFX_VARYING_PS_INPUTS) && defined(VFX_VARYING_POSCS)) #error VFX_VARYING_PS_INPUTS, VFX_VARYING_POSCS and VFX_VARYING_UV must be defined. #endif #include "Packages/com.unity.render-pipelines.universal/Runtime/VFXGraph/Shaders/VFXCommon.hlsl" #include "Packages/com.unity.visualeffectgraph/Shaders/VFXCommon.hlsl" #include "Packages/com.unity.visualeffectgraph/Shaders/VFXCommonOutput.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 defined(HAS_STRIPS) && !defined(VFX_PRIMITIVE_QUAD) #error VFX_PRIMITIVE_QUAD must be defined when HAS_STRIPS is. #endif #define VFX_NON_UNIFORM_SCALE VFX_LOCAL_SPACE struct vs_input { VFX_DECLARE_INSTANCE_ID }; #if HAS_STRIPS #define PARTICLE_IN_EDGE (id & 1) 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 #pragma vertex vert VFX_VARYING_PS_INPUTS vert(uint id : SV_VertexID, vs_input i) { VFX_VARYING_PS_INPUTS o = (VFX_VARYING_PS_INPUTS)0; UNITY_SETUP_INSTANCE_ID(i); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); #if VFX_PRIMITIVE_TRIANGLE uint index = id / 3; #elif VFX_PRIMITIVE_QUAD #if HAS_STRIPS id += VFX_GET_INSTANCE_ID(i) * 8192; const uint vertexPerStripCount = (PARTICLE_PER_STRIP_COUNT - 1) << 2; uint index = id / vertexPerStripCount; // stripIndex. Needed by VFXInitInstancing uint instanceIndex, instanceActiveIndex, instanceCurrentIndex; index = VFXInitInstancing(index, instanceIndex, instanceActiveIndex, instanceCurrentIndex); const StripData stripData = GetStripDataFromStripIndex(index, instanceIndex); uint relativeIndexInStrip = ((id % vertexPerStripCount) >> 2) + (id & 1); // relative index of particle uint maxEdgeIndex = relativeIndexInStrip - PARTICLE_IN_EDGE + 1; if (maxEdgeIndex >= stripData.nextIndex) return o; index = GetParticleIndex(relativeIndexInStrip, stripData); #else uint index = (id >> 2) + VFX_GET_INSTANCE_ID(i) * 2048; #endif #elif VFX_PRIMITIVE_OCTAGON uint index = (id >> 3) + VFX_GET_INSTANCE_ID(i) * 1024; #endif #if !HAS_STRIPS // With strips we need to derive the instance index prior to get the particle index uint instanceIndex, instanceActiveIndex, instanceCurrentIndex; index = VFXInitInstancing(index, instanceIndex, instanceActiveIndex, instanceCurrentIndex); #endif 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)); ContextData contextData = instancingContextData[instanceActiveIndex]; uint systemSeed = contextData.systemSeed; uint nbMax = contextData.maxParticleCount; uint deadCount = 0; #if USE_DEAD_LIST_COUNT deadCount = deadListCount[instanceIndex]; #endif #if VFX_USE_INSTANCING if (index >= nbMax - deadCount) #else if (index >= asuint(nbMax) - deadCount) #endif { #if USE_GEOMETRY_SHADER return; // cull #else o.pos.x = VFX_NAN; return o; // cull #endif } VFXAttributes attributes = (VFXAttributes)0; VFXSourceAttributes sourceAttributes = (VFXSourceAttributes)0; #if VFX_HAS_INDIRECT_DRAW index = indirectBuffer[VFXGetIndirectBufferIndex(index, instanceActiveIndex)]; 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.alive = (attributeBuffer.Load(((instanceIndex * 0xEC40) + (index * 0x8 + 0x3)) << 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)); attributes.color = float3(1, 1, 1); #else attributes.alive = (attributeBuffer.Load(((instanceIndex * 0xEC40) + (index * 0x8 + 0x3)) << 2)); #if !HAS_STRIPS if (!attributes.alive) { o.pos.x = VFX_NAN; return o; // cull } #endif 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)); attributes.color = float3(1, 1, 1); #endif // Initialize built-in needed attributes #if HAS_STRIPS InitStripAttributes(index, attributes, 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); } #if !HAS_STRIPS if (!attributes.alive) return o; #endif #if VFX_PRIMITIVE_QUAD #if HAS_STRIPS #if VFX_STRIPS_UV_STRECHED o.VFX_VARYING_UV.x = (float)(relativeIndexInStrip) / (stripData.nextIndex - 1); #elif VFX_STRIPS_UV_PER_SEGMENT o.VFX_VARYING_UV.x = PARTICLE_IN_EDGE; #else o.VFX_VARYING_UV.x = texCoord; #endif o.VFX_VARYING_UV.y = (id & 2) * 0.5f; const float2 vOffsets = float2(0.0f,o.VFX_VARYING_UV.y - 0.5f); #if VFX_STRIPS_SWAP_UV o.VFX_VARYING_UV.xy = float2(1.0f - o.VFX_VARYING_UV.y, o.VFX_VARYING_UV.x); #endif #else o.VFX_VARYING_UV.x = float(id & 1); o.VFX_VARYING_UV.y = (id & 2) * 0.5f; const float2 vOffsets = o.VFX_VARYING_UV.xy - 0.5f; #endif #elif VFX_PRIMITIVE_TRIANGLE const float2 kOffsets[] = { float2(-0.5f, -0.288675129413604736328125f), float2(0.0f, 0.57735025882720947265625f), float2(0.5f, -0.288675129413604736328125f), }; const float kUVScale = 0.866025388240814208984375f; const float2 vOffsets = kOffsets[id % 3]; o.VFX_VARYING_UV.xy = (vOffsets * kUVScale) + 0.5f; #elif VFX_PRIMITIVE_OCTAGON const float2 kUvs[8] = { float2(-0.5f, 0.0f), float2(-0.5f, 0.5f), float2(0.0f, 0.5f), float2(0.5f, 0.5f), float2(0.5f, 0.0f), float2(0.5f, -0.5f), float2(0.0f, -0.5f), float2(-0.5f, -0.5f), }; cropFactor = id & 1 ? 1.0f - cropFactor : 1.0f; const float2 vOffsets = kUvs[id & 7] * cropFactor; o.VFX_VARYING_UV.xy = vOffsets + 0.5f; #endif 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 size3 += size3 < 0.0f ? -VFX_EPSILON : VFX_EPSILON; // Add an epsilon so that size is never 0 for strips #endif const 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); float3 inputVertexPosition = float3(vOffsets, 0.0f); float3 vPos = mul(elementToVFX,float4(inputVertexPosition, 1.0f)).xyz; o.VFX_VARYING_POSCS = TransformPositionVFXToClip(vPos); float3 vPosWS = TransformPositionVFXToWorld(vPos); #ifdef VFX_VARYING_POSWS o.VFX_VARYING_POSWS = vPosWS; #endif #if VFX_NON_UNIFORM_SCALE float3x3 elementToVFX_N = GetElementToVFXMatrixNormal( attributes.axisX, attributes.axisY, attributes.axisZ, float3(attributes.angleX,attributes.angleY,attributes.angleZ), size3); #else float3x3 elementToVFX_N = (float3x3)elementToVFX; #endif float3 normalWS = normalize(TransformNormalVFXToWorld((-transpose(elementToVFX_N)[2]))); #ifdef VFX_VARYING_NORMAL float normalFlip = (size3.x * size3.y * size3.z) < 0 ? -1 : 1; o.VFX_VARYING_NORMAL = normalFlip * normalWS; #endif #ifdef VFX_VARYING_TANGENT o.VFX_VARYING_TANGENT.xyz = normalize(TransformDirectionVFXToWorld(normalize(transpose(elementToVFX)[0].xyz))); #endif #ifdef VFX_VARYING_BENTFACTORS #if HAS_STRIPS #define BENT_FACTOR_MULTIPLIER 2.0f #else #define BENT_FACTOR_MULTIPLIER 1.41421353816986083984375f #endif o.VFX_VARYING_BENTFACTORS = vOffsets * normalBendingFactor * BENT_FACTOR_MULTIPLIER; #endif #if VFX_FEATURE_MOTION_VECTORS && defined(VFX_VARYING_VELOCITY_CPOS_PREVIOUS) && defined(VFX_VARYING_VELOCITY_CPOS) #ifdef VFX_FEATURE_MOTION_VECTORS_VERTS o.VFX_VARYING_VELOCITY_CPOS_PREVIOUS = o.VFX_VARYING_VELOCITY_CPOS = (float2)0.0f; #else o.VFX_VARYING_VELOCITY_CPOS_PREVIOUS = o.VFX_VARYING_VELOCITY_CPOS = float4(0.0f, 0.0f, 0.0f, 1.0f); #endif uint elementToVFXBaseIndex; if (TryGetElementToVFXBaseIndex(index, instanceIndex, elementToVFXBaseIndex, currentFrameIndex)) { float4 cPos = TransformPositionVFXToNonJitteredClip(vPos); #ifdef VFX_FEATURE_MOTION_VECTORS_VERTS o.VFX_VARYING_VELOCITY_CPOS_PREVIOUS = VFXGetPreviousClipPosition(elementToVFXBaseIndex, id).xy; o.VFX_VARYING_VELOCITY_CPOS = cPos.xy / cPos.w; #else float4x4 previousElementToVFX = VFXGetPreviousElementToVFX(elementToVFXBaseIndex); float3 oldvPos = mul(previousElementToVFX, float4(inputVertexPosition, 1.0f)).xyz; o.VFX_VARYING_VELOCITY_CPOS_PREVIOUS = TransformPositionVFXToPreviousClip(oldvPos); o.VFX_VARYING_VELOCITY_CPOS = cPos; #endif } #endif #if VFX_USE_COLOR_CURRENT && defined(VFX_VARYING_COLOR) o.VFX_VARYING_COLOR = attributes.color; #endif #if VFX_USE_ALPHA_CURRENT && defined(VFX_VARYING_ALPHA) o.VFX_VARYING_ALPHA = attributes.alpha; #endif #ifdef VFX_VARYING_EXPOSUREWEIGHT o.VFX_VARYING_EXPOSUREWEIGHT = exposureWeight; #endif #if USE_SOFT_PARTICLE && defined(VFX_VARYING_INVSOFTPARTICLEFADEDISTANCE) float invSoftParticlesFadeDistance = (float)0; { invSoftParticlesFadeDistance = graphValues.invSoftParticlesFadeDistance_a; } o.VFX_VARYING_INVSOFTPARTICLEFADEDISTANCE = invSoftParticlesFadeDistance; #endif #if (USE_ALPHA_TEST || VFX_FEATURE_MOTION_VECTORS_FORWARD) && (!VFX_SHADERGRAPH || !HAS_SHADERGRAPH_PARAM_ALPHACLIPTHRESHOLD) && defined(VFX_VARYING_ALPHATHRESHOLD) o.VFX_VARYING_ALPHATHRESHOLD = alphaThreshold; #endif #if USE_UV_SCALE_BIAS #if defined (VFX_VARYING_UV) o.VFX_VARYING_UV.xy = o.VFX_VARYING_UV.xy * uvScale + uvBias; #endif #endif #ifdef VFX_VARYING_ANGLEFADE o.VFX_VARYING_ANGLEFADE = angleFade; #endif #ifdef VFX_VARYING_FADEFACTOR o.VFX_VARYING_FADEFACTOR = fadeFactor; #endif #ifdef VFX_VARYING_DECALLAYER o.VFX_VARYING_DECALLAYER = decalLayerMask; #endif #if defined(VFX_VARYING_POSWS) o.VFX_VARYING_POSWS = TransformPositionVFXToWorld(vPos); #endif #if VFX_USE_INSTANCING #ifdef UNITY_INSTANCING_ENABLED o.VFX_VARYINGS_INSTANCE_CURRENT_INDEX = unity_InstanceID; #endif o.VFX_VARYINGS_INSTANCE_ACTIVE_INDEX = instanceActiveIndex; #endif #if USE_FLIPBOOK && defined(VFX_VARYING_UV) #if USE_FLIPBOOK_ARRAY_LAYOUT float2 flipBookSize = (float2)0; { flipBookSize = graphValues.flipBookSize_a; } VFXUVData uvData = GetUVData(flipBookSize, o.VFX_VARYING_UV.xy, attributes.texIndex); o.VFX_VARYING_UV.xyz = uvData.uvs.xyz; #if USE_FLIPBOOK_INTERPOLATION && defined(VFX_VARYING_UV) && defined (VFX_VARYING_FRAMEBLEND) o.VFX_VARYING_UV.w = uvData.uvs.w; o.VFX_VARYING_FRAMEBLEND = uvData.blend; #if USE_FLIPBOOK_MOTIONVECTORS && defined(VFX_VARYING_MOTIONVECTORSCALE) o.VFX_VARYING_MOTIONVECTORSCALE = motionVectorScale; #endif #endif #else float2 invFlipBookSize = (float2)0; { invFlipBookSize = graphValues.invFlipBookSize_a; } float2 flipBookSize = (float2)0; { flipBookSize = graphValues.flipBookSize_a; } VFXUVData uvData = GetUVData(flipBookSize, invFlipBookSize, o.VFX_VARYING_UV.xy, attributes.texIndex); o.VFX_VARYING_UV.xy = uvData.uvs.xy; #if USE_FLIPBOOK_INTERPOLATION && defined(VFX_VARYING_UV) && defined (VFX_VARYING_FRAMEBLEND) o.VFX_VARYING_UV.zw = uvData.uvs.zw; o.VFX_VARYING_FRAMEBLEND = uvData.blend; #if USE_FLIPBOOK_MOTIONVECTORS && defined(VFX_VARYING_MOTIONVECTORSCALE) o.VFX_VARYING_MOTIONVECTORSCALE = motionVectorScale * invFlipBookSize; #endif #endif #endif #endif #if VFX_PASSDEPTH == VFX_PASSDEPTH_SHADOW float3 posWS = TransformPositionVFXToWorld(vPos); VFXApplyShadowBias(o.VFX_VARYING_POSCS, posWS, normalWS); #endif return o; } #define VFX_SUPPORT_MAIN_TEXTURE_SAMPLING_IN_FRAGMENT_DEPTH 1 #ifndef VFX_SUPPORT_MAIN_TEXTURE_SAMPLING_IN_FRAGMENT_DEPTH #define VFX_SUPPORT_MAIN_TEXTURE_SAMPLING_IN_FRAGMENT_DEPTH 0 #endif #ifdef VFX_SHADERGRAPH #if (SHADERPASS == SHADERPASS_DEPTHNORMALSONLY) #else #endif #endif #if VFX_PASSDEPTH == VFX_PASSDEPTH_SELECTION int _ObjectId; int _PassValue; #elif VFX_PASSDEPTH == VFX_PASSDEPTH_PICKING float4 _SelectionID; #endif #pragma fragment frag void frag(ps_input i #if VFX_PASSDEPTH == VFX_PASSDEPTH_MOTION_VECTOR #ifdef WRITE_MSAA_DEPTH // We need the depth color as SV_Target0 for alpha to coverage , out float4 outDepthColor : SV_Target0 , out float4 outMotionVector : SV_Target1 #else // When no MSAA, the motion vector is always the first buffer , out float4 outMotionVector : SV_Target0 #endif #elif VFX_PASSDEPTH == VFX_PASSDEPTH_ACTUAL #if defined(WRITE_MSAA_DEPTH) #if defined(WRITE_NORMAL_BUFFER) #error Unexpected depth setup mssa + depth normal #endif , out float4 outDepthColor : SV_Target0 #elif defined(WRITE_NORMAL_BUFFER) , out float4 outNormalBuffer : SV_Target0 #else , out float4 dummy : SV_Target0 #endif #elif VFX_PASSDEPTH == VFX_PASSDEPTH_SELECTION || VFX_PASSDEPTH == VFX_PASSDEPTH_PICKING , out float4 outSelection : SV_Target0 #elif VFX_PASSDEPTH == VFX_PASSDEPTH_SHADOW , out float4 dummy : SV_Target0 #endif ) { UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i); VFXTransformPSInputs(i); #ifdef VFX_VARYING_NORMAL #if USE_DOUBLE_SIDED const float faceMul = frontFace ? 1.0f : -1.0f; #else const float faceMul = 1.0f; #endif float3 normalWS = i.VFX_VARYING_NORMAL * faceMul; const VFXUVData uvData = GetUVData(i); #ifdef VFX_VARYING_TANGENT float3 tangentWS = i.VFX_VARYING_TANGENT; float3 bitangentWS = cross(i.VFX_VARYING_TANGENT,i.VFX_VARYING_NORMAL); #if defined(VFX_VARYING_BENTFACTORS) && USE_NORMAL_BENDING float3 bentFactors = float3(i.VFX_VARYING_BENTFACTORS.xy,sqrt(max(0.0f,1.0f - dot(i.VFX_VARYING_BENTFACTORS,i.VFX_VARYING_BENTFACTORS)))); normalWS = tangentWS * bentFactors.x + bitangentWS * bentFactors.y + normalWS * bentFactors.z; tangentWS = normalize(cross(normalWS,bitangentWS)); bitangentWS = cross(tangentWS,normalWS); tangentWS *= faceMul; #endif float3x3 tbn = float3x3(tangentWS,bitangentWS,normalWS); #if USE_NORMAL_MAP float3 n = SampleNormalMap(VFX_SAMPLER(normalMap),uvData); float normalScale = 1.0f; #ifdef VFX_VARYING_NORMALSCALE normalScale = i.VFX_VARYING_NORMALSCALE; #endif normalWS = normalize(lerp(normalWS,mul(n,tbn),normalScale)); #endif #endif #endif #ifdef VFX_SHADERGRAPH #if (SHADERPASS == SHADERPASS_DEPTHNORMALSONLY) #else #endif float alpha = OUTSG.; #else float alpha = VFXGetFragmentColor(i).a; #if VFX_SUPPORT_MAIN_TEXTURE_SAMPLING_IN_FRAGMENT_DEPTH #ifdef VFX_PROCEDURAL_UV alpha *= VFXGetTextureColorWithProceduralUV(VFX_SAMPLER(mainTexture),i,VFX_PROCEDURAL_UV(i)).a; #else alpha *= VFXGetTextureColor(VFX_SAMPLER(mainTexture),i).a; #endif #endif #endif VFXClipFragmentColor(alpha,i); #ifdef WRITE_MSAA_DEPTH outDepthColor = i.VFX_VARYING_POSCS.z; #if VFX_USE_ALPHA_TO_MASK outDepthColor.a = alpha; #endif #endif #ifdef WRITE_NORMAL_BUFFER #ifdef VFX_VARYING_NORMAL VFXComputePixelOutputToNormalBuffer(i, normalWS, GetUVData(i), outNormalBuffer); #else //Fallback for point and lines, render normal as if those are face camera plane VFXComputePixelOutputToNormalBuffer(i, VFXGetWorldToViewRotMatrix()[2], GetUVData(i), outNormalBuffer); #endif #endif #if VFX_PASSDEPTH == VFX_PASSDEPTH_MOTION_VECTOR //No w division with fast path of motion vectors #ifdef VFX_FEATURE_MOTION_VECTORS_VERTS float2 velocity = i.VFX_VARYING_VELOCITY_CPOS - i.VFX_VARYING_VELOCITY_CPOS_PREVIOUS; #else float2 velocity = (i.VFX_VARYING_VELOCITY_CPOS.xy/i.VFX_VARYING_VELOCITY_CPOS.w) - (i.VFX_VARYING_VELOCITY_CPOS_PREVIOUS.xy/i.VFX_VARYING_VELOCITY_CPOS_PREVIOUS.w); #endif #if UNITY_UV_STARTS_AT_TOP velocity.y = -velocity.y; #endif float4 encodedMotionVector = 0.0f; VFXEncodeMotionVector(velocity * 0.5f, encodedMotionVector); outMotionVector = encodedMotionVector; #elif VFX_PASSDEPTH == VFX_PASSDEPTH_SELECTION outSelection = float4(_ObjectId, _PassValue, 1.0, 1.0); #elif VFX_PASSDEPTH == VFX_PASSDEPTH_PICKING outSelection = _SelectionID; #elif VFX_PASSDEPTH == VFX_PASSDEPTH_ACTUAL #if !defined(WRITE_MSAA_DEPTH) && !defined(WRITE_NORMAL_BUFFER) dummy = float4(i.VFX_VARYING_POSCS.z, 0,0,0); #endif #elif VFX_PASSDEPTH == VFX_PASSDEPTH_SHADOW dummy = (float4)0; #else #error VFX_PASSDEPTH undefined #endif } ENDHLSL } Pass { Tags { "LightMode"="Picking" } ZWrite On Blend Off HLSLPROGRAM #define VFX_PASSDEPTH VFX_PASSDEPTH_PICKING #pragma target 4.5 #if SHADERGRAPH_NEEDS_NORMAL_DEPTHONLY || defined(WRITE_NORMAL_BUFFER) || FORCE_NORMAL_OUTPUT_UNLIT_VERTEX_SHADER #define NEEDS_NORMAL 1 #endif #if SHADERGRAPH_NEEDS_TANGENT_DEPTHONLY #define NEEDS_TANGENT 1 #endif struct ps_input { float4 pos : SV_POSITION; #if USE_FLIPBOOK_INTERPOLATION float4 uv : TEXCOORD0; #else #if USE_FLIPBOOK_ARRAY_LAYOUT float3 uv : TEXCOORD0; #else float2 uv : TEXCOORD0; #endif #endif #if USE_ALPHA_TEST || USE_FLIPBOOK_INTERPOLATION || VFX_USE_ALPHA_CURRENT // x: alpha threshold // y: frame blending factor // z: alpha VFX_OPTIONAL_INTERPOLATION float3 builtInInterpolants : TEXCOORD1; #endif #if USE_FLIPBOOK_MOTIONVECTORS // x: motion vectors scale X // y: motion vectors scale Y VFX_OPTIONAL_INTERPOLATION float2 builtInInterpolants2 : TEXCOORD2; #endif #if VFX_PASSDEPTH == VFX_PASSDEPTH_MOTION_VECTOR VFX_DECLARE_MOTION_VECTORS_STORAGE(3,4) #endif #if VFX_NEEDS_POSWS_INTERPOLATOR float3 posWS : TEXCOORD5; #endif #if NEEDS_NORMAL float3 normal : TEXCOORD6; #endif #if NEEDS_TANGENT float4 tangent : TEXCOORD7; #endif UNITY_VERTEX_OUTPUT_STEREO VFX_VERTEX_OUTPUT_INSTANCE_INDEX }; #define VFX_VARYING_PS_INPUTS ps_input #define VFX_VARYING_POSCS pos #define VFX_VARYING_ALPHA builtInInterpolants.z #define VFX_VARYING_ALPHATHRESHOLD builtInInterpolants.x #define VFX_VARYING_FRAMEBLEND builtInInterpolants.y #define VFX_VARYING_MOTIONVECTORSCALE builtInInterpolants2.xy #define VFX_VARYING_UV uv #if VFX_NEEDS_POSWS_INTERPOLATOR #define VFX_VARYING_POSWS posWS #endif #if NEEDS_NORMAL #define VFX_VARYING_NORMAL normal #endif #if NEEDS_TANGENT #define VFX_VARYING_TANGENT tangent #endif #if VFX_PASSDEPTH == VFX_PASSDEPTH_MOTION_VECTOR #define VFX_VARYING_VELOCITY_CPOS VFX_DECLARE_MOTION_VECTORS_VARYING_NONJITTER #define VFX_VARYING_VELOCITY_CPOS_PREVIOUS VFX_DECLARE_MOTION_VECTORS_VARYING_PREVIOUS #endif #if VFX_PASSDEPTH == VFX_PASSDEPTH_MOTION_VECTOR #define SHADERPASS SHADERPASS_MOTION_VECTORS #elif VFX_PASSDEPTH == VFX_PASSDEPTH_SHADOW #define SHADERPASS SHADERPASS_SHADOWS #elif VFX_PASSDEPTH == VFX_PASSDEPTH_ACTUAL || VFX_PASSDEPTH == VFX_PASSDEPTH_SELECTION || VFX_PASSDEPTH == VFX_PASSDEPTH_PICKING #if defined(WRITE_NORMAL_BUFFER) #define SHADERPASS SHADERPASS_DEPTHNORMALSONLY #else #define SHADERPASS SHADERPASS_DEPTHONLY #endif #endif #if !(defined(VFX_VARYING_PS_INPUTS) && defined(VFX_VARYING_POSCS)) #error VFX_VARYING_PS_INPUTS, VFX_VARYING_POSCS and VFX_VARYING_UV must be defined. #endif #include "Packages/com.unity.render-pipelines.universal/Runtime/VFXGraph/Shaders/VFXCommon.hlsl" #include "Packages/com.unity.visualeffectgraph/Shaders/VFXCommon.hlsl" #include "Packages/com.unity.visualeffectgraph/Shaders/VFXCommonOutput.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 defined(HAS_STRIPS) && !defined(VFX_PRIMITIVE_QUAD) #error VFX_PRIMITIVE_QUAD must be defined when HAS_STRIPS is. #endif #define VFX_NON_UNIFORM_SCALE VFX_LOCAL_SPACE struct vs_input { VFX_DECLARE_INSTANCE_ID }; #if HAS_STRIPS #define PARTICLE_IN_EDGE (id & 1) 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 #pragma vertex vert VFX_VARYING_PS_INPUTS vert(uint id : SV_VertexID, vs_input i) { VFX_VARYING_PS_INPUTS o = (VFX_VARYING_PS_INPUTS)0; UNITY_SETUP_INSTANCE_ID(i); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); #if VFX_PRIMITIVE_TRIANGLE uint index = id / 3; #elif VFX_PRIMITIVE_QUAD #if HAS_STRIPS id += VFX_GET_INSTANCE_ID(i) * 8192; const uint vertexPerStripCount = (PARTICLE_PER_STRIP_COUNT - 1) << 2; uint index = id / vertexPerStripCount; // stripIndex. Needed by VFXInitInstancing uint instanceIndex, instanceActiveIndex, instanceCurrentIndex; index = VFXInitInstancing(index, instanceIndex, instanceActiveIndex, instanceCurrentIndex); const StripData stripData = GetStripDataFromStripIndex(index, instanceIndex); uint relativeIndexInStrip = ((id % vertexPerStripCount) >> 2) + (id & 1); // relative index of particle uint maxEdgeIndex = relativeIndexInStrip - PARTICLE_IN_EDGE + 1; if (maxEdgeIndex >= stripData.nextIndex) return o; index = GetParticleIndex(relativeIndexInStrip, stripData); #else uint index = (id >> 2) + VFX_GET_INSTANCE_ID(i) * 2048; #endif #elif VFX_PRIMITIVE_OCTAGON uint index = (id >> 3) + VFX_GET_INSTANCE_ID(i) * 1024; #endif #if !HAS_STRIPS // With strips we need to derive the instance index prior to get the particle index uint instanceIndex, instanceActiveIndex, instanceCurrentIndex; index = VFXInitInstancing(index, instanceIndex, instanceActiveIndex, instanceCurrentIndex); #endif 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)); ContextData contextData = instancingContextData[instanceActiveIndex]; uint systemSeed = contextData.systemSeed; uint nbMax = contextData.maxParticleCount; uint deadCount = 0; #if USE_DEAD_LIST_COUNT deadCount = deadListCount[instanceIndex]; #endif #if VFX_USE_INSTANCING if (index >= nbMax - deadCount) #else if (index >= asuint(nbMax) - deadCount) #endif { #if USE_GEOMETRY_SHADER return; // cull #else o.pos.x = VFX_NAN; return o; // cull #endif } VFXAttributes attributes = (VFXAttributes)0; VFXSourceAttributes sourceAttributes = (VFXSourceAttributes)0; #if VFX_HAS_INDIRECT_DRAW index = indirectBuffer[VFXGetIndirectBufferIndex(index, instanceActiveIndex)]; 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.alive = (attributeBuffer.Load(((instanceIndex * 0xEC40) + (index * 0x8 + 0x3)) << 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)); attributes.color = float3(1, 1, 1); #else attributes.alive = (attributeBuffer.Load(((instanceIndex * 0xEC40) + (index * 0x8 + 0x3)) << 2)); #if !HAS_STRIPS if (!attributes.alive) { o.pos.x = VFX_NAN; return o; // cull } #endif 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)); attributes.color = float3(1, 1, 1); #endif // Initialize built-in needed attributes #if HAS_STRIPS InitStripAttributes(index, attributes, 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); } #if !HAS_STRIPS if (!attributes.alive) return o; #endif #if VFX_PRIMITIVE_QUAD #if HAS_STRIPS #if VFX_STRIPS_UV_STRECHED o.VFX_VARYING_UV.x = (float)(relativeIndexInStrip) / (stripData.nextIndex - 1); #elif VFX_STRIPS_UV_PER_SEGMENT o.VFX_VARYING_UV.x = PARTICLE_IN_EDGE; #else o.VFX_VARYING_UV.x = texCoord; #endif o.VFX_VARYING_UV.y = (id & 2) * 0.5f; const float2 vOffsets = float2(0.0f,o.VFX_VARYING_UV.y - 0.5f); #if VFX_STRIPS_SWAP_UV o.VFX_VARYING_UV.xy = float2(1.0f - o.VFX_VARYING_UV.y, o.VFX_VARYING_UV.x); #endif #else o.VFX_VARYING_UV.x = float(id & 1); o.VFX_VARYING_UV.y = (id & 2) * 0.5f; const float2 vOffsets = o.VFX_VARYING_UV.xy - 0.5f; #endif #elif VFX_PRIMITIVE_TRIANGLE const float2 kOffsets[] = { float2(-0.5f, -0.288675129413604736328125f), float2(0.0f, 0.57735025882720947265625f), float2(0.5f, -0.288675129413604736328125f), }; const float kUVScale = 0.866025388240814208984375f; const float2 vOffsets = kOffsets[id % 3]; o.VFX_VARYING_UV.xy = (vOffsets * kUVScale) + 0.5f; #elif VFX_PRIMITIVE_OCTAGON const float2 kUvs[8] = { float2(-0.5f, 0.0f), float2(-0.5f, 0.5f), float2(0.0f, 0.5f), float2(0.5f, 0.5f), float2(0.5f, 0.0f), float2(0.5f, -0.5f), float2(0.0f, -0.5f), float2(-0.5f, -0.5f), }; cropFactor = id & 1 ? 1.0f - cropFactor : 1.0f; const float2 vOffsets = kUvs[id & 7] * cropFactor; o.VFX_VARYING_UV.xy = vOffsets + 0.5f; #endif 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 size3 += size3 < 0.0f ? -VFX_EPSILON : VFX_EPSILON; // Add an epsilon so that size is never 0 for strips #endif const 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); float3 inputVertexPosition = float3(vOffsets, 0.0f); float3 vPos = mul(elementToVFX,float4(inputVertexPosition, 1.0f)).xyz; o.VFX_VARYING_POSCS = TransformPositionVFXToClip(vPos); float3 vPosWS = TransformPositionVFXToWorld(vPos); #ifdef VFX_VARYING_POSWS o.VFX_VARYING_POSWS = vPosWS; #endif #if VFX_NON_UNIFORM_SCALE float3x3 elementToVFX_N = GetElementToVFXMatrixNormal( attributes.axisX, attributes.axisY, attributes.axisZ, float3(attributes.angleX,attributes.angleY,attributes.angleZ), size3); #else float3x3 elementToVFX_N = (float3x3)elementToVFX; #endif float3 normalWS = normalize(TransformNormalVFXToWorld((-transpose(elementToVFX_N)[2]))); #ifdef VFX_VARYING_NORMAL float normalFlip = (size3.x * size3.y * size3.z) < 0 ? -1 : 1; o.VFX_VARYING_NORMAL = normalFlip * normalWS; #endif #ifdef VFX_VARYING_TANGENT o.VFX_VARYING_TANGENT.xyz = normalize(TransformDirectionVFXToWorld(normalize(transpose(elementToVFX)[0].xyz))); #endif #ifdef VFX_VARYING_BENTFACTORS #if HAS_STRIPS #define BENT_FACTOR_MULTIPLIER 2.0f #else #define BENT_FACTOR_MULTIPLIER 1.41421353816986083984375f #endif o.VFX_VARYING_BENTFACTORS = vOffsets * normalBendingFactor * BENT_FACTOR_MULTIPLIER; #endif #if VFX_FEATURE_MOTION_VECTORS && defined(VFX_VARYING_VELOCITY_CPOS_PREVIOUS) && defined(VFX_VARYING_VELOCITY_CPOS) #ifdef VFX_FEATURE_MOTION_VECTORS_VERTS o.VFX_VARYING_VELOCITY_CPOS_PREVIOUS = o.VFX_VARYING_VELOCITY_CPOS = (float2)0.0f; #else o.VFX_VARYING_VELOCITY_CPOS_PREVIOUS = o.VFX_VARYING_VELOCITY_CPOS = float4(0.0f, 0.0f, 0.0f, 1.0f); #endif uint elementToVFXBaseIndex; if (TryGetElementToVFXBaseIndex(index, instanceIndex, elementToVFXBaseIndex, currentFrameIndex)) { float4 cPos = TransformPositionVFXToNonJitteredClip(vPos); #ifdef VFX_FEATURE_MOTION_VECTORS_VERTS o.VFX_VARYING_VELOCITY_CPOS_PREVIOUS = VFXGetPreviousClipPosition(elementToVFXBaseIndex, id).xy; o.VFX_VARYING_VELOCITY_CPOS = cPos.xy / cPos.w; #else float4x4 previousElementToVFX = VFXGetPreviousElementToVFX(elementToVFXBaseIndex); float3 oldvPos = mul(previousElementToVFX, float4(inputVertexPosition, 1.0f)).xyz; o.VFX_VARYING_VELOCITY_CPOS_PREVIOUS = TransformPositionVFXToPreviousClip(oldvPos); o.VFX_VARYING_VELOCITY_CPOS = cPos; #endif } #endif #if VFX_USE_COLOR_CURRENT && defined(VFX_VARYING_COLOR) o.VFX_VARYING_COLOR = attributes.color; #endif #if VFX_USE_ALPHA_CURRENT && defined(VFX_VARYING_ALPHA) o.VFX_VARYING_ALPHA = attributes.alpha; #endif #ifdef VFX_VARYING_EXPOSUREWEIGHT o.VFX_VARYING_EXPOSUREWEIGHT = exposureWeight; #endif #if USE_SOFT_PARTICLE && defined(VFX_VARYING_INVSOFTPARTICLEFADEDISTANCE) float invSoftParticlesFadeDistance = (float)0; { invSoftParticlesFadeDistance = graphValues.invSoftParticlesFadeDistance_a; } o.VFX_VARYING_INVSOFTPARTICLEFADEDISTANCE = invSoftParticlesFadeDistance; #endif #if (USE_ALPHA_TEST || VFX_FEATURE_MOTION_VECTORS_FORWARD) && (!VFX_SHADERGRAPH || !HAS_SHADERGRAPH_PARAM_ALPHACLIPTHRESHOLD) && defined(VFX_VARYING_ALPHATHRESHOLD) o.VFX_VARYING_ALPHATHRESHOLD = alphaThreshold; #endif #if USE_UV_SCALE_BIAS #if defined (VFX_VARYING_UV) o.VFX_VARYING_UV.xy = o.VFX_VARYING_UV.xy * uvScale + uvBias; #endif #endif #ifdef VFX_VARYING_ANGLEFADE o.VFX_VARYING_ANGLEFADE = angleFade; #endif #ifdef VFX_VARYING_FADEFACTOR o.VFX_VARYING_FADEFACTOR = fadeFactor; #endif #ifdef VFX_VARYING_DECALLAYER o.VFX_VARYING_DECALLAYER = decalLayerMask; #endif #if defined(VFX_VARYING_POSWS) o.VFX_VARYING_POSWS = TransformPositionVFXToWorld(vPos); #endif #if VFX_USE_INSTANCING #ifdef UNITY_INSTANCING_ENABLED o.VFX_VARYINGS_INSTANCE_CURRENT_INDEX = unity_InstanceID; #endif o.VFX_VARYINGS_INSTANCE_ACTIVE_INDEX = instanceActiveIndex; #endif #if USE_FLIPBOOK && defined(VFX_VARYING_UV) #if USE_FLIPBOOK_ARRAY_LAYOUT float2 flipBookSize = (float2)0; { flipBookSize = graphValues.flipBookSize_a; } VFXUVData uvData = GetUVData(flipBookSize, o.VFX_VARYING_UV.xy, attributes.texIndex); o.VFX_VARYING_UV.xyz = uvData.uvs.xyz; #if USE_FLIPBOOK_INTERPOLATION && defined(VFX_VARYING_UV) && defined (VFX_VARYING_FRAMEBLEND) o.VFX_VARYING_UV.w = uvData.uvs.w; o.VFX_VARYING_FRAMEBLEND = uvData.blend; #if USE_FLIPBOOK_MOTIONVECTORS && defined(VFX_VARYING_MOTIONVECTORSCALE) o.VFX_VARYING_MOTIONVECTORSCALE = motionVectorScale; #endif #endif #else float2 invFlipBookSize = (float2)0; { invFlipBookSize = graphValues.invFlipBookSize_a; } float2 flipBookSize = (float2)0; { flipBookSize = graphValues.flipBookSize_a; } VFXUVData uvData = GetUVData(flipBookSize, invFlipBookSize, o.VFX_VARYING_UV.xy, attributes.texIndex); o.VFX_VARYING_UV.xy = uvData.uvs.xy; #if USE_FLIPBOOK_INTERPOLATION && defined(VFX_VARYING_UV) && defined (VFX_VARYING_FRAMEBLEND) o.VFX_VARYING_UV.zw = uvData.uvs.zw; o.VFX_VARYING_FRAMEBLEND = uvData.blend; #if USE_FLIPBOOK_MOTIONVECTORS && defined(VFX_VARYING_MOTIONVECTORSCALE) o.VFX_VARYING_MOTIONVECTORSCALE = motionVectorScale * invFlipBookSize; #endif #endif #endif #endif #if VFX_PASSDEPTH == VFX_PASSDEPTH_SHADOW float3 posWS = TransformPositionVFXToWorld(vPos); VFXApplyShadowBias(o.VFX_VARYING_POSCS, posWS, normalWS); #endif return o; } #define VFX_SUPPORT_MAIN_TEXTURE_SAMPLING_IN_FRAGMENT_DEPTH 1 #ifndef VFX_SUPPORT_MAIN_TEXTURE_SAMPLING_IN_FRAGMENT_DEPTH #define VFX_SUPPORT_MAIN_TEXTURE_SAMPLING_IN_FRAGMENT_DEPTH 0 #endif #ifdef VFX_SHADERGRAPH #if (SHADERPASS == SHADERPASS_DEPTHNORMALSONLY) #else #endif #endif #if VFX_PASSDEPTH == VFX_PASSDEPTH_SELECTION int _ObjectId; int _PassValue; #elif VFX_PASSDEPTH == VFX_PASSDEPTH_PICKING float4 _SelectionID; #endif #pragma fragment frag void frag(ps_input i #if VFX_PASSDEPTH == VFX_PASSDEPTH_MOTION_VECTOR #ifdef WRITE_MSAA_DEPTH // We need the depth color as SV_Target0 for alpha to coverage , out float4 outDepthColor : SV_Target0 , out float4 outMotionVector : SV_Target1 #else // When no MSAA, the motion vector is always the first buffer , out float4 outMotionVector : SV_Target0 #endif #elif VFX_PASSDEPTH == VFX_PASSDEPTH_ACTUAL #if defined(WRITE_MSAA_DEPTH) #if defined(WRITE_NORMAL_BUFFER) #error Unexpected depth setup mssa + depth normal #endif , out float4 outDepthColor : SV_Target0 #elif defined(WRITE_NORMAL_BUFFER) , out float4 outNormalBuffer : SV_Target0 #else , out float4 dummy : SV_Target0 #endif #elif VFX_PASSDEPTH == VFX_PASSDEPTH_SELECTION || VFX_PASSDEPTH == VFX_PASSDEPTH_PICKING , out float4 outSelection : SV_Target0 #elif VFX_PASSDEPTH == VFX_PASSDEPTH_SHADOW , out float4 dummy : SV_Target0 #endif ) { UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i); VFXTransformPSInputs(i); #ifdef VFX_VARYING_NORMAL #if USE_DOUBLE_SIDED const float faceMul = frontFace ? 1.0f : -1.0f; #else const float faceMul = 1.0f; #endif float3 normalWS = i.VFX_VARYING_NORMAL * faceMul; const VFXUVData uvData = GetUVData(i); #ifdef VFX_VARYING_TANGENT float3 tangentWS = i.VFX_VARYING_TANGENT; float3 bitangentWS = cross(i.VFX_VARYING_TANGENT,i.VFX_VARYING_NORMAL); #if defined(VFX_VARYING_BENTFACTORS) && USE_NORMAL_BENDING float3 bentFactors = float3(i.VFX_VARYING_BENTFACTORS.xy,sqrt(max(0.0f,1.0f - dot(i.VFX_VARYING_BENTFACTORS,i.VFX_VARYING_BENTFACTORS)))); normalWS = tangentWS * bentFactors.x + bitangentWS * bentFactors.y + normalWS * bentFactors.z; tangentWS = normalize(cross(normalWS,bitangentWS)); bitangentWS = cross(tangentWS,normalWS); tangentWS *= faceMul; #endif float3x3 tbn = float3x3(tangentWS,bitangentWS,normalWS); #if USE_NORMAL_MAP float3 n = SampleNormalMap(VFX_SAMPLER(normalMap),uvData); float normalScale = 1.0f; #ifdef VFX_VARYING_NORMALSCALE normalScale = i.VFX_VARYING_NORMALSCALE; #endif normalWS = normalize(lerp(normalWS,mul(n,tbn),normalScale)); #endif #endif #endif #ifdef VFX_SHADERGRAPH #if (SHADERPASS == SHADERPASS_DEPTHNORMALSONLY) #else #endif float alpha = OUTSG.; #else float alpha = VFXGetFragmentColor(i).a; #if VFX_SUPPORT_MAIN_TEXTURE_SAMPLING_IN_FRAGMENT_DEPTH #ifdef VFX_PROCEDURAL_UV alpha *= VFXGetTextureColorWithProceduralUV(VFX_SAMPLER(mainTexture),i,VFX_PROCEDURAL_UV(i)).a; #else alpha *= VFXGetTextureColor(VFX_SAMPLER(mainTexture),i).a; #endif #endif #endif VFXClipFragmentColor(alpha,i); #ifdef WRITE_MSAA_DEPTH outDepthColor = i.VFX_VARYING_POSCS.z; #if VFX_USE_ALPHA_TO_MASK outDepthColor.a = alpha; #endif #endif #ifdef WRITE_NORMAL_BUFFER #ifdef VFX_VARYING_NORMAL VFXComputePixelOutputToNormalBuffer(i, normalWS, GetUVData(i), outNormalBuffer); #else //Fallback for point and lines, render normal as if those are face camera plane VFXComputePixelOutputToNormalBuffer(i, VFXGetWorldToViewRotMatrix()[2], GetUVData(i), outNormalBuffer); #endif #endif #if VFX_PASSDEPTH == VFX_PASSDEPTH_MOTION_VECTOR //No w division with fast path of motion vectors #ifdef VFX_FEATURE_MOTION_VECTORS_VERTS float2 velocity = i.VFX_VARYING_VELOCITY_CPOS - i.VFX_VARYING_VELOCITY_CPOS_PREVIOUS; #else float2 velocity = (i.VFX_VARYING_VELOCITY_CPOS.xy/i.VFX_VARYING_VELOCITY_CPOS.w) - (i.VFX_VARYING_VELOCITY_CPOS_PREVIOUS.xy/i.VFX_VARYING_VELOCITY_CPOS_PREVIOUS.w); #endif #if UNITY_UV_STARTS_AT_TOP velocity.y = -velocity.y; #endif float4 encodedMotionVector = 0.0f; VFXEncodeMotionVector(velocity * 0.5f, encodedMotionVector); outMotionVector = encodedMotionVector; #elif VFX_PASSDEPTH == VFX_PASSDEPTH_SELECTION outSelection = float4(_ObjectId, _PassValue, 1.0, 1.0); #elif VFX_PASSDEPTH == VFX_PASSDEPTH_PICKING outSelection = _SelectionID; #elif VFX_PASSDEPTH == VFX_PASSDEPTH_ACTUAL #if !defined(WRITE_MSAA_DEPTH) && !defined(WRITE_NORMAL_BUFFER) dummy = float4(i.VFX_VARYING_POSCS.z, 0,0,0); #endif #elif VFX_PASSDEPTH == VFX_PASSDEPTH_SHADOW dummy = (float4)0; #else #error VFX_PASSDEPTH undefined #endif } ENDHLSL } // Forward pass Pass { Tags { "LightMode"="UniversalForwardOnly" } HLSLPROGRAM #pragma target 4.5 #pragma multi_compile_fragment _ _SCREEN_SPACE_OCCLUSION #pragma multi_compile_fog struct ps_input { float4 pos : SV_POSITION; #if USE_FLIPBOOK_INTERPOLATION float4 uv : TEXCOORD0; #else #if USE_FLIPBOOK_ARRAY_LAYOUT float3 uv : TEXCOORD0; #else float2 uv : TEXCOORD0; #endif #endif #if VFX_NEEDS_COLOR_INTERPOLATOR VFX_OPTIONAL_INTERPOLATION float4 color : COLOR0; #endif #if USE_SOFT_PARTICLE || USE_ALPHA_TEST || USE_FLIPBOOK_INTERPOLATION || USE_EXPOSURE_WEIGHT || VFX_FEATURE_MOTION_VECTORS_FORWARD // x: inverse soft particles fade distance // y: alpha threshold // z: frame blending factor // w: exposure weight VFX_OPTIONAL_INTERPOLATION float4 builtInInterpolants : TEXCOORD1; #endif #if USE_FLIPBOOK_MOTIONVECTORS // x: motion vectors scale X // y: motion vectors scale Y VFX_OPTIONAL_INTERPOLATION float2 builtInInterpolants2 : TEXCOORD2; #endif #if VFX_NEEDS_POSWS_INTERPOLATOR float3 posWS : TEXCOORD3; #endif #if VFX_FEATURE_MOTION_VECTORS_FORWARD VFX_DECLARE_MOTION_VECTORS_STORAGE(4,5) #endif #if SHADERGRAPH_NEEDS_NORMAL_FORWARD || FORCE_NORMAL_OUTPUT_UNLIT_VERTEX_SHADER float3 normal : TEXCOORD6; #endif #if SHADERGRAPH_NEEDS_TANGENT_FORWARD float3 tangent : TEXCOORD7; #endif UNITY_VERTEX_OUTPUT_STEREO VFX_VERTEX_OUTPUT_INSTANCE_INDEX }; struct ps_output { float4 color : SV_Target0; #if VFX_FEATURE_MOTION_VECTORS_FORWARD float4 outMotionVector : SV_Target1; #endif }; #define VFX_VARYING_PS_INPUTS ps_input #define VFX_VARYING_POSCS pos #define VFX_VARYING_COLOR color.rgb #define VFX_VARYING_ALPHA color.a #define VFX_VARYING_INVSOFTPARTICLEFADEDISTANCE builtInInterpolants.x #define VFX_VARYING_ALPHATHRESHOLD builtInInterpolants.y #define VFX_VARYING_FRAMEBLEND builtInInterpolants.z #define VFX_VARYING_MOTIONVECTORSCALE builtInInterpolants2.xy #define VFX_VARYING_UV uv #if VFX_NEEDS_POSWS_INTERPOLATOR #define VFX_VARYING_POSWS posWS #endif #if USE_EXPOSURE_WEIGHT #define VFX_VARYING_EXPOSUREWEIGHT builtInInterpolants.w #endif #if VFX_FEATURE_MOTION_VECTORS_FORWARD #define VFX_VARYING_VELOCITY_CPOS VFX_DECLARE_MOTION_VECTORS_VARYING_NONJITTER #define VFX_VARYING_VELOCITY_CPOS_PREVIOUS VFX_DECLARE_MOTION_VECTORS_VARYING_PREVIOUS #endif #if SHADERGRAPH_NEEDS_NORMAL_FORWARD || FORCE_NORMAL_OUTPUT_UNLIT_VERTEX_SHADER #define VFX_VARYING_NORMAL normal #endif #if SHADERGRAPH_NEEDS_TANGENT_FORWARD #define VFX_VARYING_TANGENT tangent #endif #if !(defined(VFX_VARYING_PS_INPUTS) && defined(VFX_VARYING_POSCS)) #error VFX_VARYING_PS_INPUTS, VFX_VARYING_POSCS and VFX_VARYING_UV must be defined. #endif #include "Packages/com.unity.render-pipelines.universal/Runtime/VFXGraph/Shaders/VFXCommon.hlsl" #include "Packages/com.unity.visualeffectgraph/Shaders/VFXCommon.hlsl" #include "Packages/com.unity.visualeffectgraph/Shaders/VFXCommonOutput.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 defined(HAS_STRIPS) && !defined(VFX_PRIMITIVE_QUAD) #error VFX_PRIMITIVE_QUAD must be defined when HAS_STRIPS is. #endif #define VFX_NON_UNIFORM_SCALE VFX_LOCAL_SPACE struct vs_input { VFX_DECLARE_INSTANCE_ID }; #if HAS_STRIPS #define PARTICLE_IN_EDGE (id & 1) 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 #pragma vertex vert VFX_VARYING_PS_INPUTS vert(uint id : SV_VertexID, vs_input i) { VFX_VARYING_PS_INPUTS o = (VFX_VARYING_PS_INPUTS)0; UNITY_SETUP_INSTANCE_ID(i); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); #if VFX_PRIMITIVE_TRIANGLE uint index = id / 3; #elif VFX_PRIMITIVE_QUAD #if HAS_STRIPS id += VFX_GET_INSTANCE_ID(i) * 8192; const uint vertexPerStripCount = (PARTICLE_PER_STRIP_COUNT - 1) << 2; uint index = id / vertexPerStripCount; // stripIndex. Needed by VFXInitInstancing uint instanceIndex, instanceActiveIndex, instanceCurrentIndex; index = VFXInitInstancing(index, instanceIndex, instanceActiveIndex, instanceCurrentIndex); const StripData stripData = GetStripDataFromStripIndex(index, instanceIndex); uint relativeIndexInStrip = ((id % vertexPerStripCount) >> 2) + (id & 1); // relative index of particle uint maxEdgeIndex = relativeIndexInStrip - PARTICLE_IN_EDGE + 1; if (maxEdgeIndex >= stripData.nextIndex) return o; index = GetParticleIndex(relativeIndexInStrip, stripData); #else uint index = (id >> 2) + VFX_GET_INSTANCE_ID(i) * 2048; #endif #elif VFX_PRIMITIVE_OCTAGON uint index = (id >> 3) + VFX_GET_INSTANCE_ID(i) * 1024; #endif #if !HAS_STRIPS // With strips we need to derive the instance index prior to get the particle index uint instanceIndex, instanceActiveIndex, instanceCurrentIndex; index = VFXInitInstancing(index, instanceIndex, instanceActiveIndex, instanceCurrentIndex); #endif 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)); ContextData contextData = instancingContextData[instanceActiveIndex]; uint systemSeed = contextData.systemSeed; uint nbMax = contextData.maxParticleCount; uint deadCount = 0; #if USE_DEAD_LIST_COUNT deadCount = deadListCount[instanceIndex]; #endif #if VFX_USE_INSTANCING if (index >= nbMax - deadCount) #else if (index >= asuint(nbMax) - deadCount) #endif { #if USE_GEOMETRY_SHADER return; // cull #else o.pos.x = VFX_NAN; return o; // cull #endif } VFXAttributes attributes = (VFXAttributes)0; VFXSourceAttributes sourceAttributes = (VFXSourceAttributes)0; #if VFX_HAS_INDIRECT_DRAW index = indirectBuffer[VFXGetIndirectBufferIndex(index, instanceActiveIndex)]; 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.alive = (attributeBuffer.Load(((instanceIndex * 0xEC40) + (index * 0x8 + 0x3)) << 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)); attributes.color = float3(1, 1, 1); #else attributes.alive = (attributeBuffer.Load(((instanceIndex * 0xEC40) + (index * 0x8 + 0x3)) << 2)); #if !HAS_STRIPS if (!attributes.alive) { o.pos.x = VFX_NAN; return o; // cull } #endif 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)); attributes.color = float3(1, 1, 1); #endif // Initialize built-in needed attributes #if HAS_STRIPS InitStripAttributes(index, attributes, 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); } #if !HAS_STRIPS if (!attributes.alive) return o; #endif #if VFX_PRIMITIVE_QUAD #if HAS_STRIPS #if VFX_STRIPS_UV_STRECHED o.VFX_VARYING_UV.x = (float)(relativeIndexInStrip) / (stripData.nextIndex - 1); #elif VFX_STRIPS_UV_PER_SEGMENT o.VFX_VARYING_UV.x = PARTICLE_IN_EDGE; #else o.VFX_VARYING_UV.x = texCoord; #endif o.VFX_VARYING_UV.y = (id & 2) * 0.5f; const float2 vOffsets = float2(0.0f,o.VFX_VARYING_UV.y - 0.5f); #if VFX_STRIPS_SWAP_UV o.VFX_VARYING_UV.xy = float2(1.0f - o.VFX_VARYING_UV.y, o.VFX_VARYING_UV.x); #endif #else o.VFX_VARYING_UV.x = float(id & 1); o.VFX_VARYING_UV.y = (id & 2) * 0.5f; const float2 vOffsets = o.VFX_VARYING_UV.xy - 0.5f; #endif #elif VFX_PRIMITIVE_TRIANGLE const float2 kOffsets[] = { float2(-0.5f, -0.288675129413604736328125f), float2(0.0f, 0.57735025882720947265625f), float2(0.5f, -0.288675129413604736328125f), }; const float kUVScale = 0.866025388240814208984375f; const float2 vOffsets = kOffsets[id % 3]; o.VFX_VARYING_UV.xy = (vOffsets * kUVScale) + 0.5f; #elif VFX_PRIMITIVE_OCTAGON const float2 kUvs[8] = { float2(-0.5f, 0.0f), float2(-0.5f, 0.5f), float2(0.0f, 0.5f), float2(0.5f, 0.5f), float2(0.5f, 0.0f), float2(0.5f, -0.5f), float2(0.0f, -0.5f), float2(-0.5f, -0.5f), }; cropFactor = id & 1 ? 1.0f - cropFactor : 1.0f; const float2 vOffsets = kUvs[id & 7] * cropFactor; o.VFX_VARYING_UV.xy = vOffsets + 0.5f; #endif 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 size3 += size3 < 0.0f ? -VFX_EPSILON : VFX_EPSILON; // Add an epsilon so that size is never 0 for strips #endif const 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); float3 inputVertexPosition = float3(vOffsets, 0.0f); float3 vPos = mul(elementToVFX,float4(inputVertexPosition, 1.0f)).xyz; o.VFX_VARYING_POSCS = TransformPositionVFXToClip(vPos); float3 vPosWS = TransformPositionVFXToWorld(vPos); #ifdef VFX_VARYING_POSWS o.VFX_VARYING_POSWS = vPosWS; #endif #if VFX_NON_UNIFORM_SCALE float3x3 elementToVFX_N = GetElementToVFXMatrixNormal( attributes.axisX, attributes.axisY, attributes.axisZ, float3(attributes.angleX,attributes.angleY,attributes.angleZ), size3); #else float3x3 elementToVFX_N = (float3x3)elementToVFX; #endif float3 normalWS = normalize(TransformNormalVFXToWorld((-transpose(elementToVFX_N)[2]))); #ifdef VFX_VARYING_NORMAL float normalFlip = (size3.x * size3.y * size3.z) < 0 ? -1 : 1; o.VFX_VARYING_NORMAL = normalFlip * normalWS; #endif #ifdef VFX_VARYING_TANGENT o.VFX_VARYING_TANGENT.xyz = normalize(TransformDirectionVFXToWorld(normalize(transpose(elementToVFX)[0].xyz))); #endif #ifdef VFX_VARYING_BENTFACTORS #if HAS_STRIPS #define BENT_FACTOR_MULTIPLIER 2.0f #else #define BENT_FACTOR_MULTIPLIER 1.41421353816986083984375f #endif o.VFX_VARYING_BENTFACTORS = vOffsets * normalBendingFactor * BENT_FACTOR_MULTIPLIER; #endif #if VFX_FEATURE_MOTION_VECTORS && defined(VFX_VARYING_VELOCITY_CPOS_PREVIOUS) && defined(VFX_VARYING_VELOCITY_CPOS) #ifdef VFX_FEATURE_MOTION_VECTORS_VERTS o.VFX_VARYING_VELOCITY_CPOS_PREVIOUS = o.VFX_VARYING_VELOCITY_CPOS = (float2)0.0f; #else o.VFX_VARYING_VELOCITY_CPOS_PREVIOUS = o.VFX_VARYING_VELOCITY_CPOS = float4(0.0f, 0.0f, 0.0f, 1.0f); #endif uint elementToVFXBaseIndex; if (TryGetElementToVFXBaseIndex(index, instanceIndex, elementToVFXBaseIndex, currentFrameIndex)) { float4 cPos = TransformPositionVFXToNonJitteredClip(vPos); #ifdef VFX_FEATURE_MOTION_VECTORS_VERTS o.VFX_VARYING_VELOCITY_CPOS_PREVIOUS = VFXGetPreviousClipPosition(elementToVFXBaseIndex, id).xy; o.VFX_VARYING_VELOCITY_CPOS = cPos.xy / cPos.w; #else float4x4 previousElementToVFX = VFXGetPreviousElementToVFX(elementToVFXBaseIndex); float3 oldvPos = mul(previousElementToVFX, float4(inputVertexPosition, 1.0f)).xyz; o.VFX_VARYING_VELOCITY_CPOS_PREVIOUS = TransformPositionVFXToPreviousClip(oldvPos); o.VFX_VARYING_VELOCITY_CPOS = cPos; #endif } #endif #if VFX_USE_COLOR_CURRENT && defined(VFX_VARYING_COLOR) o.VFX_VARYING_COLOR = attributes.color; #endif #if VFX_USE_ALPHA_CURRENT && defined(VFX_VARYING_ALPHA) o.VFX_VARYING_ALPHA = attributes.alpha; #endif #ifdef VFX_VARYING_EXPOSUREWEIGHT o.VFX_VARYING_EXPOSUREWEIGHT = exposureWeight; #endif #if USE_SOFT_PARTICLE && defined(VFX_VARYING_INVSOFTPARTICLEFADEDISTANCE) float invSoftParticlesFadeDistance = (float)0; { invSoftParticlesFadeDistance = graphValues.invSoftParticlesFadeDistance_a; } o.VFX_VARYING_INVSOFTPARTICLEFADEDISTANCE = invSoftParticlesFadeDistance; #endif #if (USE_ALPHA_TEST || VFX_FEATURE_MOTION_VECTORS_FORWARD) && (!VFX_SHADERGRAPH || !HAS_SHADERGRAPH_PARAM_ALPHACLIPTHRESHOLD) && defined(VFX_VARYING_ALPHATHRESHOLD) o.VFX_VARYING_ALPHATHRESHOLD = alphaThreshold; #endif #if USE_UV_SCALE_BIAS #if defined (VFX_VARYING_UV) o.VFX_VARYING_UV.xy = o.VFX_VARYING_UV.xy * uvScale + uvBias; #endif #endif #ifdef VFX_VARYING_ANGLEFADE o.VFX_VARYING_ANGLEFADE = angleFade; #endif #ifdef VFX_VARYING_FADEFACTOR o.VFX_VARYING_FADEFACTOR = fadeFactor; #endif #ifdef VFX_VARYING_DECALLAYER o.VFX_VARYING_DECALLAYER = decalLayerMask; #endif #if defined(VFX_VARYING_POSWS) o.VFX_VARYING_POSWS = TransformPositionVFXToWorld(vPos); #endif #if VFX_USE_INSTANCING #ifdef UNITY_INSTANCING_ENABLED o.VFX_VARYINGS_INSTANCE_CURRENT_INDEX = unity_InstanceID; #endif o.VFX_VARYINGS_INSTANCE_ACTIVE_INDEX = instanceActiveIndex; #endif #if USE_FLIPBOOK && defined(VFX_VARYING_UV) #if USE_FLIPBOOK_ARRAY_LAYOUT float2 flipBookSize = (float2)0; { flipBookSize = graphValues.flipBookSize_a; } VFXUVData uvData = GetUVData(flipBookSize, o.VFX_VARYING_UV.xy, attributes.texIndex); o.VFX_VARYING_UV.xyz = uvData.uvs.xyz; #if USE_FLIPBOOK_INTERPOLATION && defined(VFX_VARYING_UV) && defined (VFX_VARYING_FRAMEBLEND) o.VFX_VARYING_UV.w = uvData.uvs.w; o.VFX_VARYING_FRAMEBLEND = uvData.blend; #if USE_FLIPBOOK_MOTIONVECTORS && defined(VFX_VARYING_MOTIONVECTORSCALE) o.VFX_VARYING_MOTIONVECTORSCALE = motionVectorScale; #endif #endif #else float2 invFlipBookSize = (float2)0; { invFlipBookSize = graphValues.invFlipBookSize_a; } float2 flipBookSize = (float2)0; { flipBookSize = graphValues.flipBookSize_a; } VFXUVData uvData = GetUVData(flipBookSize, invFlipBookSize, o.VFX_VARYING_UV.xy, attributes.texIndex); o.VFX_VARYING_UV.xy = uvData.uvs.xy; #if USE_FLIPBOOK_INTERPOLATION && defined(VFX_VARYING_UV) && defined (VFX_VARYING_FRAMEBLEND) o.VFX_VARYING_UV.zw = uvData.uvs.zw; o.VFX_VARYING_FRAMEBLEND = uvData.blend; #if USE_FLIPBOOK_MOTIONVECTORS && defined(VFX_VARYING_MOTIONVECTORSCALE) o.VFX_VARYING_MOTIONVECTORSCALE = motionVectorScale * invFlipBookSize; #endif #endif #endif #endif return o; } #if VFX_SHADERGRAPH #endif #pragma fragment frag ps_output frag(ps_input i, bool frontFace : SV_IsFrontFace) { UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i); ps_output o = (ps_output)0; VFXTransformPSInputs(i); #ifdef VFX_VARYING_NORMAL #if USE_DOUBLE_SIDED const float faceMul = frontFace ? 1.0f : -1.0f; #else const float faceMul = 1.0f; #endif float3 normalWS = i.VFX_VARYING_NORMAL * faceMul; const VFXUVData uvData = GetUVData(i); #ifdef VFX_VARYING_TANGENT float3 tangentWS = i.VFX_VARYING_TANGENT; float3 bitangentWS = cross(i.VFX_VARYING_TANGENT,i.VFX_VARYING_NORMAL); #if defined(VFX_VARYING_BENTFACTORS) && USE_NORMAL_BENDING float3 bentFactors = float3(i.VFX_VARYING_BENTFACTORS.xy,sqrt(max(0.0f,1.0f - dot(i.VFX_VARYING_BENTFACTORS,i.VFX_VARYING_BENTFACTORS)))); normalWS = tangentWS * bentFactors.x + bitangentWS * bentFactors.y + normalWS * bentFactors.z; tangentWS = normalize(cross(normalWS,bitangentWS)); bitangentWS = cross(tangentWS,normalWS); tangentWS *= faceMul; #endif float3x3 tbn = float3x3(tangentWS,bitangentWS,normalWS); #if USE_NORMAL_MAP float3 n = SampleNormalMap(VFX_SAMPLER(normalMap),uvData); float normalScale = 1.0f; #ifdef VFX_VARYING_NORMALSCALE normalScale = i.VFX_VARYING_NORMALSCALE; #endif normalWS = normalize(lerp(normalWS,mul(n,tbn),normalScale)); #endif #endif #endif #if VFX_USE_GRAPH_VALUES uint instanceActiveIndex = i.VFX_VARYINGS_INSTANCE_ACTIVE_INDEX; 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)); #endif #if VFX_SHADERGRAPH #if HAS_SHADERGRAPH_PARAM_BASECOLOR o.color.rgb = OUTSG..rgb; o.color = VFXApplyPreExposure(o.color, i); #endif #if HAS_SHADERGRAPH_PARAM_EMISSION float4 emission = float4(OUTSG..rgb, 0.0f); emission = VFXApplyPreExposure(emission, 1.0f); o.color.rgb += emission.rgb; #endif #if HAS_SHADERGRAPH_PARAM_ALPHA o.color.a = OUTSG.; #endif #else #define VFX_TEXTURE_COLOR VFXGetTextureColor(VFX_SAMPLER(mainTexture),i) float4 color = VFXGetFragmentColor(i); #ifndef VFX_TEXTURE_COLOR #define VFX_TEXTURE_COLOR float4(1.0,1.0,1.0,1.0) #endif #if VFX_COLORMAPPING_DEFAULT o.color = color * VFX_TEXTURE_COLOR; #endif #if VFX_COLORMAPPING_GRADIENTMAPPED o.color = SampleGradient(gradient, VFX_TEXTURE_COLOR.a * color.a) * float4(color.rgb,1.0); #endif o.color = VFXApplyPreExposure(o.color, i); #endif o.color = VFXApplyAO(o.color,i); o.color = VFXApplyFog(o.color,i); VFXClipFragmentColor(o.color.a,i); o.color.a = saturate(o.color.a); o.color = VFXTransformFinalColor(o.color); #if VFX_FEATURE_MOTION_VECTORS_FORWARD //No w division with fast path of motion vectors #ifdef VFX_FEATURE_MOTION_VECTORS_VERTS float2 velocity = i.VFX_VARYING_VELOCITY_CPOS - i.VFX_VARYING_VELOCITY_CPOS_PREVIOUS; #else float2 velocity = (i.VFX_VARYING_VELOCITY_CPOS.xy/i.VFX_VARYING_VELOCITY_CPOS.w) - (i.VFX_VARYING_VELOCITY_CPOS_PREVIOUS.xy/i.VFX_VARYING_VELOCITY_CPOS_PREVIOUS.w); #endif #if UNITY_UV_STARTS_AT_TOP velocity.y = -velocity.y; #endif float4 encodedMotionVector = 0.0f; VFXEncodeMotionVector(velocity * 0.5f, encodedMotionVector); o.outMotionVector = encodedMotionVector; o.outMotionVector.a = o.color.a < i.VFX_VARYING_ALPHATHRESHOLD ? 0.0f : 1.0f; //Independant clipping for motion vector pass #endif return o; } ENDHLSL } // Forward pass Pass { Tags { "LightMode"="Universal2D" } HLSLPROGRAM #pragma target 4.5 #pragma multi_compile_fragment _ _SCREEN_SPACE_OCCLUSION #pragma multi_compile_fog struct ps_input { float4 pos : SV_POSITION; #if USE_FLIPBOOK_INTERPOLATION float4 uv : TEXCOORD0; #else #if USE_FLIPBOOK_ARRAY_LAYOUT float3 uv : TEXCOORD0; #else float2 uv : TEXCOORD0; #endif #endif #if VFX_NEEDS_COLOR_INTERPOLATOR VFX_OPTIONAL_INTERPOLATION float4 color : COLOR0; #endif #if USE_SOFT_PARTICLE || USE_ALPHA_TEST || USE_FLIPBOOK_INTERPOLATION || USE_EXPOSURE_WEIGHT || VFX_FEATURE_MOTION_VECTORS_FORWARD // x: inverse soft particles fade distance // y: alpha threshold // z: frame blending factor // w: exposure weight VFX_OPTIONAL_INTERPOLATION float4 builtInInterpolants : TEXCOORD1; #endif #if USE_FLIPBOOK_MOTIONVECTORS // x: motion vectors scale X // y: motion vectors scale Y VFX_OPTIONAL_INTERPOLATION float2 builtInInterpolants2 : TEXCOORD2; #endif #if VFX_NEEDS_POSWS_INTERPOLATOR float3 posWS : TEXCOORD3; #endif #if VFX_FEATURE_MOTION_VECTORS_FORWARD VFX_DECLARE_MOTION_VECTORS_STORAGE(4,5) #endif #if SHADERGRAPH_NEEDS_NORMAL_FORWARD || FORCE_NORMAL_OUTPUT_UNLIT_VERTEX_SHADER float3 normal : TEXCOORD6; #endif #if SHADERGRAPH_NEEDS_TANGENT_FORWARD float3 tangent : TEXCOORD7; #endif UNITY_VERTEX_OUTPUT_STEREO VFX_VERTEX_OUTPUT_INSTANCE_INDEX }; struct ps_output { float4 color : SV_Target0; #if VFX_FEATURE_MOTION_VECTORS_FORWARD float4 outMotionVector : SV_Target1; #endif }; #define VFX_VARYING_PS_INPUTS ps_input #define VFX_VARYING_POSCS pos #define VFX_VARYING_COLOR color.rgb #define VFX_VARYING_ALPHA color.a #define VFX_VARYING_INVSOFTPARTICLEFADEDISTANCE builtInInterpolants.x #define VFX_VARYING_ALPHATHRESHOLD builtInInterpolants.y #define VFX_VARYING_FRAMEBLEND builtInInterpolants.z #define VFX_VARYING_MOTIONVECTORSCALE builtInInterpolants2.xy #define VFX_VARYING_UV uv #if VFX_NEEDS_POSWS_INTERPOLATOR #define VFX_VARYING_POSWS posWS #endif #if USE_EXPOSURE_WEIGHT #define VFX_VARYING_EXPOSUREWEIGHT builtInInterpolants.w #endif #if VFX_FEATURE_MOTION_VECTORS_FORWARD #define VFX_VARYING_VELOCITY_CPOS VFX_DECLARE_MOTION_VECTORS_VARYING_NONJITTER #define VFX_VARYING_VELOCITY_CPOS_PREVIOUS VFX_DECLARE_MOTION_VECTORS_VARYING_PREVIOUS #endif #if SHADERGRAPH_NEEDS_NORMAL_FORWARD || FORCE_NORMAL_OUTPUT_UNLIT_VERTEX_SHADER #define VFX_VARYING_NORMAL normal #endif #if SHADERGRAPH_NEEDS_TANGENT_FORWARD #define VFX_VARYING_TANGENT tangent #endif #if !(defined(VFX_VARYING_PS_INPUTS) && defined(VFX_VARYING_POSCS)) #error VFX_VARYING_PS_INPUTS, VFX_VARYING_POSCS and VFX_VARYING_UV must be defined. #endif #include "Packages/com.unity.render-pipelines.universal/Runtime/VFXGraph/Shaders/VFXCommon.hlsl" #include "Packages/com.unity.visualeffectgraph/Shaders/VFXCommon.hlsl" #include "Packages/com.unity.visualeffectgraph/Shaders/VFXCommonOutput.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 defined(HAS_STRIPS) && !defined(VFX_PRIMITIVE_QUAD) #error VFX_PRIMITIVE_QUAD must be defined when HAS_STRIPS is. #endif #define VFX_NON_UNIFORM_SCALE VFX_LOCAL_SPACE struct vs_input { VFX_DECLARE_INSTANCE_ID }; #if HAS_STRIPS #define PARTICLE_IN_EDGE (id & 1) 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 #pragma vertex vert VFX_VARYING_PS_INPUTS vert(uint id : SV_VertexID, vs_input i) { VFX_VARYING_PS_INPUTS o = (VFX_VARYING_PS_INPUTS)0; UNITY_SETUP_INSTANCE_ID(i); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); #if VFX_PRIMITIVE_TRIANGLE uint index = id / 3; #elif VFX_PRIMITIVE_QUAD #if HAS_STRIPS id += VFX_GET_INSTANCE_ID(i) * 8192; const uint vertexPerStripCount = (PARTICLE_PER_STRIP_COUNT - 1) << 2; uint index = id / vertexPerStripCount; // stripIndex. Needed by VFXInitInstancing uint instanceIndex, instanceActiveIndex, instanceCurrentIndex; index = VFXInitInstancing(index, instanceIndex, instanceActiveIndex, instanceCurrentIndex); const StripData stripData = GetStripDataFromStripIndex(index, instanceIndex); uint relativeIndexInStrip = ((id % vertexPerStripCount) >> 2) + (id & 1); // relative index of particle uint maxEdgeIndex = relativeIndexInStrip - PARTICLE_IN_EDGE + 1; if (maxEdgeIndex >= stripData.nextIndex) return o; index = GetParticleIndex(relativeIndexInStrip, stripData); #else uint index = (id >> 2) + VFX_GET_INSTANCE_ID(i) * 2048; #endif #elif VFX_PRIMITIVE_OCTAGON uint index = (id >> 3) + VFX_GET_INSTANCE_ID(i) * 1024; #endif #if !HAS_STRIPS // With strips we need to derive the instance index prior to get the particle index uint instanceIndex, instanceActiveIndex, instanceCurrentIndex; index = VFXInitInstancing(index, instanceIndex, instanceActiveIndex, instanceCurrentIndex); #endif 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)); ContextData contextData = instancingContextData[instanceActiveIndex]; uint systemSeed = contextData.systemSeed; uint nbMax = contextData.maxParticleCount; uint deadCount = 0; #if USE_DEAD_LIST_COUNT deadCount = deadListCount[instanceIndex]; #endif #if VFX_USE_INSTANCING if (index >= nbMax - deadCount) #else if (index >= asuint(nbMax) - deadCount) #endif { #if USE_GEOMETRY_SHADER return; // cull #else o.pos.x = VFX_NAN; return o; // cull #endif } VFXAttributes attributes = (VFXAttributes)0; VFXSourceAttributes sourceAttributes = (VFXSourceAttributes)0; #if VFX_HAS_INDIRECT_DRAW index = indirectBuffer[VFXGetIndirectBufferIndex(index, instanceActiveIndex)]; 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.alive = (attributeBuffer.Load(((instanceIndex * 0xEC40) + (index * 0x8 + 0x3)) << 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)); attributes.color = float3(1, 1, 1); #else attributes.alive = (attributeBuffer.Load(((instanceIndex * 0xEC40) + (index * 0x8 + 0x3)) << 2)); #if !HAS_STRIPS if (!attributes.alive) { o.pos.x = VFX_NAN; return o; // cull } #endif 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)); attributes.color = float3(1, 1, 1); #endif // Initialize built-in needed attributes #if HAS_STRIPS InitStripAttributes(index, attributes, 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); } #if !HAS_STRIPS if (!attributes.alive) return o; #endif #if VFX_PRIMITIVE_QUAD #if HAS_STRIPS #if VFX_STRIPS_UV_STRECHED o.VFX_VARYING_UV.x = (float)(relativeIndexInStrip) / (stripData.nextIndex - 1); #elif VFX_STRIPS_UV_PER_SEGMENT o.VFX_VARYING_UV.x = PARTICLE_IN_EDGE; #else o.VFX_VARYING_UV.x = texCoord; #endif o.VFX_VARYING_UV.y = (id & 2) * 0.5f; const float2 vOffsets = float2(0.0f,o.VFX_VARYING_UV.y - 0.5f); #if VFX_STRIPS_SWAP_UV o.VFX_VARYING_UV.xy = float2(1.0f - o.VFX_VARYING_UV.y, o.VFX_VARYING_UV.x); #endif #else o.VFX_VARYING_UV.x = float(id & 1); o.VFX_VARYING_UV.y = (id & 2) * 0.5f; const float2 vOffsets = o.VFX_VARYING_UV.xy - 0.5f; #endif #elif VFX_PRIMITIVE_TRIANGLE const float2 kOffsets[] = { float2(-0.5f, -0.288675129413604736328125f), float2(0.0f, 0.57735025882720947265625f), float2(0.5f, -0.288675129413604736328125f), }; const float kUVScale = 0.866025388240814208984375f; const float2 vOffsets = kOffsets[id % 3]; o.VFX_VARYING_UV.xy = (vOffsets * kUVScale) + 0.5f; #elif VFX_PRIMITIVE_OCTAGON const float2 kUvs[8] = { float2(-0.5f, 0.0f), float2(-0.5f, 0.5f), float2(0.0f, 0.5f), float2(0.5f, 0.5f), float2(0.5f, 0.0f), float2(0.5f, -0.5f), float2(0.0f, -0.5f), float2(-0.5f, -0.5f), }; cropFactor = id & 1 ? 1.0f - cropFactor : 1.0f; const float2 vOffsets = kUvs[id & 7] * cropFactor; o.VFX_VARYING_UV.xy = vOffsets + 0.5f; #endif 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 size3 += size3 < 0.0f ? -VFX_EPSILON : VFX_EPSILON; // Add an epsilon so that size is never 0 for strips #endif const 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); float3 inputVertexPosition = float3(vOffsets, 0.0f); float3 vPos = mul(elementToVFX,float4(inputVertexPosition, 1.0f)).xyz; o.VFX_VARYING_POSCS = TransformPositionVFXToClip(vPos); float3 vPosWS = TransformPositionVFXToWorld(vPos); #ifdef VFX_VARYING_POSWS o.VFX_VARYING_POSWS = vPosWS; #endif #if VFX_NON_UNIFORM_SCALE float3x3 elementToVFX_N = GetElementToVFXMatrixNormal( attributes.axisX, attributes.axisY, attributes.axisZ, float3(attributes.angleX,attributes.angleY,attributes.angleZ), size3); #else float3x3 elementToVFX_N = (float3x3)elementToVFX; #endif float3 normalWS = normalize(TransformNormalVFXToWorld((-transpose(elementToVFX_N)[2]))); #ifdef VFX_VARYING_NORMAL float normalFlip = (size3.x * size3.y * size3.z) < 0 ? -1 : 1; o.VFX_VARYING_NORMAL = normalFlip * normalWS; #endif #ifdef VFX_VARYING_TANGENT o.VFX_VARYING_TANGENT.xyz = normalize(TransformDirectionVFXToWorld(normalize(transpose(elementToVFX)[0].xyz))); #endif #ifdef VFX_VARYING_BENTFACTORS #if HAS_STRIPS #define BENT_FACTOR_MULTIPLIER 2.0f #else #define BENT_FACTOR_MULTIPLIER 1.41421353816986083984375f #endif o.VFX_VARYING_BENTFACTORS = vOffsets * normalBendingFactor * BENT_FACTOR_MULTIPLIER; #endif #if VFX_FEATURE_MOTION_VECTORS && defined(VFX_VARYING_VELOCITY_CPOS_PREVIOUS) && defined(VFX_VARYING_VELOCITY_CPOS) #ifdef VFX_FEATURE_MOTION_VECTORS_VERTS o.VFX_VARYING_VELOCITY_CPOS_PREVIOUS = o.VFX_VARYING_VELOCITY_CPOS = (float2)0.0f; #else o.VFX_VARYING_VELOCITY_CPOS_PREVIOUS = o.VFX_VARYING_VELOCITY_CPOS = float4(0.0f, 0.0f, 0.0f, 1.0f); #endif uint elementToVFXBaseIndex; if (TryGetElementToVFXBaseIndex(index, instanceIndex, elementToVFXBaseIndex, currentFrameIndex)) { float4 cPos = TransformPositionVFXToNonJitteredClip(vPos); #ifdef VFX_FEATURE_MOTION_VECTORS_VERTS o.VFX_VARYING_VELOCITY_CPOS_PREVIOUS = VFXGetPreviousClipPosition(elementToVFXBaseIndex, id).xy; o.VFX_VARYING_VELOCITY_CPOS = cPos.xy / cPos.w; #else float4x4 previousElementToVFX = VFXGetPreviousElementToVFX(elementToVFXBaseIndex); float3 oldvPos = mul(previousElementToVFX, float4(inputVertexPosition, 1.0f)).xyz; o.VFX_VARYING_VELOCITY_CPOS_PREVIOUS = TransformPositionVFXToPreviousClip(oldvPos); o.VFX_VARYING_VELOCITY_CPOS = cPos; #endif } #endif #if VFX_USE_COLOR_CURRENT && defined(VFX_VARYING_COLOR) o.VFX_VARYING_COLOR = attributes.color; #endif #if VFX_USE_ALPHA_CURRENT && defined(VFX_VARYING_ALPHA) o.VFX_VARYING_ALPHA = attributes.alpha; #endif #ifdef VFX_VARYING_EXPOSUREWEIGHT o.VFX_VARYING_EXPOSUREWEIGHT = exposureWeight; #endif #if USE_SOFT_PARTICLE && defined(VFX_VARYING_INVSOFTPARTICLEFADEDISTANCE) float invSoftParticlesFadeDistance = (float)0; { invSoftParticlesFadeDistance = graphValues.invSoftParticlesFadeDistance_a; } o.VFX_VARYING_INVSOFTPARTICLEFADEDISTANCE = invSoftParticlesFadeDistance; #endif #if (USE_ALPHA_TEST || VFX_FEATURE_MOTION_VECTORS_FORWARD) && (!VFX_SHADERGRAPH || !HAS_SHADERGRAPH_PARAM_ALPHACLIPTHRESHOLD) && defined(VFX_VARYING_ALPHATHRESHOLD) o.VFX_VARYING_ALPHATHRESHOLD = alphaThreshold; #endif #if USE_UV_SCALE_BIAS #if defined (VFX_VARYING_UV) o.VFX_VARYING_UV.xy = o.VFX_VARYING_UV.xy * uvScale + uvBias; #endif #endif #ifdef VFX_VARYING_ANGLEFADE o.VFX_VARYING_ANGLEFADE = angleFade; #endif #ifdef VFX_VARYING_FADEFACTOR o.VFX_VARYING_FADEFACTOR = fadeFactor; #endif #ifdef VFX_VARYING_DECALLAYER o.VFX_VARYING_DECALLAYER = decalLayerMask; #endif #if defined(VFX_VARYING_POSWS) o.VFX_VARYING_POSWS = TransformPositionVFXToWorld(vPos); #endif #if VFX_USE_INSTANCING #ifdef UNITY_INSTANCING_ENABLED o.VFX_VARYINGS_INSTANCE_CURRENT_INDEX = unity_InstanceID; #endif o.VFX_VARYINGS_INSTANCE_ACTIVE_INDEX = instanceActiveIndex; #endif #if USE_FLIPBOOK && defined(VFX_VARYING_UV) #if USE_FLIPBOOK_ARRAY_LAYOUT float2 flipBookSize = (float2)0; { flipBookSize = graphValues.flipBookSize_a; } VFXUVData uvData = GetUVData(flipBookSize, o.VFX_VARYING_UV.xy, attributes.texIndex); o.VFX_VARYING_UV.xyz = uvData.uvs.xyz; #if USE_FLIPBOOK_INTERPOLATION && defined(VFX_VARYING_UV) && defined (VFX_VARYING_FRAMEBLEND) o.VFX_VARYING_UV.w = uvData.uvs.w; o.VFX_VARYING_FRAMEBLEND = uvData.blend; #if USE_FLIPBOOK_MOTIONVECTORS && defined(VFX_VARYING_MOTIONVECTORSCALE) o.VFX_VARYING_MOTIONVECTORSCALE = motionVectorScale; #endif #endif #else float2 invFlipBookSize = (float2)0; { invFlipBookSize = graphValues.invFlipBookSize_a; } float2 flipBookSize = (float2)0; { flipBookSize = graphValues.flipBookSize_a; } VFXUVData uvData = GetUVData(flipBookSize, invFlipBookSize, o.VFX_VARYING_UV.xy, attributes.texIndex); o.VFX_VARYING_UV.xy = uvData.uvs.xy; #if USE_FLIPBOOK_INTERPOLATION && defined(VFX_VARYING_UV) && defined (VFX_VARYING_FRAMEBLEND) o.VFX_VARYING_UV.zw = uvData.uvs.zw; o.VFX_VARYING_FRAMEBLEND = uvData.blend; #if USE_FLIPBOOK_MOTIONVECTORS && defined(VFX_VARYING_MOTIONVECTORSCALE) o.VFX_VARYING_MOTIONVECTORSCALE = motionVectorScale * invFlipBookSize; #endif #endif #endif #endif return o; } #if VFX_SHADERGRAPH #endif #pragma fragment frag ps_output frag(ps_input i, bool frontFace : SV_IsFrontFace) { UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i); ps_output o = (ps_output)0; VFXTransformPSInputs(i); #ifdef VFX_VARYING_NORMAL #if USE_DOUBLE_SIDED const float faceMul = frontFace ? 1.0f : -1.0f; #else const float faceMul = 1.0f; #endif float3 normalWS = i.VFX_VARYING_NORMAL * faceMul; const VFXUVData uvData = GetUVData(i); #ifdef VFX_VARYING_TANGENT float3 tangentWS = i.VFX_VARYING_TANGENT; float3 bitangentWS = cross(i.VFX_VARYING_TANGENT,i.VFX_VARYING_NORMAL); #if defined(VFX_VARYING_BENTFACTORS) && USE_NORMAL_BENDING float3 bentFactors = float3(i.VFX_VARYING_BENTFACTORS.xy,sqrt(max(0.0f,1.0f - dot(i.VFX_VARYING_BENTFACTORS,i.VFX_VARYING_BENTFACTORS)))); normalWS = tangentWS * bentFactors.x + bitangentWS * bentFactors.y + normalWS * bentFactors.z; tangentWS = normalize(cross(normalWS,bitangentWS)); bitangentWS = cross(tangentWS,normalWS); tangentWS *= faceMul; #endif float3x3 tbn = float3x3(tangentWS,bitangentWS,normalWS); #if USE_NORMAL_MAP float3 n = SampleNormalMap(VFX_SAMPLER(normalMap),uvData); float normalScale = 1.0f; #ifdef VFX_VARYING_NORMALSCALE normalScale = i.VFX_VARYING_NORMALSCALE; #endif normalWS = normalize(lerp(normalWS,mul(n,tbn),normalScale)); #endif #endif #endif #if VFX_USE_GRAPH_VALUES uint instanceActiveIndex = i.VFX_VARYINGS_INSTANCE_ACTIVE_INDEX; 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)); #endif #if VFX_SHADERGRAPH #if HAS_SHADERGRAPH_PARAM_BASECOLOR o.color.rgb = OUTSG..rgb; o.color = VFXApplyPreExposure(o.color, i); #endif #if HAS_SHADERGRAPH_PARAM_EMISSION float4 emission = float4(OUTSG..rgb, 0.0f); emission = VFXApplyPreExposure(emission, 1.0f); o.color.rgb += emission.rgb; #endif #if HAS_SHADERGRAPH_PARAM_ALPHA o.color.a = OUTSG.; #endif #else #define VFX_TEXTURE_COLOR VFXGetTextureColor(VFX_SAMPLER(mainTexture),i) float4 color = VFXGetFragmentColor(i); #ifndef VFX_TEXTURE_COLOR #define VFX_TEXTURE_COLOR float4(1.0,1.0,1.0,1.0) #endif #if VFX_COLORMAPPING_DEFAULT o.color = color * VFX_TEXTURE_COLOR; #endif #if VFX_COLORMAPPING_GRADIENTMAPPED o.color = SampleGradient(gradient, VFX_TEXTURE_COLOR.a * color.a) * float4(color.rgb,1.0); #endif o.color = VFXApplyPreExposure(o.color, i); #endif o.color = VFXApplyAO(o.color,i); o.color = VFXApplyFog(o.color,i); VFXClipFragmentColor(o.color.a,i); o.color.a = saturate(o.color.a); o.color = VFXTransformFinalColor(o.color); #if VFX_FEATURE_MOTION_VECTORS_FORWARD //No w division with fast path of motion vectors #ifdef VFX_FEATURE_MOTION_VECTORS_VERTS float2 velocity = i.VFX_VARYING_VELOCITY_CPOS - i.VFX_VARYING_VELOCITY_CPOS_PREVIOUS; #else float2 velocity = (i.VFX_VARYING_VELOCITY_CPOS.xy/i.VFX_VARYING_VELOCITY_CPOS.w) - (i.VFX_VARYING_VELOCITY_CPOS_PREVIOUS.xy/i.VFX_VARYING_VELOCITY_CPOS_PREVIOUS.w); #endif #if UNITY_UV_STARTS_AT_TOP velocity.y = -velocity.y; #endif float4 encodedMotionVector = 0.0f; VFXEncodeMotionVector(velocity * 0.5f, encodedMotionVector); o.outMotionVector = encodedMotionVector; o.outMotionVector.a = o.color.a < i.VFX_VARYING_ALPHATHRESHOLD ? 0.0f : 1.0f; //Independant clipping for motion vector pass #endif return o; } ENDHLSL } } }
Leave a Comment