PDA

View Full Version : how to bind two vertex buffers to vertex shader input, as in DirectX



saman_artorious
06-26-2013, 06:16 AM
I am porting a code from DirectX/HLSL to OpenGL/GLSL. I am stuck with inputting two vertex buffers into vertex shader. My code in HLSL is as below:

HLSL:

float4 vs_main(float4 pos0 : POSITION0, float4 pos1 : POSITION1)
{
return something;
}


I need to get two positions, two texture coords and ... and i need the GLSL and C++ code to bind the vertex buffers. I googled this and searched my opengl book, but no luck.

Any help is appreciated.

tonyo_au
06-26-2013, 07:53 AM
I assume you mean that one vertex will have 2 positions, 2 texture coordinates etc associated with it.

You do this when you construct the vertex array object.



glGenVertexArrays(1, &VAO_ID);
glBindVertexArray(VAO_ID);

glBindBuffer(GL_ARRAY_BUFFER,buffer_0_id);
glVertexAttribPointer(POSITION_0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
...


glBindBuffer(GL_ARRAY_BUFFER,buffer_1_id);
glVertexAttribPointer(POSITION_1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
...




layout(location = POSITION_0) in vec3 Position0;
layout(location = POSITION_1) in vec3 Position1;

saman_artorious
06-26-2013, 08:31 AM
thank you so much, I will do test it tomorrow.

saman_artorious
06-27-2013, 04:56 AM
I assume you mean that one vertex will have 2 positions, 2 texture coordinates etc associated with it.

You do this when you construct the vertex array object.



glGenVertexArrays(1, &VAO_ID);
glBindVertexArray(VAO_ID);

glBindBuffer(GL_ARRAY_BUFFER,buffer_0_id);
glVertexAttribPointer(POSITION_0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
...


glBindBuffer(GL_ARRAY_BUFFER,buffer_1_id);
glVertexAttribPointer(POSITION_1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
...




layout(location = POSITION_0) in vec3 Position0;
layout(location = POSITION_1) in vec3 Position1;



glVertexAttribPointer(POSITION_0, 3, GL_FLOAT, GL_FALSE, sizeof(vertices), 0);

POSITION_0 & POSITION_1 are not defined. Only GL_POSITION exists!

thokra
06-27-2013, 05:28 AM
POSITION_0 & POSITION_1 are not defined. Only GL_POSITION exists!

Hold on. First of all, of course POSITION_0 and POSITION_1 aren't defined. They're supposed to be integers in the range [0 .. MAX_VERTEX_ATTRIBS]. Therefore, if you add


#define POSITION_0 0
#define POSITION_1 1


to your shader is good. Of course, you need to make exactly the same definition in your application, or otherwise you will have potential mismatches between what the shader defines and what your application uses as arguments to glVertexAttribPointer.

EDIT: BTW, GL_POSITION doesn't exist either. gl_Position does. Remember, we're very case sensitive about such things. :)

saman_artorious
06-29-2013, 02:28 AM
Thanks. I get the index of variables vertex and colors using the following function:
shaderProgram->setAttributeLocation("vertex")

I think the logic of my code is correct, However what it draws is absolutely garbage.



void PlanPositionIndicator::render(QGLShaderProgram* shaderProgram)
{
if(!initialized)
{
GLuint vertexId = shaderProgram->attributeLocation("vertex");

GLuint colorId = shaderProgram->attributeLocation("color");

glGenVertexArrays(1, &VAO_ID);
glBindVertexArray(VAO_ID);

glBindBuffer(GL_ARRAY_BUFFER, VBO_ID[0]);
glVertexAttribPointer(vertexId, 2, GL_FLOAT, GL_FALSE, sizeof(vertices), 0);
glBufferData(GL_ARRAY_BUFFER, sizeof(QVector2D)*vertices.size(), vertices.constData(), GL_STATIC_DRAW);

glBindBuffer(GL_ARRAY_BUFFER, VBO_ID[1]);
glVertexAttribPointer(colorId, 1, GL_FLOAT, GL_FALSE, sizeof(vertices), 0);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*vertices.size(), colors, GL_STATIC_DRAW);

initialized = 1;
}

glBindBuffer(GL_ARRAY_BUFFER, VAO_ID);

// shaderProgram->setAttributeArray("vertex", vertices.constData());

int vertexLocation = shaderProgram->attributeLocation("vertex");


//shaderProgram->setAttributeArray("color", GL_FLOAT,colors,1);

shaderProgram->enableAttributeArray(vertexLocation);

// glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, sizeof(vertices), NULL);

int colorLocation = shaderProgram->attributeLocation("color");

shaderProgram->enableAttributeArray(colorLocation);

// glVertexAttribPointer(colorLocation, 3, GL_FLOAT, GL_FALSE, sizeof(colors), (const char*)(sizeof(float)*3));

// glEnable (GL_BLEND);

// glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

glDrawArrays(GL_TRIANGLES, 0, numVerts);
}



Does anyone have any idea?

Dan Bartlett
06-29-2013, 02:59 AM
You shouldn't have the line:

glBindBuffer(GL_ARRAY_BUFFER, VAO_ID);
It should be:

glBindVertexArray(VAO_ID);

Also, is your shader program compiled + linked successfully prior to querying attribute locations?

saman_artorious
06-29-2013, 03:16 AM
1063

if(!initialized)
{
GLuint vertexId = shaderProgram->attributeLocation("vertex");

GLuint colorId = shaderProgram->attributeLocation("color");

glGenVertexArrays(1, &VAO_ID);
glBindVertexArray(VAO_ID);

glBindBuffer(GL_ARRAY_BUFFER, VBO_ID[0]);
glVertexAttribPointer(vertexId, 2, GL_FLOAT, GL_FALSE, sizeof(vertices), 0);
glBufferData(GL_ARRAY_BUFFER, sizeof(QVector2D)*vertices.size(), vertices.constData(), GL_STATIC_DRAW);

glBindBuffer(GL_ARRAY_BUFFER, VBO_ID[1]);
glVertexAttribPointer(colorId, 1, GL_FLOAT, GL_FALSE, sizeof(vertices), 0);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*vertices.size(), colors, GL_STATIC_DRAW);

initialized = 1;
}

//glBindBuffer(GL_ARRAY_BUFFER, VAO_ID);
glBindVertexArray(VAO_ID);

int vertexLocation = shaderProgram->attributeLocation("vertex");
shaderProgram->enableAttributeArray(vertexLocation);
int colorLocation = shaderProgram->attributeLocation("color");
shaderProgram->enableAttributeArray(colorLocation);

glDrawArrays(GL_TRIANGLES, 0, numVerts);


I changed the function. thanks. Yes, I receive no error regarding the shader program not linked. Besides, the shader program was working properly without VBO.

this is my shader program:


//#version 130

precision mediump float;

uniform mat4 mvpMatrix;

attribute vec4 vertex;
attribute float color;

varying float varyingColor;

void main(void)
{
varyingColor = color;
gl_Position = mvpMatrix * vertex;
}






//#version 130

precision mediump float;

varying float varyingColor;

void main(void)
{
gl_FragColor = vec4(varyingColor * vec3(0, 1, 0), 0.5);
}


The program should draw a ppi, but what it draws is quite irrelevant, I attached a screen shot.

tonyo_au
06-29-2013, 09:44 PM
I notice you have an alpha value - have you enabled blending?

saman_artorious
06-30-2013, 03:47 AM
I notice you have an alpha value - have you enabled blending?

Even if I enable it, it has no effect:


glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDrawArrays(GL_TRIANGLES, 0, numVerts);

tonyo_au
06-30-2013, 11:40 PM
Your vertex positions sizes don't match


glVertexAttribPointer(vertexId, 2, GL_FLOAT, GL_FALSE, sizeof(vertices), 0)

size 2


attribute vec4 vertex;

size 4

saman_artorious
07-01-2013, 01:47 AM
I did not find any line in my code that binds the VBO to the shader program, is it possible that it's missing, or the code is complete and correct?

thokra
07-01-2013, 02:07 AM
that binds the VBO to the shader program

VBOs aren't bound to a shader. VBOs even need not be bound at all to source data from their data store. You can associate a vertex buffer object with an index in the range [0 .. GL_MAX_VERTEX_ATTRIBS] via glVertexAttribPointer (and other means with GL4.3, but since you're obviously on a lower version you shouldn't bother until you get a hold of the concept. You then bind that index to a corresponding location in your shader, either via glBindAttribLocation or, more preferably, via explicit assignment in the shader. For more details, please read this (http://www.opengl.org/discussion_boards/showthread.php/182076-Vertex-Array-Object-Question).

Also, I refer you to the corresponding wiki page (http://www.opengl.org/wiki/Vertex_Specification).

saman_artorious
07-01-2013, 03:55 AM
Thanks for the reference.
The shape I rendered is merely what I wanted. Though, 1/4 of the circle is rendered. (I need to find where that comes from).
Now, let's say I need to change the value of colors in my program. I know that for this I need to use glMapBuffer() & glUnmapBuffer().
This code gives me a segmentation fault. Could you tell me the correct way of accessing and modifying the colors variable please.


float* colors = (float *) glMapBuffer( GL_ARRAY_BUFFER, GL_WRITE_ONLY );

int k = segmentIndex * RANGE_COUNT * 6;
for(int i = 0; i < RANGE_COUNT; ++i)
{
float rnd = ((rand() + segmentIndex) % 10000) / 10000.0f;

colors[k++] = rnd;
colors[k++] = rnd;
colors[k++] = rnd;
colors[k++] = rnd;
colors[k++] = rnd;
colors[k++] = rnd;
}
glUnmapBuffer( GL_ARRAY_BUFFER );


I want to copy only a specified portion everytime, so this way I think I should use the write() function as glMapBuffer() copies the whole buffer. could explain this to me with a sample please.

GClements
07-01-2013, 10:35 PM
Your vertex positions sizes don't match

glVertexAttribPointer(vertexId, 2, GL_FLOAT, GL_FALSE, sizeof(vertices), 0)

attribute vec4 vertex;

This doesn't matter. Vertex attributes are always 4-element vectors. If you specify fewer than 4 components, y and z default to 0 while w defaults to 1.