GAMES101 Assignment 3

前言

通过阅读实验提供的代码框架,可以加深对渲染管线的理解。assignment1,2我并没有做,我们课程图形学本来有实验计划,然而老师专门让我们做GAMES101的这个实验,其意义可见一斑。
阅读过程中遇到许多困难,看了许多资料以及平台的论坛,很受启发,重要资源附在文末。

实验目的

GAMES101 Assignment 3_第1张图片

实验内容

GAMES101 Assignment 3_第2张图片
GAMES101 Assignment 3_第3张图片
第②点讲错了,一开始把这个点错理解为视点,它就是模型的顶点,后面用来插值得到渲染点的shadingcoords.

GAMES101 Assignment 3_第4张图片
GAMES101 Assignment 3_第5张图片
细心的朋友会发现一些问题。code 中用投影后的点计算重心坐标,通过几步运算得到插值点的深度(z坐标),然后依次插值得到颜色、法线、纹理坐标以及 shadingcoords.
首先,shadingcoords是什么?
它是要渲染点(在 shader 中就是红色圈出来的点)在相机坐标系下的坐标,通过仅经过mv变换(代码中有体现)的三角形顶点插值得到。
GAMES101 Assignment 3_第6张图片

为什么深度的插值计算和其他属性不同?
投影前后,重心坐标会发生变化,进行属性插值按理使用投影前的重心。那么我们如何计算投影前的重心?

透视矫正插值

GAMES101 Assignment 3_第7张图片
对蓝色三角形进行齐次变换 M M M得到红色三角形,设 K = A , B , C , P K={A,B,C,P} K=A,B,C,P,有
[ K ′ w k w k ] = M [ K 1 ] \begin{bmatrix} K'w_k \\ w_k \end{bmatrix}=M \begin{bmatrix} K \\ 1 \end{bmatrix} [Kwkwk]=M[K1]
注意到在进行齐次除法时保留了 w k w_k wk. 设点 P 变换前后重心坐标为 ( α , β , γ ) (\alpha,\beta,\gamma) (α,β,γ)以及 ( α ′ , β ′ , γ ′ ) (\alpha',\beta',\gamma') (α,β,γ),满足
P = α A + β B + γ C P ′ = α ′ A ′ + β ′ B ′ + γ ′ C ′ P=\alpha A+\beta B+\gamma C \\ P'=\alpha' A'+\beta' B'+\gamma' C' P=αA+βB+γCP=αA+βB+γC
利用 α + β + γ = 1 \alpha+\beta+\gamma=1 α+β+γ=1构建等式,建立变换前后重心坐标的关系:

GAMES101 Assignment 3_第8张图片
但是现在是已知投影后的重心坐标,因此应该用 α ′ , β ′ , γ ′ \alpha',\beta',\gamma' αβ,γ表示 α \alpha α,已知 α ′ = α w a k \alpha'=\alpha w_ak α=αwak,尝试将 k k k α ′ , β ′ , γ ′ \alpha',\beta',\gamma' αβ,γ表达即可:
GAMES101 Assignment 3_第9张图片
Z变量 对应的正是公式中 k因此深度是通过透视矫正插值精确计算的,而其他属性是通过投影后重心坐标简单近似插值计算的。
看这个回帖:
GAMES101 Assignment 3_第10张图片
帖子:https://games-cn.org/forums/topic/zuoye3-interpolated_shadingcoords/
截图材料:https://www.cs.ucr.edu/~craigs/courses/2018-fall-cs-130/lectures/perspective-correct-interpolation.pdf

auto tup = computeBarycentric2D((float)x + 0.5, (float)y + 0.5, t.v);
float alpha, beta, gamma;   // 利用重心坐标进行属性插值
std::tie(alpha, beta, gamma) = tup;
float Z = 1.0 / (alpha / v[0].w() + beta / v[1].w() + gamma / v[2].w());
float zp = alpha * v[0].z() / v[0].w() + beta * v[1].z() / v[1].w() + gamma * v[2].z() / v[2].w();
zp *= Z;    // 深度
if (zp < depth_buf[get_index(x, y)])
{
    // 近似插值
    auto interpolated_color = interpolate(alpha, beta, gamma, t.color[0], t.color[1], t.color[2], 1);
    auto interpolated_normal = interpolate(alpha, beta, gamma, t.normal[0], t.normal[1], t.normal[2], 1).normalized();
    auto interpolated_texcoords = interpolate(alpha, beta, gamma, t.tex_coords[0], t.tex_coords[1], t.tex_coords[2], 1);
    auto interpolated_shadingcoords = interpolate(alpha, beta, gamma, view_pos[0], view_pos[1], view_pos[2], 1);

在这里插入图片描述
GAMES101 Assignment 3_第11张图片
后面两个shader还未理解原理,坑。

实验结果

GAMES101 Assignment 3_第12张图片

More

山东大学图形学课程实验代码获取:Here

你可能感兴趣的:(算法,图形学,shade)