简体   繁体   中英

Simple code to create an OpenGL cubemap from “cross layout” image file

I'm looking for a simple C subroutine (in Linux) that takes a filename parameter and makes the 6 calls to glTexImage2D to define a "cubemap" texture ( GL_TEXTURE_CUBE_MAP ).

I'd like to be able to read a "cross layout" file (horizontal or vertical) or a "Horizontal Strip" file, so this requires various cropping operations (and possibly some rotates to match the orientation that OpenGL expects).

I'm sure this code exists, but I Googled around and only found fragments.

I stumbled on the GEGL / BABL libraries. This looks good. A bit overkill, but it can read from a file (" gegl:load "), crop, rotate and BABL can do various pixel format operations (to match the OpenGL GL_RGB or GL_RGBA format).

Also, it might be useful to read a "rectilinear" texture file and convert to the gnomic projections (I'm using MMPS for this now).

I found this Python "gimpfu" code ( http://registry.gimp.org/files/cubemap-to-dds-v0.3.py.txt ) that converts from a "cross layout" to a multi-image DDS file, so that's similar to what I want, but I'd rather not have Python code in my app. GIMP uses GEGL internally, so that's why I'm using that.

Well... I wrote a very simple "vertical strip" cubemap reader using the Freeimage library. Here's the crux:

FIBITMAP *bitmap = FreeImage_Load(FreeImage_GetFileType(name0, 0), name0, BMP_DEFAULT);
FIBITMAP *pImage = FreeImage_ConvertTo32Bits(bitmap);
FreeImage_Unload(bitmap);

int width0=FreeImage_GetWidth(pImage);
int height0=FreeImage_GetHeight(pImage);
void *pixels0 = FreeImage_GetBits(pImage);

// "v-strip" (for simplicity, assume OpenGL order and orientation)
height0 /= 6;
for(int idx0=GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; idx0 >= GL_TEXTURE_CUBE_MAP_POSITIVE_X ; idx0--) { // NB : index goes backwards because image files start at the bottom
    glTexImage2D(idx0, 0, GL_RGB, width0, height0,
            0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, pixels0);
    pixels0 += width0 * height0 * 4; // "4" : sizeof(RGBA pixel) ?
}
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
FreeImage_Unload(pImage);

That gets me started. I have a MMPS script that converts from rectilinear to v-strip, but I'm still fiddling with the orientations. As one book says, "The orientation of the texture coordinates of each face are counter-intuitive". I might convert the script to "nona" / PTstitcher (part of PanoTools).

FYI, there are many cubemap image file formats. V-strip is easiest to read. "Horizontal cross" seems to be popular. In general, there are {horizontal, vertical} x {cross, strip, tee} (and probably more).

I have some code that reads crosses, h-strips (it uses glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, width0) ), but it still doesn't deal with the orientations. I'll have to use something like GEGL or libpano13. Or perhaps hack an intermediate step that uses execl to run MMPS / nona / ImageMagick. Maybe libpano13 is way to go : I could generate the cubemaps on the fly from rectilinear files.

Cheers!

Update: here's the MMPS bash script to convert from a rectilinear image to v-strip (in OpenGL order and orientation) :

## NB : yum install ImageMagick # for convert & montage

infile0=$1

MMPS0=~/mmps-0-1-36
tmp0=/tmp/cube$$
convert $infile0 $tmp0.ppm

ARGS0="gnomonic -grid -gridcolor 255:255:255 -scale 2 -w 512 -h 512"
ARGS0="gnomonic -scale 2 -w 512 -h 512"
#
$MMPS0/project $ARGS0 -lat   0 -long   0 -f $tmp0.ppm -rotate -90 > $tmp0-xp.ppm &    ## africa
$MMPS0/project $ARGS0 -lat   0 -long 180 -f $tmp0.ppm -rotate  90 > $tmp0-xn.ppm &    ## pacific ocean
$MMPS0/project $ARGS0 -lat   0 -long  90 -f $tmp0.ppm -rotate 180 > $tmp0-yp.ppm &    ## indian ocean
$MMPS0/project $ARGS0 -lat   0 -long 270 -f $tmp0.ppm -rotate   0 > $tmp0-yn.ppm &    ## americas
$MMPS0/project $ARGS0 -lat  90 -long   0 -f $tmp0.ppm -rotate -90 > $tmp0-zp.ppm &    ## north pole
$MMPS0/project $ARGS0 -lat -90 -long   0 -f $tmp0.ppm -rotate -90 > $tmp0-zn.ppm &    ## south pole
wait
montage $tmp0-xp.ppm $tmp0-xn.ppm \
    $tmp0-yn.ppm $tmp0-yp.ppm \
    $tmp0-zp.ppm $tmp0-zn.ppm \
    -mode Concatenate -tile 1x6 cube-vstrip-ogl.jpg
    ##$tmp0-yp.ppm $tmp0-yn.ppm \   ##### swap 'em ??? had to reverse
    # also, for textures viewed from the "outside" (eg : earth texture on sphere, swap y in frag shader:
    # gl_FragColor = textureCube(cubemap2, vec3(texCoord0.x, -texCoord0.y, texCoord0.z));

rm $tmp0-*

FYI, I found some test images ( https://www.terathon.com/wiki/index.php/Importing_a_Texture ) and the v-strip is in OpenGL order and orientation, so maybe that's typical.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM