zoukankan      html  css  js  c++  java
  • Unity Shader——Writing Surface Shaders(3)——Surface Shader Lighting Examples

    Surface Shader 光照例子

      这里有一些自定义光照模型Surface Shaders的例子。通常的Surface Shader例子在这里

      由于延迟光照在某些自定义的逐材质光照模型中表现得并不好,在下面大多数例子中,我们让shader只编译到正向渲染中。

    漫反射(Diffuse)

      让我们以使用内建Lambert光照模型的shader作为开始吧!

    Shader "Example/Diffuse Texture" {
        Properties {
          _MainTex ("Texture", 2D) = "white" {}
        }
        SubShader {
          Tags { "RenderType" = "Opaque" }
          CGPROGRAM
          #pragma surface surf Lambert
          
          struct Input {
              float2 uv_MainTex;
          };
          
          sampler2D _MainTex;
          
          void surf (Input IN, inout SurfaceOutput o) {
              o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
          }
          ENDCG
        }
        Fallback "Diffuse"
      }

      下面是使用一张纹理贴图和不使用一张真实的纹理贴图的样子(此场景中有一个方向光)

     

      现在,我们来做个完全一样的,但是使用我们自己的光照模型,而不是内建Lambert光照模型。Surface Shader光照模型仅是一些我们需要编写的函数。这里有一个简单的Lambert光照模型。注意到只有CGPROGRAM部分发生了改变,周边的shader代码是完全一样的:

    Shader "Example/Diffuse Texture" {
            Properties {
                _MainTex ("Texture", 2D) = "white" {}
            }
            SubShader {
            Tags { "RenderType" = "Opaque" }
            CGPROGRAM
              #pragma surface surf SimpleLambert
      
              half4 LightingSimpleLambert (SurfaceOutput s, half3 lightDir, half atten) {
                  half NdotL = dot (s.Normal, lightDir);
                  half4 c;
                  c.rgb = s.Albedo * _LightColor0.rgb * (NdotL * atten * 2);
                  c.a = s.Alpha;
                  return c;
              }
      
            struct Input {
                float2 uv_MainTex;
            };
            
            sampler2D _MainTex;
            
            void surf (Input IN, inout SurfaceOutput o) {
                o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
            }
            ENDCG
            }
            Fallback "Diffuse"
        }

      所以我们的简单漫反射光照模型就是LightingSimpleLambert 函数。它通过计算表面法线和光线方向的点积来计算光照,然后应用光照衰减和颜色。

    环绕漫反射(Diffuse Wrap)

      这里是环绕漫反射——漫反射光照的修改版,即照明环绕在物体的边缘。它对用来仿照次表面散射效果很有用。因为只是CGPROGRAM 部分发生了改变,老生常谈一次,周边的shader代码就省略了:

     ...ShaderLab code...
        CGPROGRAM
        #pragma surface surf WrapLambert
    
        half4 LightingWrapLambert (SurfaceOutput s, half3 lightDir, half atten) {
            half NdotL = dot (s.Normal, lightDir);
            half diff = NdotL * 0.5 + 0.5;
            half4 c;
            c.rgb = s.Albedo * _LightColor0.rgb * (diff * atten * 2);
            c.a = s.Alpha;
            return c;
        }
    
        struct Input {
            float2 uv_MainTex;
        };
        
        sampler2D _MainTex;
            void surf (Input IN, inout SurfaceOutput o) {
            o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
        }
        ENDCG
        ...ShaderLab code...

     

    卡通渐变(Toon Ramp)

      下面是一个"渐变(Ramp)"光照模型。它使用一张渐变纹理来定义表面怎样对光线和法线的夹角做出反应。这能用来实现多种效果,包括卡通光照。

    ...ShaderLab code...
        CGPROGRAM
        #pragma surface surf Ramp
    
        sampler2D _Ramp;
    
        half4 LightingRamp (SurfaceOutput s, half3 lightDir, half atten) {
            half NdotL = dot (s.Normal, lightDir);
            half diff = NdotL * 0.5 + 0.5;
            half3 ramp = tex2D (_Ramp, float2(diff)).rgb;
            half4 c;
            c.rgb = s.Albedo * _LightColor0.rgb * ramp * (atten * 2);
            c.a = s.Alpha;
            return c;
        }
    
        struct Input {
            float2 uv_MainTex;
        };
        
        sampler2D _MainTex;
        
        void surf (Input IN, inout SurfaceOutput o) {
            o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
        }
        ENDCG
        ...ShaderLab code...

     

    简单镜面(Simple Specular)

      下面是一个简单镜面光照模型。这对于内置的BlinnPhong实际所做的内容来说非常简单。我们把它放在这来说明它是如何工作的。

      ...ShaderLab code...
        CGPROGRAM
        #pragma surface surf SimpleSpecular
    
        half4 LightingSimpleSpecular (SurfaceOutput s, half3 lightDir, half3 viewDir, half atten) {
            half3 h = normalize (lightDir + viewDir);
    
            half diff = max (0, dot (s.Normal, lightDir));
    
            float nh = max (0, dot (s.Normal, h));
            float spec = pow (nh, 48.0);
    
            half4 c;
            c.rgb = (s.Albedo * _LightColor0.rgb * diff + _LightColor0.rgb * spec) * (atten * 2);
            c.a = s.Alpha;
            return c;
        }
    
        struct Input {
            float2 uv_MainTex;
        };
        
        sampler2D _MainTex;
        
        void surf (Input IN, inout SurfaceOutput o) {
            o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
        }
        ENDCG
        ...ShaderLab code...

    解码光照贴图(Decoding Lightmaps)

      我们将以这样一个shader作为开始:它模仿内置的光照贴图解码工作,使用Unity自带的DecodeLightmap函数解码lightmap中储存的数据信息,以及使用自带的UNITY_DIRBASIS宏定义方向光照贴图(Directional lightmap)的基本向量: 

     Shader "Example/Standard Lightmap Decoding" {
            Properties {
                _MainTex ("Texture", 2D) = "white" {}
            }
            SubShader {
                Tags { "RenderType" = "Opaque" }
                CGPROGRAM
    
                #pragma surface surf Standard
    
                half4 LightingStandard (SurfaceOutput s, half3 lightDir, half atten) {
                    half NdotL = dot (s.Normal, lightDir);
                    half4 c; c.rgb = s.Albedo * _LightColor0.rgb * (NdotL * atten * 2);
                    c.a = s.Alpha;
                    return c;
                }
    
                inline fixed4 LightingStandard_SingleLightmap (SurfaceOutput s, fixed4 color) {
                    half3 lm = DecodeLightmap (color);
                    return fixed4(lm, 0);
                }
    
                inline fixed4 LightingStandard_DualLightmap (SurfaceOutput s, fixed4 totalColor, fixed4 indirectOnlyColor, half indirectFade) {
                    half3 lm = lerp (DecodeLightmap (indirectOnlyColor), DecodeLightmap (totalColor), indirectFade);
                    return fixed4(lm, 0);
                }
    
                inline fixed4 LightingStandard_StandardLightmap (SurfaceOutput s, fixed4 color, fixed4 scale, bool surfFuncWritesNormal) {
                    UNITY_DIRBASIS
    
                    half3 lm = DecodeLightmap (color);
                    half3 scalePerBasisVector = DecodeLightmap (scale);
    
                    if (surfFuncWritesNormal)
                    {
                        half3 normalInRnmBasis = saturate (mul (unity_DirBasis, s.Normal));
                        lm *= dot (normalInRnmBasis, scalePerBasisVector);
                    }
    
                    return fixed4(lm, 0);
                }
    
                struct Input {
                    float2 uv_MainTex;
                };
                
                sampler2D _MainTex;
                
                void surf (Input IN, inout SurfaceOutput o) {
                    o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
                }
                ENDCG
                }
            Fallback "Diffuse"
        }

      现在,让我们为光照贴图中储存的光添加些色调映射(tone mapping):

    Shader "Example/Tonemapped Lightmap Decoding" {
            Properties {
                _MainTex ("Texture", 2D) = "white" {}
                _Gain ("Lightmap tone-mapping Gain", Float) = 1
                _Knee ("Lightmap tone-mapping Knee", Float) = 0.5
                _Compress ("Lightmap tone-mapping Compress", Float) = 0.33
            }
            SubShader {
                Tags { "RenderType" = "Opaque" }
                CGPROGRAM
    
                #pragma surface surf Tonemapped
    
                half4 LightingTonemapped (SurfaceOutput s, half3 lightDir, half atten) {
                    half NdotL = dot (s.Normal, lightDir);
                    half4 c; c.rgb = s.Albedo * _LightColor0.rgb * (NdotL * atten * 2); c.a = s.Alpha;
                    return c;
                }
    
                half _Gain;
                half _Knee;
                half _Compress;
                
                inline half3 TonemapLight (half3 i) {
                    i *= _Gain;
                    return (i > _Knee)? (((i - _Knee)*_Compress)+_Knee): i;
                }
    
                inline fixed4 LightingTonemapped_SingleLightmap (SurfaceOutput s, fixed4 color) {
                    half3 lm = TonemapLight(DecodeLightmap (color));
                    return fixed4(lm, 0);
                }
    
                inline fixed4 LightingTonemapped_DualLightmap (SurfaceOutput s, fixed4 totalColor, fixed4 indirectOnlyColor, half indirectFade) {
                    half3 lm = TonemapLight(lerp (DecodeLightmap (indirectOnlyColor), DecodeLightmap (totalColor), indirectFade));
                    return fixed4(lm, 0);
                }
    
                inline fixed4 LightingTonemapped_StandardLightmap (SurfaceOutput s, fixed4 color, fixed4 scale, bool surfFuncWritesNormal) {
                    UNITY_DIRBASIS
    
                    half3 lm = TonemapLight(DecodeLightmap (color));
                    half3 scalePerBasisVector = DecodeLightmap (scale);
    
                    if (surfFuncWritesNormal)
                    {
                        half3 normalInRnmBasis = saturate (mul (unity_DirBasis, s.Normal));
                        lm *= dot (normalInRnmBasis, scalePerBasisVector);
                    }
    
                    return fixed4(lm, 0);
                }
    
                struct Input {
                    float2 uv_MainTex;
                };
                
                sampler2D _MainTex;
                
                void surf (Input IN, inout SurfaceOutput o) {
                    o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
                }
                ENDCG
            }
            Fallback "Diffuse"
        }
  • 相关阅读:
    软件开的目录规范+sys,os,time模块
    模块与包
    匿名函数+函数递归+二分法+面向过程编程
    快捷键
    补充叠加多个装饰器:加载顺序与执行顺序+迭代器+自定义迭代器的方式:生成器+三元表达式
    闭包函数的应用+内置函数
    函数对象+函数嵌套+名称空间与作用域+闭包函数
    SP15637 Mr Youngs Picture Permutations 高维动态规划
    LG3825/BZOJ4945/LOJ2305 「NOI2017」游戏 dfs+2-SAT
    LG1198/BZOJ1012 「JSOI2008」最大数 线段树+离线
  • 原文地址:https://www.cnblogs.com/dreamlofter/p/4507101.html
Copyright © 2011-2022 走看看