from geometry to pixels

Attribute-less rendering

The first step of the rendering pipeline is to fetch application provided data from one or multiple places (think of array buffers) and pass them as attributes into the vertex shader stage. This fetch can be controlled by an index and N attributes will get pulled from M arrays.
The details are not so important here, what’s important is the fact that we always think of the rendering pipeline as box gets explicitly feed with data, processes it and passes intermediate results from one stage to the next and produces some kind of image in the end.
But at the very beginning of this pipeline, OpenGL has a surprise for us: It is possible to render something without any data at all!
In the good old days of the fixed-function pipeline and even later in OpenGL 2.1 there were special functions to generate geometry respectively a special vertex position attribute. With user defined attributes and vertex shaders the programmer can define in any way he/she likes what will define the output vertex position – it does not have to depend on any inputs. But, at least vertex attribute 0 had to be defined.
This limitation, however, is gone in the OpenGL core profile (but still valid in the compatibility profile!). This means, that it is now legal in core profile (and only there) to call glDrawArrays() without a bound array buffer. A vertex array object on the other hand must be bound, the default vao 0 is not allowed for rendering (this in turn would be legal in the compatibility profile…).
A vertex shader with no explicit inputs has implicit inputs from the GL: gl_VertexID and gl_InstanceID. This can be sufficient to generate useful output positions either procedurally or with data from uniforms, textures etc.
Uses for attribute-less rendering would be simple objects that can be defined statically in the vertex shader (e.g. a screen filling quad). Also in cases where the datalayout has to be too complex for the default attribute fetching (so it might come from textures) or most of the work is done procedurally.


Let’s look at one example of a vertex shader that generates a quad when called with glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 ):

#version 330 core
const vec2 data[4] = vec2[]
  vec2(-1.0,  1.0),
  vec2(-1.0, -1.0),
  vec2( 1.0,  1.0),
  vec2( 1.0, -1.0)
void main()
  gl_Position = vec4( data[ gl_VertexID ], 0.0, 1.0);


While it can be useful to render without attributes, disallowing it in the compatibility profile is less useful. Historically it made sense to define rendering by providing data and it is also useful to keep the latest API 100% compatible with the old behavior. But, removing the limitation that attribute 0 (the vertex position) has to be defined will not break any working software but software that should not work would now ‘work’ (old buggy software that forgets to set attribute 0 will no longer receive an OpenGL error but will try to render something). On the other hand this would allow us to use attribute-less rendering together with GL_QUADS which are no longer present in the core profile (so in core an attribute-less screen filling quad has to be at least a GL_TRIANGLE_STRIP – less intuitive).
If you now test this and it works even in compatibility profile, you’re most likely to have a NVidia GPU, as NVidias drivers will accept this. They are wrong here and the ATI drivers are correct in not allowing attribute-less rendering in compatibility. Sadly, NVidia is more error tolerant than the spec – sounds great at first, but can be problematic when testing wrong code on other graphics cards (‘it worked before, that’s not my fault…’).
After some problems with this, in core attribute-less rendering works for both, ATI and NVidia cards. You can download the OpenGL sample pack from g-truc creation to test this on your card.

, , ,

One thought on “Attribute-less rendering
  • Tony says:

    Thanks for this! Every time I need a “fullscreen-quad” I hate the idea of setting up a vertex array, format, etc… so I’d take another stab at using gl_VertexID and never have any success. I guess I need to keep the explicit form around though for compatibility… :/

    Also, I noticed you have a post about the Rift on Linux… funny thing is my latest desire for a fullscreen-quad was due to writing gldemo (and now breaking out the gl/stereo/warp functionality for general use) for libovr_nsb — the lib is now in github, by the way:

Leave a Reply

Your email address will not be published. Required fields are marked *