PKU 可视计算概论 Lab3作业
前言
学期终于结束了,总感觉有些草草收场,期末前夕感染新冠,属实令人无语,于是该缓考的缓考,该pf的pf,总之还是十分无奈吧,如果强行考试,那么期中好不容易取得的成绩就白费了,只能如此了。
好啦废话不多说,这次的lab主题是渲染,助教还十分贴心地写了一句话“渲染器是程序员的三大浪漫之一”。感觉也是在严肃的作业中多了一点幽默吧。
本次lab分为5个task,每个task后还跟着几个小问题,下面就写一写吧。
Task 1: Phong Illumination (3’)
这个Task主要是想让实现Phong模型,以及改进后的Blinn-Phong模型,还有一个附加任务是改进一下GetNormal函数。
针对这个任务的前两部分,其实比较简单,主要就是套公式,思路的话:Phong模型主要是想通过计算环境光+反射光+高光的一个组合,实现完成,这里主要提一下高光的计算,这里在两个模型中是有区别的。
在Phong模型中:这里的高光是计算的反射光与摄像机之间的夹角cos值的次方。
在Blinn-Phong模型中:这里的高光计算的是入射光与摄像机中位角与法线的夹角的cos的次方。
至于对于GetNormal函数的改进主要是通过HeightMap,计算得出区域的梯度(也就是倾斜方向),从而进行补光,插值之类的运算。
结果如图:
Phong:
Blinn-Phong:
回答问题:
1)顶点着色器和片段着色器的关系是什么样的?顶点着色器中的输出变量是如何传递到片段着色器当中的?
顶点着色器只是对图像框架的各个定点进行着色,然后片段着色器便会对这几个定点所围成的面进行插值上色。在GLSL中,顶点着色器的输出变量通过申明进行输出,如果片段着色器开头的申明中有同样命名的变量,便实现传递。
2) 代码中的 if (diffuseFactor.a < .2) discard;
这行语句,作用是什么?为什么不能用 if (diffuseFactor.a == 0.) discard;
代替?
作用是当一个片段的alpha值小于0.2就不绘制这个片段。如果用等于0代替,那么有很多比较暗,基本看不出来的片段就无法实现不绘制。
Task 2: Environment Mapping (2’)
这里没什么,主要就是注意矩阵相乘是不满足交换律的…其他的思路就是计算反射光,然后调用texture函数计算就可。
Task 3: Non-Photorealistic Rendering (2’)
思路主要是通过应用公式即可。
回答问题:
1)代码中是如何分别渲染模型的反面和正面的?(答案在 Labs/3-Rendering/CaseNonPhoto.cpp
中的 OnRender()
函数中)
通过调用glcullface函数和glEnable和glDisable函数把另一面禁用,从而加快上色。
2)npr-line.vert
中为什么不简单将每个顶点在世界坐标中沿着法向移动一些距离来实现轮廓线的渲染?这样会导致什么问题?
线的宽度会比较难以控制。
Task 4: Shadow Mapping (3’)
有了这些投影坐标,我们就能从深度贴图中采样得到0到1的结果,从第一个渲染阶段的projCoords坐标直接对应于变换过的NDC坐标。我们将得到光的位置视野下最近的深度。
回答问题:
1)想要得到正确的深度,有向光源和点光源应该分别使用什么样的投影矩阵计算深度贴图?
有向光源为正交矩阵,点光源为透视矩阵。
2)为什么 phong-shadow.vert
和 phong-shadow.frag
中没有计算像素深度,但是能够得到正确的深度值?
因为上面的projCoords的xyz分量都是[-1,1](这对于远平面之类的点才成立),它采用pos = pos * 0.5 + 0.5;代码将其变换到[0,1]可以作为深度图使用。
Task 5: Whitted-Style Ray Tracing (4’)
这里的计算出直线三角形相交的点,从而确定光线碰撞到的平面,然后再用光追进行渲染,并不断迭代。
回答问题:
1)光线追踪和光栅化的渲染结果有何异同?如何理解这种结果?
光线追踪更有利于产生真实的阴影,而光栅化则较为困难。
这是因为光线追踪是做出真实的光线与物体的碰撞,从而能够确定阴影的位置。