How to implement standard specular into a custom lighting model surface shader

I’d like to do a surface shader with a custom lighting model but still implement the standard specular behaviour where reflection probes are picked up. I’d also like to implement the standard gi. Basically I want the standard shader but with access to a custom lighting function. Could anyone point me in the right direction?

Shader "Eastshade 2/Standard" {
    Properties {
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
    }
    SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 200
       
        CGPROGRAM
        #pragma surface surf Custom
        #pragma target 3.0

        sampler2D _MainTex;

        struct Input {
            float2 uv_MainTex;
        };

        struct SurfaceOutputCustom {
            fixed3 Albedo;
            fixed3 Normal;
            fixed3 Emission;
            fixed Specular;
            fixed Gloss;
            fixed Alpha;
        };

        half4 LightingCustom_Deferred(SurfaceOutputCustom s, UnityGI gi, out half4 outDiffuseOcclusion, out half4 outSpecSmoothness, out half4 outNormal) {

            half4 c = half4(s.Albedo, s.Alpha);
            outDiffuseOcclusion = half4(s.Albedo, 0);
            outSpecSmoothness = half4(s.Specular, s.Specular, s.Specular, s.Gloss);
            outNormal = half4(s.Normal * 0.5 + 0.5, 1);
            //maybe I put the spec here?
            return c;
        }

        inline void LightingCustom_GI( SurfaceOutputCustom s, UnityGIInput data, inout UnityGI gi ) {
            //maybe I put the spec here?
        }

        void surf (Input IN, inout SurfaceOutputCustom o) {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * .25;
            o.Albedo = c.rgb;
            o.Emission = 0;
            o.Specular = 0;
            o.Gloss = 0;
            o.Alpha = 1;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

So I’ve been working on this for a few days, and I’ve figured out the answer. I’m going to post it here in case anyone else is searching for the answer. I looked at the “LightingStandard_Deferred” and “LightingStandard_GI” functions which you can find in UnityPBSLighting.cginc in the built-in shaders. You can copy much of the code from those functions into your custom lighting functions in your surface shader. Be sure to include:

#include "UnityPBSLighting.cginc"

Your shader will likely require different implementation, but my two lighting functions look like this:

half4 LightingTranslucent_Deferred(SurfaceOutputCustom s, half3 viewDir, UnityGI gi, out half4 outDiffuseOcclusion, out half4 outSpecSmoothness, out half4 outNormal) {
    half4 c = UNITY_BRDF_PBS (s.Albedo, s.Specular, 0, s.Gloss, s.Normal, viewDir, gi.light, gi.indirect);
    c *= _Color * 2;
    c.rgb += UNITY_BRDF_GI (s.Albedo, s.Specular, 0, s.Gloss, s.Normal, viewDir, s.Occlusion, gi);

    outDiffuseOcclusion = half4(s.Albedo, s.Occlusion);
    outSpecSmoothness = half4(s.Specular, s.Specular, s.Specular, s.Gloss);
    outNormal = half4(s.Normal * 0.5 + 0.5, 1 - (s.Translucent* 1.5));

     return c;
}

inline void LightingTranslucent_GI( SurfaceOutputCustom s, UnityGIInput data, inout UnityGI gi ) {
    #if defined(UNITY_PASS_DEFERRED) && UNITY_ENABLE_REFLECTION_BUFFERS
         gi = UnityGlobalIllumination(data, s.Occlusion, s.Normal);
    #else
          Unity_GlossyEnvironmentData g = UnityGlossyEnvironmentSetup(s.Gloss, data.worldViewDir, s.Normal, lerp(unity_ColorSpaceDielectricSpec.rgb, s.Albedo, s.Specular));
           gi = UnityGlobalIllumination(data, s.Occlusion, s.Normal, g);
      #endif
}
3 Likes

LightingTranslucent_Deferred(SurfaceOutputCustom s, half3 viewDir, UnityGI gi, out half4 outDiffuseOcclusion, out half4 outSpecSmoothness, out half4 outNormal)
What do each parameter do?

Also Rider VS and Code can’t find definition of any of the shader stuff, what do you use to decypher all that?