Cocos2dx-OpenGL ES2.0教程:纹理贴图(6)
来源:互联网 发布:网络接口教程 编辑:程序博客网 时间:2024/06/04 20:02
在上一篇文章中,我们介绍了如何绘制一个立方体,里面涉及的知识点有VBO(Vertex Buffer Object)、IBO(Index Buffer Object)和MVP(Modile-View-Projection)变换。
本文将在教程4的基础之上,添加纹理贴图支持。最后,本文会把纹理贴图扩展至3D立方体上面。
基本方法
当我们把一张图片加载到内存里面之后,它是不能直接被GPU绘制出来的,纹理贴图过程如下:
首先,我们为之前的顶点添加纹理坐标属性并传到vertex shader里面去,然后把内存里面的纹理传给GPU,最后,在fragment shader里面通过采样器,就可以根据vertex shader传递过来的纹理坐标把纹理上面的颜色值用插值的方式映射到每一个像素上去。
接下来,让我们看看具体怎么做。
准备纹理坐标(纹理坐标也叫UV坐标)
首先,我们需要修改我们的顶点属性结构体,添加一个纹理坐标属性(TexCoord):
12345
typedef struct { float Position[2]; float Color[4]; float TexCoord[2];} Vertex;
接下来,需要修改顶点数组的值,主要就是添加UV坐标:
1234567
Vertex data[] = { { {-1,-1},{0,1,0,1},{0,1}}, { {1,-1},{0,1,0,1},{1,1}}, { {-1,1},{0,1,0,1},{0,0}}, { {1,1},{0,1,0,1},{1,0}} };
注意,我们的纹理坐标的(0,0)点在图片的左上角,这个与OpenGL里面的左下角是(0,0)有所区别。所以为了让我们的图片显示正常,我们在指定左下角顶点(-1,-1)的时候,它对应的纹理坐标应该是(0,1)。其它的坐标点以此类推。
GLuint TexCoordLocation = glGetAttribLocation(glProgram->getProgram(), "a_coord");
glEnableVertexAttribArray(TexCoordLocation);
glVertexAttribPointer(TexCoordLocation,
2,
GL_FLOAT,
GL_FALSE,
sizeof(Vertex),
(GLvoid*)offsetof(Vertex,TexCoord));
生成纹理
首先,我们在头文件里面定义一个纹理的句柄:
1
GLuint textureId;
然后是生成纹理:
1textureId = Director::getInstance()->getTextureCache()->addImage("HelloWorld.png")->getName();
接下来,我需要处理Shader了。
修改Shader
首先,修改vertex shader,添加纹理坐标属性:
1234567891011121314
attribute vec2 a_position;attribute vec4 a_color;attribute vec2 a_coord;varying vec4 v_fragmentColor;varying vec2 v_coord;void main(){ gl_Position = CC_MVPMatrix * vec4(a_position.xy,0,1); v_fragmentColor = a_color; v_coord = a_coord;}
因为纹理坐标最终要传递到fragment shader里面去,所以需要定义一个varing vec2 v_coord
变量。
接下来是fragment shader的代码:
12345678910
varying vec4 v_fragmentColor;varying vec2 v_coord;uniform vec4 u_color;void main(){ gl_FragColor = v_fragmentColor * texture2D(CC_Texture0,v_coord);}
这边也定义了一个同样的varing变量,同时我们看到有一个texture2D函数,它可以通过CC_Texture0这个采样器和纹理坐标(v_coord)计算出对应的颜色值。
修改draw call
在调用draw call之前,我们需要绑定纹理。我们只需要在glDrawElements方法之前调用下列方法就可以了:
1
GL::bindTexture2D(textureId);
运行结果
接下来,我们需要把立方体的六个面都添加这张纹理。
让立方体不再裸奔
这个过程大部分代码都是一样的,惟一的区别就是顶点数组的修改,我们需要为每一个面的顶点都指定UV坐标:
123456789101112131415161718192021222324252627282930313233
#define TEX_COORD_MAX 1 Vertex Vertices[] = { // Front { {1, -1, 0}, {1, 0, 0, 1}, {TEX_COORD_MAX, 0}}, { {1, 1, 0}, {0, 1, 0, 1}, {TEX_COORD_MAX, TEX_COORD_MAX}}, { {-1, 1, 0}, {0, 0, 1, 1}, {0, TEX_COORD_MAX}}, { {-1, -1, 0}, {0, 0, 0, 1}, {0, 0}}, // Back { {1, 1, -2}, {1, 0, 0, 1}, {TEX_COORD_MAX, 0}}, { {-1, -1, -2}, {0, 1, 0, 1}, {TEX_COORD_MAX, TEX_COORD_MAX}}, { {1, -1, -2}, {0, 0, 1, 1}, {0, TEX_COORD_MAX}}, { {-1, 1, -2}, {0, 0, 0, 1}, {0, 0}}, // Left { {-1, -1, 0}, {1, 0, 0, 1}, {TEX_COORD_MAX, 0}}, { {-1, 1, 0}, {0, 1, 0, 1}, {TEX_COORD_MAX, TEX_COORD_MAX}}, { {-1, 1, -2}, {0, 0, 1, 1}, {0, TEX_COORD_MAX}}, { {-1, -1, -2}, {0, 0, 0, 1}, {0, 0}}, // Right { {1, -1, -2}, {1, 0, 0, 1}, {TEX_COORD_MAX, 0}}, { {1, 1, -2}, {0, 1, 0, 1}, {TEX_COORD_MAX, TEX_COORD_MAX}}, { {1, 1, 0}, {0, 0, 1, 1}, {0, TEX_COORD_MAX}}, { {1, -1, 0}, {0, 0, 0, 1}, {0, 0}}, // Top { {1, 1, 0}, {1, 0, 0, 1}, {TEX_COORD_MAX, 0}}, { {1, 1, -2}, {0, 1, 0, 1}, {TEX_COORD_MAX, TEX_COORD_MAX}}, { {-1, 1, -2}, {0, 0, 1, 1}, {0, TEX_COORD_MAX}}, { {-1, 1, 0}, {0, 0, 0, 1}, {0, 0}}, // Bottom { {1, -1, -2}, {1, 0, 0, 1}, {TEX_COORD_MAX, 0}}, { {1, -1, 0}, {0, 1, 0, 1}, {TEX_COORD_MAX, TEX_COORD_MAX}}, { {-1, -1, 0}, {0, 0, 1, 1}, {0, TEX_COORD_MAX}}, { {-1, -1, -2}, {0, 0, 0, 1}, {0, 0}} };
下面是立方体的六个面贴上纹理之后的效果:
结语
3D旋转立方体(带纹理贴图)源代码下载 master分支
单个图片的纹理贴图源码下载
Reference
http://open.gl/textures
纹理立方体
- Cocos2dx-OpenGL ES2.0教程:纹理贴图(6)
- OpenGL ES2.0教程:纹理贴图(6)
- opengl es2.0 入门教程推荐(正方体,案例解说,Shader介绍,纹理贴图)
- Cocos2dx-OpenGL ES2.0教程:编写自己的shader(2)
- Cocos2dx-OpenGL ES2.0教程:初识MVP(3)
- Cocos2dx-OpenGL ES2.0教程:使用VBO索引(4)
- NeHe的opengl教程delphi版(6)----纹理映射(贴图)
- NeHe的opengl教程delphi版(6)----纹理映射(贴图)
- OpenGL ES2.0 生成Mipmap纹理
- openGL es2.0 创建纹理球
- openGL es2.0 创建纹理灯光球
- openGL es2.0 创建纹理灯光球
- Cocos2dx-OpenGL ES2.0教程:你的第一个立方体(5)
- cocos2dx 多重纹理贴图
- OpenGL纹理贴图 JPEG纹理
- OpenGL纹理贴图 JPEG纹理
- OpenGL ES纹理贴图
- OpenGL ES纹理贴图
- cocos2d-x v3.9 关于RotateTo和SkewTo的疑问
- nginx 快速搭建
- Shell脚本:求命令行上所有的整数和
- Android Studio adb无法响应的解决方法
- 前端开发者都应知道的 jQuery 小技巧
- Cocos2dx-OpenGL ES2.0教程:纹理贴图(6)
- 工程问题:fatal error C1071
- 基金基础知识
- 参考文献中的字母含义
- UITableView样式的自定义
- 10+年程序员总结的20+条经验教训
- 对js中的引用类型的理解(6)——基本包装类型(Booelean、Number、String)
- 实验others
- IE浏览器无法加载外部CSS文件