Код OpenGL не показывает то же самое каждый раз? - PullRequest
0 голосов
/ 27 декабря 2018

При запуске программы два раза, она не отображает тот же результат во время выполнения, даже если я использую тот же исполняемый файл.

Вот немного контекста:

Я программирую на MacAir с Sierra 10.13, и моя IDE - Xcode 10.1.

Я понял, что моя проблема вызвана добавлением матрицы преобразования в вершинный шейдер:

// This code is not working
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec2 textureCoords;

out vec2 pass_textureCoords;

uniform mat4 transformM;

void main() {
    gl_Position = transformM * vec4(position, 1.0);
    pass_textureCoords = textureCoords;
}

И я загружаю матрицу transformM таким образом (я использую библиотеку GLM для математики):

void LoadMatrix(int location, glm::mat4 matrix) {
    glUniformMatrix4fv(location, 1, GL_FALSE, &matrix[0][0]);
}

, где location :

uniformName = "transformM";
location = glGetUniformLocation(_shaderID, uniformName.c_str());

(Я сохранил это простым, но вы можете найти полный код здесь: https://github.com/Cuiyere/Ecosystem)

На самом деле, я ожидаю, что мой код отобразит куб и повернет его, но это не такпоявляется примерно в 50% случаев.

Я не понимаю, ПОЧЕМУ эта проблема возникает. Я проверял свой код сто раз, проверял сайт docs.gl, сравнивал код ThinMatrix с моим (даже если оннаписано на Java, общая структура и функции OpenGL остаются практически неизменными), проверилФорумы OpenGL, но, насколько я понимаю, никто никогда не сталкивался с этой проблемой.

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

1 Ответ

0 голосов
/ 27 декабря 2018

конструктор по умолчанию glm::mat4 не инициализирует матрицу.До вызова void Renderer::CreateProjectionMatrix() в конструкторе class Render, _projectionMatrix не инициализируется.

Метод void Renderer::CreateProjectionMatrix() не инициализирует все поля матрицы _projectionMatrix.Неинициализированные поля в матрице вызывают неопределенное поведение.

Назначьте единичную матрицу на _projectionMatrix в начале функции, чтобы обеспечить инициализацию всех полей:

void Renderer::CreateProjectionMatrix() {

    _projectionMatrix = glm::mat4(1.0f);

    // [...]
}

Или используйте конструктор для инициализации матрицы:

Renderer::Renderer (Shaders::StaticShader shader)
    : _projectionMatrix(1.0f)
{
    CreateProjectionMatrix();
    // [...]
} 

Но обратите внимание, если метод с именем CreateProjectionMatrix, он должен установить все поля члена _projectionMatrix.


Далее необходимо инициализировать элементы _position, _pitch, _yaw и _roll из class Camera в конструкторе:

Camera()
  : _position(0.0f, 0.0f, 0.0f)
  , _pitch(0.0f)
  , _yaw(0.0f)
  , _roll(0.0f)
{}; 

Вметод ShaderProgram::CompileShader это еще одна проблема.Тип возвращаемого значения ShaderProgram::ReadShader: std::string.Так что ReadShader( shaderPath ).c_str() вернет указатель на временный объект, который уничтожается сразу в конце оператора присваивания.Объект std::string разрушается, и указатель нигде не указывает.

Назначьте возвращаемое значение ShaderProgram::ReadShader локальной переменной и используйте указатель на содержимое этой локальной переменной int в области действия ShaderProgram::CompileShader:

unsigned int ShaderProgram::CompileShader (unsigned int type, const std::string & shaderPath) {
    unsigned int id = glCreateShader(type);

    std::string code = ReadShader( shaderPath );
    const char* src = code.c_str();

    glShaderSource(id, 1, &src, nullptr);
    glCompileShader(id);   

    // [...]
}
...