0
\$\begingroup\$

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?

\$\endgroup\$
  • \$\begingroup\$ Do you want an algorithm like bump mapping? \$\endgroup\$ – MickLH Nov 3 '13 at 23:43
  • \$\begingroup\$ Why you use glDeleteBuffers when deleting texture? Is it correct? \$\endgroup\$ – Yevhen Nov 4 '13 at 11:59
3
\$\begingroup\$

This line

diffuseTexture=vec4(normalize(texture(unifNormalTexture, frag_texcoord).xyz * 2.0-1.0), 1.0);

Should be

  diffuseTexture=vec4(normalize(texture(unifNormalTexture, frag_texcoord).xyz ), 1.0);

The reason is before normals are encoded into Normal maps their values could be in the range from -1.0 to 1.0, this doesn't really works with normal R8B8G8A8 images as they cannot store negative numbers. In order to make the image able to store normal numbers we do Scale and Bias by multiplying by 0.5 and adding 1.0. This will effectively map the normals' values:

  • [-1, 0] => [0.0, 0.5] and
  • [0, 1] => [0.5, 1]

Now inorder to get the original values you need to undo this Scale and Bias operation by multiplying by 2 and subtracting 1. Your problem is you don't need to do this when rendering a normal map as you don't really need the original (probably negative) values and render them on the screen.

\$\endgroup\$
1
\$\begingroup\$

You've left in the * 2.0 - 1.0 when sampling the normal map. You probably want to comment that out as well if you're trying to visualize the normal maps for debugging purposes; that way they'll match up with what you see when looking at the normal map in an image viewer.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.