[Unity Shader] 逐顶点光照和逐片元漫反射光照
书中的6.4节讲的是漫反射的逐顶点光照和逐片元光照。
前一种算法是根据漫反射公式计算顶点颜色(顶点着色器),对颜色插值(光栅化过程)返回每个像素的颜色值(片元着色器)。
第二种算法是获得顶点的法线(顶点着色器),对法线插值(光栅化过程),根据漫反射公式计算像素颜色(片元着色器)。
注:漫反射公式:(光源颜色 * 材质漫反射颜色)* (表面法线矢量 · 表面到光源的矢量)
书中对上两种算法的实现如下:
Shader "Unity Shaders Book/Chapter 6/Diffuse Vertex Level"
{
Properties
{
_Diffuse("Diffuse", Color) = (1.0, 1.0, 1.0, 1.0)
}
SubShader
{
Pass
{
Tags { "LightMode"="ForwardBase" } CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "Lighting.cginc" fixed4 _Diffuse; struct a2v
{
float4 vertex : POSITION;
float3 normal : NORMAL;
}; struct v2f
{
float4 pos : SV_POSITION;
fixed3 color : COLOR;
}; v2f vert (a2v v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
fixed3 worldNormal = normalize(mul(v.normal, (float3x3)_World2Object));
fixed3 worldLight = normalize(_WorldSpaceLightPos0.xyz);
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal, worldLight));
o.color = ambient + diffuse; return o;
} fixed4 frag(v2f i) : SV_Target
{
return fixed4(i.color, 1.0);
} ENDCG
}
} Fallback "Diffuse"
}
逐顶点光照
Shader "Unity Shaders Book/Chapter 6/Diffuse Pixel Level"
{
Properties
{
_Diffuse("Diffuse", Color) = (1.0, 1.0, 1.0, 1.0)
}
SubShader
{
Pass
{
Tags { "LightMode"="ForwardBase" } CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "Lighting.cginc" fixed4 _Diffuse; struct a2v
{
float4 vertex : POSITION;
float3 normal : NORMAL;
}; struct v2f
{
float4 pos : SV_POSITION;
fixed3 worldNormal : TEXCOORD0;
}; v2f vert (a2v v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.worldNormal = mul(v.normal, (float3x3)_World2Object);
return o;
} fixed4 frag(v2f i) : SV_Target
{
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal, worldLightDir));
fixed3 color = ambient + diffuse;
return fixed4(color.rgb, 1.0);
} ENDCG
}
} Fallback "Diffuse"
}
逐片元光照

刚开始看这两段代码有点懵,觉得并没有什么区别,不理解为什么将漫反射的计算挪到片元着色器中就能区别上面两种算法。
查了一些帖子了解到,顶点着色器是对每个顶点数据进行处理的,包括空间转换和颜色计算等,并不是对每个像素进行处理。而片元着色器有时又叫做像素着色器,它是对每个片元处理一次。片元着色器得到的片元数据(像素数据),是在光栅化过程中对顶点数据进行插值得到的,并不只是顶点数据,
“属性插值的方法可以得到片元的颜色、法向量、深度值、纹理坐标等。”(https://wenku.baidu.com/view/219ecc7daef8941ea66e0519.html?pn=50NaN),即在片元着色器中使用的法线数据,其实已经是插值后的,因此在片元着色器中计算漫反射时,使用的就是逐片元光照的算法。这也是为什么逐片元光照会比逐顶点光照效率低的原因(计算漫反射的次数更多)。
“但是,由于逐顶点光照依赖于线性插值来得到像素光照,因此,当光照模型中有非线性的计算(例如计算高光反射时)时,逐顶点光照就会出问题。而且,由于逐顶点光照会在渲染图元内部对顶点颜色进行插值,这会导致渲染图元内部的颜色总是暗于顶点处的最高颜色值,这在某些情况下会产生明显的棱角现象。”

[Unity Shader] 逐顶点光照和逐片元漫反射光照的更多相关文章
- Unity Shader入门精要学习笔记 - 第9章 更复杂的光照
转载自 冯乐乐的<Unity Shader入门精要> Unity 的渲染路径 在Unity里,渲染路径决定了光照是如何应该到Unity Shader 中的.因此,如果要和光源打交道,我们需 ...
- Unity Shader入门精要学习笔记 - 第16章 Unity中的渲染优化技术
转自冯乐乐的 <Unity Shader 入门精要> 移动平台的特点 为了尽可能一处那些隐藏的表面,减少overdraw(即一个像素被绘制多次),PowerVR芯片(通常用于ios设备和某 ...
- unity shader base pass and additional pass
[Unity Shaders]Shader中的光照,shadersshader 写在前面 自己写过Vertex & Fragment Shader的童鞋,大概都会对Unity的光照痛恨不已 ...
- OpenGL光照2:材质和光照贴图
本文是个人学习记录,学习建议看教程 https://learnopengl-cn.github.io/ 非常感谢原作者JoeyDeVries和多为中文翻译者提供的优质教程 的内容为插入注释,可以先跳过 ...
- unity shader入门(二)语义,结构体,逐顶点光照
下为一个逐顶点漫反射光照shader Shader "study/Chapter6/vertexShader"{ Properties{_Diffuse("Diffuse ...
- unity shader入门(三)逐像素光照,Blinn-Phong模型
与上篇逐顶点光照很像,只是改为在片元着色器中计算光照,下为逐像素光照shader Shader "study/Chapter6/PixelShader"{ Properties{ ...
- Unity3D学习(六):《Unity Shader入门精要》——Unity的基础光照
前言 光学中,我们是用辐射度来量化光. 光照按照不同的散射方向分为:漫反射(diffuse)和高光反射(specular).高光反射描述物体是如何反射光线的,漫反射则表示有多少光线会被折射.吸收和散射 ...
- 【Unity Shader】(六) ------ 复杂的光照(上)
笔者使用的是 Unity 2018.2.0f2 + VS2017,建议读者使用与 Unity 2018 相近的版本,避免一些因为版本不一致而出现的问题. [Unity Sha ...
- Unity Shader入门精要学习笔记 - 第6章 开始 Unity 中的基础光照
转自冯乐乐的<Unity Shader入门精要> 通常来讲,我们要模拟真实的光照环境来生成一张图像,需要考虑3种物理现象. 首先,光线从光源中被发射出来. 然后,光线和场景中的一些物体相交 ...
随机推荐
- [BJOI2019] 排兵布阵
题目 这个\(dp\)出在普及都算水题吧 直接背包,\(O(nms)\)跑不满,非常稳 #include<cstdio> #include<vector> #include&l ...
- BZOJ2694:Lcm——包看得懂/看不懂题解
http://www.lydsy.com/JudgeOnline/problem.php?id=2694 Description 对于任意的>1的n gcd(a, b)不是n^2的倍数 也就是说 ...
- A NB群友 【记忆化搜索】(2019年华南理工大学程序设计竞赛(春季赛))
冲鸭!去刷题:https://ac.nowcoder.com/acm/contest/625/A 题目描述 CC是著名的算法竞赛选手,他不仅人长得帅,而且技术了得,自然而然就有了许多粉丝. 为了能帮助 ...
- POJ 3294 Life Forms [最长公共子串加强版 后缀数组 && 二分]
题目:http://poj.org/problem?id=3294 Life Forms Time Limit: 5000MS Memory Limit: 65536K Total Submiss ...
- ping不通linux服务器排查
很久没启动linux了,今天打开试了下 ssh root@192.168.229.128 ping 一直超时 老规矩挨着来排查 检查网络设备器改为Net 模式 重启网络服务 service netw ...
- Oracle(二)SELECT语句执行顺序
转载自:小强斋太-Study Notes,原文链接 从join on和where执行顺序认识T-SQL查询处理执行顺序 目录 一.样例 二.SELECT语句的处理过程 1. FROM阶段 2. WHE ...
- [图解tensorflow源码] [转载] tensorflow设备内存分配算法解析 (BFC算法)
转载自 http://weibo.com/p/1001603980563068394770 @ICT_吴林阳 tensorflow设备内存管理模块实现了一个best-fit with coales ...
- 原生JavaScript技巧大收集
原生JavaScript技巧大收集 地址:http://itindex.net/detail/47244-javascript
- pH计
pH计 测量原理 pH计主要用于测量液体中的氢离子浓度.准确地说是测量氢离子活性,得出酸性.中性还是碱性的数值,在自来水.河水.饮料.食品.污水.医疗和化工等领域广泛地使用工业用液体分析仪. pH计原 ...
- Centos 模拟生成文件的脚本
#!/bin/sh count= #控制每秒写入不同大小的文件 while true do ;i<=$count;i++)) do /bin/-`.jpg done ;i<=$count; ...