PDA

View Full Version : attribute in vertex shader



Mick Derevnin
04-05-2011, 08:02 AM
Hi everyone,

I still been working on trying to get a flame particle system up and running, and once again I've become stuck.

I've been trying to debug this for about 7hrs so far.. and am really out of ideas.

So I'm using a FloatBuffer to send bezier curve control points to the vertex shader via attributes.

I've bound the attribute location manually (and checking it with glGetAttrubLocation gets the same location).

I believe i have called all the correct settings in the right order.

So i have 1000 particles, each particle has its own bezier curve definition. I've stored all the control point 0's into 1 float buffer, and passed that over into the vertex shader.

But when i loop through all the particles, and call glVertex3f, all the particles get given the same coordinates for the control point.

I've checked the FloatBuffer size and values, and it's all correct (and different).

The bezier curves are generated randomly, so every time i rerun the program they have different values. However, the 1 point that all the particles are drawn on is still the same (and that point isnt 0,0,0, which is the vertex im passing in to glVertex3f).

Here's the relevant code, hopefully:

in the init() function:


String vShaderSource = readFile(shaderDir + File.separator + shaderName + ".vert");
String fShaderSource = readFile(shaderDir + File.separator + shaderName + ".frag");

if(fShaderSource != null && vShaderSource != null) {

// compile vertex shader
vShader = gl.glCreateShader(GL.GL_VERTEX_SHADER);
gl.glShaderSource(vShader, 1, new String[] { vShaderSource }, (int[]) null, 0);
gl.glCompileShader(vShader);
printShaderInfoLog(gl, vShader);

// compile fragment shader
fShader = gl.glCreateShader(GL.GL_FRAGMENT_SHADER);
gl.glShaderSource(fShader, 1, new String[] { fShaderSource }, (int[]) null, 0);
gl.glCompileShader(fShader);
printShaderInfoLog(gl, fShader);
}

program = gl.glCreateProgram();

gl.glAttachShader(program, vShader);
gl.glAttachShader(program, fShader);

gl.glBindAttribLocation(program, BEZIER_CP0, "cp0");

gl.glLinkProgram(program);
gl.glValidateProgram(program);
printProgramInfoLog(gl, program);


also in the init() function to create the buffer:


cp0 = BufferUtil.newFloatBuffer(3 * 1000);

...............................
// below bit is looped 1k times:

FlameParticle particle = new FlameParticle();
cp0.put(particle.cp0.x);
cp0.put(particle.cp0.y);
cp0.put(particle.cp0.z);


in my display() function:


cp0.rewind();
gl.glVertexAttribPointer(BEZIER_CP0, 3, GL.GL_FLOAT, false, 0, cp0);

gl.glEnableVertexAttribArray(BEZIER_CP0);

gl.glColor4f(0.7f, 0.2f, 0.1f, 0.8f);
gl.glPointSize(8);

gl.glBegin(GL.GL_POINTS);

FlameParticle particle;
Vector3D particleLocation;

for(int i = 0; i < particleList.size(); i++) {

particle = (FlameParticle)particleList.get(i);


gl.glVertex3f(0.0f, 0.0f, 0.0f);
}

gl.glEnd();

gl.glDisableVertexAttribArray(BEZIER_CP0);


vertex shader:


attribute vec3 cp0;

varying vec4 colour;

void main(void)
{
vec4 position;

position = vec4(cp0.x, 0, 0, 1);

//colour = gl_Color;
colour = vec4(1,1,1,1);

gl_Position = gl_ModelViewProjectionMatrix * position;
//gl_Position = ftransform();
}


If anyone has any ideas, that would be great!

Alfonse Reinheart
04-05-2011, 02:14 PM
cp0 = BufferUtil.newFloatBuffer(3 * 1000);

I have no idea what this line of code does. I will assume for the moment that it creates some kind of OpenGL buffer object.


gl.glVertexAttribPointer(BEZIER_CP0, 3, GL.GL_FLOAT, false, 0, cp0);

Did you bind the buffer object before calling this?


gl.glBegin(GL.GL_POINTS);

Whoa. You cannot combine immediate mode rendering with array drawing. Not unless you're using glArrayElement. And that's generally really bad form.

If you're not using gl_Vertex in your shader, then don't immediate mode like this. Assign your vertex attribute to attribute zero, then use glVertexAttrib(0, ...) to send your vertex data. You shouldn't be using a buffer object with immediate mode.

Mick Derevnin
04-05-2011, 04:12 PM
Thanks again for the replies Alfonse.


I have no idea what this line of code does. I will assume for the moment that it creates some kind of OpenGL buffer object.

Yeah, that's the buffer object that JOGL uses in java.


Did you bind the buffer object before calling this?

Yeah, i bound it using glBindAttribLocation before linking the program this time.


Whoa. You cannot combine immediate mode rendering with array drawing. Not unless you're using glArrayElement. And that's generally really bad form.

If you're not using gl_Vertex in your shader, then don't immediate mode like this. Assign your vertex attribute to attribute zero, then use glVertexAttrib(0, ...) to send your vertex data. You shouldn't be using a buffer object with immediate mode.

Ahh, do you think this would be why cp0 in the vertex shader isn't receiving the buffer data, but is being bound correctly?

Does that mean i have to use glDrawArrays if i choose to pass buffered array data via attributes to the shader?

I'll have a try of this once i get some free time soon!

Thanks!

Alfonse Reinheart
04-05-2011, 04:28 PM
Yeah, i bound it using glBindAttribLocation before linking the program this time.

That does not bind a buffer object. That's binding an attribute location to a program. I'm talking about calling glBindBuffer(GL_ARRAY_BUFFER, buffer_object_name);

The OpenGL Wiki articles on this (http://www.opengl.org/wiki/Vertex_Array_Object) subject (http://www.opengl.org/wiki/Vertex_Specification#Building_the_Stream) cover how this works in detail.