Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Trying to create custom standard shader with geometric specular aliasing

Discussion in 'Shaders' started by KamiKaze425, Sep 9, 2017.

  1. KamiKaze425

    KamiKaze425

    Joined:
    Nov 20, 2012
    Posts:
    207
    We're trying to create a specific shader for VR use.
    The shader should mimic Unity's standard shader except with only these 4 settings:
    1) albedo with color selector
    2) metallic with smoothness slider
    3) normal map with float value
    4) occlusion with slider

    We need the shader to interpolate the normal twice, once with the centroid and once without. Then compare them.

    Not proficient at shader programming, but 42-44 of this doc seems to have a hint
    http://media.steampowered.com/apps/valve/2015/Alex_Vlachos_Advanced_VR_Rendering_GDC2015.pdf

    Has anyone already done this or understand how to implement it?
     
    Sokuhatiku likes this.
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    The code on page 42 is related to anisotropic blinn-phong specular. Unity uses isotropic GGX, so that code doesn't really work if you want to match Unity's lighting style. The main benefit of using anisotropic specular for VR is it's use in conjunction with with specular AA, which is what the previous ~15 pages are devoted to. That requires a bit more work than just a shader change, but an entire workflow overhaul to support. Technically it doesn't even require any shader changes, just some preprocessing of the smoothness map.

    It can be done on your own if you want. Stephen Hill and Matt Pettineo have some excellent write ups and example code you can use to implement specular AA yourself. If you don't want to do it yourself the Alloy framework asset is the only asset I can think off that implements specular AA, though I don't believe it uses anisotropic GGX by default.
    https://www.assetstore.unity3d.com/en/#!/content/11978

    The technique described on page 43 is trivial to implement in a surface shader. You can almost literally copy and paste the code into the surf function and it'll work.

    Code (CSharp):
    1. // add this to your Input struct
    2. // float3 worldNormal; INTERNAL_DATA
    3.  
    4. // assign the o.Smoothness value to your content set value prior to this code
    5. // ie. o.Smoothness = metallicGloss.a * _SmoothnessScale;
    6. float3 vNormalWsDdx = ddx( IN.worldNormal.xyz );
    7. float3 vNormalWsDdy = ddy( IN.worldNormal.xyz );
    8. float flGeometricRoughnessFactor = pow( saturate( max( dot( vNormalWsDdx.xyz, vNormalWsDdx.xyz ), dot( vNormalWsDdy.xyz, vNormalWsDdy.xyz ) ) ), 0.333 );
    9. o.Smoothness= min( o.Smoothness, 1.0 - flGeometricRoughnessFactor ); // Ensure we don’t double-count roughness if normal map encodes geometric roughness
    The technique in page 44 is a bit more involved. It can't be done with a surface shader directly as there's no control over how data is passed from the vertex shader to the fragment shader. It's a huge pain to modify the standard shader directly as to implement this I think requires modifying 5-6 files. The easiest solution is to modify the generated code from a surface shader. This isn't hard, but surface shaders' generated code is super ugly to look at so it can be more of a pain than it needs to be just from trying to figure out all the places you need to touch.

    Honestly, the technique from page 43 can fix 90% of the problems on it's own. My personal experience has been if you're needing the technique from page 44, this is more a content issue than something that should be fixed in the shader since it's caused by very thin geometry with extreme normal changes.

    edit: typo, should be a min, not max, for the smoothness
     
    Last edited: Sep 12, 2017
  3. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    One other thing about centroid sampling. It's semi-broken in Unity for reasons no one has looked into.

    Below is a video showing white lines where centroid sample and the regular interpolated sample are different. It flickers constantly. This can sometimes be worse than the aliasing it's fixing.
    centroid flicker2.gif
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    Modified a surface shader to implement centroid normals and geometric roughness. Here's a comparison using only the geometric roughness:

    vr standard.png

    Notice the fingers of the hands look smoother (and slightly brighter), but the top of the hand still has some aliasing from the normal map.
    Notice the aliasing on the under side of the shoulder and arm pit is reduced, but not completely removed. Also notice the highlight on the front side of the shoulder is aliased. This is from HDR being enabled. Disabling HDR makes that look significantly better.

    Centroid sampling can be toggled on and off, but only changes one or two pixels for this model ... when it works at all. You can try enabling it to see if it helps, but I simply ignore it for now as it's not reliable. It is unfortunate since when I implemented this in a custom engine it did wonders for very thin geometry details.

    Code (CSharp):
    1. Shader "VRStandard" {
    2.     Properties {
    3.         _Color ("Color", Color) = (1,1,1,1)
    4.         _MainTex ("Albedo (RGB)", 2D) = "white" {}
    5.         _GlossMapScale("Smoothness Scale", Range(0.0, 1.0)) = 1.0
    6.         [NoScaleOffset] _MetallicGlossMap("Metallic", 2D) = "white" {}
    7.         _BumpScale("Scale", Float) = 1.0
    8.         [NoScaleOffset] _BumpMap("Normal Map", 2D) = "bump" {}
    9.         _OcclusionStrength("Strength", Range(0.0, 1.0)) = 1.0
    10.         [NoScaleOffset] _OcclusionMap("Occlusion", 2D) = "white" {}
    11.         [Toggle(_CENTROIDNORMAL)] _CentroidNormal ("Enable Vertex Normal Centroid Sampling Fixup", Float) = 0
    12.     }
    13.     SubShader {
    14.         Tags { "RenderType"="Opaque" }
    15.         LOD 200
    16.      
    17.      
    18.     // ------------------------------------------------------------
    19.     // Surface shader code generated out of a CGPROGRAM block:
    20.  
    21.  
    22.     // ---- forward rendering base pass:
    23.     Pass {
    24.         Name "FORWARD"
    25.         Tags { "LightMode" = "ForwardBase" }
    26.  
    27. CGPROGRAM
    28. // compile directives
    29. #pragma vertex vert_surf
    30. #pragma fragment frag_surf
    31. #pragma target 5.0
    32. #pragma multi_compile_instancing
    33. #pragma shader_feature _CENTROIDNORMAL
    34. #pragma multi_compile_fog
    35. #pragma multi_compile_fwdbase
    36. #include "HLSLSupport.cginc"
    37. #include "UnityShaderVariables.cginc"
    38. #include "UnityShaderUtilities.cginc"
    39. // -------- variant for: <when no other keywords are defined>
    40. #if !defined(INSTANCING_ON)
    41. // Surface shader code generated based on:
    42. // vertex modifier: 'vert'
    43. // writes to per-pixel normal: YES
    44. // writes to emission: no
    45. // writes to occlusion: YES
    46. // needs world space reflection vector: no
    47. // needs world space normal vector: YES
    48. // needs screen space position: no
    49. // needs world space position: no
    50. // needs view direction: no
    51. // needs world space view direction: no
    52. // needs world space position for lighting: YES
    53. // needs world space view direction for lighting: YES
    54. // needs world space view direction for lightmaps: no
    55. // needs vertex color: no
    56. // needs VFACE: no
    57. // passes tangent-to-world matrix to pixel shader: YES
    58. // reads from normal: no
    59. // 1 texcoords actually used
    60. //   float2 _MainTex
    61. #define UNITY_PASS_FORWARDBASE
    62. #include "UnityCG.cginc"
    63. #include "Lighting.cginc"
    64. #include "UnityPBSLighting.cginc"
    65. #include "AutoLight.cginc"
    66.  
    67. #define INTERNAL_DATA half3 internalSurfaceTtoW0; half3 internalSurfaceTtoW1; half3 internalSurfaceTtoW2;
    68. #define WorldReflectionVector(data,normal) reflect (data.worldRefl, half3(dot(data.internalSurfaceTtoW0,normal), dot(data.internalSurfaceTtoW1,normal), dot(data.internalSurfaceTtoW2,normal)))
    69. #define WorldNormalVector(data,normal) fixed3(dot(data.internalSurfaceTtoW0,normal), dot(data.internalSurfaceTtoW1,normal), dot(data.internalSurfaceTtoW2,normal))
    70.  
    71. #ifdef DUMMY_PREPROCESSOR_TO_WORK_AROUND_HLSL_COMPILER_LINE_HANDLING
    72. #endif
    73. /* UNITY: Original start of shader */
    74.         // Physically based Standard lighting model, and enable shadows on all light types
    75.         //#pragma surface surf Standard fullforwardshadows vertex:vert
    76.  
    77.         // Use shader model 3.0 target, to get nicer looking lighting
    78.         //#pragma target 5.0
    79.  
    80.         #include "UnityStandardUtils.cginc"
    81.  
    82.         sampler2D _MainTex;
    83.         sampler2D _MetallicGlossMap;
    84.         sampler2D _BumpMap;
    85.         sampler2D _OcclusionMap;
    86.  
    87.         struct Input {
    88.             float2 uv_MainTex;
    89.             float3 worldNormal; INTERNAL_DATA
    90.         };
    91.  
    92.         fixed4 _Color;
    93.         half _GlossMapScale;
    94.         half _BumpScale;
    95.         half _OcclusionStrength;
    96.  
    97.         void surf (Input IN, inout SurfaceOutputStandard o) {
    98.             fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
    99.             o.Albedo = c.rgb;
    100.  
    101.             fixed4 mg = tex2D(_MetallicGlossMap, IN.uv_MainTex);
    102.             o.Metallic = mg.r;
    103.             o.Smoothness = mg.a * _GlossMapScale;
    104.  
    105.             float3 vNormalWsDdx = ddx_fine( IN.worldNormal.xyz );
    106.             float3 vNormalWsDdy = ddy_fine( IN.worldNormal.xyz );
    107.             float flGeometricRoughnessFactor = pow( saturate( max( dot( vNormalWsDdx.xyz, vNormalWsDdx.xyz ), dot( vNormalWsDdy.xyz, vNormalWsDdy.xyz ) ) ), 0.333 );
    108.             o.Smoothness = min( o.Smoothness, 1.0 - flGeometricRoughnessFactor ); // Ensure we don’t double-count roughness if normal map encodes geometric roughness
    109.  
    110.             half occ = tex2D(_OcclusionMap, IN.uv_MainTex).g;
    111.             o.Occlusion = LerpOneTo (occ, _OcclusionStrength);
    112.  
    113.             half3 normal = UnpackScaleNormal(tex2D(_BumpMap, IN.uv_MainTex), _BumpScale);
    114.             o.Normal = normal;
    115.         }
    116.      
    117.  
    118. // vertex-to-fragment interpolation data
    119. // no lightmaps:
    120. #ifndef LIGHTMAP_ON
    121. struct v2f_surf {
    122.     float4 pos : SV_POSITION;
    123.     float2 pack0 : TEXCOORD0; // _MainTex
    124.     float4 tSpace0 : TEXCOORD1;
    125.     float4 tSpace1 : TEXCOORD2;
    126.     float4 tSpace2 : TEXCOORD3;
    127.     #if defined(_CENTROIDNORMAL)
    128.     float3 centroidNormal : TEXCOORD4_centroid;
    129.     #endif
    130.     #if UNITY_SHOULD_SAMPLE_SH
    131.     half3 sh : TEXCOORD5; // SH
    132.     #endif
    133.     UNITY_SHADOW_COORDS(6)
    134.     UNITY_FOG_COORDS(7)
    135.     #if SHADER_TARGET >= 30
    136.     float4 lmap : TEXCOORD8;
    137.     #endif
    138.     UNITY_VERTEX_INPUT_INSTANCE_ID
    139.     UNITY_VERTEX_OUTPUT_STEREO
    140. };
    141. #endif
    142. // with lightmaps:
    143. #ifdef LIGHTMAP_ON
    144. struct v2f_surf {
    145.     float4 pos : SV_POSITION;
    146.     float2 pack0 : TEXCOORD0; // _MainTex
    147.     float4 tSpace0 : TEXCOORD1;
    148.     float4 tSpace1 : TEXCOORD2;
    149.     float4 tSpace2 : TEXCOORD3;
    150.     #if defined(_CENTROIDNORMAL)
    151.     float3 centroidNormal : TEXCOORD4_centroid;
    152.     #endif
    153.     float4 lmap : TEXCOORD5;
    154.     UNITY_SHADOW_COORDS(6)
    155.     UNITY_FOG_COORDS(7)
    156.     UNITY_VERTEX_INPUT_INSTANCE_ID
    157.     UNITY_VERTEX_OUTPUT_STEREO
    158. };
    159. #endif
    160. float4 _MainTex_ST;
    161.  
    162. // vertex shader
    163. v2f_surf vert_surf (appdata_full v) {
    164.     UNITY_SETUP_INSTANCE_ID(v);
    165.     v2f_surf o;
    166.     UNITY_INITIALIZE_OUTPUT(v2f_surf,o);
    167.     UNITY_TRANSFER_INSTANCE_ID(v,o);
    168.     UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
    169.     o.pos = UnityObjectToClipPos(v.vertex);
    170.     o.pack0.xy = TRANSFORM_TEX(v.texcoord, _MainTex);
    171.     float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
    172.     float3 worldNormal = UnityObjectToWorldNormal(v.normal);
    173.     float3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
    174.     float tangentSign = v.tangent.w * unity_WorldTransformParams.w;
    175.     float3 worldBinormal = cross(worldNormal, worldTangent) * tangentSign;
    176.     o.tSpace0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
    177.     o.tSpace1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
    178.     o.tSpace2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);
    179.     #if defined(_CENTROIDNORMAL)
    180.     o.centroidNormal = worldNormal;
    181.     #endif
    182.     #ifdef DYNAMICLIGHTMAP_ON
    183.     o.lmap.zw = v.texcoord2.xy * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw;
    184.     #endif
    185.     #ifdef LIGHTMAP_ON
    186.     o.lmap.xy = v.texcoord1.xy * unity_LightmapST.xy + unity_LightmapST.zw;
    187.     #endif
    188.  
    189.     // SH/ambient and vertex lights
    190.     #ifndef LIGHTMAP_ON
    191.         #if UNITY_SHOULD_SAMPLE_SH
    192.             o.sh = 0;
    193.             // Approximated illumination from non-important point lights
    194.             #ifdef VERTEXLIGHT_ON
    195.                 o.sh += Shade4PointLights (
    196.                     unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0,
    197.                     unity_LightColor[0].rgb, unity_LightColor[1].rgb, unity_LightColor[2].rgb, unity_LightColor[3].rgb,
    198.                     unity_4LightAtten0, worldPos, worldNormal);
    199.             #endif
    200.             o.sh = ShadeSHPerVertex (worldNormal, o.sh);
    201.         #endif
    202.     #endif // !LIGHTMAP_ON
    203.  
    204.     UNITY_TRANSFER_SHADOW(o,v.texcoord1.xy); // pass shadow coordinates to pixel shader
    205.     UNITY_TRANSFER_FOG(o,o.pos); // pass fog coordinates to pixel shader
    206.     return o;
    207. }
    208.  
    209. // fragment shader
    210. fixed4 frag_surf (v2f_surf IN) : SV_Target {
    211.     UNITY_SETUP_INSTANCE_ID(IN);
    212.     // prepare and unpack data
    213.     Input surfIN;
    214.     UNITY_INITIALIZE_OUTPUT(Input,surfIN);
    215.     surfIN.uv_MainTex.x = 1.0;
    216.     surfIN.uv_MainTex = IN.pack0.xy;
    217.     float3 worldPos = float3(IN.tSpace0.w, IN.tSpace1.w, IN.tSpace2.w);
    218.     #ifndef USING_DIRECTIONAL_LIGHT
    219.         fixed3 lightDir = normalize(UnityWorldSpaceLightDir(worldPos));
    220.     #else
    221.         fixed3 lightDir = _WorldSpaceLightPos0.xyz;
    222.     #endif
    223.     fixed3 worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos));
    224.     surfIN.worldNormal = float3(IN.tSpace0.z, IN.tSpace1.z, IN.tSpace2.z);
    225.     surfIN.internalSurfaceTtoW0 = IN.tSpace0.xyz;
    226.     surfIN.internalSurfaceTtoW1 = IN.tSpace1.xyz;
    227.     surfIN.internalSurfaceTtoW2 = IN.tSpace2.xyz;
    228.     #ifdef UNITY_COMPILER_HLSL
    229.     SurfaceOutputStandard o = (SurfaceOutputStandard)0;
    230.     #else
    231.     SurfaceOutputStandard o;
    232.     #endif
    233.     o.Albedo = 0.0;
    234.     o.Emission = 0.0;
    235.     o.Alpha = 0.0;
    236.     o.Occlusion = 1.0;
    237.     fixed3 normalWorldVertex = fixed3(0,0,1);
    238.  
    239.     #if defined(_CENTROIDNORMAL)
    240.     if ( dot( surfIN.worldNormal, surfIN.worldNormal ) >= 1.01 )
    241.     {
    242.         IN.tSpace0.z = IN.centroidNormal.x;
    243.         IN.tSpace1.z = IN.centroidNormal.y;
    244.         IN.tSpace2.z = IN.centroidNormal.z;
    245.     }
    246.     #endif
    247.  
    248.     // call surface function
    249.     surf (surfIN, o);
    250.  
    251.     // compute lighting & shadowing factor
    252.     UNITY_LIGHT_ATTENUATION(atten, IN, worldPos)
    253.     fixed4 c = 0;
    254.     fixed3 worldN;
    255.     worldN.x = dot(IN.tSpace0.xyz, o.Normal);
    256.     worldN.y = dot(IN.tSpace1.xyz, o.Normal);
    257.     worldN.z = dot(IN.tSpace2.xyz, o.Normal);
    258.     o.Normal = normalize(worldN);
    259.  
    260.     // Setup lighting environment
    261.     UnityGI gi;
    262.     UNITY_INITIALIZE_OUTPUT(UnityGI, gi);
    263.     gi.indirect.diffuse = 0;
    264.     gi.indirect.specular = 0;
    265.     gi.light.color = _LightColor0.rgb;
    266.     gi.light.dir = lightDir;
    267.     // Call GI (lightmaps/SH/reflections) lighting function
    268.     UnityGIInput giInput;
    269.     UNITY_INITIALIZE_OUTPUT(UnityGIInput, giInput);
    270.     giInput.light = gi.light;
    271.     giInput.worldPos = worldPos;
    272.     giInput.worldViewDir = worldViewDir;
    273.     giInput.atten = atten;
    274.     #if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)
    275.         giInput.lightmapUV = IN.lmap;
    276.     #else
    277.         giInput.lightmapUV = 0.0;
    278.     #endif
    279.     #if UNITY_SHOULD_SAMPLE_SH
    280.         giInput.ambient = IN.sh;
    281.     #else
    282.         giInput.ambient.rgb = 0.0;
    283.     #endif
    284.     giInput.probeHDR[0] = unity_SpecCube0_HDR;
    285.     giInput.probeHDR[1] = unity_SpecCube1_HDR;
    286.     #if defined(UNITY_SPECCUBE_BLENDING) || defined(UNITY_SPECCUBE_BOX_PROJECTION)
    287.         giInput.boxMin[0] = unity_SpecCube0_BoxMin; // .w holds lerp value for blending
    288.     #endif
    289.     #ifdef UNITY_SPECCUBE_BOX_PROJECTION
    290.         giInput.boxMax[0] = unity_SpecCube0_BoxMax;
    291.         giInput.probePosition[0] = unity_SpecCube0_ProbePosition;
    292.         giInput.boxMax[1] = unity_SpecCube1_BoxMax;
    293.         giInput.boxMin[1] = unity_SpecCube1_BoxMin;
    294.         giInput.probePosition[1] = unity_SpecCube1_ProbePosition;
    295.     #endif
    296.     LightingStandard_GI(o, giInput, gi);
    297.  
    298.     // realtime lighting: call lighting function
    299.     c += LightingStandard (o, worldViewDir, gi);
    300.     UNITY_APPLY_FOG(IN.fogCoord, c); // apply fog
    301.     UNITY_OPAQUE_ALPHA(c.a);
    302.     return c;
    303. }
    304.  
    305.  
    306. #endif
    307.  
    308. // -------- variant for: INSTANCING_ON
    309. #if defined(INSTANCING_ON)
    310. // Surface shader code generated based on:
    311. // vertex modifier: 'vert'
    312. // writes to per-pixel normal: YES
    313. // writes to emission: no
    314. // writes to occlusion: YES
    315. // needs world space reflection vector: no
    316. // needs world space normal vector: YES
    317. // needs screen space position: no
    318. // needs world space position: no
    319. // needs view direction: no
    320. // needs world space view direction: no
    321. // needs world space position for lighting: YES
    322. // needs world space view direction for lighting: YES
    323. // needs world space view direction for lightmaps: no
    324. // needs vertex color: no
    325. // needs VFACE: no
    326. // passes tangent-to-world matrix to pixel shader: YES
    327. // reads from normal: no
    328. // 1 texcoords actually used
    329. //   float2 _MainTex
    330. #define UNITY_PASS_FORWARDBASE
    331. #include "UnityCG.cginc"
    332. #include "Lighting.cginc"
    333. #include "UnityPBSLighting.cginc"
    334. #include "AutoLight.cginc"
    335.  
    336. #define INTERNAL_DATA half3 internalSurfaceTtoW0; half3 internalSurfaceTtoW1; half3 internalSurfaceTtoW2;
    337. #define WorldReflectionVector(data,normal) reflect (data.worldRefl, half3(dot(data.internalSurfaceTtoW0,normal), dot(data.internalSurfaceTtoW1,normal), dot(data.internalSurfaceTtoW2,normal)))
    338. #define WorldNormalVector(data,normal) fixed3(dot(data.internalSurfaceTtoW0,normal), dot(data.internalSurfaceTtoW1,normal), dot(data.internalSurfaceTtoW2,normal))
    339.  
    340. #ifdef DUMMY_PREPROCESSOR_TO_WORK_AROUND_HLSL_COMPILER_LINE_HANDLING
    341. #endif
    342. /* UNITY: Original start of shader */
    343.         // Physically based Standard lighting model, and enable shadows on all light types
    344.         //#pragma surface surf Standard fullforwardshadows vertex:vert
    345.  
    346.         // Use shader model 3.0 target, to get nicer looking lighting
    347.         //#pragma target 5.0
    348.  
    349.         #include "UnityStandardUtils.cginc"
    350.  
    351.         sampler2D _MainTex;
    352.         sampler2D _MetallicGlossMap;
    353.         sampler2D _BumpMap;
    354.         sampler2D _OcclusionMap;
    355.  
    356.         struct Input {
    357.             float2 uv_MainTex;
    358.             float3 worldNormal; INTERNAL_DATA
    359.         };
    360.  
    361.         fixed4 _Color;
    362.         half _GlossMapScale;
    363.         half _BumpScale;
    364.         half _OcclusionStrength;
    365.  
    366.         void surf (Input IN, inout SurfaceOutputStandard o) {
    367.             fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
    368.             o.Albedo = c.rgb;
    369.  
    370.             fixed4 mg = tex2D(_MetallicGlossMap, IN.uv_MainTex);
    371.             o.Metallic = mg.r;
    372.             o.Smoothness = mg.a * _GlossMapScale;
    373.  
    374.             float3 vNormalWsDdx = ddx_fine( IN.worldNormal.xyz );
    375.             float3 vNormalWsDdy = ddy_fine( IN.worldNormal.xyz );
    376.             float flGeometricRoughnessFactor = pow( saturate( max( dot( vNormalWsDdx.xyz, vNormalWsDdx.xyz ), dot( vNormalWsDdy.xyz, vNormalWsDdy.xyz ) ) ), 0.333 );
    377.             o.Smoothness = min( o.Smoothness, 1.0 - flGeometricRoughnessFactor ); // Ensure we don’t double-count roughness if normal map encodes geometric roughness
    378.  
    379.             half occ = tex2D(_OcclusionMap, IN.uv_MainTex).g;
    380.             o.Occlusion = LerpOneTo (occ, _OcclusionStrength);
    381.  
    382.             half3 normal = UnpackScaleNormal(tex2D(_BumpMap, IN.uv_MainTex), _BumpScale);
    383.             o.Normal = normal;
    384.         }
    385.      
    386.  
    387. // vertex-to-fragment interpolation data
    388. // no lightmaps:
    389. #ifndef LIGHTMAP_ON
    390. struct v2f_surf {
    391.     float4 pos : SV_POSITION;
    392.     float2 pack0 : TEXCOORD0; // _MainTex
    393.     float4 tSpace0 : TEXCOORD1;
    394.     float4 tSpace1 : TEXCOORD2;
    395.     float4 tSpace2 : TEXCOORD3;
    396.     #if defined(_CENTROIDNORMAL)
    397.     float3 centroidNormal : TEXCOORD4_centroid;
    398.     #endif
    399.     #if UNITY_SHOULD_SAMPLE_SH
    400.     half3 sh : TEXCOORD5; // SH
    401.     #endif
    402.     UNITY_SHADOW_COORDS(6)
    403.     UNITY_FOG_COORDS(7)
    404.     #if SHADER_TARGET >= 30
    405.     float4 lmap : TEXCOORD8;
    406.     #endif
    407.     UNITY_VERTEX_INPUT_INSTANCE_ID
    408.     UNITY_VERTEX_OUTPUT_STEREO
    409. };
    410. #endif
    411. // with lightmaps:
    412. #ifdef LIGHTMAP_ON
    413. struct v2f_surf {
    414.     float4 pos : SV_POSITION;
    415.     float2 pack0 : TEXCOORD0; // _MainTex
    416.     float4 tSpace0 : TEXCOORD1;
    417.     float4 tSpace1 : TEXCOORD2;
    418.     float4 tSpace2 : TEXCOORD3;
    419.     #if defined(_CENTROIDNORMAL)
    420.     float3 centroidNormal : TEXCOORD4_centroid;
    421.     #endif
    422.     float4 lmap : TEXCOORD5;
    423.     UNITY_SHADOW_COORDS(6)
    424.     UNITY_FOG_COORDS(7)
    425.     UNITY_VERTEX_INPUT_INSTANCE_ID
    426.     UNITY_VERTEX_OUTPUT_STEREO
    427. };
    428. #endif
    429. float4 _MainTex_ST;
    430.  
    431. // vertex shader
    432. v2f_surf vert_surf (appdata_full v) {
    433.     UNITY_SETUP_INSTANCE_ID(v);
    434.     v2f_surf o;
    435.     UNITY_INITIALIZE_OUTPUT(v2f_surf,o);
    436.     UNITY_TRANSFER_INSTANCE_ID(v,o);
    437.     UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
    438.     o.pos = UnityObjectToClipPos(v.vertex);
    439.     o.pack0.xy = TRANSFORM_TEX(v.texcoord, _MainTex);
    440.     float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
    441.     float3 worldNormal = UnityObjectToWorldNormal(v.normal);
    442.     float3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
    443.     float tangentSign = v.tangent.w * unity_WorldTransformParams.w;
    444.     float3 worldBinormal = cross(worldNormal, worldTangent) * tangentSign;
    445.     o.tSpace0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
    446.     o.tSpace1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
    447.     o.tSpace2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);
    448.     #if defined(_CENTROIDNORMAL)
    449.     o.centroidNormal = worldNormal;
    450.     #endif
    451.     #ifdef DYNAMICLIGHTMAP_ON
    452.     o.lmap.zw = v.texcoord2.xy * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw;
    453.     #endif
    454.     #ifdef LIGHTMAP_ON
    455.     o.lmap.xy = v.texcoord1.xy * unity_LightmapST.xy + unity_LightmapST.zw;
    456.     #endif
    457.  
    458.     // SH/ambient and vertex lights
    459.     #ifndef LIGHTMAP_ON
    460.         #if UNITY_SHOULD_SAMPLE_SH
    461.             o.sh = 0;
    462.             // Approximated illumination from non-important point lights
    463.             #ifdef VERTEXLIGHT_ON
    464.                 o.sh += Shade4PointLights (
    465.                     unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0,
    466.                     unity_LightColor[0].rgb, unity_LightColor[1].rgb, unity_LightColor[2].rgb, unity_LightColor[3].rgb,
    467.                     unity_4LightAtten0, worldPos, worldNormal);
    468.             #endif
    469.             o.sh = ShadeSHPerVertex (worldNormal, o.sh);
    470.         #endif
    471.     #endif // !LIGHTMAP_ON
    472.  
    473.     UNITY_TRANSFER_SHADOW(o,v.texcoord1.xy); // pass shadow coordinates to pixel shader
    474.     UNITY_TRANSFER_FOG(o,o.pos); // pass fog coordinates to pixel shader
    475.     return o;
    476. }
    477.  
    478. // fragment shader
    479. fixed4 frag_surf (v2f_surf IN) : SV_Target {
    480.     UNITY_SETUP_INSTANCE_ID(IN);
    481.     // prepare and unpack data
    482.     Input surfIN;
    483.     UNITY_INITIALIZE_OUTPUT(Input,surfIN);
    484.     surfIN.uv_MainTex.x = 1.0;
    485.     surfIN.uv_MainTex = IN.pack0.xy;
    486.     float3 worldPos = float3(IN.tSpace0.w, IN.tSpace1.w, IN.tSpace2.w);
    487.     #ifndef USING_DIRECTIONAL_LIGHT
    488.         fixed3 lightDir = normalize(UnityWorldSpaceLightDir(worldPos));
    489.     #else
    490.         fixed3 lightDir = _WorldSpaceLightPos0.xyz;
    491.     #endif
    492.     fixed3 worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos));
    493.     surfIN.worldNormal = float3(IN.tSpace0.z, IN.tSpace1.z, IN.tSpace2.z);
    494.     surfIN.internalSurfaceTtoW0 = IN.tSpace0.xyz;
    495.     surfIN.internalSurfaceTtoW1 = IN.tSpace1.xyz;
    496.     surfIN.internalSurfaceTtoW2 = IN.tSpace2.xyz;
    497.     #ifdef UNITY_COMPILER_HLSL
    498.     SurfaceOutputStandard o = (SurfaceOutputStandard)0;
    499.     #else
    500.     SurfaceOutputStandard o;
    501.     #endif
    502.     o.Albedo = 0.0;
    503.     o.Emission = 0.0;
    504.     o.Alpha = 0.0;
    505.     o.Occlusion = 1.0;
    506.     fixed3 normalWorldVertex = fixed3(0,0,1);
    507.  
    508.     #if defined(_CENTROIDNORMAL)
    509.     if ( dot( surfIN.worldNormal, surfIN.worldNormal ) >= 1.01 )
    510.     {
    511.         IN.tSpace0.z = IN.centroidNormal.x;
    512.         IN.tSpace1.z = IN.centroidNormal.y;
    513.         IN.tSpace2.z = IN.centroidNormal.z;
    514.     }
    515.     #endif
    516.  
    517.     // call surface function
    518.     surf (surfIN, o);
    519.  
    520.     // compute lighting & shadowing factor
    521.     UNITY_LIGHT_ATTENUATION(atten, IN, worldPos)
    522.     fixed4 c = 0;
    523.     fixed3 worldN;
    524.     worldN.x = dot(IN.tSpace0.xyz, o.Normal);
    525.     worldN.y = dot(IN.tSpace1.xyz, o.Normal);
    526.     worldN.z = dot(IN.tSpace2.xyz, o.Normal);
    527.     o.Normal = normalize(worldN);
    528.  
    529.     // Setup lighting environment
    530.     UnityGI gi;
    531.     UNITY_INITIALIZE_OUTPUT(UnityGI, gi);
    532.     gi.indirect.diffuse = 0;
    533.     gi.indirect.specular = 0;
    534.     gi.light.color = _LightColor0.rgb;
    535.     gi.light.dir = lightDir;
    536.     // Call GI (lightmaps/SH/reflections) lighting function
    537.     UnityGIInput giInput;
    538.     UNITY_INITIALIZE_OUTPUT(UnityGIInput, giInput);
    539.     giInput.light = gi.light;
    540.     giInput.worldPos = worldPos;
    541.     giInput.worldViewDir = worldViewDir;
    542.     giInput.atten = atten;
    543.     #if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)
    544.         giInput.lightmapUV = IN.lmap;
    545.     #else
    546.         giInput.lightmapUV = 0.0;
    547.     #endif
    548.     #if UNITY_SHOULD_SAMPLE_SH
    549.         giInput.ambient = IN.sh;
    550.     #else
    551.         giInput.ambient.rgb = 0.0;
    552.     #endif
    553.     giInput.probeHDR[0] = unity_SpecCube0_HDR;
    554.     giInput.probeHDR[1] = unity_SpecCube1_HDR;
    555.     #if defined(UNITY_SPECCUBE_BLENDING) || defined(UNITY_SPECCUBE_BOX_PROJECTION)
    556.         giInput.boxMin[0] = unity_SpecCube0_BoxMin; // .w holds lerp value for blending
    557.     #endif
    558.     #ifdef UNITY_SPECCUBE_BOX_PROJECTION
    559.         giInput.boxMax[0] = unity_SpecCube0_BoxMax;
    560.         giInput.probePosition[0] = unity_SpecCube0_ProbePosition;
    561.         giInput.boxMax[1] = unity_SpecCube1_BoxMax;
    562.         giInput.boxMin[1] = unity_SpecCube1_BoxMin;
    563.         giInput.probePosition[1] = unity_SpecCube1_ProbePosition;
    564.     #endif
    565.     LightingStandard_GI(o, giInput, gi);
    566.  
    567.     // realtime lighting: call lighting function
    568.     c += LightingStandard (o, worldViewDir, gi);
    569.     UNITY_APPLY_FOG(IN.fogCoord, c); // apply fog
    570.     UNITY_OPAQUE_ALPHA(c.a);
    571.     return c;
    572. }
    573.  
    574.  
    575. #endif
    576.  
    577.  
    578. ENDCG
    579.  
    580. }
    581.  
    582.     // ---- forward rendering additive lights pass:
    583.     Pass {
    584.         Name "FORWARD"
    585.         Tags { "LightMode" = "ForwardAdd" }
    586.         ZWrite Off Blend One One
    587.  
    588. CGPROGRAM
    589. // compile directives
    590. #pragma vertex vert_surf
    591. #pragma fragment frag_surf
    592. #pragma target 5.0
    593. #pragma multi_compile_instancing
    594. #pragma shader_feature _CENTROIDNORMAL
    595. #pragma multi_compile_fog
    596. #pragma skip_variants INSTANCING_ON
    597. #pragma multi_compile_fwdadd_fullshadows
    598. #include "HLSLSupport.cginc"
    599. #include "UnityShaderVariables.cginc"
    600. #include "UnityShaderUtilities.cginc"
    601. // -------- variant for: <when no other keywords are defined>
    602. #if !defined(INSTANCING_ON)
    603. // Surface shader code generated based on:
    604. // vertex modifier: 'vert'
    605. // writes to per-pixel normal: YES
    606. // writes to emission: no
    607. // writes to occlusion: YES
    608. // needs world space reflection vector: no
    609. // needs world space normal vector: YES
    610. // needs screen space position: no
    611. // needs world space position: no
    612. // needs view direction: no
    613. // needs world space view direction: no
    614. // needs world space position for lighting: YES
    615. // needs world space view direction for lighting: YES
    616. // needs world space view direction for lightmaps: no
    617. // needs vertex color: no
    618. // needs VFACE: no
    619. // passes tangent-to-world matrix to pixel shader: YES
    620. // reads from normal: no
    621. // 1 texcoords actually used
    622. //   float2 _MainTex
    623. #define UNITY_PASS_FORWARDADD
    624. #include "UnityCG.cginc"
    625. #include "Lighting.cginc"
    626. #include "UnityPBSLighting.cginc"
    627. #include "AutoLight.cginc"
    628.  
    629. #define INTERNAL_DATA half3 internalSurfaceTtoW0; half3 internalSurfaceTtoW1; half3 internalSurfaceTtoW2;
    630. #define WorldReflectionVector(data,normal) reflect (data.worldRefl, half3(dot(data.internalSurfaceTtoW0,normal), dot(data.internalSurfaceTtoW1,normal), dot(data.internalSurfaceTtoW2,normal)))
    631. #define WorldNormalVector(data,normal) fixed3(dot(data.internalSurfaceTtoW0,normal), dot(data.internalSurfaceTtoW1,normal), dot(data.internalSurfaceTtoW2,normal))
    632.  
    633. #ifdef DUMMY_PREPROCESSOR_TO_WORK_AROUND_HLSL_COMPILER_LINE_HANDLING
    634. #endif
    635. /* UNITY: Original start of shader */
    636.         // Physically based Standard lighting model, and enable shadows on all light types
    637.         //#pragma surface surf Standard fullforwardshadows vertex:vert
    638.  
    639.         // Use shader model 3.0 target, to get nicer looking lighting
    640.         //#pragma target 5.0
    641.  
    642.         #include "UnityStandardUtils.cginc"
    643.  
    644.         sampler2D _MainTex;
    645.         sampler2D _MetallicGlossMap;
    646.         sampler2D _BumpMap;
    647.         sampler2D _OcclusionMap;
    648.  
    649.         struct Input {
    650.             float2 uv_MainTex;
    651.             float3 worldNormal; INTERNAL_DATA
    652.         };
    653.  
    654.         fixed4 _Color;
    655.         half _GlossMapScale;
    656.         half _BumpScale;
    657.         half _OcclusionStrength;
    658.  
    659.         void surf (Input IN, inout SurfaceOutputStandard o) {
    660.             fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
    661.             o.Albedo = c.rgb;
    662.  
    663.             fixed4 mg = tex2D(_MetallicGlossMap, IN.uv_MainTex);
    664.             o.Metallic = mg.r;
    665.             o.Smoothness = mg.a * _GlossMapScale;
    666.  
    667.             float3 vNormalWsDdx = ddx_fine( IN.worldNormal.xyz );
    668.             float3 vNormalWsDdy = ddy_fine( IN.worldNormal.xyz );
    669.             float flGeometricRoughnessFactor = pow( saturate( max( dot( vNormalWsDdx.xyz, vNormalWsDdx.xyz ), dot( vNormalWsDdy.xyz, vNormalWsDdy.xyz ) ) ), 0.333 );
    670.             o.Smoothness = min( o.Smoothness, 1.0 - flGeometricRoughnessFactor ); // Ensure we don’t double-count roughness if normal map encodes geometric roughness
    671.  
    672.             half occ = tex2D(_OcclusionMap, IN.uv_MainTex).g;
    673.             o.Occlusion = LerpOneTo (occ, _OcclusionStrength);
    674.  
    675.             half3 normal = UnpackScaleNormal(tex2D(_BumpMap, IN.uv_MainTex), _BumpScale);
    676.             o.Normal = normal;
    677.         }
    678.      
    679.  
    680. // vertex-to-fragment interpolation data
    681. struct v2f_surf {
    682.     float4 pos : SV_POSITION;
    683.     float2 pack0 : TEXCOORD0; // _MainTex
    684.     fixed3 tSpace0 : TEXCOORD1;
    685.     fixed3 tSpace1 : TEXCOORD2;
    686.     fixed3 tSpace2 : TEXCOORD3;
    687.     float3 worldPos : TEXCOORD4;
    688.     float3 centroidNormal : TEXCOORD5; // centroidNormal
    689.     UNITY_SHADOW_COORDS(6)
    690.     UNITY_FOG_COORDS(7)
    691.     UNITY_VERTEX_INPUT_INSTANCE_ID
    692.     UNITY_VERTEX_OUTPUT_STEREO
    693. };
    694. float4 _MainTex_ST;
    695.  
    696. // vertex shader
    697. v2f_surf vert_surf (appdata_full v) {
    698.     UNITY_SETUP_INSTANCE_ID(v);
    699.     v2f_surf o;
    700.     UNITY_INITIALIZE_OUTPUT(v2f_surf,o);
    701.     UNITY_TRANSFER_INSTANCE_ID(v,o);
    702.     UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
    703.     o.pos = UnityObjectToClipPos(v.vertex);
    704.     o.pack0.xy = TRANSFORM_TEX(v.texcoord, _MainTex);
    705.     float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
    706.     float3 worldNormal = UnityObjectToWorldNormal(v.normal);
    707.     float3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
    708.     float tangentSign = v.tangent.w * unity_WorldTransformParams.w;
    709.     float3 worldBinormal = cross(worldNormal, worldTangent) * tangentSign;
    710.     o.tSpace0 = fixed3(worldTangent.x, worldBinormal.x, worldNormal.x);
    711.     o.tSpace1 = fixed3(worldTangent.y, worldBinormal.y, worldNormal.y);
    712.     o.tSpace2 = fixed3(worldTangent.z, worldBinormal.z, worldNormal.z);
    713.     #if defined(_CENTROIDNORMAL)
    714.     o.centroidNormal = worldNormal;
    715.     #endif
    716.     o.worldPos = worldPos;
    717.  
    718.     UNITY_TRANSFER_SHADOW(o,v.texcoord1.xy); // pass shadow coordinates to pixel shader
    719.     UNITY_TRANSFER_FOG(o,o.pos); // pass fog coordinates to pixel shader
    720.     return o;
    721. }
    722.  
    723. // fragment shader
    724. fixed4 frag_surf (v2f_surf IN) : SV_Target {
    725.     UNITY_SETUP_INSTANCE_ID(IN);
    726.     // prepare and unpack data
    727.     Input surfIN;
    728.     UNITY_INITIALIZE_OUTPUT(Input,surfIN);
    729.     surfIN.uv_MainTex.x = 1.0;
    730.     surfIN.uv_MainTex = IN.pack0.xy;
    731.     float3 worldPos = IN.worldPos;
    732.     #ifndef USING_DIRECTIONAL_LIGHT
    733.         fixed3 lightDir = normalize(UnityWorldSpaceLightDir(worldPos));
    734.     #else
    735.         fixed3 lightDir = _WorldSpaceLightPos0.xyz;
    736.     #endif
    737.     fixed3 worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos));
    738.     surfIN.worldNormal = float3(IN.tSpace0.z, IN.tSpace1.z, IN.tSpace2.z);
    739.     surfIN.internalSurfaceTtoW0 = IN.tSpace0.xyz;
    740.     surfIN.internalSurfaceTtoW1 = IN.tSpace1.xyz;
    741.     surfIN.internalSurfaceTtoW2 = IN.tSpace2.xyz;
    742.     #ifdef UNITY_COMPILER_HLSL
    743.     SurfaceOutputStandard o = (SurfaceOutputStandard)0;
    744.     #else
    745.     SurfaceOutputStandard o;
    746.     #endif
    747.     o.Albedo = 0.0;
    748.     o.Emission = 0.0;
    749.     o.Alpha = 0.0;
    750.     o.Occlusion = 1.0;
    751.     fixed3 normalWorldVertex = fixed3(0,0,1);
    752.  
    753.     #if defined(_CENTROIDNORMAL)
    754.     if ( dot( surfIN.worldNormal, surfIN.worldNormal ) >= 1.01 )
    755.     {
    756.         IN.tSpace0.z = IN.centroidNormal.x;
    757.         IN.tSpace1.z = IN.centroidNormal.y;
    758.         IN.tSpace2.z = IN.centroidNormal.z;
    759.     }
    760.     #endif
    761.  
    762.     // call surface function
    763.     surf (surfIN, o);
    764.     UNITY_LIGHT_ATTENUATION(atten, IN, worldPos)
    765.     fixed4 c = 0;
    766.     fixed3 worldN;
    767.     worldN.x = dot(IN.tSpace0.xyz, o.Normal);
    768.     worldN.y = dot(IN.tSpace1.xyz, o.Normal);
    769.     worldN.z = dot(IN.tSpace2.xyz, o.Normal);
    770.     o.Normal = normalize(worldN);
    771.  
    772.     // Setup lighting environment
    773.     UnityGI gi;
    774.     UNITY_INITIALIZE_OUTPUT(UnityGI, gi);
    775.     gi.indirect.diffuse = 0;
    776.     gi.indirect.specular = 0;
    777.     gi.light.color = _LightColor0.rgb;
    778.     gi.light.dir = lightDir;
    779.     gi.light.color *= atten;
    780.     c += LightingStandard (o, worldViewDir, gi);
    781.     c.a = 0.0;
    782.     UNITY_APPLY_FOG(IN.fogCoord, c); // apply fog
    783.     UNITY_OPAQUE_ALPHA(c.a);
    784.     return c;
    785. }
    786.  
    787.  
    788. #endif
    789.  
    790.  
    791. ENDCG
    792.  
    793. }
    794.  
    795.     // ---- deferred shading pass:
    796.     Pass {
    797.         Name "DEFERRED"
    798.         Tags { "LightMode" = "Deferred" }
    799.  
    800. CGPROGRAM
    801. // compile directives
    802. #pragma vertex vert_surf
    803. #pragma fragment frag_surf
    804. #pragma target 5.0
    805. #pragma multi_compile_instancing
    806. #pragma shader_feature _CENTROIDNORMAL
    807. #pragma exclude_renderers nomrt
    808. #pragma skip_variants FOG_LINEAR FOG_EXP FOG_EXP2
    809. #pragma multi_compile_prepassfinal
    810. #include "HLSLSupport.cginc"
    811. #include "UnityShaderVariables.cginc"
    812. #include "UnityShaderUtilities.cginc"
    813. // -------- variant for: <when no other keywords are defined>
    814. #if !defined(INSTANCING_ON)
    815. // Surface shader code generated based on:
    816. // vertex modifier: 'vert'
    817. // writes to per-pixel normal: YES
    818. // writes to emission: no
    819. // writes to occlusion: YES
    820. // needs world space reflection vector: no
    821. // needs world space normal vector: YES
    822. // needs screen space position: no
    823. // needs world space position: no
    824. // needs view direction: no
    825. // needs world space view direction: no
    826. // needs world space position for lighting: YES
    827. // needs world space view direction for lighting: YES
    828. // needs world space view direction for lightmaps: no
    829. // needs vertex color: no
    830. // needs VFACE: no
    831. // passes tangent-to-world matrix to pixel shader: YES
    832. // reads from normal: no
    833. // 1 texcoords actually used
    834. //   float2 _MainTex
    835. #define UNITY_PASS_DEFERRED
    836. #include "UnityCG.cginc"
    837. #include "Lighting.cginc"
    838. #include "UnityPBSLighting.cginc"
    839.  
    840. #define INTERNAL_DATA half3 internalSurfaceTtoW0; half3 internalSurfaceTtoW1; half3 internalSurfaceTtoW2;
    841. #define WorldReflectionVector(data,normal) reflect (data.worldRefl, half3(dot(data.internalSurfaceTtoW0,normal), dot(data.internalSurfaceTtoW1,normal), dot(data.internalSurfaceTtoW2,normal)))
    842. #define WorldNormalVector(data,normal) fixed3(dot(data.internalSurfaceTtoW0,normal), dot(data.internalSurfaceTtoW1,normal), dot(data.internalSurfaceTtoW2,normal))
    843.  
    844. #ifdef DUMMY_PREPROCESSOR_TO_WORK_AROUND_HLSL_COMPILER_LINE_HANDLING
    845. #endif
    846. /* UNITY: Original start of shader */
    847.         // Physically based Standard lighting model, and enable shadows on all light types
    848.         //#pragma surface surf Standard fullforwardshadows vertex:vert
    849.  
    850.         // Use shader model 3.0 target, to get nicer looking lighting
    851.         //#pragma target 5.0
    852.  
    853.         #include "UnityStandardUtils.cginc"
    854.  
    855.         sampler2D _MainTex;
    856.         sampler2D _MetallicGlossMap;
    857.         sampler2D _BumpMap;
    858.         sampler2D _OcclusionMap;
    859.  
    860.         struct Input {
    861.             float2 uv_MainTex;
    862.             float3 worldNormal; INTERNAL_DATA
    863.         };
    864.  
    865.         fixed4 _Color;
    866.         half _GlossMapScale;
    867.         half _BumpScale;
    868.         half _OcclusionStrength;
    869.  
    870.         void surf (Input IN, inout SurfaceOutputStandard o) {
    871.             fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
    872.             o.Albedo = c.rgb;
    873.  
    874.             fixed4 mg = tex2D(_MetallicGlossMap, IN.uv_MainTex);
    875.             o.Metallic = mg.r;
    876.             o.Smoothness = mg.a * _GlossMapScale;
    877.  
    878.             float3 vNormalWsDdx = ddx_fine( IN.worldNormal.xyz );
    879.             float3 vNormalWsDdy = ddy_fine( IN.worldNormal.xyz );
    880.             float flGeometricRoughnessFactor = pow( saturate( max( dot( vNormalWsDdx.xyz, vNormalWsDdx.xyz ), dot( vNormalWsDdy.xyz, vNormalWsDdy.xyz ) ) ), 0.333 );
    881.             o.Smoothness = min( o.Smoothness, 1.0 - flGeometricRoughnessFactor ); // Ensure we don’t double-count roughness if normal map encodes geometric roughness
    882.  
    883.             half occ = tex2D(_OcclusionMap, IN.uv_MainTex).g;
    884.             o.Occlusion = LerpOneTo (occ, _OcclusionStrength);
    885.  
    886.             half3 normal = UnpackScaleNormal(tex2D(_BumpMap, IN.uv_MainTex), _BumpScale);
    887.             o.Normal = normal;
    888.         }
    889.      
    890.  
    891. // vertex-to-fragment interpolation data
    892. struct v2f_surf {
    893.     float4 pos : SV_POSITION;
    894.     float2 pack0 : TEXCOORD0; // _MainTex
    895.     float4 tSpace0 : TEXCOORD1;
    896.     float4 tSpace1 : TEXCOORD2;
    897.     float4 tSpace2 : TEXCOORD3;
    898.     #if defined(_CENTROIDNORMAL)
    899.     float3 centroidNormal : TEXCOORD4_centroid;
    900.     #endif
    901. #ifndef DIRLIGHTMAP_OFF
    902.     half3 viewDir : TEXCOORD5;
    903. #endif
    904.     float4 lmap : TEXCOORD6;
    905. #ifndef LIGHTMAP_ON
    906.     #if UNITY_SHOULD_SAMPLE_SH
    907.         half3 sh : TEXCOORD7; // SH
    908.     #endif
    909. #else
    910.     #ifdef DIRLIGHTMAP_OFF
    911.         float4 lmapFadePos : TEXCOORD7;
    912.     #endif
    913. #endif
    914.     UNITY_VERTEX_INPUT_INSTANCE_ID
    915.     UNITY_VERTEX_OUTPUT_STEREO
    916. };
    917. float4 _MainTex_ST;
    918.  
    919. // vertex shader
    920. v2f_surf vert_surf (appdata_full v) {
    921.     UNITY_SETUP_INSTANCE_ID(v);
    922.     v2f_surf o;
    923.     UNITY_INITIALIZE_OUTPUT(v2f_surf,o);
    924.     UNITY_TRANSFER_INSTANCE_ID(v,o);
    925.     UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
    926.     o.pos = UnityObjectToClipPos(v.vertex);
    927.     o.pack0.xy = TRANSFORM_TEX(v.texcoord, _MainTex);
    928.     float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
    929.     float3 worldNormal = UnityObjectToWorldNormal(v.normal);
    930.     float3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
    931.     float tangentSign = v.tangent.w * unity_WorldTransformParams.w;
    932.     float3 worldBinormal = cross(worldNormal, worldTangent) * tangentSign;
    933.     o.tSpace0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
    934.     o.tSpace1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
    935.     o.tSpace2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);
    936.     #if defined(_CENTROIDNORMAL)
    937.     o.centroidNormal = worldNormal;
    938.     #endif
    939.     float3 viewDirForLight = UnityWorldSpaceViewDir(worldPos);
    940.     #ifndef DIRLIGHTMAP_OFF
    941.     o.viewDir.x = dot(viewDirForLight, worldTangent);
    942.     o.viewDir.y = dot(viewDirForLight, worldBinormal);
    943.     o.viewDir.z = dot(viewDirForLight, worldNormal);
    944.     #endif
    945. #ifdef DYNAMICLIGHTMAP_ON
    946.     o.lmap.zw = v.texcoord2.xy * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw;
    947. #else
    948.     o.lmap.zw = 0;
    949. #endif
    950. #ifdef LIGHTMAP_ON
    951.     o.lmap.xy = v.texcoord1.xy * unity_LightmapST.xy + unity_LightmapST.zw;
    952.     #ifdef DIRLIGHTMAP_OFF
    953.         o.lmapFadePos.xyz = (mul(unity_ObjectToWorld, v.vertex).xyz - unity_ShadowFadeCenterAndType.xyz) * unity_ShadowFadeCenterAndType.w;
    954.         o.lmapFadePos.w = (-UnityObjectToViewPos(v.vertex).z) * (1.0 - unity_ShadowFadeCenterAndType.w);
    955.     #endif
    956. #else
    957.     o.lmap.xy = 0;
    958.         #if UNITY_SHOULD_SAMPLE_SH
    959.             o.sh = 0;
    960.             o.sh = ShadeSHPerVertex (worldNormal, o.sh);
    961.         #endif
    962. #endif
    963.     return o;
    964. }
    965. #ifdef LIGHTMAP_ON
    966. float4 unity_LightmapFade;
    967. #endif
    968. fixed4 unity_Ambient;
    969.  
    970. // fragment shader
    971. void frag_surf (v2f_surf IN,
    972.         out half4 outGBuffer0 : SV_Target0,
    973.         out half4 outGBuffer1 : SV_Target1,
    974.         out half4 outGBuffer2 : SV_Target2,
    975.         out half4 outEmission : SV_Target3
    976. #if defined(SHADOWS_SHADOWMASK) && (UNITY_ALLOWED_MRT_COUNT > 4)
    977.         , out half4 outShadowMask : SV_Target4
    978. #endif
    979. ) {
    980.     UNITY_SETUP_INSTANCE_ID(IN);
    981.     // prepare and unpack data
    982.     Input surfIN;
    983.     UNITY_INITIALIZE_OUTPUT(Input,surfIN);
    984.     surfIN.uv_MainTex.x = 1.0;
    985.     surfIN.uv_MainTex = IN.pack0.xy;
    986.     float3 worldPos = float3(IN.tSpace0.w, IN.tSpace1.w, IN.tSpace2.w);
    987.     #ifndef USING_DIRECTIONAL_LIGHT
    988.         fixed3 lightDir = normalize(UnityWorldSpaceLightDir(worldPos));
    989.     #else
    990.         fixed3 lightDir = _WorldSpaceLightPos0.xyz;
    991.     #endif
    992.     fixed3 worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos));
    993.     surfIN.worldNormal = float3(IN.tSpace0.z, IN.tSpace1.z, IN.tSpace2.z);
    994.     surfIN.internalSurfaceTtoW0 = IN.tSpace0.xyz;
    995.     surfIN.internalSurfaceTtoW1 = IN.tSpace1.xyz;
    996.     surfIN.internalSurfaceTtoW2 = IN.tSpace2.xyz;
    997.     #ifdef UNITY_COMPILER_HLSL
    998.     SurfaceOutputStandard o = (SurfaceOutputStandard)0;
    999.     #else
    1000.     SurfaceOutputStandard o;
    1001.     #endif
    1002.     o.Albedo = 0.0;
    1003.     o.Emission = 0.0;
    1004.     o.Alpha = 0.0;
    1005.     o.Occlusion = 1.0;
    1006.     fixed3 normalWorldVertex = fixed3(0,0,1);
    1007.  
    1008.     // call surface function
    1009.     surf (surfIN, o);
    1010. fixed3 originalNormal = o.Normal;
    1011.     fixed3 worldN;
    1012.     worldN.x = dot(IN.tSpace0.xyz, o.Normal);
    1013.     worldN.y = dot(IN.tSpace1.xyz, o.Normal);
    1014.     worldN.z = dot(IN.tSpace2.xyz, o.Normal);
    1015.     o.Normal = normalize(worldN);
    1016.     half atten = 1;
    1017.  
    1018.     // Setup lighting environment
    1019.     UnityGI gi;
    1020.     UNITY_INITIALIZE_OUTPUT(UnityGI, gi);
    1021.     gi.indirect.diffuse = 0;
    1022.     gi.indirect.specular = 0;
    1023.     gi.light.color = 0;
    1024.     gi.light.dir = half3(0,1,0);
    1025.     // Call GI (lightmaps/SH/reflections) lighting function
    1026.     UnityGIInput giInput;
    1027.     UNITY_INITIALIZE_OUTPUT(UnityGIInput, giInput);
    1028.     giInput.light = gi.light;
    1029.     giInput.worldPos = worldPos;
    1030.     giInput.worldViewDir = worldViewDir;
    1031.     giInput.atten = atten;
    1032.     #if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)
    1033.         giInput.lightmapUV = IN.lmap;
    1034.     #else
    1035.         giInput.lightmapUV = 0.0;
    1036.     #endif
    1037.     #if UNITY_SHOULD_SAMPLE_SH
    1038.         giInput.ambient = IN.sh;
    1039.     #else
    1040.         giInput.ambient.rgb = 0.0;
    1041.     #endif
    1042.     giInput.probeHDR[0] = unity_SpecCube0_HDR;
    1043.     giInput.probeHDR[1] = unity_SpecCube1_HDR;
    1044.     #if defined(UNITY_SPECCUBE_BLENDING) || defined(UNITY_SPECCUBE_BOX_PROJECTION)
    1045.         giInput.boxMin[0] = unity_SpecCube0_BoxMin; // .w holds lerp value for blending
    1046.     #endif
    1047.     #ifdef UNITY_SPECCUBE_BOX_PROJECTION
    1048.         giInput.boxMax[0] = unity_SpecCube0_BoxMax;
    1049.         giInput.probePosition[0] = unity_SpecCube0_ProbePosition;
    1050.         giInput.boxMax[1] = unity_SpecCube1_BoxMax;
    1051.         giInput.boxMin[1] = unity_SpecCube1_BoxMin;
    1052.         giInput.probePosition[1] = unity_SpecCube1_ProbePosition;
    1053.     #endif
    1054.     LightingStandard_GI(o, giInput, gi);
    1055.  
    1056.     // call lighting function to output g-buffer
    1057.     outEmission = LightingStandard_Deferred (o, worldViewDir, gi, outGBuffer0, outGBuffer1, outGBuffer2);
    1058.     #if defined(SHADOWS_SHADOWMASK) && (UNITY_ALLOWED_MRT_COUNT > 4)
    1059.         outShadowMask = UnityGetRawBakedOcclusions (IN.lmap.xy, float3(0, 0, 0));
    1060.     #endif
    1061.     #ifndef UNITY_HDR_ON
    1062.     outEmission.rgb = exp2(-outEmission.rgb);
    1063.     #endif
    1064. }
    1065.  
    1066.  
    1067. #endif
    1068.  
    1069. // -------- variant for: INSTANCING_ON
    1070. #if defined(INSTANCING_ON)
    1071. // Surface shader code generated based on:
    1072. // vertex modifier: 'vert'
    1073. // writes to per-pixel normal: YES
    1074. // writes to emission: no
    1075. // writes to occlusion: YES
    1076. // needs world space reflection vector: no
    1077. // needs world space normal vector: YES
    1078. // needs screen space position: no
    1079. // needs world space position: no
    1080. // needs view direction: no
    1081. // needs world space view direction: no
    1082. // needs world space position for lighting: YES
    1083. // needs world space view direction for lighting: YES
    1084. // needs world space view direction for lightmaps: no
    1085. // needs vertex color: no
    1086. // needs VFACE: no
    1087. // passes tangent-to-world matrix to pixel shader: YES
    1088. // reads from normal: no
    1089. // 1 texcoords actually used
    1090. //   float2 _MainTex
    1091. #define UNITY_PASS_DEFERRED
    1092. #include "UnityCG.cginc"
    1093. #include "Lighting.cginc"
    1094. #include "UnityPBSLighting.cginc"
    1095.  
    1096. #define INTERNAL_DATA half3 internalSurfaceTtoW0; half3 internalSurfaceTtoW1; half3 internalSurfaceTtoW2;
    1097. #define WorldReflectionVector(data,normal) reflect (data.worldRefl, half3(dot(data.internalSurfaceTtoW0,normal), dot(data.internalSurfaceTtoW1,normal), dot(data.internalSurfaceTtoW2,normal)))
    1098. #define WorldNormalVector(data,normal) fixed3(dot(data.internalSurfaceTtoW0,normal), dot(data.internalSurfaceTtoW1,normal), dot(data.internalSurfaceTtoW2,normal))
    1099.  
    1100. #ifdef DUMMY_PREPROCESSOR_TO_WORK_AROUND_HLSL_COMPILER_LINE_HANDLING
    1101. #endif
    1102. /* UNITY: Original start of shader */
    1103.         // Physically based Standard lighting model, and enable shadows on all light types
    1104.         //#pragma surface surf Standard fullforwardshadows vertex:vert
    1105.  
    1106.         // Use shader model 3.0 target, to get nicer looking lighting
    1107.         //#pragma target 5.0
    1108.  
    1109.         #include "UnityStandardUtils.cginc"
    1110.  
    1111.         sampler2D _MainTex;
    1112.         sampler2D _MetallicGlossMap;
    1113.         sampler2D _BumpMap;
    1114.         sampler2D _OcclusionMap;
    1115.  
    1116.         struct Input {
    1117.             float2 uv_MainTex;
    1118.             float3 worldNormal; INTERNAL_DATA
    1119.         };
    1120.  
    1121.         fixed4 _Color;
    1122.         half _GlossMapScale;
    1123.         half _BumpScale;
    1124.         half _OcclusionStrength;
    1125.  
    1126.         void surf (Input IN, inout SurfaceOutputStandard o) {
    1127.             fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
    1128.             o.Albedo = c.rgb;
    1129.  
    1130.             fixed4 mg = tex2D(_MetallicGlossMap, IN.uv_MainTex);
    1131.             o.Metallic = mg.r;
    1132.             o.Smoothness = mg.a * _GlossMapScale;
    1133.  
    1134.             float3 vNormalWsDdx = ddx_fine( IN.worldNormal.xyz );
    1135.             float3 vNormalWsDdy = ddy_fine( IN.worldNormal.xyz );
    1136.             float flGeometricRoughnessFactor = pow( saturate( max( dot( vNormalWsDdx.xyz, vNormalWsDdx.xyz ), dot( vNormalWsDdy.xyz, vNormalWsDdy.xyz ) ) ), 0.333 );
    1137.             o.Smoothness = min( o.Smoothness, 1.0 - flGeometricRoughnessFactor ); // Ensure we don’t double-count roughness if normal map encodes geometric roughness
    1138.  
    1139.             half occ = tex2D(_OcclusionMap, IN.uv_MainTex).g;
    1140.             o.Occlusion = LerpOneTo (occ, _OcclusionStrength);
    1141.  
    1142.             half3 normal = UnpackScaleNormal(tex2D(_BumpMap, IN.uv_MainTex), _BumpScale);
    1143.             o.Normal = normal;
    1144.         }
    1145.      
    1146.  
    1147. // vertex-to-fragment interpolation data
    1148. struct v2f_surf {
    1149.     float4 pos : SV_POSITION;
    1150.     float2 pack0 : TEXCOORD0; // _MainTex
    1151.     float4 tSpace0 : TEXCOORD1;
    1152.     float4 tSpace1 : TEXCOORD2;
    1153.     float4 tSpace2 : TEXCOORD3;
    1154.     #if defined(_CENTROIDNORMAL)
    1155.     float3 centroidNormal : TEXCOORD4_centroid;
    1156.     #endif
    1157. #ifndef DIRLIGHTMAP_OFF
    1158.     half3 viewDir : TEXCOORD5;
    1159. #endif
    1160.     float4 lmap : TEXCOORD6;
    1161. #ifndef LIGHTMAP_ON
    1162.     #if UNITY_SHOULD_SAMPLE_SH
    1163.         half3 sh : TEXCOORD7; // SH
    1164.     #endif
    1165. #else
    1166.     #ifdef DIRLIGHTMAP_OFF
    1167.         float4 lmapFadePos : TEXCOORD7;
    1168.     #endif
    1169. #endif
    1170.     UNITY_VERTEX_INPUT_INSTANCE_ID
    1171.     UNITY_VERTEX_OUTPUT_STEREO
    1172. };
    1173. float4 _MainTex_ST;
    1174.  
    1175. // vertex shader
    1176. v2f_surf vert_surf (appdata_full v) {
    1177.     UNITY_SETUP_INSTANCE_ID(v);
    1178.     v2f_surf o;
    1179.     UNITY_INITIALIZE_OUTPUT(v2f_surf,o);
    1180.     UNITY_TRANSFER_INSTANCE_ID(v,o);
    1181.     UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
    1182.     o.pos = UnityObjectToClipPos(v.vertex);
    1183.     o.pack0.xy = TRANSFORM_TEX(v.texcoord, _MainTex);
    1184.     float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
    1185.     float3 worldNormal = UnityObjectToWorldNormal(v.normal);
    1186.     float3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
    1187.     float tangentSign = v.tangent.w * unity_WorldTransformParams.w;
    1188.     float3 worldBinormal = cross(worldNormal, worldTangent) * tangentSign;
    1189.     o.tSpace0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
    1190.     o.tSpace1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
    1191.     o.tSpace2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);
    1192.     #if defined(_CENTROIDNORMAL)
    1193.     o.centroidNormal = worldNormal;
    1194.     #endif
    1195.     float3 viewDirForLight = UnityWorldSpaceViewDir(worldPos);
    1196.     #ifndef DIRLIGHTMAP_OFF
    1197.     o.viewDir.x = dot(viewDirForLight, worldTangent);
    1198.     o.viewDir.y = dot(viewDirForLight, worldBinormal);
    1199.     o.viewDir.z = dot(viewDirForLight, worldNormal);
    1200.     #endif
    1201. #ifdef DYNAMICLIGHTMAP_ON
    1202.     o.lmap.zw = v.texcoord2.xy * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw;
    1203. #else
    1204.     o.lmap.zw = 0;
    1205. #endif
    1206. #ifdef LIGHTMAP_ON
    1207.     o.lmap.xy = v.texcoord1.xy * unity_LightmapST.xy + unity_LightmapST.zw;
    1208.     #ifdef DIRLIGHTMAP_OFF
    1209.         o.lmapFadePos.xyz = (mul(unity_ObjectToWorld, v.vertex).xyz - unity_ShadowFadeCenterAndType.xyz) * unity_ShadowFadeCenterAndType.w;
    1210.         o.lmapFadePos.w = (-UnityObjectToViewPos(v.vertex).z) * (1.0 - unity_ShadowFadeCenterAndType.w);
    1211.     #endif
    1212. #else
    1213.     o.lmap.xy = 0;
    1214.         #if UNITY_SHOULD_SAMPLE_SH
    1215.             o.sh = 0;
    1216.             o.sh = ShadeSHPerVertex (worldNormal, o.sh);
    1217.         #endif
    1218. #endif
    1219.     return o;
    1220. }
    1221. #ifdef LIGHTMAP_ON
    1222. float4 unity_LightmapFade;
    1223. #endif
    1224. fixed4 unity_Ambient;
    1225.  
    1226. // fragment shader
    1227. void frag_surf (v2f_surf IN,
    1228.         out half4 outGBuffer0 : SV_Target0,
    1229.         out half4 outGBuffer1 : SV_Target1,
    1230.         out half4 outGBuffer2 : SV_Target2,
    1231.         out half4 outEmission : SV_Target3
    1232. #if defined(SHADOWS_SHADOWMASK) && (UNITY_ALLOWED_MRT_COUNT > 4)
    1233.         , out half4 outShadowMask : SV_Target4
    1234. #endif
    1235. ) {
    1236.     UNITY_SETUP_INSTANCE_ID(IN);
    1237.     // prepare and unpack data
    1238.     Input surfIN;
    1239.     UNITY_INITIALIZE_OUTPUT(Input,surfIN);
    1240.     surfIN.uv_MainTex.x = 1.0;
    1241.     surfIN.uv_MainTex = IN.pack0.xy;
    1242.     float3 worldPos = float3(IN.tSpace0.w, IN.tSpace1.w, IN.tSpace2.w);
    1243.     #ifndef USING_DIRECTIONAL_LIGHT
    1244.         fixed3 lightDir = normalize(UnityWorldSpaceLightDir(worldPos));
    1245.     #else
    1246.         fixed3 lightDir = _WorldSpaceLightPos0.xyz;
    1247.     #endif
    1248.     fixed3 worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos));
    1249.     surfIN.worldNormal = float3(IN.tSpace0.z, IN.tSpace1.z, IN.tSpace2.z);
    1250.     surfIN.internalSurfaceTtoW0 = IN.tSpace0.xyz;
    1251.     surfIN.internalSurfaceTtoW1 = IN.tSpace1.xyz;
    1252.     surfIN.internalSurfaceTtoW2 = IN.tSpace2.xyz;
    1253.     #ifdef UNITY_COMPILER_HLSL
    1254.     SurfaceOutputStandard o = (SurfaceOutputStandard)0;
    1255.     #else
    1256.     SurfaceOutputStandard o;
    1257.     #endif
    1258.     o.Albedo = 0.0;
    1259.     o.Emission = 0.0;
    1260.     o.Alpha = 0.0;
    1261.     o.Occlusion = 1.0;
    1262.     fixed3 normalWorldVertex = fixed3(0,0,1);
    1263.  
    1264.     // call surface function
    1265.     surf (surfIN, o);
    1266. fixed3 originalNormal = o.Normal;
    1267.     fixed3 worldN;
    1268.     worldN.x = dot(IN.tSpace0.xyz, o.Normal);
    1269.     worldN.y = dot(IN.tSpace1.xyz, o.Normal);
    1270.     worldN.z = dot(IN.tSpace2.xyz, o.Normal);
    1271.     o.Normal = normalize(worldN);
    1272.     half atten = 1;
    1273.  
    1274.     // Setup lighting environment
    1275.     UnityGI gi;
    1276.     UNITY_INITIALIZE_OUTPUT(UnityGI, gi);
    1277.     gi.indirect.diffuse = 0;
    1278.     gi.indirect.specular = 0;
    1279.     gi.light.color = 0;
    1280.     gi.light.dir = half3(0,1,0);
    1281.     // Call GI (lightmaps/SH/reflections) lighting function
    1282.     UnityGIInput giInput;
    1283.     UNITY_INITIALIZE_OUTPUT(UnityGIInput, giInput);
    1284.     giInput.light = gi.light;
    1285.     giInput.worldPos = worldPos;
    1286.     giInput.worldViewDir = worldViewDir;
    1287.     giInput.atten = atten;
    1288.     #if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)
    1289.         giInput.lightmapUV = IN.lmap;
    1290.     #else
    1291.         giInput.lightmapUV = 0.0;
    1292.     #endif
    1293.     #if UNITY_SHOULD_SAMPLE_SH
    1294.         giInput.ambient = IN.sh;
    1295.     #else
    1296.         giInput.ambient.rgb = 0.0;
    1297.     #endif
    1298.     giInput.probeHDR[0] = unity_SpecCube0_HDR;
    1299.     giInput.probeHDR[1] = unity_SpecCube1_HDR;
    1300.     #if defined(UNITY_SPECCUBE_BLENDING) || defined(UNITY_SPECCUBE_BOX_PROJECTION)
    1301.         giInput.boxMin[0] = unity_SpecCube0_BoxMin; // .w holds lerp value for blending
    1302.     #endif
    1303.     #ifdef UNITY_SPECCUBE_BOX_PROJECTION
    1304.         giInput.boxMax[0] = unity_SpecCube0_BoxMax;
    1305.         giInput.probePosition[0] = unity_SpecCube0_ProbePosition;
    1306.         giInput.boxMax[1] = unity_SpecCube1_BoxMax;
    1307.         giInput.boxMin[1] = unity_SpecCube1_BoxMin;
    1308.         giInput.probePosition[1] = unity_SpecCube1_ProbePosition;
    1309.     #endif
    1310.     LightingStandard_GI(o, giInput, gi);
    1311.  
    1312.     // call lighting function to output g-buffer
    1313.     outEmission = LightingStandard_Deferred (o, worldViewDir, gi, outGBuffer0, outGBuffer1, outGBuffer2);
    1314.     #if defined(SHADOWS_SHADOWMASK) && (UNITY_ALLOWED_MRT_COUNT > 4)
    1315.         outShadowMask = UnityGetRawBakedOcclusions (IN.lmap.xy, float3(0, 0, 0));
    1316.     #endif
    1317.     #ifndef UNITY_HDR_ON
    1318.     outEmission.rgb = exp2(-outEmission.rgb);
    1319.     #endif
    1320. }
    1321.  
    1322.  
    1323. #endif
    1324.  
    1325.  
    1326. ENDCG
    1327.  
    1328. }
    1329.  
    1330.     // ---- meta information extraction pass:
    1331.     Pass {
    1332.         Name "Meta"
    1333.         Tags { "LightMode" = "Meta" }
    1334.         Cull Off
    1335.  
    1336. CGPROGRAM
    1337. // compile directives
    1338. #pragma vertex vert_surf
    1339. #pragma fragment frag_surf
    1340. #pragma target 5.0
    1341. #pragma multi_compile_instancing
    1342. #pragma shader_feature _CENTROIDNORMAL
    1343. #pragma skip_variants FOG_LINEAR FOG_EXP FOG_EXP2
    1344. #pragma skip_variants INSTANCING_ON
    1345. #pragma shader_feature EDITOR_VISUALIZATION
    1346.  
    1347. #include "HLSLSupport.cginc"
    1348. #include "UnityShaderVariables.cginc"
    1349. #include "UnityShaderUtilities.cginc"
    1350. // -------- variant for: <when no other keywords are defined>
    1351. #if !defined(INSTANCING_ON)
    1352. // Surface shader code generated based on:
    1353. // vertex modifier: 'vert'
    1354. // writes to per-pixel normal: YES
    1355. // writes to emission: no
    1356. // writes to occlusion: YES
    1357. // needs world space reflection vector: no
    1358. // needs world space normal vector: no
    1359. // needs screen space position: no
    1360. // needs world space position: no
    1361. // needs view direction: no
    1362. // needs world space view direction: no
    1363. // needs world space position for lighting: YES
    1364. // needs world space view direction for lighting: YES
    1365. // needs world space view direction for lightmaps: no
    1366. // needs vertex color: no
    1367. // needs VFACE: no
    1368. // passes tangent-to-world matrix to pixel shader: YES
    1369. // reads from normal: no
    1370. // 1 texcoords actually used
    1371. //   float2 _MainTex
    1372. #define UNITY_PASS_META
    1373. #include "UnityCG.cginc"
    1374. #include "Lighting.cginc"
    1375. #include "UnityPBSLighting.cginc"
    1376.  
    1377. #define INTERNAL_DATA half3 internalSurfaceTtoW0; half3 internalSurfaceTtoW1; half3 internalSurfaceTtoW2;
    1378. #define WorldReflectionVector(data,normal) reflect (data.worldRefl, half3(dot(data.internalSurfaceTtoW0,normal), dot(data.internalSurfaceTtoW1,normal), dot(data.internalSurfaceTtoW2,normal)))
    1379. #define WorldNormalVector(data,normal) fixed3(dot(data.internalSurfaceTtoW0,normal), dot(data.internalSurfaceTtoW1,normal), dot(data.internalSurfaceTtoW2,normal))
    1380.  
    1381. #ifdef DUMMY_PREPROCESSOR_TO_WORK_AROUND_HLSL_COMPILER_LINE_HANDLING
    1382. #endif
    1383. /* UNITY: Original start of shader */
    1384.         // Physically based Standard lighting model, and enable shadows on all light types
    1385.         //#pragma surface surf Standard fullforwardshadows vertex:vert
    1386.  
    1387.         // Use shader model 3.0 target, to get nicer looking lighting
    1388.         //#pragma target 5.0
    1389.  
    1390.         #include "UnityStandardUtils.cginc"
    1391.  
    1392.         sampler2D _MainTex;
    1393.         sampler2D _MetallicGlossMap;
    1394.         sampler2D _BumpMap;
    1395.         sampler2D _OcclusionMap;
    1396.  
    1397.         struct Input {
    1398.             float2 uv_MainTex;
    1399.             float3 worldNormal; INTERNAL_DATA
    1400.         };
    1401.  
    1402.         fixed4 _Color;
    1403.         half _GlossMapScale;
    1404.         half _BumpScale;
    1405.         half _OcclusionStrength;
    1406.  
    1407.         void surf (Input IN, inout SurfaceOutputStandard o) {
    1408.             fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
    1409.             o.Albedo = c.rgb;
    1410.  
    1411.             fixed4 mg = tex2D(_MetallicGlossMap, IN.uv_MainTex);
    1412.             o.Metallic = mg.r;
    1413.             o.Smoothness = mg.a * _GlossMapScale;
    1414.  
    1415.             float3 vNormalWsDdx = ddx_fine( IN.worldNormal.xyz );
    1416.             float3 vNormalWsDdy = ddy_fine( IN.worldNormal.xyz );
    1417.             float flGeometricRoughnessFactor = pow( saturate( max( dot( vNormalWsDdx.xyz, vNormalWsDdx.xyz ), dot( vNormalWsDdy.xyz, vNormalWsDdy.xyz ) ) ), 0.333 );
    1418.             o.Smoothness = min( o.Smoothness, 1.0 - flGeometricRoughnessFactor ); // Ensure we don’t double-count roughness if normal map encodes geometric roughness
    1419.  
    1420.             half occ = tex2D(_OcclusionMap, IN.uv_MainTex).g;
    1421.             o.Occlusion = LerpOneTo (occ, _OcclusionStrength);
    1422.  
    1423.             half3 normal = UnpackScaleNormal(tex2D(_BumpMap, IN.uv_MainTex), _BumpScale);
    1424.             o.Normal = normal;
    1425.         }
    1426.      
    1427. #include "UnityMetaPass.cginc"
    1428.  
    1429. // vertex-to-fragment interpolation data
    1430. struct v2f_surf {
    1431.     float4 pos : SV_POSITION;
    1432.     float2 pack0 : TEXCOORD0; // _MainTex
    1433.     float4 tSpace0 : TEXCOORD1;
    1434.     float4 tSpace1 : TEXCOORD2;
    1435.     float4 tSpace2 : TEXCOORD3;
    1436.     #if defined(_CENTROIDNORMAL)
    1437.     float3 centroidNormal : TEXCOORD4_centroid;
    1438.     #endif
    1439.     UNITY_VERTEX_INPUT_INSTANCE_ID
    1440.     UNITY_VERTEX_OUTPUT_STEREO
    1441. };
    1442. float4 _MainTex_ST;
    1443.  
    1444. // vertex shader
    1445. v2f_surf vert_surf (appdata_full v) {
    1446.     UNITY_SETUP_INSTANCE_ID(v);
    1447.     v2f_surf o;
    1448.     UNITY_INITIALIZE_OUTPUT(v2f_surf,o);
    1449.     UNITY_TRANSFER_INSTANCE_ID(v,o);
    1450.     UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
    1451.     o.pos = UnityMetaVertexPosition(v.vertex, v.texcoord1.xy, v.texcoord2.xy, unity_LightmapST, unity_DynamicLightmapST);
    1452.     o.pack0.xy = TRANSFORM_TEX(v.texcoord, _MainTex);
    1453.     float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
    1454.     float3 worldNormal = UnityObjectToWorldNormal(v.normal);
    1455.     float3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
    1456.     float tangentSign = v.tangent.w * unity_WorldTransformParams.w;
    1457.     float3 worldBinormal = cross(worldNormal, worldTangent) * tangentSign;
    1458.     o.tSpace0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
    1459.     o.tSpace1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
    1460.     o.tSpace2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);
    1461.     #if defined(_CENTROIDNORMAL)
    1462.     o.centroidNormal = worldNormal;
    1463.     #endif
    1464.     return o;
    1465. }
    1466.  
    1467. // fragment shader
    1468. fixed4 frag_surf (v2f_surf IN) : SV_Target {
    1469.     UNITY_SETUP_INSTANCE_ID(IN);
    1470.     // prepare and unpack data
    1471.     Input surfIN;
    1472.     UNITY_INITIALIZE_OUTPUT(Input,surfIN);
    1473.     surfIN.uv_MainTex.x = 1.0;
    1474.     surfIN.uv_MainTex = IN.pack0.xy;
    1475.     float3 worldPos = float3(IN.tSpace0.w, IN.tSpace1.w, IN.tSpace2.w);
    1476.     #ifndef USING_DIRECTIONAL_LIGHT
    1477.         fixed3 lightDir = normalize(UnityWorldSpaceLightDir(worldPos));
    1478.     #else
    1479.         fixed3 lightDir = _WorldSpaceLightPos0.xyz;
    1480.     #endif
    1481.     #ifdef UNITY_COMPILER_HLSL
    1482.     SurfaceOutputStandard o = (SurfaceOutputStandard)0;
    1483.     #else
    1484.     SurfaceOutputStandard o;
    1485.     #endif
    1486.     o.Albedo = 0.0;
    1487.     o.Emission = 0.0;
    1488.     o.Alpha = 0.0;
    1489.     o.Occlusion = 1.0;
    1490.     fixed3 normalWorldVertex = fixed3(0,0,1);
    1491.  
    1492.     // call surface function
    1493.     surf (surfIN, o);
    1494.     UnityMetaInput metaIN;
    1495.     UNITY_INITIALIZE_OUTPUT(UnityMetaInput, metaIN);
    1496.     metaIN.Albedo = o.Albedo;
    1497.     metaIN.Emission = o.Emission;
    1498.     return UnityMetaFragment(metaIN);
    1499. }
    1500.  
    1501.  
    1502. #endif
    1503.  
    1504.  
    1505. ENDCG
    1506.  
    1507. }
    1508.  
    1509.     // ---- end of surface shader generated code
    1510.  
    1511.     }
    1512.     FallBack "Diffuse"
    1513. }
    1514.  
     
    Last edited: Sep 12, 2017
  5. KamiKaze425

    KamiKaze425

    Joined:
    Nov 20, 2012
    Posts:
    207
    Wow, thanks bgolus! I'll take a look at this and try to play with it a little. I really appreciate it.
     
  6. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    A better model to use to compare. HDR is turned off on the camera. This is a random free car model I downloaded online. White, 100% metallic, 0.8 smoothness, no normal maps. All screenshots have 8x MSAA enabled.

    car standard.png
    car vr standard.png
    car vr standard centroid.png

    Animating between the three. The centroid sampling is most effective on the very thin geometry in the vents, but also a little on the head lamp.
    vr-standard-car-comparison.gif
     
  7. KamiKaze425

    KamiKaze425

    Joined:
    Nov 20, 2012
    Posts:
    207
    The shader makes a night and day difference, dude. I feel like you should sell it on the asset store, haha.
    So I have a vague idea how to add an emission texture and color. Am I supposed to plug it into the first block or into every block that has any emission calculations?
     
  8. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    I wouldn't sell it in that form, too annoying to modify (like adding emission). My suggestion is make a very simple surface shader with emission and look at the code that's generated and see where it's different from the shader I posted.

    Honestly emission is fairly straight forward. Sample texture, multiply by some value, add to final fragment shader output. If you need it to work with baked lighting that requires some custom scripting to modify settings on the material. The Standard Shader does this as part of its custom editor.
     
  9. KamiKaze425

    KamiKaze425

    Joined:
    Nov 20, 2012
    Posts:
    207
    So basically take a simple shader with emission, click compile, then compare the code with the shader you provided?
    I was searching the forums, and you also posted something about emission:
    Code (CSharp):
    1. Properties {
    2. _MainTex ("Albedo", 2D) = "white" {}
    3. _EmissionMap ("Emission Map", 2D) = "black" {}
    4. [HDR] _EmissionColor ("Emission Color", Color) = (0,0,0)
    5. }
    6.  
    7. ...
    8.  
    9. fixed4 albedo = tex2D(_MainTex, i.uv);
    10.  
    11. ... do some lighting ...
    12. half4 output = half4(albedo.rgb * lighting.rgb, albedo.a);
    13.  
    14. half4 emission = tex2D(_EmissionMap, i.uv) * _EmissionColor;
    15. output.rgb += emission.rgb;
    16.  
    17. return output;
    So I was thinking I incorporate that into the VRStandard shader. It looks like what I want (just the emission texture and HDR color parameter from the Unity Standard shader)
     
  10. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    I meant a simple surface shader and click on the "show generated code" button, not compile. But honestly you can shove that vertex / fragment code into the forward base pass(es) and be done.
     
  11. larsbertram1

    larsbertram1

    Joined:
    Oct 7, 2008
    Posts:
    6,899
  12. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    Ah, good to know Lux is offering this as well. Though a minor correction, they're using the same specular filtering from Ready at Dawn's The Order: 1886. It's not from Square Enix. I believe it's the same prefiltering that Alloy uses.
     
  13. larsbertram1

    larsbertram1

    Joined:
    Oct 7, 2008
    Posts:
    6,899
    that is true as far as the texture pre filtering is concerned.
    lux's lighting function however uses square enix's geometry specular AA filtering :)
     
  14. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    Ah, nice. I hadn't seen that one before.
     
  15. Deleted User

    Deleted User

    Guest

    Wondering if anyone succeeded in integrating emissive channel into bgolus' excellent 'Standard VR Shader' and would be willing to post it?

    I've tried the suggestions listed here, without success, as I have no experience writing shaders.
     
  16. olli_vrcoaster

    olli_vrcoaster

    Joined:
    Sep 1, 2017
    Posts:
    24
    this shader would look 100 times better than the default standard shader in VR, since the glossy edges were the thing that bothered me most, even on high AA. I knew there was something wrong with it. @bgolus do you know if this is already implemented in URP / HDRP ? Or if this is possible to achieve via shadergraph ?
     
  17. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    HDRP Lit Shader has a geometry roughness as a check box, might even be on the HDRP Lit Master Node Shader Graph.

    It is not implemented for URP. There’s no reason it couldn’t be implemented in Shader Graph though, either manually with nodes, or a Custom Function node that calls the
    GeometricNormalFiltering
    function, which appears to be in shared SRP shader code.
    https://github.com/Unity-Technologi...elines.core/ShaderLibrary/CommonMaterial.hlsl
     
    OlliQueck likes this.
  18. OlliQueck

    OlliQueck

    Joined:
    Apr 11, 2013
    Posts:
    49
    I'll give it a try next week.
     
  19. olli_vrcoaster

    olli_vrcoaster

    Joined:
    Sep 1, 2017
    Posts:
    24
    both ways work. Might give a summary tomorrow, too late now.
     
  20. olli_vrcoaster

    olli_vrcoaster

    Joined:
    Sep 1, 2017
    Posts:
    24
    alomst forgot, here is a shadergraph node setup of the same thing upload_2020-4-19_20-31-46.png
     

    Attached Files:

  21. AcidArrow

    AcidArrow

    Joined:
    May 20, 2010
    Posts:
    11,631
    If I understand correctly there are two techniques here. One is centroid normal sampling, which if I understand correctly should be just an interpolation qualifier, like flat, but for some reason it’s buggy in Unity (not sure if it still is? Will try it sometime tomorrow), so it has to be implemented manually.

    And the other method is just using partial derivatives on the normals, so on big normal changes per pixel, smoothness is forced to be lower and I guess that sort of results in a more AA look for reflections and specular.
     
  22. Shaunyowns

    Shaunyowns

    Joined:
    Nov 4, 2019
    Posts:
    328
    Let me know how you get on, if it does seem buggy in Unity we'd love to see more information on it
     
    AcidArrow likes this.
  23. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    I wanted to note that this while centroid sampling is just an interpolation qualifier, there's a conditional check to test for over interpolation of the normally interpolated normal before using it. Using centroid sampling all of the time can lead to seam artifacts between triangles on smooth geometry.

    I suspect over-interpolation clamping might actually be just as effective at limiting aliasing for these cases, but I've not tried since I first started experimenting with it 4-5 years ago, mainly because over interpolation causes a relatively small amount of aliasing, and geometric roughness catches a lot of those cases pretty well too.

    I haven't been able to reproduce it in the last year or so. Though in my past testing it only happened on "complex enough" projects. A fresh project generally wouldn't show the problem at all. It was relatively easy to reproduce on projects running versions of Unity 5 and early 2017, but none of the projects I have access to now (which are running various versions of 2018, and 2019) seem to show it. Not sure if the bug is fixed in Unity, if the bug was something with GPU drivers that's been fixed (though it didn't happen with custom engines I was using centroid sampling in), or if it's related to the fact that the scene view no longer shows MSAA in any of the newer versions of Unity (starting around 2017.3 or .4, not sure).
     
    AcidArrow likes this.
  24. AcidArrow

    AcidArrow

    Joined:
    May 20, 2010
    Posts:
    11,631
    @Shaunyowns I did a rough test, centroid seems to work. It's still kinda early and I'll do more testing, but for the time being I have found no issues with it on our project.

    @bgolus I saw that check for over-interpolation in your shader code, but I'm not quite sure I understand why centroid everywhere will lead to artifacts. Thanks for the heads-up, I will have to think about it some more.

    In the mean time, I have gotten a modest improvement by using both centroid and Geo roughness. Images below may not look super impressive, but in motion, the original left image is kinda super distracting, so this is overall a pretty good win for this particular use case.

    Screenshot 2020-04-21 at 2.14.32 AM.png Screenshot 2020-04-21 at 2.14.27 AM.png
     
    fuzzy3d and bgolus like this.
  25. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    So, in trying to show why centroid sampling all of the time isn't good, I started having the problem again in 2019.2.5f1

    I'm not going to submit this as a bug quite yet just because it's super hard to reproduce the bug consistently. When I wasn't recording, and not in play mode, it seemed like I could get it to flicker and sometimes complete get disabled by moving the mouse over stuff in the hierarchy. When I wasn't recording it also showed when mousing over into the game view from the inspector, but not from the project or hierarchy. Super weird.

    Anyways, here's the comparison between no centroid sampling (just geometric roughness), always using centroid sampling, and using conditional centroid sampling on a smooth normal low poly sphere. Notice the weird artifacts in the reflected horizon and in the specular highlight when centroid sampling is used. Those are because there are triangle edges cutting through those parts.
    centroidComparison.gif
     
    olli_vrcoaster and AcidArrow like this.
  26. Thaina

    Thaina

    Joined:
    Jul 13, 2012
    Posts:
    1,157
    Do we have centroid sampling in shadergraph?

    I want to try it but I already forget how to write shader code directly in unity
     
  27. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    No. Shader Graph currently does not expose any kind of way of doing interpolation modifiers. It doesn’t even expose any way of passing custom per vertex data to the fragment shader, which would be needed since you need two separate interpolated normals.
     
    Thaina likes this.
  28. Thaina

    Thaina

    Joined:
    Jul 13, 2012
    Posts:
    1,157
    Thank you for your information. Are there any plan or post that I could follow about this feature?
     
  29. AcidArrow

    AcidArrow

    Joined:
    May 20, 2010
    Posts:
    11,631
    Thaina likes this.
  30. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    Custom Interpolators are planed, but there's as yet no mention of being able to control the interpolation mode, which means it still wouldn't be capable of doing centroid sampling. AFAIK it exists only to let you offload some calculation to be done per vertex. The interpolated values are likely going to be automatically packed into components of standard TEXCOORD# interpolators.

    Basically I would not expect centroid sampling to ever show up as an option for Shader Graph.
     
    Thaina and AcidArrow like this.
  31. Thaina

    Thaina

    Joined:
    Jul 13, 2012
    Posts:
    1,157
    OK then pardon me. I would like to have centroid normal in fragment shader, it could be sent into TEXCOORD or anything. Do we have any plan to let that possible?
     
  32. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    You need to use a centroid interpolation modifier, like shown in the VR Standard Shader example above, though it should be setup like this:
    Code (CSharp):
    1. struct v2f {
    2.   float4 pos : SV_Position;
    3.   float2 uv : TEXCOORD0;
    4.   float3 normal : TEXCOORD1;
    5.   centroid float3 centNormal : TEXCOORD2;
    6.   // whatever else you need
    7. };
    The centroid normal needs to use a unique
    TEXCOORD#
    with the
    centroid
    modifier prefix before the
    float3
    to be passed to the fragment shader using centroid interpolation. Unity URP and HDRP shaders have slightly different naming schemes for the vertex to fragment structs, but the form is the same.
     
  33. Thaina

    Thaina

    Joined:
    Jul 13, 2012
    Posts:
    1,157
    I know, I mean possible in shadergraph, any plan to allow that?
     
  34. AcidArrow

    AcidArrow

    Joined:
    May 20, 2010
    Posts:
    11,631
    I believe there are currently no plans to support something like that with Shader Graph and since it's missing much more basic and elementary stuff than this, I wouldn't count on it happening any time soon (if at all).
     
    Thaina likes this.
  35. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    @AcidArrow already linked to the public planned feature list for ShaderGraph above, which doesn’t mention support for interpolation modifiers even in the “under consideration” list, which has some fairly big and frequently requested items in it. Supporting centroid sampling for the 4 or 5 of us that would use it seems highly unlikely.

    So the only way to do it would be to hand modify the generated shader code, at which point you’re not really using shader graph anymore.
     
    Thaina likes this.
  36. funkyCoty

    funkyCoty

    Joined:
    May 22, 2018
    Posts:
    719
    Wanted to chime in and say we've also had the same issue with centroid usage.



    We're doing the same thing as the valve paper mentioned, checking if the length of the normal is more than 1. if it is, use the centroid interpolated data instead. When we do this, flickering occurs. If we just use centroid on it's own, I'm not seeing flickering.
     
  37. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    I’ve talked to a few people about what’s happening with flickering centroid sampling, and the TLDR version is … no one can explain it.

    The fact it flickers even when using RenderDoc or Nvidia Nsight captures means it’s something really funky. Possibly some bug deep in Nvidia drivers (assuming you’re also running an Nvidia GPU).
     
    DanjelRicci, funkyCoty and hippocoder like this.
  38. JasonB

    JasonB

    Joined:
    Dec 29, 2010
    Posts:
    102
    Guess I'll be the guy to necro this. Any change since 2022 on this?

    I'm currently using URP and implemented some geometric AA (I did it the node method, thanks @olli_vrcoaster) and was hoping to at least try doing centroid sampling as well.

    I mean, I'm pretty happy with the basic solution. Really solves 90% of problems.