使用24位位图作为OpenGL的材质贴图

Here is a fairly fast and easy way to use a Windows bitmap file (.bmp file) as a texture map in OpenGL. The limitation is that it only works with 24-bit bitmaps. To work with other bitmaps you need to pick apart the pixel values and look them up in the images color table which is a bit more complicated.

在OpenGL里使用windows位图作为材质贴图,限制是只能是24位位图,要使用其它类型的位图必须使用颜色表

使用windowAPI来装载Image

You can load a bitmap using the Windows API function LoadImage.

To load an image from a file use:

        HBITMAP hBmp = (HBITMAP) ::LoadImage (NULL,
                        (LPCTSTR) fileName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE |
                        LR_CREATEDIBSECTION);

where filename is the name of the bitmap file. According to the documentation this doesn't work on Windows NT but I'm running NT 4.0 and it works fine for me.

To load an image from the resources use:

        HBITMAP hBmp = (HBITMAP) ::LoadImage (AfxGetResourceHandle(),
                        MAKEINTRESOURCE(IDB_BITMAP1), IMAGE_BITMAP, 0, 0,
                        LR_CREATEDIBSECTION);

where IDB_BITMAP1 is the ID of the bitmap resource.

Note that bitmaps created in the DevStudio resource editor are not 24-bit color. You'll need to create your bitmap with some other program (like mspaint).

Once you have a handle to the bitmap you can get information about it with the windows function GetObject. GetObject fills in a BITMAP structure that contains the dimensions, bits per pixel and a pointer to the pixels themselves.

        BITMAP BM;
        ::GetObject (hBmp, sizeof (BM), &BM);

If the bitmap is a 24-bit bitmap then the format that the RGB values stored is not far off from the way OpenGL RGB bitmaps are formed. BM.bmBits points to an array of unsigned chars where each set of 3 bytes represents an BGR value - an RGB value where blue and red are switched. In addition each row of the bitmap must start on a longword boundary so rows are padded with extra bytes at the end to ensure this.

In order for OpenGL to ignore the padding at the end of the rows use:

        glPixelStorei(GL_UNPACK_ALIGNMENT, 4);

This is the default setting on most systems.

In order for OpenGL to understand BGR use GL_BGR_EXT instead of GL_RGB in your call to glTexImage2D or gluBuild2DMipmaps:

        gluBuild2DMipmaps( GL_TEXTURE_2D, 3, BM.bmWidth, BM.bmHeight,
                           GL_BGR_EXT, GL_UNSIGNED_BYTE,
                           BM.bmBits );

Note that if you use glTexImage2D instead of gluBuild2DMipmaps you'll have to scale the image so that both dimensions are a power of 2.

The sample program uses these routines to load a bitmap and texture map it onto a sphere. The interesting code is in the LoadTexture method of the view class.

        HBITMAP hBmp = (HBITMAP) ::LoadImage (NULL,
                        (LPCTSTR) fileName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE |
                        LR_CREATEDIBSECTION);

        if (hBmp == NULL)
        {
          AfxMessageBox("Error: unable to load bitmap file");
          return FALSE;
        }

        // Get bitmap info.
        BITMAP BM;
        ::GetObject (hBmp, sizeof (BM), &BM);

        // Must be 24 bit
        if (BM.bmBitsPixel != 24)
        {
          AfxMessageBox("Error: bitmap must be 24 bit");
          return FALSE;
        }

 // Make the rendering context current
        // (must do b/f any OpenGL calls)
        ::wglMakeCurrent(m_hDC,m_hRC);

        // Generate name for and bind texture.
        if (!m_texName)
        {
              glGenTextures(1, &m_texName);
        }
        glBindTexture(GL_TEXTURE_2D, m_texName);

        // Set up all the the texture mapping params.
        glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
        glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
        glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
        glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST );
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

        // Build the texture map
        // Could use glTexImage2D instead but then we would have to scale
        // the image to make it a power of 2.
        gluBuild2DMipmaps( GL_TEXTURE_2D, 3, BM.bmWidth, BM.bmHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE,
              BM.bmBits );

        glBindTexture(GL_TEXTURE_2D, 0);

This code has been tested with VisualC++ 5.0, Windows NT with an OxygenGMX2000 graphics accelerator.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值