PDA

View Full Version : how to create an attribute array for primitves



miujin
03-07-2012, 06:23 AM
Hello,

I use VBOs with an element array and Shader to render my data. In the fragment shader I want to have access to an array which stores information for every primitive (visible, selected, ...). I've tried to stores these information as part of the vertex array, but there is the problem, that I can't set informations for the primitives, only for the vertices.
My idea now is, to write an array with integers in the GPU memory and access to the values in the fragment shader with the help of the GL_PRIMITIVE_ID.

My problem is, that I don't know which technology is the best way to implement this functionality. I think a good way is to use one of the possible Buffer Objects (TBO, UBO,...) or to create a texture an access to the information. I want to know which technique I have to use or is there a way to send an array to GPU memory an access them like to VBOs (glMapBuffer). Or is there an easier way to solve the problem?

menzel
03-07-2012, 06:39 AM
If this array would not be too large, a UBO would work (i think 64k is the minimum size limit), you can also update a UBO with MapBuffer/UnmapBuffer. If the data gets larger, texture would also work. There are performance differences here depending on the access pattern (afaik texture access is slower than UBO access in general, but if you have a lot of texture cache hits that can be as fast as UBOs.
You could fetch your information in a geometry shader, so you only have to fetch it once per primitive instead of once per fragment.

Kopelrativ
03-07-2012, 11:40 PM
In the fragment shader I want to have access to an array which stores information for every primitive (visible, selected, ...). I've tried to stores these information as part of the vertex array, but there is the problem, that I can't set informations for the primitives, only for the vertices.

Storing data for vertices instead of primitives would duplicate information. It is a classical problem for normals. If you are using GL_TRIANGLES, you would duplicate every primitive data times 3.

However, that is the simple solution that can work quite well. If you combine it with indexed drawing (e.g. glDrawElements), the actual number of vertices can be reduced. It depends on your performance requirements.

miujin
03-08-2012, 01:51 AM
If this array would not be too large, a UBO would work (i think 64k is the minimum size limit), you can also update a UBO with MapBuffer/UnmapBuffer. If the data gets larger, texture would also work. There are performance differences here depending on the access pattern (afaik texture access is slower than UBO access in general, but if you have a lot of texture cache hits that can be as fast as UBOs.
You could fetch your information in a geometry shader, so you only have to fetch it once per primitive instead of once per fragment.


Ok with the 64 kB the UBO is not so good. I visualize models with millions of triangles and so the UBO is to small. Implement a geometry shader would also be a option, but at the moment I have no need for a geometry shader. If I have a 3 million triangle model i have more fetches in the geometry shader than in den fragment shader. So this would also be not so good.



Storing data for vertices instead of primitives would duplicate information. It is a classical problem for normals. If you are using GL_TRIANGLES, you would duplicate every primitive data times 3.
However, that is the simple solution that can work quite well. If you combine it with indexed drawing (e.g. glDrawElements), the actual number of vertices can be reduced. It depends on your performance requirements.

I know that problem. I get the data from a STL file, so every triangle stores information for 3 vertices. So I have duplicate information. I have a function which remove all duplicate vertices and create an index array, so I use indexed drawing. The problem now is, that I can only store information for the vertices, for example if I store the information 'selected' to the 3 vertices of a triangle, all triangles which have one of these vertices get 'half-selected'. So now I need something to store information (e.g. in the form of an integer array) for every triangle independent from the vertices.

Kopelrativ
03-08-2012, 09:04 AM
The problem now is, that I can only store information for the vertices, for example if I store the information 'selected' to the 3 vertices of a triangle, all triangles which have one of these vertices get 'half-selected'. So now I need something to store information (e.g. in the form of an integer array) for every triangle independent from the vertices.

I see, if you need all this information with the vertex data, every vertex can only be used for one triangle, and the meaning of using indexed drawing is lost?

Do you want the ability to select one, or more, primitives, that shall then be highlighted some way in the fragment shader?

One way to do this could be to: Include a triangle ID (number) with each vertex. All vertices would be unique, meaning indexed drawing doesn't help. Use glDrawBuffer() instead. The triangle ID is forwarded from the vertex shader to the fragment shader. A uniform is used to tell the fragment shader the ID of the triangle currently selected.

tonyo_au
03-08-2012, 03:41 PM
Have you looked at glTexBuffer. I am looking at it at the moment for a similar problem.

miujin
03-12-2012, 05:28 AM
What I want is to have some information about every triangle in the fragment shader, but furthermore I want to use indexed drawing.

Now I have a way how it works, but not perfect. I use the texture buffer to store the information in the R value. The problem now is, that I cannot write an integer in the value. I've read somewhere that this is a driver implementation error and that only float values work with texture buffer. Does anybody know something about the error and know if there is a way to fix it?
The reason why I want to have integers there is, that I want to set the several bits to an information e.g. Bit1 - Selected, Bit2 - Invisible, Bit3 - Transparent, ...

Ilian Dinev
03-12-2012, 01:16 PM
Because the per-triangle data can change often, and there are many triangles, TBOs are the way to go.
To go around the driver-bug, meanwhile just use GL_RED8 and

float fval = texelFetch(texbuf, gl_PrimitiveID).r;
int ival = int(fval * 255.0);

tonyo_au
03-12-2012, 09:06 PM
Have you thought of creating a float texture so no normalising is done but storing the int value without conversion

eg
union FloatInt
{
int i;
float f;
};


then use floatBitsToInt to read the texture in the shader