应该是最菜的一批了,每个作业都做的磕磕绊绊,已经有点感觉了,基本上都是自己写的。最后才来参考下别人的答案,希望能有所进步。
配置
依然是这次作业用到的东西。怎么在新建项目时,不用重复配置:http://t.csdn.cn/XRtCd
写作业时的问题
浏览完作业,有几个问题,挨着排出来,挨着把这些问题解决,发现自己基本上也把这道题给做出来了。果然梳理一下还是很有用。
1.因为画面内每个像素都需要对比是否在三角形内,画面的尺寸怎么找
解决: 找到三角形的边界,将给出的三角形三个点求x,y的最小最大值(直接用t.v[][]来比较)。作业这里其实也提示了…但是第一次完全没有读懂他的意思,还是要自己从头捋一次。
// TODO : Find out the bounding box of current triangle.
//需要做的:找到当前三角形的边界
2.不改变原函数定义的话, static bool insideTriangle()应该怎么使用。是输入画面内像素的x,y还有三角形其中一条边长?
解决: Vector3f* 的意思就是数组,直接把三角形的三个点全部传过去了。所以直接传入t.v。太菜了,居然没有一眼明白。
3.depth buffer怎么使用。
解决: 确实是自己c++基础太差了,自己看了好久都没看懂到底怎么使用depth_buf。最后还是看了下其他人的答案才明白过来,但是整体框架自己也都写好了,就差了这一个函数。
作业的思路
1.找到三角形x轴和y轴的最大最小值。
2.两个嵌套for循环,依次遍历所有的点,对其进行判断是否在三角形内。分别用点和3条边进行叉乘。
点乘和叉乘:https://www.csdn.net/tags/NtjaUg4sNDYwMjQtYmxvZwO0O0OO0O0O.html
3.如果在三角形内,直接用老师给出的几行代码,得到z的坐标。如果z的坐标小于缓冲区的值,则更新缓冲区的值,并设置颜色set_pixel()
代码
static bool insideTriangle(int x, int y, const Vector3f* _v)
{
Vector3f pixel(x, y, 0);
Vector3f dot[4];//三角形三个点
float equ[3];
for (int i = 0; i < 3; i++) {
dot[i] = _v[i];
dot[i][2] = 0;//不知道把z轴加进去计算有没有影响,干脆把z给变成0
}
dot[3] = _v[0];
dot[3][2] = 0;
for (int i = 0; i < 3; i++) {//进行三次叉乘,并且把y的坐标保存。
Vector3f ve=(dot[i + 1] - dot[i]).cross(pixel - dot[i]);//叉乘运算
equ[i] = ve[2];
}
if ((equ[0] > 0 && equ[1] > 0 && equ[2] > 0) || (equ[0] < 0 && equ[1] < 0 && equ[2] < 0)) {//如果三个y的符号相同,则返回true
return true;
}
return false;
// TODO : Implement this function to check if the point (x, y) is inside the triangle represented by _v[0], _v[1], _v[2]
//需要做的:执行此函数以检查点(x,y)是否位于由_v[0]、_v[1]、_v[2]表示的三角形内
}
//Screen space rasterization
void rst::rasterizer::rasterize_triangle(const Triangle& t) {
auto v = t.toVector4();
float xmin, xmax, ymin, ymax;
float alpha, beta, gamma;
// std::tuple<float, float, float> angle(alpha, beta, gamma);
xmin = t.v[0][0] < (t.v[1][0] < t.v[2][0] ? t.v[1][0] : t.v[2][0]) ? t.v[0][0] : (t.v[1][0] < t.v[2][0] ? t.v[1][0] : t.v[2][0]);//最左边边界,最小值
xmax = t.v[0][0] > (t.v[1][0] > t.v[2][0] ? t.v[1][0] : t.v[2][0]) ? t.v[0][0] : (t.v[1][0] > t.v[2][0] ? t.v[1][0] : t.v[2][0]);//最右边边界,最大值
ymin= t.v[0][1] < (t.v[1][1] < t.v[2][1] ? t.v[1][1] : t.v[2][1]) ? t.v[0][1] : (t.v[1][1] < t.v[2][1] ? t.v[1][1] : t.v[2][1]);//最矮,最小值
ymax = t.v[0][1] > (t.v[1][1] > t.v[2][1] ? t.v[1][1] : t.v[2][1]) ? t.v[0][1] : (t.v[1][1] > t.v[2][1] ? t.v[1][1] : t.v[2][1]);//最高,最大值
int x_min = xmin, x_max = xmax, y_min = ymin, y_max = ymax;
//遍历所有坐标
for (int x = x_min; x <= x_max; x++) {
for (int y = y_min; y <= y_max; y++) {
//这里加不加0.5目前看来都好像没有影响,只是看好多人都是加上的,我也加上了
if (insideTriangle(x+0.5, y+0.5, t.v)) {//如果在三角形内
// auto angle = computeBarycentric2D(x+0.5, y+0.5, t.v);
auto [alpha, beta, gamma] = computeBarycentric2D(x+0.5, 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;
Vector3f nowpixel(x, y, z_interpolated);
if (z_interpolated < depth_buf[get_index(x, y)]) {//如果z的坐标小于缓冲区,则更新并且获取颜色
depth_buf[get_index(x, y)] = z_interpolated;
set_pixel(nowpixel, t.getColor());
}
}
}
}
// TODO : Find out the bounding box of current triangle.
//需要做的:找到当前三角形的边界
// iterate through the pixel and find if the current pixel is inside the triangle
//遍历像素,并确定当前像素是否在三角形内
// If so, use the following code to get the interpolated z value.
//如果在三角形内,根据下面的代码得到z轴的值
//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;
// 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函数)设置为三角形的颜色(使用getColor函数)。
}
运行结果
存在问题
1.代码看着有点冗余,但是不太会简化。有机会再简化。
2.auto[alpha, beta, gamma] = computeBarycentric2D(x, y, t.v);这句代码用不了,只能自己试着改改了。
解决:还是只能用老师的代码,之前报错可能是因为x,y的值代入了整数。否则按照自己写的
std::tuple<float, float, float> angle(alpha, beta, gamma);
auto angle = computeBarycentric2D(x, y, t.v);
会在作业3中出现问题,还是不知道为什么会有问题。。。
3.main函数中每次循环都很慢,不知道是当前作业限制还是自己的代码问题。
4.提高版完全看不懂。