Games101--作业2
说明
该作业主要想实现两个三角形的绘制
绘制结果走样
按照课上所讲的方法,对包围盒里面的所有像素进行判断是否在三角形内,然后着色,这样的结果由于采样频率的问题将导致边缘走样现象的发生
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的更多相关文章
- GAMES101作业2
作业任务: 填写并调用函数 rasterize_triangle(const Triangle& t). 即实现光栅化 该函数的内部工作流程如下: 创建三角形的 2 维 bounding bo ...
- 【UE4】GAMES101 图形学作业2:光栅化和深度缓存
总览 在上次作业中,虽然我们在屏幕上画出一个线框三角形,但这看起来并不是那么的有趣.所以这一次我们继续推进一步--在屏幕上画出一个实心三角形,换言之,栅格化一个三角形.上一次作业中,在视口变化之后,我 ...
- 【UE4】GAMES101 图形学作业5:光线与物体相交(球、三角面)
总览 在这部分的课程中,我们将专注于使用光线追踪来渲染图像.在光线追踪中最重要的操作之一就是找到光线与物体的交点.一旦找到光线与物体的交点,就可以执行着色并返回像素颜色. 在这次作业中,我们要实现两个 ...
- 【UE4】GAMES101 图形学作业4:贝塞尔曲线
总览 Bézier 曲线是一种用于计算机图形学的参数曲线. 在本次作业中,你需要实现de Casteljau 算法来绘制由4 个控制点表示的Bézier 曲线(当你正确实现该算法时,你可以支持绘制由更 ...
- 【UE4】GAMES101 图形学作业3:Blinn-Phong 模型与着色
总览 在这次编程任务中,我们会进一步模拟现代图形技术.我们在代码中添加了Object Loader(用于加载三维模型), Vertex Shader 与Fragment Shader,并且支持了纹理映 ...
- 【UE4】GAMES101 图形学作业1:mvp 模型、视图、投影变换
总览 到目前为止,我们已经学习了如何使用矩阵变换来排列二维或三维空间中的对象.所以现在是时候通过实现一些简单的变换矩阵来获得一些实际经验了.在接下来的三次作业中,我们将要求你去模拟一个基于CPU 的光 ...
- 【UE4】GAMES101 图形学作业0:矩阵初识
作业描述 给定一个点P=(2,1), 将该点绕原点先逆时针旋转45◦,再平移(1,2), 计算出变换后点的坐标(要求用齐次坐标进行计算). UE4 知识点 主要矩阵 FMatrix FBasisVec ...
- python10作业思路及源码:类Fabric主机管理程序开发(仅供参考)
类Fabric主机管理程序开发 一,作业要求 1, 运行程序列出主机组或者主机列表(已完成) 2,选择指定主机或主机组(已完成) 3,选择主机或主机组传送文件(上传/下载)(已完成) 4,充分使用多线 ...
- SQLServer2005创建定时作业任务
SQLServer定时作业任务:即数据库自动按照定时执行的作业任务,具有周期性不需要人工干预的特点 创建步骤:(使用最高权限的账户登录--sa) 一.启动SQL Server代理(SQL Server ...
- 使用T-SQL找出执行时间过长的作业
有些时候,有些作业遇到问题执行时间过长,因此我写了一个脚本可以根据历史记录,找出执行时间过长的作业,在监控中就可以及时发现这些作业并尽早解决,代码如下: SELECT sj.name , ...
随机推荐
- G water testing题解
G water testing 题意:给你一个多边形(可能是凸多边形,也可能是凹多边形),问该多边形内有多少个整数点(不包含边界). 思路:皮克定理 + 叉乘计算三角形面积:皮克定理是指一个计算点阵中 ...
- 我的小程序之旅五:微信公众号扫码登录PC端网页
代码仓库:https://gitee.com/wlovet/gzh-qrlogin 一.准备材料 1.已认证的公众号(必须为服务号,订阅号没有该接口的权限) 2.一个网址,用于微信回调,推荐一个内网穿 ...
- k8s(Kubernetes) 常用命令配置
一.基础命令 $ kubectl create -f ./my-manifest.yaml # 创建资源 $ kubectl create -f ./my1.yaml -f ./my2.yaml # ...
- 从 vs 的 rc 文件中获取版本号
更新项目版本号时,需要与 rc 文件的 version 同步,比较方便的方法是直接从 rc 文件中获取版本号,并应用到程序中 // 删除日志检查 bool GetVersion() { // get ...
- window上使用Putty通过ssh远程连接并通过Xming实现X11图形界面功能
# 0.先确认远程服务器的ssh配置 >>> grep X11 /etc/ssh/sshd_config X11Forwarding yes #X11DisplayOffset 10 ...
- SOTIF很快将会取代ISO 26262?为您详细解读SOTIF标准ISO/PAS 21448
SOTIF很快将会取代ISO 26262?为您详细解读SOTIF标准ISO/PAS 21448 根据MES模赛思对其全球客户的问卷调查表明, 尽管有相当一部分的参与者(35%)认为SOTIF在功能安全 ...
- 浅入ABP(2):添加基础集成服务
浅入ABP(2):添加基础集成服务 版权护体作者:痴者工良,微信公众号转载文章需要 <NCC开源社区>同意. 目录 浅入ABP(2):添加基础集成服务 定义一个特性标记 全局统一消息格式 ...
- [Python] 子线程退出孙线程不退出
遇到了一个大坑! 如图,在子线程ThreadFunc退出之后,ThreadFunc2依旧在运行... 根本不会结束 但是官方文档中说明了,只要设置了daemon不为None 就能设置子线程是守护线程, ...
- 想做大模型开发前,先来了解一下MoE
为了实现大模型的高效训练和推理,混合专家模型MoE便横空出世. 大模型发展即将进入下一阶段但目前仍面临众多难题.为满足与日俱增的实际需求,大模型参数会越来越大,数据集类型越来越多,从而导致训练难度大增 ...
- mysql添加联合唯一索引与删除索引
-- 添加联合唯一索引 alter table <表名> add unique index <索引名称> (name, no, org_id); -- 删除索引 ALTER T ...