98 lines
4.2 KiB
HLSL
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
|