美文网首页
Shader笔记-光照模型

Shader笔记-光照模型

作者: 黒可乐 | 来源:发表于2017-12-11 11:50 被阅读0次

    光照模型就是一个公式,使用这个公式来计算在某个点的光照效果。

    标准光照模型-光的分类
    ●自发光
    ●高光反射 Specular
    ●漫反射 Diffuse=直射光的颜色 * max(0,cos夹角(光和法线的夹角)) cosi =光方向 · 法线方向
    ●环境光

    只有定义了正确的LightMode与引用这个光照文件才能得到unity的内置光照变量:

    Tags("LightMode"="ForwardBase")
    #include "Lighting.cgnic"
    

    代码如下:

    Shader "BanMing/DiffuseVertex" {
        SubShader
        {
            Pass
            {
            Tags{"LightMode"="ForwardBase"}//光照标签
            CGPROGRAM
    //引入光照文件
    #include "Lighting.cginc"
    
    #pragma vertex vert
    #pragma fragment frag
    
            struct a2v {
                float4 vertex:POSITION;//告诉unity把模型空间下的顶点坐标填充给vertex
                fixed3 normal :NORMAL;
            };
    
            struct v2f{
                float4 position :SV_POSITION;
                float3 color:COLOR;
            };
    
            v2f vert(a2v v){
                v2f f;          
                f.position=mul(UNITY_MATRIX_MVP,v.vertex);
                //坐标转换可以使用mul()中间带入参数unity_WorldToObject,同时也可以使用UnityObjectToWorldDir这个方法来调用
                // fixed3 normalDir=normalize(mul(v.normal,(float3x3)unity_WorldToObject));
                //漫反射公式 :光照颜色*(cos(法线与光照夹角)) 
                //这里求角度使用到了点乘,如果两个向量都是单位向量的话,乘出来就是夹角的cos
                fixed3 normalDir=normalize(UnityObjectToWorldDir((float3)v.normal));
                //光照的位置,因为光是平行光所以也是方向
                fixed3 lightDir=normalize(_WorldSpaceLightPos0.xyz);
                //_LightColor0是光照的颜色
                fixed3 diffuse =_LightColor0.rgb*max(dot(normalDir,lightDir),0);
                f.color =diffuse;
                return f;
            }
    
            fixed4 frag (v2f f):SV_TARGET{
                return fixed4(f.color,1);
            }
    
            ENDCG
            }
        }
            FallBack "Diffuse"
    }
    

    环境光获取UNITY_LIGHTMODEL_AMBIENT
    两个光叠加就把两个颜色值相加,两个光融合则把两个颜色值相乘。
    像素漫反射:

        struct a2v {
            float4 vertex:POSITION;
            fixed3 normal :NORMAL;
        };
    
        struct v2f{
            float4 position :SV_POSITION;
            float3 worldNormalDir:COLOR;
        };
    
        v2f vert(a2v v){
            v2f f;          
            f.position=UnityObjectToClipPos(v.vertex);
    
            f.worldNormalDir=UnityObjectToWorldDir((float3)v.normal);
        
            return f;
        }
    
        fixed4 frag (v2f f):SV_TARGET{
            fixed3 normalDir= normalize(f.worldNormalDir);
            fixed3 ambient= UNITY_LIGHTMODEL_AMBIENT.rgb;
            //光照的位置,因为光是平行光所以也是方向
            fixed3 lightDir=normalize(_WorldSpaceLightPos0.xyz);
            //_LightColor0是光照的颜色
            fixed3 diffuse =_LightColor0.rgb*max(dot(normalDir,lightDir),0);
            fixed3 tempColor =diffuse*_Diffuse.rgb+ambient;
            return fixed4(tempColor,1);
        }
    

    一般使用半兰伯特光照,正常的光照计算出来是-1到1,所以在平行光的背面的漫反射计算出来是-1所以这个地方是黑色的。公式如下:

    diffuse=light*cosθ 正常的是这样的。
    diffuse=light*(cosθ*0.5+0.5) 半兰伯特光照
    
    半兰伯特与兰伯特

    高光反射公式:

    Specular = 直射光*pow(max(cosθ,0),高光的参数)
    

    这里的θ是指反射光与反射点到相机方向的夹角。


    示意图

    Blinn-Phong高光模型,公式是计算是不变的,这里的θ是上面夹角的一半。也就是反射光与反射点到相机方向的夹角的一半。这里求一个夹角的的cos,是先求出平分线,直接把两个向量相加然后再单位化就是平分线向量。

    相关文章

      网友评论

          本文标题:Shader笔记-光照模型

          本文链接:https://www.haomeiwen.com/subject/plgcsxtx.html