Как применить цвет к треугольнику с OpenGL - PullRequest
0 голосов
/ 08 ноября 2018

Я пытаюсь создать простую программу с openGL. Цель состоит в том, чтобы создать треугольник с цветами для каждой вершины. Проблема в том, что я не могу понять, как применить цвета к вершинам треугольника.

Мой вершинный шейдер:

#version 330

layout(location = 0) in vec4 vertex_position;
layout(location = 1) in vec4 vertex_color;

smooth out vec4 theColor;

void main()
{
    gl_Position = vec4(vertex_position.x, vertex_position.y, vertex_position.z, 1.0);
    theColor = vertex_color;
}

Мой фрагментный шейдер:

#version 330

smooth in vec4 theColor;
out vec4 outColor;
void main()
{
    outColor = theColor;
}

основной код:

    float vertices[] = {
                -0.5f, -0.5f, 0.0f,
                0.5f, -0.5f, 0.0f,
                0.0f, 0.5f, 0.0f,
                0.5f, 0.6f, 0.1f,
                0.2f, 0.6, 0.3f,
                0.1f, 0.23f, 0.78f
            };

        GLuint my_vao, my_vbo;
                glGenVertexArrays(1, &my_vao);
                glBindVertexArray(my_vao);
                glGenBuffers(1, &my_vbo);
                glBindBuffer(GL_ARRAY_BUFFER, my_vbo);
                glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
                glEnableVertexAttribArray(0);
            //  glEnableVertexAttribArray(1);
                glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), (void*)0);
            //  glVertexAttribPointer(3,4, GL_UNSIGNED_BYTE, GL_TRUE, 0, (void*)0);

    glClear(GL_COLOR_BUFFER_BIT);
    glUseProgram(shaderProgram);
    glBindVertexArray(vao);
    glViewport(0, 0, viewport_width, viewport_height);
    glDrawArrays(GL_TRIANGLES, 0, 3);
    swapBuffers();

Вершины массива состоят из точек вершин (первые 3 вектора) и значений цвета (вторые 3 вектора). Вы можете увидеть мой результат на следующей картинке:

Simple Triangle

Я пытался применить цвета с помощью следующего кода:

glEnableVertexAttribArray(1);
glVertexAttribPointer(3,4, GL_UNSIGNED_BYTE, GL_TRUE, 0, (void*)0);

К сожалению, это не работает, и я понятия не имею, как это исправить. Может ли кто-нибудь помочь мне здесь?

Для компиляции и загрузки моих шейдеров я использую:

    std::string loadVertexShader(const char* vertexPath)
    {
        std::string vertexCode;
        std::ifstream vShaderFile;
        vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
        try
        {
            vShaderFile.open(vertexPath);
            std::stringstream vShaderStream;
            vShaderStream << vShaderFile.rdbuf();
            vShaderFile.close();
            vertexCode = vShaderStream.str();
        }
        catch (std::ifstream::failure e)
        {
            std::cout << "ERROR::VERTEXSHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl;
        }
        return vertexCode;
    }

int vertexShader = glCreateShader(GL_VERTEX_SHADER);
        int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
        std::string vertexVal = loadVertexShader("shader/vertexshader.shader");
        const char* vShaderCode = vertexVal.c_str();
        std::string fragmentVal = loadFragmentShader("shader/fragmentshader.shader");
        const char* fShaderCode = fragmentVal.c_str();
        glShaderSource(vertexShader, 1, &vShaderCode, NULL);
        glCompileShader(vertexShader);
        glShaderSource(fragmentShader, 1, &fShaderCode, NULL);
        glCompileShader(fragmentShader);

GLint vertexStatus;
        char vertexInfoLog[512];
        char fragmentInfoLog[512];
        glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &vertexStatus);
        GLint fragmentStatus;
        glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &fragmentStatus);

        if (!vertexStatus)
        {
            glGetShaderInfoLog(vertexShader, 512, NULL, fragmentInfoLog);
            std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << fragmentInfoLog << std::endl;
        }

        if (!fragmentStatus)
        {
            glGetShaderInfoLog(fragmentShader, 512, NULL, vertexInfoLog);
            std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << vertexInfoLog << std::endl;
        }

1 Ответ

0 голосов
/ 08 ноября 2018

Прежде всего, как было показано в обсуждении в комментариях, вы не связываете свою программу. Типичная настройка программы шейдера выглядит следующим образом:

GLuint program = glCreateProgram();
glAttachShader(program, shader1);
glAttachShader(program, shader2);
...
glAttachShader(program, shaderN);
glLinkProgram(program); // <<<<<<<<< a-ha!

После этого хорошей идеей является проверка работоспособности программной связи. Хороший пример полной настройки шейдеров и программы можно найти на OpenGL wiki .

После успешного связывания программы вы даже можете отсоединить шейдеры от программы (glDetachShader) и удалить их (glDeleteShader) - программа уже связана, шейдеры теперь бесполезны (если вы не собираетесь присоединять их). в другую программу, конечно).


Во-вторых, ваши аргументы к glVertexAttribPointer слегка испорчены (что вполне нормально - требуется время и усилия, чтобы привыкнуть к ним).

void glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized,
    GLsizei stride, const GLvoid * pointer);
  • index - это индекс атрибута - такой же, как location, как указано в шейдере, поэтому для вашего атрибута цвета это должно быть 1.
  • size - размерность атрибута, то есть количество компонентов; Предположим, что вы используете 3-float RGB, размер должен быть 3
  • type - фактический тип компонентов; в вашем случае это тоже с плавающей точкой, так что GL_FLOAT
  • stride - это расстояние между атрибутами соседних вершин, которое в вашем случае составляет 3 числа с плавающей запятой, т.е. 12 байт; поскольку между соседними атрибутами в вашем массиве vertices нет ничего, мы можем фактически оставить этот ноль (как для координат, так и для цветов)
  • pointer - указатель на фактические данные атрибутов (или, в вашем случае, смещение в VBO); вы передаете один и тот же указатель на оба вызова glVertexAttribPointer, в то время как ваши значения цвета равны 9 числам с плавающей точкой после начала значений координат

Итак, должно быть

glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (float const *)(nullptr) + 9);
...