Разрыв полигонов в OpenGL - PullRequest
       115

Разрыв полигонов в OpenGL

2 голосов
/ 21 октября 2019

500x500 сетка с 1000 подразделами:

img

Всего один вопрос.

Почему это происходит?

#include <iostream>
#include <sstream>
#include <vector>
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"

#include "GameEngine.hpp"
#include "ShaderProgram.h"
#include "Camera.h"
#include "Mesh.h"

const char *title = "Terrain";

GameEngine engine;
OrbitCamera orbitCamera;
float gYaw = 0.0f;
float gPitch = 1.0f;
float gRadius = 200.0f;
const float MOUSE_SENSTIVITY = 0.25f;

bool gWireFrame = false;
void glfw_onKey(GLFWwindow *window, int key, int scancode, int action, int mode);
void glfw_onMouseMove(GLFWwindow *window, double posX, double posY);
void glfw_onMouseScroll(GLFWwindow *window, double deltaX, double deltaY);

int main()
{
    if (!engine.init(1024, 768, title))
    {
        std::cerr << "OpenGL init failed" << std::endl;
        std::cin.get();
        return -1;
    }

    //set callbacks
    glfwSetKeyCallback(engine.getWindow(), glfw_onKey);
    glfwSetCursorPosCallback(engine.getWindow(), glfw_onMouseMove);

    std::vector<Vertex> VER;

    std::vector<glm::vec3> verts;
    std::vector<unsigned int> indices;
    std::vector<glm::vec3> norms;

    int subDiv = 1000;
    int width = 500;
    int height = 500;
    int size = 0;

    for (int row = 0; row < subDiv; row++)
    {
        for (int col = 0; col < subDiv; col++)
        {
            float x = (float)((col * width) / subDiv - (width / 2.0));
            float z = ((subDiv - row) * height) / subDiv - (height / 2.0);
            glm::vec3 pos = glm::vec3(x, 0, z);
            verts.push_back(pos);
        }
    }

    size = subDiv * subDiv;

    size = verts.size();

    for (int row = 0; row < subDiv -1 ; row++)
    {
        for (int col = 0; col < subDiv -1; col++)
        {
             int row1 = row * (subDiv);
            int row2 = (row+1) * (subDiv);

            indices.push_back(row1+col);
            indices.push_back(row1+col+1);
            indices.push_back( row2+col+1);

            indices.push_back(row1+col);
            indices.push_back( row2+col+1);
            indices.push_back(row2+col);
        }
    }


    for (int i = 0; i < verts.size(); i++)
    {
        Vertex vertex;
        vertex.position = verts[i];

        vertex.normal = glm::vec3(0, 0, 0);
        vertex.texCoords = glm::vec2(0, 0);

        VER.push_back(vertex);
    }

    VER.begin();

    for (int i = 0; i < indices.size(); i += 3)
    {
        Vertex a = VER[indices[i]];
        Vertex b = VER[indices[i + 1]];
        Vertex c = VER[indices[i + 2]];

        glm::vec3 p = glm::cross(b.position - a.position, c.position - a.position);

        VER[indices[i]].normal += p;
        VER[indices[i + 1]].normal += p;
        VER[indices[i + 2]].normal += p;
    }

    for (int i = 0; i < VER.size(); i++)
    {
        VER[i].normal = glm::normalize(VER[i].normal);
    }



    glm::vec3 cubePos = glm::vec3(0.0f, 0.0f, -5.0f);

    GLuint vbo, vao, ibo;

    glGenVertexArrays(1, &vao);
    glGenBuffers(1, &vbo);

    glBindVertexArray(vao);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, VER.size() * sizeof(Vertex), &VER[0], GL_STATIC_DRAW);


// Vertex Positions
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)0);
    glEnableVertexAttribArray(0);

    // Normals attribute
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)(3 * sizeof(GLfloat)));
    glEnableVertexAttribArray(1);

    // Vertex Texture Coords
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)(6 * sizeof(GLfloat)));
    glEnableVertexAttribArray(2);

    int n = indices.size() * sizeof(unsigned int);


    glGenBuffers(1, &ibo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);


    glBindVertexArray(0);

    ShaderProgram shaderProgram;
    shaderProgram.loadShaders("shaders/vert.glsl", "shaders/frag.glsl");
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    while (!glfwWindowShouldClose(engine.getWindow()))
    {

        glfwPollEvents();

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glm::mat4 model, view, projection;

        model = glm::mat4(1.0f);

        orbitCamera.setLookAt(glm::vec3(0, 0, 0));
        orbitCamera.rotate(gYaw, gPitch);
        orbitCamera.setRadius(gRadius);

        model = glm::translate(model, glm::vec3(0, 0, 0));
        //model = glm::scale(model, glm::vec3(1, 0, 1));

        //model = scaleMat;

        projection = glm::perspective(glm::radians(45.0f), (float)engine.getWidth() / (float)engine.getHeight(), 0.00001f, 100.0f);

        shaderProgram.use();
        glm::vec3 viewPos;
        viewPos.x = orbitCamera.getPosition().x;
        viewPos.y = orbitCamera.getPosition().y;
        viewPos.z = orbitCamera.getPosition().z;

        shaderProgram.setUniform("projection", projection);
        shaderProgram.setUniform("view", orbitCamera.getViewMatrix());
        shaderProgram.setUniform("model", model);
        shaderProgram.setUniform("lightPos", glm::vec3(5, 10, 10));
        shaderProgram.setUniform("viewPos", viewPos);

        glBindVertexArray(vao);
        glDrawElements(GL_TRIANGLES,indices.size(), GL_UNSIGNED_INT, 0);
        //glDrawArrays(GL_TRIANGLES, 0, VER.size());
        glBindVertexArray(0);

        glfwSwapBuffers(engine.getWindow());
    }

    //cleanup
    glDeleteVertexArrays(1, &vao);
    glDeleteBuffers(1, &vbo);

    glfwTerminate();
    return 0;
}

void glfw_onKey(GLFWwindow *window, int key, int scancode, int action, int mode)
{
    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
    {
        glfwSetWindowShouldClose(window, GL_TRUE);
    }

    if (key == GLFW_KEY_E && action == GLFW_PRESS)
    {
        gWireFrame = !gWireFrame;
        if (gWireFrame)
            glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
        else
            glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    }
}

void glfw_onMouseMove(GLFWwindow *window, double posX, double posY)
{
    static glm::vec2 lastMousePos = glm::vec2(0, 0);
    if (glfwGetMouseButton(engine.getWindow(), GLFW_MOUSE_BUTTON_LEFT) == 1)
    {
        gYaw -= ((float)posX - lastMousePos.x) * MOUSE_SENSTIVITY;
        gPitch += ((float)posY - lastMousePos.y) * MOUSE_SENSTIVITY;
    }
    if (glfwGetMouseButton(engine.getWindow(), GLFW_MOUSE_BUTTON_RIGHT) == 1)
    {
        float dx = 0.01f * ((float)posX - lastMousePos.x);
        float dy = 0.01f * ((float)posY - lastMousePos.y);
        gRadius += dx - dy;
    }
    lastMousePos.x = (float)posX;
    lastMousePos.y = (float)posY;
}

Этоэто основной код. Отдых - это просто инициализирующий код, ничего особенного. Я пытался изменить swapinterval, но это не проблема. Я могу поделиться кодом для других классов, если кто-то хочет взглянуть. И я также попытался понизить подразделение.

Редактировать *

После увеличения значения дальней плоскости до 8000:

img

Все еще не хрустящий.

Ответы [ 2 ]

2 голосов
/ 21 октября 2019

редактирование со вторым изображением говорит вам, что происходит ... если вмешательство в znear/zfar изменяет вывод таким образом, это означает, что ваш буфер глубины имеет низкую битовую пропускную способность для диапазона, который вы хотите использовать ...

Однако увеличение zfar должно усугубить ситуацию (вы просто по какой-то причине не видите его, может быть, его обрезка или какая-то странная особенность точности математики).

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

zfar/znear < (2^depth_buffer_bitwidth)/2
  1. проверить вас depth_buffer_bitwidth

    Попробуйте использовать 24 бита (вы можетеесть 16 бит прямо сейчас). Это должно работать на всех картах GFX в эти дни. Вы также можете попробовать 32 бита, но это будет работать только на новых картах. Я использую этот код, чтобы получить максимум, что я могу:

    Однако выиспользуя GLFW, так что вам нужно найти, как это сделать в ней ... возможно, в этом есть какая-то подсказка ...

  2. увеличить znear настолько, насколько вы можете

    вмешательство znear оказывает гораздо большее влияние, чем zfar ...

  3. Использование линейного буфера глубины

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

    однако для этого вам нужны шейдеры и новые API ... Iне думайте, что это выполнимо в старых API, но, к счастью, вы уже на новых API ...

  4. , если ничего из вышеперечисленного недостаточно,

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

0 голосов
/ 21 октября 2019

Как вы инициализируете OpenGL?

Используете ли вы GL_BLEND? Использование смешивания удобно для получения сглаженных ребер многоугольника, однако это также означает, что ваш z-буфер обновляется, даже когда рисуется очень полупрозрачный фрагмент. Это предотвращает рисование других непрозрачных фрагментов с такой же глубиной z, которые могут быть причиной этих дыр. Вы можете попробовать отключить GL_BLEND, чтобы увидеть, исчезнет ли проблема.

Какую функцию глубины вы используете? По умолчанию она установлена ​​на GL_LESS. Возможно, вы захотите попробовать glDepthFunc(GL_LEQUAL);, поэтому будут нарисованы фрагменты с одинаковой глубиной z. Однако из-за ошибок округления это может не полностью решить вашу проблему.

...