GLSL:访问帧缓冲区以获取RGB并对其进行更改 [英] GLSL : accessing framebuffer to get RGB and change it

查看:533
本文介绍了GLSL:访问帧缓冲区以获取RGB并对其进行更改的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'd like to access framebuffer to get RGB and change their values for each pixel. It is because the glReadPixels, and glDrawPixels are too slow to use, so that i should use shaders instead of using them.

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

Now, I write code, and success to display three-dimensional model using GLSL shaders.

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

I drew two cubes as follows.

.... 
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)

Then, how can I access to RGB values and change it? For example, If the pixel values at (u1, v1) on window and (u2, v2) are (0,0,255), then I want to change them to (255,0,0)

推荐答案

除了仅OpenGL ES扩展,片段着色器不能仅从当前帧缓冲区读取.否则,我们将不需要混合.

With the exception of an OpenGL ES-only extension, fragment shaders cannot just read from the current framebuffer. Otherwise, we wouldn't need blending.

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

You also can't just render to the image you're reading from in a shader. So if you need to do some sort of post-processing, then that is best done by rendering to a separate image. That is, you do your rendering to image 1, then bind that as a texture and change the FBO so that you're rendering to image 2.

或者,如果您可以访问 OpenGL 4.5/ARB/NV_texture_barrier ,则您可以使用纹理屏障来解决这个问题.如果将当前帧缓冲区的图像绑定为纹理,这将允许您进行读/修改/写操作.在执行读/修改/写操作之前,您应该先发布障碍,然后将该纹理绑定到采样器,同时仍然渲染到该帧缓冲区.

Alternatively, if you have access to OpenGL 4.5/ARB/NV_texture_barrier, then you can use texture barriers to handle this. This permits you a single read/modify/write pass, if you bind the current framebuffer's image as a texture. You'd issue the barrier before doing your read/modify/write, then bind that texture to a sampler while still rendering to that framebuffer.

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

Also, this requires that the FS read from the exact texel that it would write to. Assuming a viewport anchored at 0,0, the code for this would be texelFetch(sampler, ivec2(gl_FragCoord.xy), 0). You can't read from someone else's texel and modify it.

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

Obviously you must be rendering to a texture; you cannot use the default framebuffer for this.

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

Texture barrier could be used for cases where you read from different texels than you write to. But that would require doing something similar to the first case of switching bound images. Though you wouldn't need to change the FBO exactly; you could change the region of the FBO that you render to. That is, so long as you're reading from a different area than you're rendering to, and you use barriers appropriately when switching between those regions, everything is fine.

这篇关于GLSL:访问帧缓冲区以获取RGB并对其进行更改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆