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_TEXTURE0
		glTexImage2D(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_CACHE
		cocos2d::GL::bindTexture2DN(textureUnit, -1);//不知道为何,不加本句的话会导致纹理错误(cocos2dx的bug?)
#endif

		glDeleteFramebuffers(2, frameBuffer);
		glDeleteTextures(2, frameTexture);
	} while (false);//用do-while是为了在发生错误时可以立即中断操作,然后执行后续的操作(比如清理)

	// ...

	CHECK_GL_ERROR_DEBUG();
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值