[Unity Shader] 逐顶点光照和逐片元光照

  书中的6.4节讲的是漫反射的逐顶点光照和逐片元光照。

  前一种算法是根据漫反射公式计算顶点颜色(顶点着色器),对颜色插值(光栅化过程)返回每个像素的颜色值(片元着色器)。

  第二种算法是获得顶点的法线(顶点着色器),对法线插值(光栅化过程),根据漫反射公式计算像素颜色(片元着色器)。

  注:漫反射公式:(光源颜色 * 材质漫反射颜色)* (表面法线矢量 · 表面到光源的矢量)

  书中对上两种算法的实现如下:

 1 Shader "Unity Shaders Book/Chapter 6/Diffuse Vertex Level"
 2 {
 3     Properties
 4     {
 5         _Diffuse("Diffuse", Color) = (1.0, 1.0, 1.0, 1.0)
 6     }
 7     SubShader
 8     {
 9         Pass
10         {
11             Tags { "LightMode"="ForwardBase" }
12
13             CGPROGRAM
14
15             #pragma vertex vert
16             #pragma fragment frag
17
18             #include "Lighting.cginc"
19
20             fixed4 _Diffuse;
21
22             struct a2v
23             {
24                 float4 vertex : POSITION;
25                 float3 normal : NORMAL;
26             };
27
28             struct v2f
29             {
30                 float4 pos : SV_POSITION;
31                 fixed3 color : COLOR;
32             };
33
34             v2f vert (a2v v)
35             {
36                 v2f o;
37                 o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
38                 fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
39                 fixed3 worldNormal = normalize(mul(v.normal, (float3x3)_World2Object));
40                 fixed3 worldLight = normalize(_WorldSpaceLightPos0.xyz);
41                 fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal, worldLight));
42                 o.color = ambient + diffuse;
43
44                 return o;
45             }
46
47             fixed4 frag(v2f i) : SV_Target
48             {
49                 return fixed4(i.color, 1.0);
50             }
51
52             ENDCG
53         }
54     }
55
56     Fallback "Diffuse"
57 }

逐顶点光照

 1 Shader "Unity Shaders Book/Chapter 6/Diffuse Pixel Level"
 2 {
 3     Properties
 4     {
 5         _Diffuse("Diffuse", Color) = (1.0, 1.0, 1.0, 1.0)
 6     }
 7     SubShader
 8     {
 9         Pass
10         {
11             Tags { "LightMode"="ForwardBase" }
12
13             CGPROGRAM
14
15             #pragma vertex vert
16             #pragma fragment frag
17
18             #include "Lighting.cginc"
19
20             fixed4 _Diffuse;
21
22             struct a2v
23             {
24                 float4 vertex : POSITION;
25                 float3 normal : NORMAL;
26             };
27
28             struct v2f
29             {
30                 float4 pos : SV_POSITION;
31                 fixed3 worldNormal : TEXCOORD0;
32             };
33
34             v2f vert (a2v v)
35             {
36                 v2f o;
37                 o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
38                 o.worldNormal = mul(v.normal, (float3x3)_World2Object);
39                 return o;
40             }
41
42             fixed4 frag(v2f i) : SV_Target
43             {
44                 fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
45                 fixed3 worldNormal = normalize(i.worldNormal);
46                 fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
47                 fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal, worldLightDir));
48                 fixed3 color = ambient + diffuse;
49                 return fixed4(color.rgb, 1.0);
50             }
51
52             ENDCG
53         }
54     }
55
56     Fallback "Diffuse"
57 }

逐片元光照

 

  刚开始看这两段代码有点懵,觉得并没有什么区别,不理解为什么将漫反射的计算挪到片元着色器中就能区别上面两种算法。

  查了一些帖子了解到,顶点着色器是对每个顶点数据进行处理的,包括空间转换和颜色计算等,并不是对每个像素进行处理。而片元着色器有时又叫做像素着色器,它是对每个片元处理一次。片元着色器得到的片元数据(像素数据),是在光栅化过程中对顶点数据进行插值得到的,并不只是顶点数据,

  “属性插值的方法可以得到片元的颜色、法向量、深度值、纹理坐标等。”(https://wenku.baidu.com/view/219ecc7daef8941ea66e0519.html?pn=50NaN),即在片元着色器中使用的法线数据,其实已经是插值后的,因此在片元着色器中计算漫反射时,使用的就是逐片元光照的算法。这也是为什么逐片元光照会比逐顶点光照效率低的原因(计算漫反射的次数更多)。

  “但是,由于逐顶点光照依赖于线性插值来得到像素光照,因此,当光照模型中有非线性的计算(例如计算高光反射时)时,逐顶点光照就会出问题。而且,由于逐顶点光照会在渲染图元内部对顶点颜色进行插值,这会导致渲染图元内部的颜色总是暗于顶点处的最高颜色值,这在某些情况下会产生明显的棱角现象。”

时间: 2024-10-24 17:53:15

[Unity Shader] 逐顶点光照和逐片元光照的相关文章

【Unity Shader】(七) ------ 复杂的光照(下)

笔者使用的是 Unity 2018.2.0f2 + VS2017,建议读者使用与 Unity 2018 相近的版本,避免一些因为版本不一致而出现的问题.              [Unity Shader](三)------ 光照模型原理及漫反射和高光反射的实现         [Unity Shader](四)------ 纹理之法线纹理.单张纹理和遮罩纹理的实现              [Unity Shader](五) ------ 透明效果之半透明效果的原理及实现          

unity shader base pass and additional pass

[Unity Shaders]Shader中的光照,shadersshader 写在前面 自己写过Vertex & Fragment Shader的童鞋,大概都会对Unity的光照痛恨不已.当然,我相信这是因为我们写得少...不过这也是由于官方文档对这方面介绍很少的缘故,导致我们无法自如地处理很多常见的光照变量.这篇我们就来讨论下Unity内置的一些光照变量和函数到底怎么用. 以下内容均建立在Forward Rendering Path的基础上. 自己总结的,如果有硬伤一定要告诉我啊!感激不尽~

【Unity Shader】(八) ------ 高级纹理(上)

笔者使用的是 Unity 2018.2.0f2 + VS2017,建议读者使用与 Unity 2018 相近的版本,避免一些因为版本不一致而出现的问题.    [Unity Shader](三) ------ 光照模型原理及漫反射和高光反射的实现    [Unity Shader](四) ------ 纹理之法线纹理.单张纹理及遮罩纹理的实现    [Unity Shader](五) ------ 透明效果之半透明效果的实现及原理    [Unity Shader](六) ------ 复杂的光

【Unity Shader】(九) ------ 高级纹理之渲染纹理及镜子与玻璃效果的实现

笔者使用的是 Unity 2018.2.0f2 + VS2017,建议读者使用与 Unity 2018 相近的版本,避免一些因为版本不一致而出现的问题. [Unity Shader](三) ------ 光照模型原理及漫反射和高光反射的实现 [Unity Shader](四) ------ 纹理之法线纹理.单张纹理及遮罩纹理的实现 [Unity Shader](五) ------ 透明效果之半透明效果的实现及原理 [Unity Shader](六) ------ 复杂的光照(上) [Unity

Unity Shader入门精要学习笔记 - 第6章 开始 Unity 中的基础光照

转自冯乐乐的<Unity Shader入门精要> 通常来讲,我们要模拟真实的光照环境来生成一张图像,需要考虑3种物理现象. 首先,光线从光源中被发射出来. 然后,光线和场景中的一些物体相交:一些光线被物体吸收了,而另一些光线被散射到其他方向. 最后,摄像机吸收了一些光,产生了一张图像. 在光学中,我们使用辐照度来量化光.对于平行光来说,它的辐照度可通过计算在垂直于l的单位面积上单位时间内穿过的能量来得到.在计算光照模型时,我们需要知道一个物体表面的辐照度,而物体表面往往是和l不垂直的,我们可以

【我的书】Unity Shader的书 — 目录(2015.09.04更新)

写在前面 感谢所有点进来看的朋友.没错,我目前打算写一本关于Unity Shader的书. 出书的目的有下面几个: 总结我接触Unity Shader以来的历程,给其他人一个借鉴.我非常明白学Shader的艰难,在群里也见了很多人提出的问题.我觉得学习Shader还是一件有规律可循的事情,但问题是中文资料难觅,而大家又不愿意去看英文...这对我有什么好处呢?强迫我对知识进行梳理,对细节问题把握更清楚. 第二个原因你懂的. 关于本书的定位问题: 面向Unity Shader初学者,但要: 有一定的

【我的书】Unity Shader的书 — 目录(2016.1.29更新)

写在前面 感谢所有点进来看的朋友.没错,我目前打算写一本关于Unity Shader的书. 出书的目的有下面几个: 总结我接触Unity Shader以来的历程,给其他人一个借鉴.我非常明白学Shader的艰难,在群里也见了很多人提出的问题.我觉得学习Shader还是一件有规律可循的事情,但问题是中文资料难觅,而大家又不愿意去看英文...这对我有什么好处呢?强迫我对知识进行梳理,对细节问题把握更清楚. 第二个原因你懂的. 关于本书的定位问题: 面向Unity Shader初学者,但要: 有一定的

【我的书】Unity Shader的书 — 文件夹(2015.12.21更新)

写在前面 感谢全部点进来看的朋友.没错.我眼下打算写一本关于Unity Shader的书. 出书的目的有以下几个: 总结我接触Unity Shader以来的历程,给其它人一个借鉴.我非常明确学Shader的艰难,在群里也见了非常多人提出的问题. 我认为学习Shader还是一件有规律可循的事情,但问题是中文资料难觅,而大家又不愿意去看英文...这对我有什么优点呢?强迫我对知识进行梳理,对细节问题把握更清楚. 第二个原因你懂的. 关于本书的定位问题: 面向Unity Shader刚開始学习的人,但要

Unity Shader入门精要读书笔记(一)序章

本系列的博文是笔者读<Unity Shader入门精要>的读书笔记,这本书的章节框架是: 第一章:着手准备. 第二章:GPU流水线. 第三章:Shader基本语法. 第四章:Shader数学基础. 第五章:利用简单的顶点/片元着色器来实现辅助技巧. 第六章:基本光照模型. 第七章:法线纹理.遮罩纹理等基础纹理. 第八章:透明度测试和透明度混合. 第九章:复杂光照实现. 第十章:高级纹理(立方体纹理等). 第十一章:纹理动画.顶点动画. 第十二章:屏幕特效. 第十三章:深度纹理. 第十四章:非真