最小可重现示例:
#include <iostream>
#include "glad.h"
#include <glfw3.h>
int main(int argc, char* args[])
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
auto window = glfwCreateWindow(800, 600, "Example", NULL, NULL);
glfwMakeContextCurrent(window);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
throw new std::runtime_error("Failed to initialize GLAD");
const char* vertexSrc = "#version 330 core\n"
"in vec3 APos;\n"
"in vec3 VertCol_In;\n"
"out vec3 VertCol;\n"
"in vec2 TexCoord_In;\n"
"out vec2 TexCoord;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(APos.x, APos.y, APos.z, 1.0);\n"
" VertCol = VertCol_In;\n"
" TexCoord = TexCoord_In;\n"
"}\0";
auto vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexSrc, NULL);
glCompileShader(vertexShader);
const char* fragSrc = "#version 330 core\n"
"out vec4 FragColor;\n"
"in vec3 VertCol;\n"
"in vec2 TexCoord;\n"
"void main()\n"
"{\n"
" FragColor = vec4(VertCol.x,TexCoord.xy, 1.0f);\n"
"}\0";
auto fragShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragShader, 1, &fragSrc, NULL);
glCompileShader(fragShader);
auto prog = glCreateProgram();
glAttachShader(prog, vertexShader);
glAttachShader(prog, fragShader);
glLinkProgram(prog);
auto aPos_layout = glGetAttribLocation(prog, "APos");
auto vertCol_in_layout = glGetAttribLocation(prog, "VertCol_In");
auto texCoord_in_layout = glGetAttribLocation(prog, "TexCoord_In");
GLenum type;
GLsizei length;
GLint size;
const GLuint bufSize = 16;
GLchar bufA[bufSize];
GLchar bufB[bufSize];
GLchar bufC[bufSize];
glGetActiveAttrib(prog, aPos_layout, bufSize, &length, &size, &type, bufA);
std::cout << "Name at aPos_layout ("<<aPos_layout<<"): " << bufA << "\n";
glGetActiveAttrib(prog, vertCol_in_layout, bufSize, &length, &size, &type, bufB);
std::cout << "Name at vertCol_in_layout ("<<vertCol_in_layout<<"): "<<bufB << "\n";
glGetActiveAttrib(prog, texCoord_in_layout, bufSize, &length, &size, &type, bufC);
std::cout << "Name at texCoord_in_layout ("<<texCoord_in_layout<<"): " << bufC << "\n";
return 0;
}
据我理解glGetActiveAttrib()
及其glGetAttribLocation()
工作原理,执行此操作的输出应该是:
Name at aPos_layout (0): APos
Name at vertCol_in_layout (1): VertCol_In
Name at texCoord_in_layout (2): TexCoord_In
但事实并非如此。输出结果如下:
Name at aPos_layout (0): APos
Name at vertCol_in_layout (1): **TexCoord_In**
Name at texCoord_in_layout (2): **VertCol_In**
请注意和处的名称vertCol_in_layout
texCoord_in_layout
是如何互换的。虽然我显然已经知道在这个 MRE 中获取索引的属性名称,但我在这里试图说明的一点是glGetAttribLocation()
的return
值或glGetActiveAttribute()
的第二个参数并未按照文档操作。
来自glGetAttribLocation()
的文档:
参数
程序
指定要查询的程序对象。index
指定要查询的属性变量的索引。
来自glGetActiveAttribute()
的文档:
glGetAttribLocation
查询程序指定的先前链接的程序对象以获取由名称指定的属性变量,并返回与该属性变量绑定的通用顶点属性的索引
这仅仅是 GLFW/OpenGL 中的一个错误吗?我无法想象这种情况会如何发生,因为文档中的意图非常明确。或者某些明显的问题出在了我不知何故视而不见的地方,作为一个对 OpenGL/GLFW 还很陌生的人,我愿意相信这一点。
输出中没有冲突,因为索引(在 中使用
glGetActiveAttrib
)和活动属性的位置不是同一回事。OpenGL 文档也将位置的值称为“索引”,这可能会造成混淆。在提供的代码中,首先检索属性的位置,然后将其用作的索引
glGetActiveAttribute
。另请参阅此答案,引用 Nicol Bolas 的话:“在旧的自省 API下,无法通过名称检索属性索引。”换句话说,代码试图做的事情是不可能的。索引,与顶点着色器自省相关
来自文档:
对于典型的顶点着色器自省,首先
glGetProgramiv
调用来GL_ACTIVE_ATTRIBUTES
检索活动属性的总数,然后glGetActiveAttrib
在循环中调用index
范围超过上述半开范围的函数。地点
属性的位置与数据的布局方式有关,也与、、等函数有关。一个属性(具有如上所示的唯一索引)可以占用多个位置(例如,对于一个属性)。属性的位置也可以在着色器代码本身中指定。
glBindAttribLocation
glGetAttribLocation
glVertexAttribPointer
mat4