美文网首页
23.opengl高级-抗锯齿

23.opengl高级-抗锯齿

作者: 天叔 | 来源:发表于2020-07-14 00:48 被阅读0次

    这两天有点疲惫,这一章节的代码没有run起来看效果,重点理解锯齿现象和抗锯齿的实现

    一、锯齿生成原理

    锯齿原理-参考知乎fengliancanxue

    参考上图,几何图形是连续的坐标连接实现的,实际屏幕上的像素是离散化的点,分辨率越低的屏幕离散越剧烈,在图形的边缘必然会产生锯齿。

    抗锯齿有两种常见的方案:1)超采样抗锯齿(Super Sample Anti-aliasing, SSAA);2)多重采样抗锯齿(Multisample Anti-aliasing, MSAA),MSAA借鉴了SSAA背后的理论。

    SSAA背后的理论说明,比如400 x 400的图片,采样成100 x 100,那就是缩放成原图的1/4,那么就可以用平均值的方式从相邻的4个像素采样生成100 x100中的一个新像素。SSAA用高分辨率图来降低锯齿效果较好,但是牺牲了内存性能。

    MSAA的方式是在内存中将一个采样点拓展成4个子采样点,4个子采样点不一定都在三角形中,计算包含在三角形内的子采样点的比例,再乘以原采样颜色,即得到该边缘点应该渲染的颜色。再简单点,包含在三角形中的子采样点越少,该像素的实际像素越淡

    4个子采样点 边缘像素的处理

    暂时先理解这么多,到用时再回头来深入研究

    二、Opengl中的MSAA

    2.1 默认窗口的话,2行代码实现
    glfwWindowHint(GLFW_SAMPLES, 4);
    glEnable(GL_MULTISAMPLE);
    
    无抗锯齿 锯齿放大 抗锯齿
    2.2 离屏MSAA

    使用glTexImage2DMultisample来替代glTexImage2D,它的纹理目标是GL_TEXTURE_2D_MULTISAPLE。

    glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, tex);
    glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGB, width, height, GL_TRUE);
    glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
    

    我们使用glFramebufferTexture2D将多重采样纹理附加到帧缓冲上,但这里纹理类型使用的是GL_TEXTURE_2D_MULTISAMPLE。

    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, tex, 0);
    

    和纹理类似,创建一个多重采样渲染缓冲对象并不难。我们所要做的只是在指定(当前绑定的)渲染缓冲的内存存储时,将glRenderbufferStorage的调用改为glRenderbufferStorageMultisample就可以了。

    glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, width, height);
    

    因为多重采样缓冲有一点特别,我们不能直接将它们的缓冲图像用于其他运算,比如在着色器中对它们进行采样。

    一个多重采样的图像包含比普通图像更多的信息,我们所要做的是缩小或者还原(Resolve)图像。多重采样帧缓冲的还原通常是通过glBlitFramebuffer来完成,它能够将一个帧缓冲中的某个区域复制到另一个帧缓冲中,并且将多重采样缓冲还原。

    glBindFramebuffer(GL_READ_FRAMEBUFFER, multisampledFBO);
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
    glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
    

    你可以看到,如果将多重采样与离屏渲染结合起来,我们需要自己负责一些额外的细节。但所有的这些细节都是值得额外的努力的,因为多重采样能够显著提升场景的视觉质量。当然,要注意,如果使用的采样点非常多,启用多重采样会显著降低程序的性能。在本节写作时,通常采用的是4采样点的MSAA。

    三、自定义抗锯齿算法

    将一个多重采样的纹理图像不进行还原直接传入着色器也是可行的。GLSL提供了这样的选项,让我们能够对纹理图像的每个子样本进行采样,所以我们可以创建我们自己的抗锯齿算法。在大型的图形应用中通常都会这么做。

    要想获取每个子样本的颜色值,你需要将纹理uniform采样器设置为sampler2DMS,而不是平常使用的sampler2D:

    uniform sampler2DMS screenTextureMS;
    

    使用texelFetch函数就能够获取每个子样本的颜色值了:

    vec4 colorSample = texelFetch(screenTextureMS, TexCoords, 3);  // 第4个子样本
    

    可以自己设计权重,计算输出颜色值
    我们不会深入探究自定义抗锯齿技术的细节,这里仅仅是给你一点启发。

    相关文章

      网友评论

          本文标题:23.opengl高级-抗锯齿

          本文链接:https://www.haomeiwen.com/subject/obmthktx.html