书中的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),即在片元着色器中使用的法线数据,其实已经是插值后的,因此在片元着色器中计算漫反射时,使用的就是逐片元光照的算法。这也是为什么逐片元光照会比逐顶点光照效率低的原因(计算漫反射的次数更多)。

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

[Unity Shader] 逐顶点光照和逐片元漫反射光照的更多相关文章

  1. Unity Shader入门精要学习笔记 - 第9章 更复杂的光照

    转载自 冯乐乐的<Unity Shader入门精要> Unity 的渲染路径 在Unity里,渲染路径决定了光照是如何应该到Unity Shader 中的.因此,如果要和光源打交道,我们需 ...

  2. Unity Shader入门精要学习笔记 - 第16章 Unity中的渲染优化技术

    转自冯乐乐的 <Unity Shader 入门精要> 移动平台的特点 为了尽可能一处那些隐藏的表面,减少overdraw(即一个像素被绘制多次),PowerVR芯片(通常用于ios设备和某 ...

  3. unity shader base pass and additional pass

      [Unity Shaders]Shader中的光照,shadersshader 写在前面 自己写过Vertex & Fragment Shader的童鞋,大概都会对Unity的光照痛恨不已 ...

  4. OpenGL光照2:材质和光照贴图

    本文是个人学习记录,学习建议看教程 https://learnopengl-cn.github.io/ 非常感谢原作者JoeyDeVries和多为中文翻译者提供的优质教程 的内容为插入注释,可以先跳过 ...

  5. unity shader入门(二)语义,结构体,逐顶点光照

    下为一个逐顶点漫反射光照shader Shader "study/Chapter6/vertexShader"{ Properties{_Diffuse("Diffuse ...

  6. unity shader入门(三)逐像素光照,Blinn-Phong模型

    与上篇逐顶点光照很像,只是改为在片元着色器中计算光照,下为逐像素光照shader Shader "study/Chapter6/PixelShader"{ Properties{ ...

  7. Unity3D学习(六):《Unity Shader入门精要》——Unity的基础光照

    前言 光学中,我们是用辐射度来量化光. 光照按照不同的散射方向分为:漫反射(diffuse)和高光反射(specular).高光反射描述物体是如何反射光线的,漫反射则表示有多少光线会被折射.吸收和散射 ...

  8. 【Unity Shader】(六) ------ 复杂的光照(上)

    笔者使用的是 Unity 2018.2.0f2 + VS2017,建议读者使用与 Unity 2018 相近的版本,避免一些因为版本不一致而出现的问题.              [Unity Sha ...

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

    转自冯乐乐的<Unity Shader入门精要> 通常来讲,我们要模拟真实的光照环境来生成一张图像,需要考虑3种物理现象. 首先,光线从光源中被发射出来. 然后,光线和场景中的一些物体相交 ...

随机推荐

  1. Apache2.2 + tomcat7 服务器集群配置

    1.软件安装 1.1下载和安装apache Apache 2.2 :http://httpd.apache.org/download.cgi,下载msi安装程序,选择no ssl版本 1.2下载和安装 ...

  2. Ubuntu eclipse安装

    apt-get install eclipse eclipse-cdt eclipse-jdt  # don't include eclipse if you have it already afte ...

  3. galera mariadb集群恢复策略

    1 galera mariadb首先MariaDB是一个数据库,可以看成是MySQL的一个分支,由于MySQL被SUN收购,所以MySQL面临着闭源的风险,当时MySQL之父Widenius并没有加入 ...

  4. DOM、JDOM、DOM4J的区别

    dom是解析xml的底层接口之一(另一种是sax)   而jdom和dom4j则是基于底层api的更高级封装    dom是通用的,而jdom和dom4j则是面向Java语言的       DOM 是 ...

  5. FreeMarker标签使用

    FreeMarker标签使用 模板技术在现代的软件开发中有着重要的地位,主要用于view层的展示,freemarker是比较流行的一种. 一.FreeMarker模板文件主要有4个部分组成 ①文本,直 ...

  6. python and、or以及and-or

    @Python: and.or以及and-or 一.and: 在Python 中,and 和 or 执行布尔逻辑演算,如你所期待的一样,但是它们并不返回布尔值:而是,返回它们实际进行比较的值之一. & ...

  7. [Violet]天使玩偶/SJY摆棋子

    题目 \(KD-tree\)做最近点对的复杂度好像是假的吧,怎么看也看不出来是\(O(\sqrt{n})\)啊 首先\(KD-tree\)长得和平衡树还是很像的,每个节点都存储了一个\(k\)维空间上 ...

  8. 【bzoj 4589】Hard Nim

    题目 根据我为数不多的博弈知识我发现需要求多少种方案使得异或和为\(0\) 非常显然就是构造出那个质数多项式\(F\),答案就是\(F^n(0)\),当然这里是异或卷积 于是美滋滋的敲上去一个多项式快 ...

  9. React 入门学习笔记2

    摘自阮一峰:React入门实例教程,转载请注明出处. 一.获取真实的DOM节点 组件并不是真实的 DOM 节点,而是存在于内存之中的一种数据结构,叫做虚拟 DOM (virtual DOM).只有当它 ...

  10. boost::bind 学习

    最近学习了太多与MacOS与Iphone相关的东西,因为不会有太多人有兴趣,学习的平台又是MacOS,不太喜欢MacOS下的输入法,所以写下来的东西少了很多.    等我学习的东西慢慢的与平台无关的时 ...