Texture.cpp
上传用户:lygtks
上传日期:2022-06-08
资源大小:874k
文件大小:9k
源码类别:

射击游戏

开发平台:

Visual C++

  1. #include <stdio.h> // 标准输入输出头文件
  2. #include <olectl.h> // OLE控制库头文件
  3. #include <math.h> // 数学函数头文件
  4. #include <glgl.h> // OpenGL32库的头文件
  5. #include "Texture.h"
  6. BOOL BuildTexture(char *szPathName, GLuint &texid) // 载入图片并转换为纹理
  7. {
  8. HDC hdcTemp; // DC用来保存位图
  9. HBITMAP hbmpTemp; // 保存临时位图
  10. IPicture *pPicture; // 定义IPicture Interface
  11. OLECHAR wszPath[MAX_PATH+1]; // 图片的完全路径
  12. char szPath[MAX_PATH+1]; // 图片的完全路径
  13. long lWidth; // 图像宽度
  14. long lHeight; // 图像高度
  15. long lWidthPixels; // 图像的宽带(以像素为单位)
  16. long lHeightPixels; // 图像的高带(以像素为单位)
  17. GLint glMaxTexDim ; // 保存纹理的最大尺寸
  18. if (strstr(szPathName, "http://")) // 如果路径包含 http:// 则...
  19. {
  20. strcpy(szPath, szPathName); // 把路径拷贝到 szPath
  21. }
  22. else // 否则从文件导入图片
  23. {
  24. GetCurrentDirectory(MAX_PATH, szPath); // 取得当前路径
  25. strcat(szPath, "\"); // 添加字符""
  26. strcat(szPath, szPathName); // 添加图片的相对路径
  27. }
  28. MultiByteToWideChar(CP_ACP, 0, szPath, -1, wszPath, MAX_PATH); // 把ASCII码转化为Unicode标准码
  29. HRESULT hr = OleLoadPicturePath(wszPath, 0, 0, 0, IID_IPicture, (void**)&pPicture);
  30. if(FAILED(hr)) // 如果导入失败
  31. {
  32. // 图片载入失败出错信息
  33. MessageBox (HWND_DESKTOP, "图片导入失败!n(TextureLoad Failed!)", "Error", MB_OK | MB_ICONEXCLAMATION);
  34. return FALSE; // 返回 FALSE
  35. }
  36. hdcTemp = CreateCompatibleDC(GetDC(0)); // 建立窗口设备描述表
  37. if(!hdcTemp) // 建立失败?
  38. {
  39. pPicture->Release(); // 释放IPicture
  40. // 图片载入失败出错信息
  41. MessageBox (HWND_DESKTOP, "图片导入失败!n(TextureLoad Failed!)", "Error", MB_OK | MB_ICONEXCLAMATION);
  42. return FALSE; // 返回 FALSE
  43. }
  44. glGetIntegerv(GL_MAX_TEXTURE_SIZE, &glMaxTexDim); // 取得支持的纹理最大尺寸
  45. pPicture->get_Width(&lWidth); // 取得IPicture 宽度 (转换为Pixels格式)
  46. lWidthPixels = MulDiv(lWidth, GetDeviceCaps(hdcTemp, LOGPIXELSX), 2540);
  47. pPicture->get_Height(&lHeight); // 取得IPicture 高度 (转换为Pixels格式)
  48. lHeightPixels = MulDiv(lHeight, GetDeviceCaps(hdcTemp, LOGPIXELSY), 2540);
  49. // 调整图片到最好的效果
  50. if (lWidthPixels <= glMaxTexDim) // 图片宽度是否超过显卡最大支持尺寸
  51. lWidthPixels = 1 << (int)floor((log((double)lWidthPixels)/log(2.0f)) + 0.5f); 
  52. else // 否则,将图片宽度设为显卡最大支持尺寸
  53. lWidthPixels = glMaxTexDim;
  54.  
  55. if (lHeightPixels <= glMaxTexDim) // 图片高度是否超过显卡最大支持尺寸
  56. lHeightPixels = 1 << (int)floor((log((double)lHeightPixels)/log(2.0f)) + 0.5f);
  57. else // 否则,将图片高度设为显卡最大支持尺寸
  58. lHeightPixels = glMaxTexDim;
  59. // 建立一个临时位图
  60. BITMAPINFO bi = {0}; // 位图的类型
  61. DWORD *pBits = 0; // 指向位图Bits的指针
  62. bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); // 设置结构大小
  63. bi.bmiHeader.biBitCount = 32; // 32 位
  64. bi.bmiHeader.biWidth = lWidthPixels; // 宽度像素值
  65. bi.bmiHeader.biHeight = lHeightPixels; // 高度像素值
  66. bi.bmiHeader.biCompression = BI_RGB; // RGB 格式
  67. bi.bmiHeader.biPlanes = 1; // 一个位平面
  68. // 建立一个位图这样我们可以指定颜色和深度 并访问每位的值
  69. hbmpTemp = CreateDIBSection(hdcTemp, &bi, DIB_RGB_COLORS, (void**)&pBits, 0, 0);
  70. if(!hbmpTemp) // 建立失败?
  71. {
  72. DeleteDC(hdcTemp); // 删除设备描述表
  73. pPicture->Release(); // 释放IPicture
  74. // 图片载入失败出错信息
  75. MessageBox (HWND_DESKTOP, "图片导入失败!n(TextureLoad Failed!)", "Error", MB_OK | MB_ICONEXCLAMATION);
  76. return FALSE; // 返回 FALSE
  77. }
  78. SelectObject(hdcTemp, hbmpTemp); // 选择临时DC句柄和临时位图对象
  79. // 在位图上绘制IPicture
  80. pPicture->Render(hdcTemp, 0, 0, lWidthPixels, lHeightPixels, 0, lHeight, lWidth, -lHeight, 0);
  81. // 将BGR转换为RGB 将ALPHA值设为255
  82. for(long i = 0; i < lWidthPixels * lHeightPixels; i++) // 循环遍历所有的像素
  83. {
  84. BYTE* pPixel = (BYTE*)(&pBits[i]); // 获取当前像素
  85. BYTE  temp = pPixel[0]; // 临时存储第一个颜色像素(蓝色)
  86. pPixel[0] = pPixel[2]; // 将红色值存到第一位
  87. pPixel[2] = temp; // 将蓝色值存到第三位
  88. pPixel[3] = 255; // ALPHA值设为255
  89. }
  90. glGenTextures(1, &texid); // 创建纹理
  91. // 使用来自位图数据生成 的典型纹理
  92. glBindTexture(GL_TEXTURE_2D, texid); // 绑定纹理
  93. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // 线形滤波
  94. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);   // 线形滤波
  95. // 生成纹理
  96. glTexImage2D(GL_TEXTURE_2D, 0, 3, lWidthPixels, lHeightPixels, 0, GL_RGBA, GL_UNSIGNED_BYTE, pBits);
  97. DeleteObject(hbmpTemp); // 删除对象
  98. DeleteDC(hdcTemp); // 删除设备描述表
  99. pPicture->Release(); // 释放 IPicture
  100. return TRUE; // 返回 TRUE
  101. }
  102. BOOL BuildTexture(char *filename, TextureTga *texture) // 载入一个.TGA 文件到内存
  103. {    
  104. GLubyte TGAheader[12] = {0,0,2,0,0,0,0,0,0,0,0,0}; // 没有压缩的TGA Header
  105. GLubyte TGAcompare[12]; // 用来比较 TGA Header
  106. GLubyte header[6]; // Header里,头六个有用字节
  107. GLuint bytesPerPixel; // 保存TGA文件里每个像素用到的字节数
  108. GLuint imageSize; // 用来保存随机产生的图像的大小
  109. GLuint temp; // 临时变量
  110. GLuint type = GL_RGBA; // 将默认的GL模式设置为RBGA (32 BPP)
  111. FILE *file = fopen(filename, "rb"); // 打开 TGA 文件
  112. if (file == NULL) // 文件是否已存在?
  113. {
  114. // 图片载入失败出错信息
  115. MessageBox (HWND_DESKTOP, "图片导入失败!n(TextureLoad Failed!)", "Error", MB_OK | MB_ICONEXCLAMATION);
  116. return FALSE; // 返回FALSE
  117. }
  118. if (fread(TGAcompare,1,sizeof(TGAcompare),file) != sizeof(TGAcompare)// 是否有十二个字节可读?
  119. || memcmp(TGAheader,TGAcompare,sizeof(TGAheader)) != 0 // header和我们想要的是否相符?
  120. || fread(header,1,sizeof(header),file) != sizeof(header)) // 如果是读下六个字节
  121. {
  122. fclose(file); // 如果失败,关闭文件
  123. // 图片载入失败出错信息
  124. MessageBox (HWND_DESKTOP, "图片导入失败!n(TextureLoad Failed!)", "Error", MB_OK | MB_ICONEXCLAMATION);
  125. return FALSE; // 返回FALSE
  126. }
  127. texture->width  = header[1] * 256 + header[0]; // 确定的TGA 宽度 (高字节*256+低字节)
  128. texture->height = header[3] * 256 + header[2]; // 确定的TGA 高度 (高字节*256+低字节)
  129.     
  130.   if (texture->width <= 0 // 宽度是否小于等于0
  131. || texture->height <= 0 // 高度是否小于等于0
  132. ||(header[4] != 24 && header[4] != 32)) // TGA 是24位或32位?
  133. {
  134. fclose(file); // 任何一个不成立, 则关闭文件
  135. // 图片载入失败出错信息
  136. MessageBox (HWND_DESKTOP, "图片导入失败!n(TextureLoad Failed!)", "Error", MB_OK | MB_ICONEXCLAMATION);
  137. return FALSE; // 返回FALSE
  138. }
  139. texture->bpp = header[4]; // 获取TGA每个像素的位(24 or 32)
  140. bytesPerPixel = texture->bpp / 8; // 除以8以取得 每个像素的字节
  141. imageSize = texture->width*texture->height*bytesPerPixel; // 计算TAG数据所需要的内存
  142. texture->imageData = (GLubyte *)malloc(imageSize); // 开辟一个内存空间用来存储TGA数据
  143. if (texture->imageData == NULL  // 用来存储的内存是否存在?
  144. || fread(texture->imageData, 1, imageSize, file) != imageSize) // 图像大小是否和内存空间大小相符?
  145. {
  146. if (texture->imageData != NULL) // 图像数据是否载入
  147. {
  148. free(texture->imageData); // 如果是 释放图像数据
  149. }
  150. fclose(file); // 关闭文件
  151. MessageBox (HWND_DESKTOP, "图片导入失败!n(TextureLoad Failed!)", "Error", MB_OK | MB_ICONEXCLAMATION);
  152. return FALSE; // 返回FALSE
  153. }
  154. for (GLuint i=0; i<int(imageSize); i+=bytesPerPixel) // 循环遍历图像数据
  155. { // 交换第一和第三字节(红 和 蓝)
  156. temp=texture->imageData[i]; // 将图像数据‘i’的值存在临时变量中
  157. texture->imageData[i] = texture->imageData[i + 2]; // 将第三个字节的值存到第一个字节里
  158. texture->imageData[i + 2] = temp; // 将临时变量的值存入第三字节(第一字节的值)
  159. }
  160. fclose (file); // 关闭文件
  161. //创建一种纹理
  162. glGenTextures(1, &texture->texID); // 产生OpenGL纹理ID
  163. glBindTexture(GL_TEXTURE_2D, texture->texID); // 绑定纹理
  164. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // 线性滤波
  165. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // 线性滤波
  166. if (texture->bpp == 24) // TGA图片是不是 24 位的
  167. {
  168. type = GL_RGB; // 如果是将'type'设置为 GL_RGB
  169. }
  170. glTexImage2D(GL_TEXTURE_2D, 0, type, texture->width, texture->height, 0, type, GL_UNSIGNED_BYTE, texture->imageData);
  171. return TRUE; // 纹理创建成功,返回正确
  172. }