浏览代码

Merge pull request #610 from EvgeniiG/master

Bugfix transmission
/main
GitHub 7 年前
当前提交
5cadd592
共有 3 个文件被更改,包括 68 次插入50 次删除
  1. 33
      ScriptableRenderPipeline/Core/ShaderLibrary/Common.hlsl
  2. 6
      ScriptableRenderPipeline/Core/ShaderLibrary/Macros.hlsl
  3. 79
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl

33
ScriptableRenderPipeline/Core/ShaderLibrary/Common.hlsl


// PositivePow remove this warning when you know the value is positive and avoid inf/NAN.
TEMPLATE_2_FLT(PositivePow, base, power, return pow(max(abs(base), FLT_EPS), power))
// Returns -1 for negative numbers and -0, 1 for positive numbers and +0.
// This behavior is different from the Signum function sign(), which returns 0 for 0.
// 2x VALU.
float FastSign(float s)
// Computes (FastSign(s) * x) using 2x VALU.
// See the comment about FastSign() below.
float FastMulBySignOf(float s, float x, bool ignoreNegZero = true)
uint negZero = 0x80000000u;
uint signBit = negZero & asuint(s);
return asfloat(signBit | asuint(1.0));
if (ignoreNegZero)
{
return (s >= 0) ? x : -x;
}
else
{
uint negZero = 0x80000000u;
uint signBit = negZero & asuint(s);
return asfloat(signBit ^ asuint(x));
}
// Multiplies 'x' by the sign of 's'. Treats -0 as 0.
// 2x VALU compared to 3x VALU of (x * FastSign(s)).
float FastMulBySignOf(float x, float s)
// Returns -1 for negative numbers and 1 for positive numbers.
// 0 can be handled in 2 different ways.
// The IEEE floating point standard defines 0 as signed: +0 and -0.
// However, mathematics typically treats 0 as unsigned.
// Therefore, we treat -0 as +0 by default: FastSign(+0) = FastSign(-0) = 1.
// If (ignoreNegZero = false), FastSign(-0, false) = -1.
// Note that the sign() function in HLSL implements signum, which returns 0 for 0.
float FastSign(float s, bool ignoreNegZero = true)
return (s >= 0) ? x : -x;
return FastMulBySignOf(s, 1.0, ignoreNegZero);
}
// Orthonormalizes the tangent frame using the Gram-Schmidt process.

6
ScriptableRenderPipeline/Core/ShaderLibrary/Macros.hlsl


#define LOG2_E 1.44269504088896340736
#define INFINITY asfloat(0x7F800000)
#define FLT_EPS 1.192092896e-07 // Smallest positive number, such that 1.0 + FLT_EPS != 1.0
#define FLT_MIN 1.175494351e-38 // Minimum representable positive floating-point number
#define FLT_MAX 3.402823466e+38 // Maximum representable floating-point number
#define FLT_EPS 1.192092896e-07 // Smallest positive number, such that 1.0 + FLT_EPS != 1.0
#define FLT_MIN 1.175494351e-38 // Minimum representable positive floating-point number
#define FLT_MAX 3.402823466e+38 // Maximum representable floating-point number
#define HALF_MIN 6.103515625e-5 // 2^-14, the same value for 10, 11 and 16-bit: https://www.khronos.org/opengl/wiki/Small_Float_Formats
#define HALF_MAX 65504.0
#define UINT_MAX 0xFFFFFFFFu

79
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl


PreLightData GetPreLightData(float3 V, PositionInputs posInput, BSDFData bsdfData)
{
PreLightData preLightData;
ZERO_INITIALIZE(PreLightData, preLightData);
float3 N;
float NdotV;

#elif LIT_DIFFUSE_GGX_BRDF
float3 diffuseTerm = DiffuseGGX(bsdfData.diffuseColor, NdotV, NdotL, NdotH, LdotV, bsdfData.roughness);
#else
// A note on subsurface scattering.
// A note on subsurface scattering: [SSS-NOTE-TRSM]
// The correct way to handle SSS is to transmit light inside the surface, perform SSS,
// and then transmit it outside towards the viewer.
// Transmit(X) = F_Transm_Schlick(F0, F90, NdotX), where F0 = 0, F90 = 1.

return cookie;
}
// 'intensity' is already premultiplied with 'shadow', 'color' is NOT premultiplied with anything.
void EvaluateLight_Directional(LightLoopContext lightLoopContext,
float3 N, float3 L, float NdotL, PositionInputs posInput,
// None of the outputs are premultiplied.
void EvaluateLight_Directional(LightLoopContext lightLoopContext, PositionInputs posInput,
out float3 color, out float intensity, out float shadow)
float3 N, float3 L,
out float3 color, out float attenuation, out float shadow)
color = lightData.color;
intensity = saturate(NdotL);
shadow = 1.0;
color = lightData.color;
attenuation = 1.0;
shadow = 1.0;
#ifdef SHADOWS_SHADOWMASK
// shadowMaskSelector.x is -1 if there is no shadow mask

#endif
}
intensity *= shadow;
color *= cookie.rgb;
intensity *= cookie.a;
color *= cookie.rgb;
attenuation *= cookie.a;
}
}

float3 N = bsdfData.normalWS;
float3 L = -lightData.forward; // Lights point backward in Unity
float NdotL = dot(bsdfData.normalWS, L);
float NdotL = dot(N, L);
float3 color; float intensity, shadow;
EvaluateLight_Directional(lightLoopContext, N, L, NdotL, posInput, lightData, bakeLightingData,
color, intensity, shadow);
float3 color; float attenuation, shadow;
EvaluateLight_Directional(lightLoopContext, posInput, lightData, bakeLightingData, N, L,
color, attenuation, shadow);
float intensity = shadow * attenuation * saturate(NdotL);
[branch] if (intensity > 0.0)
{

// Apply wrapped lighting to better handle thin objects (cards) at grazing angles.
float wrappedNdotL = ComputeWrappedDiffuseLighting(-NdotL, SSS_WRAP_LIGHT);
// Apply the BSDF to attenuation. See also: [SSS-NOTE-TRSM]
intensity = Lambert() * wrappedNdotL;
attenuation *= Lambert();
intensity = INV_PI * F_Transm_Schlick(0, 0.5, NdotV) * F_Transm_Schlick(0, 0.5, tNdotL) * wrappedNdotL;
attenuation *= INV_PI * F_Transm_Schlick(0, 0.5, NdotV) * F_Transm_Schlick(0, 0.5, tNdotL);
// Shadowing is applied inside EvaluateTransmission().
intensity = attenuation * wrappedNdotL;
// We use diffuse lighting for accumulation since it is going to be blurred during the SSS pass.
// We don't multiply by 'bsdfData.diffuseColor' here. It's done only once in PostEvaluateBSDF().
lighting.diffuse += EvaluateTransmission(bsdfData, intensity * lightData.diffuseScale, shadow);

return attenuation * GetAngleAttenuation(L, -lightData.forward, lightData.angleScale, lightData.angleOffset);
}
// 'intensity' is already premultiplied with 'shadow', 'color' is NOT premultiplied with anything.
void EvaluateLight_Punctual(LightLoopContext lightLoopContext,
float3 N, float3 L, float NdotL, float distSq, PositionInputs posInput,
// None of the outputs are premultiplied.
void EvaluateLight_Punctual(LightLoopContext lightLoopContext, PositionInputs posInput,
out float3 color, out float intensity, out float shadow)
float3 N, float3 L, float distSq,
out float3 color, out float attenuation, out float shadow)
color = lightData.color;
intensity = GetPunctualShapeAttenuation(lightData, L, distSq) * saturate(NdotL);
shadow = 1.0;
color = lightData.color;
attenuation = GetPunctualShapeAttenuation(lightData, L, distSq);
shadow = 1.0;
#ifdef SHADOWS_SHADOWMASK
// shadowMaskSelector.x is -1 if there is no shadow mask

#endif
}
intensity *= shadow;
// Projector lights always have a cookies, so we can perform clipping inside the if().
[branch] if (lightData.cookieIndex >= 0)
{

color *= cookie.rgb;
intensity *= cookie.a;
color *= cookie.rgb;
attenuation *= cookie.a;
}
}

float distSq = dot(unL, unL);
float3 N = bsdfData.normalWS;
float3 L = unL * rsqrt(distSq);
float NdotL = dot(bsdfData.normalWS, L);
float NdotL = dot(N, L);
float3 color; float attenuation, shadow;
EvaluateLight_Punctual(lightLoopContext, posInput, lightData, bakeLightingData, N, L, distSq,
color, attenuation, shadow);
float3 color; float intensity, shadow;
EvaluateLight_Punctual(lightLoopContext, N, L, NdotL, distSq, posInput, lightData, bakeLightingData,
color, intensity, shadow);
float intensity = shadow * attenuation * saturate(NdotL);
[branch] if (intensity > 0.0)
{

// Apply wrapped lighting to better handle thin objects (cards) at grazing angles.
float wrappedNdotL = ComputeWrappedDiffuseLighting(-NdotL, SSS_WRAP_LIGHT);
// Apply the BSDF to attenuation. See also: [SSS-NOTE-TRSM]
intensity = Lambert() * wrappedNdotL;
attenuation *= Lambert();
intensity = INV_PI * F_Transm_Schlick(0, 0.5, NdotV) * F_Transm_Schlick(0, 0.5, tNdotL) * wrappedNdotL;
attenuation *= INV_PI * F_Transm_Schlick(0, 0.5, NdotV) * F_Transm_Schlick(0, 0.5, tNdotL);
// Shadowing is applied inside EvaluateTransmission().
intensity = attenuation * wrappedNdotL;
// We use diffuse lighting for accumulation since it is going to be blurred during the SSS pass.
// We don't multiply by 'bsdfData.diffuseColor' here. It's done only once in PostEvaluateBSDF().

正在加载...
取消
保存