Search code examples
openglglslvariable-assignmentvarying

OpenGL - GLSL assigning to varying variable breaks the vertex positioning


I did a project in OpenGL version 3.2 once where I used a "sampler2DArray" to store multiple images with the same dimensions and rendered them using textured points.

Now I am trying to port that project to my gnu/linux computer. This computer only supports up to OpenGL version to 2.1 and GLSL version up to 1.20 (which doesn't have sampler2DArray). As far as I know there is no way to update OpenGL to support the newer features.

What I am currently trying to do is to use a sampler3D to store my images and use the depth value to select the image I want.

To send the texture depth from the vertex shader to the fragment shader I have declared a "varying" float variable holding the depth value (0.0 to 1.0).

I am rendering 4 images at the locations: (-0.5, +0.5), (+0.5, +0.5), (-0.5, -0.5) and (+0.5, -0.5).

The image switching method appears to be working (changing the "index" variable changes the image). But for some wierd reason all images gets rendered at (0.0, 0.0) and not at their assigned positions. This problem goes away when I don't assign to the varying variable containing the depth value for the texture and set the depth value to 0.0 in the fragment shader.

Here is the vertex shader:

#version 120

attribute vec2 position
attribute float index
varying float v_index

void main()
{
    gl_Position = vec4(position, 0.0, 1.0);
    v_index = index; // Removing this assignment makes the images appear at their assigned locations.
}

Here is the fragment shader:

#version 120

uniform sampler3D texture;
varying float v_index;

void main()
{
    gl_FragColor = texture3D(texture, vec3(gl_PointCoord, v_index));
}

The structure I use represent vertices:

struct vertex {
    GLfloat x;
    GLfloat y;
    GLfloat texture_index;
};

The calls to the glVertexAttribPointer function (the problem may be here too):

glBindAttribLocation(shader_program, 0, "position");
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(struct vertex), (void *)0);
glBindAttribLocation(shader_program, 1, "index");
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, sizeof(struct vertex), (void *)(2 * sizeof(GLfloat));

I have also found a very similar question. The answer marked "accepted" claims that the cause of the problem is that the shaders have more than 16 varying vectors (which isn't the case for me).

Here is the link: Strange error in GLSL while assigning attribute to a varying in vertex shader


Solution

  • This looks like your attribute location bings aren't effective and the locations are assigned bu the GL. Without the assignment, the index attribute is not used, and only the position one is, so it is very likely that it gets location 0. Whe index is actually used, it might get 0 (on nvidia, those locations seem to be assigned in alphabetical order).

    The glBindAttribLocation() calls only have an effect when linking the program, so these have to be called before glLinkProgram(), and you have to re-link the program when you want to change those (which you should really avoid). The code you have given suggests that this is called during your regular draw calls, so that these never have any effect on the linked program.