Unity Shader 笔记

问答题
  • 什么是渲染流水线? P6
    《Real-Time Rendering, Third Edition》一书中将一个渲染流程分为3个阶段:应用阶段、几何阶段、光栅化阶段。
    1)应用阶段:
    在这一阶段中,开发者有3个主要任务。首先准备好场景数据集,例如摄像机、光源等;其次,为了提高渲染性能,往往需要做一个粗粒度剔除,把不可见的物体剔除出去;最后,需要设置好每个模型的渲染状态,包括但不限于材质、纹理、shader等。这一阶段最重要的输出是渲染所需的几何信息,即渲染图元。由于该阶段由开发者主导,因此应用阶段的流水线化是由开发者决定的。这一阶段主要在CPU上进行。
    2)几何阶段
    几何阶段用于处理所有和我们要绘制的几何体相关的事情。例如决定绘制的图元是什么,怎样绘制它们,这一阶段主要是在GPU上进行。几何阶段负责和每个渲染图元打交道,进行逐顶点、逐多边形的操作。几何阶段的一个重要任务就是把顶点坐标变换到屏幕空间中,再交给光栅器进行处理。通过对输入的渲染图元进行多步处理后,这一阶段将会输出屏幕空间的二维顶点坐标、每个顶点对应的深度值、着色相关信息,并传递给下一个阶段。
    3)光栅化阶段
    这一阶段将会使用上个阶段传递的数据来产生屏幕上的像素,并渲染出最终的图像。这一阶段也是在GPU上运行。光栅化的任务主要是决定每个渲染图元中哪些像素应该被绘制在屏幕上,它需要对上一阶段得到的逐顶点数据(例如顶点颜色)进行插值,然后再进行逐像素处理。

  • 什么是Early-Z技术?它可能出现的问题 P17
    这是一个将深度测试提携到片元着色器之前的操作。回顾一下图像渲染的步骤,首先对顶点进行坐标变换等操作,然后对包含在三个顶点空间内的片元进行深度插值等操作,然后进行片元着色器操作,最后进行逐片元操作,逐片元操作包括模版测试、深度测试等。但是这里出了一个问题,当多个图形叠加在一起的时候,被遮住的部分其实是不用渲染并显示在屏幕上的,但是在之前片元着色器部分已经计算出了数据,这对GPU来说是很大的资源浪费,所以把深度测试提升到片元着色器之前,直接对深度大的被遮住的片元进行舍弃操作,就能减少GPU资源浪费,这便是Early-Z技术。
    但是其检测结果可能会与片元着色器中的一些操作冲突。例如在片元着色器进行了透明度测试,而这个片元没有通过透明度测试,则我们会在着色器中手动调用API将其舍弃,这就导致GPU无法提前执行各种测试。因此,现代的GPU会判断片元着色器中的操作是否跟提前测试发生冲突,如果有冲突则禁用提前测试,这会导致更多片元被处理,因而透明度测试会导致性能下降。

  • 什么是Shader? P23
    1)GPU流水线上一些可高度编程的阶段,而由着色器编译出来的最终代码是会在GPU上运行的。
    2)有一些特定类型的着色器,如顶点着色器、片元着色器等。
    3)依靠着着色器我们可以控制流水线中的渲染细节,例如用顶点着色器来进行顶点变换以及传递数据,用片元着色器来进行逐像素的渲染。
    ~总的来说,它其实就是渲染流水线中的某些特定阶段,例如顶点着色器阶段、片元着色器阶段。

  • 什么是ShaderLab? P28
    Unity Shader是Unity为开发者提供的高层级的渲染抽象层,在Unity中,所有的Unity Shader都是使用ShaderLab来编写的。ShaderLab是Unity提供的编写Unity Shader的一种说明性语言。

  • 如何选择Unity Shader形式? P36
    1)固定函数着色器已经差不多被抛弃了。
    2)如何你想跟各种光源打交道,你可能更喜欢使用表面着色器,但需要小心它在移动平台的性能表现。
    3)如果你需要使用的光照数目非常少,例如只有一个平行光,那么使用顶点/片元着色器是一个更好的选择。
    4)最重要的是,如果你有很多自定义的渲染效果,那么请选择顶点/片元着色器。

  • Unity Shader和Cg/HLSL之间的关系 P37
    正如我们之前所讲,Unity Shader是用ShaderLab语言编写的,但对于表面着色器和顶点/片元着色器,我们可以在ShaderLab内部嵌套Cg/HLSL语言来编写这些着色器代码。这些Cg/HLSL代码是嵌套在CGPROGRAM和ENDCG之间的,正如我们之前看到的示例代码一样。由于Cg和DX9风格的HLSL从写法上来说几乎是同一种语言,因此在Unity立Cg和HLSL是等价的。我们可以说,Cg/HLSL代码是区别于ShaderLab的另一个世界。

  • 矢量点积跟叉积 P49
    1)矢量点积
    点积公式一: a ⋅ b = ( x 1 , y 1 , z 1 ) ⋅ ( x 2 , y 2 , z 2 ) = x 1 x 2 + y 1 y 2 + z 1 z 2 a·b = (x1,y1,z1)·(x2,y2,z2) = x1x2+y1y2+z1z2 ab=(x1,y1,z1)(x2,y2,z2)=x1x2+y1y2+z1z2
    点积公式二: a ⋅ b = ∣ a ∣ ∣ b ∣ c o s θ a·b = |a||b|cos\theta ab=abcosθ
    结果为标量,没有方向
    2)矢量叉积
    叉积公式: a × b = ( x 1 , y 1 , z 1 ) × ( x 2 , y 2 , z 2 ) = ( y 1 z 2 − z 1 y 2 , z 1 x 2 − x 1 z 2 , x 1 y 2 − y 1 x 2 ) a\times b = (x1,y1,z1)\times (x2,y2,z2)=(y1z2-z1y2, z1x2-x1z2,x1y2-y1x2) a×b=(x1,y1,z1)×(x2,y2,z2)=(y1z2z1y2,z1x2x1z2,x1y2y1x2)
    叉积的模: ∣ a × b ∣ = ∣ a ∣ ∣ b ∣ s i n θ |a\times b| = |a||b|sin\theta a×b=absinθ,刚好是平行四边形面积
    叉积结果为矢量,方向为垂直于 a , b a, b a,b的单位矢量

  • 顶点着色器第一步顶点变换如何实现? P73
    1)顶点变换的第一步,就是将顶点坐标从模型空间变换到世界空间中。这个变换通常叫做模型变换。主要是通过模型空间的顶点坐标在世界空间中的变换得到模型空间到世界空间的变换矩阵,变换顺序为缩放,旋转,平移。
    2)顶点变换的第二步,就是将顶点坐标从世界空间变换到观察空间中。这个变换通常叫做观察变换。因为不需要缩放,所以可以通过另一种思路,把摄像机直接反向移动到世界坐标远点,并对Z轴去反。

  • 顶点裁剪是如何做到的? P78
    裁剪空间是由视锥体决定的。视锥体有两种类型:一种是正交投影,一种是透视投影。其中视锥体6块裁剪平面中,近裁剪平面和远裁剪平面比较特殊。
    1)对于透视投影,可以调整视锥体竖直方向的张开角度 F O V FOV FOV、近裁剪平面距离 N e a r Near Near和远裁剪平面距离 F a r Far Far,而当前摄像机横纵比 A s p e c t Aspect Aspect则比较确定。最终投影矩阵为:
    M f r u s t u m = [ c o t F O V 2 A s p e c t 0 0 0 0 c o t F O V 2 0 0 0 0 − F a r + N e a r F a r − N e a r − 2 ⋅ N e a r ⋅ F a r F a r − N e a r 0 0 − 1 0 ] M_{frustum} = \left[ \begin{matrix} \frac{cot\frac{FOV}{2}}{Aspect} & 0 & 0 & 0 \\ 0 & cot\frac{FOV}{2} & 0 & 0 \\ 0 & 0 & -\frac{Far+Near}{Far-Near} & -\frac{2·Near·Far}{Far-Near}\\ 0 & 0 & -1 & 0 \\ \end{matrix} \right] Mfrustum=Aspectcot2FOV0000cot2FOV0000FarNearFar+Near100FarNear2NearFar0
    2)对于正交投影,可以调整锥体竖直方向上高度的一半、近裁剪平面距离 N e a r Near Near和远裁剪平面距离 F a r Far Far,而当前摄像机横纵比 A s p e c t Aspect Aspect则比较确定。最终投影矩阵为:
    M o r t h o = [ 1 A s p e c t ⋅ S i z e 0 0 0 0 1 S i z e 0 0 0 0 − 2 F a r − N e a r − F a r + N e a r F a r − N e a r 0 0 0 1 ] M_{ortho} = \left[ \begin{matrix} \frac{1}{Aspect·Size} & 0 & 0 & 0 \\ 0 & \frac{1}{Size} & 0 & 0 \\ 0 & 0 & -\frac{2}{Far-Near} & -\frac{Far+Near}{Far-Near} \\ 0 & 0 & 0 & 1 \\ \end{matrix} \right] Mortho=AspectSize10000Size10000FarNear2000FarNearFar+Near1

  • 一个顶点如何从模型空间变换到屏幕坐标? P85
    ~顶点着色器的最基本的任务就是把顶点坐标从模型空间转换到裁剪空间中。
    1)顶点在模型空间通过模型变换到达世界空间,主要是通过变换矩阵(缩放、旋转、平移)。
    2)顶点在世界空间通过观察变换到达观察空间,可以按照将摄像机(旋转、平移)到世界坐标原点得到,注意Z轴去反。
    3)顶点在观察空间通过投影变换到达裁剪空间,2D游戏主要用正交投影,3D游戏主要用透视投影,投影之后判断顶点是否在裁剪空间内。
    4)顶点在裁剪空间通过屏幕映射到达屏幕空间,首先通过齐次除法对[x, y, z]除以w进行归一化,通过缩放平移使得[x, y]为屏幕坐标,z作为深度缓冲存起来。

  • 标准光照模型 P123
    光照模型基本概念:也叫着色,根据材质属性、光源信息,使用一个等式去计算沿某个观察方向的出射度过程。
    标准光照模型基本理念:标准光照模型只关心直接光照,也就是那些直接从光源发射出来照射到物体表面后,经过物体表面一次反射直接进入摄像机的光线。
    ~标准光照模型把进入到摄影机内的光线分为4个部分,每个部分使用一种方法来计算它的贡献度。
    1)自发光部分,表示为 c e m i s s i v e c_{emissive} cemissive,用于描述给定一个方向时,一个表面本身会向该方向发射多少辐射量。标准光照模型使用自发光来计算这个部分的贡献度,计算方式很简单,直接用该材质的自发光颜色: c e m i s s i v e = m e m i s s i v e c_{emissive}=m_{emissive} cemissive=memissive其中 m e m i s s i v e m_{emissive} memissive表示材质自发光颜色
    2)高光反射部分,表示为 c s p e c u l a r c_{specular} cspecular,用于描述当光线从光源照射到模型表面时,该表面会在完全镜面反射方向散射多少辐射量。
    ~Phone模型公式 { r ^ = 2 ( n ^ ⋅ l ^ ) n ^ − l ^ c s p e c u l a r = ( c l i g h t ⋅ m s p e c u l a r ) m a x ( 0 , v ^ ⋅ r ^ ) m g l o s s \left\{ \begin{array}{ll} \hat{r}=2(\hat{n}·\hat{l})\hat{n}-\hat{l} \\ c_{specular}=(c_{light}·m_{specular})max(0,\hat{v}·\hat{r})^{m_{gloss}} \end{array} \right. {r^=2(n^l^)n^l^cspecular=(clightmspecular)max(0,v^r^)mgloss其中 r ^ 、 v ^ 、 n ^ 、 l ^ \hat{r}、\hat{v}、\hat{n}、\hat{l} r^v^n^l^反射方向、视角方向、表面法线、光源方向 c l i g h t c_{light} clight表示光源颜色 m s p e c u l a r m_{specular} mspecular表示材质的高光反射颜色 m g l o s s m_{gloss} mgloss表示材质光泽度,也被称为反光度
    ~Blinn模型公式 { h ^ = v ^ + l ^ ∣ v ^ + l ^ ∣ c s p e c u l a r = ( c l i g h t ⋅ m s p e c u l a r ) m a x ( 0 , n ^ ⋅ h ^ ) m g l o s s \left\{ \begin{array}{ll} \hat{h}=\frac{\hat{v}+\hat{l}}{|\hat{v}+\hat{l}|} \\ c_{specular}=(c_{light}·m_{specular})max(0,\hat{n}·\hat{h})^{m_{gloss}} \end{array} \right. {h^=v^+l^v^+l^cspecular=(clightmspecular)max(0,n^h^)mgloss其中 v ^ 、 n ^ 、 l ^ \hat{v}、\hat{n}、\hat{l} v^n^l^视角方向、表面法线、光源方向 c l i g h t c_{light} clight表示光源颜色 m s p e c u l a r m_{specular} mspecular表示材质的高光反射颜色 m g l o s s m_{gloss} mgloss表示材质光泽度,也被称为反光度
    3)漫反射部分,表示为 c d i f f u s e c_{diffuse} cdiffuse,用于描述当光线从光源照射到模型表面时,该表面会向每个方向散射多少辐射量。漫反射光照符合兰伯特定律:反射光线的强度与表面法线和光源方向之间夹角的余弦值成正比。漫反射部分计算如下: c d i f f u s e = ( c l i g h t ⋅ m d i f f u s e ) m a x ( 0 , n ^ ⋅ l ^ ) c_{diffuse}=(c_{light}·m_{diffuse})max(0,\hat{n}·\hat{l}) cdiffuse=(clightmdiffuse)max(0,n^l^)其中, c l i g h t c_{light} clight表示光源颜色 m d i f f u s e m_{diffuse} mdiffuse表示材质的漫反射颜色
    4)环境光部分,表示为 c a m b i e n t c_{ambient} cambient,用于描述其他所有的间接光照。环境光的计算非常简单,它通常是一个全局变量,即场景中的所有物体都使用这个环境光。 c a m b i e n t = g a m b i e n t c_{ambient}=g_{ambient} cambient=gambient
    ~如果在片元着色器中计算,被称为逐像素光照,如果在顶点着色器中计算,被称为逐顶点光照
    标准光照模型又被称为Blinn-Phong光照模型,它还有很多局限性。首先有很多重要的物理现象无法用Blinn-Phong模型表现出来,例如菲涅尔反射。其次Blinn-Phong模型是各项同性的,也就是说,当我们固定视角和光源方向旋转这个表面时,反射不会发生任何改变。但有些表面是具有各项异性反射性质的,例如拉丝金属、毛发等。

  • 用模型空间和切线空间保存法线纹理各有啥优点? P147
    ~模型空间来存储法线的优点如下:
    1)实现简单,更加直观。我们甚至都不需要模型原始的法线和切线等信息,也就是说,计算更少。生成它也非常简单,而如果要生成切线空间下的法线纹理,由于模型的切线一般是和UV方向相同,因此想要得到效果比较好的法线映射就要求纹理映射也是连续的。
    2)在纹理坐标的缝合处和尖锐的边角部分,可见的突变(缝隙)较少,即可以提供平滑的边界。这是因为模型空间下的法线纹理存储的是同一坐标系下的法线信息,因此在边界出通过插值得到的法线可以平滑变换。而切线空间下的法线纹理中的法线信息是依靠纹理坐标的方向得到的结果,可能会在边缘处或尖锐的部分造成更多可见的缝合迹象。
    ~切线空间来存储法线的优点如下:
    1)自由度很高。模型空间下的法线纹理记录的是绝对法线信息,仅可用于创建它时的那个模型,而应用到其他模型上的效果就完全错误了。而切线空间下的法线纹理记录的是相对法线信息,这意味着,即便把该纹理应用到一个完全不同的网格上,也可以得到一个合理的结果。
    2)可进行UV动画。比如,我们可以移动一个纹理的UV坐标来实现一个凹凸移动的效果,但使用模型空间下的法线纹理会得到完全错误的结果。原因同上。这种UV动画在水或者火山熔岩这种类型的物体上会经常用到。
    3)可以重用法线纹理。比如,一个砖块,我们仅使用一张法线纹理就可以用到所有的6个面上。原因同上。
    4)可压缩。由于切线空间下的法线纹理中法线的Z方向总是正方向,因此我们可以仅存储XY方向,而推导得到Z方向。而模型空间下的法线纹理由于每个方向都是可能的,因此必须存储3个方向的值,不可压缩。

成果图
  • 第一次通过自己写顶点着色器和片元着色器实现的材质球

在这里插入图片描述

  • 逐顶点的漫反射(左),逐像素的漫反射(中),半兰伯特光照(右)

在这里插入图片描述

  • 逐顶点的高光反射(左),逐像素的高光反射(中),逐像素的高光反射Blinn-Phong(右)

在这里插入图片描述

  • 单张纹理在环境光+漫反射+高光反射条件下的显示

在这里插入图片描述

  • 单张纹理通过改变法线方向(法线纹理)达到的凹凸不平效果

在这里插入图片描述

  • 透明度测试(单面)

在这里插入图片描述

  • 透明度测试(双面)

在这里插入图片描述

  • 透明度混合

在这里插入图片描述

  • 透明度混合(双面)

在这里插入图片描述

  • 开启了深度写入的透明度混合

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值