Как использовать glm::ortho?

145
28 апреля 2019, 19:40

Хочу получить результат, как, например, в Blender, в ортогональном режиме

Но нормально работает только обычная матрица проекции

projection = glm::perspective(glm::radians(70.0f), (float)res[1] / (float)res[0], 0.1f, 100.0f);

При попытках использования ортогональной матрицы, просто ничего не отображается

projection = glm::ortho(0.0f, (float)res[0], 0.0f, (float)res[1], 0.1f, 100.0f);

Находил в интернете разные варианты использования glm::ortho (аргументы в другом порядке), но ничего не помогло.

Что может быть не так?

Ниже код рендера и вершинный шейдер.

void renderScene()
{
    glm::mat4 view;
    glm::mat4 projection;
    view = activeCamera->getViewMatrix();
    //projection = glm::perspective(glm::radians(70.0f), (float)res[1] / (float)res[0], 0.1f, 100.0f);
    projection = glm::ortho(0.0f, (float)res[0], 0.0f, (float)res[1], 0.1f, 100.0f);
    unsigned int ID = shaders[0]->ID;
    glUseProgram(ID);
    for (unsigned int _m = 0; _m < models_size; _m++)
    {
        Model *_model = models[_m];
        Mesh *_mesh = _model->mesh;
        glm::mat4 model;
        model = glm::translate(model, *_model->position);
        model = glm::scale(model, glm::vec3(_model->scale->x, _model->scale->y, _model->scale->z));
        model = glm::rotate(model, glm::radians(_model->rotation->x), glm::vec3(1.0f, 0.0f, 0.0f));
        model = glm::rotate(model, glm::radians(_model->rotation->y), glm::vec3(0.0f, 1.0f, 0.0f));
        model = glm::rotate(model, glm::radians(_model->rotation->z), glm::vec3(0.0f, 0.0f, 1.0f));
        glUseProgram(ID);
        glUniform3fv(glGetUniformLocation(ID, "viewPos"), 1, &activeCamera->position[0]);
        glUniformMatrix4fv(glGetUniformLocation(ID, "projection"), 1, GL_FALSE, &projection[0][0]);
        glUniformMatrix4fv(glGetUniformLocation(ID, "view"), 1, GL_FALSE, &view[0][0]);
        glUniformMatrix4fv(glGetUniformLocation(ID, "model"), 1, GL_FALSE, &model[0][0]);
        //for (int i = 0; i < _material->sizes.tex; i++) // Activating each texture of material
        //{
        glActiveTexture(GL_TEXTURE0 + 0);
        const char *name = "myTex"; // uniform name
        glUniform1i(glGetUniformLocation(ID, name), 0); // shaderID, tex uniform name
        glBindTexture(GL_TEXTURE_2D, texId); // tex id
        //}
        glBindVertexArray(_mesh->VAO);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _mesh->EBO);
        glDrawElements(GL_TRIANGLES, _mesh->indicesNum, GL_UNSIGNED_INT, NULL);
        glBindVertexArray(0);
        glActiveTexture(GL_TEXTURE0);
    }
}

========================================

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoords;
out vec2 TexCoords;
out vec3 FragPos;
out vec3 Normal;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
    FragPos = vec3(model * vec4(aPos, 1.0));
    Normal = mat3(transpose(inverse(model))) * aNormal;  
    TexCoords = aTexCoords;
    gl_Position = projection * view * vec4(FragPos, 1.0);
}
Answer 1

Изображение отсутствует из-за неправильно выставленной области проекции.

Вы задали её координаты в предположении, что экран покрывает область (0; 0) – (w; h). На самом же деле OpenGL отображает участок (-1; 1) – (1; −1), деформируя его при неквадратных пропорциях области вывода:

    

Источник: OpenGL | Android Developers

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

Для расчёта правильных параметров glm::ortho() надо выполнить два шага:

  1. Задать область проекции равной области вывода:

    glm::ortho(-1.0f, 1.0f, -1.0f, 1.0f, 0.1f, 100.0f);
               ^^^^^  ^^^^  ^^^^^  ^^^^
    
  2. Учесть пропорции экрана. Без этого изображение будет растянутым из-за вышеупомянутой деформации. Чтобы этого не было, мы сжимаем ось x настолько, насколько OpenGL её потом растянет:

    const float aspect = (float)res[0] / (float)res[1];
    projection = glm::ortho(-1.0f, 1.0, -1.0f * aspect, 1.0f * aspect, 0.1f, 100.0f);
                                                ^^^^^^         ^^^^^^
    

И ещё. Так как в прямоугольной проекции нет такого понятия, как угол обзора, охват сцены можно менять исключительно масштабированием видимой части сцены:

const float n = ...;
projection = glm::ortho(-n, n, -n * aspect, n * aspect, 0.1f, 100.0f);
                        ^^  ^  ^^           ^
READ ALSO
Не создаются значения в реестре

Не создаются значения в реестре

У меня есть два QSettings в разных файлах, у одного все значения передаются в реестр, а другого - нет

170
Организация MVC в c++

Организация MVC в c++

Пытаюсь использовать паттерн MVCКак лучше организовать хранение модели и представления в контроллере? Вижу 2 варианта:

145
Немного запутался с типами при создании функции которая принимает строку в виде массива

Немного запутался с типами при создании функции которая принимает строку в виде массива

Не могу понять где наапортачилТолько начал изучать С++ и предомной стоит такая задача, найти количество букы "а" в строке которая передаётся...

120