4

こんにちは、glDrawArraysInstanced() を使用して、多くの軸に沿った立方体をレンダリングしようとしています。固定サイズの各立方体は、その中心位置と色のみを変えることができます。また、各キューブはいくつかの異なる色しか取りません。したがって、次のインスタンス データごとに数百万のキューブを潜在的にレンダリングしたいと考えています。

struct CubeInfo {
  Eigen::Vector3f center; // center of the cube (x,y,z)
  int labelId;  // label of the cube which affects its color
};

したがって、次の頂点シェーダーを使用しています。

#version 330

uniform mat4 mvp_matrix;

//regular vertex attributes
layout(location = 0) in vec3 vertex_position;

// Per Instance variables
layout(location = 1) in vec3 cube_center;
layout(location = 2) in int cube_label;

// color out to frag shader
out vec4 color_out;

void main(void) {
  // Add offset cube_center
  vec4 new_pos = vec4(vertex_position + cube_center, 1);
  // Calculate vertex position in screen space
  gl_Position = mvp_matrix * new_pos;

  // Set color_out based on label
  switch (cube_label) {
  case 1:
    color_out = vec4(0.5, 0.25, 0.5, 1);
    break;
  case 2:
    color_out = vec4(0.75, 0.0, 0.0, 1);
    break;
  case 3:
    color_out = vec4(0.0, 0.0, 0.5, 1);
    break;
  case 4:
    color_out = vec4(0.75, 1.0, 0.0, 1);
    break;
  default:
    color_out = vec4(0.5, 0.5, 0.5, 1); // Grey
    break;
  }
}

および対応するフラグメント シェーダー:

#version 330

in vec4 color_out;
out vec4 fragColor;

void main()
{
    // Set fragment color from texture
    fragColor = color_out;
}

ただし、cube_label の値が 1 から 4 の間であっても、color_out は常にデフォルトの灰色の値を取ります。これは私の問題です。上記のシェーダーで何か間違ったことをしていますか?**

1 ~ 4 のランダムな labelId を使用して、cubeInfo vbo を初期化しました。したがって、次よりもカラフルな出力が表示されることを期待しています。 ここに画像の説明を入力

これは、Qt のQGLShaderProgramQGLBufferラッパーを利用する私のレンダリング コードです。

  // Enable back face culling
  glEnable(GL_CULL_FACE);
  cubeShaderProgram_.bind();

  // Set the vertexbuffer stuff (Simply 36 vertices for cube)
  cubeVertexBuffer_.bind();
  cubeShaderProgram_.setAttributeBuffer("vertex_position", GL_FLOAT, 0, 3, 0);
  cubeShaderProgram_.enableAttributeArray("vertex_position");
  cubeVertexBuffer_.release();

  // Set the per instance buffer stuff
  cubeInstanceBuffer_.bind();

  cubeShaderProgram_.setAttributeBuffer("cube_center", GL_FLOAT, offsetof(CubeInfo,center), 3, sizeof(CubeInfo));
  cubeShaderProgram_.enableAttributeArray("cube_center");
  int center_location = cubeShaderProgram_.attributeLocation("cube_center");
  glVertexAttribDivisor(center_location, 1);

  cubeShaderProgram_.setAttributeBuffer("cube_label", GL_INT, offsetof(CubeInfo,labelId), 1, sizeof(CubeInfo));
  cubeShaderProgram_.enableAttributeArray("cube_label");
  int label_location = cubeShaderProgram_.attributeLocation("cube_label");
  glVertexAttribDivisor(label_location, 1);

  cubeInstanceBuffer_.release();

  // Do Instanced Renering
  glDrawArraysInstanced(GL_TRIANGLES, 0, 36, displayed_num_cubes_ );

  cubeShaderProgram_.disableAttributeArray("vertex_position");
  cubeShaderProgram_.disableAttributeArray("cube_center");
  cubeShaderProgram_.disableAttributeArray("cube_label");

  cubeShaderProgram_.release();

上記の主な質問 (色の問題) は別として、これは Minecraft を行う良い方法ですか?

更新CubeInfo.labelId属性を からintに 変更し、対応する頂点floatシェーダー変数cube_labelfloatに変更すると、動作します!!。なぜそうなのですか?このページでは、GLSL サポーターは int 型と書かれています。私にとっては、labelId/cube_label を int/short にすることをお勧めします。

更新 2:

レンダリング コードの次の行で GL_INT の代わりに GL_FLOAT に変更しただけでも、適切な色が得られます。

cubeShaderProgram_.setAttributeBuffer("cube_label", GL_INT, offsetof(CubeInfo,labelId), 1, sizeof(CubeInfo));
4

2 に答える 2

2

ラベル属性の問題は、それが整数属性であることですが、整数属性として設定しないでください。Qt のsetAttributeBuffer関数は整数属性について何も知りません。それらはすべて内部で使用glVertexAttribPointerされ、頂点データを任意の形式で取得し、それを変換しfloatて属性に渡しますが、これはシェーダーin floatの と一致しません(したがって、in int属性はおそらくランダムなデフォルト値のままであるか、未定義の値を取得します)。

データを実際の整数頂点属性 (float 属性とはまったく異なるものであり、GL 3+ まで導入されなかった) に実際に渡すには、関数が必要ですglVertexAttribIPointer(そこにあることに注意してください。属性についてIも同様Din double、単に win GL_DOUBLE' を使用します)。この場合も機能しません)。しかし残念なことに、Qt はまだ GL 3+ に適合していないため、そのためのラッパーがないようです。したがって、次を使用して手動で行う必要があります。

glVertexAttribIPointer(cubeShaderProgram_.attributeLocation("cube_label"), 
                       1, GL_INT, sizeof(CubeInfo), 
                       static_cast<const char*>(0)+offsetof(CubeInfo,labelId));

cubeShaderProgram_.setAttributeBuffer呼び出しの代わりに、またはin float代わりに属性を使用します。

于 2013-10-06T10:36:40.827 に答える
0

頂点シェーダーで割り当てられた色を使用する場合は、少なくとも次のような単純なフラグメント シェーダーを記述する必要があります。

void main()
{
   gl_FragColor = color_out;
}

アップデート

cube_label を頂点シェーダーに渡すことができないか、そもそも (構造内で) それらを設定していないと思います。後者の可能性が高いですが、switch-case を次の行に置き換えて、渡された実際の値を確認できます。

color_out = vec4(float(cube_label) / 4.0, 0, 0, 1.0); 

Update2

Intel GPU(ドライバー)で同様の問題が発生したことがあります。何を試しても、整数値を渡すことができませんでした。ただし、同じシェーダーが NVIDIA で問題なく動作していたので、あなたの場合は int を float に変換しました。

于 2013-10-04T11:09:41.150 に答える