Opengl GLSL:访问帧缓冲区以获取RGB并对其进行更改

Opengl GLSL:访问帧缓冲区以获取RGB并对其进行更改,opengl,glsl,shader,Opengl,Glsl,Shader,我想访问帧缓冲区以获取RGB并更改每个像素的值。这是因为glReadPixels和glDrawPixels使用起来太慢,所以我应该使用着色器,而不是使用它们 现在,我编写代码,并成功地使用GLSL着色器显示三维模型 我画了两个立方体如下 .... glDrawArrays(GL_TRIANGLES, 0, 12*6); .... 和片段着色器: varying vec3 fragmentColor; void main() { gl_FragColor = vec4(fragmen

我想访问帧缓冲区以获取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,0255),那么我想将它们更改为(255,0,0)

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

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

或者,如果可以访问,则可以使用纹理屏障来处理此问题。如果将当前帧缓冲区的图像绑定为纹理,则允许执行单个读取/修改/写入过程。在执行读/修改/写操作之前,需要发出屏障,然后将该纹理绑定到采样器,同时仍渲染到该帧缓冲区

此外,这要求FS读取它将写入的确切texel。假设视口锚定在0,0,则此操作的代码为
texelFetch(采样器,ivec2(gl_FragCoord.xy),0)
。您无法读取其他人的texel并对其进行修改

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


纹理屏障可用于从不同的texel读取而不是写入的情况。但这需要做一些类似于切换绑定图像的第一种情况的事情。虽然你不需要完全改变FBO;可以更改渲染到的FBO区域。也就是说,只要您从渲染到的不同区域读取,并且在这些区域之间切换时使用适当的屏障,一切都很好。

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

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

或者,如果可以访问,则可以使用纹理屏障来处理此问题。如果将当前帧缓冲区的图像绑定为纹理,则允许执行单个读取/修改/写入过程。在执行读/修改/写操作之前,需要发出屏障,然后将该纹理绑定到采样器,同时仍渲染到该帧缓冲区

此外,这要求FS读取它将写入的确切texel。假设视口锚定在0,0,则此操作的代码为
texelFetch(采样器,ivec2(gl_FragCoord.xy),0)
。您无法读取其他人的texel并对其进行修改

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

纹理屏障可用于从不同的texel读取而不是写入的情况。但这需要做一些类似于切换绑定图像的第一种情况的事情。虽然你不需要完全改变FBO;可以更改渲染到的FBO区域。也就是说,只要您从不同的区域进行读取,而不是渲染到不同的区域,并且在这些区域之间切换时使用适当的屏障,一切都很好