Let there be light!
Written on July 11th, 2021 by AsianMario
What did I achieve today?
Today, I made a 3D light/emission object that would dynamically effect the lighting of objects near it. Currently, it has working diffusion, ‘ambient’ lighting (not really ambient, just a minimum brightness) and specular lighting. ROML wasn’t used as much today due to the fact that lighting was mostly math that didn’t need GLM anyway. It was pretty cool to see all the calculations being implemented and working and it really made me appreciate 3D lighting of art and video games even more.
Nitty Gritty
To do this I first needed to have a virtual light object (which in this case is a cube point light) that had different co-ordinates and different shaders from normal objects. It was pretty simple to implement this because all I needed to do was set a constant colour value to the cube. Then, I would subtract the brightness of the mesh depending on how far it was from the light (diffuse lighting), I managed to do this by using normals.
In this case, I used face normals which had a perpinduclar normal line for each face (since the pyramid was created for seperate smaller triangles). This tye of normal setup would result in flat-shading makinng all the faces of the object appear more obvious, a great use of flat shading would be low-poly styled models which tries to show each face of the mesh. Although, some other art styles might use vertex normals which would have a normal line projecting from each vertex of the mesh, this would result in smooth shading and would probably be better for objects with higher poly count or realistic objects.In this case I went with a flat shader due to the fact this is quite a simple mesh.
inally, came the specular lighting which depending on the camera position and where the light would hit the object would change the intensity of the diffuse or brightness. So this means the closest art of the mesh near the light would be brighter and have a more gradual diffuse rather than parts of the mesh that were far away from the light and would diffuse rapidly. Reflections would be calculated by the negative of the light direction and the normals of the object.
Technically there is also ambient lighting but coding and calculating actual ambient lighting would be quite complicated so instead I just gave the whole mesh a minimum brightness so parts that didn’t face the light wouldn’t be pitch black like they would be in space.
A small snipet of the source code:
void main(){
//''''ambient'''' lighting
float ambient = 0.20f;
vec3 normal = normalize(Normal);
vec3 lightDirection = normalize(lightPos - crntPos);
float diffuse = max(dot(normal, lightDirection), 0.0f);
float specularLight = 0.50f;
vec3 viewDirection = normalize(camPos - crntPos);
vec3 reflectionDirection = reflect(-lightDirection, normal);
float specAmount = pow(max(dot(viewDirection, reflectionDirection), 0.0f), 16); //(8 controls how defined the specular light is)
float specular = specAmount * specularLight;
FragColor = texture(tex0, texCoord) _ lightColor _ (diffuse + ambient + specular);
}
Hope you enjoyed reading!
Available Functions
- Translate degrees to radians
- Normalize a vector
- Rotate a 4x4 matrix
- Rotate a 3 length vector
- Negate (or reverse) values of a vec3
- Find an angle between two vectors
- Find cross product between two vectors
- Translate a matrix
- Create a projection matrix (not ortographic)
- Inverse square root (I think cmath already has this though)
- Camera lookat(); function which allows the use of a camera in a 3D space
- Dot product of two vectors