Open GL Shader Storage Buffer Objects to replace Vertex Attributes - c++

I basically got the same question as the guy who asked here:
Dynamically sized arrays in OpenGL ES vertex shader; used for blend shapes/morph targets .
Especially his last unanswered question bothers me too.
So I also want to use an arbitrary number of blendshapes for each mesh I'm processing. At the moment I'm using a fixed number and treat the shapes as vertex attribute. The advantage here is that I always have the relevant data for the current vertex availiable. Now, if I want to use an arbitrary number of shapes, I figured I'd use SSBOs since their clue is exactly what I want: Dynamically sized data.
However SSBOs are, as far as I understand it, static and for each processed vertex in the shader I have the blendshape data for the whole mesh availiable. That means I would have to introduce some kind of counter and try to pick the correct data piece out of my SSBO for each vertex.
Is this understanding correct?
I'm really not sure whether this is the optimal solution, maybe you can give me some hints.

Yes your understanding is correct.
You can use gl_VertexID or just pass some 'vertex number' as attribute to know what data to load in your SSBO for the particular vertex you're processing.

Related

Opengl EBO/IBO not working [duplicate]

I have some vertex data. Positions, normals, texture coordinates. I probably loaded it from a .obj file or some other format. Maybe I'm drawing a cube. But each piece of vertex data has its own index. Can I render this mesh data using OpenGL/Direct3D?
In the most general sense, no. OpenGL and Direct3D only allow one index per vertex; the index fetches from each stream of vertex data. Therefore, every unique combination of components must have its own separate index.
So if you have a cube, where each face has its own normal, you will need to replicate the position and normal data a lot. You will need 24 positions and 24 normals, even though the cube will only have 8 unique positions and 6 unique normals.
Your best bet is to simply accept that your data will be larger. A great many model formats will use multiple indices; you will need to fixup this vertex data before you can render with it. Many mesh loading tools, such as Open Asset Importer, will perform this fixup for you.
It should also be noted that most meshes are not cubes. Most meshes are smooth across the vast majority of vertices, only occasionally having different normals/texture coordinates/etc. So while this often comes up for simple geometric shapes, real models rarely have substantial amounts of vertex duplication.
GL 3.x and D3D10
For D3D10/OpenGL 3.x-class hardware, it is possible to avoid performing fixup and use multiple indexed attributes directly. However, be advised that this will likely decrease rendering performance.
The following discussion will use the OpenGL terminology, but Direct3D v10 and above has equivalent functionality.
The idea is to manually access the different vertex attributes from the vertex shader. Instead of sending the vertex attributes directly, the attributes that are passed are actually the indices for that particular vertex. The vertex shader then uses the indices to access the actual attribute through one or more buffer textures.
Attributes can be stored in multiple buffer textures or all within one. If the latter is used, then the shader will need an offset to add to each index in order to find the corresponding attribute's start index in the buffer.
Regular vertex attributes can be compressed in many ways. Buffer textures have fewer means of compression, allowing only a relatively limited number of vertex formats (via the image formats they support).
Please note again that any of these techniques may decrease overall vertex processing performance. Therefore, it should only be used in the most memory-limited of circumstances, after all other options for compression or optimization have been exhausted.
OpenGL ES 3.0 provides buffer textures as well. Higher OpenGL versions allow you to read buffer objects more directly via SSBOs rather than buffer textures, which might have better performance characteristics.
I found a way that allows you to reduce this sort of repetition that runs a bit contrary to some of the statements made in the other answer (but doesn't specifically fit the question asked here). It does however address my question which was thought to be a repeat of this question.
I just learned about Interpolation qualifiers. Specifically "flat". It's my understanding that putting the flat qualifier on your vertex shader output causes only the provoking vertex to pass it's values to the fragment shader.
This means for the situation described in this quote:
So if you have a cube, where each face has its own normal, you will need to replicate the position and normal data a lot. You will need 24 positions and 24 normals, even though the cube will only have 8 unique positions and 6 unique normals.
You can have 8 vertexes, 6 of which contain the unique normals and 2 of normal values are disregarded, so long as you carefully order your primitives indices such that the "provoking vertex" contains the normal data you want to apply to the entire face.
EDIT: My understanding of how it works:

Custom Vertex Attributes GLSL

I want to make a couple of vec4 vertex attributes in my shaders. I've done quite a bit of googling, but I can't seem to find consistent information for specifically what I want to do.
My goal here is to move skinning to the GPU, so I need a list of bones and weights per vertex, hence why I want to use vertex attributes. I have 2 arrays of floats that represent this data. Basically this:
weightsBuffer = new float[vSize*4];
indexesBuffer = new int[vSize*4];
The part that I can't consistently find is how to upload these and use them in the shader. To be clear, I don't want to upload all the position, normal and texture coordinate data, I'm already using display lists and have decided to keep using them for a few reasons that aren't relevant. How can I create the buffers and bind them properly so I can use them?
Thanks.
Binding your bone weights and indices is no different of a process than binding your position data. Assuming the data is generated properly in your buffers, you use glBindAttribLocation to bind the attribute index in your vertex stream to your shader variable, and glVertexAttribPointer to define your vertex array (and don't forget glEnableVertexAttribArray).
The exact code may vary, depending on whether you're using VAOs and VBOs (or just client buffers). If you want a more specific answer, you should provide your code and shader.

OpenGL vertex array pointers, different buffers per component

A bit of context :
I'm working on a GPU emulator (the NV2A if you want to know) at the push-buffer level, and I'm trying to implement the drawing using OpenGL. The GPU commands that I have to emulate contain separate pointers for each vertex component (so positions are in an entirely different memory address than fog coordinates, colors, texture coordinates, etc.)
Other data, like vertex component size, type and stride are also present in the push-buffer, but those are not really relevant to this question.
I've been reading about Vertex Array Objects, but as far as my tests go, the pointers you can set with glVertexAttribPointer should all be relative to a Vertex Buffer Object - something I would like to avoid, as I've already got a copy of the data in memory.
The question :
Is it possible in OpenGL to draw vertices using separate pointers (not managed by any OpenGL API) per vertex component? And how would the code look like, roughy?
PS: Since I'm emulating a GPU, I have to take vertex shader programs into account too. I haven't worked on these yet, so any suggestion on that is welcome too. TIA!
You don't need to use VBOs, glVertexAttribPointer takes a normal CPU-pointer if no VBO is bound (you can call glBindBuffer(GL_ARRAY_BUFFER, 0) to make sure). And yes, you can set up one address per attribute stream.

OpenGL 3.3, GLSL 1.5: How to setup a Texture Buffer Object containing various texture2D?

I've been wondering whether it is possible to have an array of sampler2D in a GLSL 1.5 vertex shader.
I need to access 30 different 2d-textures from my vertex shader. I read that it is not possible to have a structure like:
uniform sampler2d texture[30];
However, having 30 different uniforms is a bit exaggerated and fairly hard to manage...
So, that brought me to the idea of having a texture buffer object. TBO's are supported since OpenGL 3.0. However, I couldn't find a good tutorial or example, respectively, which shows how to initialize a TBO with not only one texture, but several textures.
This website shows an example on how to initialize a TBO with a single texture. No big deal at all. I think the most important method is
void createTBO(GLuint* tbo, GLuint* tex)
By executing the method
glTexBufferEXT(GL_TEXTURE_BUFFER_EXT, GL_RGBA32F_ARB, *tbo);
one can actually attach the texture to the buffer. This is also mentioned here. I assume calling glTexBuffer 30 times one after the other wouldn't do the trick.
So, I've been thinking if there might be another way of getting the very same result. I came up with two ideas:
Adding the 30 2d-textures to a 3d-texture and attach that directly to the vertex shader. However, that would be a big waste of memory since most of the 3d-texture's layers wouldn't be used.
Using a structure called sampler2DArray. It is mentioned in the specs. However, I searched the web and couldn't find any valuable information about how to implement that.
So, my questions are:
How do I setup a TBO containing more than only 1 texture?
Is that possible at all?
Do you know sources where I could find information about adding 2d-textures to a 3d-texture?
Do you know websites where I could find information about the initializing, binding and usage of sampler2DArray?
I'd be grateful if you could advice me. I'm really a newbie in terms of OpenGL.
Thanks
Walter
I believe you misunderstood what a Texture Buffer Object (TBO) is. A TBO is used to access a buffer object inside a shader, nothing more. It doesn't hold multiple textures or anything like that.
If the textures are of the same size, you can use a 3D texture or a Texture array. A TBO is no use for your problem.
You could use sampler2DArray uniforms. You can use them to pass multiple textures to your shader.
http://www.opengl.org/registry/specs/EXT/texture_array.txt
An alternative solution would be to use a very large tbo and store all textures within the tbo. A Texture can be as large as 11585x11585 texels (2^27)
texture_buffer_object.txt
As Jotschi suggested use one very large texture and adjust texture coordinates accordingly. (or: write a shader that maps standard coordinates to the right place)
This is what's called a texture atlas. I'd guess you can find some implementations by searching for the term.

Managing OpenGL VBO's and color

I'm creating an app that uses VBO's for drawing. The app draws line segments of multiple colors. Therefore, I'm creating a vertex and index array for each color, and sorting the segments into the appropriate array by color.
However, I'd like the user to be able to set the color of any line segment. Therefore, my potential number of colors is virtually unlimited (obviously not really, but it might as well be). I'm guessing that generating say 2,000 VBO's to hold 1,000 vertex and index arrays to support 1,000 colors would not be a good thing.
Obviously one could generate a limited number of VBO's and copy new data in each time it was time to draw a new color's vertex array, but that seems incredibly inefficient.
Any suggestions for handling this situation?
Well, considering you're not saying what's in the vbo exactly (position? color?) or how you end up drawing (fixed function? program?) it's not exactly trivial to help.
Anyways, here are some facts you want to keep in mind:
you don't have to create many vbos. VBO (just like IBO) is for storage, it can store any arbitrary number of data sets. This is helped by the "firstIndex/firstVertex" parameters of the various Draw functions and other offsets of the gl*Pointer
your color does not have to be specified per-vertex. If you store it inside the VBO, get it out, and use constant colors (how to do that depends on your drawing method. For programs, specify color through a uniform rather than an atribute)
There, I hope that's enough for you to start.