本文最后更新于 2024-11-17T14:19:20+00:00
Games101 HomeWork2
导航
导航
作业要求
rasterize_triangle(): 执行三角形栅格化算法
static bool insideTriangle(): 测试点是否在三角形内。你可以修改此函数的定义,这意味着,你可以按照自己的方式更新返回类型或函数参数。
先从简单的函数开始
insideTriangle
insideTriangle
只需要检查点是否在三角形内部,我并没有修改函数的定义,是否在三角形中,返回一个bool 类型的值似乎挺正常的。
判断一个点是否在三角形中其实是挺简单的,这里用了课程中用到的差乘法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 static bool insideTriangle (float x, float y, const Vector3f* _v) { Vector3f P=Vector3f(x,y,_v[0 ].z()); Vector3f AC=_v[2 ]-_v[0 ]; Vector3f CB=_v[1 ]-_v[2 ]; Vector3f BA=_v[0 ]-_v[1 ]; Vector3f AP=P-_v[0 ]; Vector3f BP=P-_v[1 ]; Vector3f CP=P-_v[2 ]; if (AP.cross(AC).dot(BP.cross(BA))>0.0f && BP.cross(BA).dot(CP.cross(CB))>0.0f && CP.cross(CB).dot(AP.cross(AC))>0.0f ) { return true ; } return false ; }
然后是光栅化的实现了
rasterize_triangle
首先我们要找到三角形的一个包围盒(Bunding Box)然后遍历包围盒中的点,如果点在三角形内部,使用重心公式插值得到z值(这部分框架中已经给出实现
),并且深度小于z-Buffer中的缓存,那么我们给这个像素的颜色重置为三角形的颜色。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 void rst::rasterizer::rasterize_triangle(const Triangle& t) { auto v = t.toVector4(); std ::vector <float > arr_x{t.v[0 ].x(),t.v[1 ].x(),t.v[2 ].x()}; std ::vector <float > arr_y{t.v[0 ].y(),t.v[1 ].y(),t.v[2 ].y()}; std ::sort(arr_x.begin(),arr_x.end()); std ::sort(arr_y.begin(),arr_y.end()); for (int x=arr_x[0 ];x<=arr_x[2 ];x+=1 ){ for (int y=arr_y[0 ];y<arr_y[2 ];y+=1 ){ if (insideTriangle(x+0.5f ,y+0.5f ,t.v)){ auto [alpha, beta, gamma] = computeBarycentric2D(x+0.5f , y+0.5f , 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)]) { Eigen::Vector3f point (x, y, 1.0f ) ; set_pixel(point, t.getColor()); depth_buf[get_index(x, y)] = z_interpolated; } } } } }
那么就完成了z-Buffer的步骤,编译运行得到这样的结果注意遮挡顺序
,如果你的遮挡顺序错了,请检查你的透视投影矩阵。
放大可以看到存在明显的锯齿,但是普通要求也到这结束了。
提高题
使用Surper-Sampling对一个像素进2x2超采样。
首先,我们创建两个二维向量来存储深度缓存和颜色缓存。
1 2 3 std ::vector <std ::array <float ,4 >> surpersample_corlor_buf; std ::vector <std ::array <float ,4 >> surpersample_depth_buf;
同时修改构造函数和重置函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 void rst::rasterizer::clear(rst::Buffers buff) { if ((buff & rst::Buffers::Color) == rst::Buffers::Color) { std ::fill(frame_buf.begin(), frame_buf.end(), Eigen::Vector3f{0 , 0 , 0 }); } if ((buff & rst::Buffers::Depth) == rst::Buffers::Depth) { std ::array <float ,4 > inf; inf.fill(std ::numeric_limits<float >::infinity()); std ::fill(depth_buf.begin(), depth_buf.end(), std ::numeric_limits<float >::infinity()); std ::fill(surpersample_depth_buf.begin(), surpersample_depth_buf.end(), inf); } } rst::rasterizer::rasterizer(int w, int h) : width(w), height(h) { frame_buf.resize(w * h); depth_buf.resize(w * h); surpersample_corlor_buf.resize(w * h); surpersample_depth_buf.resize(w * h); }
接着就是光栅化的实现了,使用附近四个点是否在三角形内作为参数,设置颜色的值。这里其实是一种不那么严谨的卷机(个人观点),可以让三角形和周围产生的锯齿消失。下面是卷机盒的设计:
代码实现如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 for (int i=minX;i<maxX;i++) { for (int j=minY;j<maxY;j++) { int Index=get_index(i,j); int l=0 ; int IsInTriangleCount=0 ; int IsDontBeCover=0 ; if (IsUseSurperSampling) { for (auto &k : SampleOffset) { float SampleX=i+k.x(); float SampleY=j+k.y(); if (insideTriangle(SampleX,SampleY,t.v)) { auto [alpha, beta, gamma] = computeBarycentric2D(SampleX, SampleY, 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 < surpersample_depth_buf[Index][l]) { surpersample_depth_buf[Index][l]=z_interpolated; IsDontBeCover++; } IsInTriangleCount++; } l=l+1 ; } Vector3f color= t.getColor()*IsInTriangleCount/4.0f ; if (IsDontBeCover>0 ) { set_pixel(Vector3f(i,j,0 ),color); } } else { if (insideTriangle(i+0.5f ,j+0.5f ,t.v)) { auto [alpha, beta, gamma] = computeBarycentric2D(i+0.5f , j+0.5f , 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[Index]) { depth_buf[Index]=z_interpolated; set_pixel(Vector3f(i,j,1 ),t.getColor()); } } } } }
最后的输出图片如下,比起超采样之前的三角形,锯齿明显少了。
放大后可以看到明显的柔化:
下/上一篇
下一篇:obj导入与phong
上一篇:透视投影矩阵