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

Posted

技术标签:

【中文标题】检索现有着色器属性时,glGetAttribLocation 返回 -1【英文标题】:glGetAttribLocation returns -1 when retrieving existing shader attribute 【发布时间】:2013-03-26 14:44:36 【问题描述】:

我正在尝试将属性传递给我的顶点着色器,但由于某种原因,它一直在第三个属性位置给我一个 -1,我要求 openGl 通过 glGetAttribLocation() 检索。目前它一直给我一个-1的texCoord属性,如果我切换texAttrib和colAttrib(切换代码中的行)它给我一个颜色属性而不是纹理的-1,我不知道为什么?由于将 -1 传递给 glVertexAttribPointer,我得到 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

[..]

【问题讨论】:

【参考方案1】:

您应该停止使用glGetAttribLocationAssign each attribute a location,在链接程序之前使用glBindAttribLocation,或者使用明确的属性位置,如果您可以使用的话。

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

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

【讨论】:

我明白了。从教程中得到了这一点(也许他们这样介绍它是为了让事情变得简单或什么?),变量确实被编译器优化了,使用 glBindAttribLocation 解决了这个问题。谢谢! :) 如果有人只使用 glBindAttribLocation 进行分配,它将不适用于 Radeon 卡。您需要直接使用 GLSL 代码中输入声明的布局进行分配。最近,我花了很多时间试图弄清楚为什么代码可以在 nVidia 上运行,而不是在 Radeon 卡上。似乎 AMD 家伙有点忽略了 glBindAttribLocation。 请注意在 Nvidia 卡上,我的驱动程序忽略了 glBindAttribLocation 和 GLSL 中给出的显式位置。只有当我真正确保使用顶点属性时,glGetAttribLocation 才会返回 -1。 @Balk:这很正常。如果你不使用属性,编译器可以随意丢弃它。

以上是关于检索现有着色器属性时,glGetAttribLocation 返回 -1的主要内容,如果未能解决你的问题,请参考以下文章

为啥找不到我的着色器属性?

glGetAttribLocation返回-1 [关闭]

OpenGL着色器的显式与自动属性位置绑定

将 uint 属性传递给 GLSL

openGL之API学习(一六七)默认着色器 顶点属性索引 别名索引

顶点着色器中属性的位置不正确