LOD shading closer to voxel shading.

This commit is contained in:
Joshua Yanovski 2020-05-01 22:58:55 +02:00
parent ef67bd58ba
commit dd74fa7e4a
13 changed files with 351 additions and 59 deletions

View File

@ -115,7 +115,7 @@ void main() {
float opacity = clamp(distance / distance_divider, 0, 1); float opacity = clamp(distance / distance_divider, 0, 1);
if(threshold_matrix[int(gl_FragCoord.x) % 4][int(gl_FragCoord.y) % 4] > opacity) { if(threshold_matrix[int(gl_FragCoord.x) % 4][int(gl_FragCoord.y) % 4] > opacity) {
tgt_color = vec4(color, 0.0); discard;
return; return;
} }
} }

View File

@ -64,5 +64,6 @@ void main() {
// f_shadow = textureBicubic(t_horizon, pos_to_tex(f_pos.xy)); // f_shadow = textureBicubic(t_horizon, pos_to_tex(f_pos.xy));
gl_Position = all_mat * vec4(f_pos, 1); gl_Position = all_mat * vec4(f_pos, 1);
// gl_Position.z = -gl_Position.z / 100.0;
gl_Position.z = -1000.0 / (gl_Position.z + 10000.0); gl_Position.z = -1000.0 / (gl_Position.z + 10000.0);
} }

View File

@ -39,7 +39,7 @@ void main() {
// vec3 view_dir = normalize(-vec3(vert_pos4)/* / vert_pos4.w*/); // vec3 view_dir = normalize(-vec3(vert_pos4)/* / vert_pos4.w*/);
vec3 view_dir = -cam_to_frag; vec3 view_dir = -cam_to_frag;
// vec3 surf_color = /*srgb_to_linear*/(vec3(0.4, 0.7, 2.0)); // vec3 surf_color = /*srgb_to_linear*/(vec3(0.4, 0.7, 2.0));
/*const */vec3 water_color = srgb_to_linear(vec3(0.2, 0.5, 1.0)); /*const */vec3 water_color = 1.0 - MU_WATER;//srgb_to_linear(vec3(0.2, 0.5, 1.0));
// /*const */vec3 water_color = srgb_to_linear(vec3(0.0, 0.25, 0.5)); // /*const */vec3 water_color = srgb_to_linear(vec3(0.0, 0.25, 0.5));
vec3 sun_dir = get_sun_dir(time_of_day.x); vec3 sun_dir = get_sun_dir(time_of_day.x);
@ -52,13 +52,18 @@ void main() {
// float moon_shade_frac = horizon_at(/*f_shadow, f_pos.z, */f_pos, moon_dir); // float moon_shade_frac = horizon_at(/*f_shadow, f_pos.z, */f_pos, moon_dir);
float shade_frac = /*1.0;*/sun_shade_frac + moon_shade_frac; float shade_frac = /*1.0;*/sun_shade_frac + moon_shade_frac;
float fluid_alt = max(ceil(f_pos.z), floor(f_alt));// f_alt;//max(f_alt - f_pos.z, 0.0);
const float alpha = 0.255/* / 4.0 / sqrt(2.0)*/; const float alpha = 0.255/* / 4.0 / sqrt(2.0)*/;
const float n2 = 1.3325; const float n2 = 1.3325;
const float R_s2s0 = pow((1.0 - n2) / (1.0 + n2), 2); const float R_s2s0 = pow((1.0 - n2) / (1.0 + n2), 2);
const float R_s1s0 = pow((1.3325 - n2) / (1.3325 + n2), 2); const float R_s1s0 = pow((1.3325 - n2) / (1.3325 + n2), 2);
const float R_s2s1 = pow((1.0 - 1.3325) / (1.0 + 1.3325), 2); const float R_s2s1 = pow((1.0 - 1.3325) / (1.0 + 1.3325), 2);
const float R_s1s2 = pow((1.3325 - 1.0) / (1.3325 + 1.0), 2); const float R_s1s2 = pow((1.3325 - 1.0) / (1.3325 + 1.0), 2);
float R_s = (f_pos.z < f_alt) ? mix(R_s2s1 * R_s1s0, R_s1s0, medium.x) : mix(R_s2s0, R_s1s2 * R_s2s0, medium.x); float R_s = (f_pos.z < fluid_alt) ? mix(R_s2s1 * R_s1s0, R_s1s0, medium.x) : mix(R_s2s0, R_s1s2 * R_s2s0, medium.x);
// NOTE: Assumes normal is vertical.
vec3 sun_view_dir = cam_pos.z <= fluid_alt ? /*refract(view_dir, -f_norm, 1.0 / n2)*//*reflect(view_dir, -f_norm)*/vec3(view_dir.xy, -view_dir.z) : view_dir;
vec3 k_a = vec3(1.0); vec3 k_a = vec3(1.0);
vec3 k_d = vec3(1.0); vec3 k_d = vec3(1.0);
@ -78,7 +83,7 @@ void main() {
// vec3 surf_color = /*srgb_to_linear*/(vec3(0.4, 0.7, 2.0)); // vec3 surf_color = /*srgb_to_linear*/(vec3(0.4, 0.7, 2.0));
float max_light = 0.0; float max_light = 0.0;
max_light += get_sun_diffuse2(f_norm, /*time_of_day.x*/sun_dir, moon_dir, /*-cam_to_frag*/view_dir, k_a/* * (shade_frac * 0.5 + light_frac * 0.5)*/, vec3(0.0), k_s, alpha, emitted_light, reflected_light); max_light += get_sun_diffuse2(f_norm, /*time_of_day.x*/sun_dir, moon_dir, /*-cam_to_frag*/sun_view_dir, k_a/* * (shade_frac * 0.5 + light_frac * 0.5)*/, /*vec3(0.0)*/k_d, k_s, alpha, emitted_light, reflected_light);
reflected_light *= f_light * point_shadow * shade_frac; reflected_light *= f_light * point_shadow * shade_frac;
emitted_light *= f_light * point_shadow * max(shade_frac, MIN_SHADOW); emitted_light *= f_light * point_shadow * max(shade_frac, MIN_SHADOW);
max_light *= f_light * point_shadow * shade_frac; max_light *= f_light * point_shadow * shade_frac;
@ -96,16 +101,18 @@ void main() {
emitted_light += point_light; emitted_light += point_light;
reflected_light += point_light; */ reflected_light += point_light; */
vec3 diffuse_light_point = vec3(0.0); max_light += lights_at(f_pos, f_norm, view_dir, /*vec3(0.0), vec3(1.0), fluid_alt, */k_a, k_d, k_s, alpha, emitted_light, reflected_light);
max_light += lights_at(f_pos, f_norm, view_dir, k_a, vec3(1.0), k_s, alpha, emitted_light, diffuse_light_point); // vec3 diffuse_light_point = vec3(0.0);
// max_light += lights_at(f_pos, f_norm, view_dir, k_a, vec3(1.0), k_s, alpha, emitted_light, diffuse_light_point);
vec3 dump_light = vec3(0.0); float reflected_light_point = length(reflected_light);///*length*/(diffuse_light_point.r) + f_light * point_shadow;
vec3 specular_light_point = vec3(0.0); // vec3 dump_light = vec3(0.0);
lights_at(f_pos, f_norm, view_dir, vec3(0.0), vec3(0.0), /*vec3(1.0)*/k_s, alpha, dump_light, specular_light_point); // vec3 specular_light_point = vec3(0.0);
diffuse_light_point -= specular_light_point; // lights_at(f_pos, f_norm, view_dir, vec3(0.0), vec3(0.0), /*vec3(1.0)*/k_s, alpha, dump_light, specular_light_point);
// diffuse_light_point -= specular_light_point;
float reflected_light_point = /*length*/(diffuse_light_point.r) + f_light * point_shadow; // float reflected_light_point = /*length*/(diffuse_light_point.r) + f_light * point_shadow;
reflected_light += k_d * (diffuse_light_point + f_light * point_shadow * shade_frac) + specular_light_point; // reflected_light += k_d * (diffuse_light_point + f_light * point_shadow * shade_frac) + specular_light_point;
float fog_level = fog(f_pos.xyz, focus_pos.xyz, medium.x); float fog_level = fog(f_pos.xyz, focus_pos.xyz, medium.x);
vec4 clouds; vec4 clouds;
@ -114,7 +121,7 @@ void main() {
float passthrough = /*pow(*/dot(faceforward(f_norm, f_norm, cam_to_frag/*view_dir*/), -cam_to_frag/*view_dir*/)/*, 0.5)*/; float passthrough = /*pow(*/dot(faceforward(f_norm, f_norm, cam_to_frag/*view_dir*/), -cam_to_frag/*view_dir*/)/*, 0.5)*/;
vec3 surf_color = illuminate(max_light, water_color * fog_color * emitted_light, /*surf_color * */water_color * reflected_light); vec3 surf_color = illuminate(max_light, water_color * fog_color * emitted_light, /*surf_color * */water_color * reflected_light);
vec4 color = mix(vec4(surf_color, 1.0), vec4(surf_color, 1.0 / (1.0 + /*diffuse_light*//*(f_light * point_shadow + point_light)*/reflected_light_point/* * 0.25*/)), passthrough); vec4 color = mix(vec4(surf_color, 1.0), vec4(surf_color, 1.0 / (1.0 + /*diffuse_light*//*(f_light * point_shadow + point_light)*/4.0 * reflected_light_point/* * 0.25*/)), passthrough);
tgt_color = mix(mix(color, vec4(fog_color, 0.0), fog_level), vec4(clouds.rgb, 0.0), clouds.a); tgt_color = mix(mix(color, vec4(fog_color, 0.0), fog_level), vec4(clouds.rgb, 0.0), clouds.a);
} }

View File

@ -101,8 +101,9 @@ void main() {
nmap = mix(f_norm, normalize(nmap), min(1.0 / pow(frag_dist, 0.75), 1)); nmap = mix(f_norm, normalize(nmap), min(1.0 / pow(frag_dist, 0.75), 1));
vec3 norm = vec3(0, 0, 1) * nmap.z + b_norm * nmap.x + c_norm * nmap.y; vec3 norm = vec3(0, 0, 1) * nmap.z + b_norm * nmap.x + c_norm * nmap.y;
// vec3 norm = f_norm;
float f_alt = alt_at_real(f_pos.xy); float f_alt = alt_at(f_pos.xy);
float fluid_alt = max(ceil(f_pos.z), floor(f_alt));// f_alt;//max(f_alt - f_pos.z, 0.0); float fluid_alt = max(ceil(f_pos.z), floor(f_alt));// f_alt;//max(f_alt - f_pos.z, 0.0);
const float alpha = 0.255/*/ / 4.0*//* / 4.0 / sqrt(2.0)*/; const float alpha = 0.255/*/ / 4.0*//* / 4.0 / sqrt(2.0)*/;
@ -118,7 +119,8 @@ void main() {
vec4 _clouds; vec4 _clouds;
vec3 reflect_ray_dir = reflect(cam_to_frag/*-view_dir*/, norm); vec3 reflect_ray_dir = reflect(cam_to_frag/*-view_dir*/, norm);
vec3 refract_ray_dir = refract(cam_to_frag/*-view_dir*/, norm, 1.0 / n2); vec3 refract_ray_dir = refract(cam_to_frag/*-view_dir*/, norm, 1.0 / n2);
vec3 sun_view_dir = cam_pos.z <= fluid_alt ? -view_dir : view_dir; vec3 sun_view_dir = /*sign(cam_pos.z - fluid_alt) * view_dir;*/cam_pos.z <= fluid_alt ? -view_dir : view_dir;
// vec3 sun_view_dir = cam_pos.z <= fluid_alt ? -view_dir : view_dir;
vec3 beam_view_dir = reflect_ray_dir;//cam_pos.z <= fluid_alt ? -refract_ray_dir : reflect_ray_dir; vec3 beam_view_dir = reflect_ray_dir;//cam_pos.z <= fluid_alt ? -refract_ray_dir : reflect_ray_dir;
/* vec4 reflect_ray_dir4 = view_mat * vec4(reflect_ray_dir, 1.0); /* vec4 reflect_ray_dir4 = view_mat * vec4(reflect_ray_dir, 1.0);
reflect_ray_dir = normalize(vec3(reflect_ray_dir4) / reflect_ray_dir4.w); */ reflect_ray_dir = normalize(vec3(reflect_ray_dir4) / reflect_ray_dir4.w); */
@ -130,7 +132,7 @@ void main() {
// /*const */vec3 water_color = srgb_to_linear(vec3(0.8, 0.9, 1.0)); // /*const */vec3 water_color = srgb_to_linear(vec3(0.8, 0.9, 1.0));
// NOTE: Linear RGB, attenuation coefficients for water at roughly R, G, B wavelengths. // NOTE: Linear RGB, attenuation coefficients for water at roughly R, G, B wavelengths.
// See https://en.wikipedia.org/wiki/Electromagnetic_absorption_by_water // See https://en.wikipedia.org/wiki/Electromagnetic_absorption_by_water
/*const */vec3 water_attenuation = vec3(0.8, 0.05, 0.01); /*const */vec3 water_attenuation = MU_WATER;// vec3(0.8, 0.05, 0.01);
// /*const */vec3 water_color = vec3(0.2, 0.95, 0.99); // /*const */vec3 water_color = vec3(0.2, 0.95, 0.99);
vec3 sun_dir = get_sun_dir(time_of_day.x); vec3 sun_dir = get_sun_dir(time_of_day.x);
@ -192,7 +194,7 @@ void main() {
float passthrough = /*pow(*/dot(faceforward(f_norm, f_norm, cam_to_frag/*view_dir*/), -cam_to_frag/*view_dir*/)/*, 0.5)*/; float passthrough = /*pow(*/dot(faceforward(f_norm, f_norm, cam_to_frag/*view_dir*/), -cam_to_frag/*view_dir*/)/*, 0.5)*/;
float max_light = 0.0; float max_light = 0.0;
max_light += get_sun_diffuse2(norm, /*time_of_day.x*/sun_dir, moon_dir, sun_view_dir, f_pos, mu, cam_attenuation, fluid_alt, k_a/* * (shade_frac * 0.5 + light_frac * 0.5)*/, vec3(k_d), /*vec3(f_light * point_shadow)*//*reflect_color*/k_s, alpha, emitted_light, reflected_light); max_light += get_sun_diffuse2(norm, /*time_of_day.x*/sun_dir, moon_dir, sun_view_dir, f_pos, mu, cam_attenuation, fluid_alt, k_a/* * (shade_frac * 0.5 + light_frac * 0.5)*/, vec3(k_d), /*vec3(f_light * point_shadow)*//*reflect_color*/k_s, alpha, 1.0, emitted_light, reflected_light);
reflected_light *= /*water_color_direct * */reflect_color * f_light * point_shadow * shade_frac; reflected_light *= /*water_color_direct * */reflect_color * f_light * point_shadow * shade_frac;
emitted_light *= /*water_color_direct*//*ambient_attenuation * */f_light * point_shadow * max(shade_frac, MIN_SHADOW); emitted_light *= /*water_color_direct*//*ambient_attenuation * */f_light * point_shadow * max(shade_frac, MIN_SHADOW);
max_light *= f_light * point_shadow * shade_frac; max_light *= f_light * point_shadow * shade_frac;
@ -252,7 +254,8 @@ void main() {
//vec4 color = vec4(surf_color, 1.0); //vec4 color = vec4(surf_color, 1.0);
// vec4 color = mix(vec4(reflect_color, 1.0), vec4(surf_color, 1.0 / (1.0 + /*diffuse_light*/(/*f_light * point_shadow*/reflected_light_point/* + point_light*//*reflected_light*/))), passthrough); // vec4 color = mix(vec4(reflect_color, 1.0), vec4(surf_color, 1.0 / (1.0 + /*diffuse_light*/(/*f_light * point_shadow*/reflected_light_point/* + point_light*//*reflected_light*/))), passthrough);
vec4 color = vec4(surf_color, 1.0 - passthrough * /*log(1.0 + cam_attenuation)*/cam_attenuation); float log_cam = log(min(cam_attenuation.r, min(cam_attenuation.g, cam_attenuation.b)));
vec4 color = vec4(surf_color, passthrough * (1.0 - /*log(1.0 + cam_attenuation)*//*cam_attenuation*/1.0 / (1.0 - log_cam)));
// vec4 color = vec4(surf_color, mix(1.0, 1.0 / (1.0 + /*0.25 * *//*diffuse_light*/(/*f_light * point_shadow*/reflected_light_point)), passthrough)); // vec4 color = vec4(surf_color, mix(1.0, 1.0 / (1.0 + /*0.25 * *//*diffuse_light*/(/*f_light * point_shadow*/reflected_light_point)), passthrough));
// vec4 color = vec4(surf_color, mix(1.0, length(cam_attenuation), passthrough)); // vec4 color = vec4(surf_color, mix(1.0, length(cam_attenuation), passthrough));

View File

@ -41,5 +41,6 @@ void main() {
gl_Position = gl_Position =
all_mat * all_mat *
vec4(f_pos, 1); vec4(f_pos, 1);
// gl_Position.z = -gl_Position.z / 100.0;
gl_Position.z = -1000.0 / (gl_Position.z + 10000.0); gl_Position.z = -1000.0 / (gl_Position.z + 10000.0);
} }

View File

@ -8,13 +8,13 @@ const float PI = 3.141592;
const vec3 SKY_DAY_TOP = vec3(0.1, 0.5, 0.9); const vec3 SKY_DAY_TOP = vec3(0.1, 0.5, 0.9);
const vec3 SKY_DAY_MID = vec3(0.02, 0.28, 0.8); const vec3 SKY_DAY_MID = vec3(0.02, 0.28, 0.8);
const vec3 SKY_DAY_BOT = vec3(0.1, 0.2, 0.3); const vec3 SKY_DAY_BOT = vec3(0.1, 0.2, 0.3);
const vec3 DAY_LIGHT = vec3(1.0, 1.0, 1.0); const vec3 DAY_LIGHT = vec3(1.5, 1.4, 1.0);
const vec3 SUN_HALO_DAY = vec3(0.35, 0.35, 0.0); const vec3 SUN_HALO_DAY = vec3(0.35, 0.35, 0.0);
const vec3 SKY_DUSK_TOP = vec3(0.06, 0.1, 0.20); const vec3 SKY_DUSK_TOP = vec3(0.06, 0.1, 0.20);
const vec3 SKY_DUSK_MID = vec3(0.35, 0.1, 0.15); const vec3 SKY_DUSK_MID = vec3(0.35, 0.1, 0.15);
const vec3 SKY_DUSK_BOT = vec3(0.0, 0.1, 0.23); const vec3 SKY_DUSK_BOT = vec3(0.0, 0.1, 0.23);
const vec3 DUSK_LIGHT = vec3(3.0, 1.5, 0.3); const vec3 DUSK_LIGHT = vec3(8.0, 1.5, 0.15);
const vec3 SUN_HALO_DUSK = vec3(1.2, 0.15, 0.0); const vec3 SUN_HALO_DUSK = vec3(1.2, 0.15, 0.0);
const vec3 SKY_NIGHT_TOP = vec3(0.001, 0.001, 0.0025); const vec3 SKY_NIGHT_TOP = vec3(0.001, 0.001, 0.0025);
@ -135,7 +135,7 @@ vec3 get_moon_color(vec3 moon_dir) {
// mu is the attenuation coefficient for any substance on a horizontal plane. // mu is the attenuation coefficient for any substance on a horizontal plane.
// cam_attenuation is the total light attenuation due to the substance for beams between the point and the camera. // cam_attenuation is the total light attenuation due to the substance for beams between the point and the camera.
// surface_alt is the altitude of the attenuating surface. // surface_alt is the altitude of the attenuating surface.
float get_sun_diffuse2(vec3 norm, vec3 sun_dir, vec3 moon_dir, vec3 dir, vec3 wpos, vec3 mu, vec3 cam_attenuation, float surface_alt, vec3 k_a, vec3 k_d, vec3 k_s, float alpha, out vec3 emitted_light, out vec3 reflected_light) { float get_sun_diffuse2(vec3 norm, vec3 sun_dir, vec3 moon_dir, vec3 dir, vec3 wpos, vec3 mu, vec3 cam_attenuation, float surface_alt, vec3 k_a, vec3 k_d, vec3 k_s, float alpha, float voxel_lighting, out vec3 emitted_light, out vec3 reflected_light) {
const vec3 SUN_AMBIANCE = MU_SCATTER;//0.23;/* / 1.8*/;// 0.1 / 3.0; const vec3 SUN_AMBIANCE = MU_SCATTER;//0.23;/* / 1.8*/;// 0.1 / 3.0;
const vec3 MOON_AMBIANCE = MU_SCATTER;//0.23;//0.1; const vec3 MOON_AMBIANCE = MU_SCATTER;//0.23;//0.1;
@ -239,7 +239,7 @@ float get_sun_diffuse2(vec3 norm, vec3 sun_dir, vec3 moon_dir, vec3 dir, vec3 wp
vec3 R_t_r = R_d + R_r; vec3 R_t_r = R_d + R_r;
// vec3 half_vec = normalize(-norm + dir); // vec3 half_vec = normalize(-norm + dir);
vec3 light_frac = R_t_b * (sun_chroma * SUN_AMBIANCE + moon_chroma * MOON_AMBIANCE) * light_reflection_factor(norm, /*norm*//*dir*/dir, /*-norm*/-dir, /*k_d*/k_d/* * (1.0 - k_s)*/, /*k_s*/vec3(0.0), alpha); vec3 light_frac = R_t_b * (sun_chroma * SUN_AMBIANCE + moon_chroma * MOON_AMBIANCE) * light_reflection_factor(norm, /*norm*//*dir*/dir, /*-norm*/-dir, /*k_d*/k_d/* * (1.0 - k_s)*/, /*k_s*/vec3(0.0), alpha, voxel_lighting);
// vec3 light_frac = /*vec3(1.0)*//*H_d * */ // vec3 light_frac = /*vec3(1.0)*//*H_d * */
// SUN_AMBIANCE * /*sun_light*/sun_chroma * light_reflection_factor(norm, dir, /*vec3(0, 0, -1.0)*/-norm, vec3((1.0 + cos_sun) * 0.5), vec3(k_s * (1.0 - cos_sun) * 0.5), alpha) + // SUN_AMBIANCE * /*sun_light*/sun_chroma * light_reflection_factor(norm, dir, /*vec3(0, 0, -1.0)*/-norm, vec3((1.0 + cos_sun) * 0.5), vec3(k_s * (1.0 - cos_sun) * 0.5), alpha) +
// MOON_AMBIANCE * /*sun_light*/moon_chroma * light_reflection_factor(norm, dir, /*vec3(0, 0, -1.0)*/-norm, vec3((1.0 + cos_moon) * 0.5), vec3(k_s * (1.0 - cos_moon) * 0.5), alpha); // MOON_AMBIANCE * /*sun_light*/moon_chroma * light_reflection_factor(norm, dir, /*vec3(0, 0, -1.0)*/-norm, vec3((1.0 + cos_moon) * 0.5), vec3(k_s * (1.0 - cos_moon) * 0.5), alpha);
@ -259,10 +259,10 @@ float get_sun_diffuse2(vec3 norm, vec3 sun_dir, vec3 moon_dir, vec3 dir, vec3 wp
// TODO: Add shadows. // TODO: Add shadows.
reflected_light = R_t_r * ( reflected_light = R_t_r * (
(1.0 - SUN_AMBIANCE) * sun_chroma * (light_reflection_factor(norm, dir, sun_dir, k_d, k_s, alpha) /*+ (1.0 - SUN_AMBIANCE) * sun_chroma * (light_reflection_factor(norm, dir, sun_dir, k_d, k_s, alpha, voxel_lighting) /*+
light_reflection_factor(norm, dir, normalize(sun_dir + vec3(0.0, 0.1, 0.0)), k_d, k_s, alpha) + light_reflection_factor(norm, dir, normalize(sun_dir + vec3(0.0, 0.1, 0.0)), k_d, k_s, alpha) +
light_reflection_factor(norm, dir, normalize(sun_dir - vec3(0.0, 0.1, 0.0)), k_d, k_s, alpha)*/) + light_reflection_factor(norm, dir, normalize(sun_dir - vec3(0.0, 0.1, 0.0)), k_d, k_s, alpha)*/) +
(1.0 - MOON_AMBIANCE) * moon_chroma * 1.0 * /*4.0 * */light_reflection_factor(norm, dir, moon_dir, k_d, k_s, alpha) (1.0 - MOON_AMBIANCE) * moon_chroma * 1.0 * /*4.0 * */light_reflection_factor(norm, dir, moon_dir, k_d, k_s, alpha, voxel_lighting)
); );
/* light = sun_chroma + moon_chroma + PERSISTENT_AMBIANCE; /* light = sun_chroma + moon_chroma + PERSISTENT_AMBIANCE;
@ -274,8 +274,12 @@ float get_sun_diffuse2(vec3 norm, vec3 sun_dir, vec3 moon_dir, vec3 dir, vec3 wp
return rel_luminance(emitted_light + reflected_light);//rel_luminance(emitted_light + reflected_light);//sun_chroma + moon_chroma + PERSISTENT_AMBIANCE; return rel_luminance(emitted_light + reflected_light);//rel_luminance(emitted_light + reflected_light);//sun_chroma + moon_chroma + PERSISTENT_AMBIANCE;
} }
float get_sun_diffuse2(vec3 norm, vec3 sun_dir, vec3 moon_dir, vec3 dir, vec3 k_a, vec3 k_d, vec3 k_s, float alpha, float voxel_lighting, out vec3 emitted_light, out vec3 reflected_light) {
return get_sun_diffuse2(norm, sun_dir, moon_dir, dir, vec3(0.0), vec3(0.0), vec3(1.0), 0.0, k_a, k_d, k_s, alpha, voxel_lighting, emitted_light, reflected_light);
}
float get_sun_diffuse2(vec3 norm, vec3 sun_dir, vec3 moon_dir, vec3 dir, vec3 k_a, vec3 k_d, vec3 k_s, float alpha, out vec3 emitted_light, out vec3 reflected_light) { float get_sun_diffuse2(vec3 norm, vec3 sun_dir, vec3 moon_dir, vec3 dir, vec3 k_a, vec3 k_d, vec3 k_s, float alpha, out vec3 emitted_light, out vec3 reflected_light) {
return get_sun_diffuse2(norm, sun_dir, moon_dir, dir, vec3(0.0), vec3(0.0), vec3(1.0), 0.0, k_a, k_d, k_s, alpha, emitted_light, reflected_light); return get_sun_diffuse2(norm, sun_dir, moon_dir, dir, vec3(0.0), vec3(0.0), vec3(1.0), 0.0, k_a, k_d, k_s, alpha, 1.0, emitted_light, reflected_light);
} }
// This has been extracted into a function to allow quick exit when detecting a star. // This has been extracted into a function to allow quick exit when detecting a star.
@ -299,11 +303,14 @@ float is_star_at(vec3 dir) {
return 0.0; return 0.0;
} }
vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float quality, bool with_stars, out vec4 clouds) { vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float quality, bool with_stars, float refractionIndex, out vec4 clouds) {
// Sky color // Sky color
vec3 sun_dir = get_sun_dir(time_of_day); vec3 sun_dir = get_sun_dir(time_of_day);
vec3 moon_dir = get_moon_dir(time_of_day); vec3 moon_dir = get_moon_dir(time_of_day);
// sun_dir = sun_dir.z <= 0 ? refract(sun_dir/*-view_dir*/, vec3(0.0, 0.0, 1.0), refractionIndex) : sun_dir;
// moon_dir = moon_dir.z <= 0 ? refract(moon_dir/*-view_dir*/, vec3(0.0, 0.0, 1.0), refractionIndex) : moon_dir;
// Add white dots for stars. Note these flicker and jump due to FXAA // Add white dots for stars. Note these flicker and jump due to FXAA
float star = 0.0; float star = 0.0;
if (with_stars) { if (with_stars) {
@ -321,7 +328,7 @@ vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float q
); );
vec3 sun_halo = pow(max(dot(dir, -sun_dir) + 0.1, 0.0), 8.0) * sun_halo_color; vec3 sun_halo = pow(max(dot(dir, -sun_dir) + 0.1, 0.0), 8.0) * sun_halo_color;
vec3 sun_surf = pow(max(dot(dir, -sun_dir) - 0.001, 0.0), 3000.0) * SUN_SURF_COLOR; vec3 sun_surf = pow(max(dot(dir, -sun_dir) - 0.001, 0.0), 3000.0) * SUN_SURF_COLOR * SUN_COLOR_FACTOR;
vec3 sun_light = (sun_halo + sun_surf) * clamp(dir.z * 10.0, 0, 1); vec3 sun_light = (sun_halo + sun_surf) * clamp(dir.z * 10.0, 0, 1);
// Moon // Moon
@ -388,6 +395,10 @@ vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float q
return mix(sky_color, clouds.rgb, clouds.a); return mix(sky_color, clouds.rgb, clouds.a);
} }
vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float quality, bool with_stars, out vec4 clouds) {
return get_sky_color(dir, time_of_day, origin, f_pos, quality, with_stars, 1.0, clouds);
}
float fog(vec3 f_pos, vec3 focus_pos, uint medium) { float fog(vec3 f_pos, vec3 focus_pos, uint medium) {
return max(1.0 - 5000.0 / (1.0 + distance(f_pos.xy, focus_pos.xy)), 0.0); return max(1.0 - 5000.0 / (1.0 + distance(f_pos.xy, focus_pos.xy)), 0.0);

View File

@ -25,6 +25,11 @@ float pow5(float x) {
return x2 * x2 * x; return x2 * x2 * x;
} }
vec4 pow5(vec4 x) {
vec4 x2 = x * x;
return x2 * x2 * x;
}
// Fresnel angle for perfectly specular dialectric materials. // Fresnel angle for perfectly specular dialectric materials.
// Schlick approximation // Schlick approximation
@ -43,6 +48,54 @@ float BeckmannDistribution_D(float NdotH, float alpha) {
return mix(k_spec, 0.0, NdotH == 0.0); return mix(k_spec, 0.0, NdotH == 0.0);
} }
// Voxel Distribution
float BeckmannDistribution_D_Voxel(vec3 wh, vec3 norm, float alpha) {
vec3 sides = sign(norm);
// vec3 cos_sides_i = /*sides * */sides * norm;
// vec3 cos_sides_o = max(sides * view_dir, 0.0);
vec3 NdotH = max(wh * sides, 0.0);/*cos_sides_i*///max(sides * wh, 0.0);
const float PI = 3.1415926535897932384626433832795;
vec3 NdotH2 = NdotH * NdotH;
vec3 NdotH2m2 = NdotH2 * alpha * alpha;
vec3 k_spec = exp((NdotH2 - 1) / NdotH2m2) / (PI * NdotH2m2 * NdotH2);
return dot(mix(k_spec, /*cos_sides_o*/vec3(0.0), equal(NdotH, vec3(0.0))), /*cos_sides_i*/abs(norm));
// // const float PI = 3.1415926535897932384626433832795;
// const vec3 normals[6] = vec3[](vec3(1,0,0), vec3(0,1,0), vec3(0,0,1), vec3(-1,0,0), vec3(0,-1,0), vec3(0,0,-1));
// float voxel_norm = 0.0;
// for (int i = 0; i < 6; i ++) {
// // Light reflecting off the half-angle can shine on up to three sides.
// // So, the idea here is to figure out the ratio of visibility of each of these
// // three sides such that their sum adds to 1, then computing a Beckmann Distribution for each side times
// // the this ratio.
// //
// // The ratio of these normals in each direction should be the sum of their cosines with the light over π,
// // I think.
// //
// // cos (wh, theta)
// //
// // - one normal
// //
// // The ratio of each of the three exposed sides should just be the slope.
// vec3 side = normals[i];
// float side_share = max(dot(norm, side), 0.0);
// float NdotH = max(dot(wh, side), 0.0);
// voxel_norm += side_share * BeckmannDistribution_D(NdotH, alpha);
// // voxel_norm += normals[i] * side_visible * max(dot(-cam_dir, normals[i]), 0.0);
// // voxel_norm += normals[i] * side_visible * max(dot(-cam_dir, normals[i]), 0.0);
// }
// /* float NdotH = dot(wh, norm);
// float NdotH2 = NdotH * NdotH;
// float NdotH2m2 = NdotH2 * alpha * alpha;
// float k_spec = exp((NdotH2 - 1) / NdotH2m2) / (PI * NdotH2m2 * NdotH2);
// return mix(k_spec, 0.0, NdotH == 0.0); */
// return voxel_norm;
}
float BeckmannDistribution_Lambda(vec3 norm, vec3 dir, float alpha) { float BeckmannDistribution_Lambda(vec3 norm, vec3 dir, float alpha) {
float CosTheta = /*max(dot(norm, dir), 0.0);*/dot(norm, dir); float CosTheta = /*max(dot(norm, dir), 0.0);*/dot(norm, dir);
/* if (CosTheta == 0.0) { /* if (CosTheta == 0.0) {
@ -98,6 +151,7 @@ vec3 FresnelBlend_f(vec3 norm, vec3 dir, vec3 light_dir, vec3 R_d, vec3 R_s, flo
alpha = alpha * sqrt(2.0); alpha = alpha * sqrt(2.0);
float cos_wi = /*max(*/dot(-light_dir, norm)/*, 0.0)*/; float cos_wi = /*max(*/dot(-light_dir, norm)/*, 0.0)*/;
float cos_wo = /*max(*/dot(dir, norm)/*, 0.0)*/; float cos_wo = /*max(*/dot(dir, norm)/*, 0.0)*/;
vec3 diffuse = (28.0 / (23.0 * PI)) * R_d * vec3 diffuse = (28.0 / (23.0 * PI)) * R_d *
(1.0 - R_s) * (1.0 - R_s) *
(1.0 - pow5(1.0 - 0.5 * abs(cos_wi))) * (1.0 - pow5(1.0 - 0.5 * abs(cos_wi))) *
@ -134,6 +188,41 @@ vec3 FresnelBlend_f(vec3 norm, vec3 dir, vec3 light_dir, vec3 R_d, vec3 R_s, flo
return mix(/*diffuse*//* + specular*/diffuse + specular, vec3(0.0), bvec3(all(equal(light_dir, dir)))); return mix(/*diffuse*//* + specular*/diffuse + specular, vec3(0.0), bvec3(all(equal(light_dir, dir))));
} }
// Fresnel blending
//
// http://www.pbr-book.org/3ed-2018/Reflection_Models/Microfacet_Models.html#fragment-MicrofacetDistributionPublicMethods-2
// and
// http://www.pbr-book.org/3ed-2018/Reflection_Models/Fresnel_Incidence_Effects.html
vec3 FresnelBlend_Voxel_f(vec3 norm, vec3 dir, vec3 light_dir, vec3 R_d, vec3 R_s, float alpha, float dist) {
const float PI = 3.1415926535897932384626433832795;
alpha = alpha * sqrt(2.0);
float cos_wi = /*max(*/dot(-light_dir, norm)/*, 0.0)*/;
float cos_wo = /*max(*/dot(dir, norm)/*, 0.0)*/;
vec3 sides = sign(norm);
vec4 diffuse_factor =
(1.0 - pow5(1.0 - 0.5 * max(vec4(-light_dir * sides, abs(cos_wi)), 0.0))) *
(1.0 - pow5(1.0 - 0.5 * max(vec4(dir * sides, abs(cos_wo)), 0.0)));
vec3 diffuse = (28.0 / (23.0 * PI)) * R_d *
(1.0 - R_s) *
dot(diffuse_factor, vec4(abs(norm) * (1.0 - dist), dist));
vec3 wh = -light_dir + dir;
if (cos_wi <= 0.0 || cos_wo <= 0.0) {
return vec3(/*diffuse*/0.0);
}
wh = normalize(wh);//mix(normalize(wh), vec3(0.0), equal(light_dir, dir));
float dot_wi_wh = dot(-light_dir, wh);
float distr = BeckmannDistribution_D_Voxel(wh, norm, alpha);
// float distr = BeckmannDistribution_D(dot(wh, norm), alpha);
vec3 specular = distr /
(4 * abs(dot_wi_wh)) *
max(abs(cos_wi), abs(cos_wo)) *
schlick_fresnel(R_s, dot_wi_wh);
return mix(/*diffuse*//* + specular*/diffuse + specular, vec3(0.0), bvec3(all(equal(light_dir, dir))));
}
// Phong reflection. // Phong reflection.
// //
// Note: norm, dir, light_dir must all be normalizd. // Note: norm, dir, light_dir must all be normalizd.
@ -201,6 +290,14 @@ vec3 light_reflection_factor(vec3 norm, vec3 dir, vec3 light_dir, vec3 k_d, vec3
// // return vec3(0.0); // // return vec3(0.0);
} }
vec3 light_reflection_factor(vec3 norm, vec3 dir, vec3 light_dir, vec3 k_d, vec3 k_s, float alpha, float voxel_lighting) {
if (voxel_lighting < 1.0) {
return FresnelBlend_Voxel_f(norm, dir, light_dir, k_d/* * max(dot(norm, -light_dir), 0.0)*/, k_s, alpha, voxel_lighting);
} else {
return FresnelBlend_f(norm, dir, light_dir, k_d/* * max(dot(norm, -light_dir), 0.0)*/, k_s, alpha);
}
}
float rel_luminance(vec3 rgb) float rel_luminance(vec3 rgb)
{ {
// https://en.wikipedia.org/wiki/Relative_luminance // https://en.wikipedia.org/wiki/Relative_luminance
@ -242,13 +339,14 @@ bool IntersectRayPlane(vec3 rayOrigin, vec3 rayDirection, vec3 posOnPlane, vec3
// Ideally, defaultpos is set so we can avoid branching on error. // Ideally, defaultpos is set so we can avoid branching on error.
vec3 compute_attenuation(vec3 wpos, vec3 ray_dir, vec3 mu, float surface_alt, vec3 defaultpos) { vec3 compute_attenuation(vec3 wpos, vec3 ray_dir, vec3 mu, float surface_alt, vec3 defaultpos) {
// return vec3(1.0); // return vec3(1.0);
/*if (dot(mu, mu) == 0.0) { /*if (mu == vec3(0.0)) {
return vec3(1.0); return vec3(1.0);
}*//* else { }*//* else {
return vec3(0.0); return vec3(0.0);
}*/ }*/
// return vec3(0.0); // return vec3(0.0);
vec3 surface_dir = surface_alt < wpos.z ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 0.0, -1.0); vec3 surface_dir = /*surface_alt < wpos.z ? vec3(0.0, 0.0, -1.0) : vec3(0.0, 0.0, 1.0)*/vec3(0.0, 0.0, sign(surface_alt - wpos.z));
// vec3 surface_dir = surface_alt < wpos.z ? vec3(0.0, 0.0, -1.0) : vec3(0.0, 0.0, 1.0);
// vec3 surface_dir = faceforward(vec3(0.0, 0.0, 1.0), ray_dir, vec3(0.0, 0.0, 1.0)); // vec3 surface_dir = faceforward(vec3(0.0, 0.0, 1.0), ray_dir, vec3(0.0, 0.0, 1.0));
bool _intersects_surface = IntersectRayPlane(wpos, ray_dir, vec3(0.0, 0.0, surface_alt), surface_dir, defaultpos); bool _intersects_surface = IntersectRayPlane(wpos, ray_dir, vec3(0.0, 0.0, surface_alt), surface_dir, defaultpos);
float depth = length(defaultpos - wpos); float depth = length(defaultpos - wpos);
@ -259,13 +357,14 @@ vec3 compute_attenuation(vec3 wpos, vec3 ray_dir, vec3 mu, float surface_alt, ve
// from the default point. // from the default point.
vec3 compute_attenuation_point(vec3 wpos, vec3 ray_dir, vec3 mu, float surface_alt, vec3 defaultpos) { vec3 compute_attenuation_point(vec3 wpos, vec3 ray_dir, vec3 mu, float surface_alt, vec3 defaultpos) {
// return vec3(1.0); // return vec3(1.0);
/*if (dot(mu, mu) == 0.0) { /*if (mu == vec3(0.0)) {
return vec3(1.0); return vec3(1.0);
}*//* else { }*//* else {
return vec3(0.0); return vec3(0.0);
}*/ }*/
// return vec3(0.0); // return vec3(0.0);
vec3 surface_dir = surface_alt < wpos.z ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 0.0, -1.0); vec3 surface_dir = /*surface_alt < wpos.z ? vec3(0.0, 0.0, -1.0) : vec3(0.0, 0.0, 1.0)*/vec3(0.0, 0.0, sign(wpos.z - surface_alt));
// vec3 surface_dir = surface_alt < wpos.z ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 0.0, -1.0);
// vec3 surface_dir = faceforward(vec3(0.0, 0.0, 1.0), ray_dir, vec3(0.0, 0.0, 1.0)); // vec3 surface_dir = faceforward(vec3(0.0, 0.0, 1.0), ray_dir, vec3(0.0, 0.0, 1.0));
float max_length = dot(defaultpos - wpos, defaultpos - wpos); float max_length = dot(defaultpos - wpos, defaultpos - wpos);
bool _intersects_surface = IntersectRayPlane(wpos, ray_dir, vec3(0.0, 0.0, surface_alt), surface_dir, defaultpos); bool _intersects_surface = IntersectRayPlane(wpos, ray_dir, vec3(0.0, 0.0, surface_alt), surface_dir, defaultpos);

View File

@ -87,6 +87,82 @@ void main() {
vec3 view_dir = -cam_to_frag; vec3 view_dir = -cam_to_frag;
// vec3 view_dir = normalize(f_pos - cam_pos.xyz); // vec3 view_dir = normalize(f_pos - cam_pos.xyz);
// const vec3 normals[3] = vec3[](vec3(1,0,0), vec3(0,1,0), vec3(0,0,1));//, vec3(-1,0,0), vec3(0,-1,0), vec3(0,0,-1));
// const mat3 side_norms = vec3(1, 0, 0), vec3(0, 1, 0), vec3(0, 0, 1);
// mat3 sides = mat3(
// /*vec3(1, 0, 0),
// vec3(0, 1, 0),
// vec3(0, 0, 1)*/
// vec3(1, 0, 0),
// // faceforward(vec3(1, 0, 0), -f_norm, vec3(1, 0, 0)),
// vec3(0, 1, 0),
// // faceforward(vec3(0, 1, 0), -f_norm, vec3(0, 1, 0)),
// vec3(0, 0, 1)
// // faceforward(vec3(0, 0, 1), -f_norm, vec3(0, 0, 1))
// );
// This vector is shorthand for a diagonal matrix, which works because:
// (1) our voxel normal vectors are exactly the basis vectors in worldspace;
// (2) only 3 of them can be in the direction of the actual normal anyway.
// (NOTE: This normal should always be pointing up, so implicitly sides.z = 1.0).
// vec3 sides = sign(f_norm);
// // NOTE: Should really be sides * f_norm, i.e. abs(f_norm), but voxel_norm would then re-multiply by sides so it cancels out.
// vec3 cos_sides_i = sides * f_norm;
// vec3 cos_sides_o = sides * view_dir;
// // vec3 side_factor_i = cos_sides_i;
// // vec3 side_factor_i = f_norm;
// // vec3 side_factor_i = cos_sides_o;
// vec3 side_factor_i = 1.0 - pow(1.0 - 0.5 * cos_sides_i, vec3(5));
// // vec3 side_factor_i = /*abs*/sign(f_norm) * cos_sides_i;//max(cos_sides_i, 0.0);// 1.0 - pow(1.0 - 0.5 * cos_sides_i, vec3(5.0)); // max(sides * f_norm, vec3(0.0));//
// // vec3 side_factor_i = /*abs*/sign(f_norm) * cos_sides_i;//max(cos_sides_i, 0.0);// 1.0 - pow(1.0 - 0.5 * cos_sides_i, vec3(5.0)); // max(sides * f_norm, vec3(0.0));//
// // vec3 side_factor_o = max(cos_sides_o, 0.0);// 1.0 - pow(1.0 - 0.5 * max(cos_sides_o, 0.0), vec3(5));
// vec3 side_factor_o = 1.0 - pow(1.0 - 0.5 * max(cos_sides_o, 0.0), vec3(5));
// // vec3 side_factor_o = max(cos_sides_o, 0.0);// 1.0 - pow(1.0 - 0.5 * max(cos_sides_o, vec3(0.0)), vec3(5.0));//max(sides * view_dir/* * sign(cos_sides_i) */, vec3(0.0));
// // vec3 side_factor_o = max(sides * view_dir/* * cos_sides_o*/, 0.0);// 1.0 - pow(1.0 - 0.5 * max(cos_sides_o, vec3(0.0)), vec3(5.0));//max(sides * view_dir/* * sign(cos_sides_i) */, vec3(0.0));
// // NOTE: side = transpose(sides), so we avoid the extra operatin.
// // We multply the vector by the matrix from the *left*, so each normal gets multiplied by the corresponding factor.
// // vec3 voxel_norm = normalize(/*sides * *//*sqrt(1.0 - cos_sides_i * cos_sides_i)*/(side_factor_i * side_factor_o));
// vec3 voxel_norm = normalize(/*sides * *//*sqrt(1.0 - cos_sides_i * cos_sides_i)*/((28.0 / (23.0 * PI)) * side_factor_i * side_factor_o * sides));
// vec3 voxel_norm = normalize(sign(f_norm) * sqrt(abs(f_norm)) * max(sign(f_norm) * view_dir, 0.0));
float f_ao = 1.0;//1.0;//sqrt(dot(cos_sides_i, cos_sides_i) / 3.0);
// float f_ao = 0.2;
// sqrt(dot(sqrt(1.0 - cos_sides_i * cos_sides_i)), 1.0 - cos_sides_o/* * cos_sides_o*/);// length(sqrt(1.0 - cos_sides_o * cos_sides_o) / cos_sides_i * cos_sides_o);
// f_ao = f_ao * f_ao;
// /* vec3 voxel_norm = vec3(0.0);
// for (int i = 0; i < 3; i ++) {
// // Light reflecting off the half-angle can shine on up to three sides.
// // So, the idea here is to figure out the ratio of visibility of each of these
// // three sides such that their sum adds to 1, then computing a Beckmann Distribution for each side times
// // the this ratio.
// //
// // The ratio of these normals in each direction should be the sum of their cosines with the light over π,
// // I think.
// //
// // cos (wh, theta)
// //
// // - one normal
// //
// // The ratio of each of the three exposed sides should just be the slope.
// vec3 side = normals[i];
// side = faceforward(side, -f_norm, side);
// float cos_wi = max(dot(f_norm, side), 0.0);
// float cos_wo = max(dot(view_dir, side), 0.0);
// float share = cos_wi * cos_wo;
// // float share = (1.0 - pow5(1.0 - 0.5 * cos_wi)) * (1.0 - pow5(1.0 - 0.5 * cos_wo));
// voxel_norm += share * side;
// // voxel_norm += normals[i] * side_visible * max(dot(-cam_dir, normals[i]), 0.0);
// // voxel_norm += normals[i] * side_visible * max(dot(-cam_dir, normals[i]), 0.0);
// }
// voxel_norm = normalize(voxel_norm); */
float dist_lerp = clamp(pow(max(distance(focus_pos.xy, f_pos.xy) - view_distance.x, 0.0) / 1024.0, 2.0), 0, 1);
// dist_lerp = 0.0;
// voxel_norm = normalize(mix(voxel_norm, f_norm, /*pow(dist_lerp, 1.0)*/dist_lerp));
vec3 voxel_norm = f_norm;
// voxel_norm = f_norm;
// Note: because voxels, we reduce the normal for reflections to just its z component, dpendng on distance to camera. // Note: because voxels, we reduce the normal for reflections to just its z component, dpendng on distance to camera.
// Idea: the closer we are to facing top-down, the more the norm should tend towards up-z. // Idea: the closer we are to facing top-down, the more the norm should tend towards up-z.
// vec3 l_norm; // = vec3(0.0, 0.0, 1.0); // vec3 l_norm; // = vec3(0.0, 0.0, 1.0);
@ -150,13 +226,17 @@ void main() {
// vec3 light, diffuse_light, ambient_light; // vec3 light, diffuse_light, ambient_light;
// get_sun_diffuse(f_norm, time_of_day.x, cam_to_frag, (0.25 * shade_frac + 0.25 * light_frac) * f_col, 0.5 * shade_frac * f_col, 0.5 * shade_frac * /*vec3(1.0)*/f_col, 2.0, emitted_light, reflected_light); // get_sun_diffuse(f_norm, time_of_day.x, cam_to_frag, (0.25 * shade_frac + 0.25 * light_frac) * f_col, 0.5 * shade_frac * f_col, 0.5 * shade_frac * /*vec3(1.0)*/f_col, 2.0, emitted_light, reflected_light);
float max_light = 0.0; float max_light = 0.0;
max_light += get_sun_diffuse2(f_norm/*l_norm*/, sun_dir, moon_dir, view_dir, vec3(1.0)/* * (0.5 * light_frac + vec3(0.5 * shade_frac))*/, vec3(1.0), /*0.5 * shade_frac * *//*vec3(1.0)*//*f_col*/vec3(R_s), alpha, emitted_light, reflected_light); max_light += get_sun_diffuse2(/*f_norm*/voxel_norm/*l_norm*/, sun_dir, moon_dir, view_dir, vec3(1.0)/* * (0.5 * light_frac + vec3(0.5 * shade_frac))*/, vec3(1.0), /*0.5 * shade_frac * *//*vec3(1.0)*//*f_col*/vec3(R_s), alpha, dist_lerp/*max(distance(focus_pos.xy, f_pos.xyz) - view_distance.x, 0.0) / 1000 < 1.0*/, emitted_light, reflected_light);
// emitted_light = vec3(1.0); // emitted_light = vec3(1.0);
emitted_light *= max(shade_frac, MIN_SHADOW); emitted_light *= max(shade_frac, MIN_SHADOW);
reflected_light *= shade_frac; reflected_light *= shade_frac;
max_light *= shade_frac; max_light *= shade_frac;
// reflected_light = vec3(0.0); // reflected_light = vec3(0.0);
float ao = /*pow(f_ao, 0.5)*/f_ao * 0.9 + 0.1;
emitted_light *= ao;
reflected_light *= ao;
// emitted_light += 0.5 * vec3(SUN_AMBIANCE * sun_shade_frac * sun_light + moon_shade_frac * moon_light) * f_col * (ambient_sides + 1.0); // emitted_light += 0.5 * vec3(SUN_AMBIANCE * sun_shade_frac * sun_light + moon_shade_frac * moon_light) * f_col * (ambient_sides + 1.0);
// Ambient lighting attempt: vertical light. // Ambient lighting attempt: vertical light.

View File

@ -36,13 +36,49 @@ void main() {
// f_pos.z -= 100.0 * pow(1.0 + 0.01 / view_distance.x, -pow(distance(focus_pos.xy, f_pos.xy), 2.0)); // f_pos.z -= 100.0 * pow(1.0 + 0.01 / view_distance.x, -pow(distance(focus_pos.xy, f_pos.xy), 2.0));
// f_pos.z = mix(-f_pos.z, f_pos.z, view_distance.x <= distance(focus_pos.xy, f_pos.xy) + 32.0); // f_pos.z = mix(-f_pos.z, f_pos.z, view_distance.x <= distance(focus_pos.xy, f_pos.xy) + 32.0);
// bool faces_fluid = false;// bool((f_pos_norm >> 28) & 0x1u);
// // TODO: Measure real water surface altitude here.
// float surfaceAlt = mix(view_distance.z, /*floor*/(min(f_pos.z, floor(alt_at_real(cam_pos.xy)))), medium.x);
// // float surfaceAlt = mix(view_distance.z, floor(max(cam_pos.z, alt_at_real(cam_pos.xy))), medium.x);
// // float surfaceAlt = min(floor(f_pos.z), floor(alt_at_real(cam_pos.xy))); // faces_fluid ? max(ceil(f_pos.z), floor(f_alt)) : floor(f_alt);
// f_pos.z -= max(sign(view_distance.x - distance(focus_pos.xy, f_pos.xy)), 0.0) * (32.0 * view_distance.z / 255 + 32.0 * max(0.0, f_pos.z - cam_pos.z));
f_pos.z -= max(view_distance.x - distance(focus_pos.xy, f_pos.xy), 0.0) * (1.0 + max(0.0, f_pos.z - focus_pos.z)); f_pos.z -= max(view_distance.x - distance(focus_pos.xy, f_pos.xy), 0.0) * (1.0 + max(0.0, f_pos.z - focus_pos.z));
// vec3 wRayinitial = f_pos; // cam_pos.z < f_pos.z ? f_pos : cam_pos.xyz;
// vec3 wRayfinal = cam_pos.xyz; // cam_pos.z < f_pos.z ? cam_pos.xyz : f_pos;
// wRayfinal = dot(wRayfinal - wRayinitial, focus_pos.xyz - cam_pos.xyz) < 0.0 ? wRayfinal : wRayinitial;
// vec3 wRayNormal = /*surfaceAlt < wRayinitial.z ? vec3(0.0, 0.0, -1.0) : */vec3(0.0, 0.0, 1.0);
// float n_camera = mix(1.0, 1.3325, medium.x);
// float n_vertex = faces_fluid ? 1.3325 : 1.0;
// float n1 = n_vertex; // cam_pos.z < f_pos.z ? n_vertex : n_camera;
// float n2 = n_camera; // cam_pos.z < f_pos.z ? n_camera : n_vertex;
// float wRayLength0 = length(wRayfinal - wRayinitial);
// vec3 wRayDir = (wRayfinal - wRayinitial) / wRayLength0;
// vec3 wPoint = wRayfinal;
// bool wIntersectsSurface = IntersectRayPlane(wRayinitial, wRayDir, vec3(0.0, 0.0, surfaceAlt), -wRayNormal, wPoint);
// float wRayLength = length(wPoint - wRayinitial);
// wPoint = wRayLength < wRayLength0 ? wPoint : wRayfinal;
// wRayLength = min(wRayLength, wRayLength0); // min(max_length, dot(wRayfinal - wpos, defaultpos - wpos));
// // vec3 wRayDir2 = (wRayfinal - wRayinitial) / wRayLength;
// vec3 wRayDir3 = (dot(wRayDir, wRayNormal) < 0.0 && surfaceAlt < wRayinitial.z && wIntersectsSurface/* && medium.x == 1u*/) ? refract(wRayDir, wRayNormal, n2 / n1) : wRayDir;
// // wPoint -= wRayDir3 * wRayLength * n2 / n1;
// vec3 newRay = (dot(wRayDir3, focus_pos.xyz - cam_pos.xyz) < 0.0 && /*dot(wRayDir, wRayNormal) > 0.0 && *//*surfaceAlt < wRayinitial.z && */wIntersectsSurface && medium.x == 1u) ? wPoint - wRayDir3 * wRayLength * n2 / n1/*wPoint - wRayDir3 * wRayLength * n2 / n1*/ : f_pos;// - (wRayfinal - wPoint) * n2 / n1; // wPoint + n2 * (wRayfinal - wPoint) - n2 / n1 * wRayLength * wRayDir3;
// newRay.z -= max(view_distance.x - distance(focus_pos.xy, f_pos.xy), 0.0) * (1.0 + max(0.0, f_pos.z - focus_pos.z));
// f_light = 1.0; // f_light = 1.0;
gl_Position = gl_Position =
proj_mat * proj_mat *
view_mat * view_mat *
vec4(f_pos, 1); vec4(f_pos/*newRay*/, 1);
// gl_Position.z = -gl_Position.z / 100.0;
gl_Position.z = -1000.0 / (gl_Position.z + 10000.0); gl_Position.z = -1000.0 / (gl_Position.z + 10000.0);
} }

View File

@ -21,10 +21,12 @@ void main() {
float fog_level = fog(f_pos.xyz, focus_pos.xyz, medium.x); float fog_level = fog(f_pos.xyz, focus_pos.xyz, medium.x);
float dist = 100000.0; float dist = 100000.0;
float refractionIndex = medium.x == 1u ? 1.0 / 1.3325 : 1.0;
/* if (medium.x == 1u) { /* if (medium.x == 1u) {
dist = UNDERWATER_MIST_DIST; dist = UNDERWATER_MIST_DIST;
} */ } */
vec3 wpos = cam_pos.xyz + /*normalize(f_pos)*/cam_dir * dist; vec3 wpos = cam_pos.xyz + /*normalize(f_pos)*/cam_dir * dist;
tgt_color = vec4(get_sky_color(normalize(f_pos), time_of_day.x, cam_pos.xyz, wpos, 1.0, true, _clouds), 1.0); tgt_color = vec4(get_sky_color(normalize(f_pos), time_of_day.x, cam_pos.xyz, wpos, 1.0, true, refractionIndex, _clouds), 1.0);
} }

View File

@ -58,5 +58,6 @@ void main() {
gl_Position = gl_Position =
all_mat * all_mat *
vec4(f_pos, 1); vec4(f_pos, 1);
// gl_Position.z = -gl_Position.z / 100.0;
gl_Position.z = -1000.0 / (gl_Position.z + 10000.0); gl_Position.z = -1000.0 / (gl_Position.z + 10000.0);
} }

View File

@ -6,8 +6,8 @@
in vec3 f_pos; in vec3 f_pos;
in vec3 f_chunk_pos; in vec3 f_chunk_pos;
flat in uint f_pos_norm; flat in uint f_pos_norm;
in float f_alt; // in float f_alt;
in vec4 f_shadow; // in vec4 f_shadow;
in vec3 f_col; in vec3 f_col;
in float f_light; in float f_light;
in float f_ao; in float f_ao;
@ -39,6 +39,26 @@ void main() {
vec3 sun_dir = get_sun_dir(time_of_day.x); vec3 sun_dir = get_sun_dir(time_of_day.x);
vec3 moon_dir = get_moon_dir(time_of_day.x); vec3 moon_dir = get_moon_dir(time_of_day.x);
float f_alt = alt_at(f_pos.xy);
vec4 f_shadow = textureBicubic(t_horizon, pos_to_tex(f_pos.xy));
float alpha = 1.0;
// TODO: Possibly angle with water surface into account? Since we can basically assume it's horizontal.
const float n2 = 1.01;
const float R_s2s0 = pow((1.0 - n2) / (1.0 + n2), 2);
const float R_s1s0 = pow((1.3325 - n2) / (1.3325 + n2), 2);
const float R_s2s1 = pow((1.0 - 1.3325) / (1.0 + 1.3325), 2);
const float R_s1s2 = pow((1.3325 - 1.0) / (1.3325 + 1.0), 2);
// float faces_fluid = faces_fluid && f_pos.z <= floor(f_alt);
float fluid_alt = max(ceil(f_pos.z), floor(f_alt));
float R_s = /*(f_pos.z < f_alt)*/faces_fluid /*&& f_pos.z <= fluid_alt*/ ? mix(R_s2s1 * R_s1s0, R_s1s0, medium.x) : mix(R_s2s0, R_s1s2 * R_s2s0, medium.x);
// vec3 surf_color = /*srgb_to_linear*/(f_col);
vec3 k_a = vec3(1.0);
vec3 k_d = vec3(1.0);
vec3 k_s = vec3(R_s);
// float sun_light = get_sun_brightness(sun_dir); // float sun_light = get_sun_brightness(sun_dir);
// float moon_light = get_moon_brightness(moon_dir); // float moon_light = get_moon_brightness(moon_dir);
/* float sun_shade_frac = horizon_at(f_pos, sun_dir); /* float sun_shade_frac = horizon_at(f_pos, sun_dir);
@ -55,33 +75,23 @@ void main() {
// for the sun and moon (since they have different brightnesses / colors so the shadows shouldn't attenuate equally). // for the sun and moon (since they have different brightnesses / colors so the shadows shouldn't attenuate equally).
float shade_frac = /*1.0;*/sun_shade_frac + moon_shade_frac; float shade_frac = /*1.0;*/sun_shade_frac + moon_shade_frac;
vec3 surf_color = /*srgb_to_linear*/(f_col);
float alpha = 1.0;
// TODO: Possibly angle with water surface into account? Since we can basically assume it's horizontal.
const float n2 = 1.01;
const float R_s2s0 = pow((1.0 - n2) / (1.0 + n2), 2);
const float R_s1s0 = pow((1.3325 - n2) / (1.3325 + n2), 2);
const float R_s2s1 = pow((1.0 - 1.3325) / (1.0 + 1.3325), 2);
const float R_s1s2 = pow((1.3325 - 1.0) / (1.3325 + 1.0), 2);
// float faces_fluid = faces_fluid && f_pos.z <= floor(f_alt);
float fluid_alt = max(ceil(f_pos.z), floor(f_alt));
float R_s = /*(f_pos.z < f_alt)*/faces_fluid /*&& f_pos.z <= fluid_alt*/ ? mix(R_s2s1 * R_s1s0, R_s1s0, medium.x) : mix(R_s2s0, R_s1s2 * R_s2s0, medium.x);
vec3 k_a = vec3(1.0);
vec3 k_d = vec3(1.0);
vec3 k_s = vec3(R_s);
float max_light = 0.0; float max_light = 0.0;
// After shadows are computed, we use a refracted sun and moon direction.
// sun_dir = faces_fluid && sun_shade_frac > 0.0 ? refract(sun_dir/*-view_dir*/, vec3(0.0, 0.0, 1.0), 1.0 / 1.3325) : sun_dir;
// moon_dir = faces_fluid && moon_shade_frac > 0.0 ? refract(moon_dir/*-view_dir*/, vec3(0.0, 0.0, 1.0), 1.0 / 1.3325) : moon_dir;
// Compute attenuation due to water from the camera. // Compute attenuation due to water from the camera.
vec3 mu = faces_fluid/* && f_pos.z <= fluid_alt*/ ? MU_WATER : vec3(0.0); vec3 mu = faces_fluid/* && f_pos.z <= fluid_alt*/ ? MU_WATER : vec3(0.0);
// NOTE: Default intersection point is camera position, meaning if we fail to intersect we assume the whole camera is in water. // NOTE: Default intersection point is camera position, meaning if we fail to intersect we assume the whole camera is in water.
vec3 cam_attenuation = compute_attenuation_point(f_pos, view_dir, mu, fluid_alt, /*cam_pos.z <= fluid_alt ? cam_pos.xyz : f_pos*/cam_pos.xyz); vec3 cam_attenuation = compute_attenuation_point(f_pos, -view_dir, mu, fluid_alt, /*cam_pos.z <= fluid_alt ? cam_pos.xyz : f_pos*/cam_pos.xyz);
// Computing light attenuation from water. // Computing light attenuation from water.
vec3 emitted_light, reflected_light; vec3 emitted_light, reflected_light;
// To account for prior saturation // To account for prior saturation
float f_light = pow(f_light, 1.5); float f_light = faces_fluid ? 1.0 : pow(f_light, 1.5);
float point_shadow = shadow_at(f_pos, f_norm); float point_shadow = shadow_at(f_pos, f_norm);
max_light += get_sun_diffuse2(f_norm, /*time_of_day.x, */sun_dir, moon_dir, view_dir, f_pos, mu, cam_attenuation, fluid_alt, k_a/* * (shade_frac * 0.5 + light_frac * 0.5)*/, k_d, k_s, alpha, emitted_light, reflected_light); max_light += get_sun_diffuse2(f_norm, /*time_of_day.x, */sun_dir, moon_dir, view_dir, f_pos, mu, cam_attenuation, fluid_alt, k_a/* * (shade_frac * 0.5 + light_frac * 0.5)*/, k_d, k_s, alpha, 1.0, emitted_light, reflected_light);
emitted_light *= f_light * point_shadow * max(shade_frac, MIN_SHADOW); emitted_light *= f_light * point_shadow * max(shade_frac, MIN_SHADOW);
reflected_light *= f_light * point_shadow * shade_frac; reflected_light *= f_light * point_shadow * shade_frac;
@ -89,6 +99,8 @@ void main() {
max_light += lights_at(f_pos, f_norm, view_dir, mu, cam_attenuation, fluid_alt, k_a, k_d, k_s, alpha, emitted_light, reflected_light); max_light += lights_at(f_pos, f_norm, view_dir, mu, cam_attenuation, fluid_alt, k_a, k_d, k_s, alpha, emitted_light, reflected_light);
// float f_ao = 1.0;
float ao = /*pow(f_ao, 0.5)*/f_ao * 0.9 + 0.1; float ao = /*pow(f_ao, 0.5)*/f_ao * 0.9 + 0.1;
emitted_light *= ao; emitted_light *= ao;
reflected_light *= ao; reflected_light *= ao;
@ -115,7 +127,7 @@ void main() {
// vec3 surf_color = illuminate(srgb_to_linear(f_col), light, diffuse_light, ambient_light); // vec3 surf_color = illuminate(srgb_to_linear(f_col), light, diffuse_light, ambient_light);
vec3 col = srgb_to_linear(f_col + hash(vec4(floor(f_chunk_pos * 3.0 - f_norm * 0.5), 0)) * 0.02); // Small-scale noise vec3 col = srgb_to_linear(f_col + hash(vec4(floor(f_chunk_pos * 3.0 - f_norm * 0.5), 0)) * 0.02); // Small-scale noise
surf_color = illuminate(max_light, col * emitted_light, col * reflected_light); vec3 surf_color = illuminate(max_light, col * emitted_light, col * reflected_light);
float fog_level = fog(f_pos.xyz, focus_pos.xyz, medium.x); float fog_level = fog(f_pos.xyz, focus_pos.xyz, medium.x);
vec4 clouds; vec4 clouds;

View File

@ -16,8 +16,8 @@ uniform u_locals {
out vec3 f_pos; out vec3 f_pos;
out vec3 f_chunk_pos; out vec3 f_chunk_pos;
flat out uint f_pos_norm; flat out uint f_pos_norm;
out float f_alt; // out float f_alt;
out vec4 f_shadow; // out vec4 f_shadow;
out vec3 f_col; out vec3 f_col;
out float f_light; out float f_light;
out float f_ao; out float f_ao;
@ -25,6 +25,7 @@ out float f_ao;
const int EXTRA_NEG_Z = 32768; const int EXTRA_NEG_Z = 32768;
void main() { void main() {
// over it (if this vertex to see if it intersects.
f_chunk_pos = vec3(ivec3((uvec3(v_pos_norm) >> uvec3(0, 6, 12)) & uvec3(0x3Fu, 0x3Fu, 0xFFFFu)) - ivec3(0, 0, EXTRA_NEG_Z)); f_chunk_pos = vec3(ivec3((uvec3(v_pos_norm) >> uvec3(0, 6, 12)) & uvec3(0x3Fu, 0x3Fu, 0xFFFFu)) - ivec3(0, 0, EXTRA_NEG_Z));
f_pos = f_chunk_pos + model_offs; f_pos = f_chunk_pos + model_offs;
@ -39,11 +40,49 @@ void main() {
f_pos_norm = v_pos_norm; f_pos_norm = v_pos_norm;
// Also precalculate shadow texture and estimated terrain altitude. // Also precalculate shadow texture and estimated terrain altitude.
f_alt = alt_at_real(f_pos.xy); // f_alt = alt_at(f_pos.xy);
f_shadow = textureBicubic(t_horizon, pos_to_tex(f_pos.xy)); // f_shadow = textureBicubic(t_horizon, pos_to_tex(f_pos.xy));
// IDEA: Cast a ray from the vertex to the camera (if this vertex is above the camera) or from the camera to the vertex (if this
// vertex is below the camera) to see where it intersects the plane of water. All of this only applies if either the terrain
// vertex is in water, or the camera is in water.
//
// If an intersection is found, refract the ray across the barrier using the correct ratio of indices of refraction (1 / N_WATER
// if the vertex is above the camera [ray is going from air to water], N_WATER if the camera is above the vertex
// [ray is going from water to air]).
//
// In order to make sure that terrain and other objects below such an interface are properly renered, we then "un-refract" by
// reversing the refracted vector, and multiplying that by the distance from the object from which we cast the ray to the
// intersectng point, in order to make the object appear to the viewer where it should after refraction.
// bool faces_fluid = bool((f_pos_norm >> 28) & 0x1u);
// // TODO: Measure real water surface altitude here.
// float surfaceAlt = faces_fluid ? max(ceil(f_pos.z), floor(f_alt)) : /*floor(f_alt);*/mix(view_distance.z, min(f_alt, floor(alt_at_real(cam_pos.xy))), medium.x);
// vec3 wRayinitial = f_pos; // cam_pos.z < f_pos.z ? f_pos : cam_pos.xyz;
// vec3 wRayfinal = cam_pos.xyz; // cam_pos.z < f_pos.z ? cam_pos.xyz : f_pos;
// vec3 wRayNormal = surfaceAlt < wRayinitial.z ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 0.0, -1.0);
// float n_camera = mix(1.0, 1.3325, medium.x);
// float n_vertex = faces_fluid ? 1.3325 : 1.0;
// float n1 = n_vertex; // cam_pos.z < f_pos.z ? n_vertex : n_camera;
// float n2 = n_camera; // cam_pos.z < f_pos.z ? n_camera : n_vertex;
// float wRayLength0 = length(wRayfinal - wRayinitial);
// vec3 wRayDir = (wRayfinal - wRayinitial) / wRayLength0;
// vec3 wPoint = wRayfinal;
// bool wIntersectsSurface = IntersectRayPlane(wRayinitial, wRayDir, vec3(0.0, 0.0, surfaceAlt), -wRayNormal, wPoint);
// float wRayLength = length(wPoint - wRayinitial);
// wPoint = wRayLength < wRayLength0 ? wPoint : wRayfinal;
// wRayLength = min(wRayLength, wRayLength0); // min(max_length, dot(wRayfinal - wpos, defaultpos - wpos));
// // vec3 wRayDir2 = (wRayfinal - wRayinitial) / wRayLength;
// vec3 wRayDir3 = (dot(wRayDir, wRayNormal) < 0.0 && wIntersectsSurface) ? refract(wRayDir, wRayNormal, n2 / n1) : wRayDir;
// // wPoint -= wRayDir3 * wRayLength * n2 / n1;
// vec3 newRay = dot(wRayDir, wRayNormal) < 0.0 && wIntersectsSurface ? wPoint - wRayDir3 * wRayLength * n2 / n1 : f_pos;// - (wRayfinal - wPoint) * n2 / n1; // wPoint + n2 * (wRayfinal - wPoint) - n2 / n1 * wRayLength * wRayDir3;
gl_Position = gl_Position =
all_mat * all_mat *
vec4(f_pos, 1); vec4(f_pos/*newRay*/, 1);
// gl_Position.z = -gl_Position.z / 100.0;
gl_Position.z = -1000.0 / (gl_Position.z + 10000.0); gl_Position.z = -1000.0 / (gl_Position.z + 10000.0);
} }