mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Clouds
This commit is contained in:
parent
9d19a2ec63
commit
2237500743
@ -51,6 +51,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Revamped structure of where settings, logs, and game saves are stored so that almost everything is in one place.
|
||||
- Moved hammer leap attack to skillbar
|
||||
- Reworked fire staff
|
||||
- Overhauled cloud shaders to add mist, light attenuation, an approximation of rayleigh scattering, etc.
|
||||
|
||||
### Removed
|
||||
|
||||
|
@ -328,7 +328,10 @@ magically infused items?"#,
|
||||
"hud.settings.fluid_rendering_mode": "Fluid Rendering Mode",
|
||||
"hud.settings.fluid_rendering_mode.cheap": "Cheap",
|
||||
"hud.settings.fluid_rendering_mode.shiny": "Shiny",
|
||||
"hud.settings.cloud_rendering_mode.regular": "Regular",
|
||||
"hud.settings.cloud_rendering_mode.minimal": "Minimal",
|
||||
"hud.settings.cloud_rendering_mode.low": "Low",
|
||||
"hud.settings.cloud_rendering_mode.medium": "Medium",
|
||||
"hud.settings.cloud_rendering_mode.high": "High",
|
||||
"hud.settings.fullscreen": "Fullscreen",
|
||||
"hud.settings.fullscreen_mode": "Fullscreen Mode",
|
||||
"hud.settings.fullscreen_mode.exclusive": "Exclusive",
|
||||
|
@ -183,6 +183,7 @@ void main() {
|
||||
|
||||
reflected_light *= ao;
|
||||
emitted_light *= ao;
|
||||
/* reflected_light *= cloud_shadow(f_pos); */
|
||||
/* vec3 point_light = light_at(f_pos, f_norm);
|
||||
emitted_light += point_light;
|
||||
reflected_light += point_light; */
|
||||
@ -198,15 +199,6 @@ void main() {
|
||||
// vec3 surf_color = illuminate(srgb_to_linear(highlight_col.rgb * f_col), light, diffuse_light, ambient_light);
|
||||
surf_color = illuminate(max_light, view_dir, surf_color * emitted_light, surf_color * reflected_light) * highlight_col.rgb;
|
||||
|
||||
#if (CLOUD_MODE == CLOUD_MODE_REGULAR)
|
||||
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.5, false, clouds);
|
||||
vec3 color = mix(mix(surf_color, fog_color, fog_level), clouds.rgb, clouds.a);
|
||||
#elif (CLOUD_MODE == CLOUD_MODE_NONE)
|
||||
vec3 color = surf_color;
|
||||
#endif
|
||||
|
||||
// if ((flags & 1) == 1 && int(cam_mode) == 1) {
|
||||
// float distance = distance(vec3(cam_pos), focus_pos.xyz) - 2;
|
||||
|
||||
@ -218,5 +210,5 @@ void main() {
|
||||
// // }
|
||||
// }
|
||||
|
||||
tgt_color = vec4(color, 1.0);
|
||||
tgt_color = vec4(surf_color, 1.0);
|
||||
}
|
||||
|
@ -186,13 +186,5 @@ void main() {
|
||||
// vec4 color = vec4(surf_color, passthrough * 1.0 / (1.0 + min_refl));// * (1.0 - /*log(1.0 + cam_attenuation)*//*cam_attenuation*/1.0 / (2.0 - log_cam)));
|
||||
vec4 color = mix(vec4(surf_color, 1.0), vec4(surf_color, 1.0 / (1.0 + /*diffuse_light*//*(f_light * point_shadow + point_light)*//*4.0 * reflected_light_point*/min_refl/* * 0.25*/)), passthrough);
|
||||
|
||||
#if (CLOUD_MODE == CLOUD_MODE_REGULAR)
|
||||
float fog_level = fog(f_pos.xyz, focus_pos.xyz, medium.x);
|
||||
vec4 clouds;
|
||||
vec3 fog_color = get_sky_color(cam_to_frag, time_of_day.x, cam_pos.xyz, f_pos, 0.25, false, clouds);
|
||||
vec4 final_color = mix(mix(color, vec4(fog_color, 0.0), fog_level), vec4(clouds.rgb, 0.0), clouds.a);
|
||||
#elif (CLOUD_MODE == CLOUD_MODE_NONE)
|
||||
vec4 final_color = color;
|
||||
#endif
|
||||
tgt_color = final_color;
|
||||
tgt_color = color;
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ uniform sampler2D t_waves;
|
||||
|
||||
out vec4 tgt_color;
|
||||
|
||||
#include <sky.glsl>
|
||||
#include <cloud.glsl>
|
||||
#include <light.glsl>
|
||||
#include <lod.glsl>
|
||||
|
||||
@ -87,7 +87,7 @@ float wave_height(vec3 pos) {
|
||||
0.0
|
||||
);
|
||||
|
||||
return pow(abs(height), 0.5) * sign(height) * 10.5;
|
||||
return pow(abs(height), 0.5) * sign(height) * 15.0;
|
||||
}
|
||||
|
||||
void main() {
|
||||
@ -166,7 +166,6 @@ void main() {
|
||||
|
||||
// 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 = view_dir;///*sign(cam_pos.z - fluid_alt) * view_dir;*/cam_pos.z <= fluid_alt ? -view_dir : view_dir;
|
||||
@ -177,7 +176,9 @@ void main() {
|
||||
// vec3 cam_to_frag = normalize(f_pos - cam_pos.xyz);
|
||||
// Squared to account for prior saturation.
|
||||
float f_light = 1.0;// pow(f_light, 1.5);
|
||||
vec3 reflect_color = get_sky_color(/*reflect_ray_dir*/beam_view_dir, time_of_day.x, f_pos, vec3(-100000), 0.25, true, _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, true);
|
||||
reflect_color = get_cloud_color(reflect_color, reflect_ray_dir, cam_pos.xyz, time_of_day.x, 100000.0, 1.0);
|
||||
reflect_color *= 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.
|
||||
@ -253,6 +254,7 @@ void main() {
|
||||
|
||||
float max_light = 0.0;
|
||||
max_light += get_sun_diffuse2(sun_info, moon_info, norm, /*time_of_day.x*/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, f_norm, 1.0, emitted_light, reflected_light);
|
||||
// Apply cloud layer to sky
|
||||
// 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;
|
||||
@ -323,13 +325,5 @@ void main() {
|
||||
|
||||
vec4 color = mix(vec4(reflect_color, 1.0), vec4(vec3(0), 1.0 / (1.0 + diffuse_light * 0.25)), passthrough); */
|
||||
|
||||
#if (CLOUD_MODE == CLOUD_MODE_REGULAR)
|
||||
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, false, clouds);
|
||||
vec4 final_color = mix(mix(color, vec4(fog_color, 0.0), fog_level), vec4(clouds.rgb, 0.0), clouds.a);
|
||||
#elif (CLOUD_MODE == CLOUD_MODE_NONE)
|
||||
vec4 final_color = color;
|
||||
#endif
|
||||
tgt_color = final_color;
|
||||
tgt_color = color;
|
||||
}
|
||||
|
@ -1,3 +1,3 @@
|
||||
vec4 get_cloud_color(vec3 dir, vec3 origin, float time_of_day, float max_dist, float quality) {
|
||||
return vec4(0.0);
|
||||
vec3 get_cloud_color(vec3 surf_color, vec3 dir, vec3 origin, float time_of_day, float max_dist, float quality) {
|
||||
return surf_color;
|
||||
}
|
||||
|
@ -1,85 +1,152 @@
|
||||
#include <random.glsl>
|
||||
#include <lod.glsl>
|
||||
|
||||
const float CLOUD_THRESHOLD = 0.27;
|
||||
const float CLOUD_SCALE = 5.0;
|
||||
const float CLOUD_DENSITY = 100.0;
|
||||
const float CLOUD_DENSITY = 150.0;
|
||||
|
||||
float vsum(vec3 v) {
|
||||
return v.x + v.y + v.z;
|
||||
vec2 get_cloud_heights(vec2 pos) {
|
||||
const float CLOUD_HALF_WIDTH = 300;
|
||||
const float CLOUD_HEIGHT_VARIATION = 1000.0;
|
||||
float cloud_alt = CLOUD_AVG_ALT + (texture(t_noise, pos.xy * 0.0001).x - 0.5) * CLOUD_HEIGHT_VARIATION;
|
||||
#if (CLOUD_MODE != CLOUD_MODE_MINIMAL)
|
||||
cloud_alt += (texture(t_noise, pos.xy * 0.001).x - 0.5) * 0.1 * CLOUD_HEIGHT_VARIATION;
|
||||
#endif
|
||||
return vec2(cloud_alt, CLOUD_HALF_WIDTH);
|
||||
}
|
||||
|
||||
vec3 get_cloud_heights() {
|
||||
float CLOUD_AVG_HEIGHT = /*1025.0*/view_distance.z + 0.7 * view_distance.w;
|
||||
float CLOUD_HEIGHT_MIN = CLOUD_AVG_HEIGHT - 60.0;
|
||||
float CLOUD_HEIGHT_MAX = CLOUD_AVG_HEIGHT + 60.0;
|
||||
return vec3(CLOUD_AVG_HEIGHT, CLOUD_HEIGHT_MIN, CLOUD_HEIGHT_MAX);
|
||||
}
|
||||
// Returns vec4(r, g, b, density)
|
||||
vec3 cloud_at(vec3 pos, float dist) {
|
||||
// Natural attenuation of air (air naturally attenuates light that passes through it)
|
||||
// Simulate the atmosphere thinning above 3000 metres down to nothing at 5000 metres
|
||||
float air = 0.00005 * clamp((3000.0 - pos.z) / 2000, 0, 1);
|
||||
|
||||
vec2 cloud_at(vec3 pos) {
|
||||
vec3 max_heights = get_cloud_heights();
|
||||
vec2 scaled_pos = pos.xy / CLOUD_SCALE;
|
||||
// Mist sits close to the ground in valleys (TODO: use base_alt to put it closer to water)
|
||||
float MIST_MIN = 300;
|
||||
const float MIST_FADE_HEIGHT = 250;
|
||||
float mist = 0.00025 * pow(clamp(1.0 - (pos.z - MIST_MIN) / MIST_FADE_HEIGHT, 0.0, 1), 2) / (1.0 + pow(1.0 + dist / 20000.0, 2.0));
|
||||
|
||||
float tick_offs = 0.0
|
||||
+ texture(t_noise, scaled_pos * 0.0005 - time_of_day.x * 0.00001).x * 0.5
|
||||
+ texture(t_noise, scaled_pos * 0.0015).x * 0.15;
|
||||
vec3 wind_pos = vec3(pos.xy + wind_offset, pos.z);
|
||||
|
||||
float value = (
|
||||
0.0
|
||||
+ texture(t_noise, scaled_pos * 0.0003 + tick_offs).x
|
||||
+ texture(t_noise, scaled_pos * 0.0015 - tick_offs * 2.0).x * 0.5
|
||||
) / 3.0;
|
||||
// Clouds
|
||||
float cloud_tendency = cloud_tendency_at(pos.xy);
|
||||
float sun_access = 0.05;
|
||||
float cloud = 0;
|
||||
|
||||
value += (0.0
|
||||
+ texture(t_noise, scaled_pos * 0.008 + time_of_day.x * 0.0002).x * 0.25
|
||||
+ texture(t_noise, scaled_pos * 0.02 + tick_offs + time_of_day.x * 0.0002).x * 0.15
|
||||
) * value;
|
||||
vec2 cloud_attr = get_cloud_heights(wind_pos.xy);
|
||||
float cloud_factor = 0.0;
|
||||
// This is a silly optimisation but it actually nets us a fair few fps by skipping quite a few expensive calcs
|
||||
if (cloud_tendency > 0 || mist > 0.0) {
|
||||
// Turbulence (small variations in clouds/mist)
|
||||
const float turb_speed = -1.0; // Turbulence goes the opposite way
|
||||
vec3 turb_offset = vec3(1, 1, 0) * time_of_day.x * turb_speed;
|
||||
#if (CLOUD_MODE == CLOUD_MODE_MINIMAL)
|
||||
float turb_noise = 0.0;
|
||||
#else
|
||||
float turb_noise = noise_3d((wind_pos + turb_offset) * 0.001) - 0.5;
|
||||
#endif
|
||||
#if (CLOUD_MODE == CLOUD_MODE_MEDIUM || CLOUD_MODE == CLOUD_MODE_HIGH)
|
||||
turb_noise += (noise_3d((wind_pos + turb_offset * 0.3) * 0.004) - 0.5) * 0.25;
|
||||
#endif
|
||||
mist *= (1.0 + turb_noise);
|
||||
|
||||
float density = max((value - CLOUD_THRESHOLD) - abs(pos.z - max_heights.x) / 200.0, 0.0) * CLOUD_DENSITY;
|
||||
|
||||
float SHADE_GRADIENT = 1.5 / (max_heights.x - max_heights.y);
|
||||
float shade = ((pos.z - max_heights.x) / (max_heights.z - max_heights.y)) * 5.0 + 0.3;
|
||||
|
||||
return vec2(shade, density / (1.0 + vsum(abs(pos - cam_pos.xyz)) / 5000));
|
||||
}
|
||||
|
||||
vec4 get_cloud_color(vec3 dir, vec3 origin, float time_of_day, float max_dist, float quality) {
|
||||
const int ITERS = 12;
|
||||
const float INCR = 1.0 / ITERS;
|
||||
origin = origin + focus_off.xyz;
|
||||
|
||||
vec3 max_heights = get_cloud_heights();
|
||||
float mind = (max_heights.y - origin.z) / dir.z;
|
||||
float maxd = (max_heights.z - origin.z) / dir.z;
|
||||
|
||||
float start = max(min(mind, maxd), 0.0);
|
||||
float delta = min(abs(mind - maxd), max_dist);
|
||||
|
||||
float fuzz = sin(texture(t_noise, dir.xz * 100000.0 + tick.x).x * 100.0) * INCR * delta * pow(abs(maxd - mind), 0.3) * 2.0;
|
||||
|
||||
float cloud_shade = 1.0;
|
||||
float passthrough = 1.0;
|
||||
if ((mind > 0.0 || maxd > 0.0) && start < max_dist) {
|
||||
float dist = start;
|
||||
for (int i = 0; i < ITERS; i ++) {
|
||||
dist += fuzz * 0.01 * min(pow(dist * 0.005, 2.0), 1.0);
|
||||
|
||||
vec3 pos = origin + dir * min(dist, max_dist);
|
||||
vec2 sample_ = cloud_at(pos);
|
||||
|
||||
float integral = sample_.y * INCR;
|
||||
passthrough *= 1.0 - integral;
|
||||
cloud_shade = mix(cloud_shade, sample_.x, passthrough * integral);
|
||||
dist += INCR * delta;
|
||||
|
||||
if (passthrough < 0.1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
cloud_factor = 0.25 * (1.0 - pow(min(abs(pos.z - cloud_attr.x) / (cloud_attr.y * pow(max(cloud_tendency * 20.0, 0), 0.5)), 1.0), 2.0));
|
||||
float cloud_flat = min(cloud_tendency, 0.07) * 0.05;
|
||||
cloud_flat *= (1.0 + turb_noise * 7.0 * max(0, 1.0 - cloud_factor * 5));
|
||||
cloud = cloud_flat * pow(cloud_factor, 2) * 20 / (1 + pow(1.0 + dist / 10000.0, 2.0));
|
||||
}
|
||||
|
||||
float total_density = 1.0 - passthrough / (1.0 + pow(max_dist, 0.5) * 0.0001 + max((0.015 - dir.z) * 0.0001, 0.0) * max_dist);
|
||||
// What proportion of sunlight is *not* being blocked by nearby cloud? (approximation)
|
||||
sun_access = clamp((pos.z - cloud_attr.x) * 0.002 + 0.35 + mist * 10000, 0.0, 1);
|
||||
|
||||
total_density = max(total_density - 1.0 / pow(max_dist, 0.25), 0.0); // Hack
|
||||
// Prevent clouds and mist appearing underground (but fade them out gently)
|
||||
float not_underground = clamp(1.0 - (alt_at(pos.xy - focus_off.xy) - (pos.z - focus_off.z)) / 80.0, 0, 1);
|
||||
float vapor_density = (mist + cloud) * not_underground;
|
||||
|
||||
return vec4(vec3(cloud_shade), total_density);
|
||||
// We track vapor density and air density separately. Why? Because photons will ionize particles in air
|
||||
// leading to rayleigh scattering, but water vapor will not. Tracking these indepedently allows us to
|
||||
// get more correct colours.
|
||||
return vec3(sun_access, vapor_density, air);
|
||||
}
|
||||
|
||||
float atan2(in float y, in float x) {
|
||||
bool s = (abs(x) > abs(y));
|
||||
return mix(PI/2.0 - atan(x,y), atan(y,x), s);
|
||||
}
|
||||
|
||||
const float DIST_CAP = 50000;
|
||||
#if (CLOUD_MODE == CLOUD_MODE_HIGH)
|
||||
const uint QUALITY = 100u;
|
||||
#elif (CLOUD_MODE == CLOUD_MODE_MEDIUM)
|
||||
const uint QUALITY = 40u;
|
||||
#elif (CLOUD_MODE == CLOUD_MODE_LOW)
|
||||
const uint QUALITY = 20u;
|
||||
#elif (CLOUD_MODE == CLOUD_MODE_MINIMAL)
|
||||
const uint QUALITY = 7u;
|
||||
#endif
|
||||
|
||||
const float STEP_SCALE = DIST_CAP / (10.0 * float(QUALITY));
|
||||
|
||||
float step_to_dist(float step) {
|
||||
return pow(step, 2) * STEP_SCALE;
|
||||
}
|
||||
|
||||
float dist_to_step(float dist) {
|
||||
return pow(dist / STEP_SCALE, 0.5);
|
||||
}
|
||||
|
||||
vec3 get_cloud_color(vec3 surf_color, const vec3 dir, vec3 origin, const float time_of_day, float max_dist, const float quality) {
|
||||
// Limit the marching distance to reduce maximum jumps
|
||||
max_dist = min(max_dist, DIST_CAP);
|
||||
|
||||
origin.xyz += focus_off.xyz;
|
||||
|
||||
float splay = 1.0;
|
||||
// This hack adds a little direction-dependent noise to clouds. It's not correct, but it very cheaply
|
||||
// improves visual quality for low cloud settings
|
||||
#if (CLOUD_MODE == CLOUD_MODE_MINIMAL)
|
||||
splay += (texture(t_noise, vec2(atan2(dir.x, dir.y) * 2 / PI, dir.z) * 1.5 - time_of_day * 0.000025).x - 0.5) * 0.4 / (1.0 + pow(dir.z, 2) * 10);
|
||||
#endif
|
||||
#if (CLOUD_MODE == CLOUD_MODE_MINIMAL || CLOUD_MODE == CLOUD_MODE_LOW)
|
||||
splay += (texture(t_noise, vec2(atan2(dir.x, dir.y) * 2 / PI, dir.z) * 10.0 - time_of_day * 0.00005).x - 0.5) * 0.075 / (1.0 + pow(dir.z, 2) * 10);
|
||||
#endif
|
||||
splay = clamp(splay, 0.5, 1.5);
|
||||
|
||||
// Proportion of sunlight that get scattered back into the camera by clouds
|
||||
float sun_scatter = max(dot(-dir, sun_dir.xyz), 0.5);
|
||||
float moon_scatter = max(dot(-dir, moon_dir.xyz), 0.5);
|
||||
vec3 sky_color = get_sky_color();
|
||||
vec3 directed_scatter =
|
||||
// Sun scatter
|
||||
get_sun_color() * get_sun_brightness() * sun_scatter +
|
||||
// Moon scatter
|
||||
get_moon_color() * get_moon_brightness() * moon_scatter;
|
||||
|
||||
float cdist = max_dist;
|
||||
vec3 last_sample = cloud_at(origin + dir * cdist, cdist);
|
||||
while (cdist > 10) {
|
||||
float ndist = step_to_dist(trunc(dist_to_step(cdist - 10)));
|
||||
vec3 next_sample = cloud_at(origin + dir * ndist * splay, ndist);
|
||||
|
||||
vec3 sample_avg = last_sample;//(last_sample + next_sample) / 2.0;
|
||||
vec2 density_integrals = sample_avg.yz * (cdist - ndist);
|
||||
|
||||
float sun_access = sample_avg.x;
|
||||
float scatter_factor = 1.0 - 1.0 / (1.0 + density_integrals.x);
|
||||
|
||||
surf_color =
|
||||
// Attenuate light passing through the clouds, removing light due to rayleigh scattering (transmission component)
|
||||
surf_color * (1.0 - scatter_factor) - surf_color * density_integrals.y * sky_color +
|
||||
// This is not rayleigh scattering, but it's good enough for our purposes
|
||||
sky_color * density_integrals.y +
|
||||
// Add the directed light light scattered into the camera by the clouds
|
||||
directed_scatter * sun_access * scatter_factor +
|
||||
// Global illumination (uniform scatter from the sky)
|
||||
sky_color * sun_access * scatter_factor;
|
||||
|
||||
cdist = ndist;
|
||||
last_sample = next_sample;
|
||||
}
|
||||
|
||||
return surf_color;
|
||||
}
|
||||
|
@ -10,7 +10,10 @@
|
||||
#define FLUID_MODE_SHINY 1
|
||||
|
||||
#define CLOUD_MODE_NONE 0
|
||||
#define CLOUD_MODE_REGULAR 1
|
||||
#define CLOUD_MODE_MINIMAL 1
|
||||
#define CLOUD_MODE_LOW 2
|
||||
#define CLOUD_MODE_MEDIUM 3
|
||||
#define CLOUD_MODE_HIGH 4
|
||||
|
||||
#define LIGHTING_ALGORITHM_LAMBERTIAN 0
|
||||
#define LIGHTING_ALGORITHM_BLINN_PHONG 1
|
||||
|
@ -6,6 +6,53 @@ float hash(vec4 p) {
|
||||
return (fract(p.x * p.y * p.z * p.w * (p.x + p.y + p.z + p.w)) - 0.5) * 2.0;
|
||||
}
|
||||
|
||||
#define M1 1597334677U //1719413*929
|
||||
#define M2 3812015801U //140473*2467*11
|
||||
#define M3 2741598923U
|
||||
|
||||
float hash_one(uint q)
|
||||
{
|
||||
uint n = ((M3 * q) ^ M2) * M1;
|
||||
|
||||
return float(n) * (1.0/float(0xffffffffU));
|
||||
}
|
||||
|
||||
float hash_fast(uvec3 q)
|
||||
{
|
||||
q *= uvec3(M1, M2, M3);
|
||||
|
||||
uint n = (q.x ^ q.y ^ q.z) * M1;
|
||||
|
||||
return float(n) * (1.0/float(0xffffffffU));
|
||||
}
|
||||
|
||||
// 3D, but using shifted 2D textures
|
||||
float noise_3d(vec3 pos) {
|
||||
pos.z *= 15.0;
|
||||
uint z = uint(trunc(pos.z));
|
||||
vec2 offs0 = vec2(hash_one(z), hash_one(z + 73u));
|
||||
vec2 offs1 = vec2(hash_one(z + 1u), hash_one(z + 1u + 73u));
|
||||
return mix(texture(t_noise, pos.xy + offs0).x, texture(t_noise, pos.xy + offs1).x, fract(pos.z));
|
||||
}
|
||||
|
||||
// 3D version of `snoise`
|
||||
float snoise3(in vec3 x) {
|
||||
uvec3 p = uvec3(floor(x) + 10000.0);
|
||||
vec3 f = fract(x);
|
||||
//f = f * f * (3.0 - 2.0 * f);
|
||||
return mix(
|
||||
mix(
|
||||
mix(hash_fast(p + uvec3(0,0,0)), hash_fast(p + uvec3(1,0,0)), f.x),
|
||||
mix(hash_fast(p + uvec3(0,1,0)), hash_fast(p + uvec3(1,1,0)), f.x),
|
||||
f.y),
|
||||
mix(
|
||||
mix(hash_fast(p + uvec3(0,0,1)), hash_fast(p + uvec3(1,0,1)), f.x),
|
||||
mix(hash_fast(p + uvec3(0,1,1)), hash_fast(p + uvec3(1,1,1)), f.x),
|
||||
f.y),
|
||||
f.z);
|
||||
}
|
||||
|
||||
// 4D noise
|
||||
float snoise(in vec4 x) {
|
||||
vec4 p = floor(x);
|
||||
vec4 f = fract(x);
|
||||
|
@ -1,7 +1,5 @@
|
||||
#include <random.glsl>
|
||||
#include <srgb.glsl>
|
||||
#include <cloud.glsl>
|
||||
#include <srgb.glsl>
|
||||
#include <shadows.glsl>
|
||||
#include <globals.glsl>
|
||||
|
||||
@ -25,7 +23,7 @@ const vec3 SKY_DUSK_TOP = vec3(0.06, 0.1, 0.20);
|
||||
const vec3 SKY_DUSK_MID = vec3(0.35, 0.1, 0.15);
|
||||
const vec3 SKY_DUSK_BOT = vec3(0.0, 0.1, 0.23);
|
||||
const vec3 DUSK_LIGHT = vec3(9.0, 1.5, 0.15);
|
||||
const vec3 SUN_HALO_DUSK = vec3(1.2, 0.15, 0.0);
|
||||
const vec3 SUN_HALO_DUSK = vec3(1.2, 0.25, 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);
|
||||
@ -66,12 +64,35 @@ const float PERSISTENT_AMBIANCE = 1.0 / 32.0;// 1.0 / 80; // 1.0 / 512; // 0.001
|
||||
// return normalize(-vec3(sin(moon_angle_rad), 0.0, cos(moon_angle_rad) - 0.5));
|
||||
//}
|
||||
|
||||
float CLOUD_AVG_ALT = view_distance.z + 0.75 * view_distance.w;
|
||||
|
||||
const float wind_speed = 0.25;
|
||||
vec2 wind_offset = vec2(time_of_day.x * wind_speed);
|
||||
|
||||
float cloud_tendency_at(vec2 pos) {
|
||||
return clamp(texture(t_noise, (pos + wind_offset) * 0.000075).x - 0.5, 0, 1);
|
||||
}
|
||||
|
||||
float cloud_shadow(vec3 pos, vec3 light_dir) {
|
||||
#if (CLOUD_MODE == CLOUD_MODE_NONE || CLOUD_MODE == CLOUD_MODE_MINIMAL)
|
||||
return 1.0;
|
||||
#else
|
||||
vec2 xy_offset = light_dir.xy * ((CLOUD_AVG_ALT - pos.z) / -light_dir.z);
|
||||
|
||||
// Fade out shadow if the sun angle is too steep (simulates a widening penumbra with distance)
|
||||
const vec2 FADE_RANGE = vec2(1500, 10000);
|
||||
float fade = 1.0 - clamp((length(xy_offset) - FADE_RANGE.x) / (FADE_RANGE.y - FADE_RANGE.x), 0, 1);
|
||||
|
||||
return max(0, 1 - fade * cloud_tendency_at(pos.xy + focus_off.xy - xy_offset) * 3.0);
|
||||
#endif
|
||||
}
|
||||
|
||||
float get_sun_brightness(/*vec3 sun_dir*/) {
|
||||
return max(-sun_dir.z + 0.6, 0.0) * 0.9;
|
||||
}
|
||||
|
||||
float get_moon_brightness(/*vec3 moon_dir*/) {
|
||||
return max(-moon_dir.z + 0.6, 0.0) * 0.4;
|
||||
return max(-moon_dir.z + 0.6, 0.0) * 0.1;
|
||||
}
|
||||
|
||||
vec3 get_sun_color(/*vec3 sun_dir*/) {
|
||||
@ -86,6 +107,20 @@ vec3 get_sun_color(/*vec3 sun_dir*/) {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Average sky colour (i.e: perfectly scattered light from the sky)
|
||||
vec3 get_sky_color(/*vec3 sun_dir*/) {
|
||||
return mix(
|
||||
mix(
|
||||
(SKY_DUSK_TOP + SKY_DUSK_MID) / 2,
|
||||
(SKY_NIGHT_TOP + SKY_NIGHT_MID) / 2,
|
||||
max(sun_dir.z, 0)
|
||||
),
|
||||
(SKY_DAY_TOP + SKY_DAY_MID) / 2,
|
||||
max(-sun_dir.z, 0)
|
||||
);
|
||||
}
|
||||
|
||||
vec3 get_moon_color(/*vec3 moon_dir*/) {
|
||||
return vec3(0.05, 0.05, 0.6);
|
||||
}
|
||||
@ -204,8 +239,8 @@ float get_sun_diffuse2(DirectionalLight sun_info, DirectionalLight moon_info, ve
|
||||
// float sun_shadow = 1.0;
|
||||
// float moon_shadow = 1.0;
|
||||
// #endif
|
||||
float sun_shadow = sun_info.shadow;
|
||||
float moon_shadow = moon_info.shadow;
|
||||
float sun_shadow = sun_info.shadow * cloud_shadow(wpos, sun_dir);
|
||||
float moon_shadow = moon_info.shadow * cloud_shadow(wpos, moon_dir);
|
||||
|
||||
// https://en.m.wikipedia.org/wiki/Diffuse_sky_radiation
|
||||
//
|
||||
@ -356,14 +391,7 @@ float is_star_at(vec3 dir) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float quality, bool with_stars, float refractionIndex, out vec4 clouds) {
|
||||
#if (CLOUD_MODE == CLOUD_MODE_NONE)
|
||||
const bool has_clouds = false;
|
||||
#elif (CLOUD_MODE == CLOUD_MODE_REGULAR)
|
||||
const bool has_clouds = true;
|
||||
#endif
|
||||
|
||||
if (with_stars || has_clouds) {
|
||||
vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float quality, bool with_features, float refractionIndex) {
|
||||
// Sky color
|
||||
/* vec3 sun_dir = get_sun_dir(time_of_day);
|
||||
vec3 moon_dir = get_moon_dir(time_of_day); */
|
||||
@ -375,7 +403,7 @@ vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float q
|
||||
|
||||
// Add white dots for stars. Note these flicker and jump due to FXAA
|
||||
float star = 0.0;
|
||||
if (with_stars) {
|
||||
if (with_features) {
|
||||
vec3 star_dir = normalize(sun_dir * dir.z + cross(sun_dir, vec3(0, 1, 0)) * dir.x + vec3(0, 1, 0) * dir.y);
|
||||
star = is_star_at(star_dir);
|
||||
}
|
||||
@ -386,20 +414,26 @@ vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float q
|
||||
vec3 sun_halo_color = mix(
|
||||
SUN_HALO_DUSK,
|
||||
SUN_HALO_DAY,
|
||||
max(-sun_dir.z, 0)
|
||||
max(-sun_dir.z, 0.0)
|
||||
);
|
||||
|
||||
vec3 sun_halo = pow(max(dot(dir, -sun_dir) + 0.1, 0.0), 8.0) * sun_halo_color;
|
||||
vec3 sun_surf = pow(max(dot(dir, -sun_dir) - 0.001, 0.0), 3000.0) * SUN_SURF_COLOR * SUN_COLOR_FACTOR;
|
||||
vec3 sun_light = (sun_halo + sun_surf) * clamp(dir.z * 10.0, 0, 1);
|
||||
vec3 sun_surf = vec3(0);
|
||||
if (with_features) {
|
||||
sun_surf = pow(max(dot(dir, -sun_dir) - 0.001, 0.0), 5000.0) * SUN_SURF_COLOR * SUN_COLOR_FACTOR; // Hack to prevent sun vanishing too early
|
||||
}
|
||||
vec3 sun_light = sun_halo + sun_surf;
|
||||
|
||||
// Moon
|
||||
const vec3 MOON_SURF_COLOR = vec3(0.7, 1.0, 1.5) * 500.0;
|
||||
const vec3 MOON_HALO_COLOR = vec3(0.015, 0.015, 0.05);
|
||||
|
||||
vec3 moon_halo = pow(max(dot(dir, -moon_dir) + 0.1, 0.0), 8.0) * MOON_HALO_COLOR;
|
||||
vec3 moon_surf = pow(max(dot(dir, -moon_dir) - 0.001, 0.0), 3000.0) * MOON_SURF_COLOR;
|
||||
vec3 moon_light = clamp(moon_halo + moon_surf, vec3(0), vec3(max(dir.z * 3.0, 0)));
|
||||
vec3 moon_surf = vec3(0);
|
||||
if (with_features) {
|
||||
moon_surf = pow(max(dot(dir, -moon_dir) - 0.001, 0.0), 5000.0) * MOON_SURF_COLOR; // Hack to prevent moon vanishing too early
|
||||
}
|
||||
vec3 moon_light = moon_halo + moon_surf;
|
||||
|
||||
// Replaced all clamp(sun_dir, 0, 1) with max(sun_dir, 0) because sun_dir is calculated from sin and cos, which are never > 1
|
||||
|
||||
@ -445,26 +479,14 @@ vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float q
|
||||
// Approximate distance to fragment
|
||||
float f_dist = distance(origin, f_pos);
|
||||
|
||||
// Clouds
|
||||
#if (CLOUD_MODE == CLOUD_MODE_NONE)
|
||||
clouds = vec4(0.0);
|
||||
#elif (CLOUD_MODE == CLOUD_MODE_REGULAR)
|
||||
clouds = get_cloud_color(dir, origin, time_of_day, f_dist, quality);
|
||||
clouds.rgb *= get_sun_brightness(/*sun_dir*/) * (sun_halo * 1.5 + get_sun_color(/*sun_dir*/)) + get_moon_brightness(/*moon_dir*/) * (moon_halo * 80.0 + get_moon_color(/*moon_dir*/) + 0.25);
|
||||
#endif
|
||||
|
||||
if (f_dist > 5000.0) {
|
||||
sky_color += sun_light + moon_light;
|
||||
}
|
||||
return mix(sky_color, clouds.rgb, clouds.a);
|
||||
} else {
|
||||
clouds = vec4(0.0);
|
||||
return vec3(0.0);
|
||||
}
|
||||
return sky_color;
|
||||
}
|
||||
|
||||
vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float quality, bool with_stars, out vec4 clouds) {
|
||||
return get_sky_color(dir, time_of_day, origin, f_pos, quality, with_stars, 1.0, clouds);
|
||||
vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float quality, bool with_stars) {
|
||||
return get_sky_color(dir, time_of_day, origin, f_pos, quality, with_stars, 1.0);
|
||||
}
|
||||
|
||||
float fog(vec3 f_pos, vec3 focus_pos, uint medium) {
|
||||
|
@ -446,7 +446,7 @@ void main() {
|
||||
voxel_norm = normalize(mix(voxel_norm, lerpy_norm, clamp(my_norm.z * my_norm.z - (1.0 - DIST), 0, 1) / DIST));
|
||||
|
||||
f_pos.xyz += abs(voxel_norm) * delta_sides;
|
||||
voxel_norm = voxel_norm == vec3(0.0) ? f_norm : voxel_norm;
|
||||
voxel_norm = mix(voxel_norm == vec3(0.0) ? f_norm : voxel_norm, my_norm, clamp((f_orig_len - view_distance.x) / 3500, 0, 1));
|
||||
|
||||
vec3 hash_pos = f_pos + focus_off.xyz;
|
||||
const float A = 0.055;
|
||||
@ -555,7 +555,9 @@ void main() {
|
||||
// vec3 light, diffuse_light, ambient_light;
|
||||
// get_sun_diffuse(f_norm, time_of_day.x, cam_to_frag, (0.25 * shade_frac + 0.25 * light_frac) * f_col, 0.5 * shade_frac * f_col, 0.5 * shade_frac * /*vec3(1.0)*/f_col, 2.0, emitted_light, reflected_light);
|
||||
float max_light = 0.0;
|
||||
max_light += get_sun_diffuse2(sun_info, moon_info, voxel_norm/*l_norm*/, view_dir, f_pos, vec3(0.0), cam_attenuation, fluid_alt, vec3(1.0)/* * (0.5 * light_frac + vec3(0.5 * shade_frac))*/, vec3(1.0), /*0.5 * shade_frac * *//*vec3(1.0)*//*f_col*/vec3(R_s), alpha, voxel_norm, dist_lerp/*max(distance(focus_pos.xy, f_pos.xyz) - view_distance.x, 0.0) / 1000 < 1.0*/, emitted_light, reflected_light);
|
||||
vec3 k_a = vec3(1.0);
|
||||
vec3 k_d = vec3(1.0);
|
||||
max_light += get_sun_diffuse2(sun_info, moon_info, voxel_norm/*l_norm*/, view_dir, f_pos, vec3(0.0), cam_attenuation, fluid_alt, k_a/* * (0.5 * light_frac + vec3(0.5 * shade_frac))*/, k_d, /*0.5 * shade_frac * *//*vec3(1.0)*//*f_col*/vec3(R_s), alpha, voxel_norm, dist_lerp/*max(distance(focus_pos.xy, f_pos.xyz) - view_distance.x, 0.0) / 1000 < 1.0*/, emitted_light, reflected_light);
|
||||
// emitted_light = vec3(1.0);
|
||||
// emitted_light *= max(shade_frac, MIN_SHADOW);
|
||||
// reflected_light *= shade_frac;
|
||||
@ -614,20 +616,10 @@ void main() {
|
||||
// f_col = f_col + (hash(vec4(floor(vec3(focus_pos.xy + splay(v_pos_orig), f_pos.z)) * 3.0 - round(f_norm) * 0.5, 0)) - 0.5) * 0.05; // Small-scale noise
|
||||
vec3 surf_color = /*illuminate(emitted_light, reflected_light)*/illuminate(max_light, view_dir, f_col * emitted_light, f_col * reflected_light);
|
||||
|
||||
float fog_level = fog(f_pos.xyz, focus_pos.xyz, medium.x);
|
||||
|
||||
#if (CLOUD_MODE == CLOUD_MODE_REGULAR)
|
||||
vec4 clouds;
|
||||
vec3 fog_color = get_sky_color(cam_to_frag/*view_dir*/, time_of_day.x, cam_pos.xyz, f_pos, 1.0, /*true*/false, clouds);
|
||||
vec3 color = mix(mix(surf_color, fog_color, fog_level), clouds.rgb, clouds.a);
|
||||
#elif (CLOUD_MODE == CLOUD_MODE_NONE)
|
||||
vec3 color = surf_color;
|
||||
#endif
|
||||
|
||||
// float mist_factor = max(1 - (f_pos.z + (texture(t_noise, f_pos.xy * 0.0005 + time_of_day.x * 0.0003).x - 0.5) * 128.0) / 400.0, 0.0);
|
||||
// //float mist_factor = f_norm.z * 2.0;
|
||||
// color = mix(color, vec3(1.0) * /*diffuse_light*/reflected_light, clamp(mist_factor * 0.00005 * distance(f_pos.xy, focus_pos.xy), 0, 0.3));
|
||||
// color = surf_color;
|
||||
|
||||
tgt_color = vec4(color, 1.0);
|
||||
tgt_color = vec4(surf_color, 1.0);
|
||||
}
|
||||
|
@ -77,14 +77,5 @@ void main() {
|
||||
|
||||
surf_color = illuminate(max_light, view_dir, surf_color * emitted_light, surf_color * reflected_light);
|
||||
|
||||
#if (CLOUD_MODE == CLOUD_MODE_REGULAR)
|
||||
float fog_level = fog(f_pos.xyz, focus_pos.xyz, medium.x);
|
||||
vec4 clouds;
|
||||
vec3 fog_color = get_sky_color(cam_to_frag, time_of_day.x, cam_pos.xyz, f_pos, 0.5, false, clouds);
|
||||
vec3 color = mix(mix(surf_color, fog_color, fog_level), clouds.rgb, clouds.a);
|
||||
#elif (CLOUD_MODE == CLOUD_MODE_NONE)
|
||||
vec3 color = surf_color;
|
||||
#endif
|
||||
|
||||
tgt_color = vec4(color, f_col.a);
|
||||
tgt_color = vec4(surf_color, f_col.a);
|
||||
}
|
||||
|
@ -20,12 +20,16 @@
|
||||
// Note: The sampler uniform is declared here because it differs for MSAA
|
||||
#include <anti-aliasing.glsl>
|
||||
#include <srgb.glsl>
|
||||
#include <cloud.glsl>
|
||||
|
||||
uniform sampler2D src_depth;
|
||||
|
||||
in vec2 f_pos;
|
||||
|
||||
layout (std140)
|
||||
uniform u_locals {
|
||||
vec4 nul;
|
||||
mat4 proj_mat_inv;
|
||||
mat4 view_mat_inv;
|
||||
};
|
||||
|
||||
out vec4 tgt_color;
|
||||
@ -46,7 +50,7 @@ vec3 hsv2rgb(vec3 c) {
|
||||
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
|
||||
}
|
||||
|
||||
vec3 illuminate(float max_light, vec3 view_dir, /*vec3 max_light, */vec3 emitted, vec3 reflected) {
|
||||
vec3 _illuminate(float max_light, vec3 view_dir, /*vec3 max_light, */vec3 emitted, vec3 reflected) {
|
||||
const float NIGHT_EXPOSURE = 10.0;
|
||||
const float DUSK_EXPOSURE = 2.0;//0.8;
|
||||
const float DAY_EXPOSURE = 1.0;//0.7;
|
||||
@ -141,6 +145,28 @@ vec3 illuminate(float max_light, vec3 view_dir, /*vec3 max_light, */vec3 emitted
|
||||
// return /*srgb_to_linear*/(/*0.5*//*0.125 * */vec3(pow(color.x, gamma), pow(color.y, gamma), pow(color.z, gamma)));
|
||||
}
|
||||
|
||||
float depth_at(vec2 uv) {
|
||||
float buf_depth = texture(src_depth, uv).x;
|
||||
vec4 clip_space = vec4(uv * 2.0 - 1.0, buf_depth, 1.0);
|
||||
vec4 view_space = proj_mat_inv * clip_space;
|
||||
view_space /= view_space.w;
|
||||
return -view_space.z;
|
||||
}
|
||||
|
||||
vec3 wpos_at(vec2 uv) {
|
||||
float buf_depth = texture(src_depth, uv).x * 2.0 - 1.0;
|
||||
mat4 inv = view_mat_inv * proj_mat_inv;//inverse(all_mat);
|
||||
vec4 clip_space = vec4(uv * 2.0 - 1.0, buf_depth, 1.0);
|
||||
vec4 view_space = inv * clip_space;
|
||||
view_space /= view_space.w;
|
||||
if (buf_depth == 1.0) {
|
||||
vec3 direction = normalize(view_space.xyz);
|
||||
return direction.xyz * 100000.0 + cam_pos.xyz;
|
||||
} else {
|
||||
return view_space.xyz;
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 uv = (f_pos + 1.0) * 0.5;
|
||||
|
||||
@ -176,6 +202,30 @@ void main() {
|
||||
|
||||
vec4 aa_color = aa_apply(src_color, uv * screen_res.xy, screen_res.xy);
|
||||
|
||||
// Apply clouds to `aa_color`
|
||||
#if (CLOUD_MODE != CLOUD_MODE_NONE)
|
||||
vec3 wpos = wpos_at(uv);
|
||||
float dist = distance(wpos, cam_pos.xyz);
|
||||
vec3 dir = (wpos - cam_pos.xyz) / dist;
|
||||
|
||||
aa_color.rgb = get_cloud_color(aa_color.rgb, dir, cam_pos.xyz, time_of_day.x, dist, 1.0);
|
||||
#endif
|
||||
|
||||
// aa_color.rgb = (wpos + focus_off.xyz) / vec3(32768, 32768, /*view_distance.w*/2048);
|
||||
// aa_color.rgb = mod((wpos + focus_off.xyz), vec3(32768, 32768, view_distance.w)) / vec3(32768, 32768, view_distance.w);// / vec3(32768, 32768, view_distance.w);
|
||||
// aa_color.rgb = mod((wpos + focus_off.xyz), vec3(32, 32, 16)) / vec3(32, 32, 16);// / vec3(32768, 32768, view_distance.w);
|
||||
// aa_color.rgb = focus_off.xyz / vec3(32768, 32768, view_distance.w);
|
||||
|
||||
/* aa_color.rgb = wpos / 10000.0; */
|
||||
|
||||
/* aa_color.rgb = vec3((texture(src_depth, uv).x - 0.99) * 100.0); */
|
||||
|
||||
/* aa_color.rgb = vec3((dist - 100000) / 300000.0, 1, 1); */
|
||||
|
||||
/* vec3 scatter_color = get_sun_color() * get_sun_brightness() + get_moon_color() * get_moon_brightness(); */
|
||||
|
||||
/* aa_color.rgb += cloud_color.rgb * scatter_color;//mix(aa_color, vec4(cloud_color.rgb * scatter_color, 1), cloud_color.a); */
|
||||
|
||||
// aa_color.rgb = illuminate(1.0 - 1.0 / (1.0 + bright_color), normalize(cam_pos.xyz - focus_pos.xyz), /*vec3 max_light, */vec3(0.0), aa_color.rgb);
|
||||
|
||||
//vec4 hsva_color = vec4(rgb2hsv(fxaa_color.rgb), fxaa_color.a);
|
||||
|
@ -20,11 +20,6 @@
|
||||
|
||||
in vec2 v_pos;
|
||||
|
||||
layout (std140)
|
||||
uniform u_locals {
|
||||
vec4 nul;
|
||||
};
|
||||
|
||||
out vec2 f_pos;
|
||||
|
||||
void main() {
|
||||
|
@ -32,7 +32,6 @@ out vec4 tgt_color;
|
||||
void main() {
|
||||
// tgt_color = vec4(MU_SCATTER, 1.0);
|
||||
// return;
|
||||
vec4 _clouds;
|
||||
|
||||
vec3 cam_dir = normalize(f_pos - cam_pos.xyz);
|
||||
|
||||
@ -59,5 +58,5 @@ void main() {
|
||||
} */
|
||||
vec3 wpos = cam_pos.xyz + /*normalize(f_pos)*/cam_dir * dist;
|
||||
|
||||
tgt_color = vec4(cam_attenuation * get_sky_color(normalize(f_pos), time_of_day.x, cam_pos.xyz, wpos, 1.0, true, refractionIndex, _clouds), 1.0);
|
||||
tgt_color = vec4(cam_attenuation * get_sky_color(normalize(f_pos), time_of_day.x, cam_pos.xyz, wpos, 1.0, true, refractionIndex), 1.0);
|
||||
}
|
||||
|
@ -185,15 +185,6 @@ void main() {
|
||||
surf_color = illuminate(max_light, view_dir, surf_color * emitted_light, surf_color * reflected_light) * f_light;
|
||||
// vec3 surf_color = illuminate(f_col, light, diffuse_light, ambient_light);
|
||||
|
||||
#if (CLOUD_MODE == CLOUD_MODE_REGULAR)
|
||||
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.5, false, clouds);
|
||||
vec3 color = mix(mix(surf_color, fog_color, fog_level), clouds.rgb, clouds.a);
|
||||
#elif (CLOUD_MODE == CLOUD_MODE_NONE)
|
||||
vec3 color = surf_color;
|
||||
#endif
|
||||
|
||||
// tgt_color = vec4(color, 1.0);
|
||||
tgt_color = vec4(color, 1.0 - clamp((distance(focus_pos.xy, f_pos.xy) - (sprite_render_distance - FADE_DIST)) / FADE_DIST, 0, 1));
|
||||
tgt_color = vec4(surf_color, 1.0 - clamp((distance(focus_pos.xy, f_pos.xy) - (sprite_render_distance - FADE_DIST)) / FADE_DIST, 0, 1));
|
||||
}
|
||||
|
@ -360,14 +360,5 @@ void main() {
|
||||
// vec3 col = /*srgb_to_linear*/(f_col + hash(vec4(floor(f_pos * 3.0 - f_norm * 0.5), 0)) * 0.01); // Small-scale noise
|
||||
vec3 surf_color = illuminate(max_light, view_dir, col * emitted_light, col * reflected_light);
|
||||
|
||||
#if (CLOUD_MODE == CLOUD_MODE_REGULAR)
|
||||
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, 1.0, false, clouds);
|
||||
vec3 color = mix(mix(surf_color, fog_color, fog_level), clouds.rgb, clouds.a);
|
||||
#elif (CLOUD_MODE == CLOUD_MODE_NONE)
|
||||
vec3 color = surf_color;
|
||||
#endif
|
||||
|
||||
tgt_color = vec4(color, 1.0);
|
||||
tgt_color = vec4(surf_color, 1.0);
|
||||
}
|
||||
|
@ -2052,12 +2052,27 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.cloud_mode_text, ui);
|
||||
|
||||
let mode_list = [CloudMode::None, CloudMode::Regular];
|
||||
let mode_list = [
|
||||
CloudMode::None,
|
||||
CloudMode::Minimal,
|
||||
CloudMode::Low,
|
||||
CloudMode::Medium,
|
||||
CloudMode::High,
|
||||
];
|
||||
let mode_label_list = [
|
||||
&self.localized_strings.get("common.none"),
|
||||
&self
|
||||
.localized_strings
|
||||
.get("hud.settings.cloud_rendering_mode.regular"),
|
||||
.get("hud.settings.cloud_rendering_mode.minimal"),
|
||||
&self
|
||||
.localized_strings
|
||||
.get("hud.settings.cloud_rendering_mode.low"),
|
||||
&self
|
||||
.localized_strings
|
||||
.get("hud.settings.cloud_rendering_mode.medium"),
|
||||
&self
|
||||
.localized_strings
|
||||
.get("hud.settings.cloud_rendering_mode.high"),
|
||||
];
|
||||
|
||||
// Get which cloud rendering mode is currently active
|
||||
|
@ -137,11 +137,14 @@ pub enum CloudMode {
|
||||
/// *every* fragment shader. For machines that can't optimize the check,
|
||||
/// this is absurdly expensive, so we should look at alternatives in the
|
||||
/// future that player better with the GPU.
|
||||
Regular,
|
||||
Minimal,
|
||||
Low,
|
||||
Medium,
|
||||
High,
|
||||
}
|
||||
|
||||
impl Default for CloudMode {
|
||||
fn default() -> Self { CloudMode::Regular }
|
||||
fn default() -> Self { CloudMode::Medium }
|
||||
}
|
||||
|
||||
/// Fluid modes
|
||||
|
@ -71,7 +71,7 @@ gfx_defines! {
|
||||
light_shadows: gfx::ConstantBuffer<shadow::Locals> = "u_light_shadows",
|
||||
|
||||
tgt_color: gfx::BlendTarget<TgtColorFmt> = ("tgt_color", ColorMask::all(), gfx::preset::blend::ALPHA),
|
||||
tgt_depth_stencil: gfx::DepthTarget<TgtDepthStencilFmt> = gfx::preset::depth::LESS_EQUAL_WRITE,
|
||||
tgt_depth_stencil: gfx::DepthTarget<TgtDepthStencilFmt> = gfx::preset::depth::LESS_EQUAL_TEST,
|
||||
// tgt_depth_stencil: gfx::DepthStencilTarget<TgtDepthStencilFmt> = (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff,(StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))),
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,12 @@
|
||||
use super::{
|
||||
super::{Mesh, Pipeline, Tri, WinColorFmt, WinDepthFmt},
|
||||
super::{Mesh, Pipeline, TgtColorFmt, TgtDepthStencilFmt, Tri, WinColorFmt},
|
||||
Globals,
|
||||
};
|
||||
use gfx::{
|
||||
self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta, gfx_pipeline,
|
||||
gfx_pipeline_inner, gfx_vertex_struct_meta,
|
||||
};
|
||||
use vek::*;
|
||||
|
||||
gfx_defines! {
|
||||
vertex Vertex {
|
||||
@ -13,7 +14,8 @@ gfx_defines! {
|
||||
}
|
||||
|
||||
constant Locals {
|
||||
nul: [f32; 4] = "nul",
|
||||
proj_mat_inv: [[f32; 4]; 4] = "proj_mat_inv",
|
||||
view_mat_inv: [[f32; 4]; 4] = "view_mat_inv",
|
||||
}
|
||||
|
||||
pipeline pipe {
|
||||
@ -22,15 +24,30 @@ gfx_defines! {
|
||||
locals: gfx::ConstantBuffer<Locals> = "u_locals",
|
||||
globals: gfx::ConstantBuffer<Globals> = "u_globals",
|
||||
|
||||
src_sampler: gfx::TextureSampler<<WinColorFmt as gfx::format::Formatted>::View> = "src_color",
|
||||
map: gfx::TextureSampler<[f32; 4]> = "t_map",
|
||||
alt: gfx::TextureSampler<[f32; 2]> = "t_alt",
|
||||
horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon",
|
||||
|
||||
color_sampler: gfx::TextureSampler<<TgtColorFmt as gfx::format::Formatted>::View> = "src_color",
|
||||
depth_sampler: gfx::TextureSampler<<TgtDepthStencilFmt as gfx::format::Formatted>::View> = "src_depth",
|
||||
|
||||
noise: gfx::TextureSampler<f32> = "t_noise",
|
||||
|
||||
tgt_color: gfx::RenderTarget<WinColorFmt> = "tgt_color",
|
||||
tgt_depth: gfx::DepthTarget<WinDepthFmt> = gfx::preset::depth::PASS_TEST,
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Locals {
|
||||
fn default() -> Self { Self::new(Mat4::identity(), Mat4::identity()) }
|
||||
}
|
||||
|
||||
impl Locals {
|
||||
pub fn default() -> Self { Self { nul: [0.0; 4] } }
|
||||
pub fn new(proj_mat_inv: Mat4<f32>, view_mat_inv: Mat4<f32>) -> Self {
|
||||
Self {
|
||||
proj_mat_inv: proj_mat_inv.into_col_arrays(),
|
||||
view_mat_inv: view_mat_inv.into_col_arrays(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PostProcessPipeline;
|
||||
|
@ -83,6 +83,12 @@ pub type TgtColorRes = gfx::handle::ShaderResourceView<
|
||||
<TgtColorFmt as gfx::format::Formatted>::View,
|
||||
>;
|
||||
|
||||
/// A handle to a render depth target as a resource.
|
||||
pub type TgtDepthRes = gfx::handle::ShaderResourceView<
|
||||
gfx_backend::Resources,
|
||||
<TgtDepthStencilFmt as gfx::format::Formatted>::View,
|
||||
>;
|
||||
|
||||
/// A handle to a greedy meshed color-light texture as a resource.
|
||||
pub type ColLightRes = gfx::handle::ShaderResourceView<
|
||||
gfx_backend::Resources,
|
||||
@ -144,6 +150,7 @@ pub struct Renderer {
|
||||
tgt_depth_stencil_view: TgtDepthStencilView,
|
||||
|
||||
tgt_color_res: TgtColorRes,
|
||||
tgt_depth_res: TgtDepthRes,
|
||||
|
||||
sampler: Sampler<gfx_backend::Resources>,
|
||||
|
||||
@ -218,7 +225,7 @@ impl Renderer {
|
||||
&mut shader_reload_indicator,
|
||||
)?;
|
||||
|
||||
let (tgt_color_view, tgt_depth_stencil_view, tgt_color_res) =
|
||||
let (tgt_color_view, tgt_depth_stencil_view, tgt_color_res, tgt_depth_res) =
|
||||
Self::create_rt_views(&mut factory, (dims.0, dims.1), &mode)?;
|
||||
|
||||
let shadow_map = if let (
|
||||
@ -281,6 +288,7 @@ impl Renderer {
|
||||
tgt_depth_stencil_view,
|
||||
|
||||
tgt_color_res,
|
||||
tgt_depth_res,
|
||||
|
||||
sampler,
|
||||
|
||||
@ -355,9 +363,10 @@ impl Renderer {
|
||||
|
||||
// Avoid panics when creating texture with w,h of 0,0.
|
||||
if dims.0 != 0 && dims.1 != 0 {
|
||||
let (tgt_color_view, tgt_depth_stencil_view, tgt_color_res) =
|
||||
let (tgt_color_view, tgt_depth_stencil_view, tgt_color_res, tgt_depth_res) =
|
||||
Self::create_rt_views(&mut self.factory, (dims.0, dims.1), &self.mode)?;
|
||||
self.tgt_color_res = tgt_color_res;
|
||||
self.tgt_depth_res = tgt_depth_res;
|
||||
self.tgt_color_view = tgt_color_view;
|
||||
self.tgt_depth_stencil_view = tgt_depth_stencil_view;
|
||||
if let (Some(shadow_map), ShadowMode::Map(mode)) =
|
||||
@ -394,7 +403,7 @@ impl Renderer {
|
||||
factory: &mut gfx_device_gl::Factory,
|
||||
size: (u16, u16),
|
||||
mode: &RenderMode,
|
||||
) -> Result<(TgtColorView, TgtDepthStencilView, TgtColorRes), RenderError> {
|
||||
) -> Result<(TgtColorView, TgtDepthStencilView, TgtColorRes, TgtDepthRes), RenderError> {
|
||||
let kind = match mode.aa {
|
||||
AaMode::None | AaMode::Fxaa => {
|
||||
gfx::texture::Kind::D2(size.0, size.1, gfx::texture::AaMode::Single)
|
||||
@ -435,14 +444,24 @@ impl Renderer {
|
||||
let tgt_depth_stencil_tex = factory.create_texture(
|
||||
kind,
|
||||
levels,
|
||||
gfx::memory::Bind::DEPTH_STENCIL,
|
||||
gfx::memory::Bind::SHADER_RESOURCE | gfx::memory::Bind::DEPTH_STENCIL,
|
||||
gfx::memory::Usage::Data,
|
||||
Some(depth_stencil_cty),
|
||||
)?;
|
||||
let tgt_depth_res = factory.view_texture_as_shader_resource::<TgtDepthStencilFmt>(
|
||||
&tgt_depth_stencil_tex,
|
||||
(0, levels - 1),
|
||||
gfx::format::Swizzle::new(),
|
||||
)?;
|
||||
let tgt_depth_stencil_view =
|
||||
factory.view_texture_as_depth_stencil_trivial(&tgt_depth_stencil_tex)?;
|
||||
|
||||
Ok((tgt_color_view, tgt_depth_stencil_view, tgt_color_res))
|
||||
Ok((
|
||||
tgt_color_view,
|
||||
tgt_depth_stencil_view,
|
||||
tgt_color_res,
|
||||
tgt_depth_res,
|
||||
))
|
||||
}
|
||||
|
||||
/// Create textures and views for shadow maps.
|
||||
@ -1629,6 +1648,7 @@ impl Renderer {
|
||||
model: &Model<postprocess::PostProcessPipeline>,
|
||||
globals: &Consts<Globals>,
|
||||
locals: &Consts<postprocess::Locals>,
|
||||
lod: &lod_terrain::LodData,
|
||||
) {
|
||||
self.encoder.draw(
|
||||
&gfx::Slice {
|
||||
@ -1643,9 +1663,13 @@ impl Renderer {
|
||||
vbuf: model.vbuf.clone(),
|
||||
locals: locals.buf.clone(),
|
||||
globals: globals.buf.clone(),
|
||||
src_sampler: (self.tgt_color_res.clone(), self.sampler.clone()),
|
||||
map: (lod.map.srv.clone(), lod.map.sampler.clone()),
|
||||
alt: (lod.alt.srv.clone(), lod.alt.sampler.clone()),
|
||||
horizon: (lod.horizon.srv.clone(), lod.horizon.sampler.clone()),
|
||||
color_sampler: (self.tgt_color_res.clone(), self.sampler.clone()),
|
||||
depth_sampler: (self.tgt_depth_res.clone(), self.sampler.clone()),
|
||||
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
|
||||
tgt_color: self.win_color_view.clone(),
|
||||
tgt_depth: self.win_depth_view.clone(),
|
||||
},
|
||||
)
|
||||
}
|
||||
@ -1715,12 +1739,15 @@ fn create_pipelines(
|
||||
},
|
||||
match mode.cloud {
|
||||
CloudMode::None => "CLOUD_MODE_NONE",
|
||||
CloudMode::Regular => "CLOUD_MODE_REGULAR",
|
||||
CloudMode::Minimal => "CLOUD_MODE_MINIMAL",
|
||||
CloudMode::Low => "CLOUD_MODE_LOW",
|
||||
CloudMode::Medium => "CLOUD_MODE_MEDIUM",
|
||||
CloudMode::High => "CLOUD_MODE_HIGH",
|
||||
},
|
||||
match mode.lighting {
|
||||
LightingMode::Ashikhmin => "LIGHTING_ALGORITHM_ASHIKHMIN",
|
||||
LightingMode::BlinnPhong => "LIGHTING_ALGORITHM_BLINN_PHONG",
|
||||
LightingMode::Lambertian => "CLOUD_MODE_NONE",
|
||||
LightingMode::Lambertian => "LIGHTING_ALGORITHM_LAMBERTIAN",
|
||||
},
|
||||
match mode.shadow {
|
||||
ShadowMode::None => "SHADOW_MODE_NONE",
|
||||
@ -1745,7 +1772,7 @@ fn create_pipelines(
|
||||
let cloud = Glsl::load_watched(
|
||||
&["voxygen.shaders.include.cloud.", match mode.cloud {
|
||||
CloudMode::None => "none",
|
||||
CloudMode::Regular => "regular",
|
||||
_ => "regular",
|
||||
}]
|
||||
.concat(),
|
||||
shader_reload_indicator,
|
||||
|
@ -27,7 +27,9 @@ impl Default for CameraMode {
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Dependents {
|
||||
pub view_mat: Mat4<f32>,
|
||||
pub view_mat_inv: Mat4<f32>,
|
||||
pub proj_mat: Mat4<f32>,
|
||||
pub proj_mat_inv: Mat4<f32>,
|
||||
pub cam_pos: Vec3<f32>,
|
||||
pub cam_dir: Vec3<f32>,
|
||||
}
|
||||
@ -67,7 +69,9 @@ impl Camera {
|
||||
|
||||
dependents: Dependents {
|
||||
view_mat: Mat4::identity(),
|
||||
view_mat_inv: Mat4::identity(),
|
||||
proj_mat: Mat4::identity(),
|
||||
proj_mat_inv: Mat4::identity(),
|
||||
cam_pos: Vec3::zero(),
|
||||
cam_dir: Vec3::unit_y(),
|
||||
},
|
||||
@ -112,9 +116,11 @@ impl Camera {
|
||||
* Mat4::rotation_y(self.ori.x)
|
||||
* Mat4::rotation_3d(PI / 2.0, -Vec4::unit_x())
|
||||
* Mat4::translation_3d(-self.focus.map(|e| e.fract()));
|
||||
self.dependents.view_mat_inv = self.dependents.view_mat.inverted();
|
||||
|
||||
self.dependents.proj_mat =
|
||||
Mat4::perspective_rh_no(self.fov, self.aspect, NEAR_PLANE, FAR_PLANE);
|
||||
self.dependents.proj_mat_inv = self.dependents.proj_mat.inverted();
|
||||
|
||||
// TODO: Make this more efficient.
|
||||
self.dependents.cam_pos = Vec3::from(self.dependents.view_mat.inverted() * Vec4::unit_w());
|
||||
|
@ -523,7 +523,9 @@ impl Scene {
|
||||
self.camera.compute_dependents(&*scene_data.state.terrain());
|
||||
let camera::Dependents {
|
||||
view_mat,
|
||||
view_mat_inv,
|
||||
proj_mat,
|
||||
proj_mat_inv,
|
||||
cam_pos,
|
||||
..
|
||||
} = self.camera.dependents();
|
||||
@ -662,6 +664,12 @@ impl Scene {
|
||||
scene_data.sprite_render_distance as f32 - 20.0,
|
||||
)])
|
||||
.expect("Failed to update global constants");
|
||||
renderer
|
||||
.update_consts(&mut self.postprocess.locals, &[PostProcessLocals::new(
|
||||
proj_mat_inv,
|
||||
view_mat_inv,
|
||||
)])
|
||||
.expect("Failed to update post-process locals");
|
||||
|
||||
// Maintain LoD.
|
||||
self.lod.maintain(renderer);
|
||||
@ -1071,6 +1079,7 @@ impl Scene {
|
||||
&self.postprocess.model,
|
||||
&global.globals,
|
||||
&self.postprocess.locals,
|
||||
self.lod.get_data(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -380,6 +380,7 @@ impl Scene {
|
||||
&self.postprocess.model,
|
||||
&self.data.globals,
|
||||
&self.postprocess.locals,
|
||||
&self.lod,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user