FrameBuffer及离屏渲染

Framebuffer Get知识点

  • 1、给定的模型坐标可能只占有屏幕的一般或者一部分,可以通过平移缩放等操作让他占满全屏。
  • 2、渲染纹理图像倒立,可以通过旋转操作使他正常。
  • 3、绑定framebuffer后记得清理缓冲区
    glBindRenderbuffer(GL_RENDERBUFFER, self.myColorRenderBuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, self.myColorFrameBuffer);

glDisable(GL_DEPTH_TEST);
glClearColor(1.0f, 0, 0, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);

  • 4、创建framebuffer 步骤及代码,注意renderbuffer和纹理的尺寸要对应,否则会采样错误。
- (GLuint)createCustomFrameBuffer{
    GLuint frameBuffer;
    glGenFramebuffers(1, &frameBuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
    
    //1、绑定颜色缓冲  用于离屏渲染
    GLuint texture;
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    CGSize screenSize = [UIScreen mainScreen].bounds.size;
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, screenSize.width*[UIScreen mainScreen].scale, screenSize.height*[UIScreen mainScreen].scale, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
    self.frameTexture = texture;
    
    //2、绑定深度缓冲和模板缓冲(使用renderbuffer)注意renbuderbuffer和texture 传递内存空间时,都乘了屏幕比例
    GLuint renderbuffer;
    glGenRenderbuffers(1, &renderbuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, screenSize.width*[UIScreen mainScreen].scale, screenSize.height*[UIScreen mainScreen].scale);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, renderbuffer);
    self.frameRenderBuffer = renderbuffer;
    
    //GL_FRAMEBUFFER_COMPLETE
    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
        NSLog(@"frambuffer 出错---");
        return 0;
    }
    glBindFramebuffer(GL_FRAMEBUFFER, renderbuffer);
    
    return frameBuffer;
}
  • 5、自定义framebuffer使用步骤:
    a、创建framebuffer,并绑定自定义的framebuffer.
 glUseProgram(self.grassProgram);
    //glViewport(0, 0, screenSize.width*3, screenSize.height*3);
    glBindRenderbuffer(GL_RENDERBUFFER, self.myColorRenderBuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, self.myColorFrameBuffer);

    glDisable(GL_DEPTH_TEST);
    glClearColor(1.0f, 0, 0, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
}

b、设置清屏
c、绘制物体 在frambuffer上glBindTexture(GL_TEXTURE_2D, self.frameTexture);
d1、后期处理及效果

  • 边检测
void main(){

    lowp float offset = 1.0 / 300.0;
       
    lowp vec2 v[9];
    v[0] = vec2(-offset,offset);
    v[1] = vec2(0.0,offset);
    v[2] = vec2( offset,  offset);
    v[3] = vec2(-offset,  0.0);
    v[4] = vec2( 0.0,    0.0);
    v[5] = vec2( offset,  0.0);
    v[6] = vec2(-offset, -offset);
    v[7] = vec2( 0.0,   -offset);
    v[8] = vec2( offset, -offset);
    
    lowp float kernel[9] ;
 //边缘检测
    kernel[0] = 1.0 ;
       kernel[1] =  1.0;
       kernel[2] = 1.0 ;
       kernel[3] = 1.0;
       kernel[4] = -8.0;
       kernel[5] = 1.0;
       kernel[6] = 1.0 ;
       kernel[7] = 1.0 ;
       kernel[8] = 1.0 ;
    
    lowp vec3 sampleTex[9];
    
    for (int i=0 ; i < 9; i++){
       sampleTex[i] = vec3(texture2D(boxTexture,outTextCoord.st+v[i]));
      }
     lowp vec3 col = vec3(0.0);
      for(int i = 0; i < 9; I++)
          col += sampleTex[i] * kernel[I];
    gl_FragColor = vec4(col,1.0);

边检测效果:


Snip20200315_2.png

核效果:

void main(){
    lowp float offset = 1.0 / 300.0;
       
    lowp vec2 v[9];
    v[0] = vec2(-offset,offset);
    v[1] = vec2(0.0,offset);
    v[2] = vec2( offset,  offset);
    v[3] = vec2(-offset,  0.0);
    v[4] = vec2( 0.0,    0.0);
    v[5] = vec2( offset,  0.0);
    v[6] = vec2(-offset, -offset);
    v[7] = vec2( 0.0,   -offset);
    v[8] = vec2( offset, -offset);
    
    lowp float kernel[9] ;
  
  //核定义数组
    kernel[0] = -1.0;
    kernel[1] = -1.0;
    kernel[2] = -1.0;
    kernel[3] = -1.0;
    kernel[4] = 9.0;
    kernel[5] = -1.0;
    kernel[6] = -1.0;
    kernel[7] = -1.0;
    kernel[8] = -1.0;
   lowp vec3 sampleTex[9];
    
    for (int i=0 ; i < 9; i++){
       sampleTex[i] = vec3(texture2D(boxTexture,outTextCoord.st+v[i]));
      }
     lowp vec3 col = vec3(0.0);
      for(int i = 0; i < 9; I++)
          col += sampleTex[i] * kernel[I];
      
    
    gl_FragColor = vec4(col,1.0);
}

核效果:


Snip20200315_3.png

模糊效果:

void main(){
    lowp float offset = 1.0 / 300.0;
       
    lowp vec2 v[9];
    v[0] = vec2(-offset,offset);
    v[1] = vec2(0.0,offset);
    v[2] = vec2( offset,  offset);
    v[3] = vec2(-offset,  0.0);
    v[4] = vec2( 0.0,    0.0);
    v[5] = vec2( offset,  0.0);
    v[6] = vec2(-offset, -offset);
    v[7] = vec2( 0.0,   -offset);
    v[8] = vec2( offset, -offset);
    
    lowp float kernel[9] ;

//模糊效果定义数组
     kernel[0] = 1.0 / 16.0;
    kernel[1] =  2.0 / 16.0;
    kernel[2] = 1.0 / 16.0;
    kernel[3] = 2.0 / 16.0;
    kernel[4] = 4.0 / 16.0;
    kernel[5] = 2.0 / 16.0;
    kernel[6] = 1.0 / 16.0;
    kernel[7] = 2.0 / 16.0;
    kernel[8] = 1.0 / 16.0;
  lowp vec3 sampleTex[9];
    
    for (int i=0 ; i < 9; i++){
       sampleTex[i] = vec3(texture2D(boxTexture,outTextCoord.st+v[i]));
      }
     lowp vec3 col = vec3(0.0);
      for(int i = 0; i < 9; I++)
          col += sampleTex[i] * kernel[I];
      
    
    gl_FragColor = vec4(col,1.0);
}

效果图:


Snip20200315_4.png

灰度加权:

 gl_FragColor = texture2D(boxTexture,outTextCoord);
    gl_FragColor = vec4(gl_FragColor.r*0.2126+gl_FragColor.g*0.7152+gl_FragColor.b*0.0722,gl_FragColor.r*0.2126+gl_FragColor.g*0.7152+gl_FragColor.b*0.0722,gl_FragColor.r*0.2126+gl_FragColor.g*0.7152+gl_FragColor.b*0.0722,1.0);

灰度加权效果:


Snip20200315_5.png
图像旋涡:

主要是在某个半径范围里,把当前采样点旋转一定角度,旋转以后当前点的颜色就被旋转后的点的颜色代替,因此整个半径范围里会有旋转的效果。如果旋转的时候旋转角度随着当前点离半径的距离递减,整个图像就会出现漩涡效果。这里使用的了抛物线递减因子:(1.0-(r/Radius)*(r/Radius) )。

precision mediump float;

const float PI = 3.14159265;
uniform sampler2D textureMap;

const float uD = 80.0; //旋转角度
const float uR = 0.5; //旋转半径

varying vec2 outText;

void main()
{
    ivec2 ires = ivec2(512, 512);
    float Res = float(ires.s);

    vec2 st = outText;
    float Radius = Res * uR;

    vec2 xy = Res * st;

    vec2 dxy = xy - vec2(Res/2., Res/2.);
    float r = length(dxy);

    float beta = atan(dxy.y, dxy.x) + radians(uD) * 2.0 * (-(r/Radius)*(r/Radius) + 1.0);//(1.0 - r/Radius);

    vec2 xy1 = xy;
    if(r<=Radius)
    {
        xy1 = Res/2. + r*vec2(cos(beta), sin(beta));
    }

    st = xy1/Res;

    vec3 irgb = texture2D(textureMap, st).rgb;

    gl_FragColor = vec4( irgb, 1.0 );
}
Snip20200705_39.png
马赛克效果

马赛克效果就是把图片的一个相当大小的区域用同一个点的颜色来表示.可以认为是大规模的降低图像的分辨率,而让图像的一些细节隐藏起来。

precision mediump float;

varying vec2 outText;
uniform sampler2D textureMap;
const vec2 TexSize = vec2(400.0, 400.0);
const vec2 mosaicSize = vec2(8.0, 8.0);

void main()
{
    vec2 intXY = vec2(outText.x*TexSize.x, outText.y*TexSize.y);
    vec2 XYMosaic = vec2(floor(intXY.x/mosaicSize.x)*mosaicSize.x, floor(intXY.y/mosaicSize.y)*mosaicSize.y);
    vec2 UVMosaic = vec2(XYMosaic.x/TexSize.x, XYMosaic.y/TexSize.y);
    vec4 color = texture2D(textureMap, UVMosaic);
    gl_FragColor = color;
}
Snip20200705_40.png
浮雕效果

浮雕效果是指图像的前景前向凸出背景。实现思路:把图象的一个象素和左上方的象素进行求差运算,并加上一个灰度。这个灰度就是表示背景颜色。这里我们设置这个插值为128 (图象RGB的值是0-255)。同时,我们还应该把这两个颜色的差值转换为亮度信息,避免浮雕图像出现彩色像素。

precision mediump float;
    varying vec2 outText;
    uniform sampler2D textureMap;
    const highp vec3 W = vec3(0.2125, 0.7154, 0.0721);
    const vec2 TexSize = vec2(100.0, 100.0);
    const vec4 bkColor = vec4(0.5, 0.5, 0.5, 1.0);

    void main()
    {
        vec2 tex = outText;
        vec2 upLeftUV = vec2(tex.x-1.0/TexSize.x, tex.y-1.0/TexSize.y);
        vec4 curColor = texture2D(textureMap, outText);
        vec4 upLeftColor = texture2D(textureMap, upLeftUV);
        vec4 delColor = curColor - upLeftColor;
        float luminance = dot(delColor.rgb, W);
        gl_FragColor = vec4(vec3(luminance), 0.0) + bkColor;
    }
Snip20200705_41.png

d2、绑定默认缓冲区,渲染frambuffer中的纹理到默认缓冲区,至屏幕layer上。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容