Failed to initialize FBO on Android SDK emulator device - android

So this is how FBO is initialized:
/**
* Initializes Renderbuffer.
*/
static GLuint init_renderbuffer(GLuint width, GLuint height, GLenum format) {
GLuint renderbuffer;
glGenRenderbuffers(1, &renderbuffer);
checkGlError("init_renderbuffer: glGenRenderbuffers");
glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
checkGlError("init_renderbuffer: glBindRenderbuffer");
glRenderbufferStorage(GL_RENDERBUFFER, format, width, height);
checkGlError("init_renderbuffer: glRenderbufferStorage");
glBindRenderbuffer(GL_RENDERBUFFER, 0);
checkGlError("init_renderbuffer: glBindRenderbuffer");
return renderbuffer;
}
/**
* Initializes FBO.
*/
static void engine_init_fbo(struct engine* engine, GLuint width, GLuint height) {
// create renderable texture
glGenTextures(1, &engine->renderableTexture);
checkGlError("engine_init_fbo: glGenTextures");
glBindTexture(GL_TEXTURE_2D, engine->renderableTexture);
checkGlError("engine_init_fbo: glBindTexture");
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0);
checkGlError("engine_init_fbo: glTexImage2D");
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
checkGlError("engine_init_fbo: glTexParameteri");
// create render buffers
engine->depthRenderBuffer = init_renderbuffer(width, height, GL_DEPTH_COMPONENT16);
engine->stencilRenderBuffer = init_renderbuffer(width, height, GL_STENCIL_INDEX8);
LOGI("****************************** FBO: T: %d, D: %d, S: %d", engine->renderableTexture,
engine->depthRenderBuffer, engine->stencilRenderBuffer);
// create framebuffer object
glGenFramebuffers(1, &engine->framebufferObject);
checkGlError("engine_init_fbo: glGenFramebuffers");
glBindFramebuffer(GL_FRAMEBUFFER, engine->framebufferObject);
checkGlError("engine_init_fbo: glBindFramebuffer");
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, engine->renderableTexture, 0);
checkGlError("engine_init_fbo: glFramebufferTexture2D");
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, engine->depthRenderBuffer);
checkGlError("engine_init_fbo: glFramebufferRenderbuffer");
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, engine->stencilRenderBuffer);
checkGlError("engine_init_fbo: glFramebufferRenderbuffer");
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
checkGlError("engine_init_fbo: glCheckFramebufferStatus");
if(status != GL_FRAMEBUFFER_COMPLETE) {
switch(status) {
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
LOGI("****************************** engine_init_fbo: FBO error: FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
break;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
LOGI("****************************** engine_init_fbo: FBO error: FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
break;
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
LOGI("****************************** engine_init_fbo: FBO error: FRAMEBUFFER_INCOMPLETE_DIMENSIONS");
break;
case GL_FRAMEBUFFER_UNSUPPORTED:
LOGI("****************************** engine_init_fbo: FBO error: FRAMEBUFFER_UNSUPPORTED");
break;
default:
LOGI("****************************** engine_init_fbo: Unknown FBO error");
}
}
else {
LOGI("****************************** engine_init_fbo: FBO has been successfully initialized");
}
glBindTexture(GL_TEXTURE_2D, 0);
checkGlError("engine_init_fbo: glBindTexture");
glBindFramebuffer(GL_FRAMEBUFFER, 0);
checkGlError("engine_init_fbo: glBindFramebuffer");
}
As you can see, everything here is done according to OpenGL ES standard: 2D texture with RGB565 internal format is used as color; 2 renderbuffers are used as depth and stencil surfaces; dimensions are 32x32.
It works fine on real device (Alcatel OT 918D, prints "FBO has been successfully initialized" in adb logcat), but fails with FRAMEBUFFER_UNSUPPORTED on virtual device.
My virtual device's CPU is atom, GPU emulation is enabled, OpenGL ES 2.0 works fine - checked with another applications (which do not use FBOs).
Entire project (based on native-activity sample from NDK), which can be compiled with ndk-build, is here:
https://docs.google.com/file/d/0Byy41LxMuTKUZVJxSUtBZDVDXzA/edit?usp=sharing
My question is: Is this a bug in android-sdk emulator? Because everything seems to meet the minimum requerements to the OpenGL ES 2.0 implementation.
Thank you!
EDIT:
Found the solution. It appears, that AVD does not support this configuration of attached objects. I had to remove stencil attachment to make it work.
EDIT2:
It appears to be the context creation problem. I did not require stencil bits, so probably AVD created context without stencil support, and Alcatel phone - with stencil.
Anyway, this is not a bug, but my mistake.

Related

creating a framebuffer to take an image from external oes

I am trying to do multi pass rendering with framebuffer the issue is that the source is the camera so the texInput is not of type GL_TEXTURE_2D it is of type GL_TEXTURE_EXTERNAL_OES tho, if I use the function glTexImage2D it gives a black screen when I use that texture in the future after rendering to it without any errors glErros.
On the other hand if I don't use it(because it does not support GL_TEXTURE_EXTERNAL_OES) it gives me framebuffer status of NOT_COMPLETE
here is my code for creating the framebuffer and the texture that I want to associate to it.
fun prepareFBO() {
val intArray = IntArray(1)
glGenFramebuffers(1, intArray, 0)
fboId = intArray.first()
glGenTextures(1, intArray, 0)
texId = intArray.first()
glBindTexture(GL_TEXTURE_2D, texId)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,1080, 1920, 0, GL_RGBA, GL_UNSIGNED_BYTE, null)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
glBindFramebuffer(GL_FRAMEBUFFER, fboId)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texId, 0)
val status = glCheckFramebufferStatus(GL_FRAMEBUFFER)
Log.e(TAG, "prepareFBO: ${status == GL_FRAMEBUFFER_COMPLETE}")
glBindFramebuffer(GL_FRAMEBUFFER, 0)
glBindTexture(GL_TEXTURE_2D, 0)
}
the rest is just normal glDrawArrays and glActiveTexture that already works fine when I draw directly to the default framebuffer, if needed please let me know and I will share them.
Thanks for help!
UPDATE:
I found that I need instead of using glTexImage2d I can use eglBindTexImage instead so the final code is:
fun prepareFBO() {
val intArray = IntArray(1)
glGenFramebuffers(1, intArray, 0)
fboId = intArray.first()
glBindFramebuffer(GL_FRAMEBUFFER, fboId)
glGenTextures(1, intArray, 0)
texId = intArray.first()
glBindTexture(GL_TEXTURE_EXTERNAL_OES, texId)
checkGlError("Error 1")
eglBindTexImage(eglGetCurrentDisplay(), windowSurface!!.eglSurface, EGL_BACK_BUFFER)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_EXTERNAL_OES, texId, 0)
val status = glCheckFramebufferStatus(GL_FRAMEBUFFER)
Log.e(TAG, "prepareFBO: is status complete? => ${status == GL_FRAMEBUFFER_COMPLETE}")
}
while this looks like it makes sense, still I am getting the status of the framebuffer as not complete :/

Android12 opengles3.0 glTexImage2D 0x502 error

I have 5 textures, such as diffuse specular normal roughness ao, roughness and ao are 8bit jpg.
I got glError 0x502 while loading rouggness/ao texture after call glTexImage2D, but other three texture is OK.
And this issue just occured with android 12, android 11/10/9/8 is no error. How I can fix this issue?
code:
GLuint textureID;
glGenTextures(1, &textureID);
int width, height, nrComponents;
unsigned char *data = stbi_load(path, &width, &height, &nrComponents, 0);
GLenum format;
if (nrComponents == 1) {
format = GL_RED;
} else if (nrComponents == 3) {
format = GL_RGB;
} else {
format = GL_RGBA;
}
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
According to https://www.khronos.org/registry/OpenGL-Refpages/es3.0/html/glTexImage2D.xhtml, GL_RED is not an acceptable value for internalFormat (parameter 3 in glTexImage2D).
I think you need internalFormat=GL_R8 and format=GL_RED. Or you could use GL_LUMINANCE for both.

Render to texture attached to Frame Buffer Object (texture appears black)

I have generated a frame buffer object(FBO), bind it, attached a texture to its GL_COLOR_ATTACHMENT0. Then ensure that I get its status as GL_FRAMEBUFFER_COMPLETE. I have another texture(which is displaying on display), let's call it workingTexture. Now I want to render this workingTexture onto FBO, so I bind this FBO and then render workingTexture.
Then I bind default frame buffer(reserved for display) and try to render the texture attached to FBO, thinking that I will get my texture onto display, but I get black texture.
Relevant code
code to generate workingTexture...
int[] workingTexture = new int[1];
glGenTextures(1, workingTexture, 0); // generate workingTexture
glActiveTexture(GL_TEXTURE0); // attach it to TEXTURE_UNIT0
glBindTexture(GL_TEXTURE_2D, workingTexture[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
code to generate fbo
int[] fboName = new int[1];
int[] fboTextureName = new int[1];
final int fboTextureUnit = 1; // attach this texture to texture unit GL_TEXTURE1
glGenFramebuffers(1, fboName, 0);
int generatedTextureNameForFBO =
generateTextureForFBO(fboTextureUnit,
width, height);
fboTextureName[0] = generatedTextureNameForFBO;
glBindFramebuffer(GL_FRAMEBUFFER, fboName[0]);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, generatedTextureNameForFBO, 0);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
// created FBO is not complete
throw new RuntimeException("FBO status INCOMPLETE 😔😔");
}
method used to generate texture attached to fbo
private int generateTextureForFBO(#IntRange(from = 0) final int textureUnit,
#IntRange(from = 1) final int width,
#IntRange(from = 1) final int height) {
int[] textureName = new int[1];
glGenTextures(1, textureName, 0);
glActiveTexture(GL_TEXTURE0 + textureUnit);
glBindTexture(GL_TEXTURE_2D, textureName[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, null);
// glBindTexture(GL_TEXTURE_2D, 0);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
// glBindTexture(GL_TEXTURE_2D, 0);
return textureName[0];
}
Now coming to drawing part...
#Override
public void onDrawFrame(GL10 unused) {
glClear(GL_COLOR_BUFFER_BIT);
//renderTex(mViewMatrix, 0, texProgram); // this texture is drawing on screen
glBindFramebuffer(GL_FRAMEBUFFER, fboName[0]);
renderTex(mViewMatrix, 0, texProgram); // rendering workingTexture onto FBO
glBindFramebuffer(GL_FRAMEBUFFER, 0);
renderTex(mViewMatrix, fboTextureUnit[0], texProgram); // texture appears black
}
renderTex is a simple method to render texture. It is working fine.
Also I have checked for GL_ERROR but there is no error.
My understanding of application created FBO is that every read and write glCall will happen on currently bound FBO, so is my understanding of FBO incorrect, or is there some error in my code.
Platform OpenGL|es 20 on Android
The texture which is generated in generateTextureForFBO is mipmap incomplete.
If you do not generate mipmaps (by glGenerateMipmap), then setting the GL_TEXTURE_MIN_FILTER is important. Since the default filter is GL_NEAREST_MIPMAP_LINEAR the texture would be mipmap incomplete, if you don not change the minifying function to GL_NEAREST or GL_LINEAR.
Set the texture minifying function (GL_TEXTURE_MIN_FILTER) by glTexParameter:
glBindTexture(GL_TEXTURE_2D, textureName[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, null);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

Load Texture From File problem Android NDK and OpenGL

I am trying to load an image through OpenGL and stbi_load on android ndk. The problem is that it is generating an invalid texture (equal to zero).
LoadTextureFromFile("/storage/emulated/0/Download/BPV/mic_close.jpg", &my_image_texture, &my_image_width, &my_image_height);
bool CGUI::LoadTextureFromFile(const char* filename, GLuint* out_texture, int* out_width, int* out_height)
{
// Load from file
int image_width = 0;
int image_height = 0;
unsigned char* image_data = stbi_load(filename, &image_width, &image_height, NULL, 4);
if (image_data == NULL)
return false;
// Create a OpenGL texture identifier
GLuint image_texture;
glGenTextures(1, &image_texture);
glBindTexture(GL_TEXTURE_2D, image_texture);
// Setup filtering parameters for display
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// Upload pixels into texture
glPixelStorei(0x0CF2, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image_width, image_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data);
stbi_image_free(image_data);
*out_texture = image_texture; // Receive zero
*out_width = image_width;
*out_height = image_height;
return true;
}
I use libGLESv2
GLuint image_texture;
glGenTextures(1, &image_texture);
...
*out_texture = image_texture; // Receive zero
glGenTextures() just allocates new object and practically never fails, save when called without active OpenGL context.
On Android platform, OpenGL rendering is usually done in dedicated working thread (different from GUI thread), so most likely you call the method from the wrong thread or before OpenGL context initialization (which cannot be deduced from the given code sample).

OpenGL ES2.0 glReadPixels() read data from renderbuffer through framebuffer

I am doing off-screen processing using opengl es2.0 on Android.
I created a renderbuffer, and attached it to a framebuffer FBO, after rendering to the FBO, I try to get the pixels from that FBO by getReadPixels() method. But I got nothing.
The code is shown below:
GLuint resultFBO;// FBO
GLuint rboId; //render buffer id
glGenRenderbuffers(1, &rboId);
glBindRenderbuffer(GL_RENDERBUFFER, rboId);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, image_width, image_height);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glGenFramebuffers(1, &resultFBO);
glBindFramebuffer(GL_FRAMEBUFFER, resultFBO);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, rboId);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status == GL_FRAMEBUFFER_COMPLETE) {
//LOGH("Single FBO setup successfully.");
} else {
LOGH("Problem in setup FBO texture: %d .", status);
}
//After render to the FBO
glBindFramebuffer(GL_FRAMEBUFFER, resultFBO);
glReadPixels(0, 0, w, h, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, imageSetData);
You can not glReadPixels() from GL_DEPTH_COMPONENT in OpenGL ES 2.0. Only from the color buffer. See API Reference here.
void glReadPixels( GLint x,
GLint y,
GLsizei width,
GLsizei height,
GLenum format,
GLenum type,
GLvoid * data);
format
Specifies the format of the pixel data. The following symbolic values are accepted: GL_ALPHA, GL_RGB, and GL_RGBA
Workaround1: If precision is not that important, you can write depth to one of the 8bit color channels instead.
Workaround2: You can write depth into the RGBA channels by packing the float into a vec4: See for example this SO thread.
Workaround3: You can try the OES_depth_texture extension and, if supported, render to a depth texture instead.

Categories

Resources