1. ホーム
  2. c++

[解決済み] glGetAttribLocationは、既存のシェーダーアトリビュートを取得する際に-1を返す。

2022-02-18 12:23:27

質問

頂点シェーダに属性を渡そうとしていますが、glGetAttribLocation()を使ってopenGlに取得を依頼した3番目の属性位置で、なぜか-1が返され続けています。現在、texCoord 属性に -1 を与え続け、texAttrib と colAttrib を入れ替えると(コードの行を入れ替える)、テクスチャではなく色のプロパティに -1 を与えてしまいますが、なぜなのでしょうか?glVertexAttribPointerに-1が渡されているので、1281のOpenGLエラーが発生します。gl_invalid_value.

私のバーテックスシェーダー。

#version 150

in vec3 position;
in vec3 color;
in vec2 texcoord;

out vec3 Color;
out vec2 Texcoord;

void main()
{
    Color = color;
    Texcoord = texcoord;
    gl_Position = vec4(position.x, position.y, position.z, 1.0);
}

OpenGLのコードです。

basicShader.Use();

// Buffers and shaders
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);

glGenBuffers(1, &vbo);
// Make it active vbo
glBindBuffer(GL_ARRAY_BUFFER, vbo);

// Build basic triangle
float vertices[] = {
    // position         // color          // textures
    -0.5f,  0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // Top-left
     0.5f,  0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // Top-right
     0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // Bottom-right
    -0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f// Bottom-left
};
GLuint elements[] = {
    0, 1, 2,
    2, 3, 0
};

glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

GLint posAttrib = glGetAttribLocation(basicShader.shaderProgram, "position");
glEnableVertexAttribArray(posAttrib); // Enable attribute first before specifiying attributes
glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), 0); // 6 float sizes is every new vertex

GLint colAttrib = glGetAttribLocation(basicShader.shaderProgram, "color");
glEnableVertexAttribArray(colAttrib);
glVertexAttribPointer(colAttrib, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float))); // same for color + offset

GLint texAttrib = glGetAttribLocation(basicShader.shaderProgram, "texcoord"); // Returns -1
glEnableVertexAttribArray(texAttrib);
glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float))); // 6 offset from beginning

[..]

解決方法は?

を使用しないようにする必要があります。 glGetAttribLocation . アサイン 各属性に場所を指定する のどちらか、または glBindAttribLocation をリンクする前に、あるいは明示的に属性の場所を指定することが可能であれば、それを使用します。

そうすれば、コンパイラが属性を最適化しなくなっても(ここで起こっているのは、フラグメントシェーダが補間された値の1つを使用しないことでしょう)、気にならなくなります。アトリビュートのインデックスに標準的な規約を使用して、通常通り配列をセットアップすることができます。さらに、異なるプログラムでレンダリングするたびに、アトリビュートの位置が何であるかを尋ね続ける必要がなくなります。 知っている を割り当てたので、その場所が何であるかがわかります。

できない/しようとしないのであれば、どうしようもありません。コンパイラは、実際に使っていない属性は最適化して取り除いてしまいます。唯一できることは、-1を返すことを検知して、その属性の配列をセットアップしないことです。