Transfer GL_TEXTURE_2D Image to GL_TEXTURE_CUBE_MAP

51 Views Asked by At

I am attempting to implement a Skybox into my C++ OpenGL project, and I want to use 6 x preloaded GL_TEXTURE_2D's retrieved from my TextureLibrary which loads all textures into the application as GL_TEXTURE_2D.

The issue I am running into is that I cannot use a GL_TEXTURE_2D for each face of a GL_TEXTURE_CUBE_MAP (that I know of). I have tried a variety of different approaches, however it appears that I cannot refer to or copy the image data from a GL_TEXTURE_2D to a GL_TEXTURE_CUBE_MAP face such as GL_TEXTURE_CUBE_MAP_POSITIVE_X on the GPU side.

To get this working currently the texture is being loaded on the CPU into my TextureLibrary as a GL_TEXTURE_2D, then it is being loaded again on the CPU in my Skybox class as a target of a GL_CUBE_MAP face, just as a temporary and inefficient way around this issue.

Is there any way to have the face of a GL_CUBE_MAP refer to or copy the data of a GL_TEXTURE_2D?

I plan to utilise these textures as GL_TEXTURE_2D's throughout the application in the future so I want to have them loaded on the CPU side once into my TextureLibrary, and only when they are used by a Skybox, the data is referenced or copied on the GPU side into a GL_TEXTURE_CUBE_MAP.

Alternatively, I could scrap the idea of using a GL_TEXTURE_CUBE_MAP, and pass my skybox shader 6 x Sampler2D's; however, I would like to know if there is any way I can do this per the above - OR any other ideas.

2

There are 2 best solutions below

3
Erdal Küçük On BEST ANSWER

You can try this:

//generate cubemap texture object name
glGenTextures(1, &my_cube_map_texture);
//make it a cubemap texture
glBindTexture(GL_TEXTURE_CUBE_MAP, my_cube_map_texture);

//for each cubemap face
for (int i=0; i < 6; ++i) {

    //create face
    //where i
    //0: GL_TEXTURE_CUBE_MAP_POSITIVE_X
    //1: GL_TEXTURE_CUBE_MAP_NEGATIVE_X
    //2: GL_TEXTURE_CUBE_MAP_POSITIVE_Y
    //3: GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
    //4: GL_TEXTURE_CUBE_MAP_POSITIVE_Z
    //5: GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
    glTexImage2D(
        GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, //target
        0,                //level
        iformat,          //internalformat
        width,            //width
        height,           //height
        0,                //border
        format,           //data format
        GL_UNSIGNED_BYTE, //data type
        NULL              //no copy, allocate only
    );

    //copy data from existent 2d texture into the specific face
    glCopyImageSubData(
        my_texture_2d[i],    //srcName
        GL_TEXTURE_2D,       //srcTarget
        0,                   //srcLevel
        0,                   //srcX
        0,                   //srcY
        0,                   //srcZ
        my_cube_map_texture, //dstName
        GL_TEXTURE_CUBE_MAP, //dstTarget
        0,                   //dstLevel
        0,                   //dstX
        0,                   //dstY
        i,                   //dstZ
        width,               //srcWidth
        height,              //srcHeight
        1                    //srcDepth
    );

}

Prerequisites:

  • OpenGL 4.3+
  • the textures have to be square images (width == height)
  • the cubemap faces must have all the same sizes, therefore the textures have to be of the same size
  • the format must match, otherwise copy will produce error

Reference:


There is an alternative solution, follow the links for more information:


If everything else fails:

  • bind a buffer to GL_PIXEL_PACK_BUFFER target
  • copy texture data into buffer via glGetTexImage
  • bind buffer to GL_PIXEL_UNPACK_BUFFER target
  • create cubemap face

No client memory involved, all on the GPU side.

2
Nicol Bolas On

Is there any way to have the face of a GL_CUBE_MAP refer to or copy the data of a GL_TEXTURE_2D?

I plan to utilise these textures as GL_TEXTURE_2D's throughout the application in the future so I want to have them loaded on the CPU side once into my TextureLibrary, and only when they are used by a Skybox, the data is referenced or copied on the GPU side into a GL_TEXTURE_CUBE_MAP.

You can do this the other way around. That is, you can create a cube map and create 6 view textures that are 2D textures of each cube map face. But you can't do this the other way around; you cannot take 6 independent texture objects and merge their storage into a single texture object.

It would be better to use an image loading library that allows you to load cube maps directly as such, rather than trying to hack it in after-the-fact.