Search code examples
c++openglmaya

OpenGL GL_UNPACK_ALIGNMENT


Before reading all this and getting lost my main question is how to unpack a single array of pixles and explaining how open gl is reading this data. (my background is not in c++ but mostly python)

your help is greatly appreciated.

im using maya(3d program) which has a class of MImage to get the pixel data of an image. the return result is a single array with every 4 items are RGBA this is what i need to unpack

pixels = [255, 255, 0, 255, 255, 255, 0, 255] //two yellow pixels and it keeps going with this pattern

the following code creates a 256 x 256 image with 4 channels

unsigned int size = 256;
unsigned int depth = 4;

float color[3] = {1, 1, 0};

unsigned char *pixels = new unsigned char[size * size * depth];
for(unsigned int i = 0; i < size; i += depth){
    MScriptUtil::setUcharArray(pixels, i+0, (int)floorf(color[0] * 255.0f + 0.5f));
    MScriptUtil::setUcharArray(pixels, i+1, (int)floorf(color[1] * 255.0f + 0.5f));
    MScriptUtil::setUcharArray(pixels, i+2, (int)floorf(color[2] * 255.0f + 0.5f));
    pixels[i + 3] = 255;
    }

looking into this issue i came across this snippet (which create a checker pattern)which with the last block of code does work and show up with what im trying to do

static GLubyte checkImage[256][256][4];

int i, j, c;

for (i = 0; i < 256; i++) {
    for (j = 0; j < 256; j++) {
        c = ((((i&0x8)==0)^((j&0x8))==0))*255;
        checkImage[i][j][0] = (GLubyte) c;
        checkImage[i][j][1] = (GLubyte) c;
        checkImage[i][j][2] = (GLubyte) c;
        checkImage[i][j][3] = (GLubyte) 255;
    }
}

this array becomes (instead of 256x256 i made it 2x2)

[[[255, 255, 255, 255], [255, 255, 255, 255]], [[255, 255, 255, 255], [255, 255, 255, 255]]]// so on and so forth

with this i set the GL_UNPACK_ALIGNMENT to 1 and everything works

i just cant figure out how gl is reading arrays and how to tell it

for proof of code heres what i got

glDisable ( GL_LIGHTING );
glEnable(GL_TEXTURE_2D);


glGenTextures(1, &glTextureObject);

// set the current texture to the one just created
glBindTexture (GL_TEXTURE_2D, glTextureObject);

// repeat the texture in both directions
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

// use bi-linear filtering on the texture
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);


glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,GL_REPLACE);

// load the texture data into the graphics hardware.
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);

Solution

  • The GL_UNPACK_ALIGNMENT value should not come into play here. The default value is 4. Since you have 4 bytes per pixel when using RGBA values, the size of a row is always a multiple of 4.

    The value only needs to be changed if the amount of data per row is not a multiple of 4. For example, if you have RGB data, with 3 bytes per pixel, you have to change it to 1, unless the rows are actually aligned to 4 byte multiples with extra padding.

    The real problem I see in your code is the loop:

    for(unsigned int i = 0; i < size; i += depth){
        MScriptUtil::setUcharArray(pixels, i+0, (int)floorf(color[0] * 255.0f + 0.5f));
        MScriptUtil::setUcharArray(pixels, i+1, (int)floorf(color[1] * 255.0f + 0.5f));
        MScriptUtil::setUcharArray(pixels, i+2, (int)floorf(color[2] * 255.0f + 0.5f));
        pixels[i + 3] = 255;
    }
    

    Since size is 256, this will only fill the first 256 bytes (corresponding to 64 pixels) with data. To match the definitions and the rest of your code, this loop should be:

    for(unsigned int i = 0; i < size * size * depth; i += depth) {