OpenGL 八 - 纹理案例

Posted zhangying-domy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenGL 八 - 纹理案例相关的知识,希望对你有一定的参考价值。

案例一、隧道

效果

技术图片

Demo链接

1)四面:

技术图片

技术图片

技术图片

技术图片

2)主要代码:

  1 // 初始化设置
  2 void SetupRC() {
  3     
  4     glClearColor(0.0f, 0.0f, 0.0f, 1.0f);// 黑色
  5     shaderManager.InitializeStockShaders();
  6     
  7     
  8     GLbyte *pBytes;
  9     GLint iWidth, iHeight, iComponents;
 10     GLenum eFormat;
 11     
 12     // 生成纹理标记
 13     /* 分配纹理对象 glGenTextures
 14     参数1:纹理对象的数量
 15     参数2:纹理对象标识数组
 16     */
 17     glGenTextures(TEXTURE_COUNT, textures);
 18     
 19     
 20     // 设置纹理
 21     for (GLint i = 0; i < TEXTURE_COUNT; i++) {
 22         
 23         // 绑定纹理对象
 24         /*绑定纹理对象 glBindTexture
 25         参数1:纹理模式,GL_TEXTURE_1D,GL_TEXTURE_2D,GL_TEXTURE_3D
 26         参数2:需要绑定的纹理对象id
 27         */
 28         glBindTexture(GL_TEXTURE_2D, textures[i]);
 29 
 30         
 31         // 加载 读取 tga 文件数据
 32         /* 加载 tga 文件
 33         参数1:纹理文件名称
 34         参数2:文件宽度变量地址
 35         参数3:文件高度变量地址
 36         参数4:文件组件变量地址
 37         参数5:文件格式变量地址
 38          
 39         返回值:pBytes,指向图像数据的指针
 40         */
 41         pBytes = gltReadTGABits(textureFiles[i], &iWidth, &iHeight, &iComponents, &eFormat);
 42 
 43         
 44         // 设置纹理参数
 45         // 设置放大缩小 过滤方式 GL_TEXTURE_MAG_FILTER(放大过滤器,GL_NEAREST(最邻近过滤);GL_TEXTURE_MIN_FILTER(缩小过滤器,GL_NEAREST(最邻近过滤)
 46         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 47         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 48 
 49         // 设置环绕方式
 50         // GL_TEXTURE_WRAP_S(2D:s、t轴环绕),GL_CLAMP_TO_EDGE --> 环绕模式强制对范围之外的纹理坐标沿着合法的纹理单元的最后一行或一列进行采样
 51         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 52         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 53 
 54         
 55         // 载入纹理
 56         /* 载入纹理 glTexImage2D
 57         参数1:纹理维度,GL_TEXTURE_2D
 58         参数2:mip贴图层次
 59         参数3:纹理单元存储的颜色成分(从读取像素图中获得)
 60         参数4:加载纹理宽度
 61         参数5:加载纹理的高度
 62         参数6:为纹理贴图指定一个边界宽度 0
 63         参数7、8:像素数据的数据类型, GL_UNSIGNED_BYTE无符号整型
 64         参数9:指向纹理图像数据的指针
 65         */
 66         glTexImage2D(GL_TEXTURE_2D, 0, iComponents, iWidth, iHeight, 0, eFormat, GL_UNSIGNED_BYTE, pBytes);
 67         //        glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
 68 
 69         
 70         //  生成纹理对象 glGenerateMipmap
 71         /* 为纹理对象生成一组完整的 mipmap
 72         参数1:纹理维度,GL_TEXTURE_1D,GL_TEXTURE_2D,GL_TEXTURE_2D
 73         */
 74         glGenerateMipmap(GL_TEXTURE_2D);
 75 
 76         // 释放原始纹理数据,不再需要纹理原始数据了
 77         free(pBytes);
 78     }
 79     
 80     
 81     // 设置隧道的上下左右4个面
 82     GLfloat z;// 深度,隧道的深度
 83     
 84     // 地板 -- 图 ‘地板’
 85     /*
 86     GLTools库中的容器类,GBatch -->  void GLBatch::Begin(GLenum primitive,GLuint nVerts,GLuint nTextureUnits = 0);
 87     参数1:图元枚举值
 88     参数2:顶点数
 89     参数3:纹理数 --> 1组或者2组纹理坐标
 90     */
 91     floorBatch.Begin(GL_TRIANGLE_STRIP, 28, 1);
 92     for(z = 60.0f; z >= 0.0f; z -=10.0f) {
 93         
 94         // 纹理坐标与顶点的对应
 95         floorBatch.MultiTexCoord2f(0, 0.0f, 0.0f);// 纹理坐标
 96         floorBatch.Vertex3f(-10.0f, -10.0f, z);// 顶点
 97         
 98         floorBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
 99         floorBatch.Vertex3f(10.0f, -10.0f, z);
100         
101         floorBatch.MultiTexCoord2f(0, 0.0f, 1.0f);
102         floorBatch.Vertex3f(-10.0f, -10.0f, z - 10.0f);
103         
104         floorBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
105         floorBatch.Vertex3f(10.0f, -10.0f, z - 10.0f);
106     }
107     floorBatch.End();
108     
109     // 天花板 -- 图 ‘天花板’
110     ceilingBatch.Begin(GL_TRIANGLE_STRIP, 28, 1);
111     for(z = 60.0f; z >= 0.0f; z -=10.0f) {
112         
113         ceilingBatch.MultiTexCoord2f(0, 0.0f, 1.0f);
114         ceilingBatch.Vertex3f(-10.0f, 10.0f, z - 10.0f);
115         
116         ceilingBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
117         ceilingBatch.Vertex3f(10.0f, 10.0f, z - 10.0f);
118         
119         ceilingBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
120         ceilingBatch.Vertex3f(-10.0f, 10.0f, z);
121         
122         ceilingBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
123         ceilingBatch.Vertex3f(10.0f, 10.0f, z);
124     }
125     ceilingBatch.End();
126     
127     // 左侧墙面 -- 图 ‘左墙’
128     leftWallBatch.Begin(GL_TRIANGLE_STRIP, 28, 1);
129     for(z = 60.0f; z >= 0.0f; z -=10.0f) {
130         
131         leftWallBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
132         leftWallBatch.Vertex3f(-10.0f, -10.0f, z);
133         
134         leftWallBatch.MultiTexCoord2f(0, 0.0f, 1.0f);
135         leftWallBatch.Vertex3f(-10.0f, 10.0f, z);
136         
137         leftWallBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
138         leftWallBatch.Vertex3f(-10.0f, -10.0f, z - 10.0f);
139         
140         leftWallBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
141         leftWallBatch.Vertex3f(-10.0f, 10.0f, z - 10.0f);
142     }
143     leftWallBatch.End();
144     
145     // 右侧墙面 -- 图 ‘右墙‘
146     rightWallBatch.Begin(GL_TRIANGLE_STRIP, 28, 1);
147     for(z = 60.0f; z >= 0.0f; z -=10.0f) {
148         
149         rightWallBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
150         rightWallBatch.Vertex3f(10.0f, -10.0f, z);
151         
152         rightWallBatch.MultiTexCoord2f(0, 0.0f, 1.0f);
153         rightWallBatch.Vertex3f(10.0f, 10.0f, z);
154         
155         rightWallBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
156         rightWallBatch.Vertex3f(10.0f, -10.0f, z - 10.0f);
157         
158         rightWallBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
159         rightWallBatch.Vertex3f(10.0f, 10.0f, z - 10.0f);
160     }
161     rightWallBatch.End();
162 }
163 
164 // 渲染
165 void RenderScene(void) {
166     
167     glClear(GL_COLOR_BUFFER_BIT);
168 
169     // 压栈
170     modelViewMatix.PushMatrix();
171     // z轴上平移
172     modelViewMatix.Translate(0.0f, 0.0f, viewZ);
173     
174     // 纹理替换矩阵着色器
175     /*
176      参数1:GLT_SHADER_TEXTURE_REPLACE(着色器标签)
177      参数2:模型视图投影矩阵
178      参数3:纹理层
179      */
180     shaderManager.UseStockShader(GLT_SHADER_TEXTURE_REPLACE, transformPipeline.GetModelViewProjectionMatrix(),0);
181     
182     // 绑定纹理
183     /*
184      --> 为何又绑定一次???
185      --> 为防止纹理 ID 绑定错误,状态机机制,在共同开发过程中,可能出现绑定的纹理出现变化
186      */
187     // 地板
188     glBindTexture(GL_TEXTURE_2D, textures[TEXTURE_FLOOR]);
189     floorBatch.Draw();
190     // 天花板
191     glBindTexture(GL_TEXTURE_2D, textures[TEXTURE_CEILING]);
192     ceilingBatch.Draw();
193     // 左右墙
194     glBindTexture(GL_TEXTURE_2D, textures[TEXTURE_BRICK]);
195     leftWallBatch.Draw();
196     rightWallBatch.Draw();
197     
198     // 出栈
199     modelViewMatix.PopMatrix();
200     
201     // 交换缓冲区
202     glutSwapBuffers();
203 }
204 
205 // 视口  窗口大小改变时接受新的宽度和高度,其中0,0代表窗口中视口的左下角坐标,w,h代表像素
206 void ChangeSize(int w,int h) {
207     // 防止h变为0
208     if(h == 0)
209         h = 1;
210     
211     // 设置视口窗口尺寸
212     glViewport(0, 0, w, h);
213     
214     // setPerspective 函数的参数是一个从顶点方向看去的视场角度(用角度值表示)
215     // 设置透视模式,初始化其透视矩阵
216     viewFrustum.SetPerspective(80.0f, GLfloat(w)/GLfloat(h), 1.0f, 120.0f);
217     
218     //4.把 透视矩阵 加载到 透视矩阵对阵中
219     projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
220     
221     //5.初始化渲染管线
222     transformPipeline.SetMatrixStacks(modelViewMatix, projectionMatrix);
223 }

案例二、球体转动 添加纹理

效果

技术图片

Demo链接

主要代码

  1 // 绘制球体视图
  2 void drawSpheres (GLfloat yRot) {
  3     
  4     // 设置点光源位置
  5     static GLfloat vLightPos[] = {0.0f, 3.0f, 0.0f, 1.0f};
  6     // 漫反射颜色 白色
  7     static GLfloat vWhite[] = { 1.0f, 1.0f, 1.0f, 1.0f };
  8     
  9     
 10     // 绘制 小球们
 11     // 绑定纹理
 12     glBindTexture(GL_TEXTURE_2D, textures[2]);// 小球上贴的纹理
 13     for (int i = 0; i < SPHERE_NUM; i++) {
 14         
 15         modelViewMatix.PushMatrix();
 16         modelViewMatix.MultMatrix(spheres[i]);// 小球位置
 17         modelViewMatix.Rotate(yRot, 0, 1, 0);
 18         // GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF:纹理点光源着色器;vLightPos:光源位置;vBigSphereColor:绘制颜色
 19         shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,
 20                                      modelViewMatix.GetMatrix(),
 21                                      transformPipeline.GetProjectionMatrix(),
 22                                      vLightPos,
 23                                      vWhite,
 24                                      0);
 25         sphereBatch.Draw();
 26         
 27         modelViewMatix.PopMatrix();
 28     }
 29     
 30     
 31     // 绘制大球
 32     modelViewMatix.Translate(0, 0.2f, -2.5f);// y轴上靠近镜面一点 Z轴距离再远一些
 33     //
 34     modelViewMatix.PushMatrix();
 35     // 大球沿Y轴  旋转弧度:yRot 自传
 36     modelViewMatix.Rotate(yRot, 0, 1, 0);
 37     // 绑定纹理
 38     glBindTexture(GL_TEXTURE_2D, textures[1]);
 39     shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,
 40                                  modelViewMatix.GetMatrix(),
 41                                  transformPipeline.GetProjectionMatrix(),
 42                                  vLightPos,
 43                                  vWhite,
 44                                  0);
 45     bigSphereBatch.Draw();
 46     modelViewMatix.PopMatrix();
 47     
 48     
 49     // 绘制沿大球转的小球
 50     modelViewMatix.PushMatrix();
 51     modelViewMatix.Rotate(yRot * -2, 0, 1, 0);
 52     modelViewMatix.Translate(0.8f, 0.0f, 0.0f);// 小球在X方向上偏移一定位置 不然会看不见小球
 53     glBindTexture(GL_TEXTURE_2D, textures[2]);
 54     shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,
 55                                  modelViewMatix.GetMatrix(),
 56                                  transformPipeline.GetProjectionMatrix(),
 57                                  vLightPos,
 58                                  vWhite,
 59                                  0);
 60     sphereBatch.Draw();
 61     modelViewMatix.PopMatrix();
 62     
 63 }
 64 
 65 // 设置纹理
 66 bool LoadTGATexture(const char *textureName, GLenum minFilter, GLenum magFilter, GLenum wrapModel) {
 67     
 68     GLbyte *pBits;
 69     int nWidth, nHeight, nComponents;
 70     GLenum eFormat;
 71     
 72     // 读取纹理
 73     pBits = gltReadTGABits(textureName, &nWidth, &nHeight, &nComponents, &eFormat);
 74     if (!pBits) {
 75         return false;
 76     }
 77     
 78     //  设置过滤方式
 79     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
 80     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
 81     
 82     // 设置环绕方式
 83     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapModel);
 84     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapModel);
 85     
 86     // 载入纹理
 87     glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB, nWidth, nHeight, 0, eFormat, GL_UNSIGNED_BYTE, pBits);
 88     
 89     //  使用完毕释放pbit
 90     free(pBits);
 91     
 92     
 93     // 只有minFilter 等于以下四种模式,才可以生成Mip贴图
 94     // GL_NEAREST_MIPMAP_NEAREST具有非常好的性能,并且闪烁现象非常弱
 95     // GL_LINEAR_MIPMAP_NEAREST常常用于对游戏进行加速,它使用了高质量的线性过滤器
 96     // GL_LINEAR_MIPMAP_LINEAR 和GL_NEAREST_MIPMAP_LINEAR 过滤器在Mip层之间执行了一些额外的插值,以消除他们之间的过滤痕迹。
 97     // GL_LINEAR_MIPMAP_LINEAR 三线性Mip贴图。纹理过滤的黄金准则,具有最高的精度。
 98     if (minFilter == GL_LINEAR_MIPMAP_LINEAR ||
 99         minFilter == GL_LINEAR_MIPMAP_NEAREST ||
100         minFilter == GL_NEAREST_MIPMAP_LINEAR ||
101         minFilter == GL_NEAREST_MIPMAP_NEAREST) {
102         
103         // 加载mip 纹理生成所有的mip 层
104         // 参数:GL_TEXTURE_1D、GL_TEXTURE_2D、GL_TEXTURE_3D
105         glGenerateMipmap(GL_TEXTURE_2D);
106     }
107     
108     return true;
109 }
110 
111 // 初始化 设置
112 void SetupRC() {
113     
114     // 设置清屏颜色到颜色缓存区
115     glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
116     
117     // 初始化着色器管理器
118     shaderManager.InitializeStockShaders();
119     
120     // 开启深度测试 背面剔除
121     glEnable(GL_DEPTH_TEST);
122     glEnable(GL_CULL_FACE);
123 
124     // 设置大球
125     gltMakeSphere(bigSphereBatch, 0.4f, 40, 80);
126     
127     // 设置小球
128     gltMakeSphere(sphereBatch, 0.1f, 26, 13);
129     
130     // 地板 纹理 --> 4个顶点对应纹理图的4个坐标
131     GLfloat texSize = 10.0f;
132     floorTriangleBatch.Begin(GL_TRIANGLE_FAN, 4,1);
133     floorTriangleBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
134     floorTriangleBatch.Vertex3f(-20.f, -0.41f, 20.0f);
135     
136     floorTriangleBatch.MultiTexCoord2f(0, texSize, 0.0f);
137     floorTriangleBatch.Vertex3f(20.0f, -0.41f, 20.f);
138     
139     floorTriangleBatch.MultiTexCoord2f(0, texSize, texSize);
140     floorTriangleBatch.Vertex3f(20.0f, -0.41f, -20.0f);
141     
142     floorTriangleBatch.MultiTexCoord2f(0, 0.0f, texSize);
143     floorTriangleBatch.Vertex3f(-20.0f, -0.41f, -20.0f);
144     floorTriangleBatch.End();
145     
146     
147     // 小球们的位置 随机小球顶点坐标数据
148     for (int i = 0; i < SPHERE_NUM; i++) {
149         
150         // y轴不变,X,Z产生随机值
151         GLfloat x = ((GLfloat)((rand() % 400) - 200 ) * 0.1f);
152         GLfloat z = ((GLfloat)((rand() % 400) - 200 ) * 0.1f);
153         
154         // 在y方向,将球体设置为0.0的位置,这使得它们看起来是飘浮在眼睛的高度
155         // 对spheres数组中的每一个顶点,设置顶点数据
156         spheres[i].SetOrigin(x, 0.0f, z);
157     }
158     
159     
160     // 设置纹理
161     // 生成纹理标记
162     glGenTextures(3, textures);
163     
164     // 绑定纹理 设置纹理参数
165     glBindTexture(GL_TEXTURE_2D, textures[0]);
166     LoadTGATexture("marble.tga", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_REPEAT);
167     
168     // GL_CLAMP_TO_EDGE 纹理坐标约束在0~1,超出部分边缘重复(边缘拉伸效果)
169     glBindTexture(GL_TEXTURE_2D, textures[1]);
170     LoadTGATexture("marslike.tga", GL_LINEAR_MIPMAP_LINEAR,
171                    GL_LINEAR, GL_CLAMP_TO_EDGE);
172     
173     glBindTexture(GL_TEXTURE_2D, textures[2]);
174     LoadTGATexture("moonlike.tga", GL_LINEAR_MIPMAP_LINEAR,
175                    GL_LINEAR, GL_CLAMP_TO_EDGE);
176 }
177 
178 
179 
180 // 渲染
181 void RenderScene(void) {
182     
183     // 清除窗口 颜色、深度缓冲区
184     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
185     
186     // 地板颜色 --> 镜面透明效果 alpha设置一定透明度
187     static GLfloat vFloorColor[] = {1.0, 1.0, 0.0, 0.7f};
188     
189     // 定时器时间 动画 --> 大球自传
190     static CStopWatch rotTimer;
191     float yRot = rotTimer.GetElapsedSeconds() * 60.0f;
192     
193     
194     // 压栈 --> copy 一份栈顶矩阵 --> 单元矩阵
195     modelViewMatix.PushMatrix();
196     
197     
198     // 观察者矩阵压栈
199     /*
200      观察者的移动要影响到所有绘制物体,所以要 先压栈
201      */
202     M3DMatrix44f cameraM;
203     cameraFrame.GetCameraMatrix(cameraM);
204     modelViewMatix.MultMatrix(cameraM);
205     
206     
207     // 镜面内部分
208     // 压栈 --> 原因:镜面部分绘制后要继续绘制地板上面的视图
209     modelViewMatix.PushMatrix();
210     // 镜面内的小球门
211     // 绘制镜面内部分(镜面内的小球门)
212     
213     // 沿Y轴翻转
214     modelViewMatix.Scale(1.0f, -1.0f, 1.0f);
215     // 视图距离地板面设定一定间隔 -- 避免粘在一起 就不像镜面了
216     modelViewMatix.Translate(0, 0.8, 0);
217     
218     // 此时绘制镜面部分为顺时针旋转,将顺时针旋转设为正面 --> 正背面 观察者只能看到正面
219     glFrontFace(GL_CW);
220     // 绘制视图
221     drawSpheres(yRot);
222     
223     // 恢复逆时针转为正面
224     glFrontFace(GL_CCW);
225     //
226     modelViewMatix.PopMatrix();
227     
228     
229     // 绘制镜面
230     // 开启混合
231     glEnable(GL_BLEND);
232     // 指定混合方程式
233     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
234     //  绑定地面(镜面)纹理
235     glBindTexture(GL_TEXTURE_2D, textures[0]);
236     /* 纹理调整着色器 --> 将一个基本色乘以一个取自纹理的单元nTextureUnit的纹理
237      参数1:GLT_SHADER_TEXTURE_MODULATE
238      参数2:模型视图投影矩阵
239      参数3:颜色
240      参数4:纹理单元(第0层的纹理单元)
241      */
242     shaderManager.UseStockShader(GLT_SHADER_TEXTURE_MODULATE,
243                                  transformPipeline.GetModelViewProjectionMatrix(),
244                                  vFloorColor,
245                                  0);
246     floorTriangleBatch.Draw();
247     // 取消混合
248     glDisable(GL_BLEND);
249     
250     
251     // 绘制镜面外的球
252     drawSpheres(yRot);
253     
254     modelViewMatix.PopMatrix();
255     
256     
257     //
258     glutSwapBuffers();
259     
260     //
261     glutPostRedisplay();
262 }

 

以上是关于OpenGL 八 - 纹理案例的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL、GLSL 片段着色器无法读取 Sampler2D 纹理

纹理中的 OpenGL 片段着色器

openGL 纹理05

初识OpenGL (-)纹理(Texture)

初识OpenGL (-)纹理(Texture)

初识OpenGL (-)纹理(Texture)