【复习笔记】 cocos2d-x 2.x 渲染特效实现 四 高斯模糊效果二
来源:互联网 发布:js object 循环 编辑:程序博客网 时间:2024/05/13 01:19
在上文末,我们已经完成了高斯模糊横向上的模糊效果,而且提到,纵向模糊要在横向模糊的结果上进行,所以为了得到横向模糊的贴图,我们使用离屏渲染。顾名思义,现在渲染的目的地不是屏幕了~一般状况下,gl是直接把渲染好的纹理绘制到屏幕缓冲区的,进而直接显示在屏幕上。但是现在,我们要把它绘制到一张纹理中,这样,就可以像操作一张普通的纹理一样,对它进行再次加工了~这里我们用到FBO技术。
FBO即Frame Buffer Object,帧缓存对象,这使得我们可以创建一个由gl控制的帧缓存。通常情况下,我们只绘制到操作系统提供的帧缓存。
渲染到纹理的大致步骤如下:
1.创建一个空的texture
2.创建FBO
3.绑定texture到FBO上
4.使用自己创建的FBO作为当前渲染的帧缓存
4.draw~
具体代码如下:
void CCEffectSprite::drawGaussianBlur(){CCEGLView *eglView = CCDirector::sharedDirector()->getOpenGLView();float zoomScale = eglView->getFrameZoomFactor();CCSize frameSize = eglView->getFrameSize();CCSize screenBufferSize = CCSizeMake(frameSize.width*zoomScale, frameSize.height*zoomScale);//CCLOG("frameSize : %f, %f", frameSize.width, frameSize.height);float pixelSpan = 0.5f;float blursDis[2] = {pixelSpan/getTextureRect().size.width, pixelSpan/screenBufferSize.height};GLint size = sizeof(ccV3F_C4B_T2F); long data = (long)&m_sQuad;/**/ // gen a empty texture glGenTextures(1, &_texture); glBindTexture(GL_TEXTURE_2D, _texture);glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, screenBufferSize.width, screenBufferSize.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // gen a off-screen framebuffer GLint oldFBO; glGetIntegerv(GL_RENDERBUFFER_BINDING, &oldFBO); glGenFramebuffers(1, &_framebuffer); glBindFramebuffer(GL_FRAMEBUFFER, _framebuffer); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture, 0); // ************ first draw ****************** CC_NODE_DRAW_SETUP(); ccGLBlendFunc(m_sBlendFunc.src, m_sBlendFunc.dst); // ccGLBindTexture2D(m_pobTexture->getName());glActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D, m_pobTexture->getName()); ccGLEnableVertexAttribs(kCCVertexAttribFlag_PosColorTex); // uniforms glUniform2f(_uniforms[kUniformBlurDis], blursDis[0], 0.00f); // attributes glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, size, (GLvoid *)data); glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, size, (GLvoid *)(data + sizeof(ccVertex3F))); glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, size, (GLvoid *)(data + sizeof(ccVertex3F) + sizeof(ccColor4B))); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); // ****************************************** glBindFramebuffer(GL_FRAMEBUFFER, oldFBO); // ************** second draw *****************// reset stackkmGLMatrixMode(KM_GL_MODELVIEW);kmGLPushMatrix();kmGLLoadIdentity();kmGLMatrixMode(KM_GL_PROJECTION);kmGLPushMatrix();kmGLLoadIdentity();glViewport(0, 0, screenBufferSize.width, screenBufferSize.height);CC_NODE_DRAW_SETUP();ccGLBlendFunc(m_sBlendFunc.src, m_sBlendFunc.dst);// ccGLBindTexture2D(m_pobTexture->getName());glActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D, _texture); ccGLEnableVertexAttribs(kCCVertexAttribFlag_PosColorTex);// uniformsglUniform2f(_uniforms[kUniformBlurDis], 0.00f, blursDis[1]); // attributes// do not add any other render info, just do another direction blur:ccV3F_C4B_T2F_Quad tempQuad;memset(&tempQuad, 0, sizeof(tempQuad));// vertices are located in the 4 corners of the whole viewport.tempQuad.tl.vertices = vertex3(-1, 1, -1);tempQuad.bl.vertices = vertex3(-1, -1, -1);tempQuad.tr.vertices = vertex3(1, 1, -1);tempQuad.br.vertices = vertex3(1, -1, -1);// color is black which won't change any color info.tempQuad.tl.colors = ccc4(255, 255, 255, 255);tempQuad.bl.colors = ccc4(255, 255, 255, 255);tempQuad.tr.colors = ccc4(255, 255, 255, 255);tempQuad.br.colors = ccc4(255, 255, 255, 255);// UV y-coords is also fliped just like what CCSprite did in above step.tempQuad.tl.texCoords = tex2(0, 1);tempQuad.bl.texCoords = tex2(0, 0);tempQuad.tr.texCoords = tex2(1, 1);tempQuad.br.texCoords = tex2(1, 0);data = (long)&tempQuad; glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, size, (GLvoid *)data); glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, size, (GLvoid *)(data + sizeof(ccVertex3F))); glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, size, (GLvoid *)(data + sizeof(ccVertex3F) + sizeof(ccColor4B))); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);// restore stackkmGLMatrixMode(KM_GL_PROJECTION);kmGLPopMatrix();kmGLMatrixMode(KM_GL_MODELVIEW);kmGLPopMatrix();CCDirector::sharedDirector()->setViewport(); // ************************************** /**/ glDeleteTextures(1, &_texture); glDeleteFramebuffers(1, &_framebuffer);}
上述代码中值得一提的几点是:
1.由于我们自己创建的帧缓存是为了模拟另一个“屏幕”而存在的,所以FBO中绑定的texture和viewport都使用了系统帧缓存的大小,所以当第一次渲染结束后,可以得到一张和屏幕大小相同的贴图,且和直接渲染的到屏幕之后,与屏幕上显示的像素信息完全相同。在第二次渲染中,因为原贴图大小已经变化,所以不能使用正常渲染的MVP变换,而是直接把与屏幕大小相同的贴图直接绘制出来即可。在cocos中,使用了第三方的3D数学库kazmath来存储各级节点的变换矩阵,所以,在第二次渲染的时候,在MV矩阵和P矩阵栈上都压入一个单位矩阵,来保证不做任何变换,且纹理坐标也根据cocos的习惯,在纵向上做了翻转。
2.因为两次渲染的贴图大小是不一样的,为了横向和纵向都用相同的采样标准去做高斯模糊,blurDis变量分别用原贴图的宽和生成贴图的高做了计算。
最终效果:
可以看到,相比于之前简单采样的模糊,高斯模糊有更好的模糊效果~
- 【复习笔记】 cocos2d-x 2.x 渲染特效实现 四 高斯模糊效果二
- 【复习笔记】 cocos2d-x 2.x 渲染特效实现 三 高斯模糊效果一
- 【复习笔记】 cocos2d-x 2.x 渲染特效实现 二 简单模糊效果
- 【复习笔记】 cocos2d-x 2.x 渲染特效实现 五 节点树的模糊效果
- 【复习笔记】 cocos2d-x 2.x 渲染特效实现 六 节点树的描边效果
- 【复习笔记】 cocos2d-x 2.x 渲染特效实现 七 辉光效果
- 【复习笔记】 cocos2d-x 2.x 渲染特效实现 八 流光效果
- 【复习笔记】 cocos2d-x 2.x 渲染特效实现 一 基础回顾
- Cocos2d-x高斯模糊
- cocos2D-x 3.x学习笔记【四】 动作效果
- [cocos2d-x]对CCSprite进行高斯模糊
- 使用threejs离屏渲染实现高斯模糊效果
- cocos2d-x 渲染机制深入解析(二)
- 【Cocos2d-x】 3.0渲染 分析之二
- Cocos2D-X shader(二) OpenGL渲染管线
- Cocos2d-x 3.x 图形学渲染系列四
- Cocos2d-x 粒子编辑器使用和渲染特效
- 【Cocos2d-x】实现翻牌效果
- Java多线程返回结果2 FutureTask
- Leetcode #31. Next Permutation 下一个全排列 解题报告
- Java接口特征与细节
- Wireshark网络分析实战笔记(二)显示过滤器
- 2013 翻硬币
- 【复习笔记】 cocos2d-x 2.x 渲染特效实现 四 高斯模糊效果二
- 树链剖分题库
- CF 615B. Longtail Hedgehog 图 dp
- 【10-3】条件过滤
- C# 服务器、客户端学习(二)
- 大数据驱动下的微博社会化推荐
- Python 模块动态加载技术
- pinpoint监控学习笔记
- 【10-4】多层表达式