Search Unity

Implementing customized Unity_GlossyEnvironment function in custom shader

Discussion in 'Shaders' started by vincespeed, Jun 17, 2022.

  1. vincespeed

    vincespeed

    Joined:
    Mar 8, 2014
    Posts:
    70
    Hello everyone,
    I'm trying to customize a shader in order to blend the built-in Unity_GlossyEnvironment reflections with a custom texture generated at runtime. Hope this conceptual scheme can help in understanding what I'm trying to achieve:

    I'm using as a base for this task the following thread (thanks to both of you for disclosing so much useful info):
    https://forum.unity.com/threads/shader-custom-reflections.939936/
    Basically I rewrote the "Unity_GlossyEnvironment" function in my customized shader and disabled the standard built-in Reflections (code follows). What I expected to get is a perfect replica of the standard shader with the "Reflections" check on. But what I get is a bleached version (with incorrect fresnel and lighting it seems) as shown in the image below (Left my shader, right standard shader with reflections on).


    My shader is as follows:
    Code (CSharp):
    1. Shader "Custom/NewSurfaceShader"
    2. {
    3.     Properties
    4.     {
    5.         _Color ("Color", Color) = (1,1,1,1)
    6.         _MainTex ("Albedo (RGB)", 2D) = "white" {}
    7.         _Glossiness ("Smoothness", Range(0,1)) = 0.5
    8.         _Metallic ("Metallic", Range(0,1)) = 0.0
    9.             [ToggleOff] _GlossyReflections("Glossy Reflections",Float)=1.0
    10.     }
    11.     SubShader
    12.     {
    13.         Tags { "RenderType"="Opaque" }
    14.         LOD 200
    15.  
    16.         CGPROGRAM
    17.         // Physically based Standard lighting model, and enable shadows on all light types
    18.         #pragma surface surf Standard fullforwardshadows
    19.         #pragma shader_feature_local _GLOSSYREFLECTIONS_OFF
    20.         // Use shader model 3.0 target, to get nicer looking lighting
    21.         #pragma target 3.0
    22.  
    23.         sampler2D _MainTex;
    24.  
    25.         struct Input
    26.         {
    27.             float2 uv_MainTex;
    28.             float3 viewDir;
    29.         };
    30.  
    31.         half _Glossiness;
    32.         half _Metallic;
    33.         fixed4 _Color;
    34.  
    35.         // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
    36.         // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
    37.         // #pragma instancing_options assumeuniformscaling
    38.         UNITY_INSTANCING_BUFFER_START(Props)
    39.             // put more per-instance properties here
    40.         UNITY_INSTANCING_BUFFER_END(Props)
    41.  
    42.     half3 my_GlossyEnvironment (UNITY_ARGS_TEXCUBE(tex), half4 hdr, Unity_GlossyEnvironmentData glossIn)
    43.     {
    44.     half perceptualRoughness = glossIn.roughness /* perceptualRoughness */ ;
    45.  
    46.     #if 0
    47.     float m = PerceptualRoughnessToRoughness(perceptualRoughness); // m is the real roughness parameter
    48.     const float fEps = 1.192092896e-07F;        // smallest such that 1.0+FLT_EPSILON != 1.0  (+1e-4h is NOT good here. is visibly very wrong)
    49.     float n =  (2.0/max(fEps, m*m))-2.0;        // remap to spec power. See eq. 21 in --> https://dl.dropboxusercontent.com/u/55891920/papers/mm_brdf.pdf
    50.  
    51.     n /= 4;                                     // remap from n_dot_h formulatino to n_dot_r. See section "Pre-convolved Cube Maps vs Path Tracers" --> https://s3.amazonaws.com/docs.knaldtech.com/knald/1.0.0/lys_power_drops.html
    52.  
    53.     perceptualRoughness = pow( 2/(n+2), 0.25);      // remap back to square root of real roughness (0.25 include both the sqrt root of the conversion and sqrt for going from roughness to perceptualRoughness)
    54.     #else
    55.     perceptualRoughness = perceptualRoughness*(1.7 - 0.7*perceptualRoughness);
    56.     #endif
    57.  
    58.  
    59.     half mip = perceptualRoughnessToMipmapLevel(perceptualRoughness);
    60.     half3 R = glossIn.reflUVW;
    61.     half4 rgbm = UNITY_SAMPLE_TEXCUBE_LOD(tex, R, mip);
    62.  
    63.     return DecodeHDR(rgbm, hdr);
    64.     }
    65.  
    66.  
    67.  
    68.  
    69.         void surf (Input IN, inout SurfaceOutputStandard o)
    70.         {
    71.             // Albedo comes from a texture tinted by color
    72.             fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
    73.             o.Albedo = c.rgb;
    74.             // Metallic and smoothness come from slider variables
    75.             o.Metallic = _Metallic;
    76.             o.Smoothness = _Glossiness;
    77.             o.Alpha = c.a;
    78.                half3 specColor;
    79.             half oneMinusReflectivity;
    80.          
    81.  half3 diff = DiffuseAndSpecularFromMetallic(c.rgb, _Metallic, specColor, oneMinusReflectivity);
    82.          
    83.             Unity_GlossyEnvironmentData glossIn = UnityGlossyEnvironmentSetup(_Glossiness, IN.viewDir, o.Normal, half3(0, 0, 0));
    84.             half3 env0 = my_GlossyEnvironment(UNITY_PASS_TEXCUBE(unity_SpecCube0), unity_SpecCube0_HDR, glossIn);
    85.             half surfaceReduction = 1.0 / (_Glossiness * _Glossiness + 1.0);
    86.             half grazingTerm = saturate(_Glossiness + (1 - oneMinusReflectivity));
    87.             half nv = abs(dot(o.Normal, IN.viewDir));
    88.             o.Emission = env0 * surfaceReduction * FresnelLerp(specColor, grazingTerm, nv);
    89.         }
    90.         ENDCG
    91.     }
    92.     FallBack "Diffuse"
    It would be great if anyone with more knowledge than me in shader fields could point me in the right direction =)
    Thank you to anyone who will help!
     
    Agent0023 likes this.