From 0e81e3544bc5735a344c12a6f0468e1cfc41ca79 Mon Sep 17 00:00:00 2001 From: ffreyer Date: Thu, 21 Sep 2023 18:49:28 +0200 Subject: [PATCH] add directional light, move lightpos transform to cpu --- GLMakie/assets/shader/lighting.frag | 51 +++++++++++++++-------------- GLMakie/src/drawing_primitives.jl | 34 +++++++++---------- 2 files changed, 42 insertions(+), 43 deletions(-) diff --git a/GLMakie/assets/shader/lighting.frag b/GLMakie/assets/shader/lighting.frag index 876565403ed..0be9057e552 100644 --- a/GLMakie/assets/shader/lighting.frag +++ b/GLMakie/assets/shader/lighting.frag @@ -31,21 +31,27 @@ uniform mat4 view; in vec3 o_camdir; in vec3 o_view_pos; -vec3 illuminate_pointlight(int idx, vec3 normal, vec3 camera_direction, vec3 color) { - // calculate light direction and distance - vec3 light_vec = (view * vec4(light_positions[idx], 1)).xyz - o_view_pos; - float dist = length(light_vec); - vec3 light_dir = normalize(light_vec); - - // diffuse coefficient (how directly does light hit the surface) +vec3 blinn_phong(vec3 light_color, vec3 normal, vec3 light_dir, vec3 color) { + // diffuse coefficient (how directly does light hits the surface) float diff_coeff = max(dot(light_dir, normal), 0.0); - // specular coefficient (does reflected light bounce into camera) - vec3 H = normalize(light_dir + camera_direction); + // specular coefficient (does reflected light bounce into camera?) + vec3 H = normalize(light_dir + o_camdir); float spec_coeff = pow(max(dot(H, normal), 0.0), shininess); if (diff_coeff <= 0.0 || isnan(spec_coeff)) spec_coeff = 0.0; + return light_color * vec3(diffuse * diff_coeff * color + specular * spec_coeff); +} + +vec3 calc_point_light(int idx, vec3 normal, vec3 color) { + // calculate light direction and distance + // vec3 light_vec = (view * vec4(light_positions[idx], 1)).xyz - o_view_pos; + vec3 light_vec = light_positions[idx] - o_view_pos; + + float dist = length(light_vec); + vec3 light_dir = normalize(light_vec); + // How weak has the light gotten due to distance float attentuation = 1.0; // float attentuation = 1.0 / ( @@ -54,19 +60,16 @@ vec3 illuminate_pointlight(int idx, vec3 normal, vec3 camera_direction, vec3 col // light_parameters[idx].z * dist * dist // ); - // final lighting model + return attentuation * blinn_phong(light_colors[idx], normal, light_dir, color); +} - return attentuation * light_colors[idx] * vec3( - diffuse * diff_coeff * color + - specular * spec_coeff - ); +vec3 calc_directional_light(int idx, vec3 normal, vec3 color) { + // TODO: don't calculate view * light_direction for each pixel + // vec3 light_dir = normalize((view * vec4(light_directions[idx], 1)).xyz); + vec3 light_dir = light_directions[idx]; + return blinn_phong(light_colors[idx], normal, light_dir, color); } -// vec3 illuminate_directionallight(Light light, vec3 normal, vec3 light_direction, vec3 camera_direction, vec3 color) { -// // light coming down (0, -1, 0) should reflect off of normals (0, 1, 0) the strongest -// float diff_coeff = max(dot(-light.direction, normal), 0.0); -// return diffuse * diff_coeff * light.color * color; -// } vec3 illuminate(vec3 normal, vec3 base_color) { vec3 final_color = vec3(0); @@ -76,14 +79,14 @@ vec3 illuminate(vec3 normal, vec3 base_color) { final_color += light_colors[i] * base_color; break; case PointLight: - final_color += illuminate_pointlight(i, normal, o_camdir, base_color); + final_color += calc_point_light(i, normal, base_color); + break; + case DirectionalLight: + final_color += calc_directional_light(i, normal, base_color); break; - // case DirectionalLight: - // return illuminate_directionallight(light, normal, light_direction, camera_direction, base_color); default: - final_color += vec3(1,0,1); // debug magenta + return vec3(1,0,1); // debug magenta } } return final_color; } - diff --git a/GLMakie/src/drawing_primitives.jl b/GLMakie/src/drawing_primitives.jl index eea4f1bde6e..30332a70258 100644 --- a/GLMakie/src/drawing_primitives.jl +++ b/GLMakie/src/drawing_primitives.jl @@ -5,7 +5,7 @@ using Makie: convert_arguments # TODO: Maybe move this somewhere else? # TODO: observable function handle_lights(attr::Dict, lights::Vector{Makie.AbstractLight}) - maxlength = 8 + maxlength = 64 if length(lights) > maxlength @warn "GLMakie only allows up to $maxlength lights." @@ -14,12 +14,20 @@ function handle_lights(attr::Dict, lights::Vector{Makie.AbstractLight}) attr[:light_types] = Int32.(Makie.light_type.(lights)) attr[:light_colors] = RGBf.(Makie.light_color.(lights)) - attr[:light_positions] = Vec3f.(Makie.light_position.(lights)) - attr[:light_directions] = Vec3f.(Makie.light_direction.(lights)) + attr[:light_positions] = map(attr[:view]) do view + map(Makie.light_position.(lights)) do p + p4d = view * to_ndim(Point4f, p, 1) + return Vec3f(p4d[1] / p4d[4], p4d[2] / p4d[4], p4d[3] / p4d[4]) + end + end + normalview = map(view -> transpose(inv(view[Vec(1,2,3), Vec(1,2,3)])), attr[:view]) + attr[:light_directions] = map(normalview) do nv + map(p -> nv * p, Makie.light_direction.(lights)) + end attr[:light_parameters] = Vec3f.(Makie.light_parameters.(lights)) attr[:lights_length] = length(lights) - # @info "Inserted $N lights." + @info "Inserted $(length(lights)) lights." return attr end @@ -139,26 +147,14 @@ function cached_robj!(robj_func, screen, scene, x::AbstractPlot) gl_key => gl_value end) - # pointlight = Makie.get_point_light(scene) - # if !isnothing(pointlight) - # @info "Set light position" - # gl_attributes[:lightposition] = pointlight.position - # end - - # ambientlight = Makie.get_ambient_light(scene) - # if !isnothing(ambientlight) - # @info "Set ambient light" - # gl_attributes[:ambient] = ambientlight.color - # end - - # TODO: - handle_lights(gl_attributes, scene.lights) - gl_attributes[:track_updates] = screen.config.render_on_demand handle_intensities!(gl_attributes, x) connect_camera!(x, gl_attributes, scene.camera, get_space(x)) + # TODO: + handle_lights(gl_attributes, scene.lights) + robj = robj_func(gl_attributes) get!(gl_attributes, :ssao, Observable(false))