Матрица вращения с OpenGL 4

0

Я пытаюсь повернуть треугольник с помощью OpenGL 4 с использованием матриц, но треугольник, кажется, обращается в противоположном направлении на полпути. Это, очевидно, не вращение направлений, поэтому я должен иметь буфер глубины где-то. Я попытался разрешить это, но я не нашел примеров вращения с OpenGL 4, только те, которые используют амортизированные функции. Вот мой код:

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <stdio.h>
#include <math.h>
#include <iostream>
#include "maths_funcs.h"
#include "maths_funcs.cpp"

const char* vertex_shader =
"#version 400\n"
"layout(location = 0) in vec3 vertex_position;"
"layout(location = 1) in vec3 vertex_colour;"
"uniform mat4 pmatrix;"
"uniform mat4 rmatrix;"
"uniform mat4 smatrix;"
"out vec3 colour;"
"void main () {"
"  colour = vertex_colour;"
"  gl_Position = smatrix * rmatrix * vec4 (vertex_position, 1.0);"
"}";

const char* fragment_shader =
"#version 400\n"
"in vec3 colour;"
"out vec4 frag_colour;"
"void main () {"
"  frag_colour = vec4 (colour, 1.0);"
"}";

float angle = 0.0f;

int main () {
    // start GL context and O/S window using the GLFW helper library
    if (!glfwInit ()) {
        fprintf (stderr, "ERROR: could not start GLFW3\n");
        return 1;
    } 

    GLFWwindow* window = glfwCreateWindow (640, 480, "Triangle Rotation test", NULL, NULL);
    if (!window) {
        fprintf (stderr, "ERROR: could not open window with GLFW3\n");
        glfwTerminate();
        return 1;
    }
    glfwMakeContextCurrent (window);

    // start GLEW extension handler
    glewExperimental = GL_TRUE;
    glewInit ();

    // get version info
    const GLubyte* renderer = glGetString (GL_RENDERER); // get renderer string
    const GLubyte* version = glGetString (GL_VERSION); // version as a string
    printf ("Renderer: %s\n", renderer);
    printf ("OpenGL version supported %s\n", version);

    // tell GL to only draw onto a pixel if the shape is closer to the viewer
    glEnable (GL_DEPTH_TEST); // enable depth-testing
    glDepthFunc (GL_LESS); // depth-testing interprets a smaller value as "closer"

    float points[] = {
        0.0f,  0.5f,  0.0f,
        0.5f, -0.5f,  0.0f,
        -0.5f, -0.5f,  0.0f
    };

    float colours[] = {
        1.0f, 0.0f,  0.0f,
        0.0f, 1.0f,  0.0f,
        0.0f, 0.0f,  1.0f
    };

    float pmatrix[] = {
        1.0f, 0.0f, 0.0f, 0.0f,
        0.0f, 1.0f, 0.0f, 0.0f, 
        0.0f, 0.0f, 1.0f, 0.0f, 
        0.0f, 0.0f, 0.0f, 1.0f
    };

    float rmatrix[] = {
        cos(10), 0.0f, sin(10), 0.0f,
        0.0f, 1.0f, 0.0f, 0.0f, 
        -sin(10), 0.0f, cos(10), 0.0f, 
        0.0f, 0.0f, 0.0f, 1.0f
    };

    float smatrix[] = {
        1.0f, 0.0f, 0.0f, 0.0f,
        0.0f, cos(10), sin(10), 0.0f, 
        0.0f, -sin(10), cos(10), 0.0f, 
        0.0f, 0.0f, 0.0f, 1.0f
    };

    GLuint vbo = 0;
    glGenBuffers (1, &vbo);
    glBindBuffer (GL_ARRAY_BUFFER, vbo);
    glBufferData (GL_ARRAY_BUFFER, 9 * sizeof (float), points, GL_STATIC_DRAW);

    unsigned int colours_vbo = 0;
    glGenBuffers (1, &colours_vbo);
    glBindBuffer (GL_ARRAY_BUFFER, colours_vbo);
    glBufferData (GL_ARRAY_BUFFER, 9 * sizeof (float), colours, GL_STATIC_DRAW);

    GLuint vao = 0;
    glGenVertexArrays (1, &vao);
    glBindVertexArray (vao);
    glEnableVertexAttribArray (0);
    glBindBuffer (GL_ARRAY_BUFFER, vbo);
    glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
    glBindBuffer (GL_ARRAY_BUFFER, colours_vbo);
    glVertexAttribPointer (1, 3, GL_FLOAT, GL_FALSE, 0, NULL);

    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);

    GLuint vs = glCreateShader (GL_VERTEX_SHADER);
    glShaderSource (vs, 1, &vertex_shader, NULL);
    glCompileShader (vs);
    GLuint fs = glCreateShader (GL_FRAGMENT_SHADER);
    glShaderSource (fs, 1, &fragment_shader, NULL);
    glCompileShader (fs);

    GLuint shader_programme = glCreateProgram ();
    glAttachShader (shader_programme, fs);
    glAttachShader (shader_programme, vs);
    glLinkProgram (shader_programme);

    int pmatrix_location = glGetUniformLocation (shader_programme, "pmatrix");
    int rmatrix_location = glGetUniformLocation (shader_programme, "rmatrix");
    int smatrix_location = glGetUniformLocation (shader_programme, "smatrix");

    while (!glfwWindowShouldClose (window)) {
        // wipe the drawing surface clear
        glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glUseProgram (shader_programme);
        rmatrix[0] = cos(angle);
        rmatrix[2] = sin(angle);
        rmatrix[8] = -sin(angle);
        rmatrix[10] = cos(angle);

        smatrix[5] = cos(angle);
        smatrix[6] = sin(angle);
        smatrix[9] = -sin(angle);
        smatrix[10] = cos(angle);
        glUniformMatrix4fv (pmatrix_location, 1, GL_FALSE, pmatrix);
        glUniformMatrix4fv (rmatrix_location, 1, GL_FALSE, rmatrix);
        glUniformMatrix4fv (smatrix_location, 1, GL_FALSE, smatrix);
        glBindVertexArray (vao);
        // draw points 0-3 from the currently bound VAO with current in-use shader
        glDrawArrays (GL_TRIANGLES, 0, 3);
        // update other events like input handling 
        glfwPollEvents ();
        // put the stuff we've been drawing onto the display
        glfwSwapBuffers (window);

        angle+=0.01f;
        if (angle >= 3.14f) {
            angle = -3.14f;
        }
    }

    // close GL context and any other GLFW resources
    glfwTerminate();
    return 0;
}
  • 0
    Это не похоже на то, что это как-то связано с вашим буфером глубины ... однако вы, похоже, применяете масштабирование и поворот в неправильном порядке в вашем вершинном шейдере. предполагая, что это то, что s и r должны обозначать?
  • 0
    Хорошо, r - это вращение, а s - еще одна матрица вращения. Если я использую только одну из них, то треугольник все еще появляется, чтобы изменить направление на полпути.
Показать ещё 1 комментарий
Теги:
opengl
matrix

1 ответ

1
Лучший ответ

Поскольку вы не используете матрицу проекций, вам нужно инвертировать z-координату в вашем вершинном шейдере. Измените эту строку:

gl_Position = smatrix * rmatrix * vec4 (vertex_position, 1.0);

Что-то вроде этого:

vec4 eyePos = smatrix * rmatrix * vec4 (vertex_position, 1.0);
gl_Position = vec4(eyePos.xy, -eyePos.z, eyePos.w);

Значение gl_Position находится в координатах клипов, которые после деления на w приводят к NDC (нормализованные координаты устройства). Хотя мировые координаты обычно задаются в правой системе координат, при этом ось z указывает на экран, NDC - левая система координат, ось z направлена на экран.

Типичные преобразования проекций заботятся о переворачивании z-координат из экрана из экрана в экран. Но если вы не используете преобразование проекции, вам нужно перевернуть z-координату самостоятельно.

Кроме того, вы можете дважды проверить, что у вас действительно есть буфер глубины. Возможно, добавьте это перед glfwCreateWindow():

glfwWindowHint(GLFW_DEPTH_BITS, 24);

Основываясь на том, что я мог найти в документации GLFW, это, вероятно, значение по умолчанию. Но это не помешало указать его явно.

Ещё вопросы

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