1. ホーム
  2. opengl

[解決済み] テスト

2022-01-28 09:17:37

質問

private int vbo;
private int ibo;

vbo = glGenBuffers();
ibo = glGenBuffers();

glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, Util.createFlippedBuffer(vertices), GL_STATIC_DRAW);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, Util.createFlippedBuffer(indices), GL_STATIC_DRAW);




glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
//glEnableVertexAttribArray(2);

//glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(0, 3, GL_FLOAT, false, Vertex.SIZE * 4, 0);
glVertexAttribPointer(1, 2, GL_FLOAT, false, Vertex.SIZE * 4, 12);
//glVertexAttribPointer(2, 3, GL_FLOAT, false, Vertex.SIZE * 4, 20);

//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_INT, 0);

glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
//glDisableVertexAttribArray(2);

バーテックスシェーダのコードは次のようになります。

#version 330

layout (location = 0) in vec3 position;
layout (location = 1) in vec2 texCoord;

out vec2 texCoord0;

uniform mat4 transform;

void main()
{
    gl_Position = transform * vec4(position, 1.0);
    texCoord0 = texCoord;
}

ということで、私の理解は以下の通りです。glVertexAttribPointerの目的は、頂点バッファオブジェクトのデータの形式を定義することです。つまり、vboでは以下のようにデータが格納されます。

buffer.put(vertices[i].getPos().getX());
buffer.put(vertices[i].getPos().getY());
buffer.put(vertices[i].getPos().getZ());
buffer.put(vertices[i].getTexCoord().getX());
buffer.put(vertices[i].getTexCoord().getY());
buffer.put(vertices[i].getNormal().getX());
buffer.put(vertices[i].getNormal().getY());
buffer.put(vertices[i].getNormal().getZ());

つまり、glVertexAttribPointer が 2 行あるのは、バーテックスシェーダで 2 つの変数が定義されているからです。つまり、この 2 つの変数が指すものを定義しているのです。つまり、最初の glVertexAttribPointer は、最初の変数 "position" が、それぞれ float である 3 つの座標を持つ頂点であることを定義しています。2番目のglVertexAttribPointerは、2番目の変数 "texCoord"が、それぞれfloatであるテクスチャ座標の組であることを定義しています。もし、私の理解がこれまでのところ正しければ、最初に頂点バッファオブジェクトをバインドする必要があると仮定していましたが、この行をコメントアウトした後でも

glBindBuffer(GL_ARRAY_BUFFER, vbo);

はまだ動作しています。私は混乱しています。2つのVBOがあるので、どのようにどちらのバッファオブジェクトについて話しているのかを知ることができるのでしょうか?

解決方法は?

この点については、@datenwolf がすでに上のコメントで触れています。もう少し詳しく説明します。

あなたは ない をバインドする必要があります。 GL_ARRAY_BUFFER の前にもう一度 glDrawElements() を呼び出します。重要なのは、与えられた属性をソースにしたいバッファが glVertexAttribPointer() を呼び出すと、その属性が表示されます。

これをイメージするのに最適なのは、この呼び出しを行うときです。

glVertexAttribPointer(0, 3, GL_FLOAT, false, Vertex.SIZE * 4, 0);

は、属性0(第1引数)のデータをどこから取得し、どのように読み取るかをOpenGLに伝えるために必要なすべての状態を指定していることになります。その状態の大部分は、引数によって直接与えられます。

  • 3つの要素で構成されています。
  • コンポーネントは浮動小数点数です。
  • 頂点は20バイトのストライドで読み込まれ...
  • ... バッファの 0 バイトから開始します。

しかし、さらに暗黙の了解で、呼び出したときに属性0の状態も保存されているのです。

  • にバインドされているバッファからデータが読み込まれます。 GL_ARRAY_BUFFER

つまり、各属性に関連する状態には、属性データの出典であるバッファのIDが含まれる。これは、複数の/すべての属性に対して同じバッファであることも、各属性に対して異なるバッファであることも可能です。

の場合は、同じではないことに注意してください。 GL_ELEMENT_ARRAY_BUFFER . こちらは、バインドされた時点で glDrawElements() を呼び出します。多少矛盾しているように見えますが、これは必要なことです。 glVertexAttribPointer() をインデックス配列に使用します。このような呼び出しができるようにAPIを定義することもできたはずですが、...そうではありませんでした。その理由は、複数の頂点バッファを使用できる一方で、1つの描画呼び出しには1つのインデックス配列しか使用できないため、単純に必要なかったという可能性が高いです。