一、先从画一条线开始
1.drawLine使用方法
| auto scene = Scene::create(); |
| Director::getInstance()->runWithScene(scene); |
| auto node = DrawNode::create(); |
| |
| node->drawLine(Vec2(1,1),Vec2(1,222),Color4F(222,1,1,1)); |
| scene->addChild(node); |
2.进入drawLine
| |
| void DrawNode::drawLine(const Vec2 &origin, const Vec2 &destination, const Color4F &color) |
| { |
| ensureCapacityGLLine(2); |
| V2F_C4B_T2F *point = (V2F_C4B_T2F*)(_bufferGLLine + _bufferCountGLLine); |
| V2F_C4B_T2F a = {origin, Color4B(color), Tex2F(0.0, 0.0)}; |
| V2F_C4B_T2F b = {destination, Color4B(color), Tex2F(0.0, 0.0)}; |
| *point = a; |
| *(point+1) = b; |
| _bufferCountGLLine += 2; |
| _dirtyGLLine = true; |
| } |
3.渲染准备
| bool DrawNode::init() |
| { |
| _blendFunc = BlendFunc::ALPHA_PREMULTIPLIED; |
| |
| setGLProgramState(GLProgramState::getOrCreateWithGLProgramName(GLProgram::SHADER_NAME_POSITION_LENGTH_TEXTURE_COLOR)); |
| |
| ensureCapacity(512); |
| ensureCapacityGLPoint(64); |
| ensureCapacityGLLine(256); |
| |
| if (Configuration::getInstance()->supportsShareableVAO()) |
| { |
| |
| glGenVertexArrays(1, &_vao); |
| GL::bindVAO(_vao); |
| |
| glGenBuffers(1, &_vbo); |
| |
| glBindBuffer(GL_ARRAY_BUFFER, _vbo); |
| |
| glBufferData(GL_ARRAY_BUFFER, sizeof(V2F_C4B_T2F)* _bufferCapacity, _buffer, GL_STREAM_DRAW); |
| |
| |
| glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_POSITION); |
| |
| |
| |
| |
| |
| |
| |
| |
| glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, vertices)); |
| |
| glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_COLOR); |
| glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, colors)); |
| |
| glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_TEX_COORD); |
| glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD, 2, GL_FLOAT, GL_FALSE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, texCoords)); |
| |
| |
| |
| |
| |
| |
| } |
| else |
| { |
| glGenBuffers(1, &_vbo); |
| glBindBuffer(GL_ARRAY_BUFFER, _vbo); |
| glBufferData(GL_ARRAY_BUFFER, sizeof(V2F_C4B_T2F)* _bufferCapacity, _buffer, GL_STREAM_DRAW); |
| |
| glGenBuffers(1, &_vboGLLine); |
| glBindBuffer(GL_ARRAY_BUFFER, _vboGLLine); |
| glBufferData(GL_ARRAY_BUFFER, sizeof(V2F_C4B_T2F)*_bufferCapacityGLLine, _bufferGLLine, GL_STREAM_DRAW); |
| |
| glGenBuffers(1, &_vboGLPoint); |
| glBindBuffer(GL_ARRAY_BUFFER, _vboGLPoint); |
| glBufferData(GL_ARRAY_BUFFER, sizeof(V2F_C4B_T2F)*_bufferCapacityGLPoint, _bufferGLPoint, GL_STREAM_DRAW); |
| |
| glBindBuffer(GL_ARRAY_BUFFER, 0); |
| } |
| |
| CHECK_GL_ERROR_DEBUG(); |
| |
| _dirty = true; |
| _dirtyGLLine = true; |
| _dirtyGLPoint = true; |
| |
| #if CC_ENABLE_CACHE_TEXTURE_DATA |
| |
| auto listener = EventListenerCustom::create(EVENT_RENDERER_RECREATED, [this](EventCustom* event){ |
| |
| this->init(); |
| }); |
| |
| _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); |
| #endif |
| |
| return true; |
| } |
| |
4.渲染
(1).draw
| void DrawNode::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags) |
| { |
| if(_bufferCount) |
| { |
| _customCommand.init(_globalZOrder, transform, flags); |
| _customCommand.func = CC_CALLBACK_0(DrawNode::onDraw, this, transform, flags); |
| renderer->addCommand(&_customCommand); |
| } |
| |
| if(_bufferCountGLPoint) |
| { |
| _customCommandGLPoint.init(_globalZOrder, transform, flags); |
| _customCommandGLPoint.func = CC_CALLBACK_0(DrawNode::onDrawGLPoint, this, transform, flags); |
| renderer->addCommand(&_customCommandGLPoint); |
| } |
| |
| if(_bufferCountGLLine) |
| { |
| |
| _customCommandGLLine.init(_globalZOrder, transform, flags); |
| _customCommandGLLine.func = CC_CALLBACK_0(DrawNode::onDrawGLLine, this, transform, flags); |
| renderer->addCommand(&_customCommandGLLine); |
| } |
| } |
(2).onDrawGLLine
| void DrawNode::onDrawGLLine(const Mat4 &transform, uint32_t ) |
| { |
| |
| auto glProgram = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_LENGTH_TEXTURE_COLOR); |
| glProgram->use(); |
| glProgram->setUniformsForBuiltins(transform); |
| glProgram->setUniformLocationWith1f(glProgram->getUniformLocation("u_alpha"), _displayedOpacity / 255.0); |
| |
| |
| GL::blendFunc(_blendFunc.src, _blendFunc.dst); |
| |
| if (_dirtyGLLine) |
| { |
| glBindBuffer(GL_ARRAY_BUFFER, _vboGLLine); |
| glBufferData(GL_ARRAY_BUFFER, sizeof(V2F_C4B_T2F)*_bufferCapacityGLLine, _bufferGLLine, GL_STREAM_DRAW); |
| _dirtyGLLine = false; |
| } |
| if (Configuration::getInstance()->supportsShareableVAO()) |
| { |
| |
| GL::bindVAO(_vaoGLLine); |
| } |
| else |
| { |
| glBindBuffer(GL_ARRAY_BUFFER, _vboGLLine); |
| GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POS_COLOR_TEX); |
| |
| glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, vertices)); |
| |
| glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, colors)); |
| |
| glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD, 2, GL_FLOAT, GL_FALSE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, texCoords)); |
| } |
| |
| |
| glLineWidth(_lineWidth); |
| |
| glDrawArrays(GL_LINES, 0, _bufferCountGLLine); |
| |
| |
| if (Configuration::getInstance()->supportsShareableVAO()) |
| { |
| GL::bindVAO(0); |
| } |
| |
| glBindBuffer(GL_ARRAY_BUFFER, 0); |
| |
| CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1,_bufferCountGLLine); |
| |
| CHECK_GL_ERROR_DEBUG(); |
| } |
二、看看其他图形
1.点
| void DrawNode::drawPoint(const Vec2& position, const float pointSize, const Color4F &color) |
| { |
| ensureCapacityGLPoint(1); |
| |
| V2F_C4B_T2F *point = (V2F_C4B_T2F*)(_bufferGLPoint + _bufferCountGLPoint); |
| V2F_C4B_T2F a = {position, Color4B(color), Tex2F(pointSize,0)}; |
| *point = a; |
| |
| _bufferCountGLPoint += 1; |
| _dirtyGLPoint = true; |
| } |
可以看到drawPoint用的是_bufferGLPoint,对应的VAO是_vaoGLPoint,所以渲染的方法对应使用的vao、vbo是:
| void DrawNode::onDrawGLPoint(const Mat4 &transform, uint32_t ) |
| { |
| auto glProgram = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_COLOR_TEXASPOINTSIZE); |
| glProgram->use(); |
| glProgram->setUniformsForBuiltins(transform); |
| glProgram->setUniformLocationWith1f(glProgram->getUniformLocation("u_alpha"), _displayedOpacity / 255.0); |
| |
| GL::blendFunc(_blendFunc.src, _blendFunc.dst); |
| |
| if (_dirtyGLPoint) |
| { |
| glBindBuffer(GL_ARRAY_BUFFER, _vboGLPoint); |
| glBufferData(GL_ARRAY_BUFFER, sizeof(V2F_C4B_T2F)*_bufferCapacityGLPoint, _bufferGLPoint, GL_STREAM_DRAW); |
| |
| _dirtyGLPoint = false; |
| } |
| |
| if (Configuration::getInstance()->supportsShareableVAO()) |
| { |
| GL::bindVAO(_vaoGLPoint); |
| } |
| else |
| { |
| glBindBuffer(GL_ARRAY_BUFFER, _vboGLPoint); |
| GL::enableVertexAttribs( GL::VERTEX_ATTRIB_FLAG_POS_COLOR_TEX); |
| glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, vertices)); |
| glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, colors)); |
| glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD, 2, GL_FLOAT, GL_FALSE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, texCoords)); |
| } |
| |
| glDrawArrays(GL_POINTS, 0, _bufferCountGLPoint); |
| |
| if (Configuration::getInstance()->supportsShareableVAO()) |
| { |
| GL::bindVAO(0); |
| } |
| |
| glBindBuffer(GL_ARRAY_BUFFER, 0); |
| |
| CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1,_bufferCountGLPoint); |
| CHECK_GL_ERROR_DEBUG(); |
| } |
2.其他,例如drawDot
| void DrawNode::drawDot(const Vec2 &pos, float radius, const Color4F &color) |
| { |
| unsigned int vertex_count = 2*3; |
| ensureCapacity(vertex_count); |
| |
| V2F_C4B_T2F a = {Vec2(pos.x - radius, pos.y - radius), Color4B(color), Tex2F(-1.0, -1.0) }; |
| V2F_C4B_T2F b = {Vec2(pos.x - radius, pos.y + radius), Color4B(color), Tex2F(-1.0, 1.0) }; |
| V2F_C4B_T2F c = {Vec2(pos.x + radius, pos.y + radius), Color4B(color), Tex2F( 1.0, 1.0) }; |
| V2F_C4B_T2F d = {Vec2(pos.x + radius, pos.y - radius), Color4B(color), Tex2F( 1.0, -1.0) }; |
| |
| V2F_C4B_T2F_Triangle *triangles = (V2F_C4B_T2F_Triangle *)(_buffer + _bufferCount); |
| V2F_C4B_T2F_Triangle triangle0 = {a, b, c}; |
| V2F_C4B_T2F_Triangle triangle1 = {a, c, d}; |
| triangles[0] = triangle0; |
| triangles[1] = triangle1; |
| |
| _bufferCount += vertex_count; |
| |
| _dirty = true; |
| } |
用的数据块是_buffer,对应的是_vao。
如有问题,及时指出。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律