Home › Forums › GAMES在线课程(现代计算机图形学入门)讨论区 › 关于作业2两个三角形重叠部分的Z-Buffer问题
- This topic has 14 replies, 11 voices, and was last updated 1 year, 10 months ago by Ashechol.
-
AuthorPosts
-
-
这两张图看起来都没问题
-
-
EasonZhongParticipant
被这个问题卡了好久,感谢!
-
-
wjwABCDEFGParticipant
请问楼主,为什么你不会出现中心对称问题(作业1和作业3也存在),如何解决?
-
wjwABCDEFGParticipant
已解决
-
chenghaochnParticipant
怎么解决的?
-
AstesiaParticipant
我也想问,我的三角形都是中心对称的
-
wjwABCDEFGParticipant
可以在作业1的get_projection_matrix函数中先进行一次正负转换zNear = -abs(zNear); zFar = -abs(zFar);同时在计算top时保持正数float t = tan((eye_fov / 2) / 180 * MY_PI) * abs(zNear);因为这里的zNear指的是距离
-
-
-
-
-
见龙Participant
谢谢楼主,已解决
-
感谢解答。我的理解是之前做MVP变换时采用了-z的值,那么做视图变换时也应该采用顶点的-z
`
// 单位立方体的边长
float f1 = (50 – 0.1) / 2.0;
// 单位立方体的中心点的z值 反转后的 正值
float f2 = (50 + 0.1) / 2.0;
……
// 变换前的点(0,0) 变换后应该在(width/2,height/2) 的位置
//Viewport transformation
for (auto & vert : v)
{
vert.x() = 0.5*width*(vert.x()+1.0);
vert.y() = 0.5*height*(vert.y()+1.0);
// 因为之前为了方便计算z值,将z值设置成正值
// 而我们做MVP变换时,采用的是z值的负值
// 所以这里再做视口变换,应改回负值
vert.z() = -vert.z() * f1 + f2;
// vert.z() = vert.z() * f1 + f2;
}
`
-
shs1992shsParticipant
我的理解是mvp变换后z坐标就在[-1,1]之内,那么经过放大f1倍后(vert.z()*f1),如果z值是负的,就是还是负的。第二个三角形原始的z为-5,小于第一个三角形原始z值-2,mvp变换后还是符合这种情况。
那么加上f2之后,就是所有点都平移到了z轴正方向,此时所有的z坐标都是正值,那么此时第二个三角形的z值假设由最初的-5变为1,第一个三角形的z值此时必然比1要大,可能为8,还是符合靠近相机的z值大于远离相机的z值,这会覆盖后面的z值。那么判断深度值,坚持以这个关系进行比较,即若当前的z值大于z缓冲,那么就以当前的三角形的颜色绘制,并更新z缓冲,这样理解起来是非常直观的。
此处出现问题,主要是代码框架的depth_buf初始化的问题,初始化值是正无穷大, 那么从第一个三角形开始比较,其z值小于初始 z缓冲(无穷大),认为在目前深度后面,不用更新,那么最终就什么都没有绘制,为黑屏。
如果直接把判断关系改为作业提示中的z值越大表示离视点越远,即若当前z值小于z缓冲,则以当前颜色绘制并更新,那么此时第一个三角形满足情况,顺利绘制并更新z缓冲。但是第二个三角形中的部分z值小于和第一个三角形重叠部分的z值,即小于z缓冲值,那么满足判断关系,进行绘制覆盖并更新,从而颠倒了两个三角形的绘制顺序。所以最简单的修改,就是把初始化的z缓冲设为负无穷大,这样就是z值越小,离相机越远。参考下面的代码。
如果坚持以作业提示中的方法,初始化的z缓冲还是正无穷大,那就需要修改原代码框架里的视口变换的z坐标变换了,即把 vert.z() * f1进行放大时,前面加一负号,完成z值镜像反转。此时原来离视点最远的z值由负变正,数值上变为最大,那么判断关系就符合作业要求了,z值越小离视点越近,若当前z值小于z缓冲,则绘制覆盖并更新,顺序就正确了。这个方法我认为理解起来不是那么直观,因为前面的mvp推导过程都是坚持z值为负值的,突然一下转为正值,很容易让人混淆,理解起来困难。
两种方法都试一下之后,相信就会加深理解了。修改后的代码如下:
int pixel_index = get_index(x, y); float depth = depth_buf[pixel_index]; if (depth < z_interpolated) { set_pixel(Vector3f(x, y, z_interpolated), t.getColor()); depth_buf[pixel_index] = z_interpolated; // update depth }
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::fill(depth_buf.begin(), depth_buf.end(), std::numeric_limits<float>::infinity()); //原框架初始深度值为∞ std::fill(depth_buf.begin(), depth_buf.end(), -std::numeric_limits<float>::infinity());//初始深度值改为-∞,z轴最远处。 } }
修改视口变换的代码:
// Viewport transformation for (auto &vert : v) { vert.x() = 0.5 * width * (vert.x() + 1.0); vert.y() = 0.5 * height * (vert.y() + 1.0); vert.z() = -vert.z() * f1 + f2; // 负号是为了实现镜像反转(reflection ) // vert.z() = vert.z() * f1 + f2; }
-
w小宇Participant
为什么我按楼主的方法还是没有解决啊,有没有大佬帮帮忙
-
果然是框架的问题啊,我就说怎么z在视口变换前大小正常的,视口后就反过来了
-
AuthorPosts
- You must be logged in to reply to this topic.