#ifndef UTS_MATERIAL_EVALUATION #define UTS_MATERIAL_EVALUATION #define ColorSpaceDielectricSpec half4(0.22, 0.22, 0.22, 0.779) #include "Packages/com.misaki.hdrp-toon/Runtime/Shaders/Includes/Lighting/UtsShadowEvaluation.hlsl" float RoughnessToBlinnPhongSpecularExponent(float roughness) { return clamp(2 * rcp(roughness * roughness) - 2, FLT_EPS, rcp(FLT_EPS)); } float StepFeatherToon(float value,float step,float feather) { return saturate((value - step + feather) / feather); } float3 ComputeSpecularTerm(UtsBSDFData bsdfData, PreLightData preLightData, float3 V, float3 L) { #ifdef _PBR_MODE_OFF return 0; #else float3 specTerm; float3 N = bsdfData.normalWS; float3 H = normalize(L + V); float NdotL = dot(N, L); float NdotH = saturate(dot(N, H)); float clampedNdotV = ClampNdotV(preLightData.NdotV); float clampedNdotL = saturate(NdotL); float partLambdaV; float3 DV = 0; #ifdef _PBR_MODE_STANDARD partLambdaV = GetSmithJointGGXPartLambdaV(clampedNdotV, bsdfData.roughnessT); // We use abs(NdotL) to handle the none case of double sided DV = DV_SmithJointGGX(NdotH, abs(NdotL), clampedNdotV, bsdfData.roughnessT, partLambdaV); #elif _PBR_MODE_ANISOTROPY float TdotV = dot(bsdfData.tangentWS, V); float BdotV = dot(bsdfData.bitangentWS, V); ConvertAnisotropyToRoughness(bsdfData.perceptualRoughness, bsdfData.anisotropy, bsdfData.roughnessT, bsdfData.roughnessB); partLambdaV = GetSmithJointGGXAnisoPartLambdaV(TdotV, BdotV, clampedNdotV, bsdfData.roughnessT, bsdfData.roughnessB); // For anisotropy we must not saturate these values float TdotH = dot(bsdfData.tangentWS, H); float TdotL = dot(bsdfData.tangentWS, L); float BdotH = dot(bsdfData.bitangentWS, H); float BdotL = dot(bsdfData.bitangentWS, L); // We use abs(NdotL) to handle the none case of double sided DV = DV_SmithJointGGXAniso(TdotH, BdotH, NdotH, clampedNdotV, TdotL, BdotL, abs(NdotL), bsdfData.roughnessT, bsdfData.roughnessB, partLambdaV); #elif _PBR_MODE_HAIR float3 t = ShiftTangent(bsdfData.bitangentWS, N, bsdfData.anisotropy); float specularExponent = RoughnessToBlinnPhongSpecularExponent(PerceptualRoughnessToRoughness(bsdfData.perceptualRoughness)); DV = D_KajiyaKay(t, H, specularExponent); float normalizeSpec = DV * rcp(specularExponent + 2.0) * TWO_PI; DV = DV * normalizeSpec * _KKColor.rgb; #elif _PBR_MODE_FABRIC float D = D_Charlie(NdotH, bsdfData.roughnessT); // V_Charlie is expensive, use approx with V_Ashikhmin instead // float V = V_Charlie(NdotL, clampedNdotV, bsdfData.roughness); float Vis = V_Ashikhmin(NdotL, clampedNdotV); DV = D * Vis; #elif _PBR_MODE_TOON float specularExponent = RoughnessToBlinnPhongSpecularExponent(PerceptualRoughnessToRoughness(bsdfData.perceptualRoughness)); DV = pow(NdotH, 5.0 * specularExponent); DV = StepFeatherToon(DV, _ToonSpecularStep, _ToonSpecularFeather); #endif // We use specularFGD here to approximate F. specTerm = DV * preLightData.specularFGD * clampedNdotL; return specTerm; #endif } half3 FitWithCurveApprox(half NdotL, half Curvature) { half curva = (1.0 / mad(Curvature, 0.5 - 0.0625, 0.0625) - 2.0) / (16.0 - 2.0); half oneMinusCurva = 1.0 - curva; half3 curve0; { half3 rangeMin = half3(0.0, 0.3, 0.3); half3 rangeMax = half3(1.0, 0.7, 0.7); half3 offset = half3(0.0, 0.06, 0.06); half3 t = saturate(mad(NdotL, 1.0 / (rangeMax - rangeMin), (offset + rangeMin) / (rangeMin - rangeMax))); half3 lowerLine = (t * t) * half3(0.65, 0.5, 0.9); lowerLine.r += 0.045; lowerLine.b *= t.b; half3 m = half3(1.75, 2.0, 1.97); half3 upperLine = mad(NdotL, m, half3(0.99, 0.99, 0.99) - m); upperLine = saturate(upperLine); half3 lerpMin = half3(0.0, 0.35, 0.35); half3 lerpMax = half3(1.0, 0.7, 0.6); half3 lerpT = saturate(mad(NdotL, 1.0 / (lerpMax - lerpMin), lerpMin / (lerpMin - lerpMax))); curve0 = lerp(lowerLine, upperLine, lerpT * lerpT); } half3 curve1; { half3 m = half3(1.95, 2.0, 2.0); half3 upperLine = mad(NdotL, m, half3(0.99, 0.99, 1.0) - m); curve1 = saturate(upperLine); } float oneMinusCurva2 = oneMinusCurva * oneMinusCurva; return lerp(curve0, curve1, mad(oneMinusCurva2, -1.0 * oneMinusCurva2, 1.0)); } DirectLighting UtsShadeSurface(PositionInputs posInput, UtsBSDFData bsdfData, PreLightData preLightData, SHADOW_TYPE shadow, float3 lightColor, float3 V, float3 L, float2 uv, float diffuseDimmer, float specularDimmer) { DirectLighting lighting; ZERO_INITIALIZE(DirectLighting, lighting); if (Max3(lightColor.r, lightColor.g, lightColor.b) > 0.0) { SHADOW_TYPE sharpShadow = smoothstep(0.4, 0.6, shadow); //SHADOW_TYPE sharpShadow = shadow; #if _RECEIVE_HAIR_SHADOW_ON && ENABLE_UTS_HAIR_SHAOW sharpShadow *= GetHairShadow(posInput, L); #endif #if _SHADING_MODE_SDF float angle; float3 sdfTexture = SampleSDFTexture(L, uv, angle); // r: sdf shadow, g: sdf highlight, b: halfshadow float shadowSmoothLevel = _SDFShadowSmoothLevel / 10.0; float sdfShadowMask = smoothstep(angle - shadowSmoothLevel, angle + shadowSmoothLevel, sdfTexture.r); float sdfHighlight = sdfTexture.g * _SDFHighlightStrength; #endif float3 diffuseTerm = 0.0; float3 specularTerm = ComputeSpecularTerm(bsdfData, preLightData, V, L); #if _USE_SHADING_RAMP_MAP_ON float rampMask = _ShadingRampMask; #if _SHADING_RAMP_MASK_MAP rampMask *= SAMPLE_TEXTURE2D(_ShadingRampMaskMap, s_linear_clamp_sampler, uv).r; #endif #if _SHADING_MODE_STANDARD float NdotL = dot(bsdfData.normalWS, L); float halfLambert = 0.5 * NdotL + 0.5; float3 rampColor = SAMPLE_TEXTURE2D_ARRAY_LOD(_ShadingRampMap, s_linear_clamp_sampler, float2(halfLambert * sharpShadow.x, rampMask), _ShadingIndex, 0).rgb; diffuseTerm = bsdfData.diffuseColor * rampColor * INV_PI; specularTerm *= saturate(NdotL) * sharpShadow; #elif _SHADING_MODE_SDF float3 rampColor = SAMPLE_TEXTURE2D_ARRAY_LOD(_ShadingRampMap, s_linear_clamp_sampler, float2(sdfShadowMask * sharpShadow.x, rampMask), _ShadingIndex, 0).rgb; diffuseTerm = bsdfData.diffuseColor * rampColor * INV_PI; specularTerm = (specularTerm + sdfHighlight) * sdfShadowMask * sharpShadow; #endif #else #if _SHADING_MODE_STANDARD float NdotL = dot(bsdfData.normalWS, L); float halfLambert = 0.5 * NdotL + 0.5; // float firstColorFeatherForMask = lerp(_1stShadeColorFeather, 0.0, max(_ComposerMaskMode, _FirstShadeOverridden)); float baseShadeMask = saturate((halfLambert - (_1stShadeColorStep - _1stShadeColorFeather)) / (_1stShadeColorStep - (_1stShadeColorStep - _1stShadeColorFeather))); baseShadeMask *= sharpShadow.x; // float secondColorFeatherForMask = lerp(_2ndShadeColorFeather, 0.0, max(_SecondShadeOverridden, _ComposerMaskMode)); float firstShadeMask = saturate((halfLambert - (_2ndShadeColorStep - _2ndShadeColorFeather)) / (_2ndShadeColorStep - (_2ndShadeColorStep - _2ndShadeColorFeather))); diffuseTerm = lerp(lerp(bsdfData.secondShadingDiffuseColor, bsdfData.firstShadingDiffuseColor, firstShadeMask), bsdfData.diffuseColor, baseShadeMask) * INV_PI; specularTerm *= baseShadeMask; #elif _SHADING_MODE_SDF float shadeMask = sdfShadowMask * sdfTexture.b * sharpShadow.x; diffuseTerm = lerp(bsdfData.firstShadingDiffuseColor, bsdfData.diffuseColor, shadeMask) * INV_PI; specularTerm = (specularTerm + sdfHighlight) * shadeMask; #endif #endif lighting.diffuse += diffuseTerm * lightColor * diffuseDimmer; lighting.specular += specularTerm * lightColor * specularDimmer; #if _LIGHT_BASE_RIM_LIGHT_ON if (HasFlag(bsdfData.surfaceFeatures, SURFACEFEATURE_RIM_LIGHT)) { DirectLighting rimLightLighting = UtsEvaluateLighting_RimLight(posInput, bsdfData, preLightData, L, lightColor); lighting.diffuse += rimLightLighting.diffuse; lighting.specular += rimLightLighting.specular; } #endif // lighting.diffuse = sharpShadow; } return lighting; } #endif