最小可重复示例
#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()
是如何工作的,执行此操作的输出应该是:
aPos_layout 处的名称 (0):APos
vertCol_in_layout 处的名称 (1):VertCol_In
texCoord_in_layout 处的名称 (2):TexCoord_In
然而,事实并非如此。输出是:
aPos_layout 处的名称 (0):APos
vertCol_in_layout 处的名称 (1):TexCoord_In
texCoord_in_layout 处的名称 (2): VertCol_In
注意
vertCol_in_layout
和 texCoord_in_layout
的名称如何交换。虽然显然我已经知道我要从此 MRE 中获取索引的属性名称,但我在这里试图说明的一点是 glGetAttribLocation()
的 return
值或 glGetActiveAttribute()
的第二个参数是没有按照文档行事。
来自
glGetAttribLocation()
的文档:
参数
节目
指定要查询的程序对象。
索引
指定要查询的属性变量的索引。
来自
glGetActiveAttribute()
的文档:
查询由 program 指定的先前链接的程序对象以查找由 name 指定的属性变量,并返回绑定到该属性变量的通用顶点属性的索引glGetAttribLocation
这只是 GLFW/OpenGL 中的一个错误吗?我无法想象这种情况会如何发生,因为文档中的意图非常明确。那个或一些明显的问题正在发生,我在某种程度上是盲目的,作为一个对 OpenGL/GLFW 相当陌生的人,我愿意相信这一点。
输出中不存在冲突,因为活动属性的index和location不是同一件事。 OpenGL 文档经常重复使用“索引”一词来表示不同的概念,这可能会造成混乱。
在提供的代码中,首先是检索到的属性的 location,然后将其用作 glGetActiveAttribute
的
index。另请参阅这个答案,引用 Nicol Bolas:“在旧的内省 API 下,无法通过名称检索属性索引。因此您必须循环遍历属性列表才能找到它。”
来自文档:
指数是半开范围内的数字
。[0, GL_ACTIVE_ATTRIBUTES)
对于典型的顶点着色器自省,首先使用
glGetProgramiv
调用 GL_ACTIVE_ATTRIBUTES
以检索活动属性的总数,然后在循环中调用 glGetActiveAttrib
,其中 index
使用上面的半开范围。
属性的location与数据的布局方式有关,与
glBindAttribLocation
、glGetAttribLocation
、glVertexAttribPointer
等功能有关。一个属性(具有上述唯一索引)可以取多个位置(例如,对于 mat4
属性)。属性的位置也可以在着色器代码本身中指定。