How to write into arbitrary position of a texture?

Hello everyone~~

This problem bothered me for days…

I have two textures which we could name it ‘Tex1’ and ‘Tex2’ respectively. The two textures have different resolution.

Each texel in Tex1 contains a ‘data’ field and an ‘Index’ field(which will be used next).

Now I want to traversal every texel in Tex1 in GPU to retrieve the ‘data’ and ‘Index’. Then write ‘data’ into specific postion of Tex2 according to the ‘Index’ retrieved before.

For a simple example, we retrieved ‘0.1’ and ‘1’ for ‘data’ and ‘Index’ from Tex1 respectively, then I want to write ‘0.1’ into the '1’st texel in Tex2.

How could I achieve that via vertex and fragment shaders.

I’ve read a paper which use each texel in Tex1 as a vertex in vertex shader(some ‘texture to vertex arrays’ technique I never heared), retrieve data and index, send data to the ‘right’ place according to the index. Then use a fragment shader to write the data received into framebuffer. The frame buffer have the same resolution of Tex2.

The paper didn’t tell the details. And I’m so confused about how to “send data to the right place according to the index” in a vertex shader?

Any suggestions about this requirement?

Are you able to invert the index ?
If instead of destination index it is a source index, the problem is solved : for each fragment, sample tex1 at current fragment once to get srcindex, then sample tex1 again at srcindex to get data to store.

Back to your original question : “send data to the right place according to the index” can mean change vertex position according to index. Imagine drawing a bunch of points, all have coordinate 0,0 but vertex shader samples tex1 index to change coordinates.

Hi ZbuffeR. Thanks for your suggestion.

Here is a problem: Tex1 and Tex2 have different resolutions(say 88 and 128128 respectively), so the frame buffer and tex1 have differnt resolutions(because framebuffer should have the same resolution of Tex2 in my opinion). So we cannot ‘sample tex1 at current fragment once to get srcindex’, if I got your suggestion right.

yep, my first guess is that too. But still the same problem: the number of vertexes and the number of fragments are not equal. They have no one-to-one corresponding relation. How to make each fragment get the right data after rasterization?

Thanks again~ :wink:

Indeed the inverted index would need to have the same resolution as Tex2.

Regarding the second solution : number of vertices and fragments are not equal, and that is a good thing.
Say you have 64 vertices (8x8), rasterized to a 128x128 viewport (will end up as Tex2).
The vertex shader samples from the 8x8 Tex1. Problem solved.

GPU are historically good at gather (sample n textures with m different texture coordinates), and bad at scatter (only write to current fragment). There is some progress to add scatter capabilities but not sure on which hardware it can work.

Did you investigated using OpenCL instead of OpenGL ?

Render as many points as Tex1.size_x * Tex1.size_y and give each point a position corresponding to a texel in Tex1. So your points have positions:

(0, 0)
(1, 0)
(2, 0)

In the vertex shader perform a lookup into Tex1 at the current vertex position to retrieve ‘data’ and ‘index’.
Use ‘index’ to calculate a new vertex position, i.e. the position in Tex2 you want to write to and pass ‘data’ to the fragment shader.
In the fragment shader write data to the current position.

Of course you will only write to Tex1.size_x * Tex1.size_y many texels of Tex2, but I understand that is what you want, no?
Otherwise I think you need to tell us what data you want to write to texels in Tex2 that are not directly indexed by Tex1 (because if Tex1 is smaller, as in your example, there simply are not enough indices in it to write to all texels of Tex2 :wink: ).

Thanks guys~

In my opinion you two suggested almost the same way, right? :slight_smile:

But I think there is another problem here: (so sad~~)
Vertex number is less than fragment number. Therefore, the rasterizer will do some interpolation between vertexes.

For example, after the vertex shader, fragment 1 receives the data ‘0.1’, fragment 3 receives the data ‘0.3’. Then fragment 2 will receive the data ‘0.2’ because of the interpolation. But actually fragement 2 should receive ‘0’ as I want.

I hope I expressed myself clearly~ :slight_smile:

How do you think?

In my opinion you two suggested almost the same way, right?

yes, ZBufferR must have answered while I was still typing :slight_smile:

Vertex number is less than fragment number. Therefore, the rasterizer will do some interpolation between vertexes.

For example, after the vertex shader, fragment 1 receives the data ‘0.1’, fragment 3 receives the data ‘0.3’. Then fragment 2 will receive the data ‘0.2’ because of the interpolation. But actually fragement 2 should receive ‘0’ as I want.

That is why you set the primitive type to GL_POINTS in your draw call instead of GL_TRIANGLES, GL_LINES etc. Interpolation only happens for fragments that are “between” vertices (e.g. the fragments between the two endpoints of a GL_LINES segment or in the middle of a GL_TRIANGLES).

Basically you can ask yourself: which vertices should be considered for interpolation when rendering POINTS? The current one and the next, the previous, both, all points submitted in a draw call? As you see the question does not really make sense for points, while for triangles it is clear that all three vertices that make up the triangle should be considered.

Ahha~~ Thank you lovely guys~~

After one night sleep, I realize that I asked a stupid question~ :slight_smile:

You guys really helped me out~ Cheers~