pouët.net

Accessing VBO in vertex shaders

category: code [glöplog]
 
Hi,

I'm trying to get access to a VBO from inside a vertex shader. At the moment I have a valid buffer which I bind as

glBindBuffer(GL_ARRAY_BUFFER, BufferA);

This buffer is quite large (about 0.5m - I hope that's not a problem). I want to access this in the vertex shader as I would with an array (of xyzw structs or consecutive floats) so that I can iterate through them. Is this possible?

I thought that something like this would be the first step (in GLSL):

layout(std140) uniform TheVBO {
float x;
float y;
float z;
float w;
};

and

float myx = TheVBO[index].x



and then accessing through (in C:)

int ind=glGetUniformBlockIndex (programHandle, "TheVBO");


(I would assume I know what to do from that point on). But nothing works of course.... any ideas?
added on the 2013-05-20 21:09:19 by Navis Navis
You can use TBOs and access the buffer via texelFetch.
Besides you could also use SSBOs (if you really need structs) or "Images"(imageStore/imageLoad).

If you only need read access and your struct is nothing really fancy I would go for TBOs.

Code: struct TBO { TBO() : tbo(0), texture(0) {} GLuint tbo; GLuint texture; }; TBO createTBO(GLuint sizeInBytes, const void* data, GLuint usage, GLuint internalformat) { TBO tbo; glGenBuffers(1, &tbo.tbo); glBindBuffer(GL_TEXTURE_BUFFER, tbo.tbo); glBufferData(GL_TEXTURE_BUFFER, sizeInBytes, data, usage); glGenTextures(1, &tbo.texture); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_BUFFER, tbo.texture); glTexBuffer(GL_TEXTURE_BUFFER, internalformat, tbo.tbo); glBindBuffer(GL_TEXTURE_BUFFER, 0); return tbo; } void bindTBO(TBO& tbo, unsigned int texture) { glActiveTexture(texture); glBindTexture(GL_TEXTURE_BUFFER, tbo.texture); }


Setup the proper uniforms for the samplers &
use a gsamplerBuffer then to access your texture via texelFetch.
You can directly fetch vec4's.

You could first create the "VBO" as TBO and then use glBindBuffer in order to use it as GL_ARRAY_BUFFER if you need to do so. TBOs can be up to 512 MB in recent NV implementations.
added on the 2013-05-20 21:29:26 by las las
(You are currently trying to bind the thing as UBO or something like that... I don't think that's so much of a good idea)
added on the 2013-05-20 21:30:59 by las las
I think I get it. I need to pass as a texture buffer, read as 4xfloat and sample in the shader as if it was a normal texture. I ll try tm , many thanks. Lets hope it works.
added on the 2013-05-20 23:24:51 by Navis Navis
It usually works ;). If not, feel free to ask for more details.
added on the 2013-05-20 23:38:16 by las las
I can't believe my luck but this combination seems to work (for future reference):


--------- Initialize

glGenBuffers(1, &BufferA);
glBindBuffer(GL_ARRAY_BUFFER, BufferA);
glBindBuffer(GL_TEXTURE_BUFFER, BufferA);
glBufferData(GL_ARRAY_BUFFER, sizeof(MyVertex)*m_X*m_Y, 0, GL_STREAM_DRAW);


glGenTextures (1,&TextureBufferA);
glBindTexture (GL_TEXTURE_BUFFER,TextureBufferA);
glTexBuffer (GL_TEXTURE_BUFFER, GL_RGBA32F_ARB,BufferA);
glBindBuffer(GL_ARRAY_BUFFER, 0);


--- then


glActiveTexture(GL_TEXTURE5);
glBindTexture(GL_TEXTURE_BUFFER, TextureBufferB);
my_sampler_uniform_location = glGetUniformLocation(programHandle, "Positions");
glUniform1i(my_sampler_uniform_location, 5);


--- and in shader

uniform samplerBuffer Positions;

texelFetch (Positions, gl_VertexID+1).xyz;



Not sure about that

glTexBuffer (GL_TEXTURE_BUFFER, GL_RGBA32F_ARB,BufferA);

though... shouldn't that be TextureBufferA? (in which case it doesn't work)

added on the 2013-05-21 10:21:17 by Navis Navis
Nope it shouldn't - a TBO consists of a texture (you call it TextureBufferB) and a "bufferobject" (BufferA). You can bind that buffer thing as almost everything else (e.g. GL_ARRAY_BUFFER). glTexBuffer expects the "bufferobject" of the TBO as parameter. Everything should be fine.
added on the 2013-05-21 11:41:39 by las las
Replace TextureBufferB with TextureBufferA in my post above.

You are using two TBOs? ;) B should also be A in your post in the "--then" snippet.
added on the 2013-05-21 11:45:05 by las las
yeah, everything seems to be fine apart from the fact that it fails to work sometimes - and this is pretty much not easy to reproduce. For example:

texelFetch (TheVBO,0).xyz;

this will work
but not this:

texelFetch (TheVBO,1).xyz;

although I have seen under slightly different code both working.

It is as if I'm reading from the same buffer I'm writing to, although it can't be the case as I've tried all possible combinations.


added on the 2013-05-21 12:07:16 by Navis Navis
basically the very same code will work one time but not the other.
added on the 2013-05-21 12:09:06 by Navis Navis
Well it should work. I don't know your complete codebase, so it is kind of hard to judge where that happens.

If you want to discuss it in private - you can find me on IRC in one of the common demoscene channels on IRCnet.
added on the 2013-05-21 12:17:15 by las las
thanks for the offer, I think I can find out myself what is wrong - as you say, the code is pretty straightforward (for setting up the buffer objects). I believe that there must be some problem with the ping-ponging of the buffers - I am using 2. It's just a shame that the very same code produces different results each time, something that I haven't seen before!
added on the 2013-05-21 12:22:24 by Navis Navis
I actually wonder what happens if you go out of bounds with the texelFetch?
added on the 2013-05-21 12:35:48 by Navis Navis
Navis: undefined behaviour. as far as i remember, under nvidia you either get corrupt output or total lack of thereof - depends what you're doing.
added on the 2013-05-21 13:00:59 by kbi kbi
yeah I guess that must be it, so nothing to do with the VBOs themselves... :-)
added on the 2013-05-21 14:08:25 by Navis Navis
anyway, thanks again, I think I solved it. Coming to a demo near you soon...
added on the 2013-05-24 11:31:36 by Navis Navis
Wheeeeeeeeeee! Le Navis is BACK! :D
added on the 2013-05-24 14:56:18 by rez rez

login