I've been trying for some time to successfully get some bump mapping going on a cubemapped sphere.

I have a procedurally generated height-cubemap. With this I colourize to create a diffuse map.

Now, I'm creating a normalmap based on the code from "Mathematics for 3D Game Programming and Computer Graphics, Third Edition", which appears to work really well.

The problem I've had to date is Tangent-space normal map. I just cannot find a way to generate the normal-map and generate the tangent and binormal on my vertices without any graphical artifacts.
http://gamedev.stackexchange.com/que...ping-a-cubemap
http://stackoverflow.com/questions/3...ts-my-tangents

If anyone has a solution for that I'd love to know it.

I've basically given up on this for now though. What I'm trying to do now is generate a object-space normal map for my cubemapped sphere. This seems like it would be easier to generate and fool-proof to use. But so far I'm having trouble.

My normal map looks like this:


So I think there's clearly something wrong in it's generation. Here's the code that generates it.

Code :
float scale = 15.0;
std::deque<glm::vec4> normalMap(textureSize*textureSize);
for(int x = 0; x < textureSize; ++x)
{
    for(int y = 0; y < textureSize; ++y)
    {
        // center point
        int i11 = utils::math::get_1d_array_index_from_2d(x,y,textureSize);
        float v11 = cubeFacesHeight[i][i11].r;
 
        // to the left
        int i01 = utils::math::get_1d_array_index_from_2d(std::max(x-1,0),y,textureSize);
        float v01 = cubeFacesHeight[i][i01].r;
 
        // to the right
        int i21 = utils::math::get_1d_array_index_from_2d(std::min(x+1,textureSize-1),y,textureSize);
        float v21 = cubeFacesHeight[i][i21].r;
 
        // to the top
        int i10 = utils::math::get_1d_array_index_from_2d(x,std::max(y-1,0),textureSize);
        float v10 = cubeFacesHeight[i][i10].r;
 
        // and now the bottom
        int i12 = utils::math::get_1d_array_index_from_2d(x,std::min(y+1,textureSize-1),textureSize);
        float v12 = cubeFacesHeight[i][i12].r;
 
        glm::vec3 S = glm::vec3(1, 0, scale * v21 - scale * v01);
        glm::vec3 T = glm::vec3(0, 1, scale * v12 - scale * v10);
 
        glm::vec3 N = (glm::vec3(-S.z,-T.z,1) / std::sqrt(S.z*S.z + T.z*T.z + 1));
 
        glm::vec3 originalDirection;
        if(i == POSITIVE_X)
            originalDirection = glm::vec3(textureSize,-y,-x);
        else if(i == NEGATIVE_X)
            originalDirection = glm::vec3(-textureSize,-x,-y);
        else if(i == POSITIVE_Y)
            originalDirection = glm::vec3(-x,-textureSize,-y);
        else if(i == NEGATIVE_Y)
            originalDirection = glm::vec3(-y,textureSize,-x);
        else if(i == POSITIVE_Z)
            originalDirection = glm::vec3(-y,-x,textureSize);
        else if(i == NEGATIVE_Z)
            originalDirection = glm::vec3(-y,-x,-textureSize);
 
        glm::vec3 o = originalDirection;
        glm::vec3 a = N;
 
        glm::vec3 ax = glm::normalize(o) * (glm::dot(a,glm::normalize(o)));
 
        N = ax;
 
        N.x = (N.x+1.0)/2.0;
        N.y = (N.y+1.0)/2.0;
        N.z = (N.z+1.0)/2.0;
 
        normalMap[utils::math::get_1d_array_index_from_2d(x,y,textureSize)] = glm::vec4(N.x,N.y,N.z,v11);
    }
}
for(int x = 0; x < textureSize; ++x)
{
    for(int y = 0; y < textureSize; ++y)
    {
        cubeFacesHeight[i][utils::math::get_1d_array_index_from_2d(x,y,textureSize)] = normalMap[utils::math::get_1d_array_index_from_2d(x,y,textureSize)];  
    }
}

cubeFacesHeight is 6 faces of height values.

What I'm attempting to do is use the value originally given to N, as this is the normal map as though it was the surface of a plane. Then, I'm attempting to apply this to the original direction vector of each point (which is also the normal vector). I think it's that application, where ax is set that it the problem.

I then implement it in my Fragment shader like so:

Code :
#version 400
 
layout (location = 0) out vec4 color;
 
struct Material
{
    bool useMaps;
    samplerCube diffuse;
    samplerCube specular;
    samplerCube normal;
    float shininess;
    vec4 color1;
    vec4 color2;
};
 
struct PointLight
{
    bool active;
 
    vec3 position;
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
 
    float constant;
    float linear;
    float quadratic;
};
 
uniform Material uMaterial;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
 
in vec3 ex_normal;
in vec3 ex_positionCameraSpace;
in vec3 ex_originalPosition;
in vec3 ex_positionWorldSpace;
in vec4 ex_positionLightSpace;
 
in PointLight ex_light;
 
/* *********************
Calculates the color when using a point light. Uses shadow map
********************* */
vec3 CalcPointLight(PointLight light, Material mat, vec3 n, vec3 fragPos, vec3 originalPos, vec3 viewDir)
{
     /* just lighting stuff that doesn't matter */
 
    vec3 lightDir = normalize(fragPos - light.position);    
 
    vec3 reflectDir = normalize(reflect(lightDir, n));
    float specularFactor = pow(dot(viewDir,reflectDir), mat.shininess);
    if(specularFactor > 0 && diffuseFactor > 0)
        specularColor = light.specular * specularFactor * specularMat;
 
    /*more lighting stuff*/
}
 
vec3 get_normal(vec3 SRT)
{
    vec3 map = texture(uMaterial.normal,SRT).rgb * 2.0 - 1.0;
    return mat3(transpose(inverse(view * model))) * map;
}
 
void main(void)
{
    vec3 viewDir = normalize(-ex_positionCameraSpace);
 
    vec3 n = get_normal(glm::normalize(ex_originalPosition));
 
    vec3 result = CalcPointLight(ex_light,uMaterial,n,ex_positionCameraSpace, ex_positionWorldSpace,viewDir);
 
    color = vec4(result,1.0);
}

Considering that my Fragment shader works fine without sampling the normal map, and instead using "ex_originalPosition", I don't think it's the problem. I could just use some help in generating the object space normal map.