2
votes

I'm trying to learn GLSL and I'm wanting to send a float attribute to my vertex shader. For now, this float is to be used simply to set the brightness (I mulitply in_Color by in_Light and assign it to out_Color). The brightness always seems to equal 1.0 in the vertex shader regardless of what I try to pass (0.1 in the code below). I've tried googling and I've tried experimenting quite a bit but I just don't get what's wrong. Position, texture coordinates and color seem to work fine.

Here is how I'm binding the attribute locations, and a bit more of the code.

    this.vsId = Shader.loadShader(pVertexFilePath, GL20.GL_VERTEX_SHADER);
    this.fsId = Shader.loadShader(pFragmentFilePath, GL20.GL_FRAGMENT_SHADER);

    this.pId = GL20.glCreateProgram();
    GL20.glAttachShader(this.pId, this.vsId);
    GL20.glAttachShader(this.pId, this.fsId);

    GL20.glBindAttribLocation(this.pId, 0, "in_Position");
    GL20.glBindAttribLocation(this.pId, 1, "in_TextureCoord");
    GL20.glBindAttribLocation(this.pId, 2, "in_Color");
    GL20.glBindAttribLocation(this.pId, 3, "in_Light");

    GL20.glLinkProgram(this.pId);

    this.normalMatrixId = GL20.glGetUniformLocation(this.pId, "normalMatrix");
    this.projectionModelViewMatrixId = GL20.glGetUniformLocation(this.pId, "projModelViewMatrix");

This is how I'm setting the position of each attribute

    FloatBuffer verticesFloatBuffer = BufferUtils.createFloatBuffer(verticesCount * 36);
    for (VertexData vert : vertices) {verticesFloatBuffer.put(vert.getElements());}
    vertices.clear();
    verticesFloatBuffer.flip();

    GL30.glBindVertexArray(vaoId);

    GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboId);
    GL15.glBufferData(GL15.GL_ARRAY_BUFFER, verticesFloatBuffer, GL15.GL_STATIC_DRAW);

    GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 36, 0);
    GL20.glVertexAttribPointer(1, 2, GL11.GL_FLOAT, false, 36, 12);
    GL20.glVertexAttribPointer(2, 3, GL11.GL_FLOAT, false, 36, 20);
    GL20.glVertexAttribPointer(3, 1, GL11.GL_FLOAT, false, 36, 32);

    GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);

This is the getElements method used above (I have manually input color and brightness for testing purposes). Note that the last value which should be in_Light is 0.1f and always turns out to be 1.f in the vertex shader.

public float[] getElements() {
    return new float[]{this.x, this.y, this.z, this.s, this.t, 1.f, 0.f, 1.f, 0.1f};
}

Vertex Shader:

#version 430 core

uniform mat4 projModelViewMatrix;
uniform mat3 normalMatrix;

in vec3 in_Position;
in vec2 in_TextureCoord;
in vec3 in_Color;
in float in_Light;

out vec4 pass_Color;
out vec2 pass_TextureCoord;

void main(void) {
    gl_Position = projModelViewMatrix * vec4(in_Position, 1.0);

    pass_TextureCoord = in_TextureCoord;

    pass_Color = vec4(in_Color * in_Light, 1.0);
}

Fragment Shader (just in case someone wants to see it):

#version 430 core

uniform sampler2D texture_diffuse;

in vec4 pass_Color;
in vec2 pass_TextureCoord;

out vec4 out_Color;

void main(void) {
    out_Color = texture2D(texture_diffuse, pass_TextureCoord) * pass_Color;
}

All other attributes that I pass to the vertex shader work fine.

EDIT: Just as a note, I've tried changing the shader to specify locations, eg:

layout (location = 0) in vec3 in_Position;

I've also used glGetAttributeLocation which gives me the same attribute locations (0, 1, 2, 3), eg:

GL20.glGetAttribLocation(this.pId, "in_Position");

I've also added an if statement to the shader to check the value of in_Light and it always equals one.

EDIT2: Now I've changed the color attribute to a vec4 and passed the light value in place of the alpha which works fine. Based on other trials, as well as this, it's almost as if I can't have more than 3 attributes for some reason.

2
try using layout_location in shader code, opengl.org/wiki/Layout_Qualifier_(GLSL), layout(location = attribute index) in vec3 position; instead of glBindAttribLocation in code.fen
Tried this as well. I also tried using glGetAttribLocation which gives me the same locations (0, 1, 2, 3) anyway.VrydayVrything

2 Answers

4
votes
GL20.glLinkProgram(this.pId);

GL20.glBindAttribLocation(this.pId, 0, "in_Position");
GL20.glBindAttribLocation(this.pId, 1, "in_TextureCoord");
GL20.glBindAttribLocation(this.pId, 2, "in_Color");
GL20.glBindAttribLocation(this.pId, 3, "in_Light");

The glBindAttribLocation call needs to come before you link the program. Attribute locations are fixed at link time, so if you didn't bind any, OpenGL will arbitrarily assign them locations.

0
votes

Yup, simple noob mistake in addition to the one Nicol Bolas mentioned. (wonder how many more I have ;)

I needed to add glEnableVertexAttribArray before setting the position of each attribute with glVertexAttribPointer. Seems like the first three attributes are automatically enabled, though I imagine this could change on a per GPU basis?

FloatBuffer verticesFloatBuffer = BufferUtils.createFloatBuffer(verticesCount * 36);
for (VertexData vert : vertices) {verticesFloatBuffer.put(vert.getElements());}
vertices.clear();
verticesFloatBuffer.flip();

GL30.glBindVertexArray(vaoId);

GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboId);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, verticesFloatBuffer, GL15.GL_STATIC_DRAW);

GL20.glEnableVertexAttribArray(0);
GL20.glEnableVertexAttribArray(1);
GL20.glEnableVertexAttribArray(2);
GL20.glEnableVertexAttribArray(3);

GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 36, 0);
GL20.glVertexAttribPointer(1, 2, GL11.GL_FLOAT, false, 36, 12);
GL20.glVertexAttribPointer(2, 3, GL11.GL_FLOAT, false, 36, 20);
GL20.glVertexAttribPointer(3, 1, GL11.GL_FLOAT, false, 36, 32);

GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);

Thanks to everyone that replied!