Games101--Assignment2
时间:2022-07-22
本文章向大家介绍Games101--Assignment2,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
Update(2020/7/9)
- 之前得到了倒置三角形,正置需要修改近平面为负值,因为框架中使用的是左手系。
- void rst::rasterizer::rasterize_triangle(const Triangle& t) 中包围盒上边界计算书写错误,应该为MAX而非MIN。
修改后的投影矩阵:
Eigen::Matrix4f get_projection_matrix(float eye_fov, float aspect_ratio, float zNear, float zFar)
{
// TODO: Use the same projection matrix from the previous assignments
Eigen::Matrix4f projection = Eigen::Matrix4f::Identity();
float n=zNear,f=zFar;
float t=-n*tan(eye_fov/2.0);//Use -n because the left-hand coordinate used in the framework
// float t=fabs(n)*tan(eye_fov/2.0); //即为倒置三角形
float r=t*aspect_ratio;
float b=-t,l=-r;
projection<<(2.0*n)/(r-l),0,(r+l)/(l-r),0,
0,(2.0*n)/(t-b),(t+b)/(b-t),0,
0,0,(n+f)/(n-f),(2.0*n*f)/(f-n),
0,0,1,0;
return projection;
}
要求
Gams101的Assignment2的要求如下:
修改函数rasterize_triangle(const Triangle& t)。 该函数的内部工作流程如下:
- 创建三角形的2 维bounding box。
- 遍历此bounding box 内的所有像素(使用其整数索引)。然后,使用像素中 心的屏幕空间坐标来检查中心点是否在三角形内。
- 如果在内部,则将其位置处的插值深度值(interpolated depth value) 与深度 缓冲区(depth buffer) 中的相应值进行比较。
- 如果当前点更靠近相机,请设置像素颜色并更新深度缓冲区(depth buffer)。
需要修改的函数如下: • rasterize_triangle(): 执行三角形栅格化算法 • static bool insideTriangle(): 测试点是否在三角形内。
判断点是否在三角形内,只要用叉积来判断方向即可。
static bool insideTriangle(float x, float 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]
float a=_v[0].x(),b=_v[0].y(),c=_v[1].x(),d=_v[1].y(),e=_v[2].x(),f=_v[2].y();
float t1=(c-a)*(y-b)-(d-b)*(x-a);
float t2=(e-c)*(y-d)-(f-d)*(x-c);
float t3=(a-e)*(y-f)-(b-f)*(x-e);
bool x1=true?t1>0.0:false,x2=true?t2>0.0:false,x3=true?t3>0.0:false;
bool ret=false;
if((x1 &x2&x3) || (!x1)&(!x2)&(!x3)) ret=true;
return ret;
}
rasterize_triangle(),使用MSAA,用的是4x4的supersampling。
//Screen space rasterization
void rst::rasterizer::rasterize_triangle(const Triangle& t) {
auto v = t.toVector4();
// TODO : Find out the bounding box of current triangle.
// iterate through the pixel and find if the current pixel is inside the triangle
int left=MIN(v[0].x(),MIN(v[1].x(),v[2].x()))-1;
int right=MAX(v[0].x(),MAX(v[1].x(),v[2].x()))+1;
int bottom=MIN(v[0].y(),MIN(v[1].y(),v[2].y()))-1;
int top=MAX(v[0].y(),MAX(v[1].y(),v[2].y()))+1;
//修正top计算书写错误,应该取最大值
bool MSAA=true;
//4x4 SuperSampling
float dir[16][2]={
{0.125,0.125},
{0.125,0.375},
{0.125,0.625},
{0.125,0.875},
{0.375,0.125},
{0.375,0.375},
{0.375,0.625},
{0.375,0.875},
{0.625,0.125},
{0.625,0.375},
{0.625,0.625},
{0.625,0.875},
{0.875,0.125},
{0.875,0.375},
{0.875,0.625},
{0.875,0.875},
};
if(MSAA){
for(int x=left;x<=right;x++){
for(int y=bottom;y<=top;y++){
float min_dep=0x7f7ffff;
int count=0;
for(int i=0;i<16;i++){
if(insideTriangle(x+dir[i][0],y+dir[i][1],t.v)){
count++;
std::tuple<float, float, float> alpha= computeBarycentric2D(x, y, t.v);
float w_reciprocal = 1.0/(std::get<0>(alpha) / v[0].w() + std::get<1>(alpha) / v[1].w() + std::get<2>(alpha) / v[2].w());
float z_interpolated = std::get<0>(alpha)* v[0].z() / v[0].w() + std::get<1>(alpha) * v[1].z() / v[1].w() + std::get<2>(alpha) * v[2].z() / v[2].w();
z_interpolated *= w_reciprocal;
min_dep=MIN(min_dep,z_interpolated);
}
}
if(count==0)continue;
if(min_dep < depth_buf[get_index(x,y)]){
depth_buf[get_index(x,y)]=min_dep;
set_pixel(Vector3f(x,y,min_dep),t.getColor()*count/16.0);
}
}
}
}
else
{
for(int x=left;x<=right;x++){
for(int y=bottom;y<=top;y++){
if(insideTriangle(x,y,t.v)){
std::tuple<float, float, float> alpha= computeBarycentric2D(x, y, t.v);
float w_reciprocal = 1.0/(std::get<0>(alpha) / v[0].w() + std::get<1>(alpha) / v[1].w() + std::get<2>(alpha) / v[2].w());
float z_interpolated = std::get<0>(alpha)* v[0].z() / v[0].w() + std::get<1>(alpha) * v[1].z() / v[1].w() + std::get<2>(alpha) * v[2].z() / v[2].w();
z_interpolated *= w_reciprocal;
if(z_interpolated<depth_buf[get_index(x,y)]){
depth_buf[get_index(x,y)]=z_interpolated;
set_pixel(Vector3f(x,y,z_interpolated),t.getColor());
}
}
}
}
}
// If so, use the following code to get the interpolated z value.
//auto tpp = computeBarycentric2D(x, y, t.v);
//float alpha, beta, gamma;
//std::tie(alpha, beta, gamma)=tpp;
//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;
// TODO : set the current pixel (use the set_pixel function) to the color of the triangle (use getColor function) if it should be painted.
}
如果不用MSAA,则代码如下:
//Screen space rasterization
void rst::rasterizer::rasterize_triangle(const Triangle& t) {
auto v = t.toVector4();
// TODO : Find out the bounding box of current triangle.
// iterate through the pixel and find if the current pixel is inside the triangle
int left=MIN(v[0].x(),MIN(v[1].x(),v[2].x()))-1;
int right=MAX(v[0].x(),MAX(v[1].x(),v[2].x()))+1;
int bottom=MIN(v[0].y(),MIN(v[1].y(),v[2].y()))-1;
int top=MAX(v[0].y(),MIN(v[1].y(),v[2].y()))+1;
for(int x=left;x<=right;x++)
{
for(int y=bottom;y<=top;y++)
{
if(insideTriangle(x,y,t.v))
{
std::tuple<float, float, float> alpha= computeBarycentric2D(x, y, t.v);
float w_reciprocal = 1.0/(std::get<0>(alpha) / v[0].w() + std::get<1>(alpha) / v[1].w() + std::get<2>(alpha) / v[2].w());
float z_interpolated = std::get<0>(alpha)* v[0].z() / v[0].w() + std::get<1>(alpha) * v[1].z() / v[1].w() + std::get<2>(alpha) * v[2].z() / v[2].w();
z_interpolated *= w_reciprocal;
if(z_interpolated<depth_buf[get_index(x,y)])
{
depth_buf[get_index(x,y)]=z_interpolated;
set_pixel(Vector3f(x,y,z_interpolated),t.getColor());
}
}
}
}
// If so, use the following code to get the interpolated z value.
//auto tpp = computeBarycentric2D(x, y, t.v);
//float alpha, beta, gamma;
//std::tie(alpha, beta, gamma)=tpp;
//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;
// TODO : set the current pixel (use the set_pixel function) to the color of the triangle (use getColor function) if it should be painted.
}
结果
两者对比结果如下:
- Java高级进阶:自定义ClassLoader
- 字符串拼接+和concat的区别
- Spring Boot Runner启动器
- Spring Boot自动配置原理、实战
- Spring Aware容器感知技术
- 深入探究frame和bounds的区别以及setbounds使用
- 如何生成二维码过程详解
- hashCode和identityHashCode的区别你知道吗?
- SpringCloud注册中心高可用搭建
- SpringMVC表单验证器的使用
- Hadoop作业提交与执行源码分析
- 一分钟开启Tomcat https支持
- Spring Enable*高级应用及原理
- 各hbase版本对hadoop各版本的支持情况
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- java中的reference(二): jdk1.8中Reference的源码阅读
- 08 Confluent_Kafka权威指南 第八章:跨集群数据镜像
- java的reference(五): WeakReference的应用之二--InheritableThreadLocal源码分析
- rabbitmq-3.7.7安装过程
- 09 Confluent_Kafka权威指南 第九章:管理kafka集群
- 关于禁止使用Executors创建线程池的分析
- ArrayList源码分析(基于jdk1.8)(一):源码及基本操作
- ArrayList源码分析(基于jdk1.8)(二):subList陷阱
- 【每日一题】31. Next Permutation
- 关于聚合和多线程的处理套路
- Jboss漏洞利用总结
- 二次注入——sqli-labs第24关
- OCMock 源码分析
- MessageMock : 优雅的模拟 Objective-C 方法
- 10 个最佳 CSS 动画库