完成函数static bool insideTriangle(): 测试点是否在三角形内。

一段优雅的easy代码,没什么好说的。(但是需要修改这里传入的xy的类型为float,默认为int是想让我通过修改返回值的方式来实现MSAA:例如返回一个int值,这里传入单个像素坐标后在insideTriangle函数中实现超采样,然后返回k,再在设置颜色时* k/4)

static bool insideTriangle(float x, float y, const Vector3f* _v)
{
// TODO : Implement this function to check if the point p(x, y) is inside the triangle represented by _v[0], _v[1], _v[2] (a, b, c)
// 如果p(x,y)与三点a、b、c构成的向量x乘同向(z坐标都为正)则在其内部
// 构建向量
Vector3f p = Vector3f(x, y, 1);
Vector3f ap = p - _v[0];
Vector3f bp = p - _v[1];
Vector3f cp = p - _v[2];
Vector3f ab = _v[1] - _v[0];
Vector3f bc = _v[2] - _v[1];
Vector3f ca = _v[0] - _v[2];
// 运算x乘结果的z值
float z1 = ab.cross(ap).z(); //ab x ap
float z2 = bc.cross(bp).z(); //bc x bp
float z3 = ca.cross(cp).z(); //ca x cp
// in Triangle
return (z1 > 0 && z2 > 0 && z3 > 0) || (z1 < 0 && z2 < 0 && z3 < 0);
}

rasterize_triangle(): 执行三角形栅格化算法

在采样点在三角形内部时更新z_buffer和frame_buffer(这里使用了MSAA,故颜色值需乘以一个float的k)

//Screen space rasterization
void rst::rasterizer::rasterize_triangle(const Triangle& t) {
auto v = t.toVector4();
// 获取三角形数据并分别传入 insideTriangle()
Vector3f triangle[3];
for(int i = 0; i < 3; i++){
triangle[i] = Vector3f(v[i].x(), v[i].y(), v[i].z());
} // TODO : Find out the bounding box of current triangle.
float min_x = std::min(v[0].x(), std::min(v[1].x(), v[2].x()));
float max_x = std::max(v[0].x(), std::max(v[1].x(), v[2].x()));
float min_y = std::min(v[0].y(), std::min(v[1].y(), v[2].y()));
float max_y = std::max(v[0].y(), std::max(v[1].y(), v[2].y())); // iterate through the pixel and find if the current pixel is inside the triangle
// frame_buffer 和 z_buffer早已定义好
for(int x = min_x; x <= max_x; x++){
for(int y = min_y; y <= max_y; y++){
// MSAA version
float k = 0;
if(insideTriangle(0.25 + x, 0.25 + y, triangle)) k += 0.25;
if(insideTriangle(0.75 + x, 0.25 + y, triangle)) k += 0.25;
if(insideTriangle(0.25 + x, 0.75 + y, triangle)) k += 0.25;
if(insideTriangle(0.75 + x, 0.75 + y, triangle)) k += 0.25;
if(k != 0){
// Simple Sampling
//if(insideTriangle(x + 0.5, y + 0.5, triangle)){
// 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; if(z_interpolated < depth_buf[get_index(x, y)]){
// TODO : set the current pixel (use the set_pixel function) to the color of the triangle (use getColor function) if it should be painted.
depth_buf[get_index(x, y)] = z_interpolated;
//set_pixel(Vector3f(x, y, 1), t.getColor());
set_pixel(Vector3f(x, y, 1),k * t.getColor());
}
}
}
}
}

值得注意的是,这里zNear和zFar使用的是正值,故在main.cpp中需要修改float t = -1 * abs(zNear) * tanf(eye_fov / 2);将其y轴颠倒一下才能做出正确图形(第八节课讲这是左手右手系的原因)

注:MSAA将会导致黑线是正常的,因为我们在计算边缘像素时他的z是高于下方三角形的,但实际可能覆盖面积过小导致0.25*color,故出现黑线

随机推荐

  1. 如何将Linux的NIC 名称更改为 eth0 而不是 enps33 或 enp0s25,只要几秒钟

    概述 我们使用Linux系统,网卡名称通常都是eth0,但是有一些新的linux发行版,网卡名字 enps33 或 enp0s25. peng@ubuntu:~$ ifconfig ens33 Lin ...

  2. 粉丝提问|c语言:如何定义一个和库函数名一样的函数,并在函数中调用该库函数

    问题描述: 某个函数fun_1()是在lib内,没法修改的,在程序中大量的使用了该函数,现在想把原本fun_1失效(现在失效的方法是#define fun_1(..)),用另外一个函数fun_2(), ...

  3. nginx配置请求头防止点击劫持

    在返回index.html配置中加入add_header X-Frame-Options DENY; location / {undefined root /data/nginx/html/dist/ ...

  4. Echarts 5 动态按需引入图表

    官网提供的按需引入方法为全量按需引入,在打包分离中,仍旧存在使用不到的图表被打包进去. 例如:组件A使用了折线图.柱状图,组件B只用到了折线图,但是打包组件B的时候,柱状图也就被打包进去. 本文提供一 ...

  5. NeoVim 安装

    NeoVim 官网 安装 macOS brew install neovim Windows 使用 winget: winget install Neovim.Neovim 也可以使用 scoop: ...

  6. SpringMVC的视图

    目录 ThymeleafView 转发视图 重定向视图 视图控制器view-controller SpringMVC中的视图是View接口,视图的作用渲染数据,将模型Model中的数据展示给用户Spr ...

  7. Zabbix-(1)安装

    环境: VMware Workstation Pro 16.0 版本 系统 Centos7 内存 2G 处理器 1G 硬盘 20G 网络适配器 NAT 服务器地址:192.168.220.40 1.安 ...

  8. C++: 智能指针的自定义删除器 `Custom Deleter` 有什么用?

    C++11智能指针std::shared_ptr和std::unique_ptr都支持自定义删除器,本文将介绍自定义删除器的使用场景和使用方法.智能指针模板参数的第二个类型是删除器,一般是一个函数指针 ...

  9. Angular 18+ 高级教程 – Prettier, ESLint, Stylelint

    前言 不熟悉 Prettier, ESLint, Stylelint 的朋友可以先看这篇 工具 – Prettier.ESLint.Stylelint. 首先,Angular 没有 built-in ...

  10. nRF24L01芯片驱动记录

    nRF24L01芯片驱动记录 ​ 学习完了usb,了解了部分元器件的功能以及用途后,打算在端午假期用一天的时间完成一个小目标,不过实际上是花了一天半才成功实现,现将驱动nRF24L01芯片的整个过程记 ...