OpenGL——纹理贴图

来源:互联网 发布:流程优化项目计划书 编辑:程序博客网 时间:2024/04/20 04:33

需求分析:

不贴图的Opengl是不完整的Opengl,给模型贴上贴图,让其显得更加逼真



编译环境:

vsiual stduio 2015




引用:

Opengl——光照系统




解决方案:

要做就要做的全面一点,例如我们要假设以后如果要加载多个纹理做预备处理
[OpenglDraw.h]

//{ Opengl画图类struct CTexture{    WCHAR pCharName[256];    GLuint nIndex; };class COpenglDraw {    // ...protected:    CTexture* m_pTextures;      // 纹理数组    GLuint  m_nTextureLoaded;   // 已经使用的纹理数    GLuint  m_nTextureCount;    // 支持的纹理数    GLuint  m_nTextureInc;      // 纹理数组满了以后的增长    // 读取纹理    BOOL LoadGLTextures(LPCWSTR szFileName);}

[OpenglDraw.cpp]

COpenglDraw::COpenglDraw(){    // ...    m_nTextureLoaded = 0;    m_nTextureCount = 10;    m_nTextureInc = m_nTextureCount;    m_pTextures = new CTexture[m_nTextureInc];}COpenglDraw::~COpenglDraw(){    if( m_pTextures )        delete[] m_pTextures;  // 释放纹理}BOOL COpenglDraw::InitOpenGL( HWND hWnd ){    //..    // 加载我们需要的纹理    LoadGLTextures( _T("E:\\Project\\OpenGLX\\Crate.bmp" );    // 允许纹理    glEnable(GL_TEXTURE_2D);    //..}// 加载纹理BOOL LoadGLTextures(LPCWSTR szFileName){    HBITMAP hBMP;                                       // Handle Of The Bitmap    BITMAP BMP;                                         // Bitmap Structure    hBMP = (HBITMAP)LoadImage(GetModuleHandle(NULL), szFileName, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE);    if (!hBMP)                          // Does The Bitmap Exist?        return FALSE;                   // If Not Return False    if( m_nTextureLoaded == m_nTextureCount )    {        m_nTextureCount += m_nTextureInc;        CTexture* pNew = new CTexture[m_nTextureCount];        memcpy( pNew, m_pTextures, sizeof(CTexture)*(m_nTextureCount-m_nTextureInc) );        delete []m_pTextures;        m_pTextures = pNew;    }    wcscpy_s( m_pTextures[m_nTextureLoaded].pCharName, szFileName );    glGenTextures( 1, &m_pTextures[m_nTextureLoaded].nIndex );    GetObject(hBMP, sizeof(BMP), &BMP);    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);    glBindTexture(GL_TEXTURE_2D, m_pTextures[m_nTextureLoaded].nIndex );    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);   // Linear Min Filter    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);   // Linear Mag Filter    glTexImage2D(GL_TEXTURE_2D, 0, 3, BMP.bmWidth, BMP.bmHeight, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, BMP.bmBits);    DeleteObject(hBMP);   // Delete The Object    m_nTextureLoaded++;    return TRUE;}

我们使用的纹理图片,没错就是盗用NeHe的
这里写图片描述

普通使用glColor上色以后结合纹理的图样
这里写图片描述

启用颜色追踪的时候开启光照
这里写图片描述

使用材质开启光照的时候
这里写图片描述




补丁:

时间:2017.03.14
说明:根据后期添加透明背景图的支持,对纹理加载部分进行了补充支持
[OpenglDraw.h]

//{ Opengl画图类class COpenglDraw {public:    // 读取纹理    BOOL LoadGLTextures(LPCWSTR szFileName, BOOL bTransparent = FALSE, COLORREF trClr = RGB(0,0,0), int nRange = 0 );}

[OpenglDraw.cpp]
纹理加载

// 加载纹理  这部分较之前还是有很大变化的BOOL COpenglDraw::LoadGLTextures(LPCWSTR szFileName, BOOL bTransparent, COLORREF trClr, int nRange){    BYTE* pBuffer = NULL;    int nWidth = 0;    int nHeight = 0;    TransparentBmp(szFileName, pBuffer, nWidth, nHeight, RGB(255,255,255), 50, bTransparent );    if (pBuffer == NULL)        return FALSE;    if (m_nTextureLoaded == m_nTextureCount)    {        m_nTextureCount += m_nTextureInc;        CTexture* pNew = new CTexture[m_nTextureCount];        memcpy(pNew, m_pTextures, sizeof(CTexture)*(m_nTextureCount - m_nTextureInc));        delete[]m_pTextures;        m_pTextures = pNew;    }    // 获得可用纹理    glGenTextures( 1, &m_pTextures[m_nTextureLoaded].m_nIndex );    wcscpy_s(m_pTextures[m_nTextureLoaded].m_szCharName, szFileName);    glBindTexture(GL_TEXTURE_2D, m_pTextures[m_nTextureLoaded].m_nIndex);    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);   // Linear Min Filter    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);   // Linear Mag Filter    // 带透明化纹理    // 是GBRA模式    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, nWidth, nHeight, 0, GL_GBRA, GL_UNSIGNED_BYTE, pBuffer);    delete[] pBuffer;    m_nTextureLoaded++;    return TRUE;}



图片可透明化处理

// 加载图片获得像素信息(透明化或则非透明化都可以,针对32位和24位位深BMP)BOOL COpenglDraw::TransparentBmp(LPCWSTR pFileName, BYTE*& pBuffer, int& nWidth, int& nHeight, COLORREF transparentClr, GLuint nRange, BOOL bTransparent ){    char FileName[256] = { 0 };    size_t Count;    wcstombs_s(&Count, FileName, pFileName, 256);    FILE* bmpFile = NULL;    fopen_s(&bmpFile,FileName, "rb");    if (bmpFile == NULL)        return FALSE;    BITMAPFILEHEADER bmpFileHeader;    BITMAPINFOHEADER bmpInfoHeader;    // 读取文件头    fread(&bmpFileHeader, sizeof(bmpFileHeader), 1, bmpFile);    // 读取位图信息头    fread(&bmpInfoHeader, sizeof(bmpInfoHeader), 1, bmpFile);    nWidth = bmpInfoHeader.biWidth;    nHeight = abs(bmpInfoHeader.biHeight);    int nPixelCount = nWidth * nWidth;    int nSize32 = nPixelCount * 4;        // 转换成RGBA的模式    int nSize24 = nPixelCount * 3;    BYTE* orgImage = NULL;    if( bmpInfoHeader.biBitCount == 32 )    {        orgImage = new BYTE[nSize32];        fread( orgImage, nSize32, 1, bmpFile );    }    else if( bmpInfoHeader.biBitCount == 24 )    {        orgImage = new BYTE[nSize24];        fread( orgImage, nSize24, 1, bmpFile );        nSize = nSize24;    }    fclose( bmpFile );    if( !bTransparent )    {        pBuffer = orgImage;        return TRUE;    }    nSize = nSize32;    if( bmpInfoHeader.biBitCount == 24 )    {        pBuffer = new BYTE[nSize32];        for (int i = 0; i < nPixelCount; i ++ )        {            pBuffer[i*4] = orgImage[i*3];            pBuffer[i*4+1] = orgImage[i*3+1];            pBuffer[i*4+2] = orgImage[i*3+2];        }        delete[] orgImage;    }    int lR = GetRValue(transparentClr) - nRange;    int lG = GetGValue(transparentClr) - nRange;    int lB = GetBValue(transparentClr) - nRange;    int hR = GetRValue(transparentClr) + nRange;    int hG = GetGValue(transparentClr) + nRange;    int hB = GetBValue(transparentClr) + nRange;    // 透明度修正, BMP颜色内存存储方式 GBR     for (int i = 0; i < nPixelCount; i ++ )    {        if (pBuffer[i*4+2] > lR    &&  pBuffer[i*4+2] < hR   &&             pBuffer[i*4+1] > lG  &&  pBuffer[i*4+1] < hG &&             pBuffer[i*4] > lB  && pBuffer[i*4] < hB  )            pBuffer[i*4+3] = 0;        else            pBuffer[i*4+3] = 255;    }    return TRUE;}
0 0
原创粉丝点击