Shader optimisations

This commit is contained in:
Joshua Barretto 2020-01-21 12:57:59 +00:00
parent bf1b2d96f5
commit 8e7a8aa4f9
9 changed files with 44 additions and 61 deletions

View File

@ -42,6 +42,6 @@ void main() {
vec4(v_norm, 0.0)
).xyz);
gl_Position = proj_mat * view_mat * vec4(f_pos, 1);
gl_Position = all_mat * vec4(f_pos, 1);
gl_Position.z = 1.0 / (1.0 - gl_Position.z - 10.0);
}

View File

@ -38,8 +38,7 @@ void main() {
f_pos_norm = v_pos_norm;
gl_Position =
proj_mat *
view_mat *
all_mat *
vec4(f_pos, 1);
gl_Position.z = 1.0 / (1.0 - gl_Position.z - 10.0);
}

View File

@ -5,36 +5,39 @@ const float CLOUD_HEIGHT_MIN = CLOUD_AVG_HEIGHT - 50.0;
const float CLOUD_HEIGHT_MAX = CLOUD_AVG_HEIGHT + 50.0;
const float CLOUD_THRESHOLD = 0.3;
const float CLOUD_SCALE = 5.0;
const float CLOUD_DENSITY = 50.0;
const float CLOUD_DENSITY = 80.0;
float vsum(vec3 v) {
return v.x + v.y + v.z;
}
vec2 cloud_at(vec3 pos) {
vec2 scaled_pos = pos.xy / CLOUD_SCALE;
float tick_offs = 0.0
+ texture(t_noise, pos.xy * 0.0001 - tick.x * 0.001).x * 0.5
+ texture(t_noise, pos.xy * 0.000003).x * 5.0;
+ texture(t_noise, scaled_pos * 0.0005 - time_of_day.x * 0.00002).x * 0.5
+ texture(t_noise, scaled_pos * 0.000015).x * 5.0;
float value = (
0.0
+ texture(t_noise, pos.xy / CLOUD_SCALE * 0.0003 + tick_offs).x
+ texture(t_noise, pos.xy / CLOUD_SCALE * 0.0009 - tick_offs).x * 0.5
+ texture(t_noise, pos.xy / CLOUD_SCALE * 0.0025 - tick.x * 0.01).x * 0.25
+ texture(t_noise, pos.xy / CLOUD_SCALE * 0.008 + tick.x * 0.02).x * 0.15
+ texture(t_noise, pos.xy / CLOUD_SCALE * 0.02 + tick_offs + tick.x * 0.02).x * 0.1
+ texture(t_noise, scaled_pos * 0.0003 + tick_offs).x
+ texture(t_noise, scaled_pos * 0.0009 - tick_offs).x * 0.5
+ texture(t_noise, scaled_pos * 0.0025 - time_of_day.x * 0.0002).x * 0.25
+ texture(t_noise, scaled_pos * 0.008 + time_of_day.x * 0.0004).x * 0.15
+ texture(t_noise, scaled_pos * 0.02 + tick_offs + time_of_day.x * 0.0004).x * 0.1
) / 3.0;
float density = max((value - CLOUD_THRESHOLD) - abs(pos.z - CLOUD_AVG_HEIGHT) / 400.0, 0.0) * CLOUD_DENSITY;
float shade = ((pos.z - CLOUD_AVG_HEIGHT) * 1.8 / (CLOUD_AVG_HEIGHT - CLOUD_HEIGHT_MIN) + 0.5);
const float SHADE_GRADIENT = 1.8 / (CLOUD_AVG_HEIGHT - CLOUD_HEIGHT_MIN);
float shade = ((pos.z - CLOUD_AVG_HEIGHT) * SHADE_GRADIENT + 0.5);
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 float INCR = 0.1;
const int ITERS = 10;
const float INCR = 1.0 / ITERS;
float mind = (CLOUD_HEIGHT_MIN - origin.z) / dir.z;
float maxd = (CLOUD_HEIGHT_MAX - origin.z) / dir.z;
@ -42,28 +45,22 @@ vec4 get_cloud_color(vec3 dir, vec3 origin, float time_of_day, float max_dist, f
float start = max(min(mind, maxd), 0.0);
float delta = min(abs(mind - maxd), max_dist);
bool do_cast = true;
if (mind < 0.0 && maxd < 0.0) {
do_cast = false;
}
float incr = INCR;
float fuzz = sin(texture(t_noise, dir.xz * 100000.0 + tick.x).x * 100.0) * incr * delta;
float fuzz = sin(texture(t_noise, dir.xz * 100000.0 + tick.x).x * 100.0) * INCR * delta * pow(maxd - mind, 0.5);
float cloud_shade = 1.0;
float passthrough = 1.0;
if (do_cast) {
for (float d = 0.0; d < 1.0; d += incr) {
float dist = start + d * delta;
dist += fuzz * pow(maxd - mind, 0.5) * 0.01 * min(pow(dist * 0.005, 2.0), 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 *= max(1.0 - integral, 0.0);
float integral = sample.y * INCR;
passthrough *= 1.0 - integral;
cloud_shade = mix(cloud_shade, sample.x, passthrough * integral);
dist += INCR * delta;
}
}

View File

@ -2,6 +2,7 @@ layout (std140)
uniform u_globals {
mat4 view_mat;
mat4 proj_mat;
mat4 all_mat;
vec4 cam_pos;
vec4 focus_pos;
vec4 view_distance;

View File

@ -66,7 +66,7 @@ float shadow_at(vec3 wpos, vec3 wnorm) {
vec3 diff = shadow_pos - wpos;
if (diff.z >= 0.0) {
diff.z = diff.z * 0.1;
diff.z = sign(diff.z) * 0.1;
}
float shade = max(pow(diff.x * diff.x + diff.y * diff.y + diff.z * diff.z, 0.25) / pow(radius * radius * 0.5, 0.25), 0.5);

View File

@ -82,33 +82,27 @@ void get_sun_diffuse(vec3 norm, float time_of_day, out vec3 light, out vec3 diff
light = sun_chroma + moon_chroma + PERSISTENT_AMBIANCE;
diffuse_light =
sun_chroma * mix(1.0, max(dot(-norm, sun_dir) * 0.6 + 0.4, 0.0), diffusion) +
moon_chroma * mix(1.0, pow(max(dot(-norm, moon_dir) * 2.0, 0.0), 2.0), diffusion) +
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);
}
// This has been extracted into a function to allow quick exit when detecting a star.
float is_star_at(vec3 dir) {
float star_scale = 30.0;
float star_scale = 80.0;
for (int i = 0; i < 2; i ++) {
for (int j = 0; j < 2; j ++) {
for (int k = 0; k < 2; k ++) {
// Star positions
vec3 pos = (floor(dir * star_scale) + vec3(i, j, k) - vec3(0.5)) / star_scale;
// Star positions
vec3 pos = (floor(dir * star_scale) - 0.5) / star_scale;
// Noisy offsets
pos += (3.0 / star_scale) * rand_perm_3(pos);
// Noisy offsets
pos += (3.0 / star_scale) * rand_perm_3(pos);
// Find distance to fragment
float dist = length(normalize(pos) - dir);
// Find distance to fragment
float dist = length(normalize(pos) - dir);
// Star threshold
if (dist < 0.0015) {
return 1.0;
}
}
}
// Star threshold
if (dist < 0.0015) {
return 1.0;
}
return 0.0;
@ -121,7 +115,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_stars && sun_dir.z > 0.0) {
star = is_star_at(dir);
}

View File

@ -50,8 +50,7 @@ void main() {
f_light = 1.0;
gl_Position =
proj_mat *
view_mat *
all_mat *
vec4(f_pos, 1);
gl_Position.z = 1.0 / (1.0 - gl_Position.z - 10.0);
}

View File

@ -18,28 +18,19 @@ out vec3 f_col;
out float f_light;
void main() {
f_pos = vec3(
float((v_pos_norm >> 0) & 0x00FFu),
float((v_pos_norm >> 8) & 0x00FFu),
float((v_pos_norm >> 16) & 0x1FFFu)
) + model_offs;
f_pos = vec3((uvec3(v_pos_norm) >> uvec3(0, 8, 16)) & uvec3(0xFFu, 0xFFu, 0x1FFFu)) + model_offs;
f_pos.z *= min(1.0001 - 0.02 / pow(tick.x - load_time, 10.0), 1.0);
f_pos.z -= 25.0 * pow(distance(focus_pos.xy, f_pos.xy) / view_distance.x, 20.0);
f_col = vec3(
float((v_col_light >> 8) & 0xFFu),
float((v_col_light >> 16) & 0xFFu),
float((v_col_light >> 24) & 0xFFu)
) / 255.0;
f_col = vec3((uvec3(v_col_light) >> uvec3(8, 16, 24)) & uvec3(0xFFu)) / 255.0;
f_light = float(v_col_light & 0xFFu) / 255.0;
f_pos_norm = v_pos_norm;
gl_Position =
proj_mat *
view_mat *
all_mat *
vec4(f_pos, 1);
gl_Position.z = 1.0 / (1.0 - gl_Position.z - 10.0);
}

View File

@ -21,6 +21,7 @@ gfx_defines! {
constant Globals {
view_mat: [[f32; 4]; 4] = "view_mat",
proj_mat: [[f32; 4]; 4] = "proj_mat",
all_mat: [[f32; 4]; 4] = "all_mat",
cam_pos: [f32; 4] = "cam_pos",
focus_pos: [f32; 4] = "focus_pos",
// TODO: Fix whatever alignment issue requires these uniforms to be aligned.
@ -62,6 +63,7 @@ impl Globals {
Self {
view_mat: arr_to_mat(view_mat.into_col_array()),
proj_mat: arr_to_mat(proj_mat.into_col_array()),
all_mat: arr_to_mat((proj_mat * view_mat).into_col_array()),
cam_pos: Vec4::from(cam_pos).into_array(),
focus_pos: Vec4::from(focus_pos).into_array(),
view_distance: [view_distance; 4],