OpenGL代码每次都不会显示相同的内容吗?

时间:2018-12-27 19:25:28

标签: c++ opengl glsl shader glm-math

两次运行程序时,即使我使用相同的可执行文件,运行时也不会显示相同的结果。

这里有一些上下文:

我正在使用Sierra 10.13在MacAir上进行编程,而我的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]);
}

其中位置是:

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

(我保持简单,但您可以在此处找到完整的代码:https://github.com/Cuiyere/Ecosystem

实际上,我希望我的代码能够渲染一个立方体并旋转它,但是它并没有像50%的时间那样显示。

我不知道为什么会发生此问题。我检查了一百次代码,检查了docs.gl网站,将ThinMatrix的代码与我的代码进行了比较(即使它是用Java编写的,其总体结构和OpenGL函数仍然相同),检查了OpenGL论坛,但据我所知瞧,没人遇到这个问题。

我认为OpenGL使用顶点着色器的方式存在问题,但我不能肯定。

1 个答案:

答案 0 :(得分:5)

glm::mat4的默认构造函数不会初始化矩阵。在void Renderer::CreateProjectionMatrix()的构造函数中调用class Render之前,_projectionMatrix未初始化。

方法void Renderer::CreateProjectionMatrix()不会初始化矩阵_projectionMatrix的所有字段。矩阵中未初始化的字段会导致未定义的行为。

在函数开始时将identity matrix分配给_projectionMatrix,以确保所有字段都 初始化:

void Renderer::CreateProjectionMatrix() {

    _projectionMatrix = glm::mat4(1.0f);

    // [...]
}

或使用构造函数初始化矩阵:

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

但是请注意,如果一个方法名为CreateProjectionMatrix,则应设置成员_projectionMatrix的所有字段。


此外,您必须初始化构造函数中_position的成员_pitch_yaw_rollclass 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的返回值分配给一个局部变量,并使用一个指向此局部变量内容的指针,将其设置为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);   

    // [...]
}