zoukankan      html  css  js  c++  java
  • Unity-Shader-光照模型之漫反射

    【旧博客转移 - 2016年4月3日 23:27】

    前面的话:

    在现实生活中,我们看见能看见的东西都是光反射出来的颜色,如果反射光太弱,或者没有进入你的视角范围,你看到的就是黑色的。
    在游戏中光分为几种,平行光源(太阳光),点光源(灯泡)等等,最常用的是Directional light(平行光源)。
    当然在计算机中光不过是一些数据罢了,
    方向,颜色,亮度就可以决定一个平行光源
     

    漫反射光照:

    漫反射是是投射在粗糙表面上的光向各个方向反射的现象,根据入射光线与此点的法线来决定此点的反射强度,
    用ShaderLab书上的公式表达就是
    Lum = C * max(0, cos<L, N>)
    C:到达此点光线的强度和颜色
    N:法线
    L:单位长度(标准化)的入射光向量
     
    Shader "lijia/Diffcue"
    {
        Properties
        {
            _MainTex ("Texture", 2D) = "white" {}
        }
        SubShader
        {
            Tags { "RenderType"="Opaque" }
            LOD 100
    
            Pass
            {
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
    
                #include "UnityCG.cginc"
    
                struct v2f
                {
                    float2 uv : TEXCOORD0;
                    float4 vertex : SV_POSITION;
                    float3 normal : TEXCOORD1;
                    float3 lightDir : TEXCOORD2;
                };
    
                sampler2D _MainTex;
                float4 _MainTex_ST;
    
                float4 _LightColor0;
    
                v2f vert (appdata_full v)
                {
                    v2f o;
                    o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
                    o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
                    o.normal = v.normal;
                    o.lightDir = ObjSpaceLightDir(v.vertex);//把光向量从世界空间转成模型空间
                    return o;
                }
    
                fixed4 frag (v2f i) : SV_Target
                {
                    float3 L = normalize(i.lightDir);
                    float3 N = normalize(i.normal);
                    fixed4 col = tex2D(_MainTex, i.uv);
                    float diff = max(0, dot(N, L)) * _LightColor0.rgb + UNITY_LIGHTMODEL_AMBIENT;//加上环境光
                    return col*diff;
                }
                ENDCG
            }
        }
    }

    这里要注意的是,计算LightDir跟Normal的夹角的时候,一定要保证在同一个坐标空间。有两种方式

    1. 把LightDir转成模型空间
    2. 把Normal转世界空间

    但是把Normal转世界坐标一定要注意,不要用mul(_Object2World, normal)去转,这样如果模型有一些缩放变化就会出现异常。正确的做法是用模型到世界的逆矩阵的转置矩阵。mul(float4(normal, 0), _World2Object);

    漫反射效果:

    适合用在地形,岩石,墙壁等粗糙的物体上,人物可以使用更炫丽的光照计算,比如下一篇要写的 镜面高光和Phong

  • 相关阅读:
    LeetCode Merge Two Sorted Lists 归并排序
    LeetCode Add Binary 两个二进制数相加
    LeetCode Climbing Stairs 爬楼梯
    034 Search for a Range 搜索范围
    033 Search in Rotated Sorted Array 搜索旋转排序数组
    032 Longest Valid Parentheses 最长有效括号
    031 Next Permutation 下一个排列
    030 Substring with Concatenation of All Words 与所有单词相关联的字串
    029 Divide Two Integers 两数相除
    028 Implement strStr() 实现 strStr()
  • 原文地址:https://www.cnblogs.com/lijiajia/p/6861542.html
Copyright © 2011-2022 走看看