Объекты FrameBuffer для динамических кубических карт в GLES 2.0 на Android - PullRequest
2 голосов
/ 01 мая 2011

Обновление: выясняется, что это проблема с драйверами PowerVR SGX в моем Nexus S. Код работает плавно на всех других устройствах, на которых я его тестировал.

Я сделаю меньший тестовый примери отправив сообщение об ошибке ... кому-то.Не знаю, кто.


Привет, ребята,

Прежде всего, я работаю над портом AndAR (ARToolkit для Android) для GLES 2.0, используя Java GLES2.0привязок.Весь мой код можно найти здесь, если вам интересно, но я постараюсь подвести итог проблемы в этом вопросе. AndARShaders

Я пытаюсь реализовать этот документ для генерации AR-визуализации, которая правдоподобно отражает и преломляет: Виртуальные отражения в средах дополненной реальности .Для этого определяется ограничивающая рамка экранного пространства визуализируемого объекта, которая затем используется для генерации координат текстуры для плоскостей, представляющих каждую грань кубической карты.Это означает рендеринг кубической карты для каждого кадра для каждой модели.Сейчас я рендую только одну модель за раз.Я пытаюсь использовать объекты кадрового буфера для рендеринга кубической карты на основе метода, описанного в статье.

Во всяком случае, к проблеме.

У меня это в основном реализовано.Насколько я могу судить, по крайней мере, передняя грань кубической карты имеет вершины и правильно сгенерированные координаты UV.Я могу отрисовать свое переднее лицо в системном буфере кадров для экрана, и он отрисовывается без проблем ровно столько, сколько хотелось бы.Проблема заключается в том, что он рендерится в объект framebuffer.

Когда я рендерирую свои кубические карты в объект framebuffer, связанный с текстурой кубической карты, GL съедает ВСЕ мою память в течение нескольких секунд и вылетает сОШИБКА 1285 (ИЗ ПАМЯТИ).Если я не связываю FBO, я могу рендерить грани кубической карты на экран без проблем с памятью.Размер текстуры кубической карты составляет 128 пикселей, что должно быть приемлемо для мобильного устройства.Почему-то у 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);

Возможно, мой заказ неправильный или мои настройки неверны?

Извинитеза длинный пост.Я действительно сделал все, что в моих силах, чтобы сделать это как можно более коротким, при этом предоставив достаточно информации для решения проблемы.Я вырезал много дополнительного кода, который зависит от приложения.Если вам интересно или вы думаете, что проблема может быть вызвана в другом месте, я включил ссылки на фактические исходные файлы, чтобы вы могли быстро взглянуть.

Спасибо за ваше время!Я потратил на это слишком много времени.

-Гриф

Редактировать: размер уточненной текстуры

...