开发者社区> jamesjxiao> 正文

学习笔记——基本光照模型简单实现

简介: Lambert光照模型,根据光照向量与顶点发现的夹角来确定光照强度: Shader "James/VP Shader/LightModel-Lambert" { Properties { _MainTex ("MainTex", 2D) = "whi...
+关注继续查看

Lambert光照模型,根据光照向量与顶点发现的夹角来确定光照强度:

Shader "James/VP Shader/LightModel-Lambert" 
{
    Properties 
    {
        _MainTex ("MainTex", 2D) = "white" {}
    }
    SubShader 
    {
        Pass
        {
            Tags { "LightMode"="ForwardBase" }
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            
            float _LightColor0;
            sampler2D _MainTex;
            float4 _MainTex_ST;
            struct v2f
            {
                float4 pos : SV_POSITION;
                float2 uv : TEXCOORD0;
                float3 lightDir : TEXCOORD1;
                float3 normal : TEXCOORD2;
            };
            
            v2f vert(appdata_full v)
            {
                v2f o;
                o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
                o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
                // 从顶点位置到Light的局部向量
                o.lightDir = ObjSpaceLightDir(v.vertex);
                o.normal = v.normal;
                return o;
            }
            
            float4 frag(v2f i) : COLOR
            {
                i.lightDir = normalize(i.lightDir);
                i.normal = normalize(i.normal);
                // 纹理采样
                float4 c = tex2D(_MainTex, i.uv);
                // 光强度,法向和光照方向的cos值
                float diffuse = max(0, dot(i.normal, i.lightDir));
                // 纹理色 * 光源色 * 强度参数
                c = c * _LightColor0 * diffuse;
                return c * 2;
            }
            ENDCG
        }
    } 
    FallBack "Diffuse"
}

Phong光照模型,根据光照向量的反射向量与视线的夹角来计算镜面高光的强度,另外再加上漫射光的成分:

Shader "James/VP Shader/LightModel-Phong" 
{
    Properties 
    {
        _MainTex ("MainTex", 2D) = "white" {}
        _gloss ("Gloss", Float) = 1
    }
    SubShader 
    {
        Pass
        {
            Tags { "LightMode"="ForwardBase" }
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            
            float _LightColor0;
            sampler2D _MainTex;
            float4 _MainTex_ST;
            float _gloss;
            
            struct v2f
            {
                float4 pos : SV_POSITION;
                float2 uv : TEXCOORD0;
                float3 normal : TEXCOORD1;
                float3 lightDir : TEXCOORD2;            // 光照方向
                float3 reflectLightDir : TEXCOORD3;        // 光照反射方向
                float3 viewDir : TEXCOORD4;                // 视线方向
            };
            
            v2f vert(appdata_full v)
            {
                v2f o;
                o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
                o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
                o.normal = v.normal;
                // 从顶点位置到light的局部向量
                o.lightDir = ObjSpaceLightDir(v.vertex);
                // 反射向量,注意需要使用-o.lightDir
                o.reflectLightDir = reflect(-o.lightDir, v.normal);
                // 视线,顶点到camera的局部变量
                o.viewDir = ObjSpaceViewDir(v.vertex);
                return o;
            }
            
            float4 frag(v2f i) : COLOR
            {
                i.normal = normalize(i.normal);
                i.reflectLightDir = normalize(i.reflectLightDir);
                i.viewDir = normalize(i.viewDir);
                // 纹理采样
                float4 c = tex2D(_MainTex, i.uv);
                // 漫射光强度
                float diffuse = max(0, dot(i.normal, i.lightDir));
                // 镜面光强度
                float specular = max(0, dot(i.reflectLightDir, i.viewDir));
                specular = pow(specular, 32) * _gloss;
                // 纹理色 * 光源色 * 强度参数
                c = c * _LightColor0 * (diffuse + specular);
                return c * 2;
            }
            ENDCG
        }
    } 
    FallBack "Diffuse"
}

BinnPhong光照模型,根据光照向量和视线的半角向量,与顶点法线的夹角来计算镜面高光的强度,另外再加上漫射光的成分:

Shader "James/VP Shader/LightModel-BinnPhong" 
{
    Properties 
    {
        _MainTex ("MainTex", 2D) = "white" {}
        _gloss ("Gloss", Float) = 5
    }
    SubShader 
    {
        Pass
        {
            Tags { "LightMode"="ForwardBase" }
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            
            float _LightColor0;
            sampler2D _MainTex;
            float4 _MainTex_ST;
            float _gloss;
            struct v2f
            {
                float4 pos : SV_POSITION;
                float2 uv : TEXCOORD0;
                float3 normal : TEXCOORD1;        
                float3 lightDir : TEXCOORD2;        // 光照方向
            };
            
            v2f vert(appdata_full v)
            {
                v2f o;
                o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
                o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
                o.normal = v.normal;
                // 顶点->light的局部向量
                o.lightDir = ObjSpaceLightDir(v.vertex);
                // 顶点->camera的局部向量
                float3 viewDir = ObjSpaceViewDir(v.vertex);
                return o;
            }
            
            float4 frag(v2f i) : COLOR
            {
                i.lightDir = normalize(i.lightDir);
                i.normal = normalize(i.normal);
                // 半角向量,光照方向和视线的中间值
                float3 halfDir = (i.lightDir + i.normal) * 0.5;
                // 纹理采样
                float4 c = tex2D(_MainTex, i.uv);
                // 漫射光强度
                float diffuse = max(0, dot(i.normal, i.lightDir));
                // 镜面光强度
                float specular = max(0, dot(i.normal, halfDir));
                specular = pow(specular, 32) * _gloss;
                // 纹理色 * 光源色 * 强度参数
                c = c * _LightColor0 * (diffuse + specular);
                return c * 2;
            }
            ENDCG
        }
    } 
    FallBack "Diffuse"
}

BinnPhong比Phong少计算一次反射向量,会更简洁和高效。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
前端知识案例学习4-毛玻璃效果代码实现局部
前端知识案例学习4-毛玻璃效果代码实现局部
12 0
这一篇让你彻底搞懂贝塞尔曲线
贝塞尔曲线不懂画?不知道怎么回事?看这一篇就够了!用图形,点曲线运动图和公式推导,让你彻底搞懂贝塞尔曲线的运行原理!
980 0
Java实现规则几何图形问题求解
Java实现规则几何图形问题求解
72 0
了解 OpenGL ES实现自定义编程粒子效果 思路
本案例旨在于了解OpenGL ES中自定义编程粒子效果的整体实现思路。
104 0
☆打卡算法☆LeetCode 75、颜色分类 算法解析
“给定包含红白蓝颜色的数组,对它们进行排序,使得相同颜色的元素相邻。”
89 0
☆打卡算法☆LeetCode 48、旋转图像 算法解析
“给定一个二维矩阵表示一个图像,将图像顺时针旋转90°,返回旋转后的图像矩阵。”
65 0
☆打卡算法☆LeetCode 85、最大矩形 算法解析
“给定包含0和1的二维矩阵,找出只包含1的最大矩阵,返回其面积。”
97 0
☆打卡算法☆LeetCode 77、组合 算法解析
“给定两个整数nk,返回范围[1,n]中所有可能的k个数的组合。”
79 0
☆打卡算法☆LeetCode 84、柱状图中最大的矩形 算法解析
“给定n个非负整数,用来表示柱状图每个柱子的高度,求柱状图中最大的矩形的面积。”
55 0
☆打卡算法☆LeetCode 6、Z字形变换 算法解析
“将给定的字符串以给定的行数记性Z字形排列。”
49 0
【Unity3D 灵巧小知识点】 ☀️ | 获取某个游戏对象下的所有子物体
Unity 小科普 老规矩,先介绍一下 Unity 的科普小知识: Unity是 实时3D互动内容创作和运营平台 。 包括游戏开发、美术、建筑、汽车设计、影视在内的所有创作者,借助 Unity 将创意变成现实。 Unity 平台提供一整套完善的软件解决方案,可用于创作、运营和变现任何实时互动的2D和3D内容,支持平台包括手机、平板电脑、PC、游戏主机、增强现实和虚拟现实设备。
323 0
手把手教你绘制类图 | 带你学《Java面向对象编程》之七十一
类图是让人能够直观了解类的一种表现形式,本节将手把手带你使用PowerDesigner绘制类图。
955 0
旋转跳跃-学会操作String类数据 | 带你学《Java面向对象编程》之二十七
本节将带领读者完成对字符串数据之间的比较,并为读者介绍了字符串常量的概念与比较字符串数据的注意事项。
1257 0
第二十一章:变换(十四)
3D-ish旋转 即使计算机屏幕是平面和二维的,也可以在这些屏幕上绘制视觉对象,使其具有第三维的外观。 在本章的前面,您看到了一些文本效果,它们提供了第三个维度的提示,而Xamarin.Forms支持两个额外的旋转,名为RotationX和RotationY,它们似乎也突破了屏幕固有的二维平面度。
1236 0
+关注
jamesjxiao
游戏领域耕耘者~
文章
问答
视频
相关电子书
更多
骨骼动画实践
立即下载
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载