Just to explain the problem a bit more:
I’m trying to add bump mapping to my (idk what I should call it, it isn’t actually a game yet) thing, and I get the following weird result:
A closer look:
Some things changed with normal/tangent calculation (this is for every triangle):
private Vector3f[] calcNormals(int x1, int z1, int x2, int z2, int x3, int z3, float uvx1, float uvy1, float uvx2, float uvy2, float uvx3, float uvy3) {
Vector3f v1 = new Vector3f(), v2 = new Vector3f();
v1.x = (x2 - x1);
v1.y = -data[z1][x1] + data[z2][x2];
v1.z = (z2 - z1);
v2.x = (x3 - x1);
v2.y = -data[z1][x1] + data[z3][x3];
v2.z = (z3 - z1);
Vector3f normal = Vector3f.cross(v1, v2, null);
normal.normalise();
Vector2f uv1 = new Vector2f(), uv2 = new Vector2f();
uv1.x = (uvx2 - uvx1);
uv1.y = (uvy2 - uvy1);
uv2.x = (uvx3 - uvx1);
uv2.y = (uvy3 - uvy1);
float r = 1f / (uv1.x * uv2.y - uv1.y * uv2.x);
Vector3f tangent = new Vector3f(v1.x * uv2.y - v2.x * uv1.y * r, v1.y * uv2.y - v2.y * uv1.y * r, v1.z * uv2.y - v2.z * uv1.y * r);
tangent.normalise();
Vector3f bitangent = Vector3f.cross(normal, tangent, null);
bitangent.normalise();
return new Vector3f[] {normal, tangent, bitangent};
}
Vertex shader (yes I have to change the names here :D):
#version 330
layout(location = 0)in vec3 vertex;
layout(location = 1)in vec3 normal;
layout(location = 2)in vec3 color;
layout(location = 3)in vec2 texCoord;
layout(location = 4)in vec3 tangent;
layout(location = 5)in vec3 bitangent;
layout(location = 0)out vec3 Position;
layout(location = 1)out vec2 TexCoord;
out vec3 EyeDirection_cameraspace;
out vec3 LightDirection_cameraspace;
out vec3 LightDirection_tangentspace;
out vec3 EyeDirection_tangentspace;
uniform mat4 ModelMatrix;
uniform mat4 ViewMatrix;
uniform mat4 ProjectionMatrix;
void main( void )
{
mat4 MVP = ProjectionMatrix * ViewMatrix * ModelMatrix;
gl_Position = MVP * vec4(vertex, 1.0f);
TexCoord = texCoord;
vec3 Normal = normalize(gl_NormalMatrix * normal);
Position = (ModelMatrix * vec4(vertex, 1.0f)).xyz;
vec3 LightPosition_worldspace = vec3(64, 20, 64); // Just a pre-set location for testing
// Vector that goes from the vertex to the camera, in camera space.
// In camera space, the camera is at the origin (0,0,0).
vec3 vertexPosition_cameraspace = (ViewMatrix * ModelMatrix * vec4(vertex, 1.0f)).xyz;
EyeDirection_cameraspace = vec3(0.0f) - vertexPosition_cameraspace;
// Vector that goes from the vertex to the light, in camera space. M is ommited because it's identity.
vec3 LightPosition_cameraspace = (ViewMatrix * vec4(LightPosition_worldspace, 1.0f)).xyz;
LightDirection_cameraspace = LightPosition_cameraspace + EyeDirection_cameraspace;
// model to camera = ModelView
mat3 MV3x3 = mat3(ViewMatrix * ModelMatrix);
vec3 vertexTangent_cameraspace = MV3x3 * tangent;
vec3 vertexBitangent_cameraspace = MV3x3 * bitangent;
vec3 vertexNormal_cameraspace = MV3x3 * Normal;
mat3 TBN = transpose(mat3(
vertexTangent_cameraspace,
vertexBitangent_cameraspace,
vertexNormal_cameraspace
));
LightDirection_tangentspace = TBN * LightDirection_cameraspace;
EyeDirection_tangentspace = TBN * EyeDirection_cameraspace;
}
Fragment shader:
#version 330
layout(location = 0)in vec3 position;
layout(location = 1)in vec2 texCoord;
in vec3 EyeDirection_cameraspace;
in vec3 LightDirection_cameraspace;
in vec3 LightDirection_tangentspace;
in vec3 EyeDirection_tangentspace;
layout(location = 0)out vec4 Color;
uniform sampler2D diffuseMap;
uniform sampler2D normalMap;
uniform vec3 cameraPosition;
void main( void )
{
vec3 LightPosition_worldspace = vec3(64, 20, 64); // Just a pre-set location for testing
// Light emission properties
// You probably want to put them as uniforms
vec3 LightColor = vec3(1,1,1);
float LightPower = 400.0;
// Material properties
float Shininess = 0.3f;
vec3 MaterialDiffuseColor = texture2D(diffuseMap, texCoord).rgb;
vec3 MaterialAmbientColor = vec3(0.1,0.1,0.1) * MaterialDiffuseColor;
vec3 MaterialSpecularColor = vec3(1.0f) * Shininess;//texture2D( SpecularTextureSampler, texCoord ).rgb * Shininess;
vec3 TextureNormal_tangentspace = normalize(texture2D( normalMap, texCoord).rgb * 2.0 - 1.0);
// Distance to the light
float distance = length( LightPosition_worldspace - position );
// Normal of the computed fragment, in camera space
vec3 n = TextureNormal_tangentspace;
// Direction of the light (from the fragment to the light)
vec3 l = normalize(LightDirection_tangentspace);
// Cosine of the angle between the normal and the light direction,
// clamped above 0
// - light is at the vertical of the triangle -> 1
// - light is perpendicular to the triangle -> 0
// - light is behind the triangle -> 0
float cosTheta = clamp( dot( n,l ), 0,1 );
// Eye vector (towards the camera)
vec3 E = normalize(EyeDirection_tangentspace);
// Direction in which the triangle reflects the light
vec3 R = reflect(-l,n);
// Cosine of the angle between the Eye vector and the Reflect vector,
// clamped to 0
// - Looking into the reflection -> 1
// - Looking elsewhere -> < 1
float cosAlpha = clamp( dot( E,R ), 0,1 );
Color = vec4(
// Ambient : simulates indirect lighting
MaterialAmbientColor +
// Diffuse : "color" of the object
MaterialDiffuseColor * LightColor * LightPower * cosTheta / (distance*distance) +
// Specular : reflective highlight, like a mirror
MaterialSpecularColor * LightColor * LightPower * pow(cosAlpha,5) / (distance*distance), 1.0f);
}