开发者

Setting neighbor fragment color via GLSL

I need to setup a GLSL fragment shader to change the color of a fragment other than the one currently being processed. Since that may not seem desirable, I'll provide a very brief context.

The project utilizes a render pass whereby a given model is drawn into an FBO w开发者_运维技巧ith unique colors that correspond to UV coordinates in the texture map. These colors are then sampled and converted to image coordinates so that the texture map for the model can be updated based on what's visible to the camera. Essentially:

Render model to FBO
For each FBO pixel
   1. sample secondary texture based on FBO pixel position
   2. convert color at current pixel to image coordinate for the model's texture map
   3. update model's texture with sampled secondary texture at calculated coordinate
End loop

The problem is that the current implementation is very CPU bound, so I'm reading the pixels out of the FBO and then manipulating them. Ideally, since I already have the color of the fragment to work with in the fragment shader, I want to just tack on the last few steps to the process and keep everything on the GPU.

The specific issue I'm having is that I don't quite know how (or if it's even possible) to have a fragment shader set the color of a fragment that it is not processing. If I can't work something up by using an extra large FBO and just offsetting the fragment that I want to set the color on, can I work something up that writes directly into a texture?

Any help/advice?


It's not possible to have a fragment shader write to anywhere other than the fragment it is processing. What you probably want to do is ping pong rendering.

In your code, you'd have three textures, matching your listed tasks:

  1. the secondary texture
  2. the source model texture map
  3. the destination model texture map

At a first run, you'd use (1) and (2) as source textures, to draw to (3). Next time through the loop you'd use (1) and (3) to write to (2). Then you'd switch back to using (1) and (2) to write to (3). And so on.

So (2) and (3) are connected with framebuffer objects with the textures supplied as the colour buffer in place of a renderbuffer.

NVidia authored the GL_NV_texture_barrier extension in 2009 that allows you to compact (2) and (3) into a single texture, provided you are explicit about the dividing line between where you're reading and where you're writing. I don't have the expertise to say how widely available it is.

Attempting to read and write to the same texture (as is possible with FBOs) otherwise produces undefined results in OpenGL. Prompting issues at the hardware level are related to caching and multisampling.


As far as I understand, you need a scatter operation (uniform FBO pixel space -> random mesh UV texture destination) to be performed in OpenGL. There is a way to do this, not as simple as you may expect, and not even as fast, but I can't find a better one:

  • Run a draw call of type GL_POINTS and size equal to the width*height of your source FBO.
  • Select model texture as a destination FBO color layer, with no depth layer attached
  • In a vertex shader, compute the original screen coordinate by using gl_VertexID.
  • Sample from the source FBO texture to get color and target position (assuming your original FBO surface was a texture). Assign a proper gl_Position and pass the target color to the fragment shader.
  • In a fragment shader, just copy the color to the output.

This will make GPU to go through each of your original FBO pixels and scatter the computed colors over the destination texture.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜