继续上一篇文章的例子:OpenGL的几何变换2之内观察立方体
上一篇是通过绘图方式得到的立方体,没有贴图,这次加上纹理贴图。
通过纹理贴图有两种方案:
1、图片分割化,即是把一张完整的VR图片(VR图片就是720度全景图片)人工的分隔成前后左右上下六张图片(静态),然后分别加载这六张图片;
2、数据分割化,即是保留一张完整的VR图片,加载图片以后,对图片数据进行上下左右前后进行数据切割,或者应该说进行图片切割(动态)。
这一篇文章主要用到的技术点是纹理映射,具体不再累述,可以参考OpenGL的glTexCoord2f纹理坐标配置
本篇文章的案例主要是采用第一种(图片分割化),先附上代码:
1 #include <stdio.h> 2 #include <windows.h> 3 #include <gl/glut.h> //引用相关包 4 #include <gl/glaux.h> 5 6 GLfloat xangle = 0.0; //X 旋转量 7 GLfloat yangle = 0.0; //Y 旋转量 8 GLfloat zangle = 0.0; //Z 旋转量 9 GLuint textureArr[6]; //存储6个纹理 10 11 AUX_RGBImageRec *loadBMP(char *Filename) //载入位图图象 12 { 13 14 15 FILE *File = NULL; //文件句柄 16 if (!Filename) //确保文件名已提供 17 { 18 return NULL; //如果没提供,返回 NULL 19 } 20 21 File = fopen(Filename,"r"); //尝试打开文件 22 if (File) //文件存在么? 23 { 24 fclose(File); //关闭句柄 25 return auxDIBImageLoadA(Filename); //载入位图并返回指针 26 } 27 return NULL; //如果载入失败,返回 NULL 28 } 29 30 //载入位图(调用上面的代码)并转换成纹理 31 int loadGLTexture(void) 32 { 33 int Status = FALSE; //状态指示器 34 char *imgArr[6] = { 35 "pano/pano_f.bmp", //前面 36 "pano/pano_b.bmp", //后面 37 "pano/pano_u.bmp", //顶面 38 "pano/pano_d.bmp", //底面 39 "pano/pano_r.bmp", //右面 40 "pano/pano_l.bmp" //左面 41 }; 42 AUX_RGBImageRec *TextureImage[6]; //创建纹理的存储空间 43 44 memset(textureArr, 0x0, sizeof(textureArr)); 45 memset(TextureImage,0,sizeof(TextureImage)); //将指针设为NULL 46 47 for (int i = 0; i < 6; i++) { 48 Status = FALSE; 49 //载入位图,检查有无错误,如果位图没找到则退出 50 if (TextureImage[i] = loadBMP(imgArr[i])) 51 { 52 Status = TRUE; //将 Status 设为 TRUE 53 glGenTextures(1, &textureArr[i]); //创建纹理 54 55 //使用来自位图数据生成 的典型纹理 56 glBindTexture(GL_TEXTURE_2D, textureArr[i]); 57 //生成纹理 58 glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[i]->sizeX, TextureImage[i]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[i]->data); 59 60 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); //线形滤波 61 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); //线形滤波 62 } 63 64 if (TextureImage[i]) //纹理是否存在 65 { 66 if (TextureImage[i]->data) //纹理图像是否存在 67 { 68 free(TextureImage[i]->data); //释放纹理图像占用的内存 69 } 70 free(TextureImage[i]); //释放图像结构 71 } 72 if (Status == FALSE) { 73 break; 74 } 75 } 76 return Status; //返回 Status 77 } 78 79 void drawCube(void) //从这里开始进行所有的绘制 80 { 81 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除屏幕和深度缓存 82 glMatrixMode(GL_MODELVIEW); 83 glLoadIdentity(); //重置当前的模型观察矩阵 84 85 glPushMatrix(); 86 { 87 gluLookAt(0, 0, -5, 0, 0, 0, 0, 1, 0); 88 glTranslatef(0.0f, 0.0f, -5.0f); //移入屏幕 5 个单位 89 glRotatef(xangle, 1.0f, 0.0f, 0.0f); //绕X轴旋转 90 glRotatef(-yangle, 0.0f, 1.0f, 0.0f); //绕Y轴旋转 91 glRotatef(zangle, 0.0f, 0.0f, 1.0f); //绕Z轴旋转 92 #if (0) //显示反面 93 glBindTexture(GL_TEXTURE_2D, textureArr[0]); //选择纹理 94 glBegin(GL_QUADS); { 95 //前面:逆时针 96 glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); //纹理和四边形的左下 97 glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); //纹理和四边形的右下 98 glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); //纹理和四边形的右上 99 glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); //纹理和四边形的左上 100 }glEnd(); 101 102 glBindTexture(GL_TEXTURE_2D, textureArr[1]); //选择纹理 103 glBegin(GL_QUADS); { 104 //后面:逆时针 105 glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); //纹理和四边形的左下 106 glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); //纹理和四边形的右下 107 glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); //纹理和四边形的右上 108 glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); //纹理和四边形的左上 109 }glEnd(); 110 111 glBindTexture(GL_TEXTURE_2D, textureArr[2]); //选择纹理 112 glBegin(GL_QUADS); { 113 //顶面:逆时针 114 glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f); //纹理和四边形的左下 115 glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 1.0f); //纹理和四边形的右下 116 glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); //纹理和四边形的右上 117 glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); //纹理和四边形的左上 118 }glEnd(); 119 120 glBindTexture(GL_TEXTURE_2D, textureArr[3]); //选择纹理 121 glBegin(GL_QUADS); { 122 //底面:逆时针 123 glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); //纹理和四边形的左下 124 glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); //纹理和四边形的右下 125 glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, -1.0f, 1.0f); //纹理和四边形的右上 126 glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, -1.0f, 1.0f); //纹理和四边形的左上 127 }glEnd(); 128 129 glBindTexture(GL_TEXTURE_2D, textureArr[4]); //选择纹理 130 glBegin(GL_QUADS); { 131 //右面:逆时针 132 glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); //纹理和四边形的左下 133 glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); //纹理和四边形的右下 134 glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); //纹理和四边形的右上 135 glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); //纹理和四边形的左上 136 }glEnd(); 137 138 glBindTexture(GL_TEXTURE_2D, textureArr[5]); //选择纹理 139 glBegin(GL_QUADS); { 140 //左面:逆时针 141 glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); //纹理和四边形的左下 142 glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); //纹理和四边形的右下 143 glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); //纹理和四边形的右上 144 glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); //纹理和四边形的左上 145 }glEnd(); 146 #else //显示正面 147 glBindTexture(GL_TEXTURE_2D, textureArr[0]); //选择纹理 148 glBegin(GL_QUADS); { 149 //前面:纹理顺时针,立方体逆时针 150 glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); //纹理和四边形的左下 151 glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); //纹理和四边形的左上 152 glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); //纹理和四边形的右上 153 glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); //纹理和四边形的右下 154 }glEnd(); 155 156 glBindTexture(GL_TEXTURE_2D, textureArr[1]); //选择纹理 157 glBegin(GL_QUADS); { 158 //后面:纹理顺时针,立方体逆时针 159 glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); //纹理和四边形的左下 160 glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); //纹理和四边形的左上 161 glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); //纹理和四边形的右上 162 glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); //纹理和四边形的右下 163 }glEnd(); 164 165 glBindTexture(GL_TEXTURE_2D, textureArr[2]); //选择纹理 166 glBegin(GL_QUADS); { 167 //顶面:纹理顺时针,立方体逆时针 168 glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 1.0f); //纹理和四边形的左下 169 glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); //纹理和四边形的左上 170 glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); //纹理和四边形的右上 171 glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f); //纹理和四边形的右下 172 }glEnd(); 173 174 glBindTexture(GL_TEXTURE_2D, textureArr[3]); //选择纹理 175 glBegin(GL_QUADS); { 176 //底面:纹理顺时针,立方体逆时针 177 glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); //纹理和四边形的左下 178 glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, 1.0f); //纹理和四边形的左上 179 glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, 1.0f); //纹理和四边形的右上 180 glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); //纹理和四边形的右下 181 }glEnd(); 182 183 glBindTexture(GL_TEXTURE_2D, textureArr[5]); //选择纹理 184 glBegin(GL_QUADS); { 185 //右面:纹理顺时针,立方体逆时针 186 glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); //纹理和四边形的左下 187 glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); //纹理和四边形的左上 188 glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); //纹理和四边形的右上 189 glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); //纹理和四边形的右下 190 }glEnd(); 191 192 glBindTexture(GL_TEXTURE_2D, textureArr[4]); //选择纹理 193 glBegin(GL_QUADS); { 194 //左面:纹理顺时针,立方体逆时针 195 196 glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); //纹理和四边形的左下 197 glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); //纹理和四边形的左上 198 glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); //纹理和四边形的右上 199 glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); //纹理和四边形的右下 200 }glEnd(); 201 #endif 202 }glPopMatrix(); 203 glFlush(); 204 } 205 206 //初始化 207 void init(void) 208 { 209 glClearColor (0.0, 0.0, 0.0, 0.0); //清理颜色,为黑色,(也可认为是背景颜色) 210 211 glCullFace(GL_FRONT); //前面裁剪(前面不可见) 212 glEnable(GL_CULL_FACE); //启用裁剪 213 glEnable(GL_TEXTURE_2D); 214 loadGLTexture(); //载入纹理贴图 215 } 216 217 void display(void) 218 { 219 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清楚颜色数据和深度数据(清屏) 220 glLoadIdentity(); //Reset The View 221 222 drawCube(); 223 224 glutSwapBuffers(); //交换缓冲区。显示图形 225 226 //xangle += 0.3f; 227 //yangle += 0.3f; 228 //zangle += 0.3f; 229 Sleep(10); 230 } 231 232 //当窗口大小改变时,会调用这个函数 233 void reshape(GLsizei w,GLsizei h) 234 { 235 //这里小说明一下:矩阵模式是不同的,他们各自有一个矩阵。投影相关 236 //只能用投影矩阵。(只是目前情况下哦,等我学多了可能就知道为什么了。) 237 238 glViewport(0,0,w,h); //设置视口 239 glMatrixMode(GL_PROJECTION); //设置矩阵模式为投影变换矩阵, 240 glLoadIdentity(); //变为单位矩阵 241 gluPerspective(90, (GLfloat)w / h, 0.1f, 100.0f); //设置投影矩阵 242 glMatrixMode(GL_MODELVIEW); //设置矩阵模式为视图矩阵(模型) 243 glLoadIdentity(); //变为单位矩阵 244 } 245 246 //键盘输入事件函数 247 void keyboard(unsigned char key,int x,int y) 248 { 249 switch(key) 250 { 251 case ‘x‘: //当按下键盘上d时,以沿X轴旋转为主 252 xangle += 1.0f; //设置旋转增量 253 glutPostRedisplay(); //重绘函数 254 break; 255 case ‘y‘: 256 yangle += 1.0f; 257 glutPostRedisplay(); 258 break; 259 case ‘z‘: 260 zangle += 1.0f; 261 glutPostRedisplay(); 262 break; 263 default: 264 break; 265 } 266 } 267 268 int main(int argc, char *argv[]) 269 { 270 printf("可通过xyz按键控制VR全景图绕哪个轴旋转\n"); 271 272 glutInit(&argc, argv); //固定格式 273 glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); 274 glutInitWindowSize(1024/2, 1024/2); //显示框的大小 275 glutInitWindowPosition(100,100); //确定显示框左上角的位置 276 glutCreateWindow("OpenGL纹理贴图"); 277 278 init(); //初始化资源,这里一定要在创建窗口以后,不然会无效。 279 glutDisplayFunc(display); 280 //glutIdleFunc(display); 281 glutReshapeFunc(reshape); //绘制图形时的回调 282 glutKeyboardFunc(keyboard); 283 glutMainLoop(); 284 return 0; 285 }
附上VR图片:
附上代码运行结果:
最后附上可执行的EXE链接: http://pan.baidu.com/s/1nvixGFZ 密码: 3cw2
时间: 2024-11-07 10:22:43