Расположение вершин отключено при использовании профиля Mesa Core

Я использую Mesa 10.1.3, чтобы иметь возможность использовать OpenGL 3.3 на моем компьютере с Linux. Я запрашиваю основной профиль при создании окна, так как только основной профиль имеет OpenGL 3.3. Но когда я попытался написать простую программу для отображения треугольника на экране, я ничего не получил. Поэтому я подумал, что я где-то облажался в коде, но я перепроверил это, и это было правильно. Чтобы проверить это, я попытался запустить программу в Windows, и она работала как надо. Поэтому я немного больше экспериментировал с кодом; Я умножил расположение вершин в вершинном шейдере на 0,001, и только тогда я смог увидеть свой треугольник, но даже тогда он не работал должным образом. Треугольник, который я вижу, был прямоугольным, в то время как я хотел, чтобы он был равносторонним (в Windows я вижу равносторонний треугольник). Поэтому я предполагаю, что расположение вершин несколько отличается при использовании профиля OpenGL Core, но я не совсем знаю, как это исправить. Что я делаю не так и что я должен делать?

Кстати, это мой вершинный шейдер выглядит так:

#version 330

in vec3 position;

void main()
{
  gl_Position = vec4(0.001*position, 1.0);
}

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

#version 330

out vec4 fragColor;

void main()
{
  fragColor = vec4(0.0, 1.0, 1.0, 1.0);
}

Класс шейдеров:

public Shader()
    {
    program = glCreateProgram();
    if(program == 0)
    {
        System.err.println("Shader creation failed: Could not find valid memory location");
        System.exit(1);
    }
    }

    public void bind()
    {
    glBindAttribLocation(program, 0, "position");
    glUseProgram(program);
    }

    public void addVertexShader(String text)
    {
    addProgram(text, GL_VERTEX_SHADER);
    }

    public void addFragmentShader(String text)
    {
    addProgram(text, GL_FRAGMENT_SHADER);
    }

    public void addGeometryShader(String text)
    {
    addProgram(text, GL_GEOMETRY_SHADER);
    }

    public void compile()
    {
    glLinkProgram(program);

    if(glGetProgrami(program, GL_LINK_STATUS) == 0)
    {
        System.err.println(glGetProgramInfoLog(program, 1024));
        System.exit(1);
    }

    glValidateProgram(program);

    if(glGetProgrami(program, GL_VALIDATE_STATUS) == 0)
    {
        System.err.println(glGetProgramInfoLog(program, 1024));
        System.exit(1);
    }
    }

    public void addProgram(String text, int type)
    {
    int shader = glCreateShader(type);

    if(shader == 0)
    {
        System.err.println("Shader creation failed");
        System.exit(1);
    }

    glShaderSource(shader, text);
    glCompileShader(shader);

    if(glGetShaderi(shader, GL_COMPILE_STATUS) == 0)
    {
        System.err.println(glGetShaderInfoLog(shader, 1024));
        System.exit(1);
    }

    glAttachShader(program, shader);

    }

И мой массив вершин, с которым я создаю VBO:

Vertex[] data = new Vertex[] {            
new Vertex(new Vector3f(-0.1f, -0.1f, 0)),
new Vertex(new Vector3f(0,  1, 0)),
new Vertex(new Vector3f( 1,  -1, 0))};

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

public void draw()
{
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
//Vertex is a class which only holds a Vector3f for position, currently, so size is set to 3
glVertexAttribPointer(0, 3, GL_FLOAT, false, Vertex.SIZE * 4, 0);
glDrawArrays(GL_TRIANGLES, 0, size);
glDisableVertexAttribArray(0);
}

И вот результат, который я получаю:

1 ответ

Ваш glBindAttribLocation() звонок приходит слишком поздно:

glBindAttribLocation(program, 0, "position");
glUseProgram(program);

glBindAttribLocation() должен быть вызван до glLinkProgram() иметь какой-либо эффект. Вы можете переместить его или использовать glGetAttribLocation() после связывания получить местоположение, которое компоновщик назначил атрибуту. Или даже проще, так как вы используете GLSL 3.30, вы можете указать местоположение в коде шейдера:

layout(location = 0) in vec3 position;

При использовании Core Profile вам также необходимо использовать Vertex Array Objects (VAO). Если у вас нет звонков, как glGenVertexArrays() а также glBindVertexArray() в вашем коде они вам понадобятся. При поиске "OpenGL VAO" или "OpenGL Vertex Array Object" должно быть множество примеров здесь, в SO или в остальной части Интернета, поэтому я не буду повторять это слишком много. Грубо говоря, у вас будет что-то вроде этого, прежде чем вы начнете инициализировать свое состояние вершины:

GLuint vaoId = 0;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// calls to glVertexAttribPointer, glEnableVertexAttribArray

Тогда, когда вы будете готовы рисовать:

glBindVertexArray(vao);

Ваше определение данных вершин также выглядит так, как будто оно может быть источником проблем:

Vertex[] data = new Vertex[] {            
new Vertex(new Vector3f(-0.1f, -0.1f, 0)),
new Vertex(new Vector3f(0,  1, 0)),
new Vertex(new Vector3f( 1,  -1, 0))};

Хотя код для заполнения этого в VBO не отображается, данные передаются glBufferData() должен быть плоским непрерывным массивом / буфером с плавающей точкой, в то время как это массив ссылок на векторные объекты.

Другие вопросы по тегам