mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Experimental underwater lighting.
This commit is contained in:
parent
2c5ad9d076
commit
ef67bd58ba
@ -40,6 +40,7 @@ void main() {
|
|||||||
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 = srgb_to_linear(vec3(0.2, 0.5, 1.0));
|
||||||
|
// /*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);
|
||||||
vec3 moon_dir = get_moon_dir(time_of_day.x);
|
vec3 moon_dir = get_moon_dir(time_of_day.x);
|
||||||
@ -112,7 +113,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 * emitted_light, /*surf_color * */fog_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)*/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);
|
||||||
|
@ -102,19 +102,39 @@ void main() {
|
|||||||
|
|
||||||
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;
|
||||||
|
|
||||||
|
float f_alt = alt_at_real(f_pos.xy);
|
||||||
|
|
||||||
|
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 n2 = 1.3325;
|
||||||
|
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 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);
|
||||||
|
|
||||||
|
// Water is transparent so both normals are valid.
|
||||||
|
vec3 cam_norm = faceforward(norm, norm, cam_to_frag);
|
||||||
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 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;
|
||||||
/* 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); */
|
||||||
// vec3 cam_to_frag = normalize(f_pos - cam_pos.xyz);
|
// vec3 cam_to_frag = normalize(f_pos - cam_pos.xyz);
|
||||||
// Squared to account for prior saturation.
|
// Squared to account for prior saturation.
|
||||||
float f_light = pow(f_light, 1.5);
|
float f_light = pow(f_light, 1.5);
|
||||||
vec3 reflect_color = get_sky_color(reflect_ray_dir, time_of_day.x, f_pos, vec3(-100000), 0.25, false, _clouds) * f_light;
|
vec3 reflect_color = get_sky_color(/*reflect_ray_dir*/beam_view_dir, time_of_day.x, f_pos, vec3(-100000), 0.25, false, _clouds) * f_light;
|
||||||
/*const */vec3 water_color = srgb_to_linear(vec3(0.2, 0.5, 1.0));
|
// /*const */vec3 water_color = srgb_to_linear(vec3(0.2, 0.5, 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.
|
||||||
|
// See https://en.wikipedia.org/wiki/Electromagnetic_absorption_by_water
|
||||||
|
/*const */vec3 water_attenuation = vec3(0.8, 0.05, 0.01);
|
||||||
|
// /*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);
|
||||||
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));
|
vec4 f_shadow = textureBicubic(t_horizon, pos_to_tex(f_pos.xy));
|
||||||
float sun_shade_frac = horizon_at2(f_shadow, f_alt, f_pos, sun_dir);
|
float sun_shade_frac = horizon_at2(f_shadow, f_alt, f_pos, sun_dir);
|
||||||
float moon_shade_frac = horizon_at2(f_shadow, f_alt, f_pos, moon_dir);
|
float moon_shade_frac = horizon_at2(f_shadow, f_alt, f_pos, moon_dir);
|
||||||
@ -122,16 +142,46 @@ 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;
|
||||||
|
|
||||||
const float alpha = 0.255/*/ / 4.0*//* / 4.0 / sqrt(2.0)*/;
|
// Hack to determine water depth: color goes down with distance through water, so
|
||||||
const float n2 = 1.3325;
|
// we assume water color absorption from this point a to some other point b is the distance
|
||||||
const float R_s2s0 = pow((1.0 - n2) / (1.0 + n2), 2);
|
// along the the ray from a to b where it intersects with the surface plane; if it doesn't,
|
||||||
const float R_s1s0 = pow((1.3325 - n2) / (1.3325 + n2), 2);
|
// then the whole segment from a to b is considered underwater.
|
||||||
const float R_s2s1 = pow((1.0 - 1.3325) / (1.0 + 1.3325), 2);
|
// TODO: Consider doing for point lights.
|
||||||
const float R_s1s2 = pow((1.3325 - 1.0) / (1.3325 + 1.0), 2);
|
// vec3 cam_surface_dir = faceforward(vec3(0.0, 0.0, 1.0), cam_to_frag, vec3(0.0, 0.0, 1.0));
|
||||||
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);
|
|
||||||
|
// vec3 water_intersection_surface_camera = vec3(cam_pos);
|
||||||
|
// bool _water_intersects_surface_camera = IntersectRayPlane(f_pos, view_dir, vec3(0.0, 0.0, /*f_alt*/f_pos.z + f_light), cam_surface_dir, water_intersection_surface_camera);
|
||||||
|
// // Should work because we set it up so that if IntersectRayPlane returns false for camera, its default intersection point is cam_pos.
|
||||||
|
// float water_depth_to_camera = length(water_intersection_surface_camera - f_pos);
|
||||||
|
|
||||||
|
// vec3 water_intersection_surface_light = f_pos;
|
||||||
|
// bool _light_intersects_surface_water = IntersectRayPlane(f_pos, sun_dir.z <= 0.0 ? sun_dir : moon_dir, vec3(0.0, 0.0, /*f_alt*/f_pos.z + f_light), vec3(0.0, 0.0, 1.0), water_intersection_surface_light);
|
||||||
|
// // Should work because we set it up so that if IntersectRayPlane returns false for light, its default intersection point is f_pos--
|
||||||
|
// // i.e. if a light ray can't hit the water, it shouldn't contribute to coloring at all.
|
||||||
|
// float water_depth_to_light = length(water_intersection_surface_light - f_pos);
|
||||||
|
|
||||||
|
// // For ambient color, we just take the distance to the surface out of laziness.
|
||||||
|
// float water_depth_to_vertical = max(/*f_alt - f_pos.z*/f_light, 0.0);
|
||||||
|
|
||||||
|
// // Color goes down with distance...
|
||||||
|
// // See https://en.wikipedia.org/wiki/Beer%E2%80%93Lambert_law.
|
||||||
|
vec3 water_color_direct = vec3(1.0);//exp(-MU_WATER);//vec3(1.0);
|
||||||
|
// vec3 water_color_direct = exp(-water_attenuation * (water_depth_to_light + water_depth_to_camera));
|
||||||
|
// vec3 water_color_ambient = exp(-water_attenuation * (water_depth_to_vertical + water_depth_to_camera));
|
||||||
|
vec3 mu = MU_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.xyz);
|
||||||
|
// float water_depth_to_vertical = max(/*f_alt - f_pos.z*/f_light, 0.0);
|
||||||
|
// For ambient color, we just take the distance to the surface out of laziness.
|
||||||
|
// See https://en.wikipedia.org/wiki/Beer%E2%80%93Lambert_law.
|
||||||
|
float water_depth_to_vertical = max(fluid_alt - cam_pos.z/*f_light*/, 0.0);
|
||||||
|
vec3 ambient_attenuation = exp(-mu * water_depth_to_vertical);
|
||||||
|
|
||||||
|
// For ambient reflection, we just take the water
|
||||||
|
|
||||||
vec3 k_a = vec3(1.0);
|
vec3 k_a = vec3(1.0);
|
||||||
vec3 k_d = vec3(1.0);
|
// Oxygen is light blue.
|
||||||
|
vec3 k_d = vec3(/*vec3(0.2, 0.9, 0.99)*/1.0);
|
||||||
vec3 k_s = vec3(R_s);//2.0 * reflect_color;
|
vec3 k_s = vec3(R_s);//2.0 * reflect_color;
|
||||||
|
|
||||||
vec3 emitted_light, reflected_light;
|
vec3 emitted_light, reflected_light;
|
||||||
@ -142,21 +192,26 @@ 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, view_dir, k_a/* * (shade_frac * 0.5 + light_frac * 0.5)*/, vec3(0.0), /*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, emitted_light, reflected_light);
|
||||||
reflected_light *= reflect_color * f_light * point_shadow * shade_frac;
|
reflected_light *= /*water_color_direct * */reflect_color * f_light * point_shadow * shade_frac;
|
||||||
emitted_light *= 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;
|
||||||
|
|
||||||
vec3 diffuse_light_point = vec3(0.0);
|
// vec3 diffuse_light_point = vec3(0.0);
|
||||||
max_light += lights_at(f_pos, norm, view_dir, k_a, vec3(1.0), /*vec3(0.0)*/k_s, alpha, emitted_light, diffuse_light_point);
|
// max_light += lights_at(f_pos, cam_norm, view_dir, mu, cam_attenuation, fluid_alt, k_a, vec3(1.0), /*vec3(0.0)*/k_s, alpha, emitted_light, diffuse_light_point);
|
||||||
|
|
||||||
vec3 dump_light = vec3(0.0);
|
// vec3 dump_light = vec3(0.0);
|
||||||
vec3 specular_light_point = vec3(0.0);
|
// vec3 specular_light_point = vec3(0.0);
|
||||||
lights_at(f_pos, norm, view_dir, vec3(0.0), vec3(0.0), /*vec3(1.0)*/k_s, alpha, dump_light, specular_light_point);
|
// lights_at(f_pos, cam_norm, view_dir, mu, cam_attenuation, fluid_alt, vec3(0.0), vec3(0.0), /*vec3(1.0)*/k_s, alpha, dump_light, specular_light_point);
|
||||||
diffuse_light_point -= specular_light_point;
|
// diffuse_light_point -= specular_light_point;
|
||||||
|
// max_light += lights_at(f_pos, cam_norm, view_dir, mu, cam_attenuation, fluid_alt, k_a, /*k_d*/vec3(0.0), /*vec3(0.0)*/k_s, alpha, emitted_light, /*diffuse_light*/reflected_light);
|
||||||
|
|
||||||
|
max_light += lights_at(f_pos, cam_norm, view_dir, mu, cam_attenuation, fluid_alt, k_a, /*k_d*//*vec3(0.0)*/k_d, /*vec3(0.0)*/k_s, alpha, emitted_light, /*diffuse_light*/reflected_light);
|
||||||
|
|
||||||
|
float reflected_light_point = length(reflected_light);///*length*/(diffuse_light_point.r) + f_light * point_shadow;
|
||||||
|
// TODO: See if we can be smarter about this using point light distances.
|
||||||
|
// reflected_light += k_d * (diffuse_light_point/* + f_light * point_shadow * shade_frac*/) + /*water_color_ambient*/specular_light_point;
|
||||||
|
|
||||||
float reflected_light_point = /*length*/(diffuse_light_point.r) + f_light * point_shadow;
|
|
||||||
reflected_light += reflect_color * k_d * (diffuse_light_point + f_light * point_shadow * shade_frac) + reflect_color * specular_light_point;
|
|
||||||
/* vec3 point_light = light_at(f_pos, norm);
|
/* vec3 point_light = light_at(f_pos, norm);
|
||||||
emitted_light += point_light;
|
emitted_light += point_light;
|
||||||
reflected_light += point_light; */
|
reflected_light += point_light; */
|
||||||
@ -169,12 +224,19 @@ void main() {
|
|||||||
// diffuse_light += point_light;
|
// diffuse_light += point_light;
|
||||||
// reflected_light += point_light;
|
// reflected_light += point_light;
|
||||||
// vec3 surf_color = srgb_to_linear(vec3(0.2, 0.5, 1.0)) * light * diffuse_light * ambient_light;
|
// vec3 surf_color = srgb_to_linear(vec3(0.2, 0.5, 1.0)) * light * diffuse_light * ambient_light;
|
||||||
vec3 surf_color = illuminate(max_light, water_color * emitted_light, reflected_light);
|
vec3 surf_color = illuminate(max_light, emitted_light/* * log(1.0 - MU_WATER)*/, /*water_color * */reflected_light/* * log(1.0 - MU_WATER)*/);
|
||||||
|
|
||||||
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;
|
||||||
vec3 fog_color = get_sky_color(cam_to_frag/*-view_dir*/, time_of_day.x, cam_pos.xyz, f_pos, 0.25, true, clouds);
|
vec3 fog_color = get_sky_color(cam_to_frag/*-view_dir*/, time_of_day.x, cam_pos.xyz, f_pos, 0.25, true, clouds);
|
||||||
|
|
||||||
|
// passthrough = pow(passthrough, 1.0 / (1.0 + water_depth_to_camera));
|
||||||
|
/* surf_color = cam_attenuation.g < 0.5 ?
|
||||||
|
vec3(1.0, 0.0, 0.0) :
|
||||||
|
vec3(0.0, 1.0, 1.0)
|
||||||
|
; */
|
||||||
|
// passthrough = passthrough * length(cam_attenuation);
|
||||||
|
|
||||||
// vec3 reflect_ray_dir = reflect(cam_to_frag, norm);
|
// vec3 reflect_ray_dir = reflect(cam_to_frag, norm);
|
||||||
// Hack to prevent the reflection ray dipping below the horizon and creating weird blue spots in the water
|
// Hack to prevent the reflection ray dipping below the horizon and creating weird blue spots in the water
|
||||||
// reflect_ray_dir.z = max(reflect_ray_dir.z, 0.01);
|
// reflect_ray_dir.z = max(reflect_ray_dir.z, 0.01);
|
||||||
@ -189,7 +251,11 @@ void main() {
|
|||||||
// vec4 color = mix(vec4(surf_color, 1.0), vec4(surf_color, 0.0), passthrough);
|
// vec4 color = mix(vec4(surf_color, 1.0), vec4(surf_color, 0.0), passthrough);
|
||||||
//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, mix(1.0, 1.0 / (1.0 + /*0.25 * *//*diffuse_light*/(/*f_light * point_shadow*/reflected_light_point)), passthrough));
|
|
||||||
|
vec4 color = vec4(surf_color, 1.0 - passthrough * /*log(1.0 + cam_attenuation)*/cam_attenuation);
|
||||||
|
// 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));
|
||||||
|
|
||||||
/* reflect_color = reflect_color * 0.5 * (diffuse_light + ambient_light);
|
/* reflect_color = reflect_color * 0.5 * (diffuse_light + ambient_light);
|
||||||
// 0 = 100% reflection, 1 = translucent water
|
// 0 = 100% reflection, 1 = translucent water
|
||||||
float passthrough = dot(faceforward(f_norm, f_norm, cam_to_frag), -cam_to_frag);
|
float passthrough = dot(faceforward(f_norm, f_norm, cam_to_frag), -cam_to_frag);
|
||||||
|
@ -25,6 +25,41 @@ float attenuation_strength(vec3 rpos) {
|
|||||||
return max(2.0 / pow(d2 + 10, 0.35) - pow(d2 / 50000.0, 0.8), 0.0);
|
return max(2.0 / pow(d2 + 10, 0.35) - pow(d2 / 50000.0, 0.8), 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Linear RGB, attenuation coefficients for water at roughly R, G, B wavelengths.
|
||||||
|
// See https://en.wikipedia.org/wiki/Electromagnetic_absorption_by_water
|
||||||
|
const vec3 MU_WATER = vec3(0.6, 0.04, 0.01);
|
||||||
|
|
||||||
|
// // Compute attenuation due to light passing through a substance that fills an area below a horizontal plane
|
||||||
|
// // (e.g. in most cases, water below the water surface depth).
|
||||||
|
// //
|
||||||
|
// // wpos is the position of the point being hit.
|
||||||
|
// // ray_dir is the reversed direction of the ray (going "out" of the point being hit).
|
||||||
|
// // surface_alt is the estimated altitude of the horizontal surface separating the substance from air.
|
||||||
|
// // defaultpos is the position to use in computing the distance along material at this point if there was a failure.
|
||||||
|
// //
|
||||||
|
// // Ideally, defaultpos is set so we can avoid branching on error.
|
||||||
|
// float compute_attenuation_beam(vec3 wpos, vec3 ray_dir, float surface_alt, vec3 defaultpos, float attenuation_depth) {
|
||||||
|
// vec3 water_intersection_surface_camera = vec3(cam_pos);
|
||||||
|
// bool _water_intersects_surface_camera = IntersectRayPlane(f_pos, view_dir, vec3(0.0, 0.0, /*f_alt*/f_pos.z + f_light), cam_surface_dir, water_intersection_surface_camera);
|
||||||
|
// // Should work because we set it up so that if IntersectRayPlane returns false for camera, its default intersection point is cam_pos.
|
||||||
|
// float water_depth_to_camera = length(water_intersection_surface_camera - f_pos);
|
||||||
|
//
|
||||||
|
// vec3 water_intersection_surface_light = f_pos;
|
||||||
|
// bool _light_intersects_surface_water = IntersectRayPlane(f_pos, sun_dir.z <= 0.0 ? sun_dir : moon_dir, vec3(0.0, 0.0, /*f_alt*/f_pos.z + f_light), vec3(0.0, 0.0, 1.0), water_intersection_surface_light);
|
||||||
|
// // Should work because we set it up so that if IntersectRayPlane returns false for light, its default intersection point is f_pos--
|
||||||
|
// // i.e. if a light ray can't hit the water, it shouldn't contribute to coloring at all.
|
||||||
|
// float water_depth_to_light = length(water_intersection_surface_light - f_pos);
|
||||||
|
//
|
||||||
|
// // For ambient color, we just take the distance to the surface out of laziness.
|
||||||
|
// float water_depth_to_vertical = max(/*f_alt - f_pos.z*/f_light, 0.0);
|
||||||
|
//
|
||||||
|
// // Color goes down with distance...
|
||||||
|
// // See https://en.wikipedia.org/wiki/Beer%E2%80%93Lambert_law.
|
||||||
|
// vec3 water_color_direct = exp(-water_attenuation * (water_depth_to_light + water_depth_to_camera));
|
||||||
|
// vec3 water_color_ambient = exp(-water_attenuation * (water_depth_to_vertical + water_depth_to_camera));
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
|
||||||
vec3 light_at(vec3 wpos, vec3 wnorm) {
|
vec3 light_at(vec3 wpos, vec3 wnorm) {
|
||||||
const float LIGHT_AMBIENCE = 0.025;
|
const float LIGHT_AMBIENCE = 0.025;
|
||||||
|
|
||||||
@ -75,7 +110,11 @@ float shadow_at(vec3 wpos, vec3 wnorm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Returns computed maximum intensity.
|
// Returns computed maximum intensity.
|
||||||
float lights_at(vec3 wpos, vec3 wnorm, vec3 cam_to_frag, vec3 k_a, vec3 k_d, vec3 k_s, float alpha, inout vec3 emitted_light, inout vec3 reflected_light/*, out float shadow*/) {
|
//
|
||||||
|
// 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.
|
||||||
|
// surface_alt is the altitude of the attenuating surface.
|
||||||
|
float lights_at(vec3 wpos, vec3 wnorm, vec3 cam_to_frag, vec3 mu, vec3 cam_attenuation, float surface_alt, vec3 k_a, vec3 k_d, vec3 k_s, float alpha, inout vec3 emitted_light, inout vec3 reflected_light/*, out float shadow*/) {
|
||||||
// shadow = 0.0;
|
// shadow = 0.0;
|
||||||
vec3 ambient_light = vec3(0.0);
|
vec3 ambient_light = vec3(0.0);
|
||||||
vec3 directed_light = vec3(0.0);
|
vec3 directed_light = vec3(0.0);
|
||||||
@ -125,7 +164,13 @@ float lights_at(vec3 wpos, vec3 wnorm, vec3 cam_to_frag, vec3 k_a, vec3 k_d, vec
|
|||||||
// light_dir = faceforward(light_dir, wnorm, light_dir);
|
// light_dir = faceforward(light_dir, wnorm, light_dir);
|
||||||
bool is_direct = dot(-light_dir, wnorm) > 0.0;
|
bool is_direct = dot(-light_dir, wnorm) > 0.0;
|
||||||
// reflected_light += color * (distance_2 == 0.0 ? vec3(1.0) : light_reflection_factor(wnorm, cam_to_frag, light_dir, k_d, k_s, alpha));
|
// reflected_light += color * (distance_2 == 0.0 ? vec3(1.0) : light_reflection_factor(wnorm, cam_to_frag, light_dir, k_d, k_s, alpha));
|
||||||
vec3 direct_light = PI * color * strength * square_factor * light_reflection_factor(wnorm, cam_to_frag, is_direct ? light_dir : -light_dir, k_d, k_s, alpha);
|
vec3 direct_light_dir = is_direct ? light_dir : -light_dir;
|
||||||
|
// Compute attenuation due to fluid.
|
||||||
|
// Default is light_pos, so we take the whole segment length for this beam if it never intersects the surface, unlesss the beam itself
|
||||||
|
// is above the surface, in which case we take zero (wpos).
|
||||||
|
color *= cam_attenuation * compute_attenuation_point(wpos, -direct_light_dir, mu, surface_alt, light_pos.z < surface_alt ? light_pos : wpos);
|
||||||
|
|
||||||
|
vec3 direct_light = PI * color * strength * square_factor * light_reflection_factor(wnorm, cam_to_frag, direct_light_dir, k_d, k_s, alpha);
|
||||||
directed_light += is_direct ? direct_light * square_factor : vec3(0.0);
|
directed_light += is_direct ? direct_light * square_factor : vec3(0.0);
|
||||||
ambient_light += is_direct ? vec3(0.0) : direct_light * LIGHT_AMBIENCE;
|
ambient_light += is_direct ? vec3(0.0) : direct_light * LIGHT_AMBIENCE;
|
||||||
|
|
||||||
@ -164,3 +209,8 @@ float lights_at(vec3 wpos, vec3 wnorm, vec3 cam_to_frag, vec3 k_a, vec3 k_d, vec
|
|||||||
emitted_light += k_a * ambient_light/* * shadow*/;// min(shadow, 1.0);
|
emitted_light += k_a * ambient_light/* * shadow*/;// min(shadow, 1.0);
|
||||||
return /*rel_luminance(ambient_light + directed_light)*/rel_luminance(max_light);//ambient_light;
|
return /*rel_luminance(ambient_light + directed_light)*/rel_luminance(max_light);//ambient_light;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Same as lights_at, but with no assumed attenuation due to fluid.
|
||||||
|
float lights_at(vec3 wpos, vec3 wnorm, vec3 cam_to_frag, vec3 k_a, vec3 k_d, vec3 k_s, float alpha, inout vec3 emitted_light, inout vec3 reflected_light) {
|
||||||
|
return lights_at(wpos, wnorm, cam_to_frag, vec3(0.0), vec3(1.0), 0.0, k_a, k_d, k_s, alpha, emitted_light, reflected_light);
|
||||||
|
}
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
#include <random.glsl>
|
#include <random.glsl>
|
||||||
#include <srgb.glsl>
|
#include <srgb.glsl>
|
||||||
#include <cloud.glsl>
|
#include <cloud.glsl>
|
||||||
|
#include <srgb.glsl>
|
||||||
|
|
||||||
const float PI = 3.141592;
|
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.2, 1.0, 1.0);
|
const vec3 DAY_LIGHT = vec3(1.0, 1.0, 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);
|
||||||
@ -19,9 +20,14 @@ 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);
|
||||||
const vec3 SKY_NIGHT_MID = vec3(0.001, 0.005, 0.02);
|
const vec3 SKY_NIGHT_MID = vec3(0.001, 0.005, 0.02);
|
||||||
const vec3 SKY_NIGHT_BOT = vec3(0.002, 0.004, 0.004);
|
const vec3 SKY_NIGHT_BOT = vec3(0.002, 0.004, 0.004);
|
||||||
const vec3 NIGHT_LIGHT = vec3(0.002, 0.01, 0.03);
|
const vec3 NIGHT_LIGHT = vec3(0.002, 0.02, 0.02);
|
||||||
// const vec3 NIGHT_LIGHT = vec3(0.0, 0.0, 0.0);
|
// const vec3 NIGHT_LIGHT = vec3(0.0, 0.0, 0.0);
|
||||||
|
|
||||||
|
// Linear RGB, scattering coefficients for atmosphere at roughly R, G, B wavelengths.
|
||||||
|
//
|
||||||
|
// See https://en.wikipedia.org/wiki/Diffuse_sky_radiation
|
||||||
|
const vec3 MU_SCATTER = vec3(0.05, 0.10, 0.23);
|
||||||
|
|
||||||
const float SUN_COLOR_FACTOR = 6.0;//1.8;
|
const float SUN_COLOR_FACTOR = 6.0;//1.8;
|
||||||
|
|
||||||
const float UNDERWATER_MIST_DIST = 100.0;
|
const float UNDERWATER_MIST_DIST = 100.0;
|
||||||
@ -48,7 +54,7 @@ vec3 get_moon_dir(float time_of_day) {
|
|||||||
return normalize(-vec3(sin(moon_angle_rad), 0.0, cos(moon_angle_rad) - 0.5));
|
return normalize(-vec3(sin(moon_angle_rad), 0.0, cos(moon_angle_rad) - 0.5));
|
||||||
}
|
}
|
||||||
|
|
||||||
const float PERSISTENT_AMBIANCE = 0.00125; // 0.1;// 0.025; // 0.1;
|
const float PERSISTENT_AMBIANCE = 1.0 / 512;// 1.0 / 512; // 0.00125 // 0.1;// 0.025; // 0.1;
|
||||||
|
|
||||||
float get_sun_brightness(vec3 sun_dir) {
|
float get_sun_brightness(vec3 sun_dir) {
|
||||||
return max(-sun_dir.z + 0.6, 0.0) * 0.9;
|
return max(-sun_dir.z + 0.6, 0.0) * 0.9;
|
||||||
@ -124,9 +130,14 @@ vec3 get_moon_color(vec3 moon_dir) {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
// Returns computed maximum intensity.
|
// Returns computed maximum intensity.
|
||||||
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) {
|
//
|
||||||
const float SUN_AMBIANCE = 0.23;/* / 1.8*/;// 0.1 / 3.0;
|
// wpos is the position of this fragment.
|
||||||
const float MOON_AMBIANCE = 0.23;//0.1;
|
// 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.
|
||||||
|
// 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) {
|
||||||
|
const vec3 SUN_AMBIANCE = MU_SCATTER;//0.23;/* / 1.8*/;// 0.1 / 3.0;
|
||||||
|
const vec3 MOON_AMBIANCE = MU_SCATTER;//0.23;//0.1;
|
||||||
|
|
||||||
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);
|
||||||
@ -134,8 +145,12 @@ float get_sun_diffuse2(vec3 norm, vec3 sun_dir, vec3 moon_dir, vec3 dir, vec3 k_
|
|||||||
vec3 sun_color = get_sun_color(sun_dir) * SUN_COLOR_FACTOR;
|
vec3 sun_color = get_sun_color(sun_dir) * SUN_COLOR_FACTOR;
|
||||||
vec3 moon_color = get_moon_color(moon_dir);
|
vec3 moon_color = get_moon_color(moon_dir);
|
||||||
|
|
||||||
vec3 sun_chroma = sun_color * sun_light;
|
// If the sun is facing the wrong way, we currently just want zero light, hence default point is wpos.
|
||||||
vec3 moon_chroma = moon_color * moon_light;
|
vec3 sun_attenuation = compute_attenuation(wpos, -sun_dir, mu, surface_alt, wpos);
|
||||||
|
vec3 moon_attenuation = compute_attenuation(wpos, -moon_dir, mu, surface_alt, wpos);
|
||||||
|
|
||||||
|
vec3 sun_chroma = sun_color * sun_light * cam_attenuation * sun_attenuation;
|
||||||
|
vec3 moon_chroma = moon_color * moon_light * cam_attenuation * moon_attenuation;
|
||||||
|
|
||||||
// https://en.m.wikipedia.org/wiki/Diffuse_sky_radiation
|
// https://en.m.wikipedia.org/wiki/Diffuse_sky_radiation
|
||||||
//
|
//
|
||||||
@ -256,9 +271,12 @@ float get_sun_diffuse2(vec3 norm, vec3 sun_dir, vec3 moon_dir, vec3 dir, vec3 k_
|
|||||||
moon_chroma * mix(1.0, pow(dot(-norm, moon_dir) * 2.0, 2.0), diffusion) +
|
moon_chroma * mix(1.0, pow(dot(-norm, moon_dir) * 2.0, 2.0), diffusion) +
|
||||||
PERSISTENT_AMBIANCE;
|
PERSISTENT_AMBIANCE;
|
||||||
ambient_light = vec3(SUN_AMBIANCE * sun_light + moon_light); */
|
ambient_light = vec3(SUN_AMBIANCE * sun_light + moon_light); */
|
||||||
return 0.0;//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, 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);
|
||||||
|
}
|
||||||
|
|
||||||
// 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.
|
||||||
float is_star_at(vec3 dir) {
|
float is_star_at(vec3 dir) {
|
||||||
@ -399,8 +417,8 @@ vec3 illuminate(float max_light, /*vec3 max_light, */vec3 emitted, vec3 reflecte
|
|||||||
const float DUSK_EXPOSURE = 2.0;//0.8;
|
const float DUSK_EXPOSURE = 2.0;//0.8;
|
||||||
const float DAY_EXPOSURE = 1.0;//0.7;
|
const float DAY_EXPOSURE = 1.0;//0.7;
|
||||||
|
|
||||||
const float DAY_SATURATION = 1.0;
|
const float DAY_SATURATION = 1.1;
|
||||||
const float DUSK_SATURATION = 0.5;
|
const float DUSK_SATURATION = 0.6;
|
||||||
const float NIGHT_SATURATION = 0.1;
|
const float NIGHT_SATURATION = 0.1;
|
||||||
|
|
||||||
const float gamma = /*0.5*//*1.*0*/1.0;//1.0;
|
const float gamma = /*0.5*//*1.*0*/1.0;//1.0;
|
||||||
|
@ -207,3 +207,68 @@ float rel_luminance(vec3 rgb)
|
|||||||
const vec3 W = vec3(0.2126, 0.7152, 0.0722);
|
const vec3 W = vec3(0.2126, 0.7152, 0.0722);
|
||||||
return dot(rgb, W);
|
return dot(rgb, W);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// From https://discourse.vvvv.org/t/infinite-ray-intersects-with-infinite-plane/10537
|
||||||
|
// out of laziness.
|
||||||
|
bool IntersectRayPlane(vec3 rayOrigin, vec3 rayDirection, vec3 posOnPlane, vec3 planeNormal, inout vec3 intersectionPoint)
|
||||||
|
{
|
||||||
|
float rDotn = dot(rayDirection, planeNormal);
|
||||||
|
|
||||||
|
//parallel to plane or pointing away from plane?
|
||||||
|
if (rDotn < 0.0000001 )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
float s = dot(planeNormal, (posOnPlane - rayOrigin)) / rDotn;
|
||||||
|
|
||||||
|
intersectionPoint = rayOrigin + s * rayDirection;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute uniform attenuation due to beam passing through a substance that fills an area below a horizontal plane
|
||||||
|
// (e.g. in most cases, water below the water surface depth) using the simplest form of the Beer-Lambert law
|
||||||
|
// (https://en.wikipedia.org/wiki/Beer%E2%80%93Lambert_law):
|
||||||
|
//
|
||||||
|
// I(z) = I₀ e^(-μz)
|
||||||
|
//
|
||||||
|
// We compute this value, except for the initial intensity which may be multiplied out later.
|
||||||
|
//
|
||||||
|
// wpos is the position of the point being hit.
|
||||||
|
// ray_dir is the reversed direction of the ray (going "out" of the point being hit).
|
||||||
|
// mu is the attenuation coefficient for R, G, and B wavelenghts.
|
||||||
|
// surface_alt is the estimated altitude of the horizontal surface separating the substance from air.
|
||||||
|
// defaultpos is the position to use in computing the distance along material at this point if there was a failure.
|
||||||
|
//
|
||||||
|
// 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) {
|
||||||
|
// return vec3(1.0);
|
||||||
|
/*if (dot(mu, mu) == 0.0) {
|
||||||
|
return vec3(1.0);
|
||||||
|
}*//* else {
|
||||||
|
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 = 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);
|
||||||
|
float depth = length(defaultpos - wpos);
|
||||||
|
return exp(-mu * depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Same as compute_attenuation but since both point are known, set a maximum to make sure we don't exceed the length
|
||||||
|
// from the default point.
|
||||||
|
vec3 compute_attenuation_point(vec3 wpos, vec3 ray_dir, vec3 mu, float surface_alt, vec3 defaultpos) {
|
||||||
|
// return vec3(1.0);
|
||||||
|
/*if (dot(mu, mu) == 0.0) {
|
||||||
|
return vec3(1.0);
|
||||||
|
}*//* else {
|
||||||
|
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 = 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);
|
||||||
|
bool _intersects_surface = IntersectRayPlane(wpos, ray_dir, vec3(0.0, 0.0, surface_alt), surface_dir, defaultpos);
|
||||||
|
float depth2 = min(max_length, dot(defaultpos - wpos, defaultpos - wpos));
|
||||||
|
return exp(-mu * sqrt(depth2));
|
||||||
|
}
|
||||||
|
@ -46,9 +46,9 @@ void main() {
|
|||||||
|
|
||||||
vec4 final_color = pow(aa_color, gamma);
|
vec4 final_color = pow(aa_color, gamma);
|
||||||
|
|
||||||
if (medium.x == 1u) {
|
/* if (medium.x == 1u) {
|
||||||
final_color *= vec4(0.2, 0.2, 0.8, 1.0);
|
final_color *= vec4(0.2, 0.2, 0.8, 1.0);
|
||||||
}
|
} */
|
||||||
|
|
||||||
tgt_color = vec4(final_color.rgb, 1);
|
tgt_color = vec4(final_color.rgb, 1);
|
||||||
}
|
}
|
||||||
|
@ -21,9 +21,9 @@ 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;
|
||||||
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, _clouds), 1.0);
|
||||||
|
@ -28,6 +28,8 @@ void main() {
|
|||||||
uint norm_dir = ((f_pos_norm >> 29) & 0x1u) * 3u;
|
uint norm_dir = ((f_pos_norm >> 29) & 0x1u) * 3u;
|
||||||
// Use an array to avoid conditional branching
|
// Use an array to avoid conditional branching
|
||||||
vec3 f_norm = normals[(f_pos_norm >> 29) & 0x7u];
|
vec3 f_norm = normals[(f_pos_norm >> 29) & 0x7u];
|
||||||
|
// Whether this face is facing fluid or not.
|
||||||
|
bool faces_fluid = bool((f_pos_norm >> 28) & 0x1u);
|
||||||
|
|
||||||
vec3 cam_to_frag = normalize(f_pos - cam_pos.xyz);
|
vec3 cam_to_frag = normalize(f_pos - cam_pos.xyz);
|
||||||
// vec4 vert_pos4 = view_mat * vec4(f_pos, 1.0);
|
// vec4 vert_pos4 = view_mat * vec4(f_pos, 1.0);
|
||||||
@ -61,23 +63,31 @@ void main() {
|
|||||||
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 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_a = vec3(1.0);
|
||||||
vec3 k_d = vec3(1.0);
|
vec3 k_d = vec3(1.0);
|
||||||
vec3 k_s = vec3(R_s);
|
vec3 k_s = vec3(R_s);
|
||||||
float max_light = 0.0;
|
float max_light = 0.0;
|
||||||
|
|
||||||
|
// Compute attenuation due to water from the camera.
|
||||||
|
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.
|
||||||
|
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.
|
||||||
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 = 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, 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, 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;
|
||||||
max_light *= f_light * point_shadow * shade_frac;
|
max_light *= f_light * point_shadow * shade_frac;
|
||||||
|
|
||||||
max_light += lights_at(f_pos, f_norm, view_dir, 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 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;
|
||||||
|
@ -22,10 +22,10 @@ out vec3 f_col;
|
|||||||
out float f_light;
|
out float f_light;
|
||||||
out float f_ao;
|
out float f_ao;
|
||||||
|
|
||||||
const int EXTRA_NEG_Z = 65536;
|
const int EXTRA_NEG_Z = 32768;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
f_chunk_pos = vec3(ivec3((uvec3(v_pos_norm) >> uvec3(0, 6, 12)) & uvec3(0x3Fu, 0x3Fu, 0x1FFFFu)) - 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;
|
||||||
|
|
||||||
f_pos.z -= 250.0 * (1.0 - min(1.0001 - 0.02 / pow(tick.x - load_time, 10.0), 1.0));
|
f_pos.z -= 250.0 * (1.0 - min(1.0001 - 0.02 / pow(tick.x - load_time, 10.0), 1.0));
|
||||||
@ -39,7 +39,7 @@ 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(f_pos.xy);
|
f_alt = alt_at_real(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));
|
||||||
|
|
||||||
gl_Position =
|
gl_Position =
|
||||||
|
@ -25,8 +25,6 @@ impl CharSelectionState {
|
|||||||
pub fn new(global_state: &mut GlobalState, client: Rc<RefCell<Client>>) -> Self {
|
pub fn new(global_state: &mut GlobalState, client: Rc<RefCell<Client>>) -> Self {
|
||||||
let scene = Scene::new(
|
let scene = Scene::new(
|
||||||
global_state.window.renderer_mut(),
|
global_state.window.renderer_mut(),
|
||||||
&client.borrow(),
|
|
||||||
&global_state.settings,
|
|
||||||
Some("fixture.selection_bg"),
|
Some("fixture.selection_bg"),
|
||||||
);
|
);
|
||||||
Self {
|
Self {
|
||||||
|
@ -46,7 +46,7 @@ where
|
|||||||
faces_to_make(self, pos, true, |vox| vox.is_empty()),
|
faces_to_make(self, pos, true, |vox| vox.is_empty()),
|
||||||
offs + pos.map(|e| e as f32),
|
offs + pos.map(|e| e as f32),
|
||||||
&[[[Rgba::from_opaque(col); 3]; 3]; 3],
|
&[[[Rgba::from_opaque(col); 3]; 3]; 3],
|
||||||
|origin, norm, col, light, ao| {
|
|origin, norm, col, light, ao, _meta| {
|
||||||
FigureVertex::new(
|
FigureVertex::new(
|
||||||
origin * scale,
|
origin * scale,
|
||||||
norm,
|
norm,
|
||||||
@ -112,7 +112,7 @@ where
|
|||||||
faces_to_make(self, pos, true, |vox| vox.is_empty()),
|
faces_to_make(self, pos, true, |vox| vox.is_empty()),
|
||||||
offs + pos.map(|e| e as f32),
|
offs + pos.map(|e| e as f32),
|
||||||
&[[[Rgba::from_opaque(col); 3]; 3]; 3],
|
&[[[Rgba::from_opaque(col); 3]; 3]; 3],
|
||||||
|origin, norm, col, light, ao| {
|
|origin, norm, col, light, ao, _meta| {
|
||||||
SpriteVertex::new(
|
SpriteVertex::new(
|
||||||
origin * scale,
|
origin * scale,
|
||||||
norm,
|
norm,
|
||||||
@ -150,12 +150,14 @@ fn faces_to_make<V: ReadVol>(
|
|||||||
pos: Vec3<i32>,
|
pos: Vec3<i32>,
|
||||||
error_makes_face: bool,
|
error_makes_face: bool,
|
||||||
should_add: impl Fn(&V::Vox) -> bool,
|
should_add: impl Fn(&V::Vox) -> bool,
|
||||||
) -> [bool; 6] {
|
) -> [Option<()>; 6] {
|
||||||
let (x, y, z) = (Vec3::unit_x(), Vec3::unit_y(), Vec3::unit_z());
|
let (x, y, z) = (Vec3::unit_x(), Vec3::unit_y(), Vec3::unit_z());
|
||||||
let make_face = |offset| {
|
let make_face = |offset| {
|
||||||
seg.get(pos + offset)
|
let res = seg
|
||||||
|
.get(pos + offset)
|
||||||
.map(|v| should_add(v))
|
.map(|v| should_add(v))
|
||||||
.unwrap_or(error_makes_face)
|
.unwrap_or(error_makes_face);
|
||||||
|
if res { Some(()) } else { None }
|
||||||
};
|
};
|
||||||
[
|
[
|
||||||
make_face(-x),
|
make_face(-x),
|
||||||
|
@ -395,10 +395,16 @@ impl<'a, V: RectRasterableVol<Vox = Block> + ReadVol + Debug>
|
|||||||
if block.map_or(false, |vox| vox.is_opaque()) {
|
if block.map_or(false, |vox| vox.is_opaque()) {
|
||||||
vol::push_vox_verts(
|
vol::push_vox_verts(
|
||||||
&mut opaque_mesh, //selected_opaque_mesh,
|
&mut opaque_mesh, //selected_opaque_mesh,
|
||||||
faces_to_make(&blocks, false, |vox| !vox.is_opaque()),
|
faces_to_make(&blocks, None, |vox| {
|
||||||
|
if vox.is_opaque() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(vox.is_fluid())
|
||||||
|
}
|
||||||
|
}),
|
||||||
offs,
|
offs,
|
||||||
&colors,
|
&colors,
|
||||||
|pos, norm, col, light, ao| {
|
|pos, norm, col, light, ao, &meta| {
|
||||||
//let light = (light.min(ao) * 255.0) as u32;
|
//let light = (light.min(ao) * 255.0) as u32;
|
||||||
let light = (light * 255.0) as u32;
|
let light = (light * 255.0) as u32;
|
||||||
let ao = (ao * 255.0) as u32;
|
let ao = (ao * 255.0) as u32;
|
||||||
@ -409,17 +415,33 @@ impl<'a, V: RectRasterableVol<Vox = Block> + ReadVol + Debug>
|
|||||||
} else {
|
} else {
|
||||||
if norm.z < 0.0 { 4 } else { 5 }
|
if norm.z < 0.0 { 4 } else { 5 }
|
||||||
};
|
};
|
||||||
TerrainVertex::new(norm, light, ao, pos, col)
|
TerrainVertex::new(norm, light, ao, pos, col, meta)
|
||||||
},
|
},
|
||||||
&lights,
|
&lights,
|
||||||
);
|
);
|
||||||
} else if block.map_or(false, |vox| vox.is_fluid()) {
|
} else if block.map_or(false, |vox| vox.is_fluid()) {
|
||||||
vol::push_vox_verts(
|
vol::push_vox_verts(
|
||||||
&mut fluid_mesh,
|
&mut fluid_mesh,
|
||||||
faces_to_make(&blocks, true, |vox| vox.is_air()),
|
// NOTE: want to skip blocks that aren't either next to air, or next to
|
||||||
|
// opaque blocks like ground. Addnig the blocks next to ground lets us
|
||||||
|
// make sure we compute lighting effects both at the water surface, and
|
||||||
|
// just before hitting the ground.
|
||||||
|
faces_to_make(&blocks, Some(()), |vox| {
|
||||||
|
if vox.is_air() { Some(()) } else { None }
|
||||||
|
}),
|
||||||
offs,
|
offs,
|
||||||
&colors,
|
&colors,
|
||||||
|pos, norm, col, light, _ao| {
|
|pos, norm, col, light, _ao, _meta| {
|
||||||
|
/* let rel_pos = pos - offs;
|
||||||
|
let rel_vox_pos = if rel_pos == offs {
|
||||||
|
rel_pos + norm + 1.0
|
||||||
|
} else {
|
||||||
|
rel_pos + 1.0
|
||||||
|
}.map(|e| e as usize);
|
||||||
|
let vox_neighbor = blocks[rel_vox_pos.z][rel_vox_pos.y][rel_vox_pos.x];
|
||||||
|
if vox_neighbor.is_opaque() {
|
||||||
|
} else {
|
||||||
|
} */
|
||||||
FluidVertex::new(pos, norm, col, light, 0.3)
|
FluidVertex::new(pos, norm, col, light, 0.3)
|
||||||
},
|
},
|
||||||
&lights,
|
&lights,
|
||||||
@ -450,13 +472,17 @@ impl<'a, V: RectRasterableVol<Vox = Block> + ReadVol + Debug>
|
|||||||
/// Unlike the one in segments.rs this uses a provided array of blocks instead
|
/// Unlike the one in segments.rs this uses a provided array of blocks instead
|
||||||
/// of retrieving from a volume
|
/// of retrieving from a volume
|
||||||
/// blocks[z][y][x]
|
/// blocks[z][y][x]
|
||||||
fn faces_to_make(
|
fn faces_to_make<M: Clone>(
|
||||||
blocks: &[[[Option<Block>; 3]; 3]; 3],
|
blocks: &[[[Option<Block>; 3]; 3]; 3],
|
||||||
error_makes_face: bool,
|
error_makes_face: Option<M>,
|
||||||
should_add: impl Fn(Block) -> bool,
|
should_add: impl Fn(Block) -> Option<M>,
|
||||||
) -> [bool; 6] {
|
) -> [Option<M>; 6] {
|
||||||
// Faces to draw
|
// Faces to draw
|
||||||
let make_face = |opt_v: Option<Block>| opt_v.map(|v| should_add(v)).unwrap_or(error_makes_face);
|
let make_face = |opt_v: Option<Block>| {
|
||||||
|
opt_v
|
||||||
|
.map(|v| should_add(v))
|
||||||
|
.unwrap_or(error_makes_face.clone())
|
||||||
|
};
|
||||||
[
|
[
|
||||||
make_face(blocks[1][1][0]),
|
make_face(blocks[1][1][0]),
|
||||||
make_face(blocks[1][1][2]),
|
make_face(blocks[1][1][2]),
|
||||||
|
@ -96,13 +96,14 @@ fn get_col_quad(dirs: &[Vec3<i32>], cols: &[[[Rgba<u8>; 3]; 3]; 3]) -> Vec4<Rgb<
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Utility function
|
// Utility function
|
||||||
fn create_quad<P: Pipeline, F: Fn(Vec3<f32>, Vec3<f32>, Rgb<f32>, f32, f32) -> P::Vertex>(
|
fn create_quad<P: Pipeline, M, F: Fn(Vec3<f32>, Vec3<f32>, Rgb<f32>, f32, f32, &M) -> P::Vertex>(
|
||||||
origin: Vec3<f32>,
|
origin: Vec3<f32>,
|
||||||
unit_x: Vec3<f32>,
|
unit_x: Vec3<f32>,
|
||||||
unit_y: Vec3<f32>,
|
unit_y: Vec3<f32>,
|
||||||
norm: Vec3<f32>,
|
norm: Vec3<f32>,
|
||||||
cols: Vec4<Rgb<f32>>,
|
cols: Vec4<Rgb<f32>>,
|
||||||
darkness_ao: Vec4<(f32, f32)>,
|
darkness_ao: Vec4<(f32, f32)>,
|
||||||
|
meta: &M,
|
||||||
vcons: &F,
|
vcons: &F,
|
||||||
) -> Quad<P> {
|
) -> Quad<P> {
|
||||||
let darkness = darkness_ao.map(|e| e.0);
|
let darkness = darkness_ao.map(|e| e.0);
|
||||||
@ -112,45 +113,47 @@ fn create_quad<P: Pipeline, F: Fn(Vec3<f32>, Vec3<f32>, Rgb<f32>, f32, f32) -> P
|
|||||||
|
|
||||||
if ao[0].min(ao[2]) < ao[1].min(ao[3]) {
|
if ao[0].min(ao[2]) < ao[1].min(ao[3]) {
|
||||||
Quad::new(
|
Quad::new(
|
||||||
vcons(origin + unit_y, norm, cols[3], darkness[3], ao_map[3]),
|
vcons(origin + unit_y, norm, cols[3], darkness[3], ao_map[3], meta),
|
||||||
vcons(origin, norm, cols[0], darkness[0], ao_map[0]),
|
vcons(origin, norm, cols[0], darkness[0], ao_map[0], meta),
|
||||||
vcons(origin + unit_x, norm, cols[1], darkness[1], ao_map[1]),
|
vcons(origin + unit_x, norm, cols[1], darkness[1], ao_map[1], meta),
|
||||||
vcons(
|
vcons(
|
||||||
origin + unit_x + unit_y,
|
origin + unit_x + unit_y,
|
||||||
norm,
|
norm,
|
||||||
cols[2],
|
cols[2],
|
||||||
darkness[2],
|
darkness[2],
|
||||||
ao_map[2],
|
ao_map[2],
|
||||||
|
meta,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
Quad::new(
|
Quad::new(
|
||||||
vcons(origin, norm, cols[0], darkness[0], ao_map[0]),
|
vcons(origin, norm, cols[0], darkness[0], ao_map[0], meta),
|
||||||
vcons(origin + unit_x, norm, cols[1], darkness[1], ao_map[1]),
|
vcons(origin + unit_x, norm, cols[1], darkness[1], ao_map[1], meta),
|
||||||
vcons(
|
vcons(
|
||||||
origin + unit_x + unit_y,
|
origin + unit_x + unit_y,
|
||||||
norm,
|
norm,
|
||||||
cols[2],
|
cols[2],
|
||||||
darkness[2],
|
darkness[2],
|
||||||
ao_map[2],
|
ao_map[2],
|
||||||
|
meta,
|
||||||
),
|
),
|
||||||
vcons(origin + unit_y, norm, cols[3], darkness[3], ao_map[3]),
|
vcons(origin + unit_y, norm, cols[3], darkness[3], ao_map[3], meta),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push_vox_verts<P: Pipeline>(
|
pub fn push_vox_verts<P: Pipeline, M>(
|
||||||
mesh: &mut Mesh<P>,
|
mesh: &mut Mesh<P>,
|
||||||
faces: [bool; 6],
|
faces: [Option<M>; 6],
|
||||||
offs: Vec3<f32>,
|
offs: Vec3<f32>,
|
||||||
cols: &[[[Rgba<u8>; 3]; 3]; 3],
|
cols: &[[[Rgba<u8>; 3]; 3]; 3],
|
||||||
vcons: impl Fn(Vec3<f32>, Vec3<f32>, Rgb<f32>, f32, f32) -> P::Vertex,
|
vcons: impl Fn(Vec3<f32>, Vec3<f32>, Rgb<f32>, f32, f32, &M) -> P::Vertex,
|
||||||
darknesses: &[[[Option<f32>; 3]; 3]; 3],
|
darknesses: &[[[Option<f32>; 3]; 3]; 3],
|
||||||
) {
|
) {
|
||||||
let (x, y, z) = (Vec3::unit_x(), Vec3::unit_y(), Vec3::unit_z());
|
let (x, y, z) = (Vec3::unit_x(), Vec3::unit_y(), Vec3::unit_z());
|
||||||
|
|
||||||
// -x
|
// -x
|
||||||
if faces[0] {
|
if let Some(meta) = &faces[0] {
|
||||||
mesh.push_quad(create_quad(
|
mesh.push_quad(create_quad(
|
||||||
offs,
|
offs,
|
||||||
Vec3::unit_z(),
|
Vec3::unit_z(),
|
||||||
@ -158,11 +161,12 @@ pub fn push_vox_verts<P: Pipeline>(
|
|||||||
-Vec3::unit_x(),
|
-Vec3::unit_x(),
|
||||||
get_col_quad(&[-z, -y, z, y, -z], cols),
|
get_col_quad(&[-z, -y, z, y, -z], cols),
|
||||||
get_ao_quad(-Vec3::unit_x(), &[-z, -y, z, y, -z], darknesses),
|
get_ao_quad(-Vec3::unit_x(), &[-z, -y, z, y, -z], darknesses),
|
||||||
|
meta,
|
||||||
&vcons,
|
&vcons,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
// +x
|
// +x
|
||||||
if faces[1] {
|
if let Some(meta) = &faces[1] {
|
||||||
mesh.push_quad(create_quad(
|
mesh.push_quad(create_quad(
|
||||||
offs + Vec3::unit_x(),
|
offs + Vec3::unit_x(),
|
||||||
Vec3::unit_y(),
|
Vec3::unit_y(),
|
||||||
@ -170,11 +174,12 @@ pub fn push_vox_verts<P: Pipeline>(
|
|||||||
Vec3::unit_x(),
|
Vec3::unit_x(),
|
||||||
get_col_quad(&[-y, -z, y, z, -y], cols),
|
get_col_quad(&[-y, -z, y, z, -y], cols),
|
||||||
get_ao_quad(Vec3::unit_x(), &[-y, -z, y, z, -y], darknesses),
|
get_ao_quad(Vec3::unit_x(), &[-y, -z, y, z, -y], darknesses),
|
||||||
|
meta,
|
||||||
&vcons,
|
&vcons,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
// -y
|
// -y
|
||||||
if faces[2] {
|
if let Some(meta) = &faces[2] {
|
||||||
mesh.push_quad(create_quad(
|
mesh.push_quad(create_quad(
|
||||||
offs,
|
offs,
|
||||||
Vec3::unit_x(),
|
Vec3::unit_x(),
|
||||||
@ -182,11 +187,12 @@ pub fn push_vox_verts<P: Pipeline>(
|
|||||||
-Vec3::unit_y(),
|
-Vec3::unit_y(),
|
||||||
get_col_quad(&[-x, -z, x, z, -x], cols),
|
get_col_quad(&[-x, -z, x, z, -x], cols),
|
||||||
get_ao_quad(-Vec3::unit_y(), &[-x, -z, x, z, -x], darknesses),
|
get_ao_quad(-Vec3::unit_y(), &[-x, -z, x, z, -x], darknesses),
|
||||||
|
meta,
|
||||||
&vcons,
|
&vcons,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
// +y
|
// +y
|
||||||
if faces[3] {
|
if let Some(meta) = &faces[3] {
|
||||||
mesh.push_quad(create_quad(
|
mesh.push_quad(create_quad(
|
||||||
offs + Vec3::unit_y(),
|
offs + Vec3::unit_y(),
|
||||||
Vec3::unit_z(),
|
Vec3::unit_z(),
|
||||||
@ -194,11 +200,12 @@ pub fn push_vox_verts<P: Pipeline>(
|
|||||||
Vec3::unit_y(),
|
Vec3::unit_y(),
|
||||||
get_col_quad(&[-z, -x, z, x, -z], cols),
|
get_col_quad(&[-z, -x, z, x, -z], cols),
|
||||||
get_ao_quad(Vec3::unit_y(), &[-z, -x, z, x, -z], darknesses),
|
get_ao_quad(Vec3::unit_y(), &[-z, -x, z, x, -z], darknesses),
|
||||||
|
meta,
|
||||||
&vcons,
|
&vcons,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
// -z
|
// -z
|
||||||
if faces[4] {
|
if let Some(meta) = &faces[4] {
|
||||||
mesh.push_quad(create_quad(
|
mesh.push_quad(create_quad(
|
||||||
offs,
|
offs,
|
||||||
Vec3::unit_y(),
|
Vec3::unit_y(),
|
||||||
@ -206,11 +213,12 @@ pub fn push_vox_verts<P: Pipeline>(
|
|||||||
-Vec3::unit_z(),
|
-Vec3::unit_z(),
|
||||||
get_col_quad(&[-y, -x, y, x, -y], cols),
|
get_col_quad(&[-y, -x, y, x, -y], cols),
|
||||||
get_ao_quad(-Vec3::unit_z(), &[-y, -x, y, x, -y], darknesses),
|
get_ao_quad(-Vec3::unit_z(), &[-y, -x, y, x, -y], darknesses),
|
||||||
|
meta,
|
||||||
&vcons,
|
&vcons,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
// +z
|
// +z
|
||||||
if faces[5] {
|
if let Some(meta) = &faces[5] {
|
||||||
mesh.push_quad(create_quad(
|
mesh.push_quad(create_quad(
|
||||||
offs + Vec3::unit_z(),
|
offs + Vec3::unit_z(),
|
||||||
Vec3::unit_x(),
|
Vec3::unit_x(),
|
||||||
@ -218,6 +226,7 @@ pub fn push_vox_verts<P: Pipeline>(
|
|||||||
Vec3::unit_z(),
|
Vec3::unit_z(),
|
||||||
get_col_quad(&[-x, -y, x, y, -x], cols),
|
get_col_quad(&[-x, -y, x, y, -x], cols),
|
||||||
get_ao_quad(Vec3::unit_z(), &[-x, -y, x, y, -x], darknesses),
|
get_ao_quad(Vec3::unit_z(), &[-x, -y, x, y, -x], darknesses),
|
||||||
|
meta,
|
||||||
&vcons,
|
&vcons,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -40,14 +40,22 @@ gfx_defines! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Vertex {
|
impl Vertex {
|
||||||
pub fn new(norm_bits: u32, light: u32, ao: u32, pos: Vec3<f32>, col: Rgb<f32>) -> Self {
|
pub fn new(
|
||||||
const EXTRA_NEG_Z: f32 = 65536.0;
|
norm_bits: u32,
|
||||||
|
light: u32,
|
||||||
|
ao: u32,
|
||||||
|
pos: Vec3<f32>,
|
||||||
|
col: Rgb<f32>,
|
||||||
|
meta: bool,
|
||||||
|
) -> Self {
|
||||||
|
const EXTRA_NEG_Z: f32 = 32768.0;
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
pos_norm: 0
|
pos_norm: 0
|
||||||
| ((pos.x as u32) & 0x003F) << 0
|
| ((pos.x as u32) & 0x003F) << 0
|
||||||
| ((pos.y as u32) & 0x003F) << 6
|
| ((pos.y as u32) & 0x003F) << 6
|
||||||
| (((pos + EXTRA_NEG_Z).z.max(0.0).min((1 << 17) as f32) as u32) & 0xFFFFF) << 12
|
| (((pos + EXTRA_NEG_Z).z.max(0.0).min((1 << 16) as f32) as u32) & 0xFFFF) << 12
|
||||||
|
| if meta { 1 } else { 0 } << 28
|
||||||
| (norm_bits & 0x7) << 29,
|
| (norm_bits & 0x7) << 29,
|
||||||
col_light: 0
|
col_light: 0
|
||||||
| ((col.r.mul(255.0) as u32) & 0xFF) << 8
|
| ((col.r.mul(255.0) as u32) & 0xFF) << 8
|
||||||
|
@ -16,7 +16,7 @@ use crate::{
|
|||||||
render::{Consts, FigureBoneData, FigureLocals, Globals, Light, Renderer, Shadow},
|
render::{Consts, FigureBoneData, FigureLocals, Globals, Light, Renderer, Shadow},
|
||||||
scene::{
|
scene::{
|
||||||
camera::{Camera, CameraMode},
|
camera::{Camera, CameraMode},
|
||||||
Lod, SceneData,
|
LodData, SceneData,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use common::{
|
use common::{
|
||||||
@ -1499,7 +1499,7 @@ impl FigureMgr {
|
|||||||
globals: &Consts<Globals>,
|
globals: &Consts<Globals>,
|
||||||
lights: &Consts<Light>,
|
lights: &Consts<Light>,
|
||||||
shadows: &Consts<Shadow>,
|
shadows: &Consts<Shadow>,
|
||||||
lod: &Lod,
|
lod: &LodData,
|
||||||
camera: &Camera,
|
camera: &Camera,
|
||||||
figure_lod_render_distance: f32,
|
figure_lod_render_distance: f32,
|
||||||
) {
|
) {
|
||||||
@ -1553,7 +1553,7 @@ impl FigureMgr {
|
|||||||
globals: &Consts<Globals>,
|
globals: &Consts<Globals>,
|
||||||
lights: &Consts<Light>,
|
lights: &Consts<Light>,
|
||||||
shadows: &Consts<Shadow>,
|
shadows: &Consts<Shadow>,
|
||||||
lod: &Lod,
|
lod: &LodData,
|
||||||
camera: &Camera,
|
camera: &Camera,
|
||||||
figure_lod_render_distance: f32,
|
figure_lod_render_distance: f32,
|
||||||
) {
|
) {
|
||||||
@ -1602,7 +1602,7 @@ impl FigureMgr {
|
|||||||
globals: &Consts<Globals>,
|
globals: &Consts<Globals>,
|
||||||
lights: &Consts<Light>,
|
lights: &Consts<Light>,
|
||||||
shadows: &Consts<Shadow>,
|
shadows: &Consts<Shadow>,
|
||||||
lod: &Lod,
|
lod: &LodData,
|
||||||
camera: &Camera,
|
camera: &Camera,
|
||||||
character_state: Option<&CharacterState>,
|
character_state: Option<&CharacterState>,
|
||||||
entity: EcsEntity,
|
entity: EcsEntity,
|
||||||
|
@ -10,53 +10,79 @@ use client::Client;
|
|||||||
use common::{spiral::Spiral2d, util::srgba_to_linear};
|
use common::{spiral::Spiral2d, util::srgba_to_linear};
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
pub struct Lod {
|
pub struct LodData {
|
||||||
model: Option<(u32, Model<LodTerrainPipeline>)>,
|
|
||||||
locals: Consts<Locals>,
|
|
||||||
pub map: Texture<LodColorFmt>,
|
pub map: Texture<LodColorFmt>,
|
||||||
pub horizon: Texture<LodTextureFmt>,
|
pub horizon: Texture<LodTextureFmt>,
|
||||||
pub tgt_detail: u32,
|
pub tgt_detail: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Lod {
|
||||||
|
model: Option<(u32, Model<LodTerrainPipeline>)>,
|
||||||
|
locals: Consts<Locals>,
|
||||||
|
data: LodData,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LodData {
|
||||||
|
pub fn new(
|
||||||
|
renderer: &mut Renderer,
|
||||||
|
lod_base: &image::DynamicImage,
|
||||||
|
lod_horizon: &image::DynamicImage,
|
||||||
|
tgt_detail: u32,
|
||||||
|
border_color: gfx::texture::PackedColor,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
map: renderer
|
||||||
|
.create_texture(
|
||||||
|
lod_base,
|
||||||
|
Some(FilterMethod::Bilinear),
|
||||||
|
Some(WrapMode::Border),
|
||||||
|
Some(border_color),
|
||||||
|
)
|
||||||
|
.expect("Failed to generate map texture"),
|
||||||
|
horizon: renderer
|
||||||
|
.create_texture(
|
||||||
|
lod_horizon,
|
||||||
|
Some(FilterMethod::Trilinear),
|
||||||
|
Some(WrapMode::Border),
|
||||||
|
Some([0.0, 1.0, 0.0, 1.0].into()),
|
||||||
|
)
|
||||||
|
.expect("Failed to generate map texture"),
|
||||||
|
tgt_detail,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Lod {
|
impl Lod {
|
||||||
pub fn new(renderer: &mut Renderer, client: &Client, settings: &Settings) -> Self {
|
pub fn new(renderer: &mut Renderer, client: &Client, settings: &Settings) -> Self {
|
||||||
let water_color = /*Rgba::new(0.2, 0.5, 1.0, 0.0)*/srgba_to_linear(Rgba::new(0.0, 0.25, 0.5, 0.0)/* * 0.5*/);
|
let water_color = /*Rgba::new(0.2, 0.5, 1.0, 0.0)*/srgba_to_linear(Rgba::new(0.0, 0.25, 0.5, 0.0)/* * 0.5*/);
|
||||||
Self {
|
Self {
|
||||||
model: None,
|
model: None,
|
||||||
locals: renderer.create_consts(&[Locals::default()]).unwrap(),
|
locals: renderer.create_consts(&[Locals::default()]).unwrap(),
|
||||||
map: renderer
|
data: LodData::new(
|
||||||
.create_texture(
|
renderer,
|
||||||
&client.lod_base,
|
&client.lod_base,
|
||||||
Some(FilterMethod::Bilinear),
|
|
||||||
Some(WrapMode::Border),
|
|
||||||
Some([water_color.r, water_color.g, water_color.b, water_color.a].into()),
|
|
||||||
)
|
|
||||||
.expect("Failed to generate map texture"),
|
|
||||||
horizon: renderer
|
|
||||||
.create_texture(
|
|
||||||
&client.lod_horizon,
|
&client.lod_horizon,
|
||||||
Some(FilterMethod::Trilinear),
|
settings.graphics.lod_detail.max(100).min(2500),
|
||||||
Some(WrapMode::Border),
|
[water_color.r, water_color.g, water_color.b, water_color.a].into(),
|
||||||
Some([0.0, 1.0, 0.0, 1.0].into()),
|
),
|
||||||
)
|
|
||||||
.expect("Failed to generate map texture"),
|
|
||||||
tgt_detail: settings.graphics.lod_detail.max(100).min(2500),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_detail(&mut self, detail: u32) { self.tgt_detail = detail.max(100).min(2500); }
|
pub fn get_data(&self) -> &LodData { &self.data }
|
||||||
|
|
||||||
|
pub fn set_detail(&mut self, detail: u32) { self.data.tgt_detail = detail.max(100).min(2500); }
|
||||||
|
|
||||||
pub fn maintain(&mut self, renderer: &mut Renderer, _time_of_day: f64) {
|
pub fn maintain(&mut self, renderer: &mut Renderer, _time_of_day: f64) {
|
||||||
if self
|
if self
|
||||||
.model
|
.model
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|(detail, _)| *detail != self.tgt_detail)
|
.map(|(detail, _)| *detail != self.data.tgt_detail)
|
||||||
.unwrap_or(true)
|
.unwrap_or(true)
|
||||||
{
|
{
|
||||||
self.model = Some((
|
self.model = Some((
|
||||||
self.tgt_detail,
|
self.data.tgt_detail,
|
||||||
renderer
|
renderer
|
||||||
.create_model(&create_lod_terrain_mesh(self.tgt_detail))
|
.create_model(&create_lod_terrain_mesh(self.data.tgt_detail))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -64,7 +90,13 @@ impl Lod {
|
|||||||
|
|
||||||
pub fn render(&self, renderer: &mut Renderer, globals: &Consts<Globals>) {
|
pub fn render(&self, renderer: &mut Renderer, globals: &Consts<Globals>) {
|
||||||
if let Some((_, model)) = self.model.as_ref() {
|
if let Some((_, model)) = self.model.as_ref() {
|
||||||
renderer.render_lod_terrain(&model, globals, &self.locals, &self.map, &self.horizon);
|
renderer.render_lod_terrain(
|
||||||
|
&model,
|
||||||
|
globals,
|
||||||
|
&self.locals,
|
||||||
|
&self.data.map,
|
||||||
|
&self.data.horizon,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ pub mod terrain;
|
|||||||
use self::{
|
use self::{
|
||||||
camera::{Camera, CameraMode},
|
camera::{Camera, CameraMode},
|
||||||
figure::FigureMgr,
|
figure::FigureMgr,
|
||||||
lod::Lod,
|
lod::{Lod, LodData},
|
||||||
terrain::Terrain,
|
terrain::Terrain,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -352,7 +352,7 @@ impl Scene {
|
|||||||
cam_pos,
|
cam_pos,
|
||||||
self.camera.get_focus_pos(),
|
self.camera.get_focus_pos(),
|
||||||
self.loaded_distance,
|
self.loaded_distance,
|
||||||
self.lod.tgt_detail as f32,
|
self.lod.get_data().tgt_detail as f32,
|
||||||
self.map_bounds,
|
self.map_bounds,
|
||||||
scene_data.state.get_time_of_day(),
|
scene_data.state.get_time_of_day(),
|
||||||
scene_data.state.get_time(),
|
scene_data.state.get_time(),
|
||||||
@ -413,7 +413,7 @@ impl Scene {
|
|||||||
&self.globals,
|
&self.globals,
|
||||||
&self.lights,
|
&self.lights,
|
||||||
&self.shadows,
|
&self.shadows,
|
||||||
&self.lod,
|
self.lod.get_data(),
|
||||||
self.camera.get_focus_pos(),
|
self.camera.get_focus_pos(),
|
||||||
);
|
);
|
||||||
self.figure_mgr.render(
|
self.figure_mgr.render(
|
||||||
@ -424,7 +424,7 @@ impl Scene {
|
|||||||
&self.globals,
|
&self.globals,
|
||||||
&self.lights,
|
&self.lights,
|
||||||
&self.shadows,
|
&self.shadows,
|
||||||
&self.lod,
|
self.lod.get_data(),
|
||||||
&self.camera,
|
&self.camera,
|
||||||
scene_data.figure_lod_render_distance,
|
scene_data.figure_lod_render_distance,
|
||||||
);
|
);
|
||||||
@ -441,7 +441,7 @@ impl Scene {
|
|||||||
&self.globals,
|
&self.globals,
|
||||||
&self.lights,
|
&self.lights,
|
||||||
&self.shadows,
|
&self.shadows,
|
||||||
&self.lod,
|
self.lod.get_data(),
|
||||||
&self.camera,
|
&self.camera,
|
||||||
scene_data.figure_lod_render_distance,
|
scene_data.figure_lod_render_distance,
|
||||||
);
|
);
|
||||||
@ -451,7 +451,7 @@ impl Scene {
|
|||||||
&self.globals,
|
&self.globals,
|
||||||
&self.lights,
|
&self.lights,
|
||||||
&self.shadows,
|
&self.shadows,
|
||||||
&self.lod,
|
self.lod.get_data(),
|
||||||
self.camera.get_focus_pos(),
|
self.camera.get_focus_pos(),
|
||||||
scene_data.sprite_render_distance,
|
scene_data.sprite_render_distance,
|
||||||
);
|
);
|
||||||
|
@ -12,12 +12,10 @@ use crate::{
|
|||||||
scene::{
|
scene::{
|
||||||
camera::{self, Camera, CameraMode},
|
camera::{self, Camera, CameraMode},
|
||||||
figure::{load_mesh, FigureModelCache, FigureState},
|
figure::{load_mesh, FigureModelCache, FigureState},
|
||||||
Lod,
|
LodData,
|
||||||
},
|
},
|
||||||
settings::Settings,
|
|
||||||
window::{Event, PressState},
|
window::{Event, PressState},
|
||||||
};
|
};
|
||||||
use client::Client;
|
|
||||||
use common::{
|
use common::{
|
||||||
comp::{humanoid, Body, Loadout},
|
comp::{humanoid, Body, Loadout},
|
||||||
figure::Segment,
|
figure::Segment,
|
||||||
@ -67,7 +65,7 @@ pub struct Scene {
|
|||||||
|
|
||||||
skybox: Skybox,
|
skybox: Skybox,
|
||||||
postprocess: PostProcess,
|
postprocess: PostProcess,
|
||||||
lod: Lod,
|
lod: LodData,
|
||||||
map_bounds: Vec2<f32>,
|
map_bounds: Vec2<f32>,
|
||||||
backdrop: Option<(Model<FigurePipeline>, FigureState<FixtureSkeleton>)>,
|
backdrop: Option<(Model<FigurePipeline>, FigureState<FixtureSkeleton>)>,
|
||||||
|
|
||||||
@ -89,15 +87,23 @@ pub struct SceneData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Scene {
|
impl Scene {
|
||||||
pub fn new(
|
pub fn new(renderer: &mut Renderer, backdrop: Option<&str>) -> Self {
|
||||||
renderer: &mut Renderer,
|
|
||||||
client: &Client,
|
|
||||||
settings: &Settings,
|
|
||||||
backdrop: Option<&str>,
|
|
||||||
) -> Self {
|
|
||||||
let start_angle = 90.0f32.to_radians();
|
let start_angle = 90.0f32.to_radians();
|
||||||
let resolution = renderer.get_resolution().map(|e| e as f32);
|
let resolution = renderer.get_resolution().map(|e| e as f32);
|
||||||
|
|
||||||
|
let map_bounds = Vec2::new(-65536.0, 131071.0);
|
||||||
|
let map_border = [0.0, 0.0, 0.0, 0.0];
|
||||||
|
let map_image = image::DynamicImage::ImageRgba8(image::RgbaImage::from_pixel(
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
image::Rgba([0, 0, 0, 0]),
|
||||||
|
));
|
||||||
|
let horizon_image = image::DynamicImage::ImageRgba8(image::RgbaImage::from_pixel(
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
image::Rgba([0, 1, 0, 1]),
|
||||||
|
));
|
||||||
|
|
||||||
let mut camera = Camera::new(resolution.x / resolution.y, CameraMode::ThirdPerson);
|
let mut camera = Camera::new(resolution.x / resolution.y, CameraMode::ThirdPerson);
|
||||||
camera.set_focus_pos(Vec3::unit_z() * 1.5);
|
camera.set_focus_pos(Vec3::unit_z() * 1.5);
|
||||||
camera.set_distance(3.0); // 4.2
|
camera.set_distance(3.0); // 4.2
|
||||||
@ -118,8 +124,8 @@ impl Scene {
|
|||||||
.create_consts(&[PostProcessLocals::default()])
|
.create_consts(&[PostProcessLocals::default()])
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
},
|
},
|
||||||
lod: Lod::new(renderer, client, settings),
|
lod: LodData::new(renderer, &map_image, &horizon_image, 1, map_border.into()),// Lod::new(renderer, client, settings),
|
||||||
map_bounds: client.world_map.2,
|
map_bounds,//: client.world_map.2,
|
||||||
|
|
||||||
figure_model_cache: FigureModelCache::new(),
|
figure_model_cache: FigureModelCache::new(),
|
||||||
figure_state: FigureState::new(renderer, CharacterSkeleton::new()),
|
figure_state: FigureState::new(renderer, CharacterSkeleton::new()),
|
||||||
|
@ -6,7 +6,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{Lod, SceneData};
|
use super::{LodData, SceneData};
|
||||||
use common::{
|
use common::{
|
||||||
assets,
|
assets,
|
||||||
figure::Segment,
|
figure::Segment,
|
||||||
@ -2191,7 +2191,7 @@ impl<V: RectRasterableVol> Terrain<V> {
|
|||||||
globals: &Consts<Globals>,
|
globals: &Consts<Globals>,
|
||||||
lights: &Consts<Light>,
|
lights: &Consts<Light>,
|
||||||
shadows: &Consts<Shadow>,
|
shadows: &Consts<Shadow>,
|
||||||
lod: &Lod,
|
lod: &LodData,
|
||||||
focus_pos: Vec3<f32>,
|
focus_pos: Vec3<f32>,
|
||||||
) {
|
) {
|
||||||
let focus_chunk = Vec2::from(focus_pos).map2(TerrainChunk::RECT_SIZE, |e: f32, sz| {
|
let focus_chunk = Vec2::from(focus_pos).map2(TerrainChunk::RECT_SIZE, |e: f32, sz| {
|
||||||
@ -2227,7 +2227,7 @@ impl<V: RectRasterableVol> Terrain<V> {
|
|||||||
globals: &Consts<Globals>,
|
globals: &Consts<Globals>,
|
||||||
lights: &Consts<Light>,
|
lights: &Consts<Light>,
|
||||||
shadows: &Consts<Shadow>,
|
shadows: &Consts<Shadow>,
|
||||||
lod: &Lod,
|
lod: &LodData,
|
||||||
focus_pos: Vec3<f32>,
|
focus_pos: Vec3<f32>,
|
||||||
sprite_render_distance: f32,
|
sprite_render_distance: f32,
|
||||||
) {
|
) {
|
||||||
|
Loading…
Reference in New Issue
Block a user