Files
2026-11-01 23:39:55 +02:00

98 lines
4.2 KiB
HLSL

#ifndef UNIVERSAL_PARTICLESINSTANCING_INCLUDED
#define UNIVERSAL_PARTICLESINSTANCING_INCLUDED
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/ParticlesInstancing.hlsl"
#if defined(UNITY_PARTICLE_INSTANCING_ENABLED)
// Kept for backward compatibility with custom shaders that call it directly.
void ParticleInstancingMatrices(out float4x4 objectToWorld, out float4x4 worldToObject)
{
UNITY_PARTICLE_INSTANCE_DATA data = unity_ParticleInstanceData[unity_InstanceID];
// transform matrix
objectToWorld._11_21_31_41 = float4(data.transform._11_21_31, 0.0f);
objectToWorld._12_22_32_42 = float4(data.transform._12_22_32, 0.0f);
objectToWorld._13_23_33_43 = float4(data.transform._13_23_33, 0.0f);
objectToWorld._14_24_34_44 = float4(data.transform._14_24_34, 1.0f);
// inverse transform matrix
float3x3 worldToObject3x3;
worldToObject3x3[0] = objectToWorld[1].yzx * objectToWorld[2].zxy - objectToWorld[1].zxy * objectToWorld[2].yzx;
worldToObject3x3[1] = objectToWorld[0].zxy * objectToWorld[2].yzx - objectToWorld[0].yzx * objectToWorld[2].zxy;
worldToObject3x3[2] = objectToWorld[0].yzx * objectToWorld[1].zxy - objectToWorld[0].zxy * objectToWorld[1].yzx;
float det = dot(objectToWorld[0].xyz, worldToObject3x3[0]);
worldToObject3x3 = transpose(worldToObject3x3);
worldToObject3x3 *= rcp(det);
float3 worldToObjectPosition = mul(worldToObject3x3, -objectToWorld._14_24_34);
worldToObject._11_21_31_41 = float4(worldToObject3x3._11_21_31, 0.0f);
worldToObject._12_22_32_42 = float4(worldToObject3x3._12_22_32, 0.0f);
worldToObject._13_23_33_43 = float4(worldToObject3x3._13_23_33, 0.0f);
worldToObject._14_24_34_44 = float4(worldToObjectPosition, 1.0f);
}
// Builds VertexPositionInputs from the particle instance transform directly,
// bypassing GetVertexPositionInputs() which reads UNITY_MATRIX_M.
VertexPositionInputs ParticleInstancingGetVertexPositionInputs(float3x4 transform, float3 positionOS)
{
VertexPositionInputs vertexInput;
vertexInput.positionWS = ParticleInstancingTransformPosition(transform, positionOS);
vertexInput.positionVS = TransformWorldToView(vertexInput.positionWS);
vertexInput.positionCS = TransformWorldToHClip(vertexInput.positionWS);
float4 ndc = vertexInput.positionCS * 0.5f;
vertexInput.positionNDC.xy = float2(ndc.x, ndc.y * _ProjectionParams.x) + ndc.w;
vertexInput.positionNDC.zw = vertexInput.positionCS.zw;
return vertexInput;
}
// Builds VertexNormalInputs from the particle instance transform directly,
// bypassing GetVertexNormalInputs() which reads UNITY_MATRIX_I_M.
// Tangents transform with the forward 3x3 (covariant, like directions).
// Normals require the inverse-transpose: cofactor(m) equals det(m)*m^{-T};
// after SafeNormalize this gives the correct world normal under non-uniform scale.
// Matches TransformParticleMesh in the ShaderGraph package (Particles.hlsl).
VertexNormalInputs ParticleInstancingGetVertexNormalInputs(float3x4 transform, float3 normalOS, float4 tangentOS)
{
ParticleInstancingTransformNormalTangent(transform, normalOS, tangentOS.xyz);
VertexNormalInputs tbn;
tbn.normalWS = SafeNormalize(normalOS);
tbn.tangentWS = real3(SafeNormalize(tangentOS.xyz));
real sign = real(tangentOS.w) * GetOddNegativeScale();
tbn.bitangentWS = real3(cross(tbn.normalWS, float3(tbn.tangentWS))) * sign;
return tbn;
}
#endif
VertexPositionInputs GetParticleVertexPositionInputs(float3 positionOS)
{
#if defined(UNITY_PARTICLE_INSTANCING_ENABLED)
return ParticleInstancingGetVertexPositionInputs(unity_ParticleInstanceData[unity_InstanceID].transform, positionOS);
#else
return GetVertexPositionInputs(positionOS);
#endif
}
VertexNormalInputs GetParticleVertexNormalInputs(float3 normalOS, float4 tangentOS)
{
#if defined(UNITY_PARTICLE_INSTANCING_ENABLED)
return ParticleInstancingGetVertexNormalInputs(unity_ParticleInstanceData[unity_InstanceID].transform, normalOS, tangentOS);
#else
return GetVertexNormalInputs(normalOS, tangentOS);
#endif
}
VertexNormalInputs GetParticleVertexNormalInputs(float3 normalOS)
{
return GetParticleVertexNormalInputs(normalOS, float4(0, 0, 0, 1));
}
#endif // UNIVERSAL_PARTICLESINSTANCING_INCLUDED