zoukankan      html  css  js  c++  java
  • Phong光照模型的Shader实现

    计算反射向量

    Phong用到的是反射向量,计算反射向量的公式是
    R = 2*N(dot(N, L)) - L
    这个公式是根据向量的投影公式以及平行四边形法则推导出来的
    详细步骤请看这篇文章,讲的非常好
     
    Shader "Phong"
    {
        Properties
        {
            _MainTex ("Texture", 2D) = "white" {}
            _Specular("Specular", Range(1, 20)) = 1
            _SpecColor("SpecColor", Color) = (1,1,1,1)
        }
        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;
                    float4 objPos : TEXCOORD3;
                };
    
                sampler2D _MainTex;
                float4 _MainTex_ST;
    
                float4 _LightColor0;
    
                float _Specular;
                float4 _SpecColor;
    
                v2f vert (appdata_full v)
                {
                    v2f o;
                    o.objPos = v.vertex;
                    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);
                    float3 viewDir = normalize(ObjSpaceViewDir(i.objPos));//计算出视线
    
                    float diff = saturate(dot(L, N));
                    float3 reflection = normalize(2.0 * N * diff - L);//反射向量
                    float spec = pow(max(0, dot(reflection, viewDir)), _Specular);
                    float3 finalSpec = _SpecColor.rgb * spec;
                    //漫反射+镜面高光+环境光
                    float3 finalLight = diff * _LightColor0 + finalSpec + UNITY_LIGHTMODEL_AMBIENT;
    
                    fixed4 col = tex2D(_MainTex, i.uv);
                    return col * float4(finalLight, 1);
                }
                ENDCG
            }
        }
    }

    Blinn-phong光照模型

    blinn是一个人的名字,他叫吉姆·布林,图形学界的大牛,他发现了使用半角向量代替反射向量的计算方式
    原理是通过视线向量跟光向量的半角向量代替反射向量
    halfVector = normalize( L + V );
     
    http://blog.csdn.net/herox25000/article/details/50491483



    求反射向量

    
    

    在图形学中,计算光照模型时,经常需要求取反射向量,一般的shader函数库都提供计算反射向量的方法,下面介绍一下如何手动计算反射向量。

    给定入射光线向量I和平面法向量N,求反射向量R,如下图。为了方便计算,这里假定I和N都是单位向量(模为1,编程时可先将I和N单位化)

    方法一

    设入射光线向量I和反射平面的法向量N之间的夹角为theta。连接I的始端和R的末端,则有

    R = 2P - I              (1)

    现在问题变成了如何求取P,设入射点0到P与N的交点的向量为S,那么有

    P = I + S               (2)

    现在问题变成了如何求取向量S,向量S即向量-N(注意,这里是-N,因为S和N的方向相反。)在向量N上的投影,根据向量的投影公式有

    因为N是单位向量,简化一下得到

    将S代入公式(2),再将P代入公式(1)得到

    方法二

    将R平移一下,与向量N的延长线相交。

    由于入射角和反射角相等,且I和R的长度也相等,所以三角形ION是等腰三角形。故有

    ON = 2S

    所以有

    R = I + 2S

    而S是-I在N上的投影,所以有

    由于N是单位向量,简化一下得到

    所以

    貌似方法二更直观些。

     
  • 相关阅读:
    跃迁方法论 Continuous practice
    EPI online zoom session 面试算法基础知识直播分享
    台州 OJ 2648 小希的迷宫
    洛谷 P1074 靶形数独
    洛谷 P1433 DP 状态压缩
    台州 OJ FatMouse and Cheese 深搜 记忆化搜索
    台州 OJ 2676 Tree of Tree 树状 DP
    台州 OJ 2537 Charlie's Change 多重背包 二进制优化 路径记录
    台州 OJ 2378 Tug of War
    台州 OJ 2850 Key Task BFS
  • 原文地址:https://www.cnblogs.com/alps/p/7629820.html
Copyright © 2011-2022 走看看