need help understanding glVertexAttribPointer and GL_INVALID_OPERATION

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

need help understanding glVertexAttribPointer and GL_INVALID_OPERATION

jmaasing
I started out with the RawGL2ES2demo.java and that worked fine. Then I decided to play around with GL3 so I changed the shaders a little bit (made them even more stupid) but I can't seem to get the hang of how to use glVertexAttribPointer

I pass in a direct float buffer but I get:
glGetError() returned the following error codes after a call to glVertexAttribPointer(<int> 0x0, <int> 0x3, <int> 0x1406, <boolean> false, <int> 0x0, <java.nio.Buffer> java.nio.DirectFloatBufferU[pos=0 lim=9 cap=9]):
 GL_INVALID_OPERATION ( 1282 0x502),

I must be missing something fundamental but I've been looking at the specs the entire day and trying stuff at random with no luck. If anyone could point me in the right direction I'd be very happy :)

I'm using jogamp 2.0-rc11 on OSC 10.8.  I've upladed a test case:

GL3TestAttrib.java
Reply | Threaded
Open this post in threaded view
|

Re: need help understanding glVertexAttribPointer and GL_INVALID_OPERATION

Xerxes Rånby
Hi i can see two issues with your code:

1.  do not recompile a new shader program each frame. you currently do this by having these two lines:
        int positionAttribute = loadShaderProgram(gl);
        gl.glUseProgram(program.program());
placed inside your display function. The loadShaderProgram function contains:
        program = new ShaderProgram();
so... for each second you upload, compile and link 60 new vertex and fragment shader program that gets stored inside your GPU memory. You will quickly run out of GPU memory by doing this.
The display function gets run about 60 times/second!
     
I suggest that you make the possitionAttribute global
and then move the above two lines from the display function into the
        public void init(GLAutoDrawable drawable) {
function so that they only gets run once at program startup.

The only way to reclaim GPU memory is by explicit detach the program that you have previously have linked inside the GPU memory.
You reclaim ShaderProgram GPU memory by calling:
        program.release(gl);
or
        program.destroy(gl);

http://jogamp.org/deployment/jogamp-next/javadoc/jogl/javadoc/com/jogamp/opengl/util/glsl/ShaderProgram.html


2.) swap the order of these three lines that initialize the VertexAttribArray and place gl.glEnableVertexAttribArray at the end:
Change:
                        gl.glEnableVertexAttribArray(positionAttribute);
                        FloatBuffer fbVertices = Buffers.newDirectFloatBuffer(vertices);
                        gl.glVertexAttribPointer(positionAttribute, 3, GL3.GL_FLOAT, false, 0, fbVertices);

to:
                        FloatBuffer fbVertices = Buffers.newDirectFloatBuffer(vertices);
                        gl.glVertexAttribPointer(positionAttribute, 3, GL3.GL_FLOAT, false, 0, fbVertices);
                        gl.glEnableVertexAttribArray(positionAttribute);

Unfortunately I do not own a GL3 enabled device so my suggestions are untested.
Reply | Threaded
Open this post in threaded view
|

Re: need help understanding glVertexAttribPointer and GL_INVALID_OPERATION

jmaasing
Yeah, I understand that I recompile the shaders a bit more than is needed :-) Thanks for the tip.
Sadly, rearranging the lines didn't help. Still get the same error. Tried it on a linux+nVidia with the same result.

I'm pretty new to the shader based pipeline so I must be getting the GL state wrong for some fundamental reason.

Things I've tried also is to allocate VBOs, VAs and all that jazz like so

gl.glGenVertexArrays(1, vertexArrays, 0);
gl.glBindVertexArray(this.vertexArrays[0]);
gl.glGenBuffers(1, vertexBuffers, 0);
gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, this.vertexBuffers[0]);
FloatBuffer fbVertices = Buffers.newDirectFloatBuffer(vertices);
gl.glBufferData(GL3.GL_ARRAY_BUFFER, vertices.length * Float.SIZE / 8, fbVertices, GL3.GL_STATIC_DRAW);

gl.glEnableVertexAttribArray(vertexArrays[0]);
gl.glVertexAttribPointer(positionAttribute, 3, GL3.GL_FLOAT, false, 0, 0);

gl.glBindVertexArray(this.vertexArrays[0]);
gl.glDrawArrays(GL3.GL_TRIANGLES, 0, 3);

Which gave me an GL_INVALID_OPERATION on the draw call, I don't know if that is progress or just another noob error in not understanding the fundamentals

I'll struggle on, thanks for your time.
Reply | Threaded
Open this post in threaded view
|

Re: need help understanding glVertexAttribPointer and GL_INVALID_OPERATION

Xerxes Rånby
This post was updated on .
jmaasing wrote
Yeah, I understand that I recompile the shaders a bit more than is needed :-) Thanks for the tip.
Sadly, rearranging the lines didn't help. Still get the same error. Tried it on a linux+nVidia with the same result.
Try bind the attribute explicit using  glBindAttribLocation before the program.link step.
http://www.opengl.org/sdk/docs/man/xhtml/glBindAttribLocation.xml

The index number that is set to 1 below is then picked by you.
Any index number below GL_MAX_VERTEX_ATTRIBS will do,
Most GPU cards got 16 Vertex attribute slots, unless the driver is broken then 0 attrib slots might be available.
http://www.kludx.com/capability.php?capability=737

...
                program.add(vertexShader);
                program.add(fragmentShader);
                gl.glBindAttribLocation(program.program(), 1 /* user picked index */ , "attribute_Position"); // <- here
                program.link(gl, System.out);
...

I will try test the code if i get my hands on some GL3 hardware.
Cheers and have a great day!
Xerxes
Reply | Threaded
Open this post in threaded view
|

Re: need help understanding glVertexAttribPointer and GL_INVALID_OPERATION

jmaasing
That was one of the first things I tried actually and it didn't help :/
I did that to see if I read the GLSPecs correctly about finding the location. If I bind a number before linking I can see that by getting the attribute location after linking the number is the same as I assign. If I let the driver assign numbers I usually get 0 for the location.

Am I supposed to be able to bind a FloatBuffer directly as the API suggest or do I have to go through generating VAs and VBOs?
Not counting optimization, just, is it possible? I'm worried that I totally misunderstand the purpose of that method.

I haven't read the ES2-spec yet but maybe someone in the forum knows if there are some changes in glVertexAttribPointer since the RawGL2ES2 demo works fine but this code does not.
Reply | Threaded
Open this post in threaded view
|

Re: need help understanding glVertexAttribPointer and GL_INVALID_OPERATION

jmaasing
So, after reading a bit more tutorials I sort of kind of get how it hangs together. These helped me: stackoverflow.com "is-vertexattribpointer-needed-after-each-bindbuffer" and this one from swiftless.com (be sure to read the comments, they correct some mistakes in the example)

Here is my working sample, it is really stupid and may not follow best practice but it worked
public class GL3TestAttrib implements GLEventListener {
	private ShaderProgram program;
	int[] vertexArrays = new int[1];
	private int[] vertexBuffers = new int[1];
	int positionAttribute;

	public static void main(String[] args) {
		GL3TestAttrib app = new GL3TestAttrib();
		app.run();
	}

	public void run() {
		final GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL3));
		caps.setBackgroundOpaque(true);
		final GLWindow glWindow = GLWindow.create(caps);
		glWindow.setTitle("Sample GL3");
		glWindow.setSize(640, 480);
		glWindow.setUndecorated(false);
		glWindow.setPointerVisible(true);
		glWindow.addGLEventListener(this);
		final Animator animator = new Animator(glWindow);
		glWindow.addWindowListener(new WindowAdapter() {

			@Override
			public void windowDestroyed(WindowEvent event) {
				animator.stop();
				glWindow.setVisible(false);
				System.exit(0);
			}
		});
		glWindow.setVisible(true);
		animator.start();
	}

	@Override
	public void init(GLAutoDrawable drawable) {
		final float[] vertices = { 0.0f, 0.7f, 0.0f, 0.0f, 0.1f, 0.0f, 0.9f, 0.1f, 0.0f };

		if (drawable.getGL().isGL3()) {
			final GL3 gl = drawable.getGL().getGL3();
			drawable.setGL(new DebugGL3(gl));
			gl.glGenVertexArrays(1, vertexArrays, 0);
			gl.glBindVertexArray(this.vertexArrays[0]);
			gl.glGenBuffers(1, vertexBuffers, 0);
			gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, this.vertexBuffers[0]);
			FloatBuffer fbVertices = Buffers.newDirectFloatBuffer(vertices);
			gl.glBufferData(GL3.GL_ARRAY_BUFFER, vertices.length * Float.SIZE / 8, fbVertices, GL3.GL_STATIC_DRAW);

			try {
				positionAttribute = loadShaderProgram(gl);
			} catch (IOException e) {
				e.printStackTrace();
				throw new IllegalStateException(e);
			}
			gl.glVertexAttribPointer(positionAttribute, 3, GL3.GL_FLOAT, false, 0, 0);

			gl.glBindVertexArray(0);
			gl.glDisableVertexAttribArray(positionAttribute);
		} else {
			System.err.println("Not a GL3 drawable");
			System.exit(1);
		}
	}

	@Override
	public void dispose(GLAutoDrawable drawable) {
	}

	@Override
	public void display(GLAutoDrawable drawable) {

		GL3 gl = drawable.getGL().getGL3();
		gl.glClearColor(1, 0, 1, 0.5f); // Purple
		gl.glClear(GL3.GL_STENCIL_BUFFER_BIT | GL3.GL_COLOR_BUFFER_BIT | GL3.GL_DEPTH_BUFFER_BIT);

		gl.glUseProgram(program.program());
		gl.glBindVertexArray(this.vertexArrays[0]);
		gl.glEnableVertexAttribArray(positionAttribute);

		gl.glDrawArrays(GL3.GL_TRIANGLES, 0, 3);

		gl.glDisableVertexAttribArray(positionAttribute);
		gl.glBindVertexArray(0);
		gl.glUseProgram(0);
	}

	@Override
	public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
	}

	private int loadShaderProgram(final GL3 gl) throws IOException {
		final String nameBase = "sample";
		final String filePrefix = "/shaders/" + nameBase;

		/*
		 * #version 150 core
		 * 
		 * in vec3 attribute_Position;
		 * 
		 * void main(void) { gl_Position = vec4(attribute_Position, 1.0); }
		 */
		ShaderCode vertexShader = ShaderCode.create(gl, GL3.GL_VERTEX_SHADER, getClass(), filePrefix, "/tmp", nameBase,
				false);
		final boolean vertexCompile = vertexShader.compile(gl);
		if (!vertexCompile) {
			throw new RuntimeException("Unable to compile vertex shader: " + nameBase);
		}

		/*
		 * #version 150 core
		 * 
		 * out vec4 fragColor ;
		 * 
		 * void main (void) { fragColor = vec4(0.0f, 1.0f, 1.0f, 1.0f); }
		 */
		ShaderCode fragmentShader = ShaderCode.create(gl, GL3.GL_FRAGMENT_SHADER, getClass(), filePrefix, "/tmp",
				nameBase, false);
		final boolean fragmentCompile = fragmentShader.compile(gl);
		if (!fragmentCompile) {
			throw new RuntimeException("Unable to compile fragment shader: " + nameBase);
		}
		program = new ShaderProgram();
		program.init(gl);

		program.add(vertexShader);
		program.add(fragmentShader);

		program.link(gl, System.out);

		final boolean validateProgram = program.validateProgram(gl, System.out);
		if (!validateProgram) {
			throw new RuntimeException("Shader program did not validate: " + nameBase);
		}

		int attribPosition = gl.glGetAttribLocation(program.program(), "attribute_Position");
		return attribPosition;
	}
}
Reply | Threaded
Open this post in threaded view
|

Re: need help understanding glVertexAttribPointer and GL_INVALID_OPERATION

Xerxes Rånby
This post was updated on .
Thank you for this GL3 triangle example!

I stumbled across a great OpenGL 3 online book with focus on OpenGL 3.3 and the programmable pipeline!
Jason L. McKesson: Learning Modern 3D Graphics Programming
http://arcsynthesis.org/gltut/

The MIT licensed source for this book is found on Bitbucket, a neat collection of example projects to port :)
https://bitbucket.org/alfonse/gltut/wiki/Home

I will read up and prime myself.
Focusing on OpenGL 3 now is a good way to get familiar with the new mobile OpenGL ES 3 devices that use a subset of GL3.
Reply | Threaded
Open this post in threaded view
|

Re: need help understanding glVertexAttribPointer and GL_INVALID_OPERATION

jmaasing
Xerxes Rånby wrote
I stumbled across a great OpenGL 3 online book with focus on OpenGL 3.3 and the programmable pipeline!
Jason L. McKesson: Learning Modern 3D Graphics Programming
http://arcsynthesis.org/gltut/

The MIT licensed source for this book is found on Bitbucket, a neat collection of example projects to port :)
https://bitbucket.org/alfonse/gltut/wiki/Home
I've read most of the first 3 chapters now. It is a really good book. I wouldn't call it absolute beginners book even if it explains some basic concepts. But if you have some experience, for example like me with the fixed pipeline or GL2, it is perfect.