Reputation: 13
When running the program two times, it doesn't display the same result at run time, even though I'm using the same executable.
Here is a bit of context:
I'm programming on a MacAir with Sierra 10.13 and my IDE is Xcode 10.1.
I figured out that my problem is caused by the addition of the transformation Matrix in the vertex shader:
// 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;
}
And I load the transformM matrix this way (I'm using the GLM library for maths):
void LoadMatrix(int location, glm::mat4 matrix) {
glUniformMatrix4fv(location, 1, GL_FALSE, &matrix[0][0]);
}
where location is:
uniformName = "transformM";
location = glGetUniformLocation(_shaderID, uniformName.c_str());
(I keeped it simple but you can found the full code here: https://github.com/Cuiyere/Ecosystem)
In fact, I expect my code to render a cube and rotate it, but it didn't shows up like 50% of the time.
I don't understand WHY this issue is happening. I checked my code a hundred times, checked the docs.gl website, compared ThinMatrix's code to mine (even if it written in Java, the overall structure and OpenGL functions remains quite the same), checked OpenGL forums, but as far as I can see, nobody ever had this problem.
I think it's an issue with OpenGL's way to use a vertex shader, but I can't affirm that.
Upvotes: 0
Views: 253
Reputation: 210877
the default constructor of glm::mat4
doesn't initialize the matrix. Before void Renderer::CreateProjectionMatrix()
is called in the constructor of class Render
, _projectionMatrix
is not initialized.
The method void Renderer::CreateProjectionMatrix()
does not initialize all the fields of the matrix _projectionMatrix
. The uninitialized fields in the matrix causes undefined behaviour.
Assign the identity matrix to _projectionMatrix
at the begin of the function, to ensure that all fields are
initialized:
void Renderer::CreateProjectionMatrix() {
_projectionMatrix = glm::mat4(1.0f);
// [...]
}
Or use a constructor to initialize the matrix:
Renderer::Renderer (Shaders::StaticShader shader)
: _projectionMatrix(1.0f)
{
CreateProjectionMatrix();
// [...]
}
But note, if a method is named CreateProjectionMatrix
, it should set all the fields of the member _projectionMatrix
.
Further you have to initialize the members _position
, _pitch
, _yaw
and _roll
of class Camera
in the constructor:
Camera()
: _position(0.0f, 0.0f, 0.0f)
, _pitch(0.0f)
, _yaw(0.0f)
, _roll(0.0f)
{};
In the method ShaderProgram::CompileShader
is another issue. The type of the return value of ShaderProgram::ReadShader
is std::string
. So ReadShader( shaderPath ).c_str()
will return a pointer to a temporary object, that is destructed immediately at the end of the assignment statement. The std::string
object gets destructed and the pointer points nowhere.
Assign the return value of ShaderProgram::ReadShader
to a local variable and use a pointer to the content of this local variable int the scope of 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);
// [...]
}
Upvotes: 5