0
votes

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.

4
You are submitting 6 vertices, first 3 are a clock-wise triangle, the next 3 aren't a valid triangle. Your texcoords also seem to be incorrect. And you are calling glDrawArrays for 8 indices, when you only have 6... The commented out tricoords seems to be correct.kbirk

4 Answers

1
votes

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

0
votes

The fact that a texture is showing up on the screen suggests that your setup code is correct.

Most likely the issue as that wrong information being passed to glTexImage2D concerning the size or formatting of the raw data. The first thing I would try would be to swap the width and height, since the texture might be arranged in memory different than OpenGL is expecting.

0
votes

Don't forget textures need to be a power of 2. Though I'm surprised you got anything at all on the screen. I'd create a 1k x 1k texture and then just pass in the corrected texture coords.

0
votes

Thanks guys for your answers. Now,I've used Pondwater code to display simple colored triangles I've changed color table (each color should be on 4 channels ) :

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] = { -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 colors[24] = { 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0,
        0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 };

It works perfectly as expected.

Now it's clear as fentelia said that the problem is related to how my raw data is organized,because when I go back to my raw data I get strange results,I need help ,how to read correctly a bmp image in native android ,and transmit it correctly to the opengl buffer through glTexImage2D or glSubTexImage2D. Thanks..