用OpenGL进行立方体表面纹理贴图
一、目的
掌握OpenGL中纹理对象的创建、绑定与使用方法。
二、简单介绍
1,连接静态库
#pragma comment(lib, "glut32.lib") #pragma comment(lib, "glaux.lib")
2,载入位图图像到内存(这是固定用法)
AUX_RGBImageRec *LoadBMP(CHAR *Filename) {FILE *File = NULL; // 文件句柄if (!Filename) // 确保文件名已提供 {return NULL; // 如果没提供,返回 NULL }File = fopen(Filename, "r"); // 尝试打开文件if (File) // 判断文件存在与否 {fclose(File); // 关闭句柄return auxDIBImageLoadA(Filename); // 载入位图并返回指针 }return NULL; // 如果载入失败,返回 NULL }
3,载入位图并转换成纹理(固定用法)
int LoadGLTextures(GLuint *texture, char *bmp_file_name, int texture_id) {int Status = FALSE; // 状态指示器// 创建纹理的存储空间AUX_RGBImageRec *TextureImage[1];memset(TextureImage, 0, sizeof(void *) * 1); // 将指针设为 NULL// 载入位图,检查有无错误,如果位图没找到则退出if (TextureImage[0] = LoadBMP(bmp_file_name)){Status = TRUE; // 将 Status 设为 TRUE//生成(generate)纹理glGenTextures(texture_id, texture); //&texture[0]); //绑定2D纹理对象glBindTexture(GL_TEXTURE_2D, *texture); //texture[0]);//关联图像数据与纹理对象glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);//图形绘制时所使用的滤波器参数glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // 线形滤波glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // 线形滤波 }//释放图像的内存,因为已经生成纹理了,没用了if (TextureImage[0]) // 纹理是否存在 {if (TextureImage[0]->data) // 纹理图像是否存在 {free(TextureImage[0]->data); // 释放纹理图像占用的内存 }free(TextureImage[0]); // 释放图像结构 }elseprintf("纹理不存在");return Status; // 返回 Status }
4,开始绘制
void DrawCube(void) // 从这里开始进行所有的绘制 {glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清除屏幕和深度缓存 glLoadIdentity(); // 重置当前的模型观察矩阵 glBindTexture(GL_TEXTURE_2D, texture[0]); // 选择纹理 glBegin(GL_QUADS);// 前面glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // 纹理和四边形的左下glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f); // 纹理和四边形的右下glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, 1.0f); // 纹理和四边形的右上glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // 纹理和四边形的左上// 后面glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // 纹理和四边形的右下glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // 纹理和四边形的右上glTexCoord2f(0.0f, 1.0f); glVertex3f(1.0f, 1.0f, -1.0f); // 纹理和四边形的左上glTexCoord2f(0.0f, 0.0f); glVertex3f(1.0f, -1.0f, -1.0f); // 纹理和四边形的左下 glFlush(); //glutSwapBuffers(); }
根据坐标关系,依次类推出顶面、底面、左面、右面的绘制方式。
三、示例代码
Github地址
#include "stdafx.h" #include <GL/glut.h> //引用相关包 #include <windows.h> #include <GL/glaux.h> #include <stdio.h> #include <stdlib.h>//注意下面的编译指令——告诉编译器要连接的静态库 #pragma comment(lib, "glut32.lib") #pragma comment(lib, "glaux.lib")GLfloat xrot = 0; // X 旋转量 GLfloat yrot = 0; // Y 旋转量 GLfloat zrot = 0; // Z 旋转量 GLuint texture[1]; // 存储一个纹理---数组//载入位图图象到内存——固定用法 AUX_RGBImageRec *LoadBMP(CHAR *Filename) {FILE *File = NULL; // 文件句柄if (!Filename) // 确保文件名已提供 {return NULL; // 如果没提供,返回 NULL }File = fopen(Filename, "r"); // 尝试打开文件if (File) // 判断文件存在与否 {fclose(File); // 关闭句柄return auxDIBImageLoadA(Filename); // 载入位图并返回指针 }return NULL; // 如果载入失败,返回 NULL }//载入位图(调用上面的代码)并转换成纹理——固定用法 //参数:纹理指针、bmp文件名、用户指定的纹理编号 int LoadGLTextures(GLuint *texture, char *bmp_file_name, int texture_id) {int Status = FALSE; // 状态指示器// 创建纹理的存储空间AUX_RGBImageRec *TextureImage[1];memset(TextureImage, 0, sizeof(void *) * 1); // 将指针设为 NULL// 载入位图,检查有无错误,如果位图没找到则退出if (TextureImage[0] = LoadBMP(bmp_file_name)){Status = TRUE; // 将 Status 设为 TRUE//生成(generate)纹理glGenTextures(texture_id, texture); //&texture[0]); //绑定2D纹理对象glBindTexture(GL_TEXTURE_2D, *texture); //texture[0]);//关联图像数据与纹理对象glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);//图形绘制时所使用的滤波器参数glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // 线形滤波glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // 线形滤波 }//释放图像的内存,因为已经生成纹理了,没用了if (TextureImage[0]) // 纹理是否存在 {if (TextureImage[0]->data) // 纹理图像是否存在 {free(TextureImage[0]->data); // 释放纹理图像占用的内存 }free(TextureImage[0]); // 释放图像结构 }elseprintf("纹理不存在");return Status; // 返回 Status }void DrawCube(void) // 从这里开始进行所有的绘制 {glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清除屏幕和深度缓存 glLoadIdentity(); // 重置当前的模型观察矩阵 glTranslatef(0.0f, 0.0f, -5.0f); // 移入屏幕 5 个单位glRotatef(xrot, 1.0f, 0.0f, 0.0f); // 绕X轴旋转glRotatef(yrot, 0.0f, 1.0f, 0.0f); // 绕Y轴旋转glRotatef(zrot, 0.0f, 0.0f, 1.0f); // 绕Z轴旋转 glBindTexture(GL_TEXTURE_2D, texture[0]); // 选择纹理 glBegin(GL_QUADS);// 前面glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // 纹理和四边形的左下glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f); // 纹理和四边形的右下glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, 1.0f); // 纹理和四边形的右上glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // 纹理和四边形的左上// 后面glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // 纹理和四边形的右下glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // 纹理和四边形的右上glTexCoord2f(0.0f, 1.0f); glVertex3f(1.0f, 1.0f, -1.0f); // 纹理和四边形的左上glTexCoord2f(0.0f, 0.0f); glVertex3f(1.0f, -1.0f, -1.0f); // 纹理和四边形的左下// 顶面glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // 纹理和四边形的左上glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // 纹理和四边形的左下glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, 1.0f, 1.0f); // 纹理和四边形的右下glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, -1.0f); // 纹理和四边形的右上// 底面glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // 纹理和四边形的右上glTexCoord2f(0.0f, 1.0f); glVertex3f(1.0f, -1.0f, -1.0f); // 纹理和四边形的左上glTexCoord2f(0.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f); // 纹理和四边形的左下glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // 纹理和四边形的右下// 右面glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, -1.0f, -1.0f); // 纹理和四边形的右下glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, -1.0f); // 纹理和四边形的右上glTexCoord2f(0.0f, 1.0f); glVertex3f(1.0f, 1.0f, 1.0f); // 纹理和四边形的左上glTexCoord2f(0.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f); // 纹理和四边形的左下// 左面glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // 纹理和四边形的左下glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // 纹理和四边形的右下glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // 纹理和四边形的右上glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // 纹理和四边形的左上 glEnd();glFlush(); //glutSwapBuffers(); xrot += 0.3f; // X 轴旋转yrot += 0.2f; // Y 轴旋转zrot += 0.4f; // Z 轴旋转 }void display(void) {glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清楚颜色数据和深度数据(清屏)glLoadIdentity(); // 重置视图glTranslatef(0.0f, 0.0f, -5.0f);DrawCube();glutSwapBuffers(); //交换缓冲区。显示图形 }//初始化 void init(void) {glClearColor(1.0, 1.0, 1.0, 0.0); //清理颜色,为黑色,(也可认为是背景颜色)glCullFace(GL_BACK); //背面裁剪(背面不可见)glEnable(GL_CULL_FACE); //启用裁剪 glEnable(GL_TEXTURE_2D);LoadGLTextures(&texture[0], "mf.bmp", 1); //载入纹理贴图//LoadGLTextures(&texture[1], "mf1.bmp", 2); //载入纹理贴图 }//当窗口大小改变时,会调用这个函数 void reshape(GLsizei w, GLsizei h) {//这里小说明一下:矩阵模式是不同的,他们各自有一个矩阵。投影相关//只能用投影矩阵。(只是目前情况下哦,等我学多了可能就知道为什么了。)glViewport(0, 0, w, h); //设置视口glMatrixMode(GL_PROJECTION); //设置矩阵模式为投影变换矩阵,glLoadIdentity(); //变为单位矩阵gluPerspective(60, (GLfloat)w / h, 0, 1000); //设置投影矩阵 glMatrixMode(GL_MODELVIEW); //设置矩阵模式为视图矩阵(模型)glLoadIdentity(); //变为单位矩阵 }//键盘输入事件函数 void keyboard(unsigned char key, int x, int y) {switch (key){case 'x': //当按下键盘上d时,以沿X轴旋转为主xrot += 1.0f; //设置旋转增量glutPostRedisplay(); //重绘函数break;case 'y':yrot += 1.0f;glutPostRedisplay();break;case 'z':zrot += 1.0f;glutPostRedisplay();break;default:break;} }int main(int argc, char *argv[]) {glutInit(&argc, argv); //固定格式glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); //注意这里glutInitWindowSize(600, 600); //显示框的大小glutInitWindowPosition(100, 100); //确定显示框左上角的位置glutCreateWindow("OpenGL纹理贴图");init(); //初始化资源,这里一定要在创建窗口以后,不然会无效。LoadGLTextures(&texture[0], "mf.bmp", 1);glutDisplayFunc(display);glutReshapeFunc(reshape); //绘制图形时的回调 glutKeyboardFunc(keyboard);glutMainLoop();return 0; }
四、注意
1.贴图文件大小必须为:宽、高都必须为2的整数次幂,格式必须为BMP。
2.贴图需要放在相应文件夹下,在编译器中直接运行此程序可能会看不到贴图效果。
点开箭头所指的文件夹
放置需要贴纹理的位图文件
五、总结
这是我在学校做的图形学纹理贴图实验,放暑假了一直忙着准备考研,今天突然想起应该把以前做的实验整理一下,于是找到了这个实验。
纹理贴图是一个很有趣的实验,它就像一层嫁衣,为你所创建的目标对象披上一件外衣,让别人看着赏心悦目,当然我目前所学的只是对规则物体进行纹理贴图,以后还会遇到不规则的物体等。
用OpenGL进行立方体表面纹理贴图相关推荐
- 现代opengl 设计入门,坐标系统和立方体的纹理贴图
本文在 现代opengl 设计入门,纹理贴图 一文的基础上,引入opengl坐标系统,实现立方体的纹理贴图.介绍了opengl 的5个空间,3个变换矩阵.如果看这部分介绍比较繁琐,可以直接看看效果图, ...
- OpenGL基本概念入门——纹理贴图
1. 创建纹理图像 OpenGL要求纹理的高度和宽度都必须是2的n次方大小,只有满足这个条件,这个纹理图片才是有效的. 一旦获取了像素值,我们就可以将这些数据传给OpenGL,让OpenGL生 ...
- OpenGL ES之十——纹理贴图(展示一张图片)
概述 这是一个系列的Android平台下OpenGl ES介绍,从最基本的使用最终到VR图的展示的实现,属于基础篇.(后面针对VR视频会再有几篇文章,属于进阶篇) OpenGL ES之一--概念扫盲 ...
- OpenGL ES绘制3D纹理贴图
最近看了<疯狂android讲义>的图形相关的内容,结合自己的理解,整理了一下. 下图是做出来的3D纹理贴图效果,手指在屏幕滑动时,图片可以随之转动. 要实现一个纹理贴图,很简单,大致需要 ...
- OpenGL总结6-圆柱纹理贴图
圆柱纹理贴图我采用了OpenGL中的函数gluCylinder,这个函数会生成空心的圆柱,这个圆柱固定生成为底面位于xy面,z=0,顶面从z=0开始向z轴正方向,也就是说圆柱体是冲着我们生成的,如果想 ...
- 现代opengl 设计入门,纹理贴图
上节 现代opengl 设计入门,着色器 介绍了着色器语言GLSL, 可以绘制多彩的三角形.这节介绍更高级的着色,纹理贴图. 先做纹理贴图的基本介绍,然后介绍其中几个重要设置:纹理环绕方式,纹理过滤 ...
- android 使用OPENGL ES实现三角形纹理贴图效果-纹理映射基础
效果图:...... 编写Dad.java *在Dad构造器中创建和设置场景渲染器为主动渲染,并设置重写触屏时间回调方法以记录触控笔坐标,改变三角形坐标系的位置,使三角形能够在场景中转动 *为声明场景 ...
- 【OpenGL学习笔记④】——纹理贴图【SOIL2的配置 + 绘制木板 + 纹理环绕】
- OpenGL ES实现三棱锥纹理贴图
这是老师布置的课后作业,闲来无事分享出来,也加深一遍自己的印象~ 自己定义一个MyRenderer.java类: package com.example.shiyan3_2;import androi ...
- Android Studio OpenGL ES绘制三棱锥/四面体的多纹理贴图 每个面使用一张图片渲染
本文参考了王刚的<疯狂Android讲义(第3版)>P554-P559 要求:利用OpenGL ES绘制一个三棱锥,并对每个面进行纹理贴图,每个面使用不同的图片进行渲染. 环境:Andro ...
最新文章
- 不一样的命令行 – Windows PowerShell简介
- 什么是OKR?这就是OKR
- Python 实例方法、类方法、静态方法的区别与作用
- “相对论“ 2019-07-10
- AngularJS日期格式化
- A Scala Tutorial for Java programmers之(一)Scala入门:Scala例子,以及如何与Java交互
- 阿里分布式数据库服务实践
- Sql Server 2000 无法打开用户默认数据库。登录失败
- INFO: task java:27465 blocked for more than 120 seconds不一定是cache太大的问题
- centos最新版solr5.3.1安装和数据整理以及遇到的问题解答
- vba中find用法
- 用结构化思维策划一个会议
- vb调用python函数_vb.net / C# 调用 python
- struts2 拦截器
- Input鼠标键盘输入
- python求最小公倍数_Python 最小公倍数算法
- 建模是什么,建模定义,及学习方法
- 物理建模钢琴-Modartt Pianoteq Pro v6.7.0 WiN
- matlab图像处理二,图像缩放、旋转、修剪
- 【转载】租房被骗,选择忍让,成就黑中介的猖狂