Shader笔记-光照模型

2017-12-11  本文已影响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,是先求出平分线,直接把两个向量相加然后再单位化就是平分线向量。

上一篇下一篇

猜你喜欢

热点阅读