I am having some trouble with my Phong shading algorithm. It seems like the normals are off and I always get a flat shaded surface.
I am implementing deferred rendering, so in my geometry pass I store the vertex' position and normal in textures. In the lighting pass, I output the normals as color to check their "values".
EDIT 1 My Gbuffer uses two textures for storing the positions and normals. Both textures use the GL_RGB16F format.
EDIT 5 As you can see in this image
I do not get an elegant color transition. The head on the left is the result of my engine, on the right you can see the same model in Blender. In Blender, the normals (in blue) look correct (no duplicates, etc) but in my engine, they behave like a face-normal (every 4 showing in the same direction).
I am using Assimp to load the models and I include the
aiProcess_GenSmoothNormals
flag when importing them.
The geometry-pass vertex shader:
#version 440 core
layout (location = 0) in vec4 positionOS;
layout (location = 1) in vec3 normalOS;
layout (location = 2) in vec2 uv;
out VertexData
{
vec3 PositionVS;
vec3 NormalVS;
vec2 UV;
} vs_out;
uniform mat3 normalViewMatrix;
uniform mat4 modelViewMatrix;
struct Camera
{
mat4 viewMatrix;
mat4 projMatrix;
};
layout(std140, binding = 0) uniform CameraBlock
{
Camera cam;
};
void main()
{
vec4 positionVS = modelViewMatrix * positionOS;
vs_out.PositionVS = positionVS.xyz;
vs_out.NormalVS = normalViewMatrix * normalOS;
vs_out.UV = uv;
gl_Position = cam.projMatrix * positionVS;
}
The geometry-pass fragment shader:
#version 440 core
layout (location = 0) out vec3 PositionVS;
layout (location = 1) out vec3 NormalVS;
in VertexData
{
vec3 PositionVS;
vec3 NormalVS;
vec2 UV;
} vs_in;
void main()
{
PositionVS = vs_in.PositionVS;
NormalVS = normalize(vs_in.NormalVS);
}
EDIT 4 Reading vertex values from Assimp (aiMesh)
void MeshLoader::prepareMesh(const aiMesh & mesh)
{
{ // vertices
for (int i = 0; i < mesh.mNumVertices; i++) {
if (mesh.HasPositions()) {
glm::vec3 position = glm::vec3(mesh.mVertices[i].x, mesh.mVertices[i].y, mesh.mVertices[i].z);
positions.emplace_back(position.x, position.y, position.z, 1);
}
if (mesh.HasNormals()) {
normals.emplace_back(mesh.mNormals[i].x, mesh.mNormals[i].y, mesh.mNormals[i].z);
}
if (mesh.HasTangentsAndBitangents()) {
tangents.emplace_back(mesh.mTangents[i].x, mesh.mTangents[i].y, mesh.mTangents[i].z);
bitangents.emplace_back(mesh.mBitangents[i].x, mesh.mBitangents[i].y, mesh.mBitangents[i].z);
}
if (mesh.HasTextureCoords(0)) {
uvs.emplace_back(mesh.mTextureCoords[0][i].x, mesh.mTextureCoords[0][i].y);
}
}
}
{ // polygons
numFaces = mesh.mNumFaces;
for (int i = 0; i < numFaces; i++) {
indices.push_back(mesh.mFaces[i].mIndices[0]);
indices.push_back(mesh.mFaces[i].mIndices[1]);
indices.push_back(mesh.mFaces[i].mIndices[2]);
}
}
}
I would like to find the solution for this mess. I know that the normals are the issue but I can't figure out why.
EDIT 2 By the look of the sphere, it seems like an interpolation problem, hence the shader code above. If the shaders are correct then maybe the importer class is causing this issue?
EDIT 3 I've also implemented a forward rendering version and display the normals as color, but I get the same result as in the deferred version.