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:

http://thelastboundary.com/wp-conten...normal-map.jpg

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.