4

For my shader, I don't want to enable all attributes for all draw calls. For example in one draw call, I want to use different color for each vertex which is stored in vertex buffer. So I use glEnableVertexAttribArray and glVertexAttribPointer to bind the buffer and it works fine.

However I can't use glVertexAttrib methods for constant colors. Did I misunderstood of these methods? Can you tell if a vertex attribute is enabled from within a vertex shader? says that

If an attribute is disabled, its value comes from regular OpenGL state. Namely, the state set by the glVertexAttrib functions

But when I disable glDisableVertexAttribArray and use glVertexAttrib to set it to a constant, it does not render anything. If I try to use that attribute in the shader, it simply renders black.

What am I missing?

edit:

My code is something like this (it has some abstraction but call order for gl functions is this)

    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
    glEnableVertexAttribArray(position);
    glVertexAttribPointer(position, 3, GL_FLOAT, false, sizeof(Vertex), 0);
    glEnableVertexAttribArray(normal);
    glVertexAttribPointer(normal, 3, GL_FLOAT, true, sizeof(Vertex), (void*)(sizeof(Vec3)));
    glEnableVertexAttribArray(color);
    glVertexAttribPointer(color, 4, GL_FLOAT, false, sizeof(Vertex), (void*)(sizeof(Vec3)+sizeof(Vec3)));

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);

    glDrawElements(
        GL_TRIANGLES,
        (edgeCount - 1)*(edgeCount - 1) * 6,
        GL_UNSIGNED_INT,
        (void*)0
        );

This works however when I replace glEnableVertexAttribArray(color); glVertexAttribPointer(color, 4, GL_FLOAT, false, sizeof(Vertex), (void*)(sizeof(Vec3)+sizeof(Vec3)));

with

glDisableVertexAttribArray(color);
glVertexAttrib4f(color, 1.0f, 0.0, 0.0, 1.0);

It does not work.

Community
  • 1
  • 1
  • Well, that shouldn't happen. However, are you sure that you use it correctly? Please provide the relevant parts of the code. – derhass Mar 02 '15 at 20:50
  • Well. It should work. At least based on that little code snippet you provided so far. One thing you should be aware of is that the _current state_ of each vertex attribute will be _undefined_ (and could as well also be reset to all zeros) whenever you did render with the corresponding attrib pointer enabled. But your code seems to set the desired values directly before the draw call, and that should definitively work. I'm using this feature and had no error reports so far, on a number of different implementations and platforms. – derhass Mar 02 '15 at 21:05
  • It looks like the problem is about attribute location '0', I added another attribute, color2 and it is assigned to location 1 and I can edit it without a problem. Weird –  Mar 02 '15 at 21:12
  • Oh, attribute location 0 should be avoided for stuff like this. That will alias to commands like `glVertex3f (...)`. Some drivers are particularly stupid and do not like to draw anything when attribute 0 is disabled, it's just a mess all around dealing with that particular generic attribute. – Andon M. Coleman Mar 02 '15 at 21:14
  • Yeah, thank you for clarification. I set my vertex position attribute to layout(location = 0) and it works now –  Mar 02 '15 at 21:16

1 Answers1

2

It looks like my problem was location of color attribute was being 0, If that location is not enabled it does not render anything.

I moved my position attribute to location 0 (layout(location = 0) attribute vec3 aVertexPosition;) and I can safely enable or disable color attribute now

  • Well in core GL >= 3.2 it should also work when attribute 0 is disabled. In legacy GL <= 2.1, it won't work at all. In compatibility profiles or modern GL, I'm really not sure. I think it should alkso work there, but I haven;t looked that up in the spec. – derhass Mar 02 '15 at 21:40
  • @derhass: It doesn't violate anything in the spec., but the number of drivers I've encountered that don't behave properly when vertex attribute **0** is used for something other than position is concerning. AMD, NV and Intel _all_ seem to make one assumption or another about attribute **0** that does not hold up (even in core profiles). The funniest one comes from the first shader in the OpenGL super bible, some older drivers saw no enabled vertex attribute array and would skip all primitives except for `GL_POINTS`. – Andon M. Coleman Mar 03 '15 at 00:13
  • For the record, one could alternatively fix the problem using `glBindAttribLocation`. That could be useful if one is coding to the GLSL 1.5 spec, which does not have a location layout attribute. – JWWalker Oct 01 '19 at 17:30