Reputation: 284
I have a simple Vulkan setup that loads a quite large mesh file (woman) and also applies the diffuse and normal map textures.
Vertex Shader:
#version 450 core
layout (set = 0, binding = 0) uniform ModelMatrix {
mat4 model;
} modelMatrix;
layout (push_constant) uniform ViewProjection {
mat4 view;
mat4 projection;
} viewProjection;
layout (location = 0) in vec3 inPos;
layout (location = 1) in vec3 inNor;
layout (location = 2) in vec2 inUV;
layout (location = 3) in vec3 inTan;
layout (location = 4) in vec3 inBitan;
layout (location = 0) out vec3 fragPos;
layout (location = 1) out vec2 fragUV;
layout (location = 2) out vec3 fragNor;
layout (location = 3) out vec3 fragTan;
layout (location = 4) out vec3 fragBitan;
void main()
{
fragPos = vec3(viewProjection.view * modelMatrix.model * vec4(inPos, 1.0));
fragNor = mat3(viewProjection.view * modelMatrix.model) * inNor;
fragUV = inUV;
fragTan = mat3(viewProjection.view * modelMatrix.model) * inTan;
fragBitan = mat3(viewProjection.view * modelMatrix.model) * inBitan;
gl_Position = viewProjection.projection * vec4(fragPos, 1.0);
}
Fragment Shader:
#version 450 core
layout (location = 0) in vec3 fragPos;
layout (location = 1) in vec2 fragUV;
layout (location = 2) in vec3 fragNor;
layout (location = 3) in vec3 fragTan;
layout (location = 4) in vec3 fragBitan;
layout (location = 0) out vec4 outFragColor;
layout (set = 0, binding = 0) uniform MVP {
mat4 model;
} mvp;
layout (set = 0, binding = 1) uniform sampler2D textureSampler;
layout (set = 0, binding = 2) uniform sampler2D normalSampler;
layout (set = 0, binding = 3) uniform sampler2D specSampler;
layout (push_constant) uniform VP {
mat4 view;
mat4 projection;
} vp;
const vec3 lightPos = vec3(0.0, 0.0, 300.0);
const float lightIntensity = 1.0f;
const float shininess = 50.0;
void main()
{
mat3 TBN = transpose(mat3(
fragTan,
fragBitan,
fragNor
));
vec3 normapFragNor = normalize(texture(normalSampler, fragUV).rgb * 2.0 - 1.0);
vec3 lightDirectionTangSpace = TBN * (lightPos - fragPos);
float dotProduct = dot(normalize(lightDirectionTangSpace), normalize(normapFragNor));
float meshNormalDotProduct = dot(normalize(lightDirectionTangSpace), normalize(fragNor));
float diffuse = min(max(dotProduct, 0.0), 1.0);
float specular = pow(diffuse, shininess);
vec4 texelColor = texture(textureSampler, fragUV);
vec3 specularColor = vec3(texture(specSampler, fragUV));
float specResultColorComponent = min(1.0, diffuse);
outFragColor = vec4(diffuse * vec3(texelColor) , texelColor.a); // For Spec Map: diffuse * vec3(texelColor) + (specular * specularColor)
}
As it can be seen, the fragments on the whole mesh are shaded a bit fuzzy and noisy, specially on the arms.
Whenever i load this mesh with the same textures in Unity3D, the result is without the mentioned noises:
Another model with normal map + spec map works like a charm, so this sounds paradoxical to me, since Unity3D can render both these three models correctly, but my program fails to generate lighting values only for a specific model, which implicates that the shader could interpret the data in textures/models!
What could be the source of this problem?
[UPDATE]
After visualizing normals with geometry shader:
Upvotes: 5
Views: 441
Reputation: 13246
Your transformations of normals (and potentialy the others) seem wrong to me. You typically don't transform using the same matrix as vertex. Inverse transpose is usually used.
Try visualising your normals with e.g. using geometry shader (emit lines).
Upvotes: 2