Games101结合Unity Shader入门精要学习笔记(个人向)

第四章

3D旋转

绕X轴旋转:

绕Y轴旋转:

绕Z轴旋转:

 旋转变换(一)旋转矩阵_csxiaoshui的博客-CSDN博客_旋转矩阵

重点:MVP变换!!!

model transformation

view(camera) transformation  

     ​​​​​

projection transformation

        orthogra projection:

img

perspective projection:

 

Tip:要是忘记了求解过程的话就去看这个吧: Games101 学习笔记_什么时候才能坚持做好一件事啊的博客-CSDN博客_games101笔记

And!!!!!!!!!!!!!!!!!!!!!!!!(有时间再写)

viewport transformation

法线变换

M矩阵:模型空间->世界空间(unity默认获取的就是模型空间)

V矩阵:世界空间->观察空间(相机空间)

P矩阵:观察空间->齐次裁剪空间

第五章、第六章

光栅化————承接上文

基础做法:对每个像素循环处理

但是会出先许多问题,接下来的内容就是对出现的问题进行解决。

反走样和深度缓冲走样: 

        反走样:我们在光栅图形显示器上绘制非水平、非垂直的直线或多边形边界时,会呈现锯齿状外观。这是因为直线和多边形的边界是连续的,而光栅则是由离散的点组成。在光栅显示设备上表现直线、多边形等,必须在离散位置采样。由于采样不充分重建后造成的信息失真,就叫走样;用于减少或消除这种效果的技术,就称为反走样。

        深度缓存:在计算机图形学中,深度缓冲是在三维图形中处理图像深度坐标的过程,这个过程通常在硬件中完成,它也可以在软件中完成,它是可见性问题的一个解决方法。可见性问题是确定渲染场景中哪部分可见、哪部分不可见的问题。画家算法是另外一种常用的方法,尽管效率较低,但是也可以处理透明场景元素。深度缓冲也称为Z缓冲。

本质上是:相对来说信号变换过快(频率过高)而采样速度太慢

如何反走样:在采样前进行一次模糊Blurring(Pre-Filtering滤波)——使用低通滤波去掉高频信号,相当于减少频域上频谱的宽度(模糊边缘来抗锯齿) ,这样在稀疏采样时也不容易重叠。所以要先滤波再采样,反之则不行。

也可以提高采样率:即增加频域上两个频谱之间的距离,这样在稀疏采样时频谱之间更不容易重叠。实际上就是提高画面分辨率,但开销很高。

MSAA:一个像素中设置多个采样点,通过判断采样点insde的比率(像素比例)进行渲染。

Z-buffering(掌握的不是很好啊小子

为每一个采样的像素点存储一个当前最近的z值(注意是-z轴)

需要额外的buffer去存储这个深度值

–frame buffer存储颜色值

–depth buffer存储深度值

 

伪代码:针对每一个被光栅化的三角形的其内的一个采样点,记录最小的z值

所以z-buffer永远维护的当前最近的像素的深度信息。

z-buffer计算的时间复杂度:我们只需要遍历场景中的每一个三角形,对其中的采样像素点记录最小z值,所以对于n个三角形,复杂度为O(n)

通过GPU硬件进行计算

注意在使用MASS时,z-buffer就不单纯是针对像素进行,而是针对其中的每个采样点进行,带宽会急剧增加。

第七、八、九章
此部分结合了Unity Shader~

Blinn-Phong Reflectance Model(冯氏光照模型)

Tip:fixed3 albedo=tex2D(_MainTex,v2f.uv).rgb*_Color.rgb;

漫反射:

Ld=Kd(I/r^2)max(0,n*l)

fixed3 diffuse=_LightColor0.rgb*albedo*max(0,dot(worldNormal,worldLightDir));(Unity Shader中)

高光:

Ls=Ks(I/r^2)max(0,cosa)^p;

fixed3 specular=_LightColor0.rgb*_Specular.rgb*pow(max(0,dot(worldNormal,halfDir)),_Gloss);(Unity Shader中)

环境光:

La=Ka*Ia;

fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT.xyz*albedo;(Unity Shader中)

albedo是反射率,不认识的基本都是unity中的内置变量与函数。

重点!!! 

Graphics(Real-time Rendering) Pipeline(渲染管线)

 

 

 

纹理映射

uv:范围为0-1。

求重心坐标

 

 

注意,3维的三角形投影到2维上重心坐标可能会发生变化,所以要先在3d空间中算出重心坐标再投影到2d

纹理映射

纹理坐标定义在三角形面片顶点上,再通过重心坐标插值,可以得到三角形内部任意点的uv,通过这个uv值从纹理中拿到对应的像素颜色,这个颜色就是漫反射系数kd。

纹理过滤

对远处物体进行简单化渲染(特别远的人只是一个黑点)的方式,应用的就是纹理过滤。当与物体dis为0时,屏幕显示像素为400*400,随着距离拉远,屏幕显示的pix变成200*200,相比之前,一个像素就要显示2*2的纹理像素,那么这个像素要显示什么颜色呢?并且,当我们进行操作时,我们会发现远处的显示效果可能会产生锯齿或者摩尔纹,又该怎么解决?

        MipMap  

        

        Mipmap创建:预先创建原纹理大小2分之一的多级渐远纹理,在多级渐远纹理取色采样时,也会进行线性过滤,可以理解成预先创建每隔一定阈值(也就是每次映射像素为上一级别多级渐远纹理的2分之一的时候)并经过了线性过滤的纹理。

        使用Mipmap的渲染过程:20*20的像素需要映射400*400的纹理像素时,检测到一颗像素需要映射到纹理像素为20*20,在Mipmap纹理中里寻找最接近20*20纹理像素的多级渐远纹理,并使用此多级渐远纹理进行采样。

        此时采样用的多级渐远纹理的颜色也是从上一级的多级渐远纹理迭代采样插值计算而来,也就是一颗像素映射此多级渐远纹理间接插值计算了20*20的纹理像素的颜色,取色的效果当然比一颗像素直接映射原图20*20只采样了2*2的纹理像素颜色进行线性插值要好得多,使用Mipmap就避免了采样的纹理像素过少而失真。

        各向异性过滤 Anisotropic Filtering

        

        Mipmap虽然十分巧妙但也不是完美的,其范围计算是近似的正方形区域,对于纹理映射到斜着的或者不规则的情况下,效果不是很好,所以有了各向异性过滤。

        在mipmap中,我们考虑正方形近似计算,所以两个边是等比压缩,但在实际情况中,很多情况下是不会等比的,所以将这部分贴图也预计算进去,mipmap的部分其实就是下图的左上到右下的对角线。所以理论上各向异性过滤增加了纹理内存三倍的大小。

        各向异性过滤同mipmap一样,可以压缩多层,一般为16层,游戏中选择最大第几层其实在显存足够的情况下并无太大区别,因为纹理内存都近似增大三倍。

        各向异性过滤因为可以在单方向上压缩,所以对于处理这种纹理映射到一个矩形区域的情况十分有优势,可以计算更精确的矩形范围,相反mipmap是正方形区域,误差更多。

       

各向同性的过滤在采样的时候,是对正方形区域里行采样。各向异性过滤把纹理与屏幕空间的角度这个因素考虑时去。简单地说,它会考滤一个pixel(x:y=1:1)对应到纹理空间中在u和v方向上u和v的比例关系,当u:v不是1:1时,将会按比例在各方向上采样不同数量的点来计算最终的结果(这时采样就有可能是长方形区域)。

我们一般指的Anisotropic Filtering(AF)均是基于三线过滤的Anisotropic Filtering,因此当u:v不为1:1时,则Anisotropic Filtering比Trilinear需要采样更多的点,具体要采多少,取决于是多少X的AF,现在的显卡最多技持到16X AF。

当开启16X AF的时候,硬件并不是对所有的texture采样都用16X AF,而是需要先计算屏幕空间与纹理空间的夹角(量化后便是上面所说的u:v),只有当夹角大到需要16X时,才会真正使用16X.

如果想了解AF的实现原理,可以查阅此篇Paper: “Implementing an anisotropic texture filter”. 现在AF都是硬件实现,因此只有少数人才清楚AF就尽是怎样实现了(其实细节我也没搞清楚),其实完全可以由Pixel Shader来实现AF,当然性能和由硬件做是没得比的。
各项异性滤波简介Anisotropic Filtering(AF)_jieniyimiao的博客-CSDN博客_各向异性过滤有什么用

bump/normal Map 凹凸/法线贴图作用原理

float dU = kh * kh * (payload.texture->getColor(u + 1.0f / w, v).norm() - payload.texture->getColor(u, v).norm());
    float dV = kh * kn * (payload.texture->getColor(u, v + 1.0f / h).norm() - payload.texture->getColor(u, v).norm());

Eigen::Vector3f ln;
    ln << -dU, -dV, 1.0f;
    normal = (TBN * ln).normalized();

其中TBN矩阵

模型顶点中的纹理坐标,就定义于切线空间。普通2维纹理坐标包含U、V两项,其中U坐标增长的方向, 即切线空间中的tangent轴,V坐标增加的方向,为切线空间中的bitangent轴,N就不用说了吧......

 OpenGL.Shader:9-学习光照-法线贴图(计算TBN矩阵)_Mr_Zzr的博客-CSDN博客_tbn矩阵

TBN矩阵的应用
使用TBN矩阵解决从法线贴图中采样得到的法线所处坐标空间与其他向量所处的坐标空间不同的问题:
从法线贴图中采样得到的法线处于切线空间下,而其他的向量是处于世界坐标下的。而TBN矩阵可以将切线空间的坐标变换到世界空间中,有两种方法来解决:

方法一:在片段着色器中,对采样得到的法线向量左乘TBN矩阵,将其变换到世界坐标中,需要将TBN矩阵从顶点着色器传给片段着色器。
方法二:在顶点着色器中,对光线向量和视线向量左乘TBN矩阵的逆矩阵将向量变换到切线空间中,不需要将TBN矩阵从顶点着色器传给片段着色器。

关于纹理放大和缩小,在之后unity shader的纹理部分再讨论~

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值