Opengl es 如何在OpenGL ES上高效地将深度缓冲区复制到纹理
我试图通过从标准GL移植,在iOS上的OpenGL ES 2.0中获得一些阴影效果。部分示例涉及将深度缓冲区复制到纹理:Opengl es 如何在OpenGL ES上高效地将深度缓冲区复制到纹理,opengl-es,opengl-es-2.0,depth-buffer,Opengl Es,Opengl Es 2.0,Depth Buffer,我试图通过从标准GL移植,在iOS上的OpenGL ES 2.0中获得一些阴影效果。部分示例涉及将深度缓冲区复制到纹理: glBindTexture(GL_TEXTURE_2D, g_uiDepthBuffer); glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 0, 0, 800, 600, 0); 但是,ES上似乎不支持glCopyTexImage2D。阅读a,我似乎可以使用帧缓冲区和片段着色器来提取深度数据。因此,我尝试将深度
glBindTexture(GL_TEXTURE_2D, g_uiDepthBuffer);
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 0, 0, 800, 600, 0);
但是,ES上似乎不支持glCopyTexImage2D。阅读a,我似乎可以使用帧缓冲区和片段着色器来提取深度数据。因此,我尝试将深度组件写入颜色缓冲区,然后复制它:
// clear everything
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// turn on depth rendering
glUseProgram(m_BaseShader.uiId);
// this is a switch to cause the fragment shader to just dump out the depth component
glUniform1i(uiBaseShaderRenderDepth, true);
// and for this, the color buffer needs to be on
glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
// and clear it to 1.0, like how the depth buffer starts
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// draw the scene
DrawScene();
// bind our texture
glBindTexture(GL_TEXTURE_2D, g_uiDepthBuffer);
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, width, height, 0);
以下是片段着色器:
uniform sampler2D sTexture;
uniform bool bRenderDepth;
varying lowp float LightIntensity;
varying mediump vec2 TexCoord;
void main()
{
if(bRenderDepth) {
gl_FragColor = vec4(vec3(gl_FragCoord.z), 1.0);
} else {
gl_FragColor = vec4(texture2D(sTexture, TexCoord).rgb * LightIntensity, 1.0);
}
}
我曾经尝试过不使用“bRenderDepth”分支,但它并没有显著加快速度
现在,仅仅以每秒14帧的速度完成这一步,这显然是不可接受的。如果我把拷贝拉到30帧以上。我从Xcode OpenGLES分析器中得到两条关于复制命令的建议:
file://localhost/Users/xxxx/Documents/Development/xxxx.mm: 错误:
验证错误:glCopyTexImage2DGL_纹理_2D,0,GL_RGBA,0,0,
9606400:0高度不是二的幂
file://localhost/Users/xxxx/Documents/Development/xxxx.mm: 警告:
GPU等待纹理:您的应用程序更新了当前正在使用的纹理
用于渲染。这导致CPU等待GPU启动
完成渲染
我将努力解决上述两个问题,也许它们是问题的症结所在。同时,有人能提出一种更有效的方法将深度数据拉入纹理吗
提前谢谢 iOS设备通常支持,因此在存在扩展的设备上,可以设置帧缓冲区对象,并将深度纹理作为其唯一附件:
GLuint g_uiDepthBuffer;
glGenTextures(1, &g_uiDepthBuffer);
glBindTexture(GL_TEXTURE_2D, g_uiDepthBuffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
// glTexParameteri calls omitted for brevity
GLuint g_uiDepthFramebuffer;
glGenFramebuffers(1, &g_uiDepthFramebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, g_uiDepthFramebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, g_uiDepthBuffer, 0);
然后,在绘制场景时,纹理将接收写入深度缓冲区的所有值。您可以使用一个简单的片段着色器进行此操作,并且您可以直接从中进行纹理处理,而无需调用glCopyTexImage2D。我还没有尝试过此操作,但是,您不能使用片段着色器将深度信息写入渲染纹理的颜色缓冲区,然后将其作为另一个着色器的输入进行后期处理吗?OpenGL应该只在GPU上进行同步,而不会因为执行基于CPU的回读/复制而暂停管道。另请参阅相关讨论,您完全正确。我是基于对OpenGL2.0ES规范支持的内容的理解,该规范没有提及任何扩展。所有iOS ES 2.0设备都支持OES_depth_纹理,因此这确实是解决方案。谢谢所以,有一个只附加深度的帧缓冲区可以吗?