GAMES101作业2

文章目录

  • 作业内容
  • Step 1. 创建三角形的2维bounding box
  • Step 2. 判断bBox中的像素中心点是否在三角形内
  • Step 3. 比较插值深度和Depth Buffer
  • MSAA

作业内容

在屏幕上画出一个实心三角形,
换言之,栅格化一个三角形。上一次作业中,在视口变化之后,我们调用了函数
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?
    Bounding Box
    已知三角形的三个顶点,如何得出蓝色矩形的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 左下角和右上角的坐标为
在这里插入图片描述
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 内的所有像素(使用其整数索引)。然后,使用像素中心的屏幕空间坐标来检查中心点是否在三角形内。

在这里插入图片描述

在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);                    // HomogeneousVector3f 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_pqVector3f v2_tmp = (_v[2] - _v[1]).cross(p1_pq);       //p1_p2 x p1_pqVector3f v3_tmp = (_v[0] - _v[2]).cross(p2_pq);       //p2_p0 x p2_pqif ((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 valueif (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。最后,如果你实现正确的话,你得到的三角形不应该有不正常的黑边

在这里插入图片描述
在这里插入图片描述

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);}}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/3348.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

二次元少女-InsCode Stable Diffusion 美图活动一期

一、 Stable Diffusion 模型在线使用地址&#xff1a; https://inscode.csdn.net/inscode/Stable-Diffusion 二、模型相关版本和参数配置&#xff1a; 模型版本&#xff1a;chilloutmix_NiPrunedFp32Fix.safetensors 采样方法(Sampler)Sampling method&#xff1a;DPM SDE …

2023年经典【自动化面试题】附答案

一、请描述一下自动化测试流程&#xff1f; 自动化测试流程一般可以分为以下七步&#xff1a; 编写自动化测试计划&#xff1b; 设计自动化测试用例&#xff1b; 编写自动化测试框架和脚本&#xff1b; 调试并维护脚本&#xff1b; 无人值守测试&#xff1b; 后期脚本维…

【UE4 塔防游戏系列】07-子弹对敌人造成伤害

目录 效果 步骤 一、让子弹拥有不同伤害 二、敌人拥有不同血量 三、修改“BP_TowerBase”逻辑 四、发射的子弹对敌人造成伤害 效果 步骤 一、让子弹拥有不同伤害 为了让每一种子弹拥有不同的伤害值&#xff0c;打开“TotalBulletsCategory”&#xff08;所有子弹的父类…

【Spring Boot】Web开发 — Web开发简介

Web开发简介 首先介绍Spring Boot 提供的Web组件spring-boot-starter-web&#xff0c;然后介绍Controller和RestController注解&#xff0c;以及控制数据返回的ResponseBody注解&#xff0c;最后介绍Web配置&#xff0c;以便让读者对使用Spring Boot开发Web系统有初步的了解。…

linux下一个iic驱动(按键+点灯)-互斥

一、前提&#xff1a; 硬件部分&#xff1a; 1. rk3399开发板&#xff0c;其中的某一路iic&#xff0c;这个作为总线的主控制器 2. gd32单片机&#xff0c;其中的某一路iic&#xff0c;从设备。主要是按键上报和灯的亮灭控制。&#xff08;按键大约30个&#xff0c;灯在键的…

送呆萌的她一个皮卡丘(Python实现)

目录 1 呆萌的她 2 思维需要革新 3 送她的一个漂亮皮卡丘 4 Python完整代码奉上 1 呆萌的她 又是一季春风暖阳下, 你是一湾一湾羞涩的春波。 静静感受着&#xff0c; 你垂下的枝膊 在我的脸上轻轻抚摸 一对春燕,低低掠过 涟漪乍起&#xff0c;是你浅浅的笑窝...... 2 思…

(五)「消息队列」之 RabbitMQ 主题(使用 .NET 客户端)

0、引言 先决条件 本教程假设 RabbitMQ 已安装并且正在 本地主机 的标准端口&#xff08;5672&#xff09;上运行。如果您使用了不同的主机、端口或凭证&#xff0c;则要求调整连接设置。 获取帮助 如果您在阅读本教程时遇到问题&#xff0c;可以通过邮件列表或者 RabbitMQ 社区…

56 # 实现 pipe 方法进行拷贝

pipe 是异步的&#xff0c;可以实现读一点写一点&#xff0c;管道的优势&#xff1a;不会淹没可用内存&#xff0c;但是在导入的过程中无法获取到内容 const fs require("fs"); const path require("path");fs.createReadStream(path.resolve(__dirname…

前端 | (七)浮动 | 尚硅谷前端html+css零基础教程2023最新

学习来源&#xff1a;尚硅谷前端htmlcss零基础教程&#xff0c;2023最新前端开发html5css3视频 文章目录 &#x1f4da;浮动介绍&#x1f407;元素浮动后的特点&#x1f407;浮动小练习&#x1f525;盒子1右浮动&#x1f525;盒子1左浮动&#x1f525;所有盒子都浮动&#x1f5…

数学建模 插值算法

有问题 牛顿差值也有问题它们都有龙格现象&#xff0c;一般用分段插值。 插值预测要比灰色关联预测更加准确&#xff0c;灰色预测只有2次 拟合样本点要非常多&#xff0c;样本点少差值合适

Spring底层

配置文件 配置优先级 之前讲解过&#xff0c;可以用这三种方式进行配置 那如果这三种都进行了配置&#xff0c;那到底哪一份生效呢&#xff1f; 结论 优先级从大到小 properties>yml>yaml然后就是现在一般都用yml文件进行配置 其他配置方式 除了配置文件外 还有不同…

电压放大器在超声波焊接中的作用以及应用

电压放大器是一种运用于电子设备中的信号放大器&#xff0c;主要作用是将小信号放大为更高幅度的信号。在超声波焊接中&#xff0c;电压放大器起到了重要的作用&#xff0c;它可以将从传感器采集到的微小信号放大为能够被检测和处理的合适大小的信号。 超声波焊接是现代工业生产…

微信怎么自动加好友,通过好友后自动打招呼

很多客户朋友每天花大量的时间用手机搜索添加好友&#xff0c;这样的添加很集中也容易频繁&#xff0c;而且效率还低。对方通过后&#xff0c;有时也不能及时和客户搭建链接&#xff0c;导致客户也流失了。 现在可以实现自动添加和自动打招呼哦&#xff0c;只需要导入数据、设置…

【从零开始学CSS | 第二篇】伪类选择器

目录 前言&#xff1a; 伪类选择器&#xff1a; 常见的伪类选择器&#xff1a; 举例&#xff1a; 小窍门&#xff1a; 总结: 前言&#xff1a; 上一篇文章我们详细的为大家介绍了一些常见的选择器&#xff0c;这几篇我们将再次介绍CSS中的一个常见选择器——伪类选择器&am…

设计模式之适配器模式

写在前面 适配器设计模式属于结构型设计模式的一种&#xff0c;本文一起来看下。 1&#xff1a;介绍 1.1&#xff1a;什么时候适配器设计模式 当现有接口客户端无法直接调用时&#xff0c;我们可以考虑适配器设计模式&#xff0c;来定义一个能够供客户端直接调用的接口&…

软件测试的分类

代码分类&#xff1a; 1、黑盒测试 2、白盒测试 3、灰黑测试 黑盒测试&#xff1a; 把测试的对象看成是一个黑色的盒子的&#xff0c;看不到里面内部的结构&#xff0c;是对软件的一种功能性的测试。 白盒测试&#xff1a; 就是把测试的对象看成是一个透明的盒子&#x…

测试老鸟总结,性能测试-最佳并发和最大并发,性能测试实施...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 性能测试&#xf…

curl操作

下载路径&#xff1a;https://curl.se/windows/ 参考&#xff1a;https://blog.csdn.net/weixin_45191386/article/details/130652821 操作&#xff1a; curl http://localhost:8085/api/v1/aaa/bbbb/?ccc 652781344055627776

第四次CCF计算机软件能力认证

第一题&#xff1a;图像旋转 旋转是图像处理的基本操作&#xff0c;在这个问题中&#xff0c;你需要将一个图像逆时针旋转 90 度。 计算机中的图像表示可以用一个矩阵来表示&#xff0c;为了旋转一个图像&#xff0c;只需要将对应的矩阵旋转即可。 输入格式 输入的第一行包含两…

我国版式文档格式OFD前端WEB展示之EasyOFD

EasyOFD an ofd file web shower 一个在web端展示ofd文件的控件&#xff0c;该控件基于CANVAS绘制。 该控件使用了以下外部程序 1&#xff09;jszip&#xff1a;解决解压文件。 2&#xff09;x2js: 解决XML文件到JS转换 3&#xff09;easyjbig2: 解决ofd内部使用jb2文件存储的…