Adreno OpenGL ES 3.0 介绍(7)

这篇教程详细介绍了如何使用AdrenoOpenGLES3.0进行2D阵列纹理渲染。通过屏幕外帧缓冲区配置、屏幕外渲染和最终图像合成,演示了如何将多个帧渲染到2D阵列纹理的不同层,并将这些层合成为最终图像。应用展示了2D阵列纹理在渲染金字塔并旋转至不同角度时的用途。

3.3.2渲染为2D阵列纹理–demo

在以下目录中找到此演示:<SDK_install_dir> \ Development \ Tutorials \ OpenGLES \ 25_FramebufferTextureLayerOGLES30。

此应用程序演示了一些实际使用的OpenGL ES 3.0功能,包括:

  • 渲染为2D阵列纹理
  • 将2D阵列纹理的图层拖到默认帧缓冲区的不同区域

该演示使用屏幕外的帧缓冲区将大量帧渲染到2D阵列纹理的连续层。 每帧都显示一个金字塔,旋转到略微不同的角度。 渲染完成后,这些层将使用帧缓冲区混合机制来合成后缓冲区内容。 最后,将后缓冲区与前缓冲区交换,以将呈现的帧呈现给用户。

为了更好地了解应用程序的工作方式,请查看以下方面:

  • 配置屏幕外帧缓冲区
  • 进行屏幕外渲染
  • 合成最终渲染结果

跳过了与之前的演示演练中已介绍的部分相似的代码部分的讨论。

3.3.2.1配置屏幕外帧缓冲区

屏幕外帧缓冲区是在CreateFBO中构造的。

glGenTextures( 1, &g_hTextureHandle ); glBindTexture(
GL_TEXTURE_2D_ARRAY, g_hTextureHandle );
glTexParameteri( GL_TEXTURE_2D_ARRAY,
GL_TEXTURE_MAG_FILTER,
GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER,
GL_LINEAR ); glTexImage3D( GL_TEXTURE_2D_ARRAY, 0,
nInternalFormat, nWidth,
nHeight, g_nLayers, 0,
nFormat, nType, NULL );

上面的代码初始化了2D数组纹理。 这是9层,因为它是常数g_nLayers的值。

glGenRenderbuffers( 1, &(*ppFBO)->m_hRenderBuffer );
glBindRenderbuffer( GL_RENDERBUFFER, (*ppFBO)->m_hRenderBuffer );
glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, nWidth,
nHeight );

在这里,它将创建一个单独的渲染缓冲区,以24位精度保存深度数据。

glFramebufferTextureLayer( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
g_hTextureHandle, 0, 0);
glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, (*ppFBO)->m_hRenderBuffer );

现在,帧缓冲区配置了以下附件:

  • 2D阵列纹理的零层附加到颜色附加点零
  • Renderbuffer绑定到深度附着点

3.3.2.2屏幕外渲染

屏幕外渲染过程由render函数的第一部分完成:

for(int i=0; i<g_nLayers; i++) {
BeginFBO( g_pOffscreenFBO, i );
glClearColor( 0.0f, 0.5f, 0.0f, 1.0f );
RenderScene( fTime+i*0.1f );
EndFBO( g_pOffscreenFBO );
}

该块在所有2D阵列纹理层上循环。 对于每一层,BeginFBO用于配置帧缓冲区对象,其操作如下:

glBindFramebuffer( GL_FRAMEBUFFER, pFBO->m_hFrameBuffer );
glFramebufferTextureLayer( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
g_hTextureHandle, 0, layer);
glViewport( 0, 0, pFBO->m_nWidth, pFBO->m_nHeight );

将当前图层作为颜色附件零进行附加。 另外,请确保视口分辨率与纹理分辨率保持同步。 如果不这样做,则金字塔将不适合渲染目标,或者将仅绘制渲染目标的一部分。

完成此操作后,render会调用RenderScene,后者负责发送渲染金字塔所需的命令。

glBindFramebuffer( GL_FRAMEBUFFER, 0 );
glViewport( 0, 0, g_nWindowWidth, g_nWindowHeight );

最后,在EndFBO中,绑定回默认的帧缓冲区,并将视口分辨率重置为窗口的尺寸。

渲染循环完成执行后,所有2D阵列纹理层均填充有旋转到不同角度的金字塔。 在这一点上,这些金字塔都还没有进入后台缓冲区。

3.3.2.3合成最终图像

合成过程由渲染功能的其余部分实现。

FLOAT offsets[9][4] =
{
{ 0.0f,
0.0f, 1.0f/3.0f, 1.0f/3.0f },
{ 1.0f/3.0f, 0.0f, 2.0f/3.0f, 1.0f/3.0f },
{ 2.0f/3.0f, 0.0f, 1.0f,
{ 0.0f,
1.0f/3.0f },
1.0f/3.0f, 1.0f/3.0f, 2.0f/3.0f },
{ 1.0f/3.0f, 1.0f/3.0f, 2.0f/3.0f, 2.0f/3.0f },
{ 2.0f/3.0f, 1.0f/3.0f, 1.0f,
{ 0.0f,
2.0f/3.0f },
2.0f/3.0f, 1.0f/3.0f, 1.0f },
{ 1.0f/3.0f, 2.0f/3.0f, 2.0f/3.0f, 1.0f },
{ 2.0f/3.0f, 2.0f/3.0f, 1.0f,
1.0f },
};

这从定义阵列图像放置区域的数组开始。 定义了九个矩形。 每个矩形给出的四个值如下:

  • 左上角的X坐标
  • 左上角的Y坐标
  • 右下角的X坐标
  • 右下角的Y坐标
glBindFramebuffer( GL_DRAW_FRAMEBUFFER, 0 );
glBindFramebuffer( GL_READ_FRAMEBUFFER,
g_pOffscreenFBO->m_hFrameBuffer );

在进入进行合成的循环之前,请准备帧缓冲区绑定:

  • 将默认帧缓冲区作为所有渲染操作的目标,以将金字塔图像映射到后缓冲区。
  • 屏幕外的帧缓冲区被设置为读取操作的源; 这告诉glBlitFramebuffer应该从哪里获取源数据。
for(int i=0; i<g_nLayers; i++)
{
glFramebufferTextureLayer( GL_READ_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0, g_hTextureHandle, 0, i);
0, 0, g_pOffscreenFBO->m_nWidth,
>m_nHeight,
glBlitFramebuffer(
g_pOffscreenFBO-
INT32(g_nWindowWidth*offsets[i][0]),
INT32(g_nWindowHeight*offsets[i][1]),
INT32(g_nWindowWidth*offsets[i][2]),
INT32(g_nWindowHeight*offsets[i][3]),
GL_COLOR_BUFFER_BIT, GL_LINEAR );
}

对于2D阵列纹理的每一层,必须完成两件事以将图像数据复制到后台缓冲区:

  1. 将该层配置为读取帧缓冲区的颜色附件零; 这将是blit行动的源头
  2. 使用glBlitFramebuffer将一幅金字塔图像从读取帧缓冲区中向背面缓冲区中,在数组中矩形坐标定义的位置处进行对齐

当循环完成并且渲染函数返回时,最终图像现在将在后台缓冲区中完全合成。 现在可以将后缓冲区与前缓冲区交换,以使场景在屏幕上可见。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值