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 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.0, 0.25, 0.5));
|
||||
|
||||
vec3 sun_dir = get_sun_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)*/;
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
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);
|
||||
reflect_ray_dir = normalize(vec3(reflect_ray_dir4) / reflect_ray_dir4.w); */
|
||||
// vec3 cam_to_frag = normalize(f_pos - cam_pos.xyz);
|
||||
// Squared to account for prior saturation.
|
||||
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;
|
||||
/*const */vec3 water_color = srgb_to_linear(vec3(0.2, 0.5, 1.0));
|
||||
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.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 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 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);
|
||||
@ -122,16 +142,46 @@ void main() {
|
||||
// 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;
|
||||
|
||||
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 < f_alt) ? mix(R_s2s1 * R_s1s0, R_s1s0, medium.x) : mix(R_s2s0, R_s1s2 * R_s2s0, medium.x);
|
||||
// Hack to determine water depth: color goes down with distance through water, so
|
||||
// we assume water color absorption from this point a to some other point b is the distance
|
||||
// along the the ray from a to b where it intersects with the surface plane; if it doesn't,
|
||||
// then the whole segment from a to b is considered underwater.
|
||||
// TODO: Consider doing for point lights.
|
||||
// vec3 cam_surface_dir = faceforward(vec3(0.0, 0.0, 1.0), cam_to_frag, vec3(0.0, 0.0, 1.0));
|
||||
|
||||
// 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_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 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 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);
|
||||
reflected_light *= reflect_color * f_light * point_shadow * shade_frac;
|
||||
emitted_light *= f_light * point_shadow * max(shade_frac, MIN_SHADOW);
|
||||
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 *= /*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);
|
||||
max_light *= f_light * point_shadow * shade_frac;
|
||||
|
||||
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);
|
||||
// vec3 diffuse_light_point = vec3(0.0);
|
||||
// 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 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);
|
||||
diffuse_light_point -= specular_light_point;
|
||||
// vec3 dump_light = vec3(0.0);
|
||||
// vec3 specular_light_point = vec3(0.0);
|
||||
// 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;
|
||||
// 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);
|
||||
emitted_light += point_light;
|
||||
reflected_light += point_light; */
|
||||
@ -169,12 +224,19 @@ void main() {
|
||||
// diffuse_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 = 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);
|
||||
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);
|
||||
|
||||
// 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);
|
||||
// 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);
|
||||
@ -189,7 +251,11 @@ void main() {
|
||||
// vec4 color = mix(vec4(surf_color, 1.0), vec4(surf_color, 0.0), passthrough);
|
||||
//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 = 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);
|
||||
// 0 = 100% reflection, 1 = translucent water
|
||||
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);
|
||||
}
|
||||
|
||||
// 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) {
|
||||
const float LIGHT_AMBIENCE = 0.025;
|
||||
|
||||
@ -75,7 +110,11 @@ float shadow_at(vec3 wpos, vec3 wnorm) {
|
||||
}
|
||||
|
||||
// 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;
|
||||
vec3 ambient_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);
|
||||
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));
|
||||
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);
|
||||
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);
|
||||
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 <srgb.glsl>
|
||||
#include <cloud.glsl>
|
||||
#include <srgb.glsl>
|
||||
|
||||
const float PI = 3.141592;
|
||||
|
||||
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_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 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_MID = vec3(0.001, 0.005, 0.02);
|
||||
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);
|
||||
|
||||
// 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 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));
|
||||
}
|
||||
|
||||
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) {
|
||||
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.
|
||||
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;
|
||||
const float MOON_AMBIANCE = 0.23;//0.1;
|
||||
//
|
||||
// wpos is the position of this fragment.
|
||||
// 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 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 moon_color = get_moon_color(moon_dir);
|
||||
|
||||
vec3 sun_chroma = sun_color * sun_light;
|
||||
vec3 moon_chroma = moon_color * moon_light;
|
||||
// If the sun is facing the wrong way, we currently just want zero light, hence default point is wpos.
|
||||
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
|
||||
//
|
||||
@ -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) +
|
||||
PERSISTENT_AMBIANCE;
|
||||
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.
|
||||
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 DAY_EXPOSURE = 1.0;//0.7;
|
||||
|
||||
const float DAY_SATURATION = 1.0;
|
||||
const float DUSK_SATURATION = 0.5;
|
||||
const float DAY_SATURATION = 1.1;
|
||||
const float DUSK_SATURATION = 0.6;
|
||||
const float NIGHT_SATURATION = 0.1;
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
if (medium.x == 1u) {
|
||||
/* if (medium.x == 1u) {
|
||||
final_color *= vec4(0.2, 0.2, 0.8, 1.0);
|
||||
}
|
||||
} */
|
||||
|
||||
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 dist = 100000.0;
|
||||
if (medium.x == 1u) {
|
||||
/* if (medium.x == 1u) {
|
||||
dist = UNDERWATER_MIST_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);
|
||||
|
@ -28,6 +28,8 @@ void main() {
|
||||
uint norm_dir = ((f_pos_norm >> 29) & 0x1u) * 3u;
|
||||
// Use an array to avoid conditional branching
|
||||
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);
|
||||
// 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_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 < 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_d = vec3(1.0);
|
||||
vec3 k_s = vec3(R_s);
|
||||
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;
|
||||
// To account for prior saturation
|
||||
float f_light = pow(f_light, 1.5);
|
||||
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);
|
||||
reflected_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;
|
||||
emitted_light *= ao;
|
||||
|
@ -22,10 +22,10 @@ out vec3 f_col;
|
||||
out float f_light;
|
||||
out float f_ao;
|
||||
|
||||
const int EXTRA_NEG_Z = 65536;
|
||||
const int EXTRA_NEG_Z = 32768;
|
||||
|
||||
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.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;
|
||||
|
||||
// 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));
|
||||
|
||||
gl_Position =
|
||||
|
@ -25,8 +25,6 @@ impl CharSelectionState {
|
||||
pub fn new(global_state: &mut GlobalState, client: Rc<RefCell<Client>>) -> Self {
|
||||
let scene = Scene::new(
|
||||
global_state.window.renderer_mut(),
|
||||
&client.borrow(),
|
||||
&global_state.settings,
|
||||
Some("fixture.selection_bg"),
|
||||
);
|
||||
Self {
|
||||
|
@ -46,7 +46,7 @@ where
|
||||
faces_to_make(self, pos, true, |vox| vox.is_empty()),
|
||||
offs + pos.map(|e| e as f32),
|
||||
&[[[Rgba::from_opaque(col); 3]; 3]; 3],
|
||||
|origin, norm, col, light, ao| {
|
||||
|origin, norm, col, light, ao, _meta| {
|
||||
FigureVertex::new(
|
||||
origin * scale,
|
||||
norm,
|
||||
@ -112,7 +112,7 @@ where
|
||||
faces_to_make(self, pos, true, |vox| vox.is_empty()),
|
||||
offs + pos.map(|e| e as f32),
|
||||
&[[[Rgba::from_opaque(col); 3]; 3]; 3],
|
||||
|origin, norm, col, light, ao| {
|
||||
|origin, norm, col, light, ao, _meta| {
|
||||
SpriteVertex::new(
|
||||
origin * scale,
|
||||
norm,
|
||||
@ -150,12 +150,14 @@ fn faces_to_make<V: ReadVol>(
|
||||
pos: Vec3<i32>,
|
||||
error_makes_face: 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 make_face = |offset| {
|
||||
seg.get(pos + offset)
|
||||
let res = seg
|
||||
.get(pos + offset)
|
||||
.map(|v| should_add(v))
|
||||
.unwrap_or(error_makes_face)
|
||||
.unwrap_or(error_makes_face);
|
||||
if res { Some(()) } else { None }
|
||||
};
|
||||
[
|
||||
make_face(-x),
|
||||
|
@ -395,10 +395,16 @@ impl<'a, V: RectRasterableVol<Vox = Block> + ReadVol + Debug>
|
||||
if block.map_or(false, |vox| vox.is_opaque()) {
|
||||
vol::push_vox_verts(
|
||||
&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,
|
||||
&colors,
|
||||
|pos, norm, col, light, ao| {
|
||||
|pos, norm, col, light, ao, &meta| {
|
||||
//let light = (light.min(ao) * 255.0) as u32;
|
||||
let light = (light * 255.0) as u32;
|
||||
let ao = (ao * 255.0) as u32;
|
||||
@ -409,17 +415,33 @@ impl<'a, V: RectRasterableVol<Vox = Block> + ReadVol + Debug>
|
||||
} else {
|
||||
if norm.z < 0.0 { 4 } else { 5 }
|
||||
};
|
||||
TerrainVertex::new(norm, light, ao, pos, col)
|
||||
TerrainVertex::new(norm, light, ao, pos, col, meta)
|
||||
},
|
||||
&lights,
|
||||
);
|
||||
} else if block.map_or(false, |vox| vox.is_fluid()) {
|
||||
vol::push_vox_verts(
|
||||
&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,
|
||||
&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)
|
||||
},
|
||||
&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
|
||||
/// of retrieving from a volume
|
||||
/// blocks[z][y][x]
|
||||
fn faces_to_make(
|
||||
fn faces_to_make<M: Clone>(
|
||||
blocks: &[[[Option<Block>; 3]; 3]; 3],
|
||||
error_makes_face: bool,
|
||||
should_add: impl Fn(Block) -> bool,
|
||||
) -> [bool; 6] {
|
||||
error_makes_face: Option<M>,
|
||||
should_add: impl Fn(Block) -> Option<M>,
|
||||
) -> [Option<M>; 6] {
|
||||
// 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][2]),
|
||||
|
@ -96,13 +96,14 @@ fn get_col_quad(dirs: &[Vec3<i32>], cols: &[[[Rgba<u8>; 3]; 3]; 3]) -> Vec4<Rgb<
|
||||
}
|
||||
|
||||
// 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>,
|
||||
unit_x: Vec3<f32>,
|
||||
unit_y: Vec3<f32>,
|
||||
norm: Vec3<f32>,
|
||||
cols: Vec4<Rgb<f32>>,
|
||||
darkness_ao: Vec4<(f32, f32)>,
|
||||
meta: &M,
|
||||
vcons: &F,
|
||||
) -> Quad<P> {
|
||||
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]) {
|
||||
Quad::new(
|
||||
vcons(origin + unit_y, norm, cols[3], darkness[3], ao_map[3]),
|
||||
vcons(origin, norm, cols[0], darkness[0], ao_map[0]),
|
||||
vcons(origin + unit_x, norm, cols[1], darkness[1], ao_map[1]),
|
||||
vcons(origin + unit_y, norm, cols[3], darkness[3], ao_map[3], meta),
|
||||
vcons(origin, norm, cols[0], darkness[0], ao_map[0], meta),
|
||||
vcons(origin + unit_x, norm, cols[1], darkness[1], ao_map[1], meta),
|
||||
vcons(
|
||||
origin + unit_x + unit_y,
|
||||
norm,
|
||||
cols[2],
|
||||
darkness[2],
|
||||
ao_map[2],
|
||||
meta,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
Quad::new(
|
||||
vcons(origin, norm, cols[0], darkness[0], ao_map[0]),
|
||||
vcons(origin + unit_x, norm, cols[1], darkness[1], ao_map[1]),
|
||||
vcons(origin, norm, cols[0], darkness[0], ao_map[0], meta),
|
||||
vcons(origin + unit_x, norm, cols[1], darkness[1], ao_map[1], meta),
|
||||
vcons(
|
||||
origin + unit_x + unit_y,
|
||||
norm,
|
||||
cols[2],
|
||||
darkness[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>,
|
||||
faces: [bool; 6],
|
||||
faces: [Option<M>; 6],
|
||||
offs: Vec3<f32>,
|
||||
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],
|
||||
) {
|
||||
let (x, y, z) = (Vec3::unit_x(), Vec3::unit_y(), Vec3::unit_z());
|
||||
|
||||
// -x
|
||||
if faces[0] {
|
||||
if let Some(meta) = &faces[0] {
|
||||
mesh.push_quad(create_quad(
|
||||
offs,
|
||||
Vec3::unit_z(),
|
||||
@ -158,11 +161,12 @@ pub fn push_vox_verts<P: Pipeline>(
|
||||
-Vec3::unit_x(),
|
||||
get_col_quad(&[-z, -y, z, y, -z], cols),
|
||||
get_ao_quad(-Vec3::unit_x(), &[-z, -y, z, y, -z], darknesses),
|
||||
meta,
|
||||
&vcons,
|
||||
));
|
||||
}
|
||||
// +x
|
||||
if faces[1] {
|
||||
if let Some(meta) = &faces[1] {
|
||||
mesh.push_quad(create_quad(
|
||||
offs + Vec3::unit_x(),
|
||||
Vec3::unit_y(),
|
||||
@ -170,11 +174,12 @@ pub fn push_vox_verts<P: Pipeline>(
|
||||
Vec3::unit_x(),
|
||||
get_col_quad(&[-y, -z, y, z, -y], cols),
|
||||
get_ao_quad(Vec3::unit_x(), &[-y, -z, y, z, -y], darknesses),
|
||||
meta,
|
||||
&vcons,
|
||||
));
|
||||
}
|
||||
// -y
|
||||
if faces[2] {
|
||||
if let Some(meta) = &faces[2] {
|
||||
mesh.push_quad(create_quad(
|
||||
offs,
|
||||
Vec3::unit_x(),
|
||||
@ -182,11 +187,12 @@ pub fn push_vox_verts<P: Pipeline>(
|
||||
-Vec3::unit_y(),
|
||||
get_col_quad(&[-x, -z, x, z, -x], cols),
|
||||
get_ao_quad(-Vec3::unit_y(), &[-x, -z, x, z, -x], darknesses),
|
||||
meta,
|
||||
&vcons,
|
||||
));
|
||||
}
|
||||
// +y
|
||||
if faces[3] {
|
||||
if let Some(meta) = &faces[3] {
|
||||
mesh.push_quad(create_quad(
|
||||
offs + Vec3::unit_y(),
|
||||
Vec3::unit_z(),
|
||||
@ -194,11 +200,12 @@ pub fn push_vox_verts<P: Pipeline>(
|
||||
Vec3::unit_y(),
|
||||
get_col_quad(&[-z, -x, z, x, -z], cols),
|
||||
get_ao_quad(Vec3::unit_y(), &[-z, -x, z, x, -z], darknesses),
|
||||
meta,
|
||||
&vcons,
|
||||
));
|
||||
}
|
||||
// -z
|
||||
if faces[4] {
|
||||
if let Some(meta) = &faces[4] {
|
||||
mesh.push_quad(create_quad(
|
||||
offs,
|
||||
Vec3::unit_y(),
|
||||
@ -206,11 +213,12 @@ pub fn push_vox_verts<P: Pipeline>(
|
||||
-Vec3::unit_z(),
|
||||
get_col_quad(&[-y, -x, y, x, -y], cols),
|
||||
get_ao_quad(-Vec3::unit_z(), &[-y, -x, y, x, -y], darknesses),
|
||||
meta,
|
||||
&vcons,
|
||||
));
|
||||
}
|
||||
// +z
|
||||
if faces[5] {
|
||||
if let Some(meta) = &faces[5] {
|
||||
mesh.push_quad(create_quad(
|
||||
offs + Vec3::unit_z(),
|
||||
Vec3::unit_x(),
|
||||
@ -218,6 +226,7 @@ pub fn push_vox_verts<P: Pipeline>(
|
||||
Vec3::unit_z(),
|
||||
get_col_quad(&[-x, -y, x, y, -x], cols),
|
||||
get_ao_quad(Vec3::unit_z(), &[-x, -y, x, y, -x], darknesses),
|
||||
meta,
|
||||
&vcons,
|
||||
));
|
||||
}
|
||||
|
@ -40,14 +40,22 @@ gfx_defines! {
|
||||
}
|
||||
|
||||
impl Vertex {
|
||||
pub fn new(norm_bits: u32, light: u32, ao: u32, pos: Vec3<f32>, col: Rgb<f32>) -> Self {
|
||||
const EXTRA_NEG_Z: f32 = 65536.0;
|
||||
pub fn new(
|
||||
norm_bits: u32,
|
||||
light: u32,
|
||||
ao: u32,
|
||||
pos: Vec3<f32>,
|
||||
col: Rgb<f32>,
|
||||
meta: bool,
|
||||
) -> Self {
|
||||
const EXTRA_NEG_Z: f32 = 32768.0;
|
||||
|
||||
Self {
|
||||
pos_norm: 0
|
||||
| ((pos.x as u32) & 0x003F) << 0
|
||||
| ((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,
|
||||
col_light: 0
|
||||
| ((col.r.mul(255.0) as u32) & 0xFF) << 8
|
||||
|
@ -16,7 +16,7 @@ use crate::{
|
||||
render::{Consts, FigureBoneData, FigureLocals, Globals, Light, Renderer, Shadow},
|
||||
scene::{
|
||||
camera::{Camera, CameraMode},
|
||||
Lod, SceneData,
|
||||
LodData, SceneData,
|
||||
},
|
||||
};
|
||||
use common::{
|
||||
@ -1499,7 +1499,7 @@ impl FigureMgr {
|
||||
globals: &Consts<Globals>,
|
||||
lights: &Consts<Light>,
|
||||
shadows: &Consts<Shadow>,
|
||||
lod: &Lod,
|
||||
lod: &LodData,
|
||||
camera: &Camera,
|
||||
figure_lod_render_distance: f32,
|
||||
) {
|
||||
@ -1553,7 +1553,7 @@ impl FigureMgr {
|
||||
globals: &Consts<Globals>,
|
||||
lights: &Consts<Light>,
|
||||
shadows: &Consts<Shadow>,
|
||||
lod: &Lod,
|
||||
lod: &LodData,
|
||||
camera: &Camera,
|
||||
figure_lod_render_distance: f32,
|
||||
) {
|
||||
@ -1602,7 +1602,7 @@ impl FigureMgr {
|
||||
globals: &Consts<Globals>,
|
||||
lights: &Consts<Light>,
|
||||
shadows: &Consts<Shadow>,
|
||||
lod: &Lod,
|
||||
lod: &LodData,
|
||||
camera: &Camera,
|
||||
character_state: Option<&CharacterState>,
|
||||
entity: EcsEntity,
|
||||
|
@ -10,53 +10,79 @@ use client::Client;
|
||||
use common::{spiral::Spiral2d, util::srgba_to_linear};
|
||||
use vek::*;
|
||||
|
||||
pub struct Lod {
|
||||
model: Option<(u32, Model<LodTerrainPipeline>)>,
|
||||
locals: Consts<Locals>,
|
||||
pub struct LodData {
|
||||
pub map: Texture<LodColorFmt>,
|
||||
pub horizon: Texture<LodTextureFmt>,
|
||||
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 {
|
||||
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*/);
|
||||
Self {
|
||||
model: None,
|
||||
locals: renderer.create_consts(&[Locals::default()]).unwrap(),
|
||||
map: renderer
|
||||
.create_texture(
|
||||
data: LodData::new(
|
||||
renderer,
|
||||
&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,
|
||||
Some(FilterMethod::Trilinear),
|
||||
Some(WrapMode::Border),
|
||||
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),
|
||||
settings.graphics.lod_detail.max(100).min(2500),
|
||||
[water_color.r, water_color.g, water_color.b, water_color.a].into(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
if self
|
||||
.model
|
||||
.as_ref()
|
||||
.map(|(detail, _)| *detail != self.tgt_detail)
|
||||
.map(|(detail, _)| *detail != self.data.tgt_detail)
|
||||
.unwrap_or(true)
|
||||
{
|
||||
self.model = Some((
|
||||
self.tgt_detail,
|
||||
self.data.tgt_detail,
|
||||
renderer
|
||||
.create_model(&create_lod_terrain_mesh(self.tgt_detail))
|
||||
.create_model(&create_lod_terrain_mesh(self.data.tgt_detail))
|
||||
.unwrap(),
|
||||
));
|
||||
}
|
||||
@ -64,7 +90,13 @@ impl Lod {
|
||||
|
||||
pub fn render(&self, renderer: &mut Renderer, globals: &Consts<Globals>) {
|
||||
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::{
|
||||
camera::{Camera, CameraMode},
|
||||
figure::FigureMgr,
|
||||
lod::Lod,
|
||||
lod::{Lod, LodData},
|
||||
terrain::Terrain,
|
||||
};
|
||||
use crate::{
|
||||
@ -352,7 +352,7 @@ impl Scene {
|
||||
cam_pos,
|
||||
self.camera.get_focus_pos(),
|
||||
self.loaded_distance,
|
||||
self.lod.tgt_detail as f32,
|
||||
self.lod.get_data().tgt_detail as f32,
|
||||
self.map_bounds,
|
||||
scene_data.state.get_time_of_day(),
|
||||
scene_data.state.get_time(),
|
||||
@ -413,7 +413,7 @@ impl Scene {
|
||||
&self.globals,
|
||||
&self.lights,
|
||||
&self.shadows,
|
||||
&self.lod,
|
||||
self.lod.get_data(),
|
||||
self.camera.get_focus_pos(),
|
||||
);
|
||||
self.figure_mgr.render(
|
||||
@ -424,7 +424,7 @@ impl Scene {
|
||||
&self.globals,
|
||||
&self.lights,
|
||||
&self.shadows,
|
||||
&self.lod,
|
||||
self.lod.get_data(),
|
||||
&self.camera,
|
||||
scene_data.figure_lod_render_distance,
|
||||
);
|
||||
@ -441,7 +441,7 @@ impl Scene {
|
||||
&self.globals,
|
||||
&self.lights,
|
||||
&self.shadows,
|
||||
&self.lod,
|
||||
self.lod.get_data(),
|
||||
&self.camera,
|
||||
scene_data.figure_lod_render_distance,
|
||||
);
|
||||
@ -451,7 +451,7 @@ impl Scene {
|
||||
&self.globals,
|
||||
&self.lights,
|
||||
&self.shadows,
|
||||
&self.lod,
|
||||
self.lod.get_data(),
|
||||
self.camera.get_focus_pos(),
|
||||
scene_data.sprite_render_distance,
|
||||
);
|
||||
|
@ -12,12 +12,10 @@ use crate::{
|
||||
scene::{
|
||||
camera::{self, Camera, CameraMode},
|
||||
figure::{load_mesh, FigureModelCache, FigureState},
|
||||
Lod,
|
||||
LodData,
|
||||
},
|
||||
settings::Settings,
|
||||
window::{Event, PressState},
|
||||
};
|
||||
use client::Client;
|
||||
use common::{
|
||||
comp::{humanoid, Body, Loadout},
|
||||
figure::Segment,
|
||||
@ -67,7 +65,7 @@ pub struct Scene {
|
||||
|
||||
skybox: Skybox,
|
||||
postprocess: PostProcess,
|
||||
lod: Lod,
|
||||
lod: LodData,
|
||||
map_bounds: Vec2<f32>,
|
||||
backdrop: Option<(Model<FigurePipeline>, FigureState<FixtureSkeleton>)>,
|
||||
|
||||
@ -89,15 +87,23 @@ pub struct SceneData {
|
||||
}
|
||||
|
||||
impl Scene {
|
||||
pub fn new(
|
||||
renderer: &mut Renderer,
|
||||
client: &Client,
|
||||
settings: &Settings,
|
||||
backdrop: Option<&str>,
|
||||
) -> Self {
|
||||
pub fn new(renderer: &mut Renderer, backdrop: Option<&str>) -> Self {
|
||||
let start_angle = 90.0f32.to_radians();
|
||||
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);
|
||||
camera.set_focus_pos(Vec3::unit_z() * 1.5);
|
||||
camera.set_distance(3.0); // 4.2
|
||||
@ -118,8 +124,8 @@ impl Scene {
|
||||
.create_consts(&[PostProcessLocals::default()])
|
||||
.unwrap(),
|
||||
},
|
||||
lod: Lod::new(renderer, client, settings),
|
||||
map_bounds: client.world_map.2,
|
||||
lod: LodData::new(renderer, &map_image, &horizon_image, 1, map_border.into()),// Lod::new(renderer, client, settings),
|
||||
map_bounds,//: client.world_map.2,
|
||||
|
||||
figure_model_cache: FigureModelCache::new(),
|
||||
figure_state: FigureState::new(renderer, CharacterSkeleton::new()),
|
||||
|
@ -6,7 +6,7 @@ use crate::{
|
||||
},
|
||||
};
|
||||
|
||||
use super::{Lod, SceneData};
|
||||
use super::{LodData, SceneData};
|
||||
use common::{
|
||||
assets,
|
||||
figure::Segment,
|
||||
@ -2191,7 +2191,7 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
globals: &Consts<Globals>,
|
||||
lights: &Consts<Light>,
|
||||
shadows: &Consts<Shadow>,
|
||||
lod: &Lod,
|
||||
lod: &LodData,
|
||||
focus_pos: Vec3<f32>,
|
||||
) {
|
||||
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>,
|
||||
lights: &Consts<Light>,
|
||||
shadows: &Consts<Shadow>,
|
||||
lod: &Lod,
|
||||
lod: &LodData,
|
||||
focus_pos: Vec3<f32>,
|
||||
sprite_render_distance: f32,
|
||||
) {
|
||||
|
Loading…
Reference in New Issue
Block a user