这几天在看子龙山人的关于OpenGL的文章,先依葫芦画瓢,能看到些东西,才能慢慢深入了解,当入门文章不错,但是其中遇到的一些问题,折腾了一些时间,为了方便和我一样的小白们,在这篇文章中进行写补充。
原文地址:OpenGL ES2.0教程:编写自己的shader(2)--子龙山人
文章中关于VBO和VAO部分的代码的写法,我进行了些修改,将重复使用的变量定义全局变量,并修改初始化数据位置,防止在onDraw方法中重复的Malloc,致使内存泄露,具体的修改在代码注释中会说明。
源码如下:
HelloWorldScene.h
#include "cocos2d.h"
USING_NS_CC;
class HelloWorld : public cocos2d::Layer
{
public:
static cocos2d::Scene* createScene();
virtual bool init() override;
CREATE_FUNC(HelloWorld);
virtual void visit(Renderer *renderer, const Mat4& parentTransform, uint32_t parentFlags) override;
void onDraw();
private:
CustomCommand _command;
float _position[16];
float _color[12];
GLProgram* glProgram;
GLuint vao;//定义VAO缓冲
GLuint positionVBO;
GLuint colorVBO;
GLuint positionLocation;
GLuint colorLocation;
};
HelloWorldScene.cpp
#include "HelloWorldScene.h"
Scene* HelloWorld::createScene()
{
auto scene = Scene::create();
auto layer = HelloWorld::create();
scene->addChild(layer);
return scene;
}
void HelloWorld::visit(Renderer *renderer, const Mat4 &transform,uint32_t parentFlags)
{
Layer::visit(renderer, transform, parentFlags);
_command.init(_globalZOrder);
_command.func = CC_CALLBACK_0(HelloWorld::onDraw, this);
Director::getInstance()->getRenderer()->addCommand(&_command);
}
void HelloWorld::onDraw()
{
//使用已经在init中初始化的glProgram
glProgram->use();
glProgram->setUniformsForBuiltins();
//获取VAO(OSX和ISO中默认开启,windows中默认不开启)
glBindVertexArray(vao);
//获取VBO
glBindBuffer(GL_ARRAY_BUFFER, positionVBO);
//填充坐标数据
glBufferData(GL_ARRAY_BUFFER, sizeof(_position), _position, GL_STATIC_DRAW);
positionLocation = glGetAttribLocation(glProgram->getProgram(), "a_position");
glEnableVertexAttribArray(positionLocation);
glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0);
//获取VBO
glBindBuffer(GL_ARRAY_BUFFER, colorVBO);
//填充颜色数据
glBufferData(GL_ARRAY_BUFFER, sizeof(_color), _color, GL_STATIC_DRAW);
colorLocation = glGetAttribLocation(glProgram->getProgram(), "a_color");
glEnableVertexAttribArray(colorLocation);
glVertexAttribPointer(colorLocation, 4, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0);
//使用VAO
glBindVertexArray(vao);
//渲染
glDrawArrays(GL_TRIANGLES, 0, 3);
//清空VAO
glBindVertexArray(0);
CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, 3);
CHECK_GL_ERROR_DEBUG();
}
bool HelloWorld::init()
{
if ( !Layer::init() )
{
return false;
}
//准备数据
auto size = Director::getInstance()->getWinSize();
float position[] = { 0, 0, size.width, 0, size.width / 2, size.height};
float color[] = { 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1};
for (int i = 0; i < sizeof(position); i++) {
_position[i] = position[i];
}
for (int i = 0; i < sizeof(color); i++) {
_color[i] = color[i];
}
//vert和frag文件和原文一样,直接放在Classes目录就可以读取到(环境:XCode)
glProgram = new GLProgram;
glProgram->initWithFilenames("myVertextShader.vert","myFragmentShader.frag");
glProgram->link();
glProgram->updateUniforms();
this->setGLProgram(glProgram);
//glGen的系列方法会不断的Malloc内存空间,写在onDraw中会导致内存泄漏
glGenVertexArrays(1, &vao);
glGenBuffers(1, &positionVBO);
glGenBuffers(1, &colorVBO);
return true;
}
网友评论