You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
92 lines
4.1 KiB
92 lines
4.1 KiB
#if defined(SURFACE_GRADIENT) || defined(DECAL_NORMAL_BLENDING)
|
|
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/NormalSurfaceGradient.hlsl"
|
|
#endif
|
|
|
|
// Using this function instead of accessing the constant directly allows for overrides, in particular
|
|
// in Path Tracing where we want to change the sidedness behaviour based on the transparency mode.
|
|
float3 GetDoubleSidedConstants()
|
|
{
|
|
#ifdef _DOUBLESIDED_ON
|
|
|
|
#if (SHADERPASS == SHADERPASS_PATH_TRACING)
|
|
|
|
#if defined(_SURFACE_TYPE_TRANSPARENT) && (defined(_REFRACTION_PLANE) || defined(_REFRACTION_SPHERE))
|
|
return 1.0; // Force to 'None'
|
|
#else
|
|
return _DoubleSidedConstants.z > 0.0 ? -1.0 : _DoubleSidedConstants.xyz; // Force to 'Flip' or 'Mirror'
|
|
#endif
|
|
|
|
#else // SHADERPASS_PATH_TRACING
|
|
|
|
return _DoubleSidedConstants.xyz;
|
|
|
|
#endif // SHADERPASS_PATH_TRACING
|
|
|
|
#else // _DOUBLESIDED_ON
|
|
|
|
return 1.0;
|
|
|
|
#endif // _DOUBLESIDED_ON
|
|
}
|
|
|
|
// Flipping or mirroring a normal can be done directly on the tangent space. This has the benefit to apply to the whole process either in surface gradient or not.
|
|
// This function will modify FragInputs and this is not propagate outside of GetSurfaceAndBuiltinData(). This is ok as tangent space is not use outside of GetSurfaceAndBuiltinData().
|
|
void ApplyDoubleSidedFlipOrMirror(inout FragInputs input, float3 doubleSidedConstants)
|
|
{
|
|
#ifdef _DOUBLESIDED_ON
|
|
// 'doubleSidedConstants' is float3(-1, -1, -1) in flip mode and float3(1, 1, -1) in mirror mode.
|
|
// It's float3(1, 1, 1) in the none mode.
|
|
float flipSign = input.isFrontFace ? 1.0 : doubleSidedConstants.z;
|
|
// For the 'Flip' mode, we should not modify the tangent and the bitangent (which correspond
|
|
// to the surface derivatives), and instead modify (invert) the displacements.
|
|
input.tangentToWorld[2] = flipSign * input.tangentToWorld[2]; // normal
|
|
#endif
|
|
}
|
|
|
|
#if defined(SURFACE_GRADIENT) || defined(DECAL_NORMAL_BLENDING)
|
|
void GetNormalWS_SG(FragInputs input, float3 normalTS, out float3 normalWS, float3 doubleSidedConstants)
|
|
{
|
|
#ifdef _DOUBLESIDED_ON
|
|
// Flip the displacements (the entire surface gradient) in the 'flip normal' mode.
|
|
float flipSign = input.isFrontFace ? 1.0 : doubleSidedConstants.x;
|
|
normalTS *= flipSign;
|
|
#endif
|
|
|
|
normalWS = SurfaceGradientResolveNormal(input.tangentToWorld[2], normalTS);
|
|
}
|
|
#endif
|
|
|
|
// This function convert the tangent space normal/tangent to world space and orthonormalize it + apply a correction of the normal if it is not pointing towards the near plane
|
|
void GetNormalWS(FragInputs input, float3 normalTS, out float3 normalWS, float3 doubleSidedConstants)
|
|
{
|
|
#if defined(SURFACE_GRADIENT)
|
|
GetNormalWS_SG(input, normalTS, normalWS, doubleSidedConstants);
|
|
#else
|
|
|
|
#ifdef _DOUBLESIDED_ON
|
|
float flipSign = input.isFrontFace ? 1.0 : doubleSidedConstants.x;
|
|
normalTS.xy *= flipSign;
|
|
#endif // _DOUBLESIDED_ON
|
|
|
|
// We need to normalize as we use mikkt tangent space and this is expected (tangent space is not normalized)
|
|
normalWS = SafeNormalize(TransformTangentToWorld(normalTS, input.tangentToWorld));
|
|
#endif
|
|
}
|
|
|
|
// This function takes a world space src normal + applies a correction to the normal if it is not pointing towards the near plane.
|
|
void GetNormalWS_SrcWS(FragInputs input, float3 srcNormalWS, out float3 normalWS, float3 doubleSidedConstants)
|
|
{
|
|
#ifdef _DOUBLESIDED_ON
|
|
srcNormalWS = (!input.isFrontFace && doubleSidedConstants.z < 0) ? srcNormalWS + 2 * input.tangentToWorld[2] * max(0, -dot(input.tangentToWorld[2], srcNormalWS)) : srcNormalWS;
|
|
normalWS = (!input.isFrontFace && doubleSidedConstants.x < 0) ? reflect(-srcNormalWS, input.tangentToWorld[2]) : srcNormalWS;
|
|
#else
|
|
normalWS = srcNormalWS;
|
|
#endif
|
|
}
|
|
|
|
// This function converts an object space normal to world space + applies a correction to the normal if it is not pointing towards the near plane.
|
|
void GetNormalWS_SrcOS(FragInputs input, float3 srcNormalOS, out float3 normalWS, float3 doubleSidedConstants)
|
|
{
|
|
float3 srcNormalWS = TransformObjectToWorldNormal(srcNormalOS);
|
|
GetNormalWS_SrcWS(input, srcNormalWS, normalWS, doubleSidedConstants);
|
|
}
|