#ifndef CHARACTERCOMMONUTIL_BASE #define CHARACTERCOMMONUTIL_BASE #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl" #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/SurfaceInput.hlsl" #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl" inline half3 BlendMode_Screen( half3 s, half3 d) { return s + d - s*d; } inline half3 RotationY(half3 pointP, half angle) { half radY = radians(angle); half sinY = sin(radY); half cosY = cos(radY); return half3(pointP.x * cosY - pointP.z * sinY, pointP.y, pointP.x * sinY + pointP.z * cosY); } inline half3 RgbToHsv_SGame(half3 c) { half4 K = half4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); half4 p = lerp(half4(c.bg, K.wz), half4(c.gb, K.xy), step(c.b, c.g)); half4 q = lerp(half4(p.xyw, c.r), half4(c.r, p.yzx), step(p.x, c.r)); half d = q.x - min(q.w, q.y); half e = 1.0e-4; return half3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x); } inline half3 HsvToRgb_SGame(half3 c) { half4 K = half4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); half3 p = abs(frac(c.xxx + K.xyz) * 6.0 - K.www); return c.z * lerp(K.xxx, saturate(p - K.xxx), c.y); } struct UnityLight { half3 color; half3 dir; half ndotl; // Deprecated: Ndotl is now calculated on the fly and is no longer stored. Do not used it. }; struct UnityIndirect { half3 diffuse; half3 specular; }; struct UnityGI { UnityLight light; UnityIndirect indirect; }; struct UnityGIInput { UnityLight light; // pixel light, sent from the engine float3 worldPos; half3 worldViewDir; half atten; half3 ambient; float4 lightmapUV; // .xy = static lightmap UV, .zw = dynamic lightmap UV #if defined(UNITY_SPECCUBE_BLENDING) || defined(UNITY_SPECCUBE_BOX_PROJECTION) || defined(UNITY_ENABLE_REFLECTION_BUFFERS) float4 boxMin[2]; #endif #ifdef UNITY_SPECCUBE_BOX_PROJECTION float4 boxMax[2]; float4 probePosition[2]; #endif // HDR cubemap properties, use to decompress HDR texture float4 probeHDR[2]; }; struct Unity_GlossyEnvironmentData { half roughness; // CAUTION: This is perceptualRoughness but because of compatibility this name can't be change :( half3 reflUVW; }; //------------------------------------------------------------------------------------- half3 NormalizePerVertexNormal (float3 n) // takes float to avoid overflow { #if (SHADER_TARGET < 30) || UNITY_STANDARD_SIMPLE return normalize(n); #else return n; // will normalize per-pixel instead #endif } half3 NormalizePerPixelNormal (half3 n) { #if (SHADER_TARGET < 30) || UNITY_STANDARD_SIMPLE return n; #else return normalize(n); #endif } //------------------------------------------------------------------------------------- UnityLight MainLight () { UnityLight l; l.color = GetMainLight().color.rgb; half3 hsvLightCol = RgbToHsv_SGame(GetMainLight().color.rgb); hsvLightCol.b = clamp(hsvLightCol.b, 0.9, 1.1); l.color = HsvToRgb_SGame(hsvLightCol); l.dir = GetMainLight().direction; return l; } UnityLight AdditiveLight (half3 lightDir, half atten) { UnityLight l; l.color = GetMainLight().color.rgb; l.dir = lightDir; #ifndef USING_DIRECTIONAL_LIGHT l.dir = NormalizePerPixelNormal(l.dir); #endif l.color *= atten; return l; } UnityLight DummyLight () { UnityLight l; l.color = 0; l.dir = half3 (0,1,0); return l; } UnityIndirect ZeroIndirect () { UnityIndirect ind; ind.diffuse = 0; ind.specular = 0; return ind; } Unity_GlossyEnvironmentData UnityGlossyEnvironmentSetup(half Smoothness, half3 worldViewDir, half3 Normal, half3 fresnel0) { Unity_GlossyEnvironmentData g; g.roughness /* perceptualRoughness */ = PerceptualSmoothnessToPerceptualRoughness(Smoothness); g.reflUVW = reflect(-worldViewDir, Normal); return g; } inline void ResetUnityLight(out UnityLight outLight) { outLight.color = half3(0, 0, 0); outLight.dir = half3(0, 1, 0); // Irrelevant direction, just not null outLight.ndotl = 0; // Not used } inline void ResetUnityGI(out UnityGI outGI) { ResetUnityLight(outGI.light); outGI.indirect.diffuse = 0; outGI.indirect.specular = 0; } half3 UnpackScaleNormalRGorAG(half4 packednormal, half bumpScale) { #if defined(UNITY_NO_DXT5nm) half3 normal = packednormal.xyz * 2 - 1; #if (SHADER_TARGET >= 30) normal.xy *= bumpScale; #endif return normal; #elif defined(UNITY_ASTC_NORMALMAP_ENCODING) half3 normal; normal.xy = (packednormal.wy * 2 - 1); normal.z = sqrt(1.0 - saturate(dot(normal.xy, normal.xy))); normal.xy *= bumpScale; return normal; #else packednormal.x *= packednormal.w; half3 normal; normal.xy = (packednormal.xy * 2 - 1); #if (SHADER_TARGET >= 30) normal.xy *= bumpScale; #endif normal.z = sqrt(1.0 - saturate(dot(normal.xy, normal.xy))); return normal; #endif } half3 UnpackScaleNormal(half4 packednormal, half bumpScale) { return UnpackScaleNormalRGorAG(packednormal, bumpScale); } half3x3 CreateTangentToWorldPerVertex(half3 normal, half3 tangent, half tangentSign) { // For odd-negative scale transforms we need to flip the sign half sign = tangentSign * unity_WorldTransformParams.w; half3 binormal = cross(normal, tangent) * sign; return half3x3(tangent, binormal, normal); } // ---------------------------------------------------------------------------- inline half3 DecodeHDR (half4 data, half4 decodeInstructions) { // Take into account texture alpha if decodeInstructions.w is true(the alpha value affects the RGB channels) half alpha = decodeInstructions.w * (data.a - 1.0) + 1.0; // If Linear mode is not supported we can skip exponent part #if defined(UNITY_COLORSPACE_GAMMA) return (decodeInstructions.x * alpha) * data.rgb; #else #if defined(UNITY_USE_NATIVE_HDR) return decodeInstructions.x * data.rgb; // Multiplier for future HDRI relative to absolute conversion. #else return (decodeInstructions.x * pow(alpha, decodeInstructions.y)) * data.rgb; #endif #endif } inline half3 PreMultiplyAlpha (half3 diffColor, half alpha, half oneMinusReflectivity, out half outModifiedAlpha) { diffColor *= alpha; outModifiedAlpha = 1-oneMinusReflectivity + alpha*oneMinusReflectivity; return diffColor; } inline half OneMinusReflectivityFromMetallic(half metallic) { half oneMinusDielectricSpec = 0.56; return oneMinusDielectricSpec - metallic * oneMinusDielectricSpec; } inline half3 DiffuseAndSpecularFromMetallic (half3 albedo, half metallic, out half3 specColor, out half oneMinusReflectivity) { specColor = lerp (UNITY_LIGHTMODEL_AMBIENT.xyz, albedo, metallic); oneMinusReflectivity = OneMinusReflectivityFromMetallic(metallic); return albedo * oneMinusReflectivity; } inline UnityGI UnityGI_Base(UnityGIInput data, half occlusion, half3 normalWorld) { UnityGI o_gi; ResetUnityGI(o_gi); o_gi.light = data.light; o_gi.light.color *= data.atten; o_gi.indirect.diffuse *= occlusion; return o_gi; } inline half3 UnityGI_IndirectSpecular(UnityGIInput data, half occlusion, Unity_GlossyEnvironmentData glossIn) { half3 specular; specular = unity_IndirectSpecColor.rgb; return specular * occlusion; } inline half3 UnityGI_IndirectSpecular(UnityGIInput data, half occlusion, half3 normalWorld, Unity_GlossyEnvironmentData glossIn) { return UnityGI_IndirectSpecular(data, occlusion, glossIn); } inline UnityGI UnityGlobalIllumination (UnityGIInput data, half occlusion, half3 normalWorld) { return UnityGI_Base(data, occlusion, normalWorld); } inline UnityGI UnityGlobalIllumination (UnityGIInput data, half occlusion, half3 normalWorld, Unity_GlossyEnvironmentData glossIn) { UnityGI o_gi = UnityGI_Base(data, occlusion, normalWorld); o_gi.indirect.specular = UnityGI_IndirectSpecular(data, occlusion, glossIn); return o_gi; } inline UnityGI UnityGlobalIllumination (UnityGIInput data, half occlusion, half smoothness, half3 normalWorld, bool reflections) { Unity_GlossyEnvironmentData g = UnityGlossyEnvironmentSetup(smoothness, data.worldViewDir, normalWorld, float3(0, 0, 0)); return UnityGlobalIllumination(data, occlusion, normalWorld, g); } inline UnityGI UnityGlobalIllumination (UnityGIInput data, half occlusion, half smoothness, half3 normalWorld) { bool sampleReflections = true; return UnityGlobalIllumination (data, occlusion, smoothness, normalWorld, sampleReflections); } inline half3 GetSpecularColorGGX_Smoothness (half ndotH, half ndotL, half ldotH, half3 specularColor, half smoothness, half powFac = 64, half ggxClamp = 3) { half3 specular = 0; #if defined(_SG_GGX_SMOOTH) half perceptualRoughness = PerceptualSmoothnessToPerceptualRoughness (smoothness); perceptualRoughness = max(0.08, perceptualRoughness); half roughness = PerceptualSmoothnessToPerceptualRoughness(perceptualRoughness); half a = roughness; half a2 = a * a; half d = ndotH * ndotH * (a2 - 1) + 1.0001; half specularTerm = a2 / (max(0.2, ldotH * ldotH) * (roughness + 0.5) * (d * d) * powFac); specularTerm = specularTerm - 1e-4h; specularTerm = clamp(specularTerm, 0, ggxClamp); specular = specularTerm * specularColor.rgb; #endif return specular; } inline half3x3 GetDiffuseColor(half smoothness, half3 specularColor, half3 mainColor, half3 worldNormal, half lightAtten, half3 NDotL) { half3 lightColor = lerp(half3(0,0,0), GetMainLight().color.rgb, lightAtten * NDotL); specularColor = lerp(half3(0,0,0), GetMainLight().color.rgb, lightAtten) * specularColor; half3 diffuse = mainColor * lightColor; #if defined(SGAME_WET) && defined(SGAME_QUALITY_PERFECT) || defined(SGAME_QUALITY_HIGH) mainColor = lerp(mainColor, mainColor * _SG_WetColor, _SG_WetFactor); specularColor = lerp(specularColor, _SG_WetSpecularColor * _SG_WetSpecularStrength, _SG_WetFactor); smoothness = lerp(lerp(smoothness, _SG_WetSmoothness, _SG_WetFactor), smoothness, smoothness > _SG_WetSmoothness); half thunderNDotL = saturate(dot(worldNormal, _SG_ThunderDirection)); half3 thunderDiffuse = mainColor * lerp(half3(0, 0, 0), _SG_ThunderColor, max(lightAtten,0.1)) * thunderNDotL * _SG_ThunderStrength; diffuse += thunderDiffuse; #endif half3x3 matrixColor; matrixColor[0] = diffuse; matrixColor[1] = specularColor; matrixColor[2] = half3(smoothness, 0, 0); return matrixColor; } inline half3 GetSumLightingColorSpecGGX_Smoothness(half3 mainColor, half3 specularColor, half3 shLight, half3 worldNormal, half3 worldPos, half smoothness, half lightAtten, half powFac = 64, half ggxClamp = 3, half intensity = 1) { half3 worldViewDir = normalize(GetCameraPositionWS() - worldPos); half3 worldLightDir = normalize(GetMainLight().direction); half3 halfDir = normalize(worldLightDir + worldViewDir); half ndotH = max(dot(worldNormal, halfDir), 0); half NDotL = max(dot(worldNormal, worldLightDir), 0); half ldotH = max(dot(worldLightDir, halfDir), 0); half3x3 colorMatrix = GetDiffuseColor(smoothness, specularColor, mainColor, worldNormal, lightAtten, NDotL); specularColor = colorMatrix[1]; smoothness = colorMatrix[2].x; half3 ambient = mainColor * 0.5; half3 diffuse = colorMatrix[0]; half3 specular = GetSpecularColorGGX_Smoothness(ndotH, NDotL, ldotH, specularColor, smoothness, powFac, ggxClamp); return ambient + diffuse + specular * intensity; } inline half SGameShadowAtten(half atten) { return max(atten, 0.2); } inline half SGameStylizedAtten(half atten, half _DoubleSGameShadowAtten) { half stylizedAtten = (atten + _DoubleSGameShadowAtten) * 0.5; stylizedAtten = saturate(stylizedAtten); return stylizedAtten; } inline half SGameRoughness(half smoothness, out half perceptualRoughness ) { perceptualRoughness = PerceptualSmoothnessToPerceptualRoughness (smoothness); perceptualRoughness = max(0.001, perceptualRoughness); half roughness = PerceptualRoughnessToRoughness(perceptualRoughness); return roughness; } inline half SGameDirectSpecular(half3 normal, half3 viewDir, half NDotL, half metallic, half nh, half lh) { half3 backfaceLightDir = viewDir; half3 backfaceHalfDir = viewDir; half backface_nh = saturate(dot(normal, backfaceHalfDir)); half backface_lh = saturate(dot(backfaceLightDir, backfaceHalfDir)); //half notBackface = smoothstep(0,0.5,NDotL * 0.5 + 0.5); //0背光 -> 1受光 half notBackface = smoothstep(-1,0.5,NDotL); //0背光 -> 1受光 //nh = lerp(backface_nh, nh, notBackface); //lh = lerp(backface_lh, lh, notBackface); half isBackface = 1 - smoothstep(-1,0.5,NDotL); //half ratio = isBackface * step(0.5, metallic); half ratio = isBackface * lerp(0.3,1,metallic); nh = lerp(nh, backface_nh, ratio); lh = lerp(lh, backface_lh, ratio); return isBackface; } inline half3 SGameStylizedSpecularColor( half3 specularColor, half metallic ) { half3 linearSpecularColor = specularColor * specularColor; specularColor = lerp( linearSpecularColor, specularColor, metallic ); return specularColor; } #endif