Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenGL: Single vertex attribute for multiple vertices?

I have a vertex shader that accepts the following attributes:

  • a_posCoord: vertex position
  • a_texCoord: texture coordinate (passed to the fragment shader)
  • a_alpha: transparency factor (passed to the fragment shader)

The objects I'm rendering are all "billboards" (a pair of right triangles to make a rectangle).

I'm using a single call to glDrawArrays to render many billboards, each which may have a unique alpha value. A single billboard has 6 vertices. Here's some pseudocode to illustrate how I organize the vertex attribute buffer for a single billboard:

vertexAttributes = [

  px1,py1,pz1, // vertex 1: a_posCoord
  tx1,ty1,     // vertex 1: a_texCoord
  alpha,       // vertex 1: a_alpha

  px2,py2,pz2, // vertex 2: a_posCoord
  tx2,ty2,     // vertex 2: a_texCoord
  alpha,       // vertex 2: a_alpha

  px3,py3,pz3, // vertex 3: a_posCoord
  tx3,ty3,     // vertex 3: a_texCoord
  alpha,       // vertex 3: a_alpha

  px4,py4,pz4, // vertex 4: a_posCoord
  tx4,ty4,     // vertex 4: a_texCoord
  alpha,       // vertex 4: a_alpha

  px5,py5,pz5, // vertex 5: a_posCoord
  tx5,ty5,     // vertex 5: a_texCoord
  alpha,       // vertex 5: a_alpha

  px6,py6,pz6, // vertex 6: a_posCoord
  tx6,ty6,     // vertex 6: a_texCoord
  alpha        // vertex 6: a_alpha

  // ... Many more billboards not shown ...
];

Notice how the same alpha value is repeated 6 times, once for each vertex.

Is there a way I can specify an attribute for all 6 vertices without repeating it for each individual vertex?

Here's what I want my vertex attribute buffer to look like, in the interest of reducing the size of the buffer:

vertexAttributes = [
  px1,py1,pz1, // vertex 1: a_posCoord
  tx1,ty1,     // vertex 1: a_texCoord

  px2,py2,pz2, // vertex 2: a_posCoord
  tx2,ty2,     // vertex 2: a_texCoord

  px3,py3,pz3, // vertex 3: a_posCoord
  tx3,ty3,     // vertex 3: a_texCoord

  px4,py4,pz4, // vertex 4: a_posCoord
  tx4,ty4,     // vertex 4: a_texCoord

  px5,py5,pz5, // vertex 5: a_posCoord
  tx5,ty5,     // vertex 5: a_texCoord

  px6,py6,pz6, // vertex 6: a_posCoord
  tx6,ty6,     // vertex 6: a_texCoord

  alpha        // vertex 1-6: a_alpha

  // ... Many more billboards not shown ...
];

For what it's worth, my current solution works just fine, but makes me feel dirty. I've only just begun to get a handle on using glVertexAttribPointer and was wondering if it somehow supported something like this, or if there's a different method or technique I could use to achieve something less brute-force.


This is more specifically a WebGL question, but I'm curious about OpenGL in the general sense.

I'm aware that a geometry shader is really what I need for this particular example, but it's out of the question since they are currently unsupported in WebGL.

like image 627
namuol Avatar asked Jan 05 '13 06:01

namuol


1 Answers

A vertex is not a position A vertex is a long vector consisting of multiplie attributes. Change one single attribute and you end up with a different vertex. So no, you can not use a single vertex attribute for multiple vertices, because that makes no sense semantically.

However what is possible with newer versions of OpenGL is setting the rate at which a certain vertex attribute's buffer offset advances. Effectively this means that the data for a given vertex array gets duplicated to n vertices before the buffer offset for a attribute advances. The function to set this divisor is glVertexAttribDivisor. In your case you'd set a Binding Divisor of 6 for the alpha array. But it's important that this does not use a single attribute for multiple vertices, but it makes OpenGL do that duplication you were doing for you.

like image 126
datenwolf Avatar answered Oct 12 '22 21:10

datenwolf