13

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.

4

5 に答える 5

7

頂点は位置ではありません 頂点は、複数の属性で構成される長いベクトルです。1つの属性を変更すると、別の頂点になります。つまり、意味的に意味がないため、複数の頂点に単一の頂点属性を使用することはできません。

ただし、OpenGLの新しいバージョンで可能なことは、特定の頂点属性のバッファオフセットが進む速度を設定することです。事実上、これは、属性のバッファオフセットが進む前に、特定の頂点配列のデータがn個の頂点に複製されることを意味します。この除数を設定する関数はglVertexAttribDivisorです。あなたの場合、アルファ配列に6のバインディング除数を設定します。ただし、これが複数の頂点に単一の属性を使用しないことが重要ですが、OpenGLにあなたが行っていた複製を実行させます。

于 2013-01-05T12:25:51.490 に答える
0

いくつかのアイデア:

1.)弾丸を噛み、頂点バッファーを更新しますが、アルファが変更された場合のみです。

2.)クワッドのリストをバッチに分割し、変更されたバッチのみを再構築します。

3.)ビルボードの数を制御し、アルファ値の配列をユニフォームにバインドします...頂点データのアルファ、または未使用のチャネル/追加チャネルで、そのビルボードのアルファのインデックスを均一な配列。少なくともその方法では、n個のアルファ値のみをアップロードする可能性があります。

4.)2と3を組み合わせる...

私は大げさな推測をしているだけです...他の誰かが良い解決策を持っているかどうかを見たいです!

于 2013-02-25T18:24:58.160 に答える
0

If some vertex attribute is constant for each vertex, why don't you use an uniform variable? If it is constant, it is uniform! By this way you set the uniform value only once and your data set is reduced.

于 2013-01-05T07:06:05.387 に答える
0

I achieve this effect with instanced rendering. glVertexAttribDivisor(1); makes openGL read vertex attribute once per instance. If your bullboards have different geometry you may consider passing you model matrix as an attribute the same way as alpha.

于 2013-01-05T08:35:13.227 に答える
0

I haven't looked into this in detail but I think you could possibly also use glDrawElementsInstanced. With this you would put your alpha values into a big uniform array and the instance index would somehow be passed to the shader. Check this out:

http://sol.gfxile.net/instancing.html

于 2013-12-03T18:02:15.680 に答える