Reflections in custom shader

Hi everyone,

I’ve made this shader in Unity 5b12 :

Shader "simple" {
Properties {
    _Color ("Main Color", Color) = (1,1,1,1)
    _MainTex ("Base (RGB)", 2D) = "white" {}
    _SpecTex ("Spec (RGB) Gloss (A)", 2D) = "white" {}
    _NormTex ("Normal (RGB)", 2D) = "white" {}
    _NormFactor ("Normal Strength", Range (0,2)) = 1
}

SubShader {
    Tags { "RenderType"="Opaque" }
    LOD 300
   
CGPROGRAM
#pragma target 3.0
#include "UnityPBSLighting.cginc"
#pragma surface surf Standard

sampler2D _MainTex;
sampler2D _NormTex;
sampler2D _SpecTex;
fixed4 _Color;
half _NormFactor;

struct Input {
    float2 uv_MainTex;
    float2 uv_SpecTex;
    float2 uv_NormTex;
};

void surf (Input IN, inout SurfaceOutputStandard o) {
    fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);
    fixed4 spectex = tex2D(_SpecTex, IN.uv_SpecTex);
    o.Albedo = tex.rgb * _Color.rgb;
    o.Normal = UnpackScaleNormal(tex2D(_NormTex, IN.uv_NormTex),_NormFactor);
    o.Specular = spectex.rgb;
    o.Smoothness = spectex.a;
}
ENDCG
}

Fallback "VertexLit"
}

The lighting seems correct when I remove specular but as you can see, there is no reflections.
Is there an “easy” way to mimic the standard shader reflections in surface shaders?

1844687--118323--cubes.jpg
left cube : standard shader
right cube : my shader with the same images/parameters
bottom left : why I need reflections :slight_smile:

I think there was a bug with surface shaders where reflection information was not being passed in the shader. Wait for 5.0 b13, if it will still not work, please submit a bug.

Great, thanks !

Has this been fixed as I am having the same problem, can get the lighting working but have no reflections at all.

nope, I have submitted a bug report.

I think you need to add the following codes to custom shader to enable the reflection:

    CGINCLUDE
        #define _GLOSSYENV 1
        #define UNITY_SETUP_BRDF_INPUT SpecularSetup
    ENDCG

It will also work for Metallic Setup

#define UNITY_SETUP_BRDF_INPUT MetallicSetup

Full Shader Example:

// All textures share the same Tiling and Offset value from Main Texture

Shader "Custom/PBS (Specular Setup)" {
Properties {
    _Color ("Main Color", Color) = (1,1,1,1)
    _MainTex ("Base (RGB)", 2D) = "white" {}
    _SpecColor ("Specular Color", Color) = (1,1,1,1)
    _Glossiness("Smoothness", Range(0,1)) = 0.75
[NoScaleOffset] _SpecGlossMap("Specular (RGB) Glossiness (A)", 2D) = "white" {}
[NoScaleOffset] _BumpMap ("Normal Map", 2D) = "bump" {}
    _BumpScale("Bump Scale", Float) = 1.0

}
     CGINCLUDE
        //@TODO: should this be pulled into a shader_feature, to be able to turn it off?
        #define _GLOSSYENV 1
        #define UNITY_SETUP_BRDF_INPUT SpecularSetup
    ENDCG

SubShader {
    Tags { "RenderType"="Opaque" }
    LOD 300

CGPROGRAM
#pragma target 3.0
#include "UnityPBSLighting.cginc"
#pragma surface surf Standard
sampler2D _MainTex;
sampler2D _BumpMap;
sampler2D _SpecGlossMap;
fixed4 _Color ;
half _Glossiness;
half _BumpScale;
struct Input {
    float2 uv_MainTex;
};
void surf (Input IN, inout SurfaceOutputStandard o) {
    fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);
    fixed4 sg = tex2D(_SpecGlossMap, IN.uv_MainTex);
    o.Albedo = tex.rgb * _Color.rgb;
    o.Normal = UnpackScaleNormal(tex2D(_BumpMap, IN.uv_MainTex),_BumpScale);
    o.Specular = sg.rgb * _SpecColor.rgb;
    o.Smoothness = sg.a *_Glossiness ;
}
ENDCG
}
Fallback "VertexLit"

}

This shader has been tested, it will show either skybox reflection or reflection probe :slight_smile:

[Edit] Updated the shader “Properties”.

3 Likes

It’s working ! Thanks luckymouse.

did you managed to get transparency working with PBS Surface Shader? I did not find the switch, yet. Am I missing something?
This is what I’ve got so far, including a custom light model (currently untouched, just copied from the cginc-files), but it’s not working with the “Standard” Lightmodel, either.

Code

    // All textures share the same Tiling and Offset value from Main Texture
  
    Shader "Custom/PBS (Specular Setup)" {
    Properties {
        _Color ("Main Color", Color) = (1,1,1,1)
        _MainTex ("Base (RGB)", 2D) = "white" {}
        _SpecColor ("Specular Color", Color) = (1,1,1,1)
        _Glossiness("Smoothness", Range(0,1)) = 0.75
        [NoScaleOffset] _SpecGlossMap("Specular (RGB) Glossiness (A)", 2D) = "white" {}
        [NoScaleOffset] _BumpMap ("Normal Map", 2D) = "bump" {}
        _BumpScale("Bump Scale", Float) = 1.0
    }
    CGINCLUDE
    //@TODO: should this be pulled into a shader_feature, to be able to turn it off?
    #define _GLOSSYENV 1
    #define UNITY_SETUP_BRDF_INPUT SpecularSetup
    ENDCG
  
    SubShader {
        Tags { "RenderType"="Transparent"}
        LOD 300
        ZWrite Off
        ZTest LEqual
        Blend SrcAlpha OneMinusSrcAlpha
         
    CGPROGRAM
    #pragma target 3.0
    #include "UnityPBSLighting.cginc"
    #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON
    #pragma surface surf MyLightModel
 
    sampler2D _MainTex;
    sampler2D _BumpMap;
    sampler2D _SpecGlossMap;
    fixed4 _Color ;
    half _Glossiness;
    half _BumpScale;
 

inline half4 LightingMyLightModel (SurfaceOutputStandard s, half3 viewDir, UnityGI gi)
{
    s.Normal = normalize(s.Normal);

    // energy conservation
    half oneMinusReflectivity = 1 - SpecularStrength(s.Specular);
    half oneMinusRoughness = s.Smoothness;
    s.Albedo = s.Albedo * oneMinusReflectivity;
    half4 c = UNITY_BRDF_PBS (s.Albedo, s.Specular, oneMinusReflectivity, oneMinusRoughness, s.Normal, viewDir, gi.light, gi.environment);
    #if defined(DIRLIGHTMAP_SEPARATE)
        c += DirectionalLightmapsIndirectBRDF (s.Albedo, s.Specular, oneMinusReflectivity, oneMinusRoughness, s.Normal, viewDir, gi);
    #endif
    return c;
}

inline half4 LightingMyLightModel_Deferred (SurfaceOutputStandard s, half3 viewDir, UnityGI gi, out half4 outDiffuse, out half4 outSpecSmoothness, out half4 outNormal)
{
    // energy conservation
    half oneMinusReflectivity = 1 - SpecularStrength(s.Specular);
    half oneMinusRoughness = s.Smoothness;
    s.Albedo = s.Albedo * oneMinusReflectivity;
    half4 c = UNITY_BRDF_PBS (s.Albedo, s.Specular, oneMinusReflectivity, oneMinusRoughness, s.Normal, viewDir, gi.light, gi.environment);
    #if defined(DIRLIGHTMAP_SEPARATE)
        c += DirectionalLightmapsIndirectBRDF (s.Albedo, s.Specular, oneMinusReflectivity, oneMinusRoughness, s.Normal, viewDir, gi);
    #endif
    outDiffuse = half4(s.Albedo, s.Alpha);
    outSpecSmoothness = half4(s.Specular, s.Smoothness);
    outNormal = half4(s.Normal * 0.5 + 0.5, 1);
    half4 emission = half4(s.Emission + c.rgb, 1);
    return emission;
}
    inline void LightingMyLightModel_GI (SurfaceOutputStandard s, UnityGIInputData data, inout UnityGI gi)
    {
        UnityStandardGlobalIllumination (data, s.Occlusion, (1-s.Smoothness), s.Normal, gi);
    }

    struct Input {
        float2 uv_MainTex;
    };
    void surf (Input IN, inout SurfaceOutputStandard o) {
        fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);
        fixed4 sg = tex2D(_SpecGlossMap, IN.uv_MainTex);
        o.Albedo = tex.rgb * _Color.rgb;
        o.Normal = UnpackScaleNormal(tex2D(_BumpMap, IN.uv_MainTex),_BumpScale);
        o.Specular = sg.rgb * _SpecColor.rgb;
        o.Smoothness = sg.a *_Glossiness ;
        o.Alpha = 0.5f;
    }
    ENDCG
    }
    Fallback "VertexLit"
  
    }

@ pojoih, You forget to add the alpha word after your MyLightModel:

It should be:

    #pragma surface surf MyLightModel alpha

Thats all, the way how alpha works in surface shader is the same since Unity 3.x. Check the doc here.

After #define _GLOSSYENV 1 , what variables do you get to use and how are they used? I expected the shader example to use something in o.Emission but I guess it doesn’t work like that anymore. Anyone has found out anything yet? I urgently need to set some custom reflection strengths independent of the specular (and without changing the Reflection Probe Inspector strength)

I’d appreciate your insights.

EDIT: Small update on what I have found so far:
It looks like we may need to do it with custom lighting functions? They recently moved more code and now you find reflection related code in UnityPBSLighting.cginc

It’s all a little hard to follow with many things still spread out through tons of files but if I copypaste and base on the UnityPBSLighting.cginc I may be able to achieve what I want. I still need to try it, I havn’t touched it yet. I still think I’m missing something though, it seems all a little complicated… what if I want a much simpler Lighting Model but with access to the probes? It goes through so many files with things declared everywhere I don’t even know. But yeah that’s what I found so far.

Are you still able to use your custom lighting model with b17 ? I get an error : “Shader error in ‘Custom/PBS (Specular Setup)’: Syntax error at line 71 (on )”

It refers to this:

inline void LightingMyLightModel_GI (SurfaceOutputStandard s, UnityGIInputData data, inout UnityGI gi)
        {
            UnityStandardGlobalIllumination (data, s.Occlusion, (1-s.Smoothness), s.Normal, gi);
        }

I copy pasted the code posted here and it gives me this error. also I can’t get the metalic setup to work, it makes no difference if I use this:
#define UNITY_SETUP_BRDF_INPUT SpecularSetup
or this
#define UNITY_SETUP_BRDF_INPUT MetallicSetup