大佬教程收集整理的这篇文章主要介绍了cocos2dx3.x绘制自己的node,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
@H_618_1@3.x最大的变化就是绘制,通过绘制命令添加到渲染队列中,优化相邻两个渲染命中,如果使用的是同一张纹理,则会并到一个批次中绘制出来,具体流程可以看看之前的文章
http://www.voidcn.com/article/p-hfitcsxw-va.html
@H_618_1@下面的例子还顺带开了vbo,vao的话opengles2.0还不支持,所以都被我注释了
头文件.h
#ifndef __HelLOWORLD_SCENE_H__ #define __HelLOWORLD_SCENE_H__ #include "cocos2d.h" using namespace cocos2d; class HelloWorld : public cocos2d::Layer { public: virtual ~HelloWorld(); static cocos2d::Scene* createScene(); virtual bool init() override; //重写这个方法很重要,node节点递归visit完后就会调这个draw函数,所以我们在这里添加绘制命令绑定自己的绘制函数OnDraw virtual void draw(Renderer *renderer,const Mat4 &transform,bool transformupdated) override; //自己的绘制函数 void onDraw(); void menuCloseCallBACk4(cocos2d::ref* pSender); CREATE_FUNC(HelloWorld); private: Customcatommand _customcatommand; //GLuint vao; GLuint vertexVBO; //缓冲区对象句柄 - 顶点 GLuint indexVBO; //缓冲区对象句柄 - 顶点索引 //当然,你可以可以Gluint vbo[2]用数组去装 }; #endif // __HelLOWORLD_SCENE_H__
#include "HelloWorldScene.h" #include "MySprite.h" #include "CubeTexture.h" USING_NS_Cc; Scene* HelloWorld::createScene() { // 'scene' is an autorelease object auto scene = Scene::create(); Size size = Director::geTinstance()->getWinSize(); auto layer2 = Layer::create(); Sprite* sp = Sprite::create("HelloWorld.png"); //MoveTo* move = MoveTo::create(5.0f,Vec2(400,400)); //sp->runAction(movE); sp->setPosition(size.width / 2,size.height / 2); //sp->setScale(2.0f); FontDefinition fd; fd._fontSize = 40; FontShadow fs; fs._shadowEnabled = true; fs._shadowBlur = 0.1f; fs._shadowOffset = Size(10.0f,20.0f); fs._shadowOpacity = 1.0f; fd._shadow = fs; LabelTTF* lb = LabelTTF::createWithFontDefinition("Hello world",fd); lb->setPosition(size.width / 3,size.height / 3); layer2->addChild(sp); layer2->addChild(lb); //scene->addChild(layer2); // 'layer' is an autorelease object auto layer = HelloWorld::create(); // add layer as a child to scene scene->addChild(layer); // return the scene return scene; } void HelloWorld::menuCloseCallBACk4(cocos2d::ref* pSender) { auto scene = CubeTexture::createScene(); Director::geTinstance()->replaceScene(scenE); } // on "init" you need to initialize your instance bool HelloWorld::init() { ////////////////////////////// // 1. super init first if ( !Layer::init() ) { return false; } auto closeItem4 = MenuItemImage::create( "CloseNormal.png","CloseSELEcted.png",CC_CALLBACK_1(HelloWorld::menuCloseCallBACk4,this)); Size visibleSize = Director::geTinstance()->getVisibleSize(); Vec2 origin = Director::geTinstance()->getVisibLeorigin(); closeItem4->setPosition(Vec2(origin.x + visibleSize.width / 2 - closeItem4->getContentSize().width / 2,origin.y + visibleSize.height / 2 + closeItem4->getContentSize().height / 2)); // create menu,it's an autorelease object auto menu = Menu::create(closeItem4,null); menu->setPosition(Vec2::ZERO); this->addChild(menu,100); //create my own program auto glprogram = new GLProgram; glprogram->initWithFilenames("myVertextShader.vert","myFragmentShader.frag"); glprogram->link(); //set uniform LOCATIOns glprogram->updateUniforms(); setGLProgram(glprogram); //设置为自己的shader //glGenVertexArrays(1,&vao); //glBindVertexArray(vao); glGenBuffers(1,&vertexVBO); //创建缓冲区句柄 glGenBuffers(1,&indexVBO); return true; } void HelloWorld::draw(cocos2d::renderer *renderer,bool transformupdated) { _customcatommand.init(_globalZOrder); //绘制优先级 _customcatommand.func = CC_CALLBACK_0(HelloWorld::onDraw,this);//绑定自定义绘制函数,由于是用自己定于的顶点数据,所以没用矩阵信息 renderer->addCommand(&_customcatommand); //把渲染命令丢进绘制队列 } void HelloWorld::onDraw() { //如果使用对等矩阵,则三角形绘制会在最前面 Director::geTinstance()->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW); Director::geTinstance()->loadIdentitymatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW); Director::geTinstance()->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_projection); Director::geTinstance()->loadIdentitymatrix(MATRIX_STACK_TYPE::MATRIX_STACK_projection); Mat4 modelViewMatrix; Mat4::createLookAt(Vec3(0,1),Vec3(0,0),1,&modelViewMatriX); modelViewMatrix.translate(2,2,-5); //static float move = 0; //modelViewMatrix.translate(sinf(move*0.05)*2,-5); //move++; //static float rotation = 0; //modelViewMatrix.rotate(Vec3(1,CC_DEGREES_TO_RADIANS(rotation)); //rotation++; //if (rotation > 360) { // rotation = 0; //} Mat4 projectionMatrix; Mat4::createPerspective(60,480/320,1.0,42,&projectionMatriX); Director::geTinstance()->multiplymatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROjeCTION,projectionMatriX); Director::geTinstance()->multiplymatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW,modelViewMatriX); auto glProgram = getGLProgram(); glProgram->use(); glProgram->setUniformsForBuilTins(); Director::geTinstance()->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_projection); Director::geTinstance()->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW); typedef struct { float Position[3]; float Color[4]; } Vertex; // auto size = Director::geTinstance()->getVisibleSize(); Vertex data[] = { // Front { { 1,-1,0 },{ 1,1 } },{ { 1,{ 0,{ { -1,// BACk { { 1,-2 },// Left { { -1,// Right { { 1,// Top { { 1,// Bottom { { 1,1 } } }; GLubyte inDices[] = { // Front 0,3,// BACk 4,5,6,4,7,// Left 8,9,10,11,8,// Right 12,13,14,15,12,// Top 16,17,18,19,16,// Bottom 20,21,22,23,20 }; glBindBuffer(GL_ARRAY_BUFFER,vertexVBO); //绑定这个缓冲区句柄为顶点类型 glBufferData(GL_ARRAY_BUFFER,sizeof(data),data,GL_STATIC_DRAW); //申请内存大小和绑定数据,静态绘制,有几种枚举类型这里就不说了,自行百度 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,indexVBO);//绑定这个缓冲区句柄为索引类型 glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(inDices),inDices,GL_STATIC_DRAW); GLuint positionLOCATIOn = glGetAttribLOCATIOn(glProgram->getProgram(),"a_position"); //获取自定义shader中的属性变量的地址 GLuint colorLOCATIOn = glGetAttribLOCATIOn(glProgram->getProgram(),"a_color"); glEnableVertexAttribArray(positionLOCATIOn);//激活 glEnableVertexAttribArray(colorLOCATIOn); glVertexAttribPointer(positionLOCATIOn,GL_FLOAT,GL_falSE,sizeof(VerteX),(GLvoid*)offsetof(Vertex,Position)); glVertexAttribPointer(colorLOCATIOn,Color)); // 0 ~ 1 之间波动 static float colorCount = 0; float tmp = sinf(colorCount*0.01); tmp = tmp < 0 ? -tmp : tmp; colorCount++; /* ---------------------- test1, 为一个float赋值 */ //GLuint uColorLOCATIOn1 = glGetUniformLOCATIOn(glProgram->getProgram(),"specIntensity"); //float specIntensity = tmp; //glUniform1f(uColorLOCATIOn1,specIntensity); /* ---------------------- test2, 为1个由4个float组成的vec4赋值 */ //GLuint uColorLOCATIOn2 = glGetUniformLOCATIOn(glProgram->getProgram(),"u_color"); //float uColor2[] = { tmp,tmp,tmp }; //glUniform4fv(uColorLOCATIOn2,uColor2); /* ---------------------- test3, 为float[]数组中的两个元素赋值 */ //GLuint uColorLOCATIOn3 = glGetUniformLOCATIOn(glProgram->getProgram(),"threshold"); //float threshold[2] = { 0.5,tmp }; //glUniform1fv(uColorLOCATIOn3,threshold); /* ---------------------- test4, 为vec4[]数组中的3个元素赋值 */ //GLuint uColorLOCATIOn4 = glGetUniformLOCATIOn(glProgram->getProgram(),"colors"); //float colors[12] = { 0.4,0.4,0.8,// 0.2,0.2,// 1.0,tmp }; //glUniform4fv(uColorLOCATIOn4,colors); /* ---------------------- test5, 为float[]数组中的某个元素赋值,根据下标索引 */ GLuint uColorLOCATIOn5 = glGetUniformLOCATIOn(glProgram->getProgram(),"threshold[0]"); //传入自定shader中的uniform变量,控制alpha透明度 float asd = tmp; glUniform1f(uColorLOCATIOn5,asd); glDrawElements(GL_TRIANGLES,36,GL_UNSIGNED_BYTE,(GLvoid*)0); //绘制三角形,由于索引也上传到缓冲区了,所以这里的索引直接传0地址 //解除激活的缓冲区 glBindBuffer(GL_ARRAY_BUFFER,0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1,36); checK_GL_ERROR_DEBUG(); } HelloWorld::~HelloWorld() { //清除缓冲区句柄 gldeleteBuffers(1,&vertexVBO); gldeleteBuffers(1,&indexVBO); }
attribute vec3 a_position; attribute vec4 a_color; varying vec4 v_fragmentColor; varying vec3 normal; void main() { gl_Position = CC_MVPMatrix * vec4(a_position.xyz,1.0); v_fragmentColor = a_color; }
varying vec4 v_fragmentColor; uniform float specIntensity; uniform vec4 u_color; uniform float threshold[2]; uniform vec4 colors[3]; vec4 toonify(float intensity) { vec4 color; if (intensity < 0.3) color = vec4(1.0,0.0,0.5); else if (intensity < 0.5) color = vec4(0.0,0.5); else if (intensity < 0.7) color = vec4(0.0,0.5); else { color = vec4(1.0,0.5); //discard; //最后的discard关键字只能在片断shader中使用,它将在不写入帧缓存或者深度缓存的情况下,终止当前片断的shader程序。 } return(color); } void main() { // ---------------------- test1 // gl_FragColor = v_fragmentColor * vec4(1.0,specIntensity); // ---------------------- test2 //gl_FragColor = v_fragmentColor * u_color; // ---------------------- test3 //gl_FragColor = v_fragmentColor * vec4(1.0,threshold[1]); // ---------------------- test4 //gl_FragColor = v_fragmentColor * colors[2]; // ---------------------- test5 gl_FragColor = v_fragmentColor * vec4(1.0,threshold[0]); // ---------------------- test6 //gl_FragColor = toonify(threshold[0]); }
shader编写需要注意的是
如果shader中定义了uniform属性名但没有使用,会在编译shader时优化调,所以在c++中获取uniform中的变量地址会是个空地址
其次就是类型需要严格一直,在windows平台体现不出来,应为win平台用的是opengl4.0的,而手机平台的是opengles2.0标准,类型不一致在运行时导致异常崩溃,崩溃信息可以重eclipse中看到,比如 float a = 4.0 * 123就是错的,float*int,应改为 float a = 4.0 * float(123)才正确
以上是大佬教程为你收集整理的cocos2dx3.x绘制自己的node全部内容,希望文章能够帮你解决cocos2dx3.x绘制自己的node所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。