Skip to content

Commit

Permalink
integrate lighting with volume
Browse files Browse the repository at this point in the history
  • Loading branch information
ffreyer committed Sep 28, 2023
1 parent 9bf730f commit df40954
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 51 deletions.
49 changes: 29 additions & 20 deletions GLMakie/assets/shader/lighting.frag
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ uniform float backlight;
in vec3 o_camdir;
in vec3 o_world_pos;

vec3 blinn_phong(vec3 light_color, vec3 normal, vec3 light_dir, vec3 color) {
vec3 blinn_phong(vec3 light_color, vec3 light_dir, vec3 camdir, vec3 normal, vec3 color) {
// diffuse coefficient (how directly does light hits the surface)
float diff_coeff = max(dot(light_dir, -normal), 0.0) +
backlight * max(dot(light_dir, normal), 0.0);

// specular coefficient (does reflected light bounce into camera?)
vec3 H = normalize(light_dir + normalize(o_camdir));
vec3 H = normalize(light_dir + camdir);
float spec_coeff = max(dot(H, -normal), 0.0) + backlight * max(dot(H, normal), 0.0);
spec_coeff = pow(spec_coeff, shininess);
if (diff_coeff <= 0.0 || isnan(spec_coeff))
Expand All @@ -55,10 +55,14 @@ uniform vec3 ambient;
uniform vec3 light_color;
uniform vec3 lightposition;

vec3 illuminate(vec3 world_pos, vec3 camdir, vec3 normal, vec3 base_color) {
vec3 light_dir = normalize(world_pos - lightposition);
vec3 shaded_color = blinn_phong(light_color, light_dir, camdir, normal, base_color);
return ambient * base_color + shaded_color;
}

vec3 illuminate(vec3 normal, vec3 base_color) {
vec3 lightdir = normalize(o_world_pos - lightposition);
vec3 shaded_color = blinn_phong(light_color, normal, lightdir, base_color.rgb);
return ambient * base_color.rgb + shaded_color;
return illuminate(o_world_pos, o_camdir, normal, base_color);
}

#endif
Expand Down Expand Up @@ -87,13 +91,13 @@ uniform int light_types[MAX_LIGHTS];
uniform vec3 light_colors[MAX_LIGHTS];
uniform float light_parameters[MAX_LIGHT_PARAMETERS];

vec3 calc_point_light(vec3 light_color, uint idx, vec3 normal, vec3 color) {
vec3 calc_point_light(vec3 light_color, uint idx, vec3 world_pos, vec3 camdir, vec3 normal, vec3 color) {
// extract args
vec3 position = vec3(light_parameters[idx], light_parameters[idx+1], light_parameters[idx+2]);
vec2 param = vec2(light_parameters[idx+3], light_parameters[idx+4]);

// calculate light direction and distance
vec3 light_vec = o_world_pos - position;
vec3 light_vec = world_pos - position;

float dist = length(light_vec);
vec3 light_dir = normalize(light_vec);
Expand All @@ -102,28 +106,29 @@ vec3 calc_point_light(vec3 light_color, uint idx, vec3 normal, vec3 color) {
// float attentuation = 1.0 / (1.0 + dist * dist * dist);
float attentuation = 1.0 / (1.0 + param.x * dist + param.y * dist * dist);

return attentuation * blinn_phong(light_color, normal, light_dir, color);
return attentuation * blinn_phong(light_color, light_dir, camdir, normal, color);
}

vec3 calc_directional_light(vec3 light_color, uint idx, vec3 normal, vec3 color) {
vec3 direction = vec3(light_parameters[idx], light_parameters[idx+1], light_parameters[idx+2]);
return blinn_phong(light_color, normal, direction, color);
vec3 calc_directional_light(vec3 light_color, uint idx, vec3 camdir, vec3 normal, vec3 color) {
vec3 light_dir = vec3(light_parameters[idx], light_parameters[idx+1], light_parameters[idx+2]);
return blinn_phong(light_color, light_dir, camdir, normal, color);
}

vec3 calc_spot_light(vec3 light_color, uint idx, vec3 normal, vec3 color) {
vec3 calc_spot_light(vec3 light_color, uint idx, vec3 world_pos, vec3 camdir, vec3 normal, vec3 color) {
// extract args
vec3 position = vec3(light_parameters[idx], light_parameters[idx+1], light_parameters[idx+2]);
vec3 light_dir = normalize(vec3(light_parameters[idx+3], light_parameters[idx+4], light_parameters[idx+5]));
vec3 spot_light_dir = normalize(vec3(light_parameters[idx+3], light_parameters[idx+4], light_parameters[idx+5]));
float inner_angle = light_parameters[idx+6]; // cos applied
float outer_angle = light_parameters[idx+7]; // cos applied

vec3 vertex_dir = normalize(o_world_pos - position);
float intensity = smoothstep(outer_angle, inner_angle, dot(vertex_dir, light_dir));
vec3 light_dir = normalize(world_pos - position);
float intensity = smoothstep(outer_angle, inner_angle, dot(light_dir, spot_light_dir));

return intensity * blinn_phong(light_color, normal, vertex_dir, color);
return intensity * blinn_phong(light_color, light_dir, camdir, normal, color);
}

vec3 illuminate(vec3 normal, vec3 base_color) {
vec3 illuminate(vec3 world_pos, vec3 camdir, vec3 normal, vec3 base_color) {
// TODO lightdir
vec3 final_color = vec3(0);
uint idx = 0;
for (int i = 0; i < min(N_lights, MAX_LIGHTS); i++) {
Expand All @@ -132,15 +137,15 @@ vec3 illuminate(vec3 normal, vec3 base_color) {
final_color += light_colors[i] * base_color;
break;
case PointLight:
final_color += calc_point_light(light_colors[i], idx, normal, base_color);
final_color += calc_point_light(light_colors[i], idx, world_pos, camdir, normal, base_color);
idx += 5; // 3 position, 2 attenuation params
break;
case DirectionalLight:
final_color += calc_directional_light(light_colors[i], idx, normal, base_color);
final_color += calc_directional_light(light_colors[i], idx, camdir, normal, base_color);
idx += 3; // 3 direction
break;
case SpotLight:
final_color += calc_spot_light(light_colors[i], idx, normal, base_color);
final_color += calc_spot_light(light_colors[i], idx, world_pos, camdir, normal, base_color);
idx += 8; // 3 position, 3 direction, 1 parameter
break;
default:
Expand All @@ -150,4 +155,8 @@ vec3 illuminate(vec3 normal, vec3 base_color) {
return final_color;
}

vec3 illuminate(vec3 normal, vec3 base_color) {
return illuminate(o_world_pos, normalize(o_camdir), normal, base_color);
}

#endif
43 changes: 16 additions & 27 deletions GLMakie/assets/shader/volume.frag
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
{{GLSL_VERSION}}

// Sets which shading procedures to use
// Options:
// NO_SHADING - skip shading calculation, handled outside
// FAST_SHADING - single point light (forward rendering)
// MULTI_LIGHT_SHADING - simple shading with multiple lights (forward rendering)
{{shading}}

struct Nothing{ //Nothing type, to encode if some variable doesn't contain any data
bool _; //empty structs are not allowed
};
in vec3 frag_vert;
in vec3 o_light_dir;

{{volumedata_type}} volumedata;

Expand All @@ -15,11 +21,6 @@ in vec3 o_light_dir;
uniform float absorption = 1.0;
uniform vec3 eyeposition;

uniform vec3 ambient;
uniform vec3 diffuse;
uniform vec3 specular;
uniform float shininess;

uniform mat4 modelinv;
uniform int algorithm;
uniform float isovalue;
Expand Down Expand Up @@ -107,21 +108,9 @@ vec3 gennormal(vec3 uvw, float d)
return normalize(a-b);
}

// Includes front and back-facing normals (N, -N)
vec3 blinnphong(vec3 N, vec3 V, vec3 L, vec3 color){
float diff_coeff = max(dot(L, N), 0.0) + max(dot(L, -N), 0.0);
// specular coefficient
vec3 H = normalize(L + V);
float spec_coeff = pow(max(dot(H, N), 0.0) + max(dot(H, -N), 0.0), shininess);
if (diff_coeff <= 0.0 || isnan(spec_coeff))
spec_coeff = 0.0;
// final lighting model
return vec3(
ambient * color +
diffuse * diff_coeff * color +
specular * spec_coeff
);
}
#ifndef NO_SHADING
vec3 illuminate(vec3 world_pos, vec3 camdir, vec3 normal, vec3 base_color);
#endif

// Simple random generator found: http://stackoverflow.com/questions/4200224/random-noise-functions-for-glsl
float rand(){
Expand Down Expand Up @@ -208,7 +197,7 @@ vec4 contours(vec3 front, vec3 dir)
float T = 1.0;
vec3 Lo = vec3(0.0);
int i = 0;
vec3 camdir = normalize(-dir);
vec3 camdir = normalize(dir);
{{depth_init}}
// may write: float depth = 100000.0;
for (i; i < num_samples; ++i) {
Expand All @@ -221,8 +210,8 @@ vec4 contours(vec3 front, vec3 dir)
// vec4 frag_coord = projectionview * model * vec4(pos, 1);
// depth = min(depth, frag_coord.z / frag_coord.w);
vec3 N = gennormal(pos, step_size);
vec3 L = normalize(o_light_dir - pos);
vec3 opaque = blinnphong(N, camdir, L, density.rgb);
vec4 world_pos = model * vec4(pos, 1);
vec3 opaque = illuminate(world_pos.xyz / world_pos.w, camdir, N, density.rgb);
Lo += (T * opacity) * opaque;
T *= 1.0 - opacity;
if (T <= 0.01)
Expand All @@ -242,7 +231,7 @@ vec4 isosurface(vec3 front, vec3 dir)
vec4 c = vec4(0.0);
int i = 0;
vec4 diffuse_color = color_lookup(isovalue, color_map, color_norm, color);
vec3 camdir = normalize(-dir);
vec3 camdir = normalize(dir);
{{depth_init}}
// may write: float depth = 100000.0;
for (i; i < num_samples; ++i){
Expand All @@ -253,9 +242,9 @@ vec4 isosurface(vec3 front, vec3 dir)
// vec4 frag_coord = projectionview * model * vec4(pos, 1);
// depth = min(depth, frag_coord.z / frag_coord.w);
vec3 N = gennormal(pos, step_size);
vec3 L = normalize(o_light_dir - pos);
vec4 world_pos = model * vec4(pos, 1);
c = vec4(
blinnphong(N, camdir, L, diffuse_color.rgb),
illuminate(world_pos.xyz / world_pos.w, camdir, N, diffuse_color.rgb),
diffuse_color.a
);
break;
Expand Down
8 changes: 6 additions & 2 deletions GLMakie/assets/shader/volume.vert
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,28 @@
in vec3 vertices;

out vec3 frag_vert;
out vec3 o_light_dir;
// out vec3 o_light_pos;

uniform mat4 projectionview, model;
uniform vec3 lightposition;
uniform mat4 modelinv;
uniform float depth_shift;

// SSAO
out vec3 o_view_pos;
out vec3 o_view_normal;

// Lighting (unused, don't need to be available?)
// out vec3 o_world_pos;
// out vec3 o_world_normal;

void main()
{
// TODO set these in volume.frag
o_view_pos = vec3(0);
o_view_normal = vec3(0);
vec4 world_vert = model * vec4(vertices, 1);
frag_vert = world_vert.xyz;
o_light_dir = vec3(modelinv * vec4(lightposition, 1));
gl_Position = projectionview * world_vert;
gl_Position.z += gl_Position.w * depth_shift;
}
10 changes: 8 additions & 2 deletions GLMakie/src/glshaders/image_like.jl
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ end
function draw_volume(screen, main::VolumeTypes, data::Dict)
geom = Rect3f(Vec3f(0), Vec3f(1))
to_opengl_mesh!(data, const_lift(GeometryBasics.triangle_mesh, geom))
shading = pop!(data, :shading, :fxaa)
shading = pop!(data, :shading, :fast)
pop!(data, :backlight, 0f0) # We overwrite this
@gen_defaults! data begin
volumedata = main => Texture
model = Mat4f(I)
Expand All @@ -69,12 +70,17 @@ function draw_volume(screen, main::VolumeTypes, data::Dict)
absorption = 1f0
isovalue = 0.5f0
isorange = 0.01f0
backlight = 1f0
enable_depth = true
transparency = false
shader = GLVisualizeShader(
screen,
"fragment_output.frag", "util.vert", "volume.vert", "volume.frag",
"util.vert", "volume.vert",
"fragment_output.frag", "lighting.frag", "volume.frag",
view = Dict(
"shading" => light_calc(shading),
"MAX_LIGHTS" => "#define MAX_LIGHTS $(screen.config.max_lights)",
"MAX_LIGHT_PARAMETERS" => "#define MAX_LIGHT_PARAMETERS $(screen.config.max_light_parameters)",
"depth_init" => vol_depth_init(to_value(enable_depth)),
"depth_default" => vol_depth_default(to_value(enable_depth)),
"depth_main" => vol_depth_main(to_value(enable_depth)),
Expand Down

0 comments on commit df40954

Please sign in to comment.