How to use texture buffers to read a single integer instead of vec4
Asked Answered
C

1

9

I have a working code where I am reading vec4 values in the shader from a texture buffer.

On the client side, I create a buffer of displacement vectors:

vec4 vector1 : vec4(x1, y1, z1, w1);
vec4 vector2 : vec4(x2, y2, z2, w2);
vec4 vector3 : vec4(x3, y3, z3, w3);
..

then I create a vertex buffer that contains vector1, vector2, vector3....

next, I create a texture and bind the above buffer to it using:

glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, bufferID);

I chose GL_RGBA32F because each of x1, y1, z1, w1, etc are float.

in the shader I can fetch the individual vectors using:

vec4 vector1 = texelFetch(samplerObj, 0);
vec4 vector2 = texelFetch(samplerObj, 1);
.
.

But, now suppose my displacement vector is not a vec4, but a single integer. i.e

int vector1 = x1; //(int is 32 bit unsigned)
int vector2 = x2; //(int is 32 bit unsigned)

can somebody please tell what will be the corresponding internalFormat be? is it

glTexBuffer(GL_TEXTURE_BUFFER, GL_R32UI, bufferID);

also how will I fetch the value using texelFetch in shader? is it

int vector1 = texelFetch(samplerObj, 0);

or

int vector1 = texelFetch(samplerObj, 0).r ?

I am confused because texelFetch should return a texel that has 4 components, so must I use the red component of the result?

Catabasis answered 6/9, 2013 at 6:57 Comment(4)
I don't know about samplerBuffers but for image_load_store, the internal format must match the layout() statement and when you call imageLoad() it always returns a vec4/uivec4/ivec4 etc. If it doesn't have 4 components you ignore the rest and as you say, just read .r for example. I'm just speculating here but maybe this means it's better to read in 16 byte blocks.Stelle
@jozxyqk: There is no such thing as a format qualifier for non-image uniform layouts.Inalterable
@Inalterable which is why I began with "I don't know about samplerBuffers". I'm attempting to give my knowledge about something similar. It doesn't match exactly but maybe there's some overlap. Does texelFetch implicitly index a usamplerbuffer with internal format GL_R32UI in strides of 4 bytes and leave the gba of rgba undefined? I don't know.Stelle
@jozxyqk: If you use a sampler which doesn't match the internal format, values returned by texture lookup functions will be undefined. So, for floating-point formats you use a sampler*, for non-normalized int- and uint-formats you use an isampler* or usampler* respectively.Inalterable
I
11

You already mentioned the correct sized internal format for unsigned ints: R32UI. The permissible formats are enumerated in table 8.15, found in section 8.9 of the OpenGL 4.4 Core Profile Specification. Please note that the contents of the buffer store will not be normalized when using texelFetch on a buffer texture with the above internal format! That means, you don't get values in the range [0, 1] but in the range [0, 2^(n-1)] when doing lookups.

Instead of a samplerBuffer you will also need a usamplerBuffer.

If you do a texelFetch on a samplerBuffer with an internal format of R32UI, as specified in the aforementioned table, will return an uvec4 where the components returned will contain the following values: uvec4(R, 0, 0, 1).

int vector1 = texelFetch(samplerObj, 0);

This will lead to a compile-time error, because there is no implicit conversion from uvec4 to int.

int vector1 = texelFetch(samplerObj, 0).r;

this swizzle-mask will return the R-component of the uvec4 returned by texelFetch and do an implicit conversion from uint to int. Semantically, it also doesn't make sense to name a scalar value a vector. ;)

What you actually want is something like

uint displacement = texelFetch(samplerObj, 0).r;

where samplerObj is a usamplerBuffer.

EDIT: Just to clarify, texelFetch will always return a gvec4 - where g will simply by empty (fixed- and floating-point formats), i or u. How the vector is filled depends on the internal format of the buffer texture. If you choose R32F, you'll get a non-normalized vec4(R, 0, 0, 1), for RGBA16 you'll get a normalized vec4(R, G, B, A).

To avoid further confusion: you don't allocate memory for 4-component vectors when using a single-component format! They're all only expanded to a gvec4 on lookup!

Inalterable answered 6/9, 2013 at 9:6 Comment(2)
I believe a big part of the questions is referring to the fact that texelFetch does always return a 4 component vector. If you texelFetch(samplerObj, 0).r, that gives the first element. Does texelFetch(samplerObj, 1).r give you the second or the 5th element? Is the answer to that question dependent on the internal format? For example if the internal format was GL_R32UI it would be understandable if it returns the second element and GL_RGBA32UI causes the 5th unsigned int to be returned. Image_load_store requires an explicit layout declaration, is it similar for a samplerBuffer but implicit?Stelle
@jozxyqk: See my edit. You will get the first and the second element in the data store. Incrementing the texcoord by one will always give you the next element, since a buffer texture is essentially backed by a 1D array (the data store of the buffer object).Inalterable

© 2022 - 2024 — McMap. All rights reserved.