OpenGL载入图片作为纹理

时间:2021-10-30 04:47:38

参考资料:《厦门大学计算机图像学教程》第4.1章(附代码)

一、可以使用该教程包装的类用俩个函数来实现图片的导入,

第一个函数支持导入*.BMP,*.EMF,*.GIF,*.ICO,*.JPG和*.WMF

第二个函数用来导入*.TGA格式的图片。


2、我在自己的项目使用过程中,只使用了第一个函数,并把它包装到了自己的类中。

进行了少许修改

①、删掉了“添加/和将路径拼接起来”的那部分代码,因为我的代码可以直接传递完整路径。

但将string路径转为char*用了强制转换。(char*)strFiletexData.c_str()

②、添加了保存原始图片大小变量。以便于后面在纹理映射中的使用(opengl要求纹理图片大小为1,像素坐标必须要除以图片大小)

//原始图像大小赋值
ImgageWidth=lWidthPixels;
ImgageHeight=lHeightPixels;

③、纹理的显示做了部分修改,添加了几个函数

glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);


附一:我改的类函数

// 载入图片并转换为纹理
BOOL CtestviewView::BuildTexture(char *szPathName, GLuint &texid)
{

MultiByteToWideChar(CP_ACP, 0, szPathName, -1, wszPath, MAX_PATH);// 把ASCII码转化为Unicode标准码
HRESULT hr = OleLoadPicturePath(wszPath, 0, 0, 0, IID_IPicture, (void**)&pPicture);

if(FAILED(hr))// 如果导入失败
{
// 图片载入失败出错信息
MessageBox ("图片导入失败!\n(TextureLoad Failed!)", "Error", MB_OK | MB_ICONEXCLAMATION);
return FALSE;// 返回 FALSE
}

hdcTemp = CreateCompatibleDC(::GetDC(0)); // 建立窗口设备描述表
if(!hdcTemp)// 建立失败?
{
pPicture->Release();// 释放IPicture
// 图片载入失败出错信息
MessageBox ("图片导入失败!\n(TextureLoad Failed!)", "Error", MB_OK | MB_ICONEXCLAMATION);
return FALSE;// 返回 FALSE
}
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &glMaxTexDim);// 取得支持的纹理最大尺寸
pPicture->get_Width(&lWidth);// 取得IPicture 宽度 (转换为Pixels格式)
lWidthPixels= MulDiv(lWidth, GetDeviceCaps(hdcTemp, LOGPIXELSX), 2540);
pPicture->get_Height(&lHeight);// 取得IPicture 高度 (转换为Pixels格式)
lHeightPixels= MulDiv(lHeight, GetDeviceCaps(hdcTemp, LOGPIXELSY), 2540);

//原始图像大小赋值
ImgageWidth=lWidthPixels;
ImgageHeight=lHeightPixels;

// 调整图片到最好的效果
if (lWidthPixels <= glMaxTexDim)// 图片宽度是否超过显卡最大支持尺寸
lWidthPixels = 1 << (int)floor((log((double)lWidthPixels)/log(2.0f)) + 0.5f);
else// 否则,将图片宽度设为显卡最大支持尺寸
lWidthPixels = glMaxTexDim;

if (lHeightPixels <= glMaxTexDim)// 图片高度是否超过显卡最大支持尺寸
lHeightPixels = 1 << (int)floor((log((double)lHeightPixels)/log(2.0f)) + 0.5f);
else// 否则,将图片高度设为显卡最大支持尺寸
lHeightPixels = glMaxTexDim;

// 建立一个临时位图
BITMAPINFObi = {0};// 位图的类型
DWORD*pBits = 0;// 指向位图Bits的指针

bi.bmiHeader.biSize= sizeof(BITMAPINFOHEADER);// 设置结构大小
bi.bmiHeader.biBitCount= 32;// 32 位
bi.bmiHeader.biWidth= lWidthPixels;// 宽度像素值
bi.bmiHeader.biHeight= lHeightPixels;// 高度像素值
bi.bmiHeader.biCompression= BI_RGB;// RGB 格式
bi.bmiHeader.biPlanes= 1;// 一个位平面

// 建立一个位图这样我们可以指定颜色和深度 并访问每位的值
hbmpTemp = CreateDIBSection(hdcTemp, &bi, DIB_RGB_COLORS, (void**)&pBits, 0, 0);

if(!hbmpTemp)// 建立失败?
{
DeleteDC(hdcTemp);// 删除设备描述表
pPicture->Release();// 释放IPicture
// 图片载入失败出错信息
MessageBox ("图片导入失败!\n(TextureLoad Failed!)", "Error", MB_OK | MB_ICONEXCLAMATION);
return FALSE;// 返回 FALSE
}

SelectObject(hdcTemp, hbmpTemp);// 选择临时DC句柄和临时位图对象

// 在位图上绘制IPicture
pPicture->Render(hdcTemp, 0, 0, lWidthPixels, lHeightPixels, 0, lHeight, lWidth, -lHeight, 0);

// 将BGR转换为RGB 将ALPHA值设为255
for(long i = 0; i < lWidthPixels * lHeightPixels; i++)// 循环遍历所有的像素
{
BYTE* pPixel= (BYTE*)(&pBits[i]);// 获取当前像素
BYTE temp= pPixel[0];// 临时存储第一个颜色像素(蓝色)
pPixel[0]= pPixel[2];// 将红色值存到第一位
pPixel[2]= temp;// 将蓝色值存到第三位
pPixel[3]= 255;// ALPHA值设为255
}
glGenTextures(1, &texid);// 创建纹理
// 使用来自位图数据生成 的典型纹理
glBindTexture(GL_TEXTURE_2D, texid);// 绑定纹理
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);// 线形滤波
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // 线形滤波
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);

// 生成纹理
glTexImage2D(GL_TEXTURE_2D, 0, 3, lWidthPixels, lHeightPixels, 0, GL_RGBA, GL_UNSIGNED_BYTE, pBits);
DeleteObject(hbmpTemp);// 删除对象
DeleteDC(hdcTemp);// 删除设备描述表
pPicture->Release();// 释放 IPicture

return TRUE;// 返回 TRUE
}

附二:包装好的载入纹理图片的类