Search code examples
androidc++opengl-estexture2d

Displaying texture from raw data in Open GL native Android


I'm trying to draw a texture from raw data which elements are unsigned char (or unsigned int) ,each 3 subsequent elements(RGB) representing the pixel data. What I want is to *display this rgb raw data (width=640 ,height =480) on my phone's screen (1920*1080)* . here is my code ! I'm preparing the graphic envirement with egl as below:

bool Render::initializing(ANativeWindow* window)
{
const EGLint attribs[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_BLUE_SIZE,
        8, EGL_GREEN_SIZE, 8, EGL_RED_SIZE, 8, EGL_NONE };
EGLDisplay display;
EGLConfig config;
EGLint numConfigs;
EGLint format;
EGLSurface surface;
EGLContext context;
EGLint width;
EGLint height;
GLfloat ratio;

Log::info("Initializing context");

if ((display = eglGetDisplay(EGL_DEFAULT_DISPLAY)) == EGL_NO_DISPLAY) {
    Log::error("eglGetDisplay() returned error %d", eglGetError());
    return false;
}
if (!eglInitialize(display, 0, 0)) {
    Log::error("eglInitialize() returned error %d", eglGetError());
    return false;
}

if (!eglChooseConfig(display, attribs, &config, 1, &numConfigs)) {
    Log::error("eglChooseConfig() returned error %d", eglGetError());
    destroy();
    return false;
}

if (!eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format)) {
    Log::error("eglGetConfigAttrib() returned error %d", eglGetError());
    destroy();
    return false;
}
Log::info("Setting buffer geometry");
ANativeWindow_setBuffersGeometry(window, 0, 0, format);
Log::info("End Setting buffer geometry");
if (!(surface = eglCreateWindowSurface(display, config, window, 0))) {
    Log::error("eglCreateWindowSurface() returned error %d", eglGetError());
    destroy();
    return false;
}

if (!(context = eglCreateContext(display, config, 0, 0))) {
    Log::error("eglCreateContext() returned error %d", eglGetError());
    destroy();
    return false;
}

if (!eglMakeCurrent(display, surface, surface, context)) {
    Log::error("eglMakeCurrent() returned error %d", eglGetError());
    destroy();
    return false;
}

if (!eglQuerySurface(display, surface, EGL_WIDTH, &width)
        || !eglQuerySurface(display, surface, EGL_HEIGHT, &height)) {
    Log::error("eglQuerySurface() returned error %d", eglGetError());
    destroy();
    return false;
}
//If Landscape
/*if (!eglQuerySurface(display, surface, EGL_WIDTH, &width) ||
 !eglQuerySurface(display, surface, EGL_HEIGHT, &height)) {
 Log::error("eglQuerySurface() returned error %d", eglGetError());
 destroy();
 return false;
 }*/

//
_display = display;
_surface = surface;
_context = context;

} }

and this for drawing the rgb raw data : void Render::drawRGBData(unsigned char *rgb) {

glEnable(GL_TEXTURE_2D);
glGenTextures(1, &gl_rgb_tex);
glBindTexture(GL_TEXTURE_2D, gl_rgb_tex);

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

//glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);


//glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 640, 480, 0, GL_RGB,
        GL_UNSIGNED_BYTE, (GLubyte*) rgb);

//**Drawing***/

float tricoords[12] = { 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0,
        1.0, 0.0 };
float texcoords[12] = { 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0,
        1.0, 0.0 };

/*float tricoords[12] = { -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0,
 1.0, -1.0 };
 float texcoords[12] = { 0-1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0,
 1.0, -1.0 };*/


glBindTexture(GL_TEXTURE_2D, gl_rgb_tex);
glEnableClientState(GL_VERTEX_ARRAY); //enable gl vertex pointer to be used in draw fct
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

glVertexPointer(2, GL_FLOAT, 0, tricoords);
glTexCoordPointer(2, GL_FLOAT, 0, texcoords);

glDrawArrays(GL_TRIANGLES, 0, 8);

glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);

} 

This last method is called in a loop,for each new received rgb data. and I'm doing this to swap buffer:

if (!eglSwapBuffers(renderer->_display, renderer->_surface)) {
Log::error("eglSwapBuffers() returned error %d", eglGetError());
        }

This is a screenshot representing what I get on my phone's screen ,a 1080x1920 resolution.

http://s1.postimg.org/hh4z4j2gv/Screenshot_2014_07_17_17_55_17_Convert_Image.jpg

The problem is in the procedure of drawing the texture,and mapping the pixels correctly from the raw data to the texture to be displayed.


Solution

  • First let's sure your triangles are rendering correctly.

    You seem to be submitting invalid triangles so try with this:

    float tricoords[12] = { 0.0, 0.0, 
                            1.0, 0.0, 
                            1.0, 1.0, 
                            0.0, 0.0, 
                            1.0, 1.0, 
                            0.0, 1.0 };
    float texcoords[12] = { 0.0, 0.0, 
                            1.0, 0.0, 
                            1.0, 1.0, 
                            0.0, 0.0, 
                            1.0, 1.0,
                            0.0, 1.0 };
    

    Next you are attempting to draw 8 vertices... two triangles should be 6:

    glDrawArrays(GL_TRIANGLES, 0, 6);
    

    Make sure your triangles are rendering without the texture, so pass a color array:

    glDisable(GL_TEXTURE_2D);
    glEnableClientState(GL_COLOR_ARRAY);
    float colors[18] = { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 
                         0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0 }; 
    glColorPointer(3, GL_FLOAT, 0, colors);
    

    Now that you have confirmed the triangles are rendering correctly, here is a resource for loading and displaying your .bmp file:

    http://www.opengl-tutorial.org/beginners-tutorials/tutorial-5-a-textured-cube/#Loading__BMP_images_yourself