Skip to content

Commit

Permalink
remove intermediate type, increase number of lights [skip ci]
Browse files Browse the repository at this point in the history
  • Loading branch information
ffreyer committed Sep 21, 2023
1 parent d1d3fd6 commit b6f6bda
Show file tree
Hide file tree
Showing 10 changed files with 98 additions and 104 deletions.
30 changes: 18 additions & 12 deletions GLMakie/assets/shader/lighting.frag
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{{GLSL_VERSION}}
{{GLSL_EXTENSIONS}}

#define MAX_LIGHTS 8
#define MAX_LIGHTS 64

// differentiating different light sources
const int UNDEFINED = 0;
Expand All @@ -14,38 +14,44 @@ const int SpotLight = 4;
uniform int light_types[MAX_LIGHTS];
uniform vec3 light_colors[MAX_LIGHTS];
uniform vec3 light_positions[MAX_LIGHTS];
// uniform vec3 light_directions[MAX_LIGHTS];
uniform vec3 light_attenuation_parameters[MAX_LIGHTS];
uniform vec3 light_directions[MAX_LIGHTS];
uniform vec3 light_parameters[MAX_LIGHTS];
uniform int lights_length;

// Material parameters
uniform vec3 diffuse;
uniform vec3 specular;
uniform float shininess;

in vec3 o_light_directions[MAX_LIGHTS];
// TODO: we don't want to do this here...
// maybe pre-calc on cpu?
uniform mat4 view;

// in vec3 o_light_directions[MAX_LIGHTS];
in vec3 o_camdir;
in vec3 o_world_pos;
in vec3 o_view_pos;

vec3 illuminate_pointlight(int idx, vec3 normal, vec3 camera_direction, vec3 color) {
float dist = length(o_light_directions[idx]);
vec3 light_dir_norm = normalize(o_light_directions[idx]);
// 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)
float diff_coeff = max(dot(light_dir_norm, normal), 0.0);
float diff_coeff = max(dot(light_dir, normal), 0.0);

// specular coefficient (does reflected light bounce into camera)
vec3 H = normalize(light_dir_norm + camera_direction);
vec3 H = normalize(light_dir + camera_direction);
float spec_coeff = pow(max(dot(H, normal), 0.0), shininess);
if (diff_coeff <= 0.0 || isnan(spec_coeff))
spec_coeff = 0.0;

// How weak has the light gotten due to distance
float attentuation = 1.0;
// float attentuation = 1.0 / (
// light_attenuation_parameters[idx].x +
// light_attenuation_parameters[idx].y * dist +
// light_attenuation_parameters[idx].z * dist * dist
// light_parameters[idx].x +
// light_parameters[idx].y * dist +
// light_parameters[idx].z * dist * dist
// );

// final lighting model
Expand Down
12 changes: 1 addition & 11 deletions GLMakie/assets/shader/mesh.vert
Original file line number Diff line number Diff line change
Expand Up @@ -56,22 +56,12 @@ vec4 to_color(Nothing c, Nothing cm, Nothing cn) {
return vec4(0.0);
}

void prepare_lights(vec4 view_pos);

void main()
{
o_id = uvec2(objectid, gl_VertexID+1);
vec2 tex_uv = to_2d(texturecoordinates);
o_uv = vec2(1.0 - tex_uv.y, tex_uv.x) * uv_scale;
o_color = to_color(vertex_color, color_map, color_norm);
vec3 v = to_3d(vertices);

// vec4 view_pos = model * vec4(v, 1);
// prepare_lights(view_pos);
// render(view_pos, normals, view, projection, lightposition);

vec4 world_pos = model * vec4(v, 1);
render(world_pos, normals, view, projection, lightposition);
vec4 view_pos = view * world_pos;
prepare_lights(view_pos / view_pos.w);
render(model * vec4(v, 1), normals, view, projection, lightposition);
}
7 changes: 1 addition & 6 deletions GLMakie/assets/shader/particles.vert
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,5 @@ void main(){
o_color = o_color * to_color(vertex_color);
o_uv = get_uv(texturecoordinates);
rotate(rotation, index, V, N);
// render(model * vec4(pos + V, 1), N, view, projection, lightposition);

vec4 world_pos = model * vec4(pos + V, 1);
render(world_pos, N, view, projection, lightposition);
vec4 view_pos = view * world_pos;
prepare_lights(view_pos / view_pos.w);
render(model * vec4(pos + V, 1), N, view, projection, lightposition);
}
8 changes: 1 addition & 7 deletions GLMakie/assets/shader/surface.vert
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@ flat out uvec2 o_id;
out vec4 o_color;
out vec2 o_uv;

void prepare_lights(vec4 view_pos);

void main()
{
int index = gl_InstanceID;
Expand All @@ -73,9 +71,5 @@ void main()
if (isnan(pos.z)) {
pos.z = 0.0;
}

vec4 world_pos = model * vec4(pos, 1);
render(world_pos, normalvec, view, projection, lightposition);
vec4 view_pos = view * world_pos;
prepare_lights(view_pos / view_pos.w);
render(model * vec4(pos, 1), normalvec, view, projection, lightposition);
}
38 changes: 21 additions & 17 deletions GLMakie/src/drawing_primitives.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,19 @@ using Makie: convert_arguments
# TODO: observable
function handle_lights(attr::Dict, lights::Vector{Makie.AbstractLight})
maxlength = 8
N = min(maxlength, length(lights))

if length(lights) > maxlength
@warn "GLMakie only allows up to $maxlength lights."
lights = view(lights, 1:maxlength)
end

lights = Makie.GenericGLLight.(lights)
attr[:light_types] = [light.type for light in lights]
attr[:light_colors] = [light.color for light in lights]
attr[:light_positions] = [light.position for light in lights]
attr[:light_directions] = [light.direction for light in lights]
attr[:light_attentuation_parameters] = [light.attentuation_parameters for light in lights]
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_parameters] = Vec3f.(Makie.light_parameters.(lights))

attr[:lights_length] = N
attr[:lights_length] = length(lights)
# @info "Inserted $N lights."
return attr
end
Expand Down Expand Up @@ -137,15 +139,17 @@ function cached_robj!(robj_func, screen, scene, x::AbstractPlot)
gl_key => gl_value
end)

pointlight = Makie.get_point_light(scene)
if !isnothing(pointlight)
gl_attributes[:lightposition] = pointlight.position
end

ambientlight = Makie.get_ambient_light(scene)
if !isnothing(ambientlight)
gl_attributes[:ambient] = ambientlight.color
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)
Expand Down
2 changes: 1 addition & 1 deletion GLMakie/src/glshaders/mesh.jl
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ function draw_mesh(screen, data::Dict)
screen,
"util.vert", "mesh.vert",
"fragment_output.frag", "mesh.frag",
"lighting.vert", "lighting.frag",
"lighting.frag",
view = Dict(
# "light_calc" => light_calc(shading),
"buffers" => output_buffers(screen, to_value(transparency)),
Expand Down
2 changes: 1 addition & 1 deletion GLMakie/src/glshaders/particles.jl
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ function draw_mesh_particle(screen, p, data)
transparency = false
shader = GLVisualizeShader(
screen,
"util.vert", "lighting.vert", "particles.vert",
"util.vert", "particles.vert",
"fragment_output.frag", "lighting.frag", "mesh.frag",
view = Dict(
"position_calc" => position_calc(position, nothing, nothing, nothing, TextureBuffer),
Expand Down
2 changes: 1 addition & 1 deletion GLMakie/src/glshaders/surface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ function draw_surface(screen, main, data::Dict)
transparency = false
shader = GLVisualizeShader(
screen,
"util.vert", "lighting.vert", "surface.vert",
"util.vert", "surface.vert",
"fragment_output.frag", "lighting.frag", "mesh.frag",
view = Dict(
"position_calc" => position_calc(position, position_x, position_y, position_z, Texture),
Expand Down
99 changes: 52 additions & 47 deletions src/lighting.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,29 @@
abstract type AbstractLight end

# GLMakie interface

# These need to match up with light shaders to differentiate light types
module LightType
const UNDEFINED = 0
const Ambient = 1
const PointLight = 2
const DirectionalLight = 3
const SpotLight = 4
end

# always implement
light_type(::AbstractLight) = LightType.UNDEFINED

# implement as needed (keep types)
light_color(::AbstractLight) = RGBf(0, 0, 0)
light_position(::AbstractLight) = Vec3f(0)
light_direction(::AbstractLight) = Vec3f(0)
light_parameters(::AbstractLight) = Vec3f(0) # extra data passthrough



# TODO: Should we allow Palette for Light color initialization?

# TODO: probably need some kind of resize tracking?
# struct LightVector
# lights::Vector{AbstractLight}
Expand All @@ -24,18 +48,42 @@ struct AmbientLight <: AbstractLight
color::Observable{RGBf}
end

light_type(::AmbientLight) = LightType.Ambient
light_color(l::AmbientLight) = l.color[]


"""
PointLight(position, color)
PointLight(color, position)
A point-like light source placed at the given `position` with the given light
`color`. This takes the direction of the light and the surface normals of the
object into account.
`color`.
"""
struct PointLight <: AbstractLight
color::Observable{RGBf}
position::Observable{Vec3f}
radiance::Observable{RGBf} # TODO rename?
end

light_type(::PointLight) = LightType.PointLight
light_color(l::PointLight) = l.color[]
light_position(l::PointLight) = l.position[]


"""
DirectionalLight(color, direction)
A light type which simulates a distant light source with parallel light rays
going in the given `direction`.
"""
struct DirectionalLight <: AbstractLight
color::Observable{RGBf}
direction::Observable{Vec3f}
end

light_type(::DirectionalLight) = LightType.DirectionalLight
light_color(l::DirectionalLight) = l.color[]
light_direction(l::DirectionalLight) = l.direction[]


"""
EnvironmentLight(intensity, image)
Expand All @@ -51,48 +99,5 @@ end
function get_one_light(lights, Typ)
indices = findall(x-> x isa Typ, lights)
isempty(indices) && return nothing
if length(indices) > 1
@warn("Only one light supported by backend right now. Using only first light")
end
return lights[indices[1]]
end

module LightType
const UNDEFINED = 0
const Ambient = 1
const PointLight = 2
const DirectionalLight = 3
const SpotLight = 4
end

"""
GenericGLLight
Conversion target for lights in GLMakie.
"""
struct GenericGLLight <: AbstractLight
type::Int32
color::RGBf # include intensity
position::Point3f # world space
direction::Vec3f # world space

# intensity reduction following
# f = 1 / (c + l * d + q * d * d) (constant, linear, quadratic, distance)
# where (c, l, q) = attenuation_parameters
attentuation_parameters::Vec3f
end

function GenericGLLight(;
type = LightType.UNDEFINED, color = RGBf(1, 1, 1), position = Point3f(0),
direction = Vec3f(0), attenuation_parameters = Vec3f(1, 0, 0)
)
GenericGLLight(type, color, position, direction, attenuation_parameters)
end

function GenericGLLight(light::AmbientLight)
return GenericGLLight(type = LightType.Ambient, color = light.color[])
end

function GenericGLLight(light::PointLight)
return GenericGLLight(type = LightType.PointLight, color = light.radiance[], position = light.position[])
end
2 changes: 1 addition & 1 deletion src/scenes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ function Scene(;
else
error("Wrong lightposition type, use `:eyeposition` or `Vec3f(...)`")
end
push!(scene.lights, PointLight(position, RGBf(1, 1, 1)))
push!(scene.lights, PointLight(RGBf(1, 1, 1), position))
end
ambient = to_value(get(m_theme, :ambient, nothing))
if !isnothing(ambient)
Expand Down

0 comments on commit b6f6bda

Please sign in to comment.