这几天在看子龙山人的关于OpenGL的文章,先依葫芦画瓢,能看到些东西,才能慢慢深入了解,当入门文章不错,但是其中遇到的一些问题,折腾了一些时间,为了方便和我一样的小白们,在这篇文章中进行写补充。
OpenGL ES2.0教程:编写自己的shader(2)--子龙山人
文章中关于VBO和VAO部分的代码的写法,我进行了些修改,将重复使用的变量定义全局变量,并修改初始化数据位置,防止在onDraw方法中重复的Malloc,致使内存泄露,具体的修改在代码注释中会说明。
源码如下:
HelloWorldScene.h
1 #include "cocos2d.h" 2 3 USING_NS_CC; 4 5 class HelloWorld : public cocos2d::Layer 6 7 { 8 9 public: 10 11 static cocos2d::Scene* createScene(); 12 13 virtual bool init() override; 14 15 CREATE_FUNC(HelloWorld); 16 17 virtual void visit(Renderer *renderer, const Mat4& parentTransform, uint32_t parentFlags) override; 18 19 void onDraw(); 20 21 private: 22 23 CustomCommand _command; 24 25 float _position[16]; 26 27 float _color[12]; 28 29 GLProgram* glProgram; 30 31 GLuint vao;//定义VAO缓冲 32 33 GLuint positionVBO; 34 35 GLuint colorVBO; 36 37 GLuint positionLocation; 38 39 GLuint colorLocation; 40 41 };
HelloWorldScene.cpp
1 #include "HelloWorldScene.h" 2 3 Scene* HelloWorld::createScene() 4 { 5 auto scene = Scene::create(); 6 7 auto layer = HelloWorld::create(); 8 9 scene->addChild(layer); 10 11 return scene; 12 } 13 14 void HelloWorld::visit(Renderer *renderer, const Mat4 &transform,uint32_t parentFlags) 15 { 16 Layer::visit(renderer, transform, parentFlags); 17 _command.init(_globalZOrder); 18 _command.func = CC_CALLBACK_0(HelloWorld::onDraw, this); 19 Director::getInstance()->getRenderer()->addCommand(&_command); 20 } 21 22 void HelloWorld::onDraw() 23 { 24 //使用已经在init中初始化的glProgram 25 glProgram->use(); 26 glProgram->setUniformsForBuiltins(); 27 28 //获取VAO(OSX和ISO中默认开启,windows中默认不开启) 29 glBindVertexArray(vao); 30 31 //获取VBO 32 glBindBuffer(GL_ARRAY_BUFFER, positionVBO); 33 //填充坐标数据 34 glBufferData(GL_ARRAY_BUFFER, sizeof(_position), _position, GL_STATIC_DRAW); 35 positionLocation = glGetAttribLocation(glProgram->getProgram(), "a_position"); 36 glEnableVertexAttribArray(positionLocation); 37 glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0); 38 39 //获取VBO 40 glBindBuffer(GL_ARRAY_BUFFER, colorVBO); 41 //填充颜色数据 42 glBufferData(GL_ARRAY_BUFFER, sizeof(_color), _color, GL_STATIC_DRAW); 43 colorLocation = glGetAttribLocation(glProgram->getProgram(), "a_color"); 44 glEnableVertexAttribArray(colorLocation); 45 glVertexAttribPointer(colorLocation, 4, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0); 46 47 //使用VAO 48 glBindVertexArray(vao); 49 //渲染 50 glDrawArrays(GL_TRIANGLES, 0, 3); 51 //清空VAO 52 glBindVertexArray(0); 53 54 CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, 3); 55 CHECK_GL_ERROR_DEBUG(); 56 } 57 58 bool HelloWorld::init() 59 { 60 if ( !Layer::init() ) 61 { 62 return false; 63 } 64 65 //准备数据 66 auto size = Director::getInstance()->getWinSize(); 67 float position[] = { 0, 0, size.width, 0, size.width / 2, size.height}; 68 float color[] = { 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1}; 69 for (int i = 0; i < sizeof(position); i++) { 70 _position[i] = position[i]; 71 } 72 for (int i = 0; i < sizeof(color); i++) { 73 _color[i] = color[i]; 74 } 75 76 //vert和frag文件和原文一样,直接放在Classes目录就可以读取到(环境:XCode) 77 glProgram = new GLProgram; 78 glProgram->initWithFilenames("myVertextShader.vert","myFragmentShader.frag"); 79 glProgram->link(); 80 glProgram->updateUniforms(); 81 this->setGLProgram(glProgram); 82 83 //glGen的系列方法会不断的Malloc内存空间,写在onDraw中会导致内存泄漏 84 glGenVertexArrays(1, &vao); 85 glGenBuffers(1, &positionVBO); 86 glGenBuffers(1, &colorVBO); 87 return true; 88 }