Providing Data in OpenGL: Vertices and Computing Shaders

I want to be able to enter a bunch of vertices into my graphics program, and then I want to be able to do the following for them:

  • Use them in the graphical part of OpenGL, especially in Vertex Shader.
  • Perform physical calculations on them in a computational shader.

According to these requirements, I realized that I needed a structure in which I store my vertices and can access them correctly, I thought about the following:

  • Arraybuffers
  • Textures (as when storing information, not for texturing)

However, I thought and came up with the flaws of both options:

ArrayBuffers:

  • I'm not sure how my Compute Shader can read, not to mention changing the vertices. But I know how to draw them.

Textures:

  • I know how to modify them in Compute Shaders, however I'm not sure how to draw from the texture. More specifically, the number of elements to be drawn depends on the number of recorded (data is not zero) elements in the texture.

I may have missed some important other functions that I need, as the real question is:
How to create vertices that are on the GPU and which I can get in Vertex and in Compute Shader?

+6
source share
1 answer

Hopefully this fixes a few misconceptions and gives you a slightly better idea of ​​how the general-purpose shader repository is configured.

What you need to understand is how buffer objects really work in GL. You often hear people discern things like vertex buffer objects and unified buffer objects. In fact, there is no fundamental difference - the buffer object is processed the same way, regardless of what it stores. This is just a general data warehouse, and it takes on special meaning as long as it is tied to a specific point (for example, GL_ARRAY_BUFFER or GL_UNIFORM_BUFFER ).

Do not think about special vertex buffers located on the GPU, think more generally - this is actually unformatted memory that you can read / write if you know the structure. Calls of type glVertexAttribPointer (...) describe the data structure of the buffer object enough for glDrawArrays (...) to significantly pull the vertex attributes from the buffer object memory for each vertex shader call.

You need to do the same to calculate the shaders, as shown below. To fully understand the following data structure, you need to familiarize yourself with the rules described in 7.6.2.2 - the standard format of a single unit .

A description of the vertex data structure using Shader storage blocks can be done as follows:

 // Compute Shader SSB Data Structure and Buffer Definition struct VtxData { vec4 vtx_pos; // 4N [GOOD] -- Largest base alignment vec3 vtx_normal; // 3N [BAD] float vtx_padding7; // N (such that vtx_st begins on a 2N boundary) vec2 vtx_st; // 2N [BAD] vec2 vtx_padding10; // 2N (in order to align the entire thing to 4N) }; // ^^ 12 * sizeof (GLfloat) per-vtx // std140 is pretty important here, it is the only way to guarantee the data // structure is aligned as described above and that the stride between // elements in verts[] is 0. layout (std140, binding = 1) buffer VertexBuffer { VtxData verts []; }; 

This allows the interleaved vertex buffer to be used in a computational shader with the data structure indicated above. You have to be careful with data alignment when you do this ... you could accidentally use whatever alignment / step you wanted for an array of alternating vertices, but here you want to comply with the std140 layout std140 . This means that using ternary vectors is not always a wise use of memory; you need things that need to be aligned at the borders of N ( float ), 2N ( vec2 ) or 4N ( vec3 / vec4 ), and this often requires input pads and / or smart data packaging. In the above example, you can put the entire three-component vector value of the data into the entire space spent by the empty alignment.

Pseudo code showing how the buffer will be created and bound for double use:

 struct Vertex { GLfloat pos [4]; GLfloat normal [3]; GLfloat padding7; GLfloat st [2]; GLfloat padding10 [2]; } *verts; [... code to allocate and fill verts ...] GLuint vbo; glGenBuffers (1, &vbo); glBindBuffer (GL_ARRAY_BUFFER, vbo); glBufferData (GL_ARRAY_BUFFER, sizeof (Vertex) * num_verts, verts, GL_STATIC_DRAW); glVertexAttribPointer (0, 4, GL_FLOAT, GL_FALSE, 48, 0); // Vertex Attrib. 0 glVertexAttribPointer (1, 3, GL_FLOAT, GL_FALSE, 48, 16); // Vertex Attrib. 1 glVertexAttribPointer (2, 2, GL_FLOAT, GL_FALSE, 48, 32); // Vertex Attrib. 2 glBindBufferBase (GL_SHADER_STORAGE_BUFFER, 1, vbo); // Buffer Binding 1 
+10
source

All Articles