coco2dx绘制到纹理

为了完成一些特效(比如,角色狂暴,但双脚又被石化),有时需要使用GL ES的的纹理缓冲(代码未整理):

void MySprite::myDraw(const cocos2d::Mat4 &transform)
{do{GLint maxSizeOfFrameTexture = 0;glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &maxSizeOfFrameTexture);if (contentSize.width > maxSizeOfFrameTexture || contentSize.height > maxSizeOfFrameTexture){CCASSERT(false, "指定的纹理大小无效");break;}<span style="white-space:pre">	</span>GLint viewport[4];
<span style="white-space:pre">		</span>glGetIntegerv(GL_VIEWPORT, viewport);<span style="white-space:pre">		</span>
<span style="white-space:pre">		</span>glViewport(0, 0, contentSize.width, contentSize.height);// 一定不能漏掉GLuint frameBuffer[2];GLuint frameTexture[2];glGenFramebuffers(2, frameBuffer);glGenTextures(2, frameTexture);// 下面将纹理this->_texture->getName()的狂暴效果绘制到纹理frameTexture[0]中// function usingFrameTexture()cocos2d::GL::bindTexture2DN(textureUnit, frameTexture[0]);//textureUnit:GL ES中使用的是GL_TEXTURE0、GL_TEXTURE1等等,在cocos2d::GL中使用的是索引,即GL_TEXTUREXXX-GL_TEXTURE0glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, contentSize.width, contentSize.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer[0]);glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, frameTexture[0], 0);if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)//帧缓冲不完整,无法继续{glDeleteFramebuffers(2, frameBuffer);glDeleteTextures(2, frameTexture);break;;}glClearColor(0, 0, 0, 0);glClear(GL_COLOR_BUFFER_BIT);glDisable(GL_DEPTH_TEST);// 此处使用狂暴着色器,绘画狂暴效果,使用的纹理为this->_texture->getName()// ...// 至此,狂暴效果将被绘制到纹理frameTexture[0]中// 下面将纹理frameTexture[0]的脚部石化效果绘制到纹理frameTexture[1]中(还应当用到模板缓冲,此处省略了)if (!usingFrameTexture(frameTexture[1], ...)) break;// 此处使用石化着色器,绘画石化效果,使用的纹理为frameTexture[0]// ...// 至此,石化效果将被绘制到纹理frameTexture[1]中// 下面将纹理frameTexture[1]绘制主缓冲
<span style="white-space:pre">		</span>glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);// 恢复视区glBindFramebuffer(GL_FRAMEBUFFER, 0);static cocos2d::GLProgram* program = cocos2d::GLProgramCache::getInstance()->getGLProgram(cocos2d::GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR_NO_MVP);program->use();cocos2d::V3F_C4B_T2F_Quad realQuad = this->_quad;transform.transformPoint(&realQuad.bl.vertices);transform.transformPoint(&realQuad.br.vertices);transform.transformPoint(&realQuad.tl.vertices);transform.transformPoint(&realQuad.tr.vertices);mySpriteDrawHelper().setup(&realQuad, 1, nullptr, 0);cocos2d::GL::blendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);glBlendEquation(GL_FUNC_ADD);cocos2d::GLProgramState::getOrCreateWithGLProgram(program)->apply(cocos2d::Mat4::ZERO);//仅使用P矩阵,因此apply中传入的数值不会被用到cocos2d::GL::bindTexture2DN(textureUnit, frameTexture[1]);static GLuint sampler0Location = program->getUniformLocation(cocos2d::GLProgram::UNIFORM_NAME_SAMPLER0);program->setUniformLocationWith1i(sampler0Location, textureUnit); // 在上面的apply函数中,写死了UNIFORM_NAME_SAMPLER0的值为0,此处需要作出修正glDrawArrays(GL_QUAD_STRIP, 0, 4);<span style="white-space:pre">	</span>// 由于cocos2dx的缓冲机制,此处需要恢复program的sampler0Location
<span style="white-space:pre">	</span>program->setUniformLocationWith1i(sampler0Location, 0);mySpriteDrawHelper().unsetup();
#if CC_ENABLE_GL_STATE_CACHEcocos2d::GL::bindTexture2DN(textureUnit, -1);//不知道为何,不加本句的话会导致纹理错误(cocos2dx的bug?)
#endifglDeleteFramebuffers(2, frameBuffer);glDeleteTextures(2, frameTexture);} while (false);//用do-while是为了在发生错误时可以立即中断操作,然后执行后续的操作(比如清理)// ...CHECK_GL_ERROR_DEBUG();
}