unityshader自己学习笔记--基础知识--光照算法演变过程

光照


不同的光照shader,同条件下会有不一样的结果

vertex_difuse

unity光照对比顶点光照

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZgsBjJ9c-1681797878882)(image-20230306121657737.png)]

因为使用顶点做插值,所以可以看到比较严重的锯齿

Shader "Unlit/基础光照实现/vertex_difuse"
{
    Properties
    {
        _Diffuse("漫反射颜色",Color)=(1,1,1,1)
    }
    SubShader
    {
        Pass
        {
            Tags { "LightMode"="ForwardBase" }

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "Lighting.cginc"
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
                fixed3 color:COLOR;
            };

            fixed4 _Diffuse;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                //在顶点着色器中计算漫反射光照

                //unity中使用  UNITY_LIGHTMODEL_AMBIENT 来表示环境光
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
                //获取光的方向
                //当世界只有一个平行光光源的时候可以使用 _WorldSpaceLightPos0 这个内置的变量来获取光照的方向
                fixed3 worldLight = normalize(_WorldSpaceLightPos0.xyz);
                //世界中的法线信息
                //可以使用 unity_ObjectToWorld 矩阵来将其变换到世界中
                fixed3 worldNormal = normalize(mul(v.normal,(float3x3)unity_ObjectToWorld));

                //_LightColor0 世界只有一个平行光光源的时候 表示光源的颜色
                //saturate函数的作用是将输入的参数数值限定在 0-1 之间
                fixed3 diff = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal,worldLight));

                o.color = diff + ambient;

                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                return fixed4(i.color,1.0f);
            }
            ENDCG
        }
    }
}

vertex_difuse

按像素计算

效果很精美,没有锯齿,但是可以看到黑色区域非常黑

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9R4B4LkR-1681797878883)(image-20230306124825257.png)]

Shader "Unlit/基础光照实现/pixel_difuse"
{
    Properties
    {
        _Diffuse("漫反射颜色",Color)=(1,1,1,1)
    }
    SubShader
    {
        Pass
        {
            Tags { "LightMode"="ForwardBase" }

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "Lighting.cginc"
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
                float3 worldNormal:NORMAL;
            };

            fixed4 _Diffuse;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                //世界中的法线信息
                //可以使用 unity_ObjectToWorld 矩阵来将其变换到世界中
                o.worldNormal = normalize(mul(v.normal,(float3x3)unity_ObjectToWorld));
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                
                //unity中使用  UNITY_LIGHTMODEL_AMBIENT 来表示环境光
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
                //获取光的方向
                //当世界只有一个平行光光源的时候可以使用 _WorldSpaceLightPos0 这个内置的变量来获取光照的方向
                fixed3 worldLight = normalize(_WorldSpaceLightPos0.xyz);

                float3 worldNormal = normalize(i.worldNormal);
            
                 //_LightColor0 世界只有一个平行光光源的时候 表示光源的颜色
                //saturate函数的作用是将输入的参数数值限定在 0-1 之间
                fixed3 diff = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal,worldLight));

                fixed3 color = diff + ambient;

                return fixed4(color,1.0f);
            }
            ENDCG
        }
    }
}

Lamert_pixel_difuse

lamert算法改进了阴影的缺陷

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D56IqLIl-1681797878883)(image-20230306130135338.png)]

Shader "Unlit/基础光照实现/Lamert_pixel_difuse"
{
    Properties
    {
        _Diffuse("漫反射颜色",Color)=(1,1,1,1)
    }
    SubShader
    {
        Pass
        {
            Tags { "LightMode"="ForwardBase" }

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "Lighting.cginc"
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
                float3 worldNormal:NORMAL;
            };

            fixed4 _Diffuse;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                //世界中的法线信息
                //可以使用 unity_ObjectToWorld 矩阵来将其变换到世界中
                o.worldNormal = normalize(mul(v.normal,(float3x3)unity_ObjectToWorld));
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                
                //unity中使用  UNITY_LIGHTMODEL_AMBIENT 来表示环境光
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
                //获取光的方向
                //当世界只有一个平行光光源的时候可以使用 _WorldSpaceLightPos0 这个内置的变量来获取光照的方向
                fixed3 worldLight = normalize(_WorldSpaceLightPos0.xyz);

                float3 worldNormal = normalize(i.worldNormal);
            
                //兰伯特光照计算
                //c_diffuse = (c_light * m_diffuse) * (a * (normal.dot(lightdir)) + b)
                //半兰伯特公式
                //c_diffuse = (c_light * m_diffuse) * (0.5 * (normal.dot(lightdir)) + 0.5)



                fixed3 half_lambert = 0.5 * dot(worldNormal,worldLight) + 0.5;
                 //_LightColor0 世界只有一个平行光光源的时候 表示光源的颜色
                //saturate函数的作用是将输入的参数数值限定在 0-1 之间
                fixed3 diff = _LightColor0.rgb * _Diffuse.rgb * half_lambert;

                fixed3 color = diff + ambient;

                return fixed4(color,1.0f);
            }
            ENDCG
        }
    }
}

Specular_Lamert_pixel_difuse

lamert算法+高光(镜面反射)算法后的表现

可以看到这样的高光整体效果不是很自然

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ieh2j16X-1681797878884)(image-20230306131213409.png)]

Shader "Unlit/基础光照实现/Specular_Lamert_pixel_difuse"
{
    Properties
    {
        _Diffuse("漫反射颜色",Color)=(1,1,1,1)
        _Specular("镜面反射系数",Color)=(1,1,1,1)
        _Power("高光指数",Range(1.0,512.0))=20.0
    }
    SubShader
    {
        Pass
        {
            Tags { "LightMode"="ForwardBase" }

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "Lighting.cginc"
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
                float3 worldNormal:TEXCOORD0;
                float3 worldPos:TEXCOORD1;
            };

            fixed4 _Diffuse;
            fixed4 _Specular;
            float _Power;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                //世界中的法线信息
                //可以使用 unity_ObjectToWorld 矩阵来将其变换到世界中
                o.worldNormal = normalize(mul(v.normal,(float3x3)unity_ObjectToWorld));
                o.worldPos = mul(v.vertex,(float3x3)unity_ObjectToWorld);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                
                //unity中使用  UNITY_LIGHTMODEL_AMBIENT 来表示环境光
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
                //获取光的方向
                //当世界只有一个平行光光源的时候可以使用 _WorldSpaceLightPos0 这个内置的变量来获取光照的方向
                fixed3 worldLight = normalize(_WorldSpaceLightPos0.xyz);

                float3 worldNormal = normalize(i.worldNormal);
            
                //兰伯特光照计算
                //c_diffuse = (c_light * m_diffuse) * (a * (normal.dot(lightdir)) + b)
                //半兰伯特公式
                //c_diffuse = (c_light * m_diffuse) * (0.5 * (normal.dot(lightdir)) + 0.5)



                fixed3 half_lambert = 0.5 * dot(worldNormal,worldLight) + 0.5;
                 //_LightColor0 世界只有一个平行光光源的时候 表示光源的颜色
                //saturate函数的作用是将输入的参数数值限定在 0-1 之间
                fixed3 diff = _LightColor0.rgb * _Diffuse.rgb * half_lambert;

               


                //计算镜面反射
                //Unity中给出了计算反射方向的函数 r = reflect(i,n)
                /*
                r:表示反射的方向
                i:表示的是入射的方向
                n:表示的是法线方向
                */

                fixed3 reflectdir = normalize(reflect(-worldLight,worldNormal));

                //观察方向
                //_WorldSpaceCameraPos 表示的是当前世界中摄像机的位置
                fixed3 viewdir = normalize( _WorldSpaceCameraPos.xyz - i.worldPos.xyz);

                fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(reflectdir,viewdir)),_Power);

                 fixed3 color = diff + ambient + specular;
                return fixed4(color,1.0f);
            }
            ENDCG
        }
    }
}

BlinPhong_Specular_Lamert_pixel_difuse

对于折射的角度做了一些处理步骤

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w4c8zcgQ-1681797878884)(image-20230307202953953.png)]

Shader "Unlit/基础光照实现/BlinPhong_Specular_Lamert_pixel_difuse"
{
    Properties
    {
        _Diffuse("漫反射颜色",Color)=(1,1,1,1)
        _Specular("镜面反射系数",Color)=(1,1,1,1)
        _Power("高光指数",Range(1.0,512.0))=20.0
    }
    SubShader
    {
        Pass
        {
            Tags { "LightMode"="ForwardBase" }

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "Lighting.cginc"
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
                float3 worldNormal:TEXCOORD0;
                float3 worldPos:TEXCOORD1;
            };

            fixed4 _Diffuse;
            fixed4 _Specular;
            float _Power;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                //世界中的法线信息
                //可以使用 unity_ObjectToWorld 矩阵来将其变换到世界中
                o.worldNormal = normalize(mul(v.normal,(float3x3)unity_ObjectToWorld));
                o.worldPos = mul(v.vertex,(float3x3)unity_ObjectToWorld);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                
                //unity中使用  UNITY_LIGHTMODEL_AMBIENT 来表示环境光
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
                //获取光的方向
                //当世界只有一个平行光光源的时候可以使用 _WorldSpaceLightPos0 这个内置的变量来获取光照的方向
                fixed3 worldLight = normalize(_WorldSpaceLightPos0.xyz);

                float3 worldNormal = normalize(i.worldNormal);
            
                //兰伯特光照计算
                //c_diffuse = (c_light * m_diffuse) * (a * (normal.dot(lightdir)) + b)
                //半兰伯特公式
                //c_diffuse = (c_light * m_diffuse) * (0.5 * (normal.dot(lightdir)) + 0.5)



                fixed3 half_lambert = 0.5 * dot(worldNormal,worldLight) + 0.5;
                 //_LightColor0 世界只有一个平行光光源的时候 表示光源的颜色
                //saturate函数的作用是将输入的参数数值限定在 0-1 之间
                fixed3 diff = _LightColor0.rgb * _Diffuse.rgb * half_lambert;

               


                //计算镜面反射
                //Unity中给出了计算反射方向的函数 r = reflect(i,n)
                /*
                r:表示反射的方向
                i:表示的是入射的方向
                n:表示的是法线方向
                */

                //fixed3 reflectdir = normalize(reflect(-worldLight,worldNormal));

                //观察方向
                //_WorldSpaceCameraPos 表示的是当前世界中摄像机的位置
                fixed3 viewdir = normalize( _WorldSpaceCameraPos.xyz - i.worldPos.xyz);

                fixed3 halfdir = normalize(worldLight + viewdir);

                //fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(reflectdir,viewdir)),_Power);
                fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(worldNormal,halfdir)),_Power);
                 fixed3 color = diff + ambient + specular;
                return fixed4(color,1.0f);
            }
            ENDCG
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值