简体   繁体   English

如何在OpenGL ES上有效地将深度缓冲区复制到纹理

[英]How to efficiently copy depth buffer to texture on OpenGL ES

I'm trying to get some shadowing effects to work in OpenGL ES 2.0 on iOS by porting some code from standard GL. 我试图通过从标准GL移植一些代码 ,在iOS上的OpenGL ES 2.0中使用一些阴影效果。 Part of the sample involves copying the depth buffer to a texture: 部分示例涉及将深度缓冲区复制到纹理:

glBindTexture(GL_TEXTURE_2D, g_uiDepthBuffer);
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 0, 0, 800, 600, 0);

However, it appears the glCopyTexImage2D is not supported on ES. 但是,似乎ES上不支持glCopyTexImage2D。 Reading a related thread , it seems I can use the frame buffer and fragment shaders to extract the depth data. 读取相关的线程 ,似乎我可以使用帧缓冲区和片段着色器来提取深度数据。 So I'm trying to write the depth component to the color buffer, then copying it: 所以我试图将深度组件写入颜色缓冲区,然后复制它:

// 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);

Here is the fragment shader: 这是片段着色器:

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);
    }
}

I have experimented with not having the 'bRenderDepth' branch, and it doesn't speed it up significantly. 我已经尝试过没有“bRenderDepth”分支,并且它没有显着加快速度。

Right now pretty much just doing this step its at 14fps, which obviously is not acceptable. 现在几乎只是以14fps执行此步骤,这显然是不可接受的。 If I pull out the copy its way above 30fps. 如果我将副本拉出30fps以上。 I'm getting two suggestions from the Xcode OpenGLES analyzer on the copy command: 我在复制命令上从Xcode OpenGLES分析器得到两个建议:

  1. file://localhost/Users/xxxx/Documents/Development/xxxx.mm: error: Validation Error: glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 960, 640, 0) : Height<640> is not a power of two file://localhost/Users/xxxx/Documents/Development/xxxx.mm:错误:验证错误:glCopyTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,0,0,960,640,0):高度<640>不是电源两个

  2. file://localhost/Users/xxxx/Documents/Development/xxxx.mm: warning: GPU Wait on Texture: Your app updated a texture that is currently used for rendering. file://localhost/Users/xxxx/Documents/Development/xxxx.mm:警告:GPU等待纹理:您的应用更新了当前用于渲染的纹理。 This caused the CPU to wait for the GPU to finish rendering. 这导致CPU等待GPU完成渲染。

I'll work to resolve the two above issues (perhaps they are the crux if of it). 我将努力解决上述两个问题(也许它们是关键所在)。 In the meantime can anyone suggest a more efficient way to pull that depth data into a texture? 在此期间,任何人都可以建议一种更有效的方法将深度数据拉入纹理吗?

Thanks in advance! 提前致谢!

iOS devices generally support OES_depth_texture , so on devices where the extension is present, you can set up a framebuffer object with a depth texture as its only attachment: iOS设备通常支持OES_depth_texture ,因此在存在扩展名的设备上,您可以设置一个带有深度纹理的framebuffer对象作为其唯一附件:

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);

Your texture then receives all the values being written to the depth buffer when you draw your scene (you can use a trivial fragment shader for this), and you can texture from it directly without needing to call glCopyTexImage2D . 然后,当您绘制场景时,纹理会接收写入深度缓冲区的所有值(您可以使用一个简单的片段着色器),您可以直接从它进行纹理而无需调用glCopyTexImage2D

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM