glGetActiveAttribute() 读取错误的属性索引?

问题描述 投票:0回答:1

最小可重复示例

    #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()
的文档:

glGetAttribLocation
查询由 program 指定的先前链接的程序对象以查找由 name 指定的属性变量,并返回绑定到该属性变量的通用顶点属性的索引

这只是 GLFW/OpenGL 中的一个错误吗?我无法想象这种情况会如何发生,因为文档中的意图非常明确。那个或一些明显的问题正在发生,我在某种程度上是盲目的,作为一个对 OpenGL/GLFW 相当陌生的人,我愿意相信这一点。

c++ opengl glfw
1个回答
0
投票

输出中不存在冲突,因为活动属性indexlocation不是同一件事。 OpenGL 文档经常重复使用“索引”一词来表示不同的概念,这可能会造成混乱。

在提供的代码中,首先是检索到的属性的 location,然后将其用作 glGetActiveAttribute

index
。另请参阅这个答案,引用 Nicol Bolas:“在旧的内省 API 下,无法通过名称检索属性索引。因此您必须循环遍历属性列表才能找到它。”


索引,与顶点着色器内省相关

来自文档

指数是半开范围内的数字

[0, GL_ACTIVE_ATTRIBUTES)

对于典型的顶点着色器自省,首先使用

glGetProgramiv
调用
GL_ACTIVE_ATTRIBUTES
以检索活动属性的总数,然后在循环中调用
glGetActiveAttrib
,其中
index
使用上面的半开范围。

地点

属性的location与数据的布局方式有关,与

glBindAttribLocation
glGetAttribLocation
glVertexAttribPointer
等功能有关。一个属性(具有上述唯一索引)可以取多个位置(例如,对于
mat4
属性)。属性的位置也可以在着色器代码本身中指定。

© www.soinside.com 2019 - 2024. All rights reserved.