问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

Android OpenGL ES详解——多重采样抗锯齿(MSAA)

创作时间:
作者:
@小白创作中心

Android OpenGL ES详解——多重采样抗锯齿(MSAA)

引用
CSDN
1.
https://blog.csdn.net/github_27263697/article/details/143859755

多重采样抗锯齿(MSAA)是OpenGL中用于减少图像锯齿现象的重要技术。本文将从抗锯齿概念出发,深入讲解MSAA的原理及其在OpenGL中的具体实现方式,包括如何在离屏渲染中应用MSAA。

一、抗锯齿概念

在图形渲染中,锯齿边(Jagged Edge)的出现是由于顶点数据像素化后转化为片段的方式所引起的。这种现象被称为走样(Aliasing)。为了解决这个问题,出现了多种抗锯齿技术。

早期的超级采样抗锯齿技术(SSAA)通过提高渲染分辨率来减少锯齿,但这种方法会显著降低性能。因此,更现代的多重采样抗锯齿(MSAA)技术应运而生,它在保持性能的同时,提供了更好的抗锯齿效果。

二、多重采样

要理解多重采样(Multisampling)的工作原理,我们需要深入了解OpenGL的光栅化过程。光栅化将顶点转化为片段,但由于屏幕像素的限制,某些边缘像素可能无法被正确渲染,从而产生锯齿。

多重采样通过使用多个子样本(subsample)来解决这个问题。每个像素不再仅使用一个采样点,而是使用多个子样本。这些子样本用于决定像素的覆盖率,从而提高渲染精度。

在多重采样中,即使只有部分子样本被三角形覆盖,像素的颜色也会根据覆盖的子样本数量进行平均化处理。这种处理方式既保持了性能,又显著改善了图像质量。

不仅颜色值会受到多重采样的影响,深度和模板测试也同样使用多采样点。这意味着深度和模板缓冲的大小也会随着像素子样本的增加而增加。

三、OpenGL中的MSAA

1. 多样本缓冲的使用

在OpenGL中使用MSAA,需要创建一个可以储存多个颜色值的多样本缓冲(Multisample Buffer)。GLFW提供了创建这种缓冲的功能,我们可以通过设置窗口提示来创建一个带有N个样本的多样本缓冲:

glfwWindowHint(GLFW_SAMPLES, 4);

创建窗口后,需要调用glEnable开启多采样:

glEnable(GL_MULTISAMPLE);

2. 离屏MSAA——多采样帧缓冲

如果使用自定义帧缓冲进行离屏渲染,需要自己创建多采样缓冲。有两种方式可以创建多采样缓冲:纹理附件和渲染缓冲附件。

1. 多采样纹理附件

使用glTexImage2DMultisample创建支持储存多采样点的纹理:

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_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, tex, 0);

2. 多采样渲染缓冲对象

创建多采样渲染缓冲对象:

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

3. 渲染到多采样帧缓冲

渲染到多采样帧缓冲是自动的。渲染完成后,可以使用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);

如果需要在着色器中使用多采样纹理,可以将其位块传送(Blit)到一个普通纹理附件的FBO中:

GLuint msFBO = CreateFBOWithMultiSampledAttachments();
// Then create another FBO with a normal texture color attachment
...
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, screenTexture, 0);
...
while(!glfwWindowShouldClose(window))
{
    ...
    glBindFramebuffer(msFBO);
    ClearFrameBuffer();
    DrawScene();
    // Now resolve multisampled buffer(s) into intermediate FBO
    glBindFramebuffer(GL_READ_FRAMEBUFFER, msFBO);
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, intermediateFBO);
    glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
    // Now scene is stored as 2D texture image, so use that image for post-processing
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    ClearFramebuffer();
    glBindTexture(GL_TEXTURE_2D, screenTexture);
    DrawPostProcessingQuad();  
    ...
}

四、自定义抗锯齿算法

可以直接将多采样纹理图像传递到着色器中,GLSL提供了sampler2DMS类型来支持这种操作:

uniform sampler2DMS screenTextureMS;

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

vec4 colorSample = texelFetch(screenTextureMS, TexCoords, 3);  // 4th subsample

五、总结

多重采样抗锯齿(MSAA)是一种在OpenGL中用于降低渲染图形时出现的锯齿现象的技术。通过使用多个采样点来计算每个像素的颜色值,MSAA能够显著改善图像质量。虽然开启MSAA会增加渲染计算量,但其带来的视觉效果提升是值得的。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号