opengl - GLSL : accessing framebuffer to get RGB and change it

标签 opengl glsl shader

我想访问帧缓冲区以获取 RGB 并更改每个像素的值。这是因为glReadPixels和glDrawPixels使用起来太慢,所以我应该使用着色器而不是使用它们。

现在,我编写代码,并成功使用GLSL着色器显示三维模型。

我画了两个立方体,如下所示。

.... 
glDrawArrays(GL_TRIANGLES, 0, 12*6);
.... 

和片段着色器:

varying vec3 fragmentColor;
void main()
{
    gl_FragColor = vec4(fragmentColor, 1);
}

那么,我如何访问 RGB 值并更改它? 例如,如果窗口上的(u1,v1)和(u2,v2)处的像素值为(0,0,255),那么我想将它们更改为(255,0,0)

最佳答案

除了仅限 OpenGL ES 的扩展之外,片段着色器不能只从当前帧缓冲区读取。否则,我们就不需要 blending .

您也不能只渲染到着色器中读取的图像。因此,如果您需要进行某种后处理,那么最好通过渲染到单独的图像来完成。也就是说,您对图像 1 进行渲染,然后将其绑定(bind)为纹理并更改 FBO,以便渲染到图像 2。

或者,如果您有权访问 OpenGL 4.5/ARB/NV_texture_barrier ,那么你可以使用纹理屏障来处理这个问题。如果您将当前帧缓冲区的图像绑定(bind)为纹理,则这允许您单个读取/修改/写入过程。您可以在执行读取/修改/写入之前发出屏障,然后将该纹理绑定(bind)到采样器,同时仍然渲染到该帧缓冲区。

此外,这还要求 FS 从它要写入的精确纹理元素中读取。假设视口(viewport)锚定在 0,0,则代码为 texelFetch(sampler, ivec2(gl_FragCoord.xy), 0) 。您无法读取他人的纹理像素并对其进行修改。

显然你必须渲染到纹理;您不能为此使用默认帧缓冲区。

纹理屏障可用于从不同纹素读取和写入的情况。但这需要执行类似于切换绑定(bind)图像的第一种情况的操作。尽管您不需要完全更改 FBO;您可以更改渲染到的 FBO 区域。也就是说,只要您从与渲染目标不同的区域进行读取,并且在这些区域之间切换时适本地使用屏障,一切都很好。

关于opengl - GLSL : accessing framebuffer to get RGB and change it,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42016590/

相关文章:

unity3d - 根据世界空间中的光线转换命中位置绘制到对象的纹理上

c++ - 为什么在 C++ 顶点函数中有两个括号 [?

glsl - 使用GLSL在平面上渲染平滑的引用网格

glsl - 如何在 GLSL 着色器中实现颜色矩阵过滤器

c++ - OpenGL 跨平台窗口

opengl - 什么时候需要使用 OpenGL 函数加载器?

c++ - 我如何拍摄 stdafx.h?

OpenGL 原子计数器与 SSBO 中的原子

c++ - OpenGL 漫射照明问题

C++ Opengl Gsl 着色器性能问题