Steven Venham
Steven Venham

Reputation: 664

Opengl vao breaks during draw call

Currently I have a system that contains 2 buffers, one created CPU side and set to a buffer. and then one from a ssbo and populated from another shader.

Here is the struct for the ssbo data:

struct ssbo_data_t
{
    int maxcount = 1024;
    float baz[1024];
} ssbo_data;

Then the vao is build like:

//Build buffer
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, arraysize * sizeof(DATATYPE), dataarr, GL_DYNAMIC_DRAW);

//Build vao
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);

//index,size,type,norm,stride,pointerToFirst
glEnableVertexAttribArray(0);   //Position of light
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);

glEnableVertexAttribArray(1);   //Color
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)(sizeof(DATATYPE) * 2));

glEnableVertexAttribArray(2);   //Intensity
glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, 0, (void*)(sizeof(DATATYPE) * 5));

glEnableVertexAttribArray(3);   //Layer
glVertexAttribPointer(3, 1, GL_FLOAT, GL_FALSE, 0, (void*)(sizeof(DATATYPE) * 6));

//Try to bind ssbo for lighting data.
glBindBuffer(GL_ARRAY_BUFFER, ssbo);

glEnableVertexAttribArray(4);   //MaxSize
glVertexAttribPointer(4, 1, GL_INT, GL_FALSE, 0, (void*)offsetof(ssbo_data_t,maxcount));

glEnableVertexAttribArray(5);   //Corner Data
glVertexAttribPointer(5, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, (void*)offsetof(ssbo_data_t, baz));

My question is that if I set no stride for the one buffer, and then a stride for another part of the buffer it should work right? Or is there something i'm missing?

Cause when I actually preform the draw call, the first line is drawn, but all others have a position of -1,-1 Like the first buffer bound to the VAO was reset.

I am however receiving the correct potions from the other buffer, which shows it is working. Its like the first buffer is being unbound on the next draw call.

Due to how large the project is, I cant really post a working example.

Example

As you can see here, I place the primitive to the left and the other object to the right.

The primitive is drawn, and sets its corner positions to the SSBO.

The second object is then drawn and creates 4 line segments from its position.

The first vertex, works as expected, and creates a line segment from its position and terminates on the corner of the box, specified by the VAO.

The next draws don't read the position correctly. But do take the correct information from the ssbo. So... ?

Might be helpful if I posted the vertex shader:

#version 430 core
layout(location = 0) in vec2 aPos;
layout(location = 1) in vec3 aColor;
layout(location = 2) in float intensity;
layout(location = 3) in float layer;
layout(location = 4) in int maxcount;
layout(location = 5) in vec2 loc;

uniform vec2 screensize;

out VS_OUT{
    vec3 color;
    float intensity;
    vec4 targ;
} vs_out;

void main()
{
    vec2 npos = ((aPos - (screensize / 2.0)) / screensize) * 2; //Convert mouse chords to screen chords.
    gl_Position = vec4(npos, layer, 1.0);
    vs_out.targ = vec4(loc, layer, 1.0);
    vs_out.color = aColor;
    vs_out.intensity = intensity;
}

Upvotes: 1

Views: 318

Answers (1)

bernie
bernie

Reputation: 10390

To answer your question, yes you can mix and match strides and offsets in the same buffer and share vertex attribute data with an SSBO (Shader Storage Buffer Object).

Vertex stride

I'm not sure how you're trying to use the contents of the SSBO there. However, the binding of vertex attributes #4 and #5 looks fishy.

glVertexAttribPointer(4, 1, GL_INT, GL_FALSE, 0, (void*)offsetof(ssbo_data_t,maxcount));

The first vertex will have maxcount as expected in the x component. However, a stride of 0 means that consecutive vertex attributes are packed. The second vertex will therefore read 32 bits from baz[0] and treat that as an integer. The third will read baz[1] and so on. In short, only the first vertex will have the correct maxcount value and the rest will have bogus values.

To fix this, use instanced arrays (also known as vertex divisor). The function to use is glVertexAttribDivisor(). Another option is to bind your SSBO directly and read it as an SSBO (buffer type in GLSL). See the SSBO OpenGL wiki page for an example.

Finally:

glVertexAttribPointer(5, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, (void*)offsetof(ssbo_data_t, baz));

You can use a stride of 0 here because your attribute values are tightly packed. sizeof(float) * 2 gives the same result.

The (wrong) solution

I wrongly stated that BindVertexArray() resets the current GL_ARRAY_BUFFER binding. This is not the case. It does reset the indexed vertex buffer binding though but you already set those.

Upvotes: 3

Related Questions