• GLSL使用FBO实现MRT(Multiple Render Targets)绘制到多张纹理 【转】


    项目的程序里设计需要将某一帧渲染出来的画面拆成三通道单色图像存到三张纹理里面。要绘制到纹理里,自然就想到FBO了。但是一次要输出多张纹理,这个还没接触过。一阵网上搜索过后,终于了解到了MRT(多重渲染目标)。但是网上的教程大部分都使用到了Fragment Shader里的一个预置变量:gl_FragData[]。但是实际使用当中,glsl却报告说这个gl_FragData变量是不建议使用了。于是再经过多方搜索,知道了建议的操作方法是如何实现的。

    首先自然是新建一个FBO,然后绑定缓存。一般的FBO我们会绑定一个颜色缓存和一个深度缓存。如果是渲染到纹理,我们就会把一个同样尺寸的纹理绑到颜色缓存中去,比如以下代码:

    1. //新建FBO  
    2. GLuint fboId;  
    3. glGenFramebuffersEXT(1, &fboId);  
    4. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboId);  
    5.   
    6. //绑定纹理  
    7. glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,  
    8.                           GL_TEXTURE_2D, textureId, 0);  
    9.   
    10. //绑定深度缓存  
    11. glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,  
    12.                              GL_RENDERBUFFER_EXT, rboId);  


    当然深度缓存也是要预先建好的。那么现在我需要绑定三个纹理,该如何绑定呢?

    FBO是提供了不止一个颜色挂接点的。因此,我们可以将第i张纹理绑定到第i个颜色挂接点上。具体一个FBO能有多少个颜色挂接点,可以使用GL_MAX_COLOR_ATTACHMENTS_EXT参数来查询。

    因此绑定纹理的代码就变成了:

    1. for(i=0; i<3; ++i)  
    2. {  
    3.     glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + i,  
    4.                           GL_TEXTURE_2D, textureId[i], 0);  
    5. }  

    当然纹理数量不能超过颜色挂接点的最大值。


    准备工作完成之后,就是实际FBO渲染时的操作。在绑定多个纹理之后,绘制之前还要告诉FBO输出到哪些缓存。使用以下语句:

    1. GLenum mrt[] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT};  
    2. glDrawBuffers(3, mrt);  

    以上语句先枚举要输出的挂接点,然后使用glDrawBuffers语句来指定。此处绘制3个纹理。这些信息将被传入GLSL当中。


    在Fragment Shader里还需要加一些语句:

    1. //此处3个location应当与FBO的GL_COLOR_ATTACHMENTi_EXT对应  
    2. layout(location = 0) out vec4 Frag0;  
    3. layout(location = 1) out vec4 Frag1;  
    4. layout(location = 2) out vec4 Frag2;  

    这里就不用原来的gl_FragColor或者gl_FragData[]变量了,而是用自己指定位置的输出值。然后在Fragment的主循环里可以针对三个输出值做自己需要的处理。

    于是绘制完成后,FBO就会将渲染结果存入三张纹理当中,可以进行后续的使用。


    参考:

    http://blog.csdn.net/xiajun07061225/article/details/7283929

    http://blog.csdn.net/yangdelong/article/details/1668673

    http://www.cnblogs.com/vertexshader/articles/3022981.html

  • 相关阅读:
    Kafka Shell基本命令(包括topic的增删改查)
    thefuck的安装和使用
    Linux运维利器之ClusterShell
    MySQL数据库的10大经典错误案例
    Mysql 常用操作
    Git 忽略特定文件或文件夹
    为什么需要拷贝构造函数
    C语言编译过程
    设计模式之建造者模式
    设计模式之工厂/抽象工厂模式
  • 原文地址:https://www.cnblogs.com/mazhenyu/p/6488814.html
Copyright © 2020-2023  润新知