Home Forums GAMES在线课程(现代计算机图形学入门)讨论区 【总结】MSAA中黑线问题的出现原因以及解决方案 Reply To: 【总结】MSAA中黑线问题的出现原因以及解决方案

#3575 Score: 2
戴皓天
Participant
8 pts

2020.03.08 17点35分 更新:
·这次更新完全消除了黑线,是最终方案

解决方案
一开始我没搞明白所谓的维护每个子采样点的深度是什么意思,后来经过大佬们的指点,我稍微理解一点
具体做法:

第一步:扩大深度缓存
因为是2X2的MSAA,所以子采样点的个数是像素个数X4,为了能存下子采样点的深度信息,深度缓存就要扩大4倍

rst::rasterizer::rasterizer(int w, int h) : width(w), height(h)
{
    frame_buf.resize(w * h);
    w=w*4+100;//***这里改动***
    depth_buf.resize(w * h );
}

+100是为了防爆

第二步:新建一个color buffer*****这一步是“2020.03.08 17点35分 更新”新加的******
*color_buf用于存放子采样点的颜色,对每个子采样点进行深度检测时,若通过了深度检测,则在写入深度信息的同时也要往这个color_buf里写各个子采样点的颜色信息,而不是直接写进最终的颜色缓存frame_buf中
在经过四个子采样点的深度检测之后再对四个子采样点的颜色做一个平均,然后传入frame_buf
首先在rasterizer.hpp头文件里定义color_buf(用于持久保持防止回收)

std::vector<Eigen::Vector3f> frame_buf;

std::vector<Eigen::Vector3f> color_buf;//***这里

std::vector<float> depth_buf;

然后在rasterizer.cpp里设置初始化:

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});
        std::fill(color_buf.begin(), color_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()*(-1.0f));
    }
}

接着扩大到w*h的四倍

rst::rasterizer::rasterizer(int w, int h) : width(w), height(h)
{
    frame_buf.resize(w * h);
    w=w*4+100;
    color_buf.resize(w * h);//***这里
    depth_buf.resize(w * h );//*这是上一步改的
}

第三步:对每个子采样点进行三角形内部检测
这里没什么好说的,就是给insideTriangle函数传一个大小为4的数组,分别对应每个像素的4个子采样点,分别对4个子采样点进行向量叉乘判断是否在三角形内部,然后对数组写入对应的值并返回即可

第四步:对每个子采样点进行深度检测和深度写入
我在这里浪费了很多时间,因为一开始我只做了对每个子采样点进行深度检测,并没有对每个子采样点进行深度写入

for(对每个子采样点)
{
    if(如果当前子采样点在三角形内部)
    {
        if(depth_buf中当前子采样点位置的深度 < 当前三角形的深度)
        {
            depth_buf中当前子采样点位置的深度 = 当前三角形的深度;
            color_buf中当前子采样点位置的颜色 = 当前三角形的颜色;//也就是等于t.getColor()
        }
    }
}
for(对每个子采样点)
{
    最终颜色 += color_buf中当前子采样点位置的颜色/4.0f;
}

*这里要注意的是深度检测之前要先判断这个子采样点是不是在三角形内部,如果不做这个判断就会出错。因为边缘处的子采样点,只有在三角形内部才有被深度检测的意义

至此,问题就大致解决了,
我们来看下最终效果
见附件,附件已更新,是最新的效果

或许不同的情况会有不同的渲染顺序,结果可能不一样,但问题思路应该是差不多的
这个问题浪费了三天时间,但好在最后总算有了个尾声
希望能够帮到各位,谢谢

This post has received 2 votes up.
  • This reply was modified 2 years, 2 months ago by 戴皓天.
  • This reply was modified 2 years, 2 months ago by 戴皓天.
Attachments:
You must be logged in to view attached files.