I'm working on a simple render engine in java which can render OBJ files to the screen. I'm currently working on the lighting system which is used to light up the models which are present on the screen. Before introducing the lighting system I was able to load models to the screan easely:
however, when I add the light to the screen the model does no longer show up. I'm using the following shader to render the light:
VertexShader:
#version 150
in vec3 position;
in vec2 textureCoordinates;
in vec3 normals;
out vec2 passTextureCoordinates;
out vec3 surfaceNormal;
out vec3 toLightVector;
uniform mat4 transformationMatrixTextured;
uniform mat4 projectionMatrixTextured;
uniform mat4 viewMatrixTextured;
uniform vec3 lightLocation;
void main(void){
vec4 worldPosition = transformationMatrixTextured * vec4(position,1.0);
gl_Position = projectionMatrixTextured * viewMatrixTextured * worldPosition;
passTextureCoordinates = textureCoordinates;
surfaceNormal = (transformationMatrixTextured * vec4(normals,0.0)).xyz;
toLightVector = lightLocation - worldPosition.xyz;
}
FragmentShader:
#version 150
in vec2 passTextureCoordinates;
in vec3 surfaceNormal;
in vec3 toLightVector;
out vec4 out_Color;
uniform sampler2D textureSampler;
uniform vec3 lightColor;
void main(void){
vec3 unitNormal = normalize(surfaceNormal);
vec3 unitLightVector = normalize(toLightVector);
float nDot1 = dot(unitNormal, unitLightVector);
float brightness = max(nDot1, 0.0);
vec3 diffuse = brightness * lightColor;
out_Color = vec4(diffuse, 1.0) * texture(textureSampler,passTextureCoordinates);
}
I've been using the tutorial series by ThinMatrix to help me with creating this program. However, the one big difference is that I also want to be able to load programmaticly created models, as uppose to only using models loaded by the OBJLoader. Because of this I had to create a way to calculate normals given a vertices array and an index array.
My approach to this problem was this:
/**
* Sum.
*
* @param arg1 the arg 1
* @param arg2 the arg 2
* @return the vector 3 f
*/
public static Vector3f sum(Vector3f arg1, Vector3f arg2) {
return new Vector3f(arg1.x + arg2.x, arg1.y + arg2.y, arg1.z + arg2.z);
}
/**
* Subtract.
*
* @param arg1 the arg 1
* @param arg2 the arg 2
* @return the vector 3 f
*/
public static Vector3f subtract(Vector3f arg1, Vector3f arg2) {
return new Vector3f(arg1.x - arg2.x, arg1.y - arg2.y, arg1.z - arg2.z);
}
/**
* Cross product.
*
* @param arg1 the arg 1
* @param arg2 the arg 2
* @return the vector 3 f
*/
public static Vector3f crossProduct(Vector3f arg1, Vector3f arg2) {
return new Vector3f(arg1.y * arg2.z - arg2.y * arg1.z, arg2.x * arg1.z - arg1.x * arg2.z, arg1.x * arg2.y - arg2.x * arg1.y);
}
/**
* Gets the normals.
*
* @param vertices the vertices
* @param indexes the indexes
* @return the normals
*/
public static float[] getNormals(float[] vertices, int[] indexes) {
vertices = convertToIndexless(vertices, indexes);
Vector3f tmp;
float[] tmpArray = new float[vertices.length / 3];
int tmpArrayCounter = 0;
for(int i = 0; i < vertices.length; i+=9) {
Vector3f edge1 = subtract(new Vector3f(vertices[i], vertices[i + 1], vertices[i + 2]) , new Vector3f(vertices[i + 3], vertices[i + 4], vertices[i + 5]));
Vector3f edge2 = subtract(new Vector3f(vertices[i], vertices[i + 1], vertices[i + 2]) , new Vector3f(vertices[i + 6], vertices[i + 7], vertices[i + 8]));
tmp = crossProduct(edge1, edge2);
tmpArray[tmpArrayCounter++] = tmp.getX();
tmpArray[tmpArrayCounter++] = tmp.getY();
tmpArray[tmpArrayCounter++] = tmp.getZ();
}
return tmpArray;
}
/**
* Convert to indexless.
*
* @param vertices the vertices
* @param indexes the indexes
* @return the float[]
*/
private static float[] convertToIndexless(float[] vertices, int[] indexes) {
float[] tmpArray = new float[indexes.length * 3];
for(int i = 0; i < indexes.length; i++) {
tmpArray[i * 3] = vertices[indexes[i] * 3];
tmpArray[i * 3 + 1] = vertices[indexes[i] * 3 + 1];
tmpArray[i * 3 + 2] = vertices[indexes[i] * 3 + 2];
}
return tmpArray;
}
I've based this approach on this question about calculating normals. As I said before I'm not able to render the model when adding a light to the program. Am I doing something wrong in my calculations?