NeomerArcana

05-30-2015, 05:17 AM

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/questions/101624/normal-mapping-a-cubemap

http://stackoverflow.com/questions/30437457/whats-wrong-with-my-normal-mapping-i-think-its-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-content/uploads/2015/05/normal-map.jpg

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

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,textur eSize);

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,textur eSize)] = 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,textur eSize)] = normalMap[utils::math::get_1d_array_index_from_2d(x,y,textur eSize)];

}

}

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:

#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_positionCam eraSpace, 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.

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/questions/101624/normal-mapping-a-cubemap

http://stackoverflow.com/questions/30437457/whats-wrong-with-my-normal-mapping-i-think-its-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-content/uploads/2015/05/normal-map.jpg

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

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,textur eSize);

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,textur eSize)] = 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,textur eSize)] = normalMap[utils::math::get_1d_array_index_from_2d(x,y,textur eSize)];

}

}

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:

#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_positionCam eraSpace, 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.