PDA

View Full Version : Very odd results when drawing with an identity matrix



chbaker0
12-22-2013, 06:58 PM
For some reason, a shape I'm attempting to draw a sphere without any transformations (other than a camera projection) won't draw correctly. This:


#version 330 core

layout (location = 0) in vec4 InPosition;
layout (location = 1) in vec4 InColor;
uniform mat4 CameraMat;
uniform mat4 ModelMat;

smooth out vec4 FragColor;

void main()
{
gl_Position = CameraMat * ModelMat * InPosition;
FragColor = InColor;
}

1205
causes a blank screen when drawing with ModelMat set to an identity matrix, while when it is set to ANYTHING else, it draws fine (correctly transformed as well). When I use this vertex shader:


#version 330 core

layout (location = 0) in vec4 InPosition;
layout (location = 1) in vec4 InColor;
uniform mat4 CameraMat;
uniform mat4 ModelMat;

smooth out vec4 FragColor;

void main()
{
gl_Position = CameraMat * InPosition;
FragColor = InColor;
}

1203
It draws perfectly fine, in the center of my world. It's quite odd that when I remove the term it draws fine, but when I leave it, it doesn't work...even weirder is this:


#version 330 core

layout (location = 0) in vec4 InPosition;
layout (location = 1) in vec4 InColor;
uniform mat4 CameraMat;
uniform mat4 ModelMat;

smooth out vec4 FragColor;

void main()
{
mat4 TestMat(1.0f);
gl_Position = CameraMat * TestMat * InPosition;
FragColor = InColor;
}

1204
It draws a big black sphere filling the whole window, when it is supposed to be green and not the size of the window. ??? I'm baffled. My C++ code remained exactly the same through all these samples, only the vertex shader changed. And, when I use the original shader (that gives no sphere with an identity ModelMat) with a translate, it draws it correctly.

EDIT: Turns out this:


#version 330 core

layout (location = 0) in vec4 InPosition;
layout (location = 1) in vec4 InColor;
uniform mat4 CameraMat;
uniform mat4 ModelMat;

smooth out vec4 FragColor;

void main()
{
mat4 TestMat(1.0f);
gl_Position = CameraMat * ModelMat * InPosition;
FragColor = InColor;
}

causes the big black sphere as well...so it is just the declaration of TestMat (and not the use of it) that causes that issue. I'm even more confused now.

tonyo_au
12-22-2013, 08:11 PM
Does you input vertex have a 1 in w component? (AFAIK it will if you don't supply a w component).

chbaker0
12-22-2013, 08:19 PM
Yes, I made sure to set the w values to 1 before setting up the VBOs. Here is the code I used for loading the vertices and colors into arrays from a model importer:


auto *SphereMesh = SphereScene->mMeshes[0];
float SphereVertices[SphereMesh->mNumVertices * 4];
float SphereColors[SphereMesh->mNumVertices * 4];
for(uint64_t i = 0; i < SphereMesh->mNumVertices; i++)
{
auto CurrentVertex = SphereMesh->mVertices[i];
SphereVertices[i*4] = CurrentVertex.x;
SphereVertices[i*4+1] = CurrentVertex.y;
SphereVertices[i*4+2] = CurrentVertex.z;
SphereVertices[i*4+3] = 1.0f;

SphereColors[i*4] = 0.0f;
SphereColors[i*4+1] = 1.0f;
SphereColors[i*4+2] = 0.0f;
SphereColors[i*4+3] = 1.0f;
}

chbaker0
12-22-2013, 09:16 PM
Also, I just noticed that if I create my model matrix with


glm::dmat4(/* Any number other than 1 */);

It also displays fine. It is ONLY identity matrices causing the problem, even though a matrix created as glm::dmat4() with any other number still in the end should be equivalent due to the perspective divide.

Cornix
12-23-2013, 02:02 AM
Maybe you want to read them to make sure the values are actually what you are expecting them to be.
Maybe you "think" its the identity matrix but somewhere, in some hidden corner of the code, you change it without your own knowledge. (Happens to me all the time)

Nowhere-01
12-23-2013, 03:54 AM
Also, I just noticed that if I create my model matrix with


glm::dmat4(/* Any number other than 1 */);

It also displays fine. It is ONLY identity matrices causing the problem, even though a matrix created as glm::dmat4() with any other number still in the end should be equivalent due to the perspective divide.

you didn't supply the code, where you pass matrix as a uniform with glUniform* call. did you count the fact that you're using double-precision matrix in your c++ code? and also, do you use glm::value_ptr to pass matrix?

chbaker0
12-23-2013, 06:53 AM
Cornix: I actually did check that, I wrote it to output all the terms of the matrix just before sending it to the shader program, and it was correct...very odd.

Nowhere-01:
Here's the actual Uniform sending code:
Here the wrapper class code


template <class T>
class _UniformBase
{
protected:
std::forward_list<std::pair<GLuint,GLint>> Uniforms;
T Data;

virtual void SetUniform(GLint) {/*Dummy*/}; // Must be implemented in child classes

public:

//..............other code...............

void SetData(T Data_in)
{
if(Data_in != Data)
{
Data = Data_in;
GLuint Initial;
glGetIntegerv(GL_CURRENT_PROGRAM, (GLint*)(&Initial));
GLuint Previous = Initial;
for(auto &i : Uniforms)
{
if(i.first != Previous)
{
glUseProgram(i.first);
Previous = i.first;
}
SetUniform(i.second);
}
if(Initial != Previous) glUseProgram(Initial);
}
}
};



template <>
class _Uniform<glm::mat4> : public _UniformBase<glm::mat4>
{
protected:
void SetUniform(GLint Uniform_in)
{
glUniformMatrix4fv(Uniform_in, 1, GL_FALSE, glm::value_ptr(Data));
}
};

for the mat4.
Here's the actual drawing code for the sphere:


auto SphereDrawFunc =
[&](const mat4 &Transform_in, const mat4 &NormalTranform_in)
{
SphereArray.Bind();
Transform.SetData(Transform_in);
glDrawElements(GL_TRIANGLES, ElementCount, GL_UNSIGNED_INT, 0);
};

Which gets called once per iteration of the main loop. Between setting the transform and sending it to the uniform, it simply gets casted from glm::dmat4 to glm::mat4.

Cornix
12-23-2013, 07:22 AM
You should print it out after sending it to the shader.
Dont read the data that you put in, query the data directly from OpenGL and see what is inside.

chbaker0
12-23-2013, 07:53 AM
Oh, wow, I just found out what it was. For efficiency I set my Uniform class to update the uniform only if it is different from the last value it is set to. However, it is initialized to an identity matrix and the uniform isn't ever set before the first call. So, it ends up not ever setting it. Pretty stupid error haha.

Also, it turned out that the big black sphere was simply because I initialized the TestMat incorrectly (should be mat4 TestMat = mat4(1.0f)) and I forgot to check the shader logs.