Home › Forums › GAMES在线课程(现代计算机图形学入门)讨论区 › 作业二提高部分思考
- This topic has 8 replies, 4 voices, and was last updated 3 years, 11 months ago by 食铁兽.
-
AuthorPosts
-
-
dzyParticipant
刚做完作业二.提高部分顺利做出黑线版本,看了些讨论帖(主要是戴老哥的汇总贴)大概明白了问题在哪了..感觉所谓msaa其实是这么回事:
首先黑线不是黑,是比较浅(越浅越黑,越深越白)的绿色,如果背景是白色就能看出两个三角形边界都有黑边,这其实就是正常的,老师上课讲的那种思路.但很多人(包括作业要求)认为这样不够,必须把黑线去掉,那其实和老师上课讲的东西不是一回事了,大家看一下老师ppt L06 67页的红色三角形,其实就是有黑线的(肉眼看不出来),因为只取了红色的平均,无黑线要(红+白)取平均.
下面才是无黑线的思路:
我只有700像素,但我完全按照我有1400像素来计算,给它1400的depth buffer和frame buffer,最后要真正上色的时候因为1400是假的再强行4->1把4个像素捏成一个,投到700的屏幕上..这个过程中原本700的depth buffer没用了,所以总共有三个buffer(就是戴老哥发出来的,两个frame buffer分别对应700和1400,一个1400的depth buffer)
到这里我都感觉有点荒谬了,因为这就好像我买了一个高级显卡按照顶级效果做了渲染然后给他接了个计算器屏幕…大马拉小车.而且我感觉这种优化不是我们真正需要的,因为这属于把原来的锯齿给强行糊掉了,但人眼对糊掉的东西有强烈不适,这里图形简单看不出来可以看24页的图,右边的图乍一看好了不少,但看时间长了就会头晕,反而不如左边的舒服.或者有笔记本外接显示器的同学都有这样的经验,当外接高分辨率显示器并且按这个分辨率输出图像的时候,笔记本屏幕会显示变小了的图形,其实就很类似这里的1400->700,图像很糊,当然也没有锯齿了.实际中我们肯定都是把分辨率调到适应屏幕,而不会计算超出屏幕本身分辨率的图像再强行投到屏幕上.
当然以上全是我的猜测,无黑线版本我也没去做,最后感谢讨论区各位大佬的分享,如果有不对的地方欢迎指教. -
在两个三角形边界处进行超采样后,如果产生黑线,说明超采样时越过了被覆盖的蓝色三角形,采样了背景的黑色(或者混合的结果包含背景的黑色)。正确的结果应该是将蓝色和绿色进行混合,边界处产生平滑的过渡。
另外如果背景是白色,那么非交界处的边缘应该是三角形颜色和白色混合,如附图所示,看不见明显的黑边。Attachments:
You must be logged in to view attached files.-
dzyParticipant
我说的是我做的有黑边版本,只用700的depth buffer,是一定有黑边的,只是背景黑色看不出来..另外请问老哥怎么把背景调到白色
-
食铁兽Participant
我是这样理解的:
出现黑边的原因在于先画绿三角后画蓝三角。这样的话先画绿三角的边会得到i/4绿+(4-i)/4黑,因此在边界生成了看起来像黑的颜色。而再画蓝三角时这边直接z值过高给舍弃了。反之先画z值高的蓝三角就不会出现这个问题,因为蓝色取代了背景黑色。
然而实际绘制先后顺序无法决定。在demo中也许可以改变顶点顺序来调整顺序,但复杂一点的场景就无法解决这个问题。如果在画z值较大的三角形时对每个像素判定是否在z值小的三角形边上,且这条边两侧中只有一侧与其他三角形接壤,那似乎又要用一个屏幕大小的buffer来储存这个信息。
当然实际肯定是有解决方法的,然而我不知道。。。找了半天也就看到一个关于这个的讨论。希望有大佬能够解答吧。。。
-
-
decayParticipant
个人理解:无论是msaa还是ssaa都需要把depth buffer和frame buffer都开成原来的n倍,而msaa和ssaa的区别在于ssaa是直接进行完整的n遍渲染,最后再把这些渲染的结果平均起来;msaa则是进行n次光栅化,但着色只进行一次,并且认为着色点仍然是像素中心,而不是四个子像素的位置,最后根据光栅化时的结果将相应的frame buffer更新到新的着色值。
写一下伪代码更清晰一些:rasterization_ssaa: for(x : xmin ~ xmax): for(y : ymin ~ ymax): for(subsample : n): if(depth_test(subsample) == success): update(depth_buffer[subsample]) sample_buffer[subsample] = shading(subsample, other_info) frame_buffer[sample] = avg(sample_buffer)
rasterization_msaa: for(x : xmin ~ xmax): for(y : ymin ~ ymax): // 着色发生在内部采样循环外面,因此只着色一次,提高了效率 pixel_color = shading(sample, other_info) for(subsample : n): if(depth_test(subsample) == success): update(depth_buffer[subsample]) sample_buffer[subsample] = pixel_color frame_buffer[sample] = avg(sample_buffer)
可以在文刀大大的回答以及learnopengl中找到类似的结论:
https://www.zhihu.com/question/20236638/answer/44821615
https://learnopengl.com/Advanced-OpenGL/Anti-Aliasing
不过对于你可能还有个问题,就是作业2中的着色其实就是对像素进行颜色插值,所以实际上对于作业2来说,msaa和ssaa其实是差不太多的。至于你和楼主遇到的黑边,是因为你们没有开n倍的frame buffer,只要让frame buffer把每个子采样点的颜色记住就不会出问题。
我用上述思路在作业3中实现了msaa,最后附上blinn-phong着色的效果图对比图,右边是4xmsaa的,可以看到虽然还是有一些狗牙,但平滑了不少.(吐槽一下,作业3的insideTriangle函数直接把参数定义成了int,坑了我好久)
-
-
AuthorPosts
- You must be logged in to reply to this topic.