c++openglvolume-rendering

Load non power of two image stack into 3d texture OpenGL C++


i have tried to load stack of .png image files into glTexImage3D for volume rendering purpose. However, i just cant make it work as it keeps crashing. BTW, the problem seems to be related with pData.

Below is the code for your reference:

GLubyte * pData = new GLubyte[XDIM*YDIM*ZDIM];
ifstream volumeData;

getFileNameWithSpecificExtension(dir_path);
sort(begin(fileIndex), end(fileIndex));

for (int i = 0; i < 201; i ++)
{
    volumeData.open(FrontPart + to_string(fileIndex[i]) + ".png", ios::binary);
}

volumeData.read(reinterpret_cast<char*>(pData), XDIM*YDIM*ZDIM*sizeof(GLubyte));
volumeData.close();


glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_3D, textureID);

// set the texture parameters
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);

//set the mipmap levels (base and max)
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 4);

//allocate data with internal format and foramt as (GL_RED) 
glTexImage3D(GL_TEXTURE_3D, 0, GL_RED, XDIM, YDIM, ZDIM, 0, GL_RED, GL_UNSIGNED_BYTE, pData);
GL_CHECK_ERRORS

//generate mipmaps
glGenerateMipmap(GL_TEXTURE_3D);

//delete the volume data allocated on heap
delete[] pData;

Solution

  • Non-Power-of-2 is no issue since OpenGL-2.0 removed that constraint. For reading each image slice into the texture use glTexImage3D with a NULL pointer to initialize the texture, then in the loop iterating over the files, read each file, decode it and load it into the right slice using glTexSubImage3D. Also don't use explicit new and delete[] but a std::vector.

    Properly implementing the "foreach file" loop and the "ImageFileReader" are left as an exercise for the reader. I suggest looking into the Generic Image library for one particular candidate (http://sourceforge.net/adobe/genimglib/home/Home/). Also keep in mind that it's a very bad idea to hardcode any image dimensions into your code.

    glGenTextures(1, &textureID);
    glBindTexture(GL_TEXTURE_3D, textureID);
    
    // set the texture parameters
    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    
    //set the mipmap levels (base and max)
    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 0);
    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 4);
    
    //allocate data with internal format and foramt as (GL_RED) 
    glTexImage3D(GL_TEXTURE_3D, 0, GL_RED, XDIM, YDIM, ZDIM, 0, GL_RED, GL_UNSIGNED_BYTE, NULL);
    GL_CHECK_ERRORS
    
    GLubyte * pData = new GLubyte[XDIM*YDIM*ZDIM];
    std::vector<GLubyte> vData(XDIM*YDIM*ZDIM);
    foreach file in filenames (...)
    {
        ImageFileReader ifr(FrontPart + to_string(fileIndex[i]) + ".png")
        ifr.decode(vData);
        glTexSubImage3D(GL_TEXTURE_3D, 0,
            0 /* x offset */,
            0 /* y offset */,
            z,
            XDIM, YDIM, 1,
            GL_RED, GL_UNSIGNED_BYTE,
            &vData[0] );
    }
    
    //generate mipmaps
    glGenerateMipmap(GL_TEXTURE_3D);