GAMES101作业2

这篇具有很好参考价值的文章主要介绍了GAMES101作业2。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

作业内容

在屏幕上画出一个实心三角形,
换言之,栅格化一个三角形。上一次作业中,在视口变化之后,我们调用了函数
rasterize_wireframe(const Triangle& t)。但这一次,你需要自己填写并调用
函数 rasterize_triangle(const Triangle& t)。
该函数的内部工作流程如下:

  1. 创建三角形的 2 维 bounding box。
  2. 遍历此 bounding box 内的所有像素(使用其整数索引)。然后,使用像素中
    心的屏幕空间坐标来检查中心点是否在三角形内。
  3. 如果在内部,则将其位置处的插值深度值 (interpolated depth value) 与深度
    缓冲区 (depth buffer) 中的相应值进行比较。
  4. 如果当前点更靠近相机,请设置像素颜色并更新深度缓冲区 (depth buffer)。

Step 1. 创建三角形的2维bounding box

GAMES101_Lecture_05.pdf 43页

  • Checking All Pixels on the Screen?
    GAMES101作业2,GAMES101,图形渲染
    已知三角形的三个顶点,如何得出蓝色矩形的width 和 height。 或者说左下角点和右上角的坐标

假设三角形的三个顶点经过t.toVector4( )输出的坐标如下:

===== P0 ======
108.579
350
-0.714285
1
===== p1 ======
350
108.579
-0.714285
1 
===== p2 ======
591.421
350
-0.714285
1

那么bounding box 左下角和右上角的坐标为
GAMES101作业2,GAMES101,图形渲染
B_1_x = min(P0_x, P1_x, P2_x)
B_1_y = min(P0_y, P1_y, P2_y)

B_2_x = max(P0_x, P1_x, P2_x)
B_2_y = max(P0_y, P1_y, P2_y)

bounding_box_width = B_2_x - B_1_x;
bounding_box_height = B_2_y - B_1_y;

    unsigned int bBox_leftbottom_x;
    unsigned int bBox_leftbottom_y;
    unsigned int bBox_topright_x;
    unsigned int bBox_topright_y;
    unsigned int width, height;

    bBox_leftbottom_x = floor(MIN(MIN(v[0].x(), v[1].x()), v[2].x())); //向下取整
    bBox_leftbottom_y = floor(MIN(MIN(v[0].y(), v[1].y()), v[2].y()));
    bBox_topright_x   = ceil(MAX(MAX(v[0].x(), v[1].x()), v[2].x()));  //向上取整
    bBox_topright_y   = ceil(MAX(MAX(v[0].y(), v[1].y()), v[2].y()));
    std::cout << "bBox :leftbottom:(" << bBox_leftbottom_x <<
              ","<<bBox_leftbottom_y <<") "<<
              "topright:("<<bBox_topright_x <<
              ","<< bBox_topright_y <<")" << std::endl;
    width = bBox_topright_x - bBox_leftbottom_x;
    height = bBox_topright_y - bBox_topright_y;
x: 108.579 y: 350 z: -0.714285
x: 350 y: 108.579 z: -0.714285
x: 591.421 y: 350 z: -0.714285
bBox :leftbottom:(108,108) topright:(592,350)
bBox_width:484
bBox_height:242

Step 2. 判断bBox中的像素中心点是否在三角形内

遍历此 bounding box 内的所有像素(使用其整数索引)。然后,使用像素中心的屏幕空间坐标来检查中心点是否在三角形内。

GAMES101作业2,GAMES101,图形渲染

在Lecture 2中,判断一个点是否在三角形内,可以通过某个顶点到该点的向量与边的叉乘是否都满足z坐标的一致性,比如上图中判断(按逆时针方向)

  • P 0 P 1 → \overrightarrow {P_0P_1} P0P1 x P 0 P Q → \overrightarrow {P_0P_Q} P0PQ
  • P 1 P 2 → \overrightarrow {P_1P_2} P1P2 x P 1 P Q → \overrightarrow {P_1P_Q} P1PQ
  • P 2 P 0 → \overrightarrow {P_2P_0} P2P0 x P 2 P Q → \overrightarrow {P_2P_Q} P2PQ

借助Egien提供的向量叉乘的接口

v1_tmp = vector_3f_p0p1.cross(vector_3f_p0pq);
v2_tmp = vector_3f_p1p2.cross(vector_3f_p1pq);
v3_tmp = vector_3f_p2p1.cross(vector_3f_p2pq);
static bool insideTriangle(int x, int y, const Vector3f* _v)
{   
    // TODO : Implement this function to check if the point (x, y) is inside the triangle represented by _v[0], _v[1], _v[2]

    Vector3f q = Vector3f(x, y, 1.0);                    // Homogeneous
    Vector3f p0_pq = q - _v[0];
    Vector3f p1_pq = q - _v[1];
    Vector3f p2_pq = q - _v[2];

    Vector3f v1_tmp = (_v[1] - _v[0]).cross(p0_pq);       //p0_p1 x p0_pq
    Vector3f v2_tmp = (_v[2] - _v[1]).cross(p1_pq);       //p1_p2 x p1_pq
    Vector3f v3_tmp = (_v[0] - _v[2]).cross(p2_pq);       //p2_p0 x p2_pq

    if ((v1_tmp.z() > 0 && v2_tmp.z() > 0 && v3_tmp.z() > 0) ||
        (v1_tmp.z() < 0 && v2_tmp.z() < 0 && v3_tmp.z() < 0) ||
        (v1_tmp.z() < 1e-6 && v2_tmp.z() < 1e-6 && v3_tmp.z() < 1e-6))
    {
        return true;
    }
    else
    {
        return false;
    }
}   

Step 3. 比较插值深度和Depth Buffer

  1. 如果在内部,则将其位置处的插值深度值 (interpolated depth value) 与深度
    缓冲区 (depth buffer) 中的相应值进行比较。
  2. 如果当前点更靠近相机,请设置像素颜色并更新深度缓冲区 (depth buffer)。

注意,需要将工程的属性修改成兼容C++17, 否则下面语句报错

auto [alpha, beta, gamma] = computeBarycentric2D(x, y, t.v); 
for (int x = (int)bBox_leftbottom_x; x <= bBox_topright_x; x++)
{
    for (int y = (int)bBox_leftbottom_y; y <= bBox_topright_y; y++)
    {
        if (insideTriangle(x, y, t.v))
        {
            // If so, use the following code to get the interpolated z value.
            auto [alpha, beta, gamma] = computeBarycentric2D(x, y, t.v);
            float w_reciprocal = 1.0 / (alpha / v[0].w() + beta / v[1].w() + gamma / v[2].w());
            float z_interpolated = alpha * v[0].z() / v[0].w() + beta * v[1].z() / v[1].w() + gamma * v[2].z() / v[2].w();
            z_interpolated *= w_reciprocal;

            // compare the interpolated depth value with depth buffer value
            if (depth_buf[get_index(x, y)] > z_interpolated)
            {
                depth_buf[get_index(x, y)] = z_interpolated;
                // TODO : set the current pixel (use the set_pixel function) to the color of the triangle (use getColor function) if it should be painted.
                set_pixel(Vector3f(x, y, z_interpolated), t.getColor());
            }
        }
    }
}

MSAA

用 super-sampling 处理 Anti-aliasing : 你可能会注意到,当我们放大图像时,图像边缘会有锯齿感。我们可以用 super-sampling来解决这个问题,即对每个像素进行 2 * 2 采样,并比较前后的结果 (这里并不需要考虑像素与像素间的样本复用)。需要注意的点有,对于像素内的每一个样本都需要维护它自己的深度值,即每一个像素都需要维护一个 samplelist。最后,如果你实现正确的话,你得到的三角形不应该有不正常的黑边

GAMES101作业2,GAMES101,图形渲染
GAMES101作业2,GAMES101,图形渲染文章来源地址https://www.toymoban.com/news/detail-588864.html

for (int x = (int)bBox_leftbottom_x; x <= bBox_topright_x; x++)
 {
     for (int y = (int)bBox_leftbottom_y; y <= bBox_topright_y; y++)
     {
         float depth_tmp = 0.0;      // max value for float in system 
         int count = 0;
         Vector2f sample_point[4] = { Vector2f(0.25, 0.25),Vector2f(0.75, 0.25), Vector2f(0.75,0.75), Vector2f(0.75, 0.25) };
         for (int i=0; i<4; i++)
         {
             if (insideTriangle(x+ sample_point[i].x(), y+sample_point[i].y(), t.v))
             {
                 // If so, use the following code to get the interpolated z value.
                 auto [alpha, beta, gamma] = computeBarycentric2D(x, y, t.v);
                 float w_reciprocal = 1.0 / (alpha / v[0].w() + beta / v[1].w() + gamma / v[2].w());
                 float z_interpolated = alpha * v[0].z() / v[0].w() + beta * v[1].z() / v[1].w() + gamma * v[2].z() / v[2].w();
                 z_interpolated *= w_reciprocal;
                 depth_tmp += z_interpolated;
                 count +=1;
             }
         }
         float depth_average = depth_tmp / 4;
         if (count>0&&depth_buf[get_index(x,y)]> depth_average)
         {
             depth_buf[get_index(x, y)] = depth_average;

             set_pixel(Vector3f(x, y, depth_average), t.getColor() * count / 4.0 + frame_buf[get_index(x, y)] * (4 - count) / 4.0);
         }
         
     }
 }

到了这里,关于GAMES101作业2的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • GAMES101 作业1

    作业pa1对应的是GAMES101课程Lecture02到Lecture04这三节课的内容,主要是用于巩固空间中的物体投影到相机平面的整个过程。 说在前面,本文是在左手系下进行讨论的。 粗略地看一遍我们可以知晓main函数的流程: ①设定一些基本的初始参数并初始化源代码给出的 光栅化类raste

    2024年02月09日
    浏览(35)
  • GAMES101:作业3

    附其他所有作业超链接如下: Games101 作业0: 作业0 Games101 作业1: 作业1 Games101 作业2: 作业2 Games101 作业3: 作业3 Games101 作业4: 作业4 Games101 作业5: 作业5 Games101 作业6: 作业6 Games101 作业7: 作业7 完整代码获取途径: https://github.com/liupeining/Games_101_homework 照旧把这段代码

    2024年02月04日
    浏览(41)
  • 计算机图形学-GAMES101-3

    缩放变换示意图 图形每个像素对应坐标的计算公式 写成缩放矩阵的形式 非均匀缩放 镜面变换示意图 图形每个像素对应坐标的计算公式 写成镜像矩阵的形式 切变变换示意图 写成切片矩阵的形式 旋转变换示意图 旋转默认以原点为旋转中心,旋转方式为逆时针旋转。 旋转矩

    2024年02月06日
    浏览(39)
  • 计算机图形学-GAMES101-4

    当我们旋转Q角度和旋转-Q角度时,变换矩阵中旋转的部分如下图所示: 旋转Q和旋转-Q的变换矩阵应该互为逆矩阵,而我们可以看到它们互为对方矩阵的转置。其实Rq是一个正交矩阵,因此其逆矩阵就是它自己的转置。当我们旋转图形一个角度为Q时,如果我们想旋转为-Q,可以

    2024年02月05日
    浏览(48)
  • 计算机图形学-GAMES101-11

    使用一系列点表示物体的表面。 理论上可以表达空间中任何物体。 如物体扫描会得到空间中一系列点,但在建模时我们要提取出大量多边形的面。 点云对密度要求很高,因此不常使用。 使用三角形表示物体。 涉及三角形之间的连接关系。  obj模型文件格式:  v表示按顺

    2024年02月05日
    浏览(36)
  • 【GAMES101】作业1(提高)与框架理解

    本次作业的任务是填写一个旋转矩阵和一个透视投影矩阵。给定三维下三个点 v0(2.0, 0.0, −2.0), v1(0.0, 2.0, −2.0), v2(−2.0, 0.0, −2.0), 你需要将这三个点的坐标变换为屏幕坐标并在屏幕上绘制出对应的线框三角形 (在代码框架中,我们已经提供了 draw_triangle 函数,所以你只需要去

    2023年04月12日
    浏览(42)
  • GAMES101 计算机图形学 | 学习笔记 (上)

    1. C++中安装opencv库 2. C++中安装eigen库 3. C++中安装openGL库 步骤(1)glut下载 4. C++安装openGL库 步骤(2)VS中安装两个NuGet程序包 5. C++安装glew和glfw工具库 要注意的是 glew.h必须包含再glut.h之前 。 如下: 计算机图形学是利用计算机技术进行图像和视觉内容的创建、处理和显示的领

    2024年02月03日
    浏览(43)
  • 【GAMES101】作业5 简单光线追踪与代码流程理解

    在这部分的课程中,我们将专注于使用光线追踪来渲染图像。在光线追踪中最重要的操作之一就是找到光线与物体的交点。一旦找到光线与物体的交点,就可以执行着色并返回像素颜色。在这次作业中,我们需要实现两个部分:光线的生成和光线与三角的相交。本次代码框架

    2024年02月06日
    浏览(38)
  • 【GAMES101】作业7(提高)路径追踪 多线程、Microfacet(全镜面反射)、抗锯齿

    在之前的练习中,我们实现了 Whitted-Style Ray Tracing 算法,并且用 BVH等加速结构对于求交过程进行了加速。在本次实验中,我们将在上一次实验的基础上实现完整的 Path Tracing 算法。至此,我们已经来到了光线追踪版块的最后一节内容。 相比上一次实验,本次实验对框架的修改

    2023年04月08日
    浏览(43)
  • games101-3 BRDF101

    本文基于知乎Maple对brdf的文章,在此基础又收集了一些其它来源的关于brdf的文章,希望能够完全理解记忆相关知识 关于Jakub Boksansky的文章,看的过程中又去搜集了很多其它文章来理解,发现已经超出了我目前的知识厚度,因此只会简单的翻译一下我能理解的部分,感兴趣的

    2024年04月25日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包