Menu

Texture loading from a PNG file

2011-11-05
2013-05-28
  • Pat Stevenson

    Pat Stevenson - 2011-11-05

    I hope someone can help me on this.  The Helloworld program constructs an inline bitmapped image that magically loads into the cube and displays a nice red checkerboard.  My problem is that I need to load a PNG file as a texture onto a simple triangle polygon.  The problem is, there's no tutorial on the subject of loading raw RGB values in the texture.  I've scanned the forum and couldn't find anything helpful.

    The primary thing is how to pack a U32 texture array from a PNG interleaved set of row pointers that are pointing to an unsigned char data?  After looking at how its done for OpenGL textures, the same thing unfortunately doesn't apply here.  Thanks to any that can help.

     
  • Michail Vidiassov

    First option is to load PNG file as a bitmapped texture, as if you are going to use it in OpenGL.
    That is not specific to U3D. There are lots of libraries to do that.
    FreeImage and stb_image.c come first to _my_ mind.
    And libpng is the ultimate answer in any case.

    The other option is to trace how IDTFConverter works, since it takes textures as uncompressed TGA files and stores them in U3D as PNG or JPEG compressed images. In this way you may be able to use your original PNG image as is, without decompression/recompression. Did not try that myself.

     
  • Pat Stevenson

    Pat Stevenson - 2011-11-06

    Yep, I'm using libpng to load the image into memory and I'm trying to read through the rows pointers and build the IFXTextureObject through SetRawImage().  I'm gonna look at the libraries you mentioned as well as the Simple Direct Media Layer like I found in an OpenGL Game Programming book.  I guess one natural question is how the png library is being used in U3D?  It includes a version of libpng.  I've looked at the CIFXImageTools class, but wasn't sure it would suit my needs.

    I thank you for your help.  Its been a while since I've posted on the forum, had to create a new login id and everything because my email changed, as well as job, location, etc.  The project I'm using U3D on has gotten deeper in the need for texture a terrain surface with geospatial imagery from ArcGIS Server and SRTM elevation data.  Quite a lot more since the first time around was just handling DTED elevation data from a file!

     
  • Pat Stevenson

    Pat Stevenson - 2011-11-18

    I took your advice and reexamined how I was loading the texture.  I posted another question to the forum about how to do the mapping because the image was not lining up right.  See the forum question "Simple Texture Mapping".  I took a step back and tried to simplify.  Found a great demo to load an OpenGL texture, link is here:

    http://blog.nobel-joergensen.com/2010/11/07/loading-a-png-as-texture-in-opengl-using-libpng/

    Using his example, I then mashed his code with what I was doing to load the IFXTextureObject and got great results!  Even lining up two polygons as a quad and getting the texture mapping to stretch over the entire mesh.  Code subset is below with the important calls, but not the entire base.

      const U32 terrain_texture_width = 400, terrain_texture_height = 400;
      const U32 terrain_texture_bpp = 3;

      unsigned int row_bytes = png_get_rowbytes(png_ptr, info_ptr);
      unsigned char** terrain_texture;
      *terrain_texture = (unsigned char*) malloc(row_bytes * terrain_texture_height);

      for(int i = 0; i < terrain_texture_height; i++)
      {
        // note that png is ordered top to
        // bottom, but OpenGL expect it bottom to top
        // so the order or swapped
        memcpy(*terrain_texture+(row_bytes * (terrain_texture_height-1-i)), row_pointers_, row_bytes);
      }

      // clean up after the read, and free any memory allocated - REQUIRED
      png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

      // close the file
      fclose(png_file);

      // Create texture object
      IFXCreateComponent(CID_IFXTextureObject, IID_IFXTextureObject, (void**)&terrain_texture_object);

      // Initialize the texture object.
      terrain_texture_object->SetSceneGraph(pSceneGraph);

      // Set quality factor to use
      terrain_texture_object->SetQualityFactorX(IFX_DEFAULT_QUALITY_FACTOR);

      // Place the bitmap into the IFXTextureObject
      // Populate the fields in STextureSourceInfo with the properties of the texture.
      STextureSourceInfo terrain_image_info;
      terrain_image_info.m_name = terrain_texture_name;
      terrain_image_info.m_height = terrain_texture_height;
      terrain_image_info.m_width = terrain_texture_width;
      terrain_image_info.m_size = terrain_texture_width*terrain_texture_height*terrain_texture_bpp;
      terrain_image_info.m_imageType = IFXTextureObject::IFXTEXTUREMAP_FORMAT_RGB24;
      terrain_image_info.m_pCodecCID = NULL;

      // Store the texture data and its properties in the pTextureObject.
      terrain_texture_object->SetRawImage(&terrain_image_info, *terrain_texture);

    This is a very fixed hard-coded example and will need more work to make it flexible, but the idea seems to work well.
    _

     

Log in to post a comment.