引言
GAMES101现代图形学入门是由闫令琪老师教授。本次作业们会进一步模拟现代图形技术,主要是关于图形渲染管线以及纹理。
GAMES101 Spring 2021课程作业三现在发布!大家可以在SmartChair上提交了,注意截止日期为2021年7月10日。
在课程中段,我们会为同学们开启补提交通道。百度云链接
提取码: r3pc请大家根据网络环境自行下载。
总览
在这次编程任务中,我们会进一步模拟现代图形技术。我们在代码中添加了 Object Loader(用于加载三维模型), Vertex Shader 与 Fragment Shader,并且支持了纹理映射。
而在本次实验中,你需要完成的任务是:
- 修改函数
rasterize_triangle(const Triangle& t)
inrasterizer.cpp
: 在此处实现与作业 2 类似的插值算法,实现法向量、颜色、纹理颜色的插值。 - 修改函数
get_projection_matrix()
inmain.cpp
: 将你自己在之前的实验中实现的投影矩阵填到此处,此时你可以运行./Rasterizer output.png normal
来观察法向量实现结果。 - 修改函数
phong_fragment_shader()
inmain.cpp
: 实现 Blinn-Phong 模型计算 Fragment Color. - 修改函数
texture_fragment_shader()
inmain.cpp
: 在实现 Blinn-Phong 的基础上,将纹理颜色视为公式中的 kd,实现 Texture Shading Fragment Shader. - 修改函数
bump_fragment_shader()
inmain.cpp
: 在实现 Blinn-Phong 的基础上,仔细阅读该函数中的注释,实现 Bump mapping. - 修改函数
displacement_fragment_shader()
inmain.cpp
: 在实现 Bump mapping 的基础上,实现 displacement mapping.
开始编写
编译与使用
在课程提供的虚拟机上,下载本次实验的基础代码之后,请在 SoftwareRasterizer 目录下按照如下方式构建程序:
mkdir build |
这将会生成命名为 Rasterizer
的可执行文件。使用该可执行文件时,你传入的第二个参数将会是生成的图片文件名,而第三个参数可以是如下内容:
texture: 使用代码中的 texture shader.
使用举例: ./Rasterizer output.png texture
normal: 使用代码中的 normal shader.
使用举例: ./Rasterizer output.png normal
phong: 使用代码中的 blinn-phong shader.
使用举例: ./Rasterizer output.png phong
bump: 使用代码中的 bump shader.
使用举例: ./Rasterizer output.png bump
displacement: 使用代码中的 displacement shader.
使用举例: ./Rasterizer output.png displacement
当你修改代码之后,你需要重新 make 才能看到新的结果。
框架代码说明
相比上次实验,我们对框架进行了如下修改:
我们引入了一个第三方 .obj 文件加载库来读取更加复杂的模型文件,这部分库文件在
OBJ_Loader.h file
. 你无需详细理解它的工作原理,只需知道这个库将会传递给我们一个被命名被TriangleList
的Vector
,其中每个三角形都有对应的点法向量与纹理坐标。此外,与模型相关的纹理也将被一同加载。 注意:如果你想尝试加载其他模型,你目前只能手动修改模型路径。我们引入了一个新的
Texture
类以从图片生成纹理,并且提供了查找纹理颜色的接口:Vector3f getColor(float u, float v)
我们创建了
Shader.hpp
头文件并定义了fragment_shader_payload
,其中包括了 Fragment Shader 可能用到的参数。目前main.cpp
中有三个 Fragment Shader,其中fragment_shader
是按照法向量上色的样例 Shader,其余两个将由你来实现。主渲染流水线开始于
rasterizer::draw(std::vector<Triangle>&TriangleList)
. 我们再次进行一系列变换,这些变换一般由 Vertex Shader 完成。在此之后,我们调用函数rasterize_triangle
.rasterize_triangle
函数与你在作业 2 中实现的内容相似。不同之处在于被设定的数值将不再是常数,而是按照 Barycentric Coordinates 对法向量、颜色、纹理颜色与底纹颜色 (Shading Colors) 进行插值。回忆我们上次为了计算 z value 而提供的[alpha, beta, gamma]
,这次你将需要将其应用在其他参数的插值上。你需要做的是计算插值后的颜色,并将 Fragment Shader 计算得 到的颜色写入framebuffer
,这要求你首先使用插值得到的结果设置 fragment shader payload,并调用 fragment shader 得到计算结果。
运行与结果
在你按照上述说明将上次作业的代码复制到对应位置,并作出相应修改之后**(请务必认真阅读说明)**,你就可以运行默认的 normal shader 并观察到如下结果:
实现 Blinn-Phong 反射模型之后的结果应该是:
实现纹理之后的结果应该是:
实现 Bump Mapping 后,你将看到可视化的凹凸向量:
实现 Displacement Mapping 后,你将看到如下结果:
评分与提交
评分
[5 分] 提交格式正确,包括所有需要的文件。代码可以正常编译、执行。
[10 分] 参数插值: 正确插值颜色、法向量、纹理坐标、位置 (Shading Position) 并将它们传递给 fragment_shader_payload.
[20 分] Blinn-phong 反射模型: 正确实现 phong_fragment_shader 对应的 反射模型。
[5 分] Texture mapping: 将 phong_fragment_shader 的代码拷贝到 texture_fragment_shader, 在此基础上正确实现 Texture Mapping.
[10 分] Bump mapping 与 Displacement mapping: 正确实现 Bump mapping 与 Displacement mapping.
[Bonus 3 分] 尝试更多模型: 找到其他可用的.obj 文件,提交渲染结果并 把模型保存在 /models 目录下。这些模型也应该包含 Vertex Normal 信息。
[Bonus 5 分] 双线性纹理插值: 使用双线性插值进行纹理采样, 在 Texture 类中实现一个新方法 Vector3f getColorBilinear(float u, float v) 并 通过 fragment shader 调用它。为了使双线性插值的效果更加明显,你应该 考虑选择更小的纹理图。请同时提交纹理插值与双线性纹理插值的结果,并 进行比较。
[-2 分] 惩罚分数:
未删除 /build、/.vscode、Assignment3.pdf 等与代码无关的文件; 未提交或未按要求完成 README.md;
未按照要求完成/images 目录;
代码相关文件和 README.md 文件不在你提交的文件夹下的第一层。
提交
当你完成作业后,请清理你的项目 (删去:/build、/.vscode、/Assignment3.pdf
等),在你的文件夹中包含 CMakeLists.txt 和所有的程序文件 (无论是否修改);
同时,请新建一个 /images 目录,将所有实验结果图片保存在该目录下;
再添加一个 README.md 文件写清楚自己完成了以上七个得分点中的哪几 点 (如果完成了,也请同时提交一份结果图片),并简要描述你在各个函数中 实现的功能;
最后,将上述内容打包,并用“姓名 Homework3.zip”的命名方式提交到 SmartChair 平台。