Фрагмент шейдера dr aws сталкивается друг с другом, хотя не должен - PullRequest
2 голосов
/ 13 января 2020

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

Что он делает, так это игнорирует z-значение, и dr aws сталкивается с тем, чтобы они были заданы индексным буфером. Под этим я подразумеваю, что если есть, например, буфер условного индекса, и он содержит треугольник 1, треугольник 2 и треугольник 3, и они стоят в ряду перед камерой, то треугольник 3, независимо от его значения z, будет нарисован поверх двух других, потому что он последний.

В результате я стал таким: enter image description here

Это изображение показывает, что я имею в виду. Лицевая сторона ведет себя как прозрачная относительно соседней стороны, но в терминах прозрачности она игнорирует параллельную сторону, потому что они нарисованы в таком порядке.

Мой код для камеры:

PCamera::PCamera(GLFWwindow* projectWindow, float windowWidth, float windowHeight)
{
    window = projectWindow;
    wWidth = windowWidth;
    wHeight = windowHeight;

    Position = glm::vec3(0.f, 0.f, -10.f);
    Rotation = glm::vec3(0.f, glm::pi<float>(), 0.f);

    if (glfwRawMouseMotionSupported())
        glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);

    glfwGetCursorPos(window, &xposnormal, &yposnormal);
}

PCamera::~PCamera()
{
}

glm::mat4 PCamera::NavigateCamera()
{   
    double xpos, ypos;
    int state;

    glfwGetCursorPos(window, &xpos, &ypos);

    state = glfwGetKey(window, GLFW_KEY_ESCAPE);
    if (state == GLFW_PRESS) 
    { 
        bMouseControl = false; 
        glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
    }
    state = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT);
    if ((state == GLFW_PRESS) && (bMouseControl == false))
    { 
        bMouseControl =  true;
        glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); 
        glfwGetCursorPos(window, &xposnormal, &yposnormal);
    }

    if (bMouseControl)
    {
        glfwGetCursorPos(window, &xpos, &ypos);

        Rotation.x += (float)(yposnormal - ypos) / -300.f;
        Rotation.y += (float)(xposnormal - xpos) / -300.f;

        glfwSetCursorPos(window, xposnormal, yposnormal);
    }

    glm::mat4 RTSMatrix =   glm::rotate(UnitMatrix, Rotation.x, glm::vec3(1.f, 0.f, 0.f)) * glm::rotate(UnitMatrix, Rotation.y, glm::vec3(0.f, 1.f, 0.f));

    glm::vec3 DeltaPosition(0.f, 0.f, 0.f);

    state = glfwGetKey(window, GLFW_KEY_W);
    if (state == GLFW_PRESS)        DeltaPosition.z += 0.01f;

    state = glfwGetKey(window, GLFW_KEY_S);
    if (state == GLFW_PRESS)        DeltaPosition.z -= 0.01f;

    state = glfwGetKey(window, GLFW_KEY_A);
    if (state == GLFW_PRESS)        DeltaPosition.x += 0.01f;

    state = glfwGetKey(window, GLFW_KEY_D);
    if (state == GLFW_PRESS)        DeltaPosition.x -= 0.01f;

    state = glfwGetKey(window, GLFW_KEY_LEFT_SHIFT);
    if (state == GLFW_PRESS)        DeltaPosition.y -= 0.01f;

    state = glfwGetKey(window, GLFW_KEY_SPACE);
    if (state == GLFW_PRESS)        DeltaPosition.y += 0.01f;

    glm::vec4 D4Position(Position, 0.f);

    glm::mat4 InverseRTSMatrix = glm::rotate(UnitMatrix, -Rotation.y, glm::vec3(0.f, 1.f, 0.f)) * glm::rotate(UnitMatrix, -Rotation.x, glm::vec3(1.f, 0.f, 0.f));
    D4Position -= InverseRTSMatrix*glm::vec4(DeltaPosition, 0.0);

    Position.x = D4Position.x;
    Position.y = D4Position.y;
    Position.z = D4Position.z;

    RTSMatrix = RTSMatrix * glm::translate(UnitMatrix, -Position);

    return RTSMatrix;
}

void PCamera::UpdateProjectionMatrix(float Angle, float windowWidth, float windowHeight)
{
    ProjectionMatrix = glm::perspective(Angle, (GLfloat)windowWidth / (GLfloat)windowHeight, -1.0f, 1.0f);
}

Код моего рендерера:

void PRenderer::Draw(PObject * Object)
{
    Object->Bind();
    glDrawElements(GL_TRIANGLES, Object->IBCount, GL_UNSIGNED_INT, nullptr);
}

Код моего основного исполняемого файла:

PProject::PProject(PRenderer * Renderer)
{
    ProjectRenderer = Renderer;
}

PProject::~PProject()
{
}

int PProject::Launch()
{
    GLFWwindow* window;

    if (!glfwInit())                    return -1;

    window = glfwCreateWindow(640, 480, "PhysMaker", NULL, NULL);

    if (!window) { glfwTerminate(); return -1; }

    glfwMakeContextCurrent(window);

    if (glewInit() != GLEW_OK)          return -1;

    float pos[] =
    {
        -0.5, -0.5, -0.5,           1.0, 0.0, 0.0,
        -0.5, -0.5,  0.5,           0.0, 1.0, 0.0,
        -0.5,  0.5,  0.5,           0.0, 0.0, 1.0,
        -0.5,  0.5, -0.5,           1.0, 0.0, 1.0,

         0.5,  0.5,  0.5,           1.0, 0.0, 1.0,
         0.5, -0.5,  0.5,           1.0, 1.0, 0.0,
         0.5, -0.5, -0.5,           1.0, 0.0, 0.0,
         0.5,  0.5, -0.5,           0.0, 1.0, 1.0,

         0.5, -0.5,  0.5,           1.0, 0.0, 0.0,
        -0.5, -0.5,  0.5,           0.0, 1.0, 0.0,
         0.5,  0.5,  0.5,           0.0, 0.0, 1.0,
        -0.5,  0.5,  0.5,           1.0, 0.0, 0.0
    };

    unsigned int ind[]
    {
        0, 1, 2,
        2, 3, 0,

        6, 5, 4,
        4, 7, 6,

        8, 9, 10,
        9, 11, 10
    };

    PShader NewShader("Source/Shaders/Vertex.shader","Source/Shaders/Fragment.shader");
    NewShader.Bind();

    glfwGetWindowSize(window, &windowWidth, &windowHeight);

    PCamera MainCamera(window, windowWidth, windowHeight);

    PObject NewObject(pos, 24, ind, 18, 0);
    ProjectRenderer->SceneObjects.insert(ProjectRenderer->SceneObjects.end(), &NewObject);

    while (!glfwWindowShouldClose(window))
    {
        glfwGetWindowSize(window, &windowWidth, &windowHeight);
        glViewport(0, 0, windowWidth, windowHeight);

        glClear(GL_COLOR_BUFFER_BIT);
        glClearColor(0.3f, 0.3f, 0.3f, 1.0f);

        MainCamera.UpdateProjectionMatrix(45.f, windowWidth, windowHeight);
        glm::mat4 translation = MainCamera.ProjectionMatrix * MainCamera.NavigateCamera();
        glUniformMatrix4fv(glGetUniformLocation(NewShader.Shader_ID, "u_MVP"), 1, GL_FALSE, &translation[0][0]);

        ProjectRenderer->Draw(&NewObject);

        glfwSwapBuffers(window);

        glfwPollEvents();
    }
        glfwTerminate();
        return 0;
}

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

#FRAGMENT
#version 330 core

out vec4 color;
in vec3 vertexColor;

void main()
{
    color = vec4(vertexColor, 1.0);;
}

#VERTEX
#version 330 core

in layout(location = 0) vec3 position;
in layout(location = 1) vec3 Color;
out vec3 vertexColor;

uniform mat4 u_MVP;

void main()
{
    gl_Position = (u_MVP * vec4(position, 1.f));
    vertexColor = Color;
}

Возможно что-то не так с перспективой? Должен ли я использовать глубину и как? Я использовал это раньше, но это не помогло. Кажется, что-то с матрицей проекции. Итак, что не так?

1 Ответ

3 голосов
/ 13 января 2020

Вы должны включить Проверка глубины . Если проверка глубины включена, то глубина фрагмента проверяется по глубине записываемого образца. Если это не удается, фрагмент отбрасывается.
Проверка глубины является глобальным состоянием. Достаточно включить его один раз, перед циклом приложения;

glEnable(GL_DEPTH_TEST);

После того, как проверка глубины включена, вы также должны очистить буфер глубины:
(см. glClear )

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
...