适用于Android上GLES 2.0的Dynamic Cubemaps的FrameBuffer对象

时间:2011-05-01 00:48:35

标签: java android rendering opengl-es-2.0 out-of-memory

更新:原来这是我的Nexus S中的powerVR SGX的驱动程序问题。代码在我测试过的所有其他设备上流畅地工作。

我将制作一个较小的测试用例并向某人提交错误报告。不知道是谁。


嘿伙计们,

首先,我正在使用Java GLES2.0绑定将一个AndAR(ARToolkit for Android)端口用于GLES 2.0。如果你很好奇,我可以在这里找到我的全部代码,但我会尝试总结这个问题中的问题。 AndARShaders

我正在尝试实施这篇论文,以生成能够可信地反映和折射的AR渲染:Virtual Reflections in Augmented Reality Environments。为此,确定要渲染的对象的屏幕空间边界框,然后用于为表示立方体贴图的每个面的平面生成纹理坐标。这意味着为每个模型渲染每个帧的立方体贴图。我现在只渲染一个模型。我正在尝试使用帧缓冲对象来基于文章中描述的方法渲染立方体贴图。

无论如何,要解决这个问题。

我主要实现了它。据我所知,至少立方体贴图的正面具有正确生成的顶点和UV坐标。我可以将我的正面渲染到系统提供的屏幕框架缓冲区,只要我愿意,它就可以很好地解决问题。问题在于将其渲染为帧缓冲对象。

当我将立方体贴图面部渲染到链接到立方体贴图纹理的帧缓冲区对象时,GL会在几秒钟内消耗掉所有内存并使用GLError 1285(内存不足)崩溃。如果我没有绑定FBO,我可以将立方体贴图面渲染到屏幕而不会出现任何内存问题。立方体贴图纹理大小为128 PX平方,这对于移动设备应该是合理的。不知何故,GL正在泄漏内存

这是我正在做的事情的粗略顺序。这是此框架渲染的条目。 (src/edu/dhbw/andar/ARGLES20Renderer.java〜第179行)

// BEGIN TO DRAW FRAME.  DRAW BACKGROUND CAMERA IMAGE TO QUAD
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glUseProgram(mProgram);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0); // Camera image is stored in Texture0
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureName);

//load new preview frame as a texture, if needed
GLES20.glTexSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, previewFrameWidth, previewFrameHeight, mode, GLES20.GL_UNSIGNED_BYTE, frameData);

//draw camera preview frame:
squareBuffer.position(0);
GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false, GraphicsUtil.TRIANGLE_VERTICES_DATA_STRIDE_BYTES, squareBuffer);
GLES20.glEnableVertexAttribArray(maPositionHandle);
textureBuffer.position(0);
GLES20.glVertexAttribPointer(maTextureHandle, 2, GLES20.GL_FLOAT, false, GraphicsUtil.TRIANGLE_VERTICES_UV_STRIDE_BYTES, textureBuffer);
GLES20.glEnableVertexAttribArray(maTextureHandle);

Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0);
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0);
GLES20.glUniform1i(mSamplerLoc, 0);

//draw camera square
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);

GLES20.glDisableVertexAttribArray(maPositionHandle);
GLES20.glDisableVertexAttribArray(maTextureHandle);

DRAW_OBJECTS();

绘制对象的代码有点像这样:

src/edu/dhbw/andar/ARGLES20Object.java〜第36行)

src/edu/dhbw/andar/pub/CustomGLES20Object.java〜第55行)

// Use the new program for the object (Refract/reflect shader)
GLES20.glUseProgram( mProgram );

// Transform to where the marker is
Matrix.multiplyMM(mMVPMatrix, 0, glCameraMatrix, 0, glMatrix, 0);
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0);

// Create a cubemap for this object from vertices
GENERATE_CUBEMAP( box.vertArray() );

// Feed in Verts
box.verts().position(0);
box.normals().position(0);
GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false, VERTEX_NORMAL_DATA_STRIDE, box.verts());
GLES20.glEnableVertexAttribArray(maPositionHandle);

GLES20.glVertexAttribPointer(maNormalHandle, 3, GLES20.GL_FLOAT, false, VERTEX_NORMAL_DATA_STRIDE, box.normals());
GLES20.glEnableVertexAttribArray(maNormalHandle);

// Set Uniforms...
GLES20.glUniform4f(muColor, 0.0f, 1.0f, 0.0f, 1.0f);
...

// Draw the cube faces
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
...

GLES20.glDisableVertexAttribArray(maPositionHandle);
GLES20.glDisableVertexAttribArray(maNormalHandle);

注意GENERATE_CUBEMAP(顶点)朝向渲染对象的开始。这就是它的作用。屏幕空间边界框[ssbb]已根据顶点计算。 (src/edu/dhbw/andar/ARGLES20Renderer.java〜第280行)

// Grab the current viewport and program for restoration later
int[] OldViewport = new int[4], OldProgram = new int[1];
GLES20.glGetIntegerv(GLES20.GL_VIEWPORT, OldViewport, 0);
GLES20.glGetIntegerv(GLES20.GL_CURRENT_PROGRAM, OldProgram, 0);

// Update dynamic cubemap based on screen space bounding box for this frame     
mDC.UpdateUVs( DynamicCubemap.CorrectSSBB( ssbb ), widthcorrection, heightcorrection ); 

// Set up the program used to render to the texture
GLES20.glUseProgram(mProgram);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureName);
float[] projmatrix = new float[16]; // Projection Matrix
Matrix.orthoM(projmatrix, 0, -1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f);
Matrix.multiplyMM(mMVPMatrix, 0, projmatrix, 0, mVMatrix, 0);
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0);
GLES20.glUniform1i(mSamplerLoc, 0); // Use the camera texture (bound in unit zero)

// Render to the front face of the cubemap
// Note:  If I don't bind the new Framebuffer, this 
// renders the face to the screen very nicely without memory issues
GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
GLES20.glBindTexture(GLES20.GL_TEXTURE_CUBE_MAP, 0); // Ensure we aren't rendering to the same texture we're using
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFrameBuffers[5]);
GLES20.glViewport( 0, 0, edu.dhbw.andar.Config.CUBEMAP_SIZE, edu.dhbw.andar.Config.CUBEMAP_SIZE);
GLES20.glClear( GLES20.GL_COLOR_BUFFER_BIT );
mDC.DrawFace( 5, maPositionHandle, maTextureHandle ); // Draw the front face with glDrawArrays

// Unbind the framebuffer, we no longer need to render to textures.
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);

// Ensure the newly generated cubemap is bound to the correct texture unit
GLES20.glBindTexture(GLES20.GL_TEXTURE_CUBE_MAP, mCubeMapTexture);

// Bind the old program and viewport
GLES20.glUseProgram( OldProgram[0] );
GLES20.glViewport( OldViewport[0], OldViewport[1], OldViewport[2], OldViewport[3] );

就是这样......这是我在程序启动时初始化我的FBO和Cubemap纹理的方法。 (src/edu/dhbw/andar/ARGLES20Renderer.java〜第128行)

// Generate Cubemap Textures
int[] cubemaptextures = new int[1];
GLES20.glGenTextures(1, cubemaptextures, 0 );
mCubeMapTexture = cubemaptextures[0];
GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
GLES20.glBindTexture(GLES20.GL_TEXTURE_CUBE_MAP, mCubeMapTexture);   

for( int i = 0; i < 6; i++ ) {
    GLES20.glTexImage2D(GLES20.GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, mode, CUBEMAP_SIZE, CUBEMAP_SIZE, 0, mode, GLES20.GL_UNSIGNED_BYTE, ByteBuffer.wrap(frame));
}
GLES20.glTexParameterf(GLES20.GL_TEXTURE_CUBE_MAP, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_CUBE_MAP, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_CUBE_MAP, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_CUBE_MAP, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
GLES20.glBindTexture(GLES20.GL_TEXTURE_CUBE_MAP, 0);

// Create a set of FrameBuffers for the cubemap
mFrameBuffers = new int[6];
GLES20.glGenFramebuffers(6, mFrameBuffers, 0);
for( int i = 0; i < 6; i++ ) {
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFrameBuffers[i]);
    GLES20.glFramebufferTexture2D( GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0,
GLES20.GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, mCubeMapTexture, 0 );
    GLES20.glCheckFramebufferStatus( GLES20.GL_FRAMEBUFFER );
}
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);

也许我的订购错了,或者我的设置不正确?

对不起LONG帖子。我真的竭尽全力使这个尽可能短,同时仍然提供足够的信息来解决问题。我删除了许多特定于应用程序的额外代码。如果您感兴趣,或者您认为问题可能是由其他地方造成的,我会在实际源文件中添加链接,以便您快速查看。

感谢您的时间!我浪费了太多时间在这上面。

-Griff

编辑:澄清纹理大小

0 个答案:

没有答案