OpenGL Попытка визуализировать куб, но между плоскостями есть странные линии - PullRequest
0 голосов
/ 05 января 2019

рендеринг куба

Эй, я думаю, что может быть ошибка в том, как я отправляю данные в вершину, или в том, как мои индексы упорядочены с помощью GL_CCW

struct Vertex
{
    glm::vec3 position;
    glm::vec3 color;
    glm::vec3 normal;
};

Вершины, использующие структуру Vertex

Vertex vertices[] =
{   
/*FRONT SQUARE*/
    ///BOTTOM LEFT
glm::vec3(-0.5f, -0.5f, 1.f), glm::vec3(1.f, 0.f, 0.f), glm::vec3(0.f, 0.f, 1.f),

    ///bottom RIGHT
    glm::vec3(0.5f, -0.5f, 1.0f), glm::vec3(1.f, 0.f, 0.f), glm::vec3(0.f, 0.f, 1.f),
    ////TOP RIGHT
    glm::vec3(0.5f, 0.5f, 1.0f), glm::vec3(1.f, 0.f, 0.f), glm::vec3(0.f, 0.f, 1.f),
    ///TOP LEFT
    glm::vec3(-0.5f, 0.5f, 1.0f), glm::vec3(1.f, 0.f, 0.f), glm::vec3(0.f, 0.f, 1.f),

    ///BOTTOM LEFT
    glm::vec3(-0.5f, -0.5f, -1.f), glm::vec3(1.f, 0.f, 0.f), glm::vec3(0.f, 0.f, 1.f),

    ///bottom RIGHT
    glm::vec3(0.5f, -0.5f, -1.0f), glm::vec3(1.f, 0.f, 0.f), glm::vec3(0.f, 0.f, 1.f),
    ////TOP RIGHT
    glm::vec3(0.5f, 0.5f, -1.0f), glm::vec3(1.f, 0.f, 0.f), glm::vec3(0.f, 0.f, 1.f),
    ///TOP LEFT
    glm::vec3(-0.5f, 0.5f, -1.0f), glm::vec3(1.f, 0.f, 0.f), glm::vec3(0.f, 0.f, 1.f)

};

unsigned noOfVertices = sizeof(vertices) / sizeof(Vertex);

Это мой порядок индексов

GLuint indices[] =
{
    // /front face

    0, 1, 2,
    2, 3, 0,

    // right
    1, 5, 6,
    6, 2, 1,
    // back
    7, 6, 5,
    5, 4, 7,
    // left
    4, 0, 3,
    3, 7, 4,
    // bottom
    4, 5, 1,
    1, 0, 4,
    // top
    3, 2, 6,
    6, 7, 3


};

unsigned noOfIndices = sizeof(indices) / sizeof(GLuint);

Основная функция и инициализация окна

  int main()
    {

Окно инициализации

    ///initialise GLFW for Window
    if (glfwInit() == GLFW_FALSE)
    {
        std::cout << "ERROR::GLFW-INTI::FAILED" << "\n";
        glfwTerminate();
    }

    ///Create window with functions
    GLFWwindow* window;
    const int window_height = 480;
    int window_width = 680;
    int framebuffer_height = window_height;
    int framebuffer_width = window_width;
    char* title = "mytutorial";

    int GLverMAJ = 3;
    int GLverMin = 3;

    ///sets how  the window should be drawn and which hints
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, GLverMAJ);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, GLverMin);
    glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);

    ///create the window with the previously set options
    window = glfwCreateWindow(window_width, window_height, title, NULL, NULL);

    //checks if window created
    if (window == nullptr)
    {
        std::cout << "ERROR:::GLFWCREATEWINDOWFAILED" << "\n";
    }

    ///sets the frame buffer size
    glfwGetFramebufferSize(window, &framebuffer_width, &framebuffer_height);
    glfwMakeContextCurrent(window);

    //need to read on this part
    glewExperimental = GL_TRUE;

    //initiliase the glew
    if (glewInit() != GLEW_OK)
    {
        std::cout << "ERROR::GLEWINIT::FAILED" << "\n";
    }

initiliase opengl options

///enable functions first
        glEnable(GL_DEPTH_TEST);
        glEnable(GL_BLEND);
        glEnable(GL_CULL_FACE);

        //initialise the enabled  functions
        glCullFace(GL_BACK);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glDepthFunc(GL_LESS);

        ///set the way its draw
        glFrontFace(GL_CCW);

        ///set the polygon mode and fill ////Set as GL_LINE TO LOOK AT CUBE MESH
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

Здесь я инициализирую матрицы вид, проект и модель
/// инициализируем матрицы

    ///view
    ///front, position, up then use in lookat
    glm::vec3 cameraPos(0.f, 0.f, 1.f);
    glm::vec3 cameraUp(0.f, 1.f, 0.f);
    glm::vec3 cameraFront(0.f, 0.f, -0.1f);

    glm::mat4 ViewMatrix(1.f);
    ViewMatrix = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp);

    ///set up prespective projection

    float fov = 90.f;
    float nearPlane = -1.f;
    float farPlane = 1000.f;

    ///projection
    glm::mat4 ProjectionMatrix(1.f);
    ProjectionMatrix = glm::perspective(glm::radians(fov), static_cast<float>(framebuffer_width / framebuffer_height), nearPlane, farPlane);


    //Model Matrix
    glm::mat4 ModelMatrix(1.f);

Затем я создаю свои шейдеры

    ///set up SHADERS
    char infolog[512];
    GLint success;

    GLuint Vertexshader = glCreateShader(GL_VERTEX_SHADER);
    ///std::string str_src = 

    std::string temp = "";
    std::string src = "";
    std::ifstream infile;
    infile.open("vert.glsl");
    if (infile.is_open())
    {
        while (std::getline(infile, temp))
            src += temp + "\n";

    }
    infile.close();

    const GLchar* source = src.c_str();

    ///link created shader with shader source
    glShaderSource(Vertexshader, 1, &source, NULL);
    glCompileShader(Vertexshader);

    ///error check compilation status
    glGetShaderiv(Vertexshader, GL_COMPILE_STATUS, &success);

    if (!success)
    {
        glGetShaderInfoLog(Vertexshader, 512, NULL, infolog);
        std::cout << infolog;
    }



    success = 0;

    GLuint FragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    ///std::string str_src = 

    temp = "";
    src = "";
    infile.open("frag.glsl");
    if (infile.is_open())
    {
        while (std::getline(infile, temp))
            src += temp + "\n";

    }
    infile.close();

    source = src.c_str();

    ///link created shader with shader source
    glShaderSource(FragmentShader, 1, &source, NULL);
    glCompileShader(FragmentShader);

    ///error check compilation status
    glGetShaderiv(FragmentShader, GL_COMPILE_STATUS, &success);

    if (!success)
    {
        glGetShaderInfoLog(FragmentShader, 512, NULL, infolog);
        std::cout << infolog;
    }

Свяжите созданные шейдеры с программой

     ///create and link the program
    success = 0;
    GLuint programID;

    programID = glCreateProgram();

    glAttachShader(programID, Vertexshader);
    glAttachShader(programID, FragmentShader);

    glLinkProgram(programID);

    glGetProgramiv(programID, GL_LINK_STATUS, &success);
    if (!success)
    {
        glGetProgramInfoLog(programID, 512, NULL, infolog);
        std::cout << "ERROR::SHADER::COULD_NOT_LINK_PROGRAM" << "\n";
        std::cout << infolog << "\n";

    }

после связывания неиспользуемых и удаляемых буферов

///after linking we unuse the program and delete the shaders
    glUseProgram(0);
    glDeleteShader(Vertexshader);
    glDeleteShader(FragmentShader);

Это где я начинаю VAO VBO И EBO

///vbo, ebo and vertex array
    GLuint VAO;
    GLuint VBO;
    GLuint EBO;

    //gen and bind vao
    glGenVertexArrays(1, &VAO);
    glBindVertexArray(VAO);


    ///gen vbo
    glGenBuffers(1, &VBO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, noOfVertices * sizeof(Vertex), vertices, GL_STATIC_DRAW);


    ///gen EBO
    glGenBuffers(1, &EBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, noOfIndices * sizeof(GLuint), indices, GL_STATIC_DRAW);

Это та часть, где я чувствую, что может быть проблема

    ///tell  buffer where data is located
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, position));
    glEnableVertexAttribArray(0);

    //colour
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, color));
    glEnableVertexAttribArray(1);

    glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, normal));
    glEnableVertexAttribArray(2);

    glBindVertexArray(0);

    ///use program send in uniforms to the shader.
    glUseProgram(programID);

    ///GLuint s = glGetUniformLocation(programID, "ViewMatrix");
    GLuint s = glGetUniformLocation(programID, "ModelMatrix");
    glUniformMatrix4fv(s, 1, GL_FALSE, glm::value_ptr(ModelMatrix));

    s = glGetUniformLocation(programID, "ProjectionMatrix");
    glUniformMatrix4fv(s, 1, GL_FALSE, glm::value_ptr(ProjectionMatrix));

    s = glGetUniformLocation(programID, "ViewMatrix");
    glUniformMatrix4fv(s, 1, GL_FALSE, glm::value_ptr(ViewMatrix));

    glUseProgram(0);
    ///main while loop
    while (!glfwWindowShouldClose(window))
    {
        //clear
        glClearColor(0.f, 0.f, 0.f, 1.f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

        ///draw
        glfwPollEvents();



        glUseProgram(programID);
        glBindVertexArray(VAO);


        glDrawElements(GL_TRIANGLES, noOfIndices, GL_UNSIGNED_INT, 0);

        ///flush

        glfwSwapBuffers(window);
        glFlush();


    ///unuse

        glBindVertexArray(0);
        glUseProgram(0);
    }



    return 0;
}

Ответы [ 2 ]

0 голосов
/ 05 января 2019

И ближняя, и дальняя плоскости должны быть положительными значениями для glm::perspective, а static_cast<float>(framebuffer_width / framebuffer_height) будет целым делением:

float fov = 90.f;
float nearPlane = 0.1f; // 0.1 instead of -1.0
float farPlane = 1000.f;

glm::mat4 ProjectionMatrix(1.f);
ProjectionMatrix = glm::perspective(glm::radians(fov), 
    static_cast<float>(framebuffer_width) / static_cast<float>(framebuffer_height),
    nearPlane, farPlane); 

См. glm::perspective:

GLM_FUNC_DECL mat<4, 4, T, defaultp> glm::perspective(
      T     fovy,
      T     aspect,
      T     near,
      T     far 
  )

[...]
near Указывает расстояние от зрителя до ближней плоскости отсечения (всегда положительное).
far Указывает расстояние от зрителя до дальней плоскости отсечения (всегда положительное).


Библиотека glm предоставляет матричные операции, связанные с OpenGL и GLSL. Документация glm API относится к Спецификация языка затенения OpenGL 4.20 .

См. Язык затенения OpenGL 4.6, 5.4.2 Векторные и матричные конструкторы, стр. 101 :

Чтобы инициализировать матрицу путем указания векторов или скаляров, компоненты присваиваются элементам матрицы в мажорном порядке столбцов.

mat4(float, float, float, float,  // first column
       float, float, float, float,  // second column
       float, float, float, float,  // third column
       float, float, float, float); // fourth column

Это означает, что преобразование координаты вершины в вершинном шейдере должно быть:

gl_Position = ProjectionMatrix * ViewMatrix * ModelMatrix * vec4(vertex_position,1.0);

См. Также Программирование GLSL / Векторные и матричные операции :

Скорее всего, матрицу можно будет транспонировать при установке на униформу, установив для 3-го параметра glUniformMatrix4fv значение GL_TRUE:

GLuint s = glGetUniformLocation(programID, "ModelMatrix");
glUniformMatrix4fv(s, 1, GL_TRUE, glm::value_ptr(ModelMatrix));

s = glGetUniformLocation(programID, "ProjectionMatrix");
glUniformMatrix4fv(s, 1, GL_TRUE, glm::value_ptr(ProjectionMatrix));

s = glGetUniformLocation(programID, "ViewMatrix");
glUniformMatrix4fv(s, 1, GL_TRUE, glm::value_ptr(ViewMatrix));

И вычислить преобразование координат вершины в обратном порядке:

gl_Position = vec4(vertex_position,1.0) * ModelMatrix * ViewMatrix * ProjectionMatrix;

Далее, порядок наматывания граней куба a по часовой стрелке, поэтому он должен быть:

glFrontFace(GL_CCW);
glFrontFace(GL_CW);


Измените положение камеры на

glm::vec3 cameraPos(0.f, 0.f, 2.f);

и вы получите следующий результат:

0 голосов
/ 05 января 2019

Мне кажется, что ваша программа работает правильно. Если я не ошибаюсь, то ваша камера находится внутри куба, смотря прямо с позиции одной из граней на грань на другой стороне. То, что вы видите, это именно то, что можно ожидать в этом случае. В центре изображения у вас есть два треугольника, которые образуют обратную сторону лица, из которого вы смотрите. Полученные вами «странные линии» - это просто края треугольников, которые образуют другие грани. Поскольку ваша камера находится внутри куба, эти грани обязательно доходят до всей вашей камеры, и все отсекается в ближней плоскости, где вы получаете внешний прямоугольник, который «охватывает» все.

Все немного раздавлено, потому что это

static_cast<float>(framebuffer_width / framebuffer_height)

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

Кроме того, я не уверен, что именно вы ожидаете от эффекта использования отрицательного значения для ближней плоскости. Скорее всего, это также не то, что вы на самом деле хотите, я предлагаю вам использовать какое-то положительное значение, например, 0.1f there & hellip; ?

...