Не удается получить идентификаторы, присвоенные атрибуту в OpenGL

0

Я пытаюсь, чтобы OpenGL автоматически присваивал ID атрибуту glsl, но он терпит неудачу.

Моя основная программа:

#include <iostream>

#include <GL/glew.h>
#include <GL/glfw3.h>

#include "test.h"
#include "shader_utils.h"

static void error_callback(int error, const char* description) {
    std::cout << description << std::endl;
}

static void key_callback(GLFWwindow* window, int a, int b) {
    if (a == GLFW_KEY_ESCAPE && b == GLFW_PRESS) {
        glfwSetWindowShouldClose(window, GL_TRUE);
    }
}

void test()
{
    std::cout << "Starting up" << std::endl;
    init();
    run();
}

GLFWwindow *window;
GLuint shaders;
GLuint vertexBuffer;

int init() {
    glfwSetErrorCallback(error_callback);

    if(!glfwInit()) {
        return -1;
    }

    window = glfwCreateWindow(640, 480, "GLFW test", NULL, NULL);
    if (!window)  {
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);
    glfwSetKeyCallback(window, key_callback);

    glewExperimental = true;
    glewInit();

    shaders = LoadShaders("vertex.glsl", "fragment.glsl");

    GLuint vao_id;
    glGenVertexArrays(1, &vao_id);
    glBindVertexArray(vao_id);


    static const GLfloat vertex_data[] = {
        // Bottom
        -.5f, -.5f, -.5f,   1.f, 0.f, 0.f,
        -.5f, -.5f,  .5f,   1.f, 0.f, 0.f,
         .5f, -.5f,  .5f,   1.f, 0.f, 0.f,
    };

    glGenBuffers(1, &vertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW);
}

void checkE() {
    std::cout << "Checking for errors: ";
    int err;
    int a = 0;
    while((err = glGetError()) != GL_NO_ERROR) {
        std::cout << "Error: " << err << std::endl;
        a = 1;
    }

    if(a == 0) {
        std::cout << "no errors" << std::endl;
    }
    std::cout.flush();
}

int run() {
    GLfloat angle = 0;

    while(!glfwWindowShouldClose(window)) {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glUseProgram(shaders);

        glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);

        GLuint attrLocation = glGetAttribLocation(shaders, "location");
        GLuint attrColor = glGetAttribLocation(shaders, "color");

        std::cout << "AttribLocation('location'): ";
        std::cout << glGetAttribLocation(shaders, "location") << std::endl;
        std::cout << "AttribLocation('color'): ";
        std::cout << glGetAttribLocation(shaders, "color") << std::endl;

        checkE();
        std::cout << std::endl;

        std::cout << "glEnableVertexAttribArray()" << std::endl;
        glEnableVertexAttribArray(attrLocation);
        glEnableVertexAttribArray(attrColor);

        checkE();
        std::cout << std::endl;

        std::cout << "glVertexAttribPointer();" << std::endl;

        glVertexAttribPointer(
                        glGetAttribLocation(shaders, "location"), // Attribute
                        3, // Size
                        GL_FLOAT, // Size
                        GL_FALSE, // Normalized
                        24, // Stride
                        (GLvoid*) 0 // Offset
                    );

        checkE();
        std::cout << std::endl;


        std::cout << "glVertexAttribPointer();" << std::endl;
        glVertexAttribPointer(
                        glGetAttribLocation(shaders, "color"),
                        3,
                        GL_FLOAT,
                        GL_FALSE,
                        24,
                        (GLvoid*) (3*sizeof(GLfloat))
                    );
        checkE();
        std::cout << std::endl;

        glDrawArrays(GL_TRIANGLES, 0, 3);

        checkE();
        std::cout << std::endl;

        glDisableVertexAttribArray(attrLocation);
        glDisableVertexAttribArray(attrColor);

        checkE();
        std::cout << std::endl;

        glfwSwapBuffers(window);
        glfwPollEvents();

        glfwSetWindowShouldClose(window, GL_TRUE);
    }

    glfwDestroyWindow(window);
    glfwTerminate();
}

Выход из программы:

Starting up
Compiling shader : vertex.glsl

Compiling shader : fragment.glsl

Linking program

AttribLocation('location'): -1
AttribLocation('color'): -1
Checking for errors: no errors

glEnableVertexAttribArray()
Checking for errors: Error: 1281

glVertexAttribPointer();
Checking for errors: Error: 1281

glVertexAttribPointer();
Checking for errors: Error: 1281

Checking for errors: no errors

Checking for errors: Error: 1281

Шейдерный погрузчик:

#include "shader_utils.h"

#include <string>
#include <iostream>
#include <fstream>
#include <vector>

#include "GL/glew.h"
#include "GL/glfw3.h"


GLuint LoadShaders(const char * vertex_file_path, const char * fragment_file_path){

    // Create the shaders
    GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
    GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);

    // Read the Vertex Shader code from the file
    std::string VertexShaderCode;
    std::ifstream VertexShaderStream(vertex_file_path, std::ios::in);
    if(VertexShaderStream.is_open())
    {
        std::string Line = "";
        while(getline(VertexShaderStream, Line))
            VertexShaderCode += "\n" + Line;
        VertexShaderStream.close();
    } else {
        std::cout << "could not open\n";
    }

    // Read the Fragment Shader code from the file
    std::string FragmentShaderCode;
    std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in);
    if(FragmentShaderStream.is_open()){
        std::string Line = "";
        while(getline(FragmentShaderStream, Line))
            FragmentShaderCode += "\n" + Line;
        FragmentShaderStream.close();
    }

    GLint Result = GL_FALSE;
    int InfoLogLength;

    // Compile Vertex Shader
    printf("Compiling shader : %s\n", vertex_file_path);
    char const * VertexSourcePointer = VertexShaderCode.c_str();
    glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
    glCompileShader(VertexShaderID);

    // Check Vertex Shader
    glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
    glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    std::vector<char> VertexShaderErrorMessage(InfoLogLength);
    glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
    fprintf(stdout, "%s\n", &VertexShaderErrorMessage[0]);

    // Compile Fragment Shader
    printf("Compiling shader : %s\n", fragment_file_path);
    char const * FragmentSourcePointer = FragmentShaderCode.c_str();
    glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL);
    glCompileShader(FragmentShaderID);

    // Check Fragment Shader
    glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
    glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    std::vector<char> FragmentShaderErrorMessage(InfoLogLength);
    glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
    fprintf(stdout, "%s\n", &FragmentShaderErrorMessage[0]);

    // Link the program
    fprintf(stdout, "Linking program\n");
    GLuint ProgramID = glCreateProgram();
    glAttachShader(ProgramID, VertexShaderID);
    glAttachShader(ProgramID, FragmentShaderID);
    glLinkProgram(ProgramID);

    // Check the program
    glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
    glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    std::vector<char> ProgramErrorMessage( std::max(InfoLogLength, int(1)) );
    glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
    fprintf(stdout, "%s\n", &ProgramErrorMessage[0]);

    glDeleteShader(VertexShaderID);
    glDeleteShader(FragmentShaderID);

    std::cout.flush();

    return ProgramID;
}

Vertex shader:

#version 130

in vec4 position;
in vec3 color;

out vec3 f_color;

void main() {
    f_color = color;

    gl_Position = position * gl_ModelViewProjectionMatrix;
}

Фрагментный шейдер:

#version 130

in vec3 color;

void main() {
    gl_FragColor = vec4(color, 1);
}

По какой-то причине я получаю только -1 как место для обоих атрибутов. Очевидно, что остальные ошибки вызваны недействительными индексами местоположения?

Из документов OpenGL:
If the named attribute variable is not an active attribute in the specified program object or if name starts with the reserved prefix "gl_", a value of -1 is returned.

Имена не начинаются с gl_ и они используются в шейдерах, поэтому я не должен получать значение -1. Что мне не хватает?

  • 3
    Начните с очевидного: первый атрибут называется «позиция» в шейдере, и вы запрашиваете атрибут «местоположение» в C-коде.
  • 1
    Вы должны также проверить значения * _STATUS значений компиляции / ссылки.
Показать ещё 4 комментария
Теги:
opengl
shader
glsl

1 ответ

3

Вы не можете получить местоположение атрибута для color потому что оно неактивно. Хотя верно, что color используется для вычисления f_color в этом примере, шейдер фрагмента не использует f_color поэтому компоновщик определяет, что атрибут вершины с именем: color неактивен.

Решение довольно простое:

Фрагментный шейдер:

#version 130

in vec3 f_color; // RENAMED from color, so that this matches the output from the VS.

void main() {
    gl_FragColor = vec4(f_color, 1);
}

Это не ошибка повторного использования color имени для разных целей в атрибутах Vertex Shader (входной атрибут вершины) и фрагментарных шейдеров (входных переменных), поэтому компилятор/компоновщик не будет жаловаться. Было бы ошибкой, если бы вы попытались сделать что-то наподобие inout color, поэтому, поэтому вам нужно передать атрибуты вершин в геометрию/тесселяцию/фрагментарные шейдеры, используя разные имена. Если имена ввода/вывода между этапами не совпадают, вероятность того, что исходный атрибут вершины будет считаться неактивной, будет весьма хороша.


Кроме того, если вы не переносите свою модель ModelViewProjection, у вас есть матричное умножение в вершинном шейдере назад. Большое умножение матрицы на столбцы, как использует OpenGL, должно читаться справа налево. То есть вы начинаете с позиции пространства объектов (самое правое) и преобразуете в пространство клипа (самое левое).

Другими словами, это правильный способ преобразования ваших вершин...

gl_Position = gl_ModelViewProjectionMatrix * position;

~~~~~~~~~~~   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~   ~~~~~~~~~
 clip space    object space to clip space    obj space
  • 0
    Это наименование было еще одним из тех, кто стал слепым к вашим собственным ошибкам ... Я думал, что они были одинаковыми, поэтому я не заметил

Ещё вопросы

Сообщество Overcoder
Наверх
Меню