Normal map applied as diffuse textures looks wrong
Posted
by
KaiserJohaan
on Game Development
See other posts from Game Development
or by KaiserJohaan
Published on 2013-11-03T20:30:04Z
Indexed on
2013/11/03
22:20 UTC
Read the original article
Hit count: 353
Diffuse textures works fine, but I am having problem with normal maps, so I thought I'd tried to apply the normal maps as the diffuse map in my fragment shader so I could see everything is OK.
I comment-out my normal map code and just set the diffuse map to the normal map and I get this:
http://postimg.org/image/j9gudjl7r/
Looks like a smurf!
This is the actual normal map of the main body:
http://postimg.org/image/sbkyr6fg9/
Here is my fragment shader, notice I commented out normal map code so I could debug the normal map as a diffuse texture
"#version 330 \n \
\n \
layout(std140) uniform; \n \
\n \
const int MAX_LIGHTS = 8; \n \
\n \
struct Light \n \
{ \n \
vec4 mLightColor; \n \
vec4 mLightPosition; \n \
vec4 mLightDirection; \n \
\n \
int mLightType; \n \
float mLightIntensity; \n \
float mLightRadius; \n \
float mMaxDistance; \n \
}; \n \
\n \
uniform UnifLighting \n \
{ \n \
vec4 mGamma; \n \
vec3 mViewDirection; \n \
int mNumLights; \n \
\n \
Light mLights[MAX_LIGHTS]; \n \
} Lighting; \n \
\n \
uniform UnifMaterial \n \
{ \n \
vec4 mDiffuseColor; \n \
vec4 mAmbientColor; \n \
vec4 mSpecularColor; \n \
vec4 mEmissiveColor; \n \
\n \
bool mHasDiffuseTexture; \n \
bool mHasNormalTexture; \n \
bool mLightingEnabled; \n \
float mSpecularShininess; \n \
} Material; \n \
\n \
uniform sampler2D unifDiffuseTexture; \n \
uniform sampler2D unifNormalTexture; \n \
\n \
in vec3 frag_position; \n \
in vec3 frag_normal; \n \
in vec2 frag_texcoord; \n \
in vec3 frag_tangent; \n \
in vec3 frag_bitangent; \n \
\n \
out vec4 finalColor; "
" \n \
\n \
void CalcGaussianSpecular(in vec3 dirToLight, in vec3 normal, out float gaussianTerm) \n \
{ \n \
vec3 viewDirection = normalize(Lighting.mViewDirection); \n \
vec3 halfAngle = normalize(dirToLight + viewDirection); \n \
\n \
float angleNormalHalf = acos(dot(halfAngle, normalize(normal))); \n \
float exponent = angleNormalHalf / Material.mSpecularShininess; \n \
exponent = -(exponent * exponent); \n \
\n \
gaussianTerm = exp(exponent); \n \
} \n \
\n \
vec4 CalculateLighting(in Light light, in vec4 diffuseTexture, in vec3 normal) \n \
{ \n \
if (light.mLightType == 1) // point light \n \
{ \n \
vec3 positionDiff = light.mLightPosition.xyz - frag_position; \n \
float dist = max(length(positionDiff) - light.mLightRadius, 0); \n \
\n \
float attenuation = 1 / ((dist/light.mLightRadius + 1) * (dist/light.mLightRadius + 1)); \n \
attenuation = max((attenuation - light.mMaxDistance) / (1 - light.mMaxDistance), 0); \n \
\n \
vec3 dirToLight = normalize(positionDiff); \n \
float angleNormal = clamp(dot(normalize(normal), dirToLight), 0, 1); \n \
\n \
float gaussianTerm = 0.0; \n \
if (angleNormal > 0.0) \n \
CalcGaussianSpecular(dirToLight, normal, gaussianTerm); \n \
\n \
return diffuseTexture * (attenuation * angleNormal * Material.mDiffuseColor * light.mLightIntensity * light.mLightColor) + \n \
(attenuation * gaussianTerm * Material.mSpecularColor * light.mLightIntensity * light.mLightColor); \n \
} \n \
else if (light.mLightType == 2) // directional light \n \
{ \n \
vec3 dirToLight = normalize(light.mLightDirection.xyz); \n \
float angleNormal = clamp(dot(normalize(normal), dirToLight), 0, 1); \n \
\n \
float gaussianTerm = 0.0; \n \
if (angleNormal > 0.0) \n \
CalcGaussianSpecular(dirToLight, normal, gaussianTerm); \n \
\n \
return diffuseTexture * (angleNormal * Material.mDiffuseColor * light.mLightIntensity * light.mLightColor) + \n \
(gaussianTerm * Material.mSpecularColor * light.mLightIntensity * light.mLightColor); \n \
} \n \
else if (light.mLightType == 4) // ambient light \n \
return diffuseTexture * Material.mAmbientColor * light.mLightIntensity * light.mLightColor; \n \
else \n \
return vec4(0.0); \n \
} \n \
\n \
void main() \n \
{ \n \
vec4 diffuseTexture = vec4(1.0); \n \
if (Material.mHasDiffuseTexture) \n \
diffuseTexture = texture(unifDiffuseTexture, frag_texcoord); \n \
\n \
vec3 normal = frag_normal; \n \
if (Material.mHasNormalTexture) \n \
{ \n \
diffuseTexture = vec4(normalize(texture(unifNormalTexture, frag_texcoord).xyz * 2.0 - 1.0), 1.0); \n \
// vec3 normalTangentSpace = normalize(texture(unifNormalTexture, frag_texcoord).xyz * 2.0 - 1.0); \n \
//mat3 tangentToWorldSpace = mat3(normalize(frag_tangent), normalize(frag_bitangent), normalize(frag_normal)); \n \
\n \
// normal = tangentToWorldSpace * normalTangentSpace; \n \
} \n \
\n \
if (Material.mLightingEnabled) \n \
{ \n \
vec4 accumLighting = vec4(0.0); \n \
\n \
for (int lightIndex = 0; lightIndex < Lighting.mNumLights; lightIndex++) \n \
accumLighting += Material.mEmissiveColor * diffuseTexture + \n \
CalculateLighting(Lighting.mLights[lightIndex], diffuseTexture, normal); \n \
\n \
finalColor = pow(accumLighting, Lighting.mGamma); \n \
} \n \
else { \n \
finalColor = pow(diffuseTexture, Lighting.mGamma); \n \
} \n \
} \n";
Here is my wrapper around a texture
OpenGLTexture::OpenGLTexture(const std::vector<uint8_t>& textureData, uint32_t textureWidth, uint32_t textureHeight, TextureFormat textureFormat, TextureType textureType, Logger& logger) : mLogger(logger), mTextureID(gNextTextureID++), mTextureType(textureType)
{
glGenTextures(1, &mTexture);
CHECK_GL_ERROR(mLogger);
glBindTexture(GL_TEXTURE_2D, mTexture);
CHECK_GL_ERROR(mLogger);
GLint glTextureFormat = (textureFormat == TextureFormat::TEXTURE_FORMAT_RGB ? GL_RGB : textureFormat == TextureFormat::TEXTURE_FORMAT_RGBA ? GL_RGBA : GL_RED);
glTexImage2D(GL_TEXTURE_2D, 0, glTextureFormat, textureWidth, textureHeight, 0, glTextureFormat, GL_UNSIGNED_BYTE, &textureData[0]);
CHECK_GL_ERROR(mLogger);
glGenerateMipmap(GL_TEXTURE_2D);
CHECK_GL_ERROR(mLogger);
glBindTexture(GL_TEXTURE_2D, 0);
CHECK_GL_ERROR(mLogger);
}
OpenGLTexture::~OpenGLTexture()
{
glDeleteBuffers(1, &mTexture);
CHECK_GL_ERROR(mLogger);
}
And here is the sampler I create which is shared between Diffuse and normal textures
// texture sampler setup
glGenSamplers(1, &mTextureSampler);
CHECK_GL_ERROR(mLogger);
glSamplerParameteri(mTextureSampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
CHECK_GL_ERROR(mLogger);
glSamplerParameteri(mTextureSampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
CHECK_GL_ERROR(mLogger);
glSamplerParameteri(mTextureSampler, GL_TEXTURE_WRAP_S, GL_REPEAT);
CHECK_GL_ERROR(mLogger);
glSamplerParameteri(mTextureSampler, GL_TEXTURE_WRAP_T, GL_REPEAT);
CHECK_GL_ERROR(mLogger);
glSamplerParameterf(mTextureSampler, GL_TEXTURE_MAX_ANISOTROPY_EXT, mCurrentAnisotropy);
CHECK_GL_ERROR(mLogger);
glUniform1i(glGetUniformLocation(mDefaultProgram.GetHandle(), "unifDiffuseTexture"), OpenGLTexture::TEXTURE_UNIT_DIFFUSE);
CHECK_GL_ERROR(mLogger);
glUniform1i(glGetUniformLocation(mDefaultProgram.GetHandle(), "unifNormalTexture"), OpenGLTexture::TEXTURE_UNIT_NORMAL);
CHECK_GL_ERROR(mLogger);
glBindSampler(OpenGLTexture::TEXTURE_UNIT_DIFFUSE, mTextureSampler);
CHECK_GL_ERROR(mLogger);
glBindSampler(OpenGLTexture::TEXTURE_UNIT_NORMAL, mTextureSampler);
CHECK_GL_ERROR(mLogger);
SetAnisotropicFiltering(mCurrentAnisotropy);
The diffuse textures looks like they should, but the normal looks so wierd. Why is this?
© Game Development or respective owner