summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibSoftGPU
diff options
context:
space:
mode:
authorJesse Buhagiar <jooster669@gmail.com>2022-01-09 23:11:12 +1100
committerLinus Groh <mail@linusgroh.de>2022-01-12 13:36:56 +0100
commit9aae648482409904cff9847628167e168d46a2c9 (patch)
treedfc5e5554373128c897a68d6a65fefb4ebc0f614 /Userland/Libraries/LibSoftGPU
parent5a1f559ed936ef445153dcd6a2cc3d7714919db1 (diff)
downloadserenity-9aae648482409904cff9847628167e168d46a2c9.zip
LibSoftGPU: Implement per-vertex Lighting during T&L Stage
We now perform per vertex lighting during the Transform and Lighting stage of the pipeline before the triangles are sent off to be rasterized.
Diffstat (limited to 'Userland/Libraries/LibSoftGPU')
-rw-r--r--Userland/Libraries/LibSoftGPU/Device.cpp67
1 files changed, 67 insertions, 0 deletions
diff --git a/Userland/Libraries/LibSoftGPU/Device.cpp b/Userland/Libraries/LibSoftGPU/Device.cpp
index 9f87a50508..07714c3dca 100644
--- a/Userland/Libraries/LibSoftGPU/Device.cpp
+++ b/Userland/Libraries/LibSoftGPU/Device.cpp
@@ -6,6 +6,7 @@
*/
#include <AK/Function.h>
+#include <AK/Math.h>
#include <AK/SIMDExtras.h>
#include <AK/SIMDMath.h>
#include <LibCore/ElapsedTimer.h>
@@ -665,6 +666,72 @@ void Device::draw_primitives(PrimitiveType primitive_type, FloatMatrix4x4 const&
if (m_clipped_vertices.size() < 3)
continue;
+ if (m_options.lighting_enabled) {
+ auto const& front_material = m_materials.at(0);
+ // Walk through each vertex
+ for (auto& vertex : m_clipped_vertices) {
+ FloatVector4 result_color = front_material.emissive + (front_material.ambient * m_lighting_model.scene_ambient_color);
+
+ for (auto const& light : m_lights) {
+ if (!light.is_enabled)
+ continue;
+
+ FloatVector4 vertex_to_light;
+
+ // Light attenuation value.
+ float light_attenuation_factor = 1.0f;
+ if (light.position.w() != 0.0f) {
+ vertex_to_light = light.position - vertex.eye_coordinates;
+ auto const vertex_to_light_length = vertex_to_light.length();
+ auto const vertex_to_light_length_squared = vertex_to_light_length * vertex_to_light_length;
+
+ light_attenuation_factor = 1.0f / (light.constant_attenuation + (light.linear_attenuation * vertex_to_light_length) + (light.quadratic_attenuation * vertex_to_light_length_squared));
+ vertex_to_light = vertex_to_light / vertex_to_light_length;
+ } else {
+ vertex_to_light = light.position.normalized();
+ }
+
+ // Spotlight factor
+ float spotlight_factor = 1.0f;
+ if (light.spotlight_cutoff_angle != 180.0f) {
+ const auto spotlight_direction_normalized = light.spotlight_direction.normalized();
+ const auto light_to_vertex_dot_normalized_spotlight_direction = spotlight_direction_normalized.dot(FloatVector3(vertex_to_light.x(), vertex_to_light.y(), vertex_to_light.z()));
+ const auto cos_spotlight_cutoff = AK::cos<float>(light.spotlight_cutoff_angle);
+
+ if (light_to_vertex_dot_normalized_spotlight_direction >= cos_spotlight_cutoff)
+ spotlight_factor = AK::pow<float>(light_to_vertex_dot_normalized_spotlight_direction, light.spotlight_exponent);
+ else
+ spotlight_factor = 0.0f;
+ }
+
+ // FIXME: Specular. The math for it doesn't quite make sense...
+ (void)m_lighting_model.viewer_at_infinity;
+
+ // FIXME: The spec allows for splitting the colors calculated here into multiple different colors (primary/secondary color). Investigate what this means.
+ (void)m_lighting_model.single_color;
+
+ // FIXME: Two sided lighting should be implemented eventually (I believe this is where the normals are -ve and then lighting is calculated with the BACK material)
+ (void)m_lighting_model.two_sided_lighting;
+
+ // Ambient
+ auto const ambient_component = front_material.ambient * light.ambient_intensity;
+
+ // Diffuse
+ auto const normal_dot_vertex_to_light = vertex.normal.dot(FloatVector3(vertex_to_light.x(), vertex_to_light.y(), vertex_to_light.z()));
+ auto const diffuse_component = ((front_material.diffuse * light.diffuse_intensity) * normal_dot_vertex_to_light).clamped(0.0f, 1.0f);
+
+ FloatVector4 color = ambient_component;
+ color += diffuse_component;
+ color = color * light_attenuation_factor * spotlight_factor;
+ result_color += color;
+ }
+
+ vertex.color = result_color;
+ vertex.color.set_w(front_material.diffuse.w()); // OpenGL 1.5 spec, page 59: "The A produced by lighting is the alpha value associated with diffuse color material"
+ vertex.color.clamp(0.0f, 1.0f);
+ }
+ }
+
for (auto& vec : m_clipped_vertices) {
// To normalized device coordinates (NDC)
auto const one_over_w = 1 / vec.clip_coordinates.w();