当前位置 : 主页 > 手机开发 > 其它 >

基于Cocos2d-x学习OpenGL ES 2.0之多纹理

来源:互联网 收集:自由互联 发布时间:2021-06-13
没想到原文出了那么多错别字,实在对不起观众了。介绍opengl es 2.0的不多。相信介绍基于Cocos2d-x学习OpenGL ES 2.0之多纹理的,我是独此一家吧。~~ 子龙山人出了一个系列:基于Cocos2d-x学

没想到原文出了那么多错别字,实在对不起观众了。介绍opengl es 2.0的不多。相信介绍基于Cocos2d-x学习OpenGL ES 2.0之多纹理的,我是独此一家吧。~~

子龙山人出了一个系列:基于Cocos2d-x学习OpenGL ES 2.0。弄c++来搞cocos2dx的可以看看。

教程是参考iphone的教程来写的,坑点也有不少,最主要的坑点还是在版本。所以还是弄个cocos2dx 3.2比较好。前两天辉辉说cocos2dx 3.2也很操蛋,.h里声明的返回值在源码实现的时候返回类型竟然变了。不得不吐槽一下~

 

子龙山人的教程只能教你照葫芦画瓢,什么原理的东西是压根就没涉及,有的还因为cocos2dx的封装过度会产生一些误导。

cocos2dx对opengl es封装的有点让人恶心,如果想学习opengl es是不建议在cocos2dx下进行学习的。

废话少说吧,开始正文。

根据子龙山人的教程,弄出了立方体纹理贴图,但是假如想在同一个面上贴多个纹理呢?该怎么实现?

本文提到两个方法,第一就是获取两个纹理,分别画图贴纹理,意思就是装顶点,装索引,绑定纹理,画图一。装顶点,装纹理,画图二。此时用到的都是GL_TEXTURE0,在frag文件中,只需要一个采样器就ok。

第二中方法就是用两个sampler,装顶点,装索引,绑定纹理一,绑定纹理二,画图。就OK了。

说起来比较简单,真要自己动手做,对于一个新手来说,过程还是有点小郁闷的。

下面就上源码了,对于步骤和方法的含义,此处不作介绍。相信强大的google和百度可以发挥巨大的作用。

第一种是立方体六个面贴上纹理,其中一个面再次贴上第二个纹理。

所用到的shader文件:

 1 attribute vec4 a_position; // 1
 2 attribute vec4 a_color; // 2
 3 attribute vec2 TextureCoord;
 4 
 5 varying vec4 DestinationColor; // 3
 6 varying vec2 v_texCoord;
 7 
 8 
 9 void main(void) { // 4
10     DestinationColor = a_color; // 5
11     v_texCoord = TextureCoord;
12     gl_Position = CC_MVPMatrix * a_position; // 6
13 }
1 varying  vec4 DestinationColor; // 1
2 varying vec2 v_texCoord;
3 
4 void main(void) { // 2
5 
6     gl_FragColor = DestinationColor * texture2D(CC_Texture0, v_texCoord) ; // 3
7 }

所用到的两张图

 

      

头文件:

#ifndef _CubeTexture_H__
#define _CubeTexture_H__

#include "cocos2d.h"

using namespace cocos2d;

class CubeTexture : public cocos2d::Layer
{
public:
    // there's no 'id' in cpp, so we recommend returning the class instance pointer
    static cocos2d::Scene* createScene();

    // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
    virtual bool init();  

    virtual void draw(Renderer *renderer, const Mat4 &transform, uint32_t transformUpdated) override;
    //we call our actual opengl commands here
    void onDraw();

    // implement the "static create()" method manually
    CREATE_FUNC(CubeTexture);

private:
    Mat4 _modelViewMV;
    CustomCommand _customCommand;

    GLProgram *mShaderProgram;
    GLint _colorLocation;
    GLint _positionLocation;
    GLint _textureLocation;

    GLuint _textureUniform;

    GLuint _textureID;
    GLuint _textureID2;

    GLuint vertexBuffer;
    GLuint indexBuffer;
    
    GLuint _vertexBuffer2;
    GLuint _indexBuffer2;

};

#endif // __HELLOWORLD_SCENE_H__
  1 #include "CubeTexture.h"
  2 using namespace GL;
  3 
  4 cocos2d::Scene* CubeTexture::createScene()
  5 {
  6     auto scene = Scene::create();
  7     auto layer = CubeTexture::create();
  8     scene->addChild(layer);
  9     return scene;
 10 }
 11 
 12 bool CubeTexture::init()
 13 {
 14     if ( Layer::init() )
 15     {
 16         mShaderProgram = new GLProgram;
 17         mShaderProgram->initWithFilenames("myshader.vert","myshader.frag");
 18         mShaderProgram->link();
 19         mShaderProgram->updateUniforms();
 20 
 21         _textureID = Director::getInstance()->getTextureCache()->addImage( "HelloWorld.png" )->getName();
 22         _textureID2 = Director::getInstance()->getTextureCache()->addImage("item_powerup_fish.png")->getName();
 23         glGenBuffers( 1, &vertexBuffer );
 24         glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer );
 25 
 26         glGenBuffers( 1, &indexBuffer );
 27         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer );
 28 
 29         return true;
 30     }
 31     return false;
 32 }
 33 
 34 void CubeTexture::draw( Renderer *renderer, const Mat4 &transform, uint32_t transformUpdated )
 35 {
 36     Layer::draw(renderer, transform, transformUpdated);
 37  
 38     _customCommand.init(_globalZOrder);
 39     _customCommand.func = CC_CALLBACK_0(CubeTexture::onDraw,this);
 40     renderer->addCommand(&_customCommand);
 41 }
 42 
 43 void CubeTexture::onDraw()
 44 {
 45     Director::getInstance()->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
 46     Director::getInstance()->loadIdentityMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
 47     Director::getInstance()->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
 48     Director::getInstance()->loadIdentityMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
 49 
 50     Mat4 modelViewMatrix;
 51     Mat4::createLookAt(Vec3(0,0,5), Vec3(0,0,0), Vec3(0,-1,0), &modelViewMatrix);
 52     modelViewMatrix.translate(0, 0,0 );
 53 
 54     static float rotation = 20;
 55     modelViewMatrix.rotate(Vec3(0,1,0),CC_DEGREES_TO_RADIANS(rotation));
 56 
 57     Mat4 projectionMatrix;
 58     Mat4::createPerspective(60, 480/320, 1.0, 42, &projectionMatrix);
 59     Director::getInstance()->multiplyMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, projectionMatrix);
 60     Director::getInstance()->multiplyMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, modelViewMatrix);
 61 
 62     typedef struct {
 63         float Position[3];
 64         float Color[4];
 65         float TexCoord[2];
 66     } Vertex;
 67 #define TEX_COORD_MAX   1
 68 
 69     Vertex Vertices[] = {
 70         // Front
 71         {{1, -1, 0}, {1, 0, 0, 1}, {TEX_COORD_MAX, 0}},
 72         {{1, 1, 0}, {0, 1, 0, 1}, {TEX_COORD_MAX, TEX_COORD_MAX}},
 73         {{-1, 1, 0}, {0, 0, 1, 1}, {0, TEX_COORD_MAX}},
 74         {{-1, -1, 0}, {0, 0, 0, 1}, {0, 0}},
 75         // Back
 76         {{1, 1, -2}, {1, 0, 0, 1}, {TEX_COORD_MAX, 0}},
 77         {{-1, -1, -2}, {0, 1, 0, 1}, {TEX_COORD_MAX, TEX_COORD_MAX}},
 78         {{1, -1, -2}, {0, 0, 1, 1}, {0, TEX_COORD_MAX}},
 79         {{-1, 1, -2}, {0, 0, 0, 1}, {0, 0}},
 80         // Left
 81         {{-1, -1, 0}, {1, 0, 0, 1}, {TEX_COORD_MAX, 0}},
 82         {{-1, 1, 0}, {0, 1, 0, 1}, {TEX_COORD_MAX, TEX_COORD_MAX}},
 83         {{-1, 1, -2}, {0, 0, 1, 1}, {0, TEX_COORD_MAX}},
 84         {{-1, -1, -2}, {0, 0, 0, 1}, {0, 0}},
 85         // Right
 86         {{1, -1, -2}, {1, 0, 0, 1}, {TEX_COORD_MAX, 0}},
 87         {{1, 1, -2}, {0, 1, 0, 1}, {TEX_COORD_MAX, TEX_COORD_MAX}},
 88         {{1, 1, 0}, {0, 0, 1, 1}, {0, TEX_COORD_MAX}},
 89         {{1, -1, 0}, {0, 0, 0, 1}, {0, 0}},
 90         // Top
 91         {{1, 1, 0}, {1, 0, 0, 1}, {TEX_COORD_MAX, 0}},
 92         {{1, 1, -2}, {0, 1, 0, 1}, {TEX_COORD_MAX, TEX_COORD_MAX}},
 93         {{-1, 1, -2}, {0, 0, 1, 1}, {0, TEX_COORD_MAX}},
 94         {{-1, 1, 0}, {0, 0, 0, 1}, {0, 0}},
 95         // Bottom
 96         {{1, -1, -2}, {1, 0, 0, 1}, {TEX_COORD_MAX, 0}},
 97         {{1, -1, 0}, {0, 1, 0, 1}, {TEX_COORD_MAX, TEX_COORD_MAX}},
 98         {{-1, -1, 0}, {0, 0, 1, 1}, {0, TEX_COORD_MAX}}, 
 99         {{-1, -1, -2}, {0, 0, 0, 1}, {0, 0}}
100     };
101     int vertexCount = sizeof(Vertices) / sizeof(Vertices[0]);
102 
103     GLubyte Indices[] = {
104         // Front
105         0, 1, 2,
106         2, 3, 0,
107         // Back
108         4, 5, 6,
109         4, 5, 7,
110         // Left
111         8, 9, 10,
112         10, 11, 8,
113         // Right
114         12, 13, 14,
115         14, 15, 12,
116         // Top
117         16, 17, 18,
118         18, 19, 16,
119         // Bottom
120         20, 21, 22,
121         22, 23, 20
122     };
123 
124     // 1) Add to top of file
125     const Vertex Vertices2[] = {
126         {{0.5, -0.5, 0.01}, {1, 1, 1, 1}, {1, 1}},
127         {{0.5, 0.5, 0.01}, {1, 1, 1, 1}, {1, 0}},
128         {{-0.5, 0.5, 0.01}, {1, 1, 1, 1}, {0, 0}},
129         {{-0.5, -0.5, 0.01}, {1, 1, 1, 1}, {0, 1}},
130     };
131 
132     const GLubyte Indices2[] = {
133         1, 0, 2, 3
134     };
135 
136     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
137     glBufferData(GL_ARRAY_BUFFER,sizeof(Vertices),Vertices, GL_STATIC_DRAW);
138 
139     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
140     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices),Indices,GL_STATIC_DRAW);
141 
142 
143     _positionLocation = glGetAttribLocation(mShaderProgram->getProgram(), "a_position");
144     _colorLocation = glGetAttribLocation(mShaderProgram->getProgram(), "a_color");
145 
146     _textureLocation = glGetAttribLocation(mShaderProgram->getProgram(), "TextureCoord");
147     _textureUniform = glGetUniformLocation(mShaderProgram->getProgram(), "CC_Texture0");
148 
149     mShaderProgram->use();
150     mShaderProgram->setUniformsForBuiltins();
151 
152     glEnableVertexAttribArray(_positionLocation);
153     glEnableVertexAttribArray(_colorLocation);
154     glEnableVertexAttribArray(_textureLocation);
155 
156     glVertexAttribPointer(_positionLocation, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, Position));
157 
158     glVertexAttribPointer(_colorLocation, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex),(GLvoid*)offsetof(Vertex, Color));
159 
160     glVertexAttribPointer(_textureLocation, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
161         (GLvoid*)offsetof(Vertex, TexCoord));
162     //
163     ////set sampler
164      GL::bindTexture2DN(0, _textureID);
165     //glActiveTexture( GL_TEXTURE0 );
166     //glBindTexture(GL_TEXTURE_2D, _textureID);
167     glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
168     glEnable(GL_BLEND);
169     glEnable(GL_DEPTH_TEST);
170     glDrawElements(GL_TRIANGLES,  36, GL_UNSIGNED_BYTE, 0);
171     glUniform1i(_textureUniform, 0); // unnecc in practice
172 
173     glGenBuffers(1, &_vertexBuffer2);
174     glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer2);
175     glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices2), Vertices2, GL_STATIC_DRAW);
176 
177     glGenBuffers(1, &_indexBuffer2);
178     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer2);
179     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices2), Indices2, GL_STATIC_DRAW);
180 
181     glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer2);
182     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer2);
183 
184     GL::bindTexture2DN(0, _textureID2);
185     glUniform1i(_textureUniform, 0); // unnecc in practice
186 
187     glVertexAttribPointer(_positionLocation, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
188     glVertexAttribPointer(_colorLocation, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) (sizeof(float) * 3));
189     glVertexAttribPointer(_textureLocation, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) (sizeof(float) * 7));
190 
191     glDrawElements(GL_TRIANGLE_STRIP, sizeof(Indices2)/sizeof(Indices2[0]), GL_UNSIGNED_BYTE, 0);
192 
193     CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1,vertexCount);
194 
195     CHECK_GL_ERROR_DEBUG();
196     glDisable(GL_DEPTH_TEST);
197 
198     Director::getInstance()->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
199     Director::getInstance()->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
200 }

运行结果:

   

 

方法二,所需要的shader文件:

1 attribute vec4 a_position; 
2 attribute vec2 a_texCoord;
3 
4 varying vec2 v_texCoord; 
5 
6 void main(void) {
7     gl_Position = CC_MVPMatrix * a_position; 
8     v_texCoord = a_texCoord;
9 }
 1 precision mediump float;
 2 varying vec2 v_texCoord;
 3 //uniform sampler2D s_lightMap;
 4 //uniform sampler2D s_baseMap;
 5 
 6 
 7 void main(void) {
 8     vec4 baseColor;
 9     vec4 lightColor;
10     //baseColor = texture2D( s_baseMap, v_texCoord);
11     //lightColor = texture2D( s_lightMap, v_texCoord );
12     baseColor = texture2D( CC_Texture0, v_texCoord);
13     lightColor = texture2D( CC_Texture1, v_texCoord );    
14     gl_FragColor = baseColor * ( lightColor + 0.25 ); 
15 }

所需要的图

  

头文件

  MultiTexture.h

源文件

  1 #include "MultiTexture.h"
  2 
  3 cocos2d::Scene* MultiTexture::createScene()
  4 {
  5     auto scene = Scene::create();
  6     auto layer = MultiTexture::create();
  7     scene->addChild(layer);
  8     return scene;
  9 }
 10 
 11 bool MultiTexture::init()
 12 {
 13     if ( Layer::init() )
 14     {
 15         mShaderProgram = new GLProgram;
 16         mShaderProgram->initWithFilenames("multiTexture.vert","multiTexture.frag");
 17         mShaderProgram->link();
 18         mShaderProgram->updateUniforms();
 19 
 20         _baseMapTexId = Director::getInstance()->getTextureCache()->addImage( "HelloWorld.png" )->getName();
 21         _lightMapTexId = Director::getInstance()->getTextureCache()->addImage("crate.jpg")->getName();
 22         glGenVertexArrays(1, &VAO);
 23         glBindVertexArray(VAO);
 24 
 25         glGenBuffers( 1, &vertexBuffer );
 26         glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer );
 27 
 28         glGenBuffers( 1, &indexBuffer );
 29         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer );
 30 
 31         return true;
 32     }
 33     return false;
 34 }
 35 
 36 void MultiTexture::draw( Renderer *renderer, const Mat4 &transform, uint32_t transformUpdated )
 37 {
 38     Layer::draw(renderer, transform, transformUpdated);
 39 
 40     _customCommand.init(_globalZOrder);
 41     _customCommand.func = CC_CALLBACK_0(MultiTexture::onDraw,this);
 42     renderer->addCommand(&_customCommand);
 43 }
 44 
 45 void MultiTexture::onDraw()
 46 {
 47     Director::getInstance()->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
 48     Director::getInstance()->loadIdentityMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
 49     Director::getInstance()->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
 50     Director::getInstance()->loadIdentityMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
 51 
 52     typedef struct {
 53         float Position[3];
 54         float TexCoord[2];
 55     } Vertex;
 56 #define TEX_COORD_MAX   1
 57 
 58     Vertex Vertices[] = {
 59 
 60         {{-0.5, 0.5, 0}, {0, 0}},
 61         {{-0.5, -0.5, 0}, {0, TEX_COORD_MAX}},
 62         {{0.5, -0.5, 0}, { TEX_COORD_MAX,TEX_COORD_MAX}},
 63         {{0.5, 0.5, 0}, {TEX_COORD_MAX, 0}},
 64 
 65     };
 66     int vertexCount = sizeof(Vertices) / sizeof(Vertices[0]);
 67 
 68     GLubyte Indices[] = {
 69         0, 1, 2,
 70         2, 3, 0,
 71     };
 72 
 73     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
 74     glBufferData(GL_ARRAY_BUFFER,sizeof(Vertices),Vertices, GL_STATIC_DRAW);
 75 
 76     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
 77     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices),Indices,GL_STATIC_DRAW);
 78 
 79     _positionLoc = glGetAttribLocation(mShaderProgram->getProgram(), "a_position");
 80     _texCoordLoc = glGetAttribLocation(mShaderProgram->getProgram(), "a_texCoord");
 81     //_baseMapLoc = glGetUniformLocation(mShaderProgram->getProgram(), "s_baseMap");
 82     //_lightMapLoc = glGetUniformLocation(mShaderProgram->getProgram(), "s_lightMap");
 83     _baseMapLoc = glGetUniformLocation(mShaderProgram->getProgram(), "CC_Texture0");
 84     _lightMapLoc = glGetUniformLocation(mShaderProgram->getProgram(), "CC_Texture1");
 85 
 86     glEnableVertexAttribArray(_positionLoc);
 87     glEnableVertexAttribArray(_texCoordLoc);
 88 
 89     glVertexAttribPointer(_positionLoc, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, Position));
 90     glVertexAttribPointer(_texCoordLoc, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
 91         (GLvoid*)offsetof(Vertex, TexCoord));
 92 
 93     mShaderProgram->use();
 94     mShaderProgram->setUniformsForBuiltins();
 95     
 96     glEnable(GL_DEPTH_TEST);
 97     glBindVertexArray(VAO);
 98 
 99     GL::bindTexture2DN(0, _lightMapTexId);
100     glUniform1i(_lightMapLoc, 0 ); // unnecc in practice
101 
102     GL::bindTexture2DN(1, _baseMapTexId);
103     glUniform1i(_baseMapLoc, 1); // unnecc in practice
104 
105     glDrawElements(GL_TRIANGLES,6, GL_UNSIGNED_BYTE, 0 );
106 
107     glBindVertexArray(0);
108     CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1,6);
109 
110     CHECK_GL_ERROR_DEBUG();
111     glDisable(GL_DEPTH_TEST);
112 
113     Director::getInstance()->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
114     Director::getInstance()->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
115 }

运行效果:

 

  

第二种方法中,

cpp内的:

//_baseMapLoc = glGetUniformLocation(mShaderProgram->getProgram(), "s_baseMap");

//_lightMapLoc = glGetUniformLocation(mShaderProgram->getProgram(), "s_lightMap");
_baseMapLoc = glGetUniformLocation(mShaderProgram->getProgram(), "CC_Texture0");
_lightMapLoc = glGetUniformLocation(mShaderProgram->getProgram(), "CC_Texture1");

和shader内的

//baseColor = texture2D( s_baseMap, v_texCoord);
//lightColor = texture2D( s_lightMap, v_texCoord );
baseColor = texture2D( CC_Texture0, v_texCoord);
lightColor = texture2D( CC_Texture1, v_texCoord );

 

将注释解开,把下面两行注掉。同样可以。这说明了,cocos2dx在进行编译shader的时候内置了多个uniform值。大家可以看一下,其中就包括CC_Texture0系列。

其实用起来不算方便了,而不注意的人,可能会声明和内置变量相同的名字,此时,咳咳咳咳咳~ shader编译的时候就会出错了。不知道为啥cocos2dx要多次一举。

还有一点:

 

////set sampler
GL::bindTexture2DN(0, _textureID);
//glActiveTexture( GL_TEXTURE0 );
//glBindTexture(GL_TEXTURE_2D, _textureID);

我使用了GL::bindTexture2DN 方法,而并没有使用opengl es原装的 glActiveTexture 和glBindTexture这两个方法。其实GL::bindTexture2DN 内部就调用了后面的两个方法,那为何不直接用后面的两个方法呢?

原因是,直接用opengl es的方法,会出错!!!尼玛 这才是坑点。跟踪后发现,cocos2dx给GL相关的东西添加了一个StateCache的东西,当activeTexture时,需要更改cache内的东西。直接调用glActiveTexture的方法,就略去了往cache内塞东西的步骤,这样就出错了。

猜测是cocos2dx进行渲染的时候,调用了cache内的什么东西。尼玛,你还能封装的再恶心一点么?

所以说,不喜欢cocos2dx这种处理问题的方法的,可以完全抛开cocos2dx了。

(原文:https://www.cnblogs.com/slysky/p/3981210.html)

网友评论