Cocos2dx-OpenGL ES2.0教程:纹理贴图(6)

转载 2015年11月18日 17:41:58

上一篇文章中,我们介绍了如何绘制一个立方体,里面涉及的知识点有VBO(Vertex Buffer Object)、IBO(Index Buffer Object)和MVP(Modile-View-Projection)变换。

本文将在教程4的基础之上,添加纹理贴图支持。最后,本文会把纹理贴图扩展至3D立方体上面。

基本方法

当我们把一张图片加载到内存里面之后,它是不能直接被GPU绘制出来的,纹理贴图过程如下:

首先,我们为之前的顶点添加纹理坐标属性并传到vertex shader里面去,然后把内存里面的纹理传给GPU,最后,在fragment shader里面通过采样器,就可以根据vertex shader传递过来的纹理坐标把纹理上面的颜色值用插值的方式映射到每一个像素上去。

接下来,让我们看看具体怎么做。

准备纹理坐标(纹理坐标也叫UV坐标)

首先,我们需要修改我们的顶点属性结构体,添加一个纹理坐标属性(TexCoord):

1
2
3
4
5
typedef struct {
    float Position[2];
    float Color[4];
    float TexCoord[2];
} Vertex;

接下来,需要修改顶点数组的值,主要就是添加UV坐标:

1
2
3
4
5
6
7
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;

然后是生成纹理:

1

textureIdDirector::getInstance()->getTextureCache()->addImage("HelloWorld.png")->getName();


接下来,我需要处理Shader了。

修改Shader

首先,修改vertex shader,添加纹理坐标属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14

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的代码:

1
2
3
4
5
6
7
8
9
10

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);

运行结果

texturingtexturing

接下来,我们需要把立方体的六个面都添加这张纹理。

让立方体不再裸奔

这个过程大部分代码都是一样的,惟一的区别就是顶点数组的修改,我们需要为每一个面的顶点都指定UV坐标:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#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}}
    };

下面是立方体的六个面贴上纹理之后的效果:

3dtexturing3dtexturing

结语

3D旋转立方体(带纹理贴图)源代码下载 master分支

单个图片的纹理贴图源码下载

Reference

Cocos2dx绘制贴图

Cocos2dx下 基本的OpenGL ES 绘图 分类: cocos2dx2013-07-01 00:36 4652人阅读 评论(3) 收藏 举报 [cpp] vie...
  • linuxheik
  • linuxheik
  • 2015年01月16日 10:49
  • 689

Cocos2dx-OpenGL ES2.0教程:初识MVP(3)

在上一篇文章中,我在介绍vertex shader的时候挖了一个坑:CC_MVPMatrix。它其实是一个uniform,每一个cocos2d-x预定义的shader都包含有这个uniform, ...
  • dingkun520wy
  • dingkun520wy
  • 2015年11月18日 14:15
  • 2611

Cocos2dx-OpenGL ES2.0教程:编写自己的shader(2)

在上篇文章中,我给大家介绍了如何在cocos2d-x里面绘制一个三角形,当时我们使用的是cocos2d-x引擎自带的shader和一些辅助函数。在本文中,我将演示一下如何编写自己的shader,同时,...
  • dingkun520wy
  • dingkun520wy
  • 2015年11月17日 22:27
  • 6388

Cocos2dx下 基本的OpenGL ES 绘图

void GLFirstLayer::draw() { // CCLayer::draw(); //顶点数据 static GLfloat vertex[] ...
  • ym19860303
  • ym19860303
  • 2013年07月01日 00:36
  • 7310

cocos-2dx OPENGL渲染(1)

ocos-2dx的opengl初始化,通过initGLContextAttrs 设置opengl像素格式, 在applicationDidFinishLaunching中create opengl窗口...
  • taotanty
  • taotanty
  • 2015年08月17日 21:59
  • 993

Cocos2dx-OpenGL ES 2.0教程:你的第一个三角形(1)

前言 在本系列教程中,我会以当下最流行的2D引擎Cocos2D-X为基础,介绍OpenGL ES 2.0的一些基本用法。本系列教程的宗旨是OpenGL扫盲,让大家在使用Cocos2D-X过程中,...
  • dingkun520wy
  • dingkun520wy
  • 2015年11月17日 21:13
  • 3200

Cocos2d-x3.2与OpenGL渲染总结(一)Cocos2d-x3.2的渲染流程

这是一篇比较详细介绍Cocos2d-x3.2渲染过程的文章。
  • cbbbc
  • cbbbc
  • 2014年09月21日 22:36
  • 12096

cocos2D-X源码分析之从cocos2D-X学习OpenGL(1)----cocos2D-X渲染结构

cocos2D-X 3.0渲染结构代码讲解,也是cocos2D-X源码讲解系列文章和从cocos2D-X学习OpenGL系列文章的开始...
  • bill_man
  • bill_man
  • 2014年06月29日 22:17
  • 12770

Cocos2dx-OpenGL ES2.0教程:你的第一个立方体(5)

在上篇文章中,我们介绍了VBO索引的使用,使用VBO索引可以有效地减少顶点个数,优化内存,提高程序效率。 本教程将带领大家一起走进3D–绘制一个立方体。其实画立方体本质上和画三角形没什么区别,所...
  • dingkun520wy
  • dingkun520wy
  • 2015年11月18日 16:30
  • 2046

cocos2dx opengl入门系列三-画一个四边形

运行环境: mac10.12.2 xcode Version 8.2.1 cocos2dx-x-3.13.1 代码: 新建cocos2dx项目,具体操作官网有教程。新建好后, 新建Test.cpp,代...
  • u013654125
  • u013654125
  • 2017年06月22日 14:26
  • 566
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Cocos2dx-OpenGL ES2.0教程:纹理贴图(6)
举报原因:
原因补充:

(最多只允许输入30个字)