检索现有着色器属性时,glGetAttribLocation 返回 -1

2021-12-19 00:00:00 opengl c++ shader vertex-shader

我正在尝试将属性传递给我的顶点着色器,但由于某种原因,它一直在第三个属性位置给我一个 -1,我要求 openGl 通过 glGetAttribLocation() 进行检索.目前它一直给我一个 -1 的 texCoord 属性,如果我切换 texAttrib 和 colAttrib(切换代码中的行),它会给我一个 -1 的颜色属性而不是纹理,我不知道为什么?由于 -1 被传递给 glVertexAttribPointer,我得到了 1281 OpenGL 错误:GL_INVALID_VALUE.

I'm trying to pass in attributes to my vertex shader but for some reason it keeps giving me a -1 on the 3rd attribute location I'm asking openGl to retrieve via glGetAttribLocation(). Currently it keeps giving me a -1 for the texCoord attribute and if I switch the texAttrib and colAttrib around (switching the lines in code) it gives me a -1 on the color property instead of the texture and I have no idea why? Since a -1 is being passed to glVertexAttribPointer I get the 1281 OpenGL error: 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之前链接程序或使用明确的属性位置(如果您可以使用).

You should stop using glGetAttribLocation. Assign each attribute a location, either with glBindAttribLocation before linking the program or with explicit attribute locations, if that's available to you.

那样,如果编译器优化了一个属性(这就是这里发生的事情;您的片段着色器可能不使用内插值之一),您就不会在意.您将像往常一样使用属性索引的标准约定来设置数组.另外,每次要使用不同的程序进行渲染时,您都不必一直询问属性位置是什么;你知道它是什么位置,因为你分配了它.

That way, if the compiler optimizes an attribute away (which is what's happening here; your fragment shader probably doesn't use one of the interpolated values), you won't care. You'll set up your arrays as normal, using a standard convention for attribute indices. Plus, you won't have to keep asking what an attribute location is every time you want to render with a different program; you know what location it is because you assigned it.

如果你不能/不会,那么你无能为力.如果您实际上没有使用它们,编译器将优化掉它们.您唯一能做的就是检测它返回 -1 并且不为该属性设置数组.

If you can't/won't, then there's nothing you can do. The compiler will optimize away attributes if you're not actually using them. The only thing you can do is detect that it returns -1 and not set up the array for that attribute.

相关文章