说明

该作业主要想实现两个三角形的绘制

绘制结果走样

按照课上所讲的方法,对包围盒里面的所有像素进行判断是否在三角形内,然后着色,这样的结果由于采样频率的问题将导致边缘走样现象的发生

if(!insideTriangle(P.x(),P.y(),t.v)) continue;
int cur_index = get_index(P.x(),P.y());
//重心坐标
auto[alpha, beta, gamma] = computeBarycentric2D(P.x(), P.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 -- zbuffer
z_interpolated *= w_reciprocal;
if(z_interpolated < depth_buf[cur_index])
{
depth_buf[cur_index] = z_interpolated;
P.z() = z_interpolated;
set_pixel(P,t.getColor());
}

使用MSAA处理结果 -- 有黑边的情况

采用4xMSAA来进行卷积模糊,即将一个像素块分成4个采样区域。然后分别计算这个4个采样区域能否被三角形覆盖,最后最终的像素颜色就是这4块区域的平均值。

float basec = 4.0f;
float dir[4][2] = {0.25,0.25,0.25,0.75,0.75,0.25,0.75,0.75};
for(P.x()=minx;P.x()<=maxx;P.x()++)
{
for(P.y() = miny;P.y() <= maxy;P.y()++)
{
float count = 0.0;
for(float x = 0.25;x<1.0;x+=0.5)
{
for(float y = 0.25;y<1.0;y+=0.5)
{
//统计有多少个采样点在三角形内
if(insideTriangle(P.x()+x,P.y()+y,t.v))
{
count += 1.0;
}
}
}
if(insideTriangle(P.x()+0.5,P.y()+0.5,t.v))
{
auto[alpha, beta, gamma] = computeBarycentric2D(P.x()+0.5, P.y()+0.5, 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;
if(z_interpolated < depth_buf[get_index(P.x(),P.y())])
{
depth_buf[get_index(P.x(),P.y())] = z_interpolated;
P.z() = 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(P,t.getColor());
//最终颜色为平均值
Eigen::Vector3f color = t.getColor() * (count/basec);
//black edge -- the edge color is averge by green and blue but last code not do this
set_pixel(P,color);
}
}
}

黑边出现的原因

对于边缘重叠部分,由于绿色三角形的z值小,所以体现出绘制颜色为绿色,而当考虑4个采样点的情况,当只有一个采样点在绿色三角形内,其余三个在蓝色三角形内。实际最终颜色应该为1/4 green + 3/4 blue。

而上述代码只考虑覆盖,所以导致最终颜色为1/4 green 出现黑边

MSAA -- 解决黑边

在作业中说到需要为每个像素点存储颜色和深度。

最终一个像素的颜色应当是存储的这四个颜色的平均值。

//the start loc of this 2*2 area
int loc_start = get_index(P.x(),P.y())*4;
//this pixel real dep
float mindep = FLT_MAX;
//4xMSAA
float count = 0.0;
for(int k = 0;k<4;k++)
{
float curx = P.x()+dir[k][0];
float cury = P.y()+dir[k][1];
if(insideTriangle(curx,cury,t.v))
{
//calculate every sample color and dep save in sample_dep and sample_color
auto[alpha, beta, gamma] = computeBarycentric2D(curx, cury, 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;
//one sample
if(z_interpolated < sample_dep[loc_start+k])
{
sample_dep[loc_start+k] = z_interpolated;
sample_color[loc_start+k] = t.getColor()/4;
}
//this pixel dep == min(4 sample dep)
mindep = std::min(mindep,sample_dep[loc_start+k]);
}
}
//set color for this pixel
Eigen::Vector3f color = sample_color[loc_start]+sample_color[loc_start+1]+sample_color[loc_start+2]+sample_color[loc_start+3];
//get dep of this pixel
depth_buf[get_index(P.x(),P.y())] = std::min(mindep,depth_buf[get_index(P.x(),P.y())]);
P.z() = depth_buf[get_index(P.x(),P.y())];
set_pixel(P,color);

Games101--作业2的更多相关文章

  1. GAMES101作业2

    作业任务: 填写并调用函数 rasterize_triangle(const Triangle& t). 即实现光栅化 该函数的内部工作流程如下: 创建三角形的 2 维 bounding bo ...

  2. 【UE4】GAMES101 图形学作业2:光栅化和深度缓存

    总览 在上次作业中,虽然我们在屏幕上画出一个线框三角形,但这看起来并不是那么的有趣.所以这一次我们继续推进一步--在屏幕上画出一个实心三角形,换言之,栅格化一个三角形.上一次作业中,在视口变化之后,我 ...

  3. 【UE4】GAMES101 图形学作业5:光线与物体相交(球、三角面)

    总览 在这部分的课程中,我们将专注于使用光线追踪来渲染图像.在光线追踪中最重要的操作之一就是找到光线与物体的交点.一旦找到光线与物体的交点,就可以执行着色并返回像素颜色. 在这次作业中,我们要实现两个 ...

  4. 【UE4】GAMES101 图形学作业4:贝塞尔曲线

    总览 Bézier 曲线是一种用于计算机图形学的参数曲线. 在本次作业中,你需要实现de Casteljau 算法来绘制由4 个控制点表示的Bézier 曲线(当你正确实现该算法时,你可以支持绘制由更 ...

  5. 【UE4】GAMES101 图形学作业3:Blinn-Phong 模型与着色

    总览 在这次编程任务中,我们会进一步模拟现代图形技术.我们在代码中添加了Object Loader(用于加载三维模型), Vertex Shader 与Fragment Shader,并且支持了纹理映 ...

  6. 【UE4】GAMES101 图形学作业1:mvp 模型、视图、投影变换

    总览 到目前为止,我们已经学习了如何使用矩阵变换来排列二维或三维空间中的对象.所以现在是时候通过实现一些简单的变换矩阵来获得一些实际经验了.在接下来的三次作业中,我们将要求你去模拟一个基于CPU 的光 ...

  7. 【UE4】GAMES101 图形学作业0:矩阵初识

    作业描述 给定一个点P=(2,1), 将该点绕原点先逆时针旋转45◦,再平移(1,2), 计算出变换后点的坐标(要求用齐次坐标进行计算). UE4 知识点 主要矩阵 FMatrix FBasisVec ...

  8. python10作业思路及源码:类Fabric主机管理程序开发(仅供参考)

    类Fabric主机管理程序开发 一,作业要求 1, 运行程序列出主机组或者主机列表(已完成) 2,选择指定主机或主机组(已完成) 3,选择主机或主机组传送文件(上传/下载)(已完成) 4,充分使用多线 ...

  9. SQLServer2005创建定时作业任务

    SQLServer定时作业任务:即数据库自动按照定时执行的作业任务,具有周期性不需要人工干预的特点 创建步骤:(使用最高权限的账户登录--sa) 一.启动SQL Server代理(SQL Server ...

  10. 使用T-SQL找出执行时间过长的作业

        有些时候,有些作业遇到问题执行时间过长,因此我写了一个脚本可以根据历史记录,找出执行时间过长的作业,在监控中就可以及时发现这些作业并尽早解决,代码如下:   SELECT sj.name , ...

随机推荐

  1. Swoole从入门到入土(7)——TCP服务器[大杂烩]

    这一篇是异步风格的TCP服务器的最后一篇,主要的目的是疏理之前几篇没提到的一些比较有用的属性.配置.函数与事件,当然不是全部.如果想知道全部,请查看官网. 1.属性 Swoole\Server-> ...

  2. acm数学总结

    1.给定两个质数,m, n, 大于n * m - n - m的数都可以被整数个n和m唯一组成. 相关习题:[Coins] (https://ac.nowcoder.com/acm/contest/34 ...

  3. 【Android逆向】Frida 无脑暴力破解看雪test2.apk

    1. 安装apk到手机 adb install -t test2.apk apk下载位置: https://www.kanxue.com/work-task_read-800625.htm 2. 题目 ...

  4. Linux驱动开发笔记(一):helloworld驱动源码编写、makefile编写以及驱动编译基本流程

    前言   基于linux的驱动开发学习笔记,本篇是描述了一个字符驱动的基础开发流程,以便做嵌入式开发多年的应用或者系统学习驱动开发.   笔者自身情况   笔者拥有硬件基础,单片机软硬基础,linux ...

  5. 异步aioredis连接时报错TypeError: duplicate base class TimeoutError问题

    版本 python3.11版本,aioredis 2.0.1版本,redis 7.x版本 redis.conf配置文件 daemonize yes bind 0.0.0.0 port 6379 pro ...

  6. Mac环境下, VMware Fusion Pro下的虚拟机( CentOS 7)的 NAT网络配置

    前提实现说明 1.vm版本VMware Fusion Pro 12.1.0 2.centos版本centos7.6 1.虚拟机能访问外网,虚拟机能访问mac本机: 2.mac本机可以连接虚拟机 操作步 ...

  7. 制作docker方式执行Gitlab Runner所需要的镜像

    背景知识 启动Gitlab Runner时,使用Gitlab提供的官方镜像gitlab/gitlab-runner:latest即可. Runner以容器的方式启动以后,根据前文我们注册到Gitlab ...

  8. MySQL 数据库死锁排查

    死锁排查方法 查看进程状态 show processlist; 查看行锁的状态 show status like 'InnoDB_row_lock%'; 查询是否有死锁 show engine inn ...

  9. 【Azure 应用服务】Java ODBC代码中,启用 Managed Identity 登录 SQL Server 报错 Managed Identity authentication is not available

    问题描述 在App Service中启用Identity后,使用系统自动生成 Identity. 使用如下代码连接数据库 SQL Server: SQLServerDataSource dataSou ...

  10. 【Azure 应用服务】Azure Function Python函数中,如何获取Event Hub Trigger的消息Event所属于的PartitionID呢?

    问题描述 在通过Azure Function消费Event Hub中的消息时,我们从Function 的 Trigger Details 日志中,可以获得当前Funciton中处理的消息是哪一个分区( ...