LWJGL - Pass value to "in" arguement on shader

I have create a triangle using a shader which successfully renders on a green background.
(This is a code example from the superbible 6 book)

There is a value on the shader which is suppose to make the triangle move.
But I am unable to assign a floatbuffer to that value.

Here is the shader.


#version 430 core
// "offset" is an input vertex attribute
layout (location = 0) in vec4 offset;
void main(void)
{
const vec4 vertices[3] = vec4[3](vec4( 0.25, -0.25, 0.5, 1.0),
vec4(-0.25, -0.25, 0.5, 1.0),
vec4( 0.25, 0.25, 0.5, 1.0));
// Add "offset" to our hard-coded vertex position
gl_Position = vertices[gl_VertexID] + offset;
}

And here is my (failed) attempt at assigning a value to that shader.


			FloatBuffer attrib = BufferUtils.createFloatBuffer(4);
			float[] move = new float[] { //
			(float) Math.sin(getCurrentTime()) * 0.5f, //
					(float) Math.cos(getCurrentTime()) * 0.6f, 0.0f,//
					0.0f };
			attrib.put(move);
			attrib.flip();
			GameUtils.exitOnGLError("set vertex");

			// Update the value of input attribute 0
			System.out.println(attrib.get(0));
			GL20.glVertexAttrib4f(0, attrib.get(0) * 100, attrib.get(1), 0.0f, 0.0f);

			GameUtils.exitOnGLError("set shader variable");

			// Draw triangle
			GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, 3);

Here is the code to the whole object.
http://pastebin.java-gaming.org/360f7340b97

The better way to set offsets is to use uniforms. In the shader source, you use


uniform vec4 offset;

Then you have to set the offset from the Java code, like this.


float[] offset = new float[]
{
    (float) Math.sin(getCurrentTime()) * 0.5f,
    (float) Math.cos(getCurrentTime()) * 0.6f,
    0.0f,
    0.0f
};

int location = GL20.glGetUniformLocation(shaderProgramID, "offset");
GL20.glUniform4f(location, offset[0], offset[1], offset[2], offset[3]);

And they will be updated in the shaders. Hope this helps.

What’s this fascination with stuffing values in arrays/buffers, only to extract them again prior to passing them to OpenGL ?


+        float a = (float) Math.sin(getCurrentTime()) * 0.5f;
+        float b = (float) Math.cos(getCurrentTime()) * 0.6f;
-        FloatBuffer attrib = BufferUtils.createFloatBuffer(4);
-        float[] move = new float[] {
-        (float) Math.sin(getCurrentTime()) * 0.5f,
-              (float) Math.cos(getCurrentTime()) * 0.6f, 0.0f,
-              0.0f };
-        attrib.put(move);
-        attrib.flip();
         GameUtils.exitOnGLError("set vertex");

         // Update the value of input attribute 0

-        System.out.println(attrib.get(0));
-        GL20.glVertexAttrib4f(0, attrib.get(0) * 100, attrib.get(1), 0.0f, 0.0f);
+        GL20.glVertexAttrib4f(0, a * 100, b, 0.0f, 0.0f);

         GameUtils.exitOnGLError("set shader variable");

         // Draw triangle
         GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, 3);


+        float a = (float) Math.sin(getCurrentTime()) * 0.5f;
+        float b = (float) Math.cos(getCurrentTime()) * 0.6f;
-        float[] offset = new float[]
-        {
-            (float) Math.sin(getCurrentTime()) * 0.5f,
-            (float) Math.cos(getCurrentTime()) * 0.6f,
-            0.0f,
-            0.0f
-        };

         int location = GL20.glGetUniformLocation(shaderProgramID, "offset");
-        GL20.glUniform4f(location, offset[0], offset[1], offset[2], offset[3]);
+        GL20.glUniform4f(location, a, b, 0, 0);


(points up) :o A great optimisation indeed. Thanks Riven for showing this.

About the uniforms @SHC, I was under the impression that they’re from an older version, and that in’s and out’s are more up to date. Someone correct me if I’m wrong.

Edit: 500th post.

Do not confuse vertex attributes with uniforms. They are completely different things.

A uniform is like a global variable (not a constant).
A vertex attribute is a variable specified for each vertex.

Thanks for the replies.

I managed to get pass the data to the uniform variable on the shader just fine although the movement isn’t very smooth.

As for the original method I still wasn’t able to get the triangle to move at all, even with directly putting the float values in.
Is their a line of code to enable ‘layout’ variables.

I did have a little success creating a buffer before passing it to the shader.
However, this only moved one vertex of the triangle

So I create a buffer with floats containing zeros in ‘setup’

		// create vertex buffer object (VBO) for vertices
		positionBufferHandle = GL15.glGenBuffers();
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, positionBufferHandle);
		GL15.glBufferData(GL15.GL_ARRAY_BUFFER, positionBuffer, GL15.GL_STATIC_DRAW);

Then in the render loop I create a new floatbuffer with the vertex offsets.
Rebind, reEnable

			GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, positionBufferHandle);
			GL15.glBufferData(GL15.GL_ARRAY_BUFFER, attrib, GL15.GL_STATIC_DRAW);

			// assign vertex VBO to slot 0 of VAO
			GL20.glEnableVertexAttribArray(0);
			GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 0, 0);

I’ve update the code in the original link
http://pastebin.java-gaming.org/1c8e833189a

(If anyone is interested in the working ‘uniform’ version I can paste that somewhere)

You are not using a uniform Gremolin. You are creating another VBO every frame just for offsets, which you should not be doing.

I have two different versions of this code now.
One using the uniform which works fine, and I was attempted to get the above version working using a layout variable. (although I have just got one vertex moving.

I couldnt get the method GL20.glVertexAttrib4f(…) to work at all so I attempted using GL20.glVertexAttribPointer(…) but that would require the bufferData to be set on every render loop. Which it appears is not a good way to do things judging by your post?

The function [icode]glBufferData()[/icode] recreates the datastore of the buffer object. Calling it in every frame causes recreation of the datastore every time it was called, which results in a performance loss. Instead, you can use the [icode]glBufferSubData()[/icode] function which just replaces the data without recreating it.

Thanks, the glBufferSubData method worked.

Only one vertices is moving on the triangle still, so I still got to figure that out.