From c07d7a212b53f055b2ff69002041180e71c7e3e0 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Tue, 17 Oct 2023 14:02:00 +0100 Subject: [PATCH] Better LoD effects, performance improvements --- assets/voxygen/lod/oak.obj | 4 +- assets/voxygen/shaders/debug-frag.glsl | 2 +- assets/voxygen/shaders/figure-frag.glsl | 2 +- assets/voxygen/shaders/figure-vert.glsl | 2 +- assets/voxygen/shaders/fluid-frag/cheap.glsl | 2 +- assets/voxygen/shaders/fluid-frag/shiny.glsl | 2 +- assets/voxygen/shaders/include/lod.glsl | 11 +- assets/voxygen/shaders/lod-object-frag.glsl | 65 +-- assets/voxygen/shaders/lod-object-vert.glsl | 2 +- assets/voxygen/shaders/lod-terrain-frag.glsl | 430 +++---------------- assets/voxygen/shaders/lod-terrain-vert.glsl | 2 +- assets/voxygen/shaders/particle-frag.glsl | 2 +- assets/voxygen/shaders/sprite-frag.glsl | 2 +- assets/voxygen/shaders/sprite-vert.glsl | 20 +- assets/voxygen/shaders/terrain-frag.glsl | 6 +- assets/voxygen/shaders/terrain-vert.glsl | 6 +- 16 files changed, 111 insertions(+), 449 deletions(-) diff --git a/assets/voxygen/lod/oak.obj b/assets/voxygen/lod/oak.obj index c4690bfb3e..a0a89bbd6e 100644 --- a/assets/voxygen/lod/oak.obj +++ b/assets/voxygen/lod/oak.obj @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:42f0f101c18836a4f7941b551eb38aba600826208509b6e6622e8bb69c647aa5 -size 10420 +oid sha256:210ac6acdb4caf3a4c5e46eb197202944f6f5477b67e3ccb9eea75e76bd55743 +size 6952 diff --git a/assets/voxygen/shaders/debug-frag.glsl b/assets/voxygen/shaders/debug-frag.glsl index 9bf191f0a7..c1c987923e 100644 --- a/assets/voxygen/shaders/debug-frag.glsl +++ b/assets/voxygen/shaders/debug-frag.glsl @@ -41,7 +41,7 @@ void main() { #endif #if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP) - vec4 f_shadow = textureBicubic(t_horizon, s_horizon, pos_to_tex(f_pos.xy)); + vec4 f_shadow = textureMaybeBicubic(t_horizon, s_horizon, pos_to_tex(f_pos.xy)); float sun_shade_frac = horizon_at2(f_shadow, f_alt, f_pos, sun_dir); #elif (SHADOW_MODE == SHADOW_MODE_NONE) float sun_shade_frac = 1.0; diff --git a/assets/voxygen/shaders/figure-frag.glsl b/assets/voxygen/shaders/figure-frag.glsl index 575fbc3dff..ac1ca1b8e1 100644 --- a/assets/voxygen/shaders/figure-frag.glsl +++ b/assets/voxygen/shaders/figure-frag.glsl @@ -145,7 +145,7 @@ void main() { #endif #if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP) - vec4 f_shadow = textureBicubic(t_horizon, s_horizon, pos_to_tex(f_pos.xy)); + vec4 f_shadow = textureMaybeBicubic(t_horizon, s_horizon, pos_to_tex(f_pos.xy)); float sun_shade_frac = horizon_at2(f_shadow, f_alt, f_pos, sun_dir); #elif (SHADOW_MODE == SHADOW_MODE_NONE) float sun_shade_frac = 1.0;//horizon_at2(f_shadow, f_alt, f_pos, sun_dir); diff --git a/assets/voxygen/shaders/figure-vert.glsl b/assets/voxygen/shaders/figure-vert.glsl index d24b299872..ff95c0b41d 100644 --- a/assets/voxygen/shaders/figure-vert.glsl +++ b/assets/voxygen/shaders/figure-vert.glsl @@ -147,7 +147,7 @@ void main() { // Also precalculate shadow texture and estimated terrain altitude. // f_alt = alt_at(f_pos.xy); - // f_shadow = textureBicubic(t_horizon, pos_to_tex(f_pos.xy)); + // f_shadow = textureMaybeBicubic(t_horizon, pos_to_tex(f_pos.xy)); gl_Position = all_mat/*shadowMats[0].shadowMatrices*/ * vec4(f_pos, 1); // gl_Position.z = -gl_Position.z / 100.0 / gl_Position.w; diff --git a/assets/voxygen/shaders/fluid-frag/cheap.glsl b/assets/voxygen/shaders/fluid-frag/cheap.glsl index 26ff677994..456dd76c19 100644 --- a/assets/voxygen/shaders/fluid-frag/cheap.glsl +++ b/assets/voxygen/shaders/fluid-frag/cheap.glsl @@ -121,7 +121,7 @@ void main() { #endif #if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP) - vec4 f_shadow = textureBicubic(t_horizon, s_horizon, pos_to_tex(f_pos.xy)); + vec4 f_shadow = textureMaybeBicubic(t_horizon, s_horizon, pos_to_tex(f_pos.xy)); float sun_shade_frac = horizon_at2(f_shadow, f_alt, f_pos, sun_dir); #elif (SHADOW_MODE == SHADOW_MODE_NONE) float sun_shade_frac = 1.0;//horizon_at2(f_shadow, f_alt, f_pos, sun_dir); diff --git a/assets/voxygen/shaders/fluid-frag/shiny.glsl b/assets/voxygen/shaders/fluid-frag/shiny.glsl index 02ab06f297..44bee8717a 100644 --- a/assets/voxygen/shaders/fluid-frag/shiny.glsl +++ b/assets/voxygen/shaders/fluid-frag/shiny.glsl @@ -258,7 +258,7 @@ void main() { /* vec3 sun_dir = get_sun_dir(time_of_day.x); vec3 moon_dir = get_moon_dir(time_of_day.x); */ #if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP) - vec4 f_shadow = textureBicubic(t_horizon, s_horizon, pos_to_tex(f_pos.xy)); + vec4 f_shadow = textureMaybeBicubic(t_horizon, s_horizon, pos_to_tex(f_pos.xy)); float sun_shade_frac = horizon_at2(f_shadow, f_alt, f_pos, sun_dir); #elif (SHADOW_MODE == SHADOW_MODE_NONE) float sun_shade_frac = 1.0;//horizon_at2(f_shadow, f_alt, f_pos, sun_dir); diff --git a/assets/voxygen/shaders/include/lod.glsl b/assets/voxygen/shaders/include/lod.glsl index 906fca341c..e6528643fc 100644 --- a/assets/voxygen/shaders/include/lod.glsl +++ b/assets/voxygen/shaders/include/lod.glsl @@ -77,6 +77,15 @@ vec4 textureBicubic(texture2D tex, sampler sampl, vec2 texCoords) { , sy); } +vec4 textureMaybeBicubic(texture2D tex, sampler sampl, vec2 texCoords) { + #if (CLOUD_MODE >= CLOUD_MODE_HIGH) + return textureBicubic(tex, sampl, texCoords); + #else + vec2 offset = (texCoords + vec2(-1.0, 0.5)) / textureSize(sampler2D(tex, sampl), 0); + return texture(sampler2D(tex, sampl), offset); + #endif +} + // 16 bit version (each of the 2 8-bit components are combined after bilinear sampling) // NOTE: We assume the sampled coordinates are already in "texture pixels". vec2 textureBicubic16(texture2D tex, sampler sampl, vec2 texCoords) { @@ -241,7 +250,7 @@ float horizon_at2(vec4 f_horizons, float alt, vec3 pos, vec4 light_dir) { } // float horizon_at(vec3 pos, /*float time_of_day*/vec3 light_dir) { -// vec4 f_horizons = textureBicubic(t_horizon, pos_to_tex(pos.xy)); +// vec4 f_horizons = textureMaybeBicubic(t_horizon, pos_to_tex(pos.xy)); // // f_horizons.xyz = /*linear_to_srgb*/(f_horizons.xyz); // float alt = alt_at_real(pos.xy); // return horizon_at2(f_horizons, alt, pos, light_dir); diff --git a/assets/voxygen/shaders/lod-object-frag.glsl b/assets/voxygen/shaders/lod-object-frag.glsl index c1990c98d2..33b991155b 100644 --- a/assets/voxygen/shaders/lod-object-frag.glsl +++ b/assets/voxygen/shaders/lod-object-frag.glsl @@ -52,7 +52,7 @@ void main() { #endif #if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP) - vec4 f_shadow = textureBicubic(t_horizon, s_horizon, pos_to_tex(f_pos.xy)); + vec4 f_shadow = textureMaybeBicubic(t_horizon, s_horizon, pos_to_tex(f_pos.xy)); float sun_shade_frac = horizon_at2(f_shadow, f_alt, f_pos, sun_dir); #elif (SHADOW_MODE == SHADOW_MODE_NONE) float sun_shade_frac = 1.0; @@ -75,60 +75,39 @@ void main() { vec3 k_d = vec3(1.0); vec3 k_s = vec3(R_s); - vec3 my_norm = vec3(f_norm.xy, abs(f_norm.z)); - vec3 voxel_norm; + // Tree trunks + if (model_pos.z < 25.0 && dot(abs(model_pos.xy), vec2(1)) < 6.0) { surf_color = vec3(0.05, 0.02, 0.0); } + + vec3 voxel_norm = f_norm; float my_alt = f_pos.z + focus_off.z; float f_ao = 1.0; const float VOXELIZE_DIST = 2000; - float voxelize_factor = clamp(1.0 - (distance(focus_pos.xy, f_pos.xy) - view_distance.x) / VOXELIZE_DIST, 0, 0.65); - vec3 cam_dir = normalize(cam_pos.xyz - f_pos.xyz); - vec3 side_norm = normalize(vec3(my_norm.xy, 0)); - vec3 top_norm = vec3(0, 0, 1); + float voxelize_factor = clamp(1.0 - (distance(focus_pos.xy, f_pos.xy) - view_distance.x) * (1.0 / VOXELIZE_DIST), 0, 1.0); + vec3 cam_dir = cam_to_frag; #ifdef EXPERIMENTAL_NOLODVOXELS f_ao = 1.0; + vec3 side_norm = normalize(vec3(f_norm.xy, 0)); + vec3 top_norm = vec3(0, 0, 1); voxel_norm = normalize(mix(side_norm, top_norm, cam_dir.z)); #else - float side_factor = 1.0 - my_norm.z; - // min(dot(vec3(0, -sign(cam_dir.y), 0), -cam_dir), dot(vec3(-sign(cam_dir.x), 0, 0), -cam_dir)) - if (max(abs(my_norm.x), abs(my_norm.y)) < 0.01 || fract(my_alt) * clamp(dot(normalize(vec3(cam_dir.xy, 0)), side_norm), 0, 1) < cam_dir.z / my_norm.z) { - f_ao *= mix(1.0, clamp(fract(my_alt) / length(my_norm.xy) + clamp(dot(side_norm, -cam_dir), 0, 1), 0, 1), voxelize_factor); - voxel_norm = top_norm; - } else { - f_ao *= mix(1.0, clamp(pow(fract(my_alt), 0.5), 0, 1), voxelize_factor); + float t = -1.5; + while (t < 1.5) { + vec3 deltas = (step(vec3(0), -cam_dir) - fract(f_pos - cam_dir * t)) / -cam_dir; + float m = min(min(deltas.x, deltas.y), deltas.z); - if (fract(f_pos.x) * abs(my_norm.y / cam_dir.x) < fract(f_pos.y) * abs(my_norm.x / cam_dir.y)) { - voxel_norm = vec3(sign(cam_dir.x), 0, 0); - } else { - voxel_norm = vec3(0, sign(cam_dir.y), 0); + t += max(m, 0.05); + + vec3 block_pos = floor(f_pos - cam_dir * t) + 0.5; + if (dot(block_pos - f_pos, -f_norm) < 0.0) { + vec3 to_center = abs(block_pos - (f_pos - cam_dir * t)); + voxel_norm = step(max(max(to_center.x, to_center.y), to_center.z), to_center) * sign(-cam_dir); + voxel_norm = mix(f_norm, voxel_norm, voxelize_factor); + f_ao = mix(1.0, clamp(1.0 + t * 1.5, 0.3, 1.0), voxelize_factor); + break; } } - f_ao = min(f_ao, max(f_norm.z * 0.5 + 0.5, 0.0)); - voxel_norm = mix(my_norm, voxel_norm == vec3(0.0) ? f_norm : voxel_norm, voxelize_factor); #endif - vec3 f_pos2 = (f_pos + focus_off.xyz) * 0.7;//; - - surf_color *= 0.7; - if (model_pos.z < 25.0 && dot(abs(model_pos.xy), vec2(1)) < 6.0) { surf_color = vec3(0.05, 0.02, 0.0); } - - float t = -1.5;// / dot(cam_dir, f_norm); - for (int i = 0; i < 6; i ++) { - vec3 deltas = (step(vec3(0), cam_dir) - fract(f_pos2 + cam_dir * t)) / cam_dir; - float m = min(min(deltas.x, deltas.y), deltas.z); - - t += max(m, 0.01); - - vec3 block_pos = floor(f_pos2 + cam_dir * t) + 0.5; - if (dot(block_pos - f_pos2, -f_norm) < 0.0) { - vec3 to_center = abs(block_pos - (f_pos2 + cam_dir * t)); - voxel_norm = step(max(max(to_center.x, to_center.y), to_center.z), to_center) * sign(cam_dir); - /* voxel_norm = f_norm; */ - voxel_norm = normalize(mix(f_norm, voxel_norm, voxelize_factor)); - f_ao = mix(1.0, clamp(1.0 + t * 1.5, 0.3, 1.0), voxelize_factor); - break; - } - } - vec3 emitted_light, reflected_light; // To account for prior saturation. diff --git a/assets/voxygen/shaders/lod-object-vert.glsl b/assets/voxygen/shaders/lod-object-vert.glsl index 3de44d1527..c581f06879 100644 --- a/assets/voxygen/shaders/lod-object-vert.glsl +++ b/assets/voxygen/shaders/lod-object-vert.glsl @@ -47,7 +47,7 @@ void main() { #endif f_norm = v_norm; - f_col = vec4(vec3(inst_col) * (1.0 / 255.0) * v_col * (hash(inst_pos.xyxy) * 0.35 + 0.65), 1.0); + f_col = vec4(vec3(inst_col) * (1.0 / 255.0) * v_col * (hash(inst_pos.xyxy) * 0.4 + 0.6), 1.0); f_flags = inst_flags; gl_Position = diff --git a/assets/voxygen/shaders/lod-terrain-frag.glsl b/assets/voxygen/shaders/lod-terrain-frag.glsl index c9c980b529..c31fdb3b56 100644 --- a/assets/voxygen/shaders/lod-terrain-frag.glsl +++ b/assets/voxygen/shaders/lod-terrain-frag.glsl @@ -115,354 +115,46 @@ void main() { // vec4 new_f_pos = invfoo * (old_coord);//vec4(f_pos, 1.0); vec3 f_col_raw = mix(lod_col(f_pos.xy), vec3(0), clamp(pull_down / 30, 0, 1)); // tgt_color = vec4(f_col, 1.0); - // return; - // vec3 f_col = srgb_to_linear(vec3(1.0)); - // vec3 f_norm = faceforward(f_norm, cam_pos.xyz - f_pos, -f_norm); - // vec3 f_up = faceforward(cam_pos.xyz - f_pos, vec3(0.0, 0.0, -1.0), cam_pos.xyz - f_pos); - // vec3 f_norm = faceforward(f_norm, /*vec3(cam_pos.xyz - f_pos.xyz)*/vec3(0.0, 0.0, -1.0), f_norm); - // const vec3 normals[3] = vec3[](vec3(1,0,0), vec3(0,1,0), vec3(0,0,1));//, vec3(-1,0,0), vec3(0,-1,0), vec3(0,0,-1)); - // const mat3 side_norms = vec3(1, 0, 0), vec3(0, 1, 0), vec3(0, 0, 1); - // mat3 sides = mat3( - // /*vec3(1, 0, 0), - // vec3(0, 1, 0), - // vec3(0, 0, 1)*/ - // vec3(1, 0, 0), - // // faceforward(vec3(1, 0, 0), -f_norm, vec3(1, 0, 0)), - // vec3(0, 1, 0), - // // faceforward(vec3(0, 1, 0), -f_norm, vec3(0, 1, 0)), - // vec3(0, 0, 1) - // // faceforward(vec3(0, 0, 1), -f_norm, vec3(0, 0, 1)) - // ); + vec3 cam_to_frag = normalize(f_pos - cam_pos.xyz); + vec3 view_dir = -cam_to_frag; - // This vector is shorthand for a diagonal matrix, which works because: - // (1) our voxel normal vectors are exactly the basis vectors in worldspace; - // (2) only 3 of them can be in the direction of the actual normal anyway. - // (NOTE: This normal should always be pointing up, so implicitly sides.z = 1.0). - // vec3 sides = sign(f_norm); - // // NOTE: Should really be sides * f_norm, i.e. abs(f_norm), but voxel_norm would then re-multiply by sides so it cancels out. - // vec3 cos_sides_i = sides * f_norm; - // vec3 cos_sides_o = sides * view_dir; - // // vec3 side_factor_i = cos_sides_i; - // // vec3 side_factor_i = f_norm; - // // vec3 side_factor_i = cos_sides_o; - // vec3 side_factor_i = 1.0 - pow(1.0 - 0.5 * cos_sides_i, vec3(5)); - // // vec3 side_factor_i = /*abs*/sign(f_norm) * cos_sides_i;//max(cos_sides_i, 0.0);// 1.0 - pow(1.0 - 0.5 * cos_sides_i, vec3(5.0)); // max(sides * f_norm, vec3(0.0));// - // // vec3 side_factor_i = /*abs*/sign(f_norm) * cos_sides_i;//max(cos_sides_i, 0.0);// 1.0 - pow(1.0 - 0.5 * cos_sides_i, vec3(5.0)); // max(sides * f_norm, vec3(0.0));// - // // vec3 side_factor_o = max(cos_sides_o, 0.0);// 1.0 - pow(1.0 - 0.5 * max(cos_sides_o, 0.0), vec3(5)); - // vec3 side_factor_o = 1.0 - pow(1.0 - 0.5 * max(cos_sides_o, 0.0), vec3(5)); - // // vec3 side_factor_o = max(cos_sides_o, 0.0);// 1.0 - pow(1.0 - 0.5 * max(cos_sides_o, vec3(0.0)), vec3(5.0));//max(sides * view_dir/* * sign(cos_sides_i) */, vec3(0.0)); - // // vec3 side_factor_o = max(sides * view_dir/* * cos_sides_o*/, 0.0);// 1.0 - pow(1.0 - 0.5 * max(cos_sides_o, vec3(0.0)), vec3(5.0));//max(sides * view_dir/* * sign(cos_sides_i) */, vec3(0.0)); - // // NOTE: side = transpose(sides), so we avoid the extra operatin. - // // We multply the vector by the matrix from the *left*, so each normal gets multiplied by the corresponding factor. - // // vec3 voxel_norm = normalize(/*sides * *//*sqrt(1.0 - cos_sides_i * cos_sides_i)*/(side_factor_i * side_factor_o)); - // vec3 voxel_norm = normalize(/*sides * *//*sqrt(1.0 - cos_sides_i * cos_sides_i)*/((28.0 / (23.0 * PI)) * side_factor_i * side_factor_o * sides)); - // vec3 voxel_norm = normalize(sign(f_norm) * sqrt(abs(f_norm)) * max(sign(f_norm) * view_dir, 0.0)); - float f_ao = 1.0;//1.0;//sqrt(dot(cos_sides_i, cos_sides_i) / 3.0); - // float f_ao = 0.2; - // sqrt(dot(sqrt(1.0 - cos_sides_i * cos_sides_i)), 1.0 - cos_sides_o/* * cos_sides_o*/);// length(sqrt(1.0 - cos_sides_o * cos_sides_o) / cos_sides_i * cos_sides_o); - // f_ao = f_ao * f_ao; + float f_ao = 1.0; - // /* vec3 voxel_norm = vec3(0.0); - // for (int i = 0; i < 3; i ++) { - // // Light reflecting off the half-angle can shine on up to three sides. - // // So, the idea here is to figure out the ratio of visibility of each of these - // // three sides such that their sum adds to 1, then computing a Beckmann Distribution for each side times - // // the this ratio. - // // - // // The ratio of these normals in each direction should be the sum of their cosines with the light over π, - // // I think. - // // - // // cos (wh, theta) - // // - // // - one normal - // // - // // The ratio of each of the three exposed sides should just be the slope. - // vec3 side = normals[i]; - // side = faceforward(side, -f_norm, side); - // float cos_wi = max(dot(f_norm, side), 0.0); - // float cos_wo = max(dot(view_dir, side), 0.0); - // float share = cos_wi * cos_wo; - // // float share = (1.0 - pow5(1.0 - 0.5 * cos_wi)) * (1.0 - pow5(1.0 - 0.5 * cos_wo)); - // voxel_norm += share * side; - // // voxel_norm += normals[i] * side_visible * max(dot(-cam_dir, normals[i]), 0.0); - // // voxel_norm += normals[i] * side_visible * max(dot(-cam_dir, normals[i]), 0.0); - // } - // voxel_norm = normalize(voxel_norm); */ - - float dist_lerp = 0.0;//clamp(pow(max(distance(focus_pos.xy, f_pos.xy) - view_distance.x, 0.0) / 4096.0, 2.0), 0, 1); - // dist_lerp = 0.0; - // voxel_norm = normalize(mix(voxel_norm, f_norm, /*pow(dist_lerp, 1.0)*/dist_lerp)); - - // IDEA: - // We can represent three faces as sign(voxel_norm). - vec3 sides = sign(f_norm); - // There are three relevant vectors: normal, tangent, and bitangent. - // We say normal is the z component, tangent the x component, bitangent the y. - // A blocking side is in the reverse direction of each. - // So -sides is the *direction* of the next block. - // Now, we want to multiply this by the *distance* to the nearest integer in that direction. - // If sides.x is -1, the direction is 1, so the distance is 1.0 - fract(f_pos.x) and the delta is 1.0 - fract(f_pos.x). - // If sides.x is 1, the direction is -1, so the distance is fract(f_pos.x) and the delta is -fract(f_pos.x) = 1.0 + fract(-f_pos.x). - // If sides.x is 0, the direction is 0, so the distance is 0.0 and the delta is 0.0 = 0.0 + fract(0.0 * f_pos.x). - // (we ignore f_pos < 0 for the time being). - // Then this is 1.0 + sides.x * fract(-sides.x * f_pos.x); - // We repeat this for y. - // - // We treat z as the dependent variable. - // IF voxel_norm.x > 0.0, z should increase by voxel_norm.z / voxel_norm.x * delta_sides.x in the x direction; - // IF voxel_norm.y > 0.0, z should increase by voxel_norm.z / voxel_norm.y * delta_sides.y in the y direction; - // IF voxel_norm.x = 0.0, z should not increase in the x direction; - // IF voxel_norm.y = 0.0, z should not increase in the y direction; - // we assume that ¬(voxel_norm.z = 0). - // - // Now observe that we can rephrase this as saying, given a desired change in z (to get to the next integer), how far must - // we travel along x and y? - // - // TODO: Handle negative numbers. - // vec3 delta_sides = mix(-fract(f_pos), 1.0 - fract(f_pos), lessThan(sides, vec3(0.0))); - vec3 delta_sides = mix(fract(f_pos) - 1.0, fract(f_pos), lessThan(sides, vec3(0.0))); - /* vec3 delta_sides = - mix( - mix(-fract(f_pos), 1.0 - fract(f_pos), lessThan(sides, vec3(0.0))), - mix(-(f_pos - ceil(f_pos)), 1.0 - (f_pos - ceil(f_pos)), lessThan(sides, vec3(0.0))), - lessThan(f_pos, vec3(0.0)) - ); */ - /* vec3 delta_sides = - mix( - mix(1.0 - fract(f_pos), -fract(f_pos), lessThan(sides, vec3(0.0))), - mix(1.0 - (f_pos - ceil(f_pos)), -(f_pos - ceil(f_pos)), lessThan(sides, vec3(0.0))), - lessThan(f_pos, vec3(0.0)) - ); */ - // vec3 delta_sides = mix(1.0 - fract(f_pos), -fract(f_pos), lessThan(sides, vec3(0.0))); - // vec3 delta_sides = 1.0 + sides * fract(-sides * f_pos); - // delta_sides = -sign(delta_sides) * (1.0 - abs(delta_sides)); - // Three faces: xy, xz, and yz. - // TODO: Handle zero slopes (for xz and yz). - vec2 corner_xy = min(abs(f_norm.xy / f_norm.z * delta_sides.z), 1.0); - vec2 corner_yz = min(abs(f_norm.yz / f_norm.x * delta_sides.x), 1.0); - vec2 corner_xz = min(abs(f_norm.xz / f_norm.y * delta_sides.y), 1.0); - // vec3 corner_delta = vec3(voxel_norm.xy / voxel_norm.z * delta_sides.z, delta_sides.z); - // Now we just compute an (upper bounded) distance to the corner in each direction. - // vec3 corner_distance = min(abs(corner_delta), 1.0); - // Now, if both sides hit something, lerp to 0.25. If one side hits something, lerp to 0.75. And if no sides hit something, - // lerp to 1.0 (TODO: incorporate the corner properly). - // Bilinear interpolation on each plane: - float ao_xy = dot(vec2(corner_xy.x, 1.0 - corner_xy.x), mat2(vec2(corner_xy.x < 1.00 ? corner_xy.y < 1.00 ? 0.25 : 0.5 : corner_xy.y < 1.00 ? 0.5 : 0.75, corner_xy.x < 1.00 ? 0.75 : 1.00), vec2(corner_xy.y < 1.00 ? 0.75 : 1.0, 1.0)) * vec2(corner_xy.y, 1.0 - corner_xy.y)); - float ao_yz = dot(vec2(corner_yz.x, 1.0 - corner_yz.x), mat2(vec2(corner_yz.x < 1.00 ? corner_yz.y < 1.00 ? 0.25 : 0.5 : corner_yz.y < 1.00 ? 0.5 : 0.75, corner_yz.x < 1.00 ? 0.75 : 1.00), vec2(corner_yz.y < 1.00 ? 0.75 : 1.0, 1.0)) * vec2(corner_yz.y, 1.0 - corner_yz.y)); - float ao_xz = dot(vec2(corner_xz.x, 1.0 - corner_xz.x), mat2(vec2(corner_xz.x < 1.00 ? corner_xz.y < 1.00 ? 0.25 : 0.5 : corner_xz.y < 1.00 ? 0.5 : 0.75, corner_xz.x < 1.00 ? 0.75 : 1.00), vec2(corner_xz.y < 1.00 ? 0.75 : 1.0, 1.0)) * vec2(corner_xz.y, 1.0 - corner_xz.y)); - /* float ao_xy = dot(vec2(1.0 - corner_xy.x, corner_xy.x), mat2(vec2(corner_xy.x < 1.00 ? corner_xy.y < 1.00 ? 0.25 : 0.5 : corner_xy.y < 1.00 ? 0.5 : 0.75, corner_xy.x < 1.00 ? 0.75 : 1.00), vec2(corner_xy.y < 1.00 ? 0.75 : 1.0, 1.0)) * vec2(1.0 - corner_xy.y, corner_xy.y)); - float ao_yz = dot(vec2(1.0 - corner_yz.x, corner_yz.x), mat2(vec2(corner_yz.x < 1.00 ? corner_yz.y < 1.00 ? 0.25 : 0.5 : corner_yz.y < 1.00 ? 0.5 : 0.75, corner_yz.x < 1.00 ? 0.75 : 1.00), vec2(corner_yz.y < 1.00 ? 0.75 : 1.0, 1.0)) * vec2(1.0 - corner_yz.y, corner_yz.y)); - float ao_xz = dot(vec2(1.0 - corner_xz.x, corner_xz.x), mat2(vec2(corner_xz.x < 1.00 ? corner_xz.y < 1.00 ? 0.25 : 0.5 : corner_xz.y < 1.00 ? 0.5 : 0.75, corner_xz.x < 1.00 ? 0.75 : 1.00), vec2(corner_xz.y < 1.00 ? 0.75 : 1.0, 1.0)) * vec2(1.0 - corner_xz.y, corner_xz.y)); */ - // Now, if both sides hit something, lerp to 0.0. If one side hits something, lerp to 0.4. And if no sides hit something, - // lerp to 1.0. - // Bilinear interpolation on each plane: - // float ao_xy = dot(vec2(1.0 - corner_xy.x, corner_xy.x), mat2(vec2(corner_xy.x < 1.00 ? corner_xy.y < 1.00 ? 0.0 : 0.25 : corner_xy.y < 1.00 ? 0.25 : 1.0, corner_xy.x < 1.00 ? 0.25 : 1.0), vec2(corner_xy.y < 1.00 ? 0.25 : 1.0, 1.0)) * vec2(1.0 - corner_xy.y, corner_xy.y)); - // float ao_yz = dot(vec2(1.0 - corner_yz.x, corner_yz.x), mat2(vec2(corner_yz.x < 1.00 ? corner_yz.y < 1.00 ? 0.0 : 0.25 : corner_yz.y < 1.00 ? 0.25 : 1.0, corner_yz.x < 1.00 ? 0.25 : 1.0), vec2(corner_yz.y < 1.00 ? 0.25 : 1.0, 1.0)) * vec2(1.0 - corner_yz.y, corner_yz.y)); - // float ao_xz = dot(vec2(1.0 - corner_xz.x, corner_xz.x), mat2(vec2(corner_xz.x < 1.00 ? corner_xz.y < 1.00 ? 0.0 : 0.25 : corner_xz.y < 1.00 ? 0.25 : 1.0, corner_xz.x < 1.00 ? 0.25 : 1.0), vec2(corner_xz.y < 1.00 ? 0.25 : 1.0, 1.0)) * vec2(1.0 - corner_xz.y, corner_xz.y)); - // Now, multiply each component by the face "share" which is just the absolute value of its normal for that plane... - // vec3 f_ao_vec = mix(abs(vec3(ao_yz, ao_xz, ao_xy)), vec3(1.0), bvec3(f_norm.yz == vec2(0.0), f_norm.xz == vec2(0.0), f_norm.xy == vec2(0.0))); - // vec3 f_ao_vec = mix(abs(vec3(ao_yz, ao_xz, ao_xy)), vec3(1.0), bvec3(length(f_norm.yz) <= 0.0, length(f_norm.xz) <= 0.0, length(f_norm.xy) <= 0.0)); - // vec3 f_ao_vec = mix(abs(vec3(ao_yz, ao_xz, ao_xy)), vec3(1.0), bvec3(abs(f_norm.x) <= 0.0, abs(f_norm.y) <= 0.0, abs(f_norm.z) <= 0.0)); - vec3 f_ao_vec = mix(/*abs(voxel_norm)*/vec3(1.0, 1.0, 1.0), /*abs(voxel_norm) * */vec3(ao_yz, ao_xz, ao_xy), /*abs(voxel_norm)*/vec3(length(f_norm.yz), length(f_norm.xz), length(f_norm.xy))/*vec3(1.0)*//*sign(max(view_dir * sides, 0.0))*/); - float f_orig_len = length(cam_pos.xyz - f_pos); - vec3 f_orig_view_dir = normalize(cam_pos.xyz - f_pos); - // f_ao_vec *= sign(max(f_orig_view_dir * sides, 0.0)); - // Projecting view onto face: - // 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; - // } - - //bvec3 hit_yz_xz_xy; - //vec3 dist_yz_xz_xy; - /* { - // vec3 rDotn = -f_orig_view_dir * -sides; - // vec3 rDotn = f_orig_view_dir * sides; - // hit_yz_xz_xy = greaterThanEqual(rDotn, vec3(0.000001)); - // vec3 s = -sides * (f_pos + delta_sides - cam_pos.xyz) / rDotn; - // dist_yz_xz_xy = abs(s * -f_orig_view_dir); - // vec3 s = -sides * (f_pos + delta_sides - cam_pos.xyz) / (-f_orig_view_dir * -sides); - // vec3 s = (f_pos + delta_sides - cam_pos.xyz) / -f_orig_view_dir; - // dist_yz_xz_xy = abs(s); - hit_yz_xz_xy = greaterThanEqual(f_orig_view_dir * sides, vec3(0.000001)); - dist_yz_xz_xy = abs((f_pos + delta_sides - cam_pos.xyz) / -f_orig_view_dir); - } */ - { - // vec3 rDotn = -f_orig_view_dir * -sides; - // vec3 rDotn = f_orig_view_dir * sides; - // hit_yz_xz_xy = greaterThanEqual(rDotn, vec3(0.000001)); - // vec3 s = -sides * (f_pos + delta_sides - cam_pos.xyz) / rDotn; - // dist_yz_xz_xy = abs(s * -f_orig_view_dir); - // vec3 s = -sides * (f_pos + delta_sides - cam_pos.xyz) / (-f_orig_view_dir * -sides); - // vec3 s = (f_pos + delta_sides - cam_pos.xyz) / -f_orig_view_dir; - // dist_yz_xz_xy = abs(s); - //hit_yz_xz_xy = greaterThanEqual(f_orig_view_dir * sides, vec3(0.000001)); - //dist_yz_xz_xy = abs((f_pos + delta_sides - cam_pos.xyz) / f_orig_view_dir); - } - - // vec3 xy_point = f_pos, xz_point = f_pos, yz_point = f_pos; - // bool hit_xy = (/*ao_yz < 1.0 || ao_xz < 1.0*//*min(f_ao_vec.x, f_ao_vec.y)*//*f_ao_vec.z < 1.0*/true/*min(corner_xz.y, corner_yz.y) < 1.0*//*min(corner_xy.x, corner_xy.y) < 1.0*/) && IntersectRayPlane(cam_pos.xyz, -f_orig_view_dir, vec3(f_pos.x, f_pos.y, f_pos.z + delta_sides.z/* - sides.z*/), vec3(0.0, 0.0, -sides.z), xy_point); - // bool hit_xz = (/*ao_xy < 1.0 || ao_yz < 1.0*//*min(f_ao_vec.x, f_ao_vec.z)*//*f_ao_vec.y < 1.0*/true/*min(corner_xy.y, corner_yz.x) < 1.0*//*min(corner_xz.x, corner_xz.y) < 1.0*/) && IntersectRayPlane(cam_pos.xyz, -f_orig_view_dir, vec3(f_pos.x, f_pos.y + delta_sides.y/* - sides.y*/, f_pos.z), vec3(0.0, -sides.y, 0.0), xz_point); - // bool hit_yz = (/*ao_xy < 1.0 || ao_xz < 1.0*//*min(f_ao_vec.y, f_ao_vec.z) < 1.0*//*f_ao_vec.x < 1.0*/true/*true*//*min(corner_xy.x, corner_xz.x) < 1.0*//*min(corner_yz.x, corner_yz.y) < 1.0*/) && IntersectRayPlane(cam_pos.xyz, -f_orig_view_dir, vec3(f_pos.x + delta_sides.x/* - sides.x*/, f_pos.y, f_pos.z), vec3(-sides.x, 0.0, 0.0), yz_point); - // float xy_dist = distance(cam_pos.xyz, xy_point), xz_dist = distance(cam_pos.xyz, xz_point), yz_dist = distance(cam_pos.xyz, yz_point); - //bool hit_xy = hit_yz_xz_xy.z, hit_xz = hit_yz_xz_xy.y, hit_yz = hit_yz_xz_xy.x; - //float xy_dist = dist_yz_xz_xy.z, xz_dist = dist_yz_xz_xy.y, yz_dist = dist_yz_xz_xy.x; - // hit_xy = hit_xy && distance(f_pos.xy + delta_sides.xy, xy_point.xy) <= 1.0; - // hit_xz = hit_xz && distance(f_pos.xz + delta_sides.xz, xz_point.xz) <= 1.0; - // hit_yz = hit_yz && distance(f_pos.yz + delta_sides.yz, yz_point.yz) <= 1.0; - /* - vec3 voxel_norm = - hit_yz ? - hit_xz ? - yz_dist < xz_dist ? - hit_xy ? yz_dist < xy_dist ? vec3(sides.x, 0.0, 0.0) : vec3(0.0, 0.0, sides.z) : vec3(sides.x, 0.0, 0.0) : - hit_xy ? xz_dist < xy_dist ? vec3(0.0, sides.y, 0.0) : vec3(0.0, 0.0, sides.z) : vec3(0.0, sides.y, 0.0) : - hit_xy ? yz_dist < xy_dist ? vec3(sides.x, 0.0, 0.0) : vec3(0.0, 0.0, sides.z) : vec3(sides.x, 0.0, 0.0) : - hit_xz ? - hit_xy ? xz_dist < xy_dist ? vec3(0.0, sides.y, 0.0) : vec3(0.0, 0.0, sides.z) : vec3(0.0, sides.y, 0.0) : - hit_xy ? vec3(0.0, 0.0, sides.z) : vec3(0.0, 0.0, 0.0); - */ - vec3 voxel_norm; + vec3 voxel_norm = f_norm; const float VOXELIZE_DIST = 2000; - float voxelize_factor = clamp(1.0 - (distance(focus_pos.xy, f_pos.xy) - view_distance.x) / VOXELIZE_DIST, 0, 1); - vec3 cam_dir = normalize(cam_pos.xyz - f_pos.xyz); - vec3 side_norm = normalize(vec3(my_norm.xy, 0)); - vec3 top_norm = vec3(0, 0, 1); + float voxelize_factor = clamp(1.0 - (distance(focus_pos.xy, f_pos.xy) - view_distance.x) * (1.0 / VOXELIZE_DIST), 0, 1); + vec3 cam_dir = cam_to_frag; #ifdef EXPERIMENTAL_NOLODVOXELS f_ao = 1.0; + vec3 side_norm = normalize(vec3(my_norm.xy, 0.01)); + vec3 top_norm = vec3(0, 0, 1); voxel_norm = normalize(mix(side_norm, top_norm, max(cam_dir.z, 0.0))); #else - float side_factor = 1.0 - my_norm.z; - // min(dot(vec3(0, -sign(cam_dir.y), 0), -cam_dir), dot(vec3(-sign(cam_dir.x), 0, 0), -cam_dir)) - if (max(abs(my_norm.x), abs(my_norm.y)) < 0.01 || fract(my_alt) * clamp(dot(normalize(vec3(cam_dir.xy, 0)), side_norm), 0, 1) < cam_dir.z / my_norm.z) { - //f_ao *= mix(1.0, clamp(fract(my_alt) / length(my_norm.xy) + clamp(dot(side_norm, -cam_dir), 0, 1), 0, 1), voxelize_factor); - voxel_norm = top_norm; - } else { - f_ao *= mix(1.0, clamp(pow(fract(my_alt), 0.5), 0, 1), voxelize_factor); + #ifdef EXPERIMENTAL_PROCEDURALLODDETAIL + float nz_offset = (noise_2d((f_pos.xy + focus_off.xy) * 0.01) - 0.5) * 3.0 / f_norm.z; + #else + const float nz_offset = 0.0; + #endif - if (fract(f_pos.x) * abs(my_norm.y / cam_dir.x) < fract(f_pos.y) * abs(my_norm.x / cam_dir.y)) { - voxel_norm = vec3(sign(cam_dir.x), 0, 0); - } else { - voxel_norm = vec3(0, sign(cam_dir.y), 0); + float t = -2.0; + while (t < 2.0) { + vec3 deltas = (step(vec3(0), -cam_dir) - fract(f_pos - cam_dir * t)) / -cam_dir; + float m = min(min(deltas.x, deltas.y), deltas.z); + + t += max(m, 0.01); + + vec3 block_pos = floor(f_pos - cam_dir * t) + 0.5; + if (dot(block_pos - f_pos - nz_offset * f_norm, -f_norm) < 0.0) { + vec3 to_center = abs(block_pos - (f_pos - cam_dir * t)); + voxel_norm = step(max(max(to_center.x, to_center.y), to_center.z), to_center) * sign(-cam_dir); + voxel_norm = mix(f_norm, voxel_norm, voxelize_factor); + f_ao = mix(1.0, clamp(1.0 + (t - nz_offset + 0.0) * 0.5, 0.1, 1.0), voxelize_factor); + break; } } #endif - vec3 f_pos2 = (f_pos + focus_off.xyz) * 0.7;//; - - f_ao = 1.0; - float t = -2.0;// / dot(cam_dir, f_norm); - for (int i = 0; i < 6; i ++) { - vec3 deltas = (step(vec3(0), cam_dir) - fract(f_pos2 + cam_dir * t)) / cam_dir; - float m = min(min(deltas.x, deltas.y), deltas.z); - - t += max(m, 0.01); - - vec3 block_pos = floor(f_pos2 + cam_dir * t) + 0.5; - if (dot(block_pos - f_pos2, -f_norm) < 0.0) { - vec3 to_center = abs(block_pos - (f_pos2 + cam_dir * t)); - voxel_norm = step(max(max(to_center.x, to_center.y), to_center.z), to_center) * sign(cam_dir); - /* voxel_norm = f_norm; */ - voxel_norm = normalize(mix(f_norm, voxel_norm, voxelize_factor)); - f_ao = mix(1.0, clamp(1.0 + t * 0.5 / f_norm.z, 0.3, 1.0), voxelize_factor); - break; - } - } - - // vec3 f_ao_view = max(vec3(dot(f_orig_view_dir.yz, sides.yz), dot(f_orig_view_dir.xz, sides.xz), dot(f_orig_view_dir.xy, sides.xy)), 0.0); - // delta_sides *= sqrt(1.0 - f_ao_view * f_ao_view); - // delta_sides *= 1.0 - mix(view_dir / f_ao_view, vec3(0.0), equal(f_ao_view, vec3(0.0)));// sqrt(1.0 - f_ao_view * f_ao_view); - // delta_sides *= 1.0 - /*sign*/(max(vec3(dot(f_orig_view_dir.yz, sides.yz), dot(f_orig_view_dir.xz, sides.xz), dot(f_orig_view_dir.xy, sides.xy)), 0.0)); - // f_ao = length(f_ao_vec); - // f_ao = dot(f_ao_vec, vec3(1.0)) / 3.0; - // f_ao = 1.0 / sqrt(3.0) * sqrt(dot(f_ao_vec, vec3(1.0))); - // f_ao = pow(f_ao_vec.x * f_ao_vec.y * f_ao_vec.z * 3.0, 1.0 / 2.0); // 1.0 / sqrt(3.0) * sqrt(dot(f_ao_vec, vec3(1.0))); - // f_ao = pow(f_ao_vec.x * f_ao_vec.y * f_ao_vec.z, 1.0 / 3.0); // 1.0 / sqrt(3.0) * sqrt(dot(f_ao_vec, vec3(1.0))); - // f_ao = f_ao_vec.x * f_ao_vec.y * f_ao_vec.z + (1.0 - f_ao_vec.x) * (1.0 - f_ao_vec.y) * (1.0 - f_ao_vec.z); - // f_ao = sqrt((f_ao_vec.x + f_ao_vec.y + f_ao_vec.z) / 3.0); // 1.0 / sqrt(3.0) * sqrt(dot(f_ao_vec, vec3(1.0))); - // f_ao = sqrt(dot(f_ao_vec, abs(voxel_norm))); - // f_ao = 3.0 / (1.0 / f_ao_vec.x + 1.0 / f_ao_vec.y + 1.0 / f_ao_vec.z); - // f_ao = min(ao_yz, min(ao_xz, ao_xy)); - // f_ao = max(f_ao_vec.x, max(f_ao_vec.y, f_ao_vec.z)); - // f_ao = min(f_ao_vec.x, min(f_ao_vec.y, f_ao_vec.z)); - // f_ao = sqrt(dot(f_ao_vec * abs(voxel_norm), sqrt(1.0 - delta_sides * delta_sides)) / 3.0); - // f_ao = dot(f_ao_vec, sqrt(1.0 - delta_sides * delta_sides)); - // f_ao = dot(f_ao_vec, 1.0 - abs(delta_sides)); - // f_ao = - // f_ao_vec.x < 1.0 ? - // f_ao_vec.y < 1.0 ? - // abs(delta_sides.x) < abs(delta_sides.y) ? - // f_ao_vec.z < 1.0 ? abs(delta_sides.x) < abs(delta_sides.z) ? f_ao_vec.x : f_ao_vec.z : f_ao_vec.x : - // f_ao_vec.z < 1.0 ? abs(delta_sides.y) < abs(delta_sides.z) ? f_ao_vec.y : f_ao_vec.z : f_ao_vec.y : - // f_ao_vec.z < 1.0 ? abs(delta_sides.x) < abs(delta_sides.z) ? f_ao_vec.x : f_ao_vec.z : f_ao_vec.x : - // f_ao_vec.y < 1.0 ? - // f_ao_vec.z < 1.0 ? abs(delta_sides.y) < abs(delta_sides.z) ? f_ao_vec.y : f_ao_vec.z : f_ao_vec.y : - // f_ao_vec.z; - // f_ao = abs(delta_sides.x) < abs(delta_sides.y) ? abs(delta_sides.x) < abs(delta_sides.z) ? f_ao_vec.x : f_ao_vec.z : - // abs(delta_sides.y) < abs(delta_sides.z) ? f_ao_vec.y : f_ao_vec.z; - // f_ao = abs(delta_sides.x) * f_ao_vec.x < abs(delta_sides.y) * f_ao_vec.y ? abs(delta_sides.x) * f_ao_vec.x < abs(delta_sides.z) * f_ao_vec.z ? f_ao_vec.x : f_ao_vec.z : - // abs(delta_sides.y) * f_ao_vec.y < abs(delta_sides.z) * f_ao_vec.z ? f_ao_vec.y : f_ao_vec.z; - // f_ao = dot(abs(voxel_norm), abs(voxel_norm) * f_ao_vec)/* / 3.0*/; - // f_ao = sqrt(dot(abs(voxel_norm), f_ao_vec) / 3.0); - // f_ao = /*abs(sides)*/max(sign(1.0 + f_orig_view_dir * sides), 0.0) * f_ao); - // f_ao = mix(f_ao, 1.0, dist_lerp); - - // vec3 voxel_norm = f_norm; - // vec3 voxel_norm = - // f_ao_vec.x < 1.0 ? - // f_ao_vec.y < 1.0 ? - // abs(delta_sides.x) < abs(delta_sides.y) ? - // f_ao_vec.z < 1.0 ? abs(delta_sides.x) < abs(delta_sides.z) ? vec3(sides.x, 0.0, 0.0) : vec3(0.0, 0.0, sides.z) : vec3(sides.x, 0.0, 0.0) : - // f_ao_vec.z < 1.0 ? abs(delta_sides.y) < abs(delta_sides.z) ? vec3(0.0, sides.y, 0.0) : vec3(0.0, 0.0, sides.z) : vec3(0.0, sides.y, 0.0) : - // f_ao_vec.z < 1.0 ? abs(delta_sides.x) < abs(delta_sides.z) ? vec3(sides.x, 0.0, 0.0) : vec3(0.0, 0.0, sides.z) : vec3(sides.x, 0.0, 0.0) : - // f_ao_vec.y < 1.0 ? - // f_ao_vec.z < 1.0 ? abs(delta_sides.y) < abs(delta_sides.z) ? vec3(0.0, sides.y, 0.0) : vec3(0.0, 0.0, sides.z) : vec3(0.0, sides.y, 0.0) : - // f_ao_vec.z < 1.0 ? vec3(0.0, 0.0, sides.z) : vec3(0.0, 0.0, 0.0); - - // vec3 voxel_norm = - // /*f_ao_vec.x < 1.0*/true ? - // /*f_ao_vec.y < 1.0*/true ? - // abs(delta_sides.x) < abs(delta_sides.y) ? - // /*f_ao_vec.z < 1.0 */true ? abs(delta_sides.x) < abs(delta_sides.z) ? vec3(sides.x, 0.0, 0.0) : vec3(0.0, 0.0, sides.z) : vec3(sides.x, 0.0, 0.0) : - // /*f_ao_vec.z < 1.0*/true ? abs(delta_sides.y) < abs(delta_sides.z) ? vec3(0.0, sides.y, 0.0) : vec3(0.0, 0.0, sides.z) : vec3(0.0, sides.y, 0.0) : - // /*f_ao_vec.z < 1.0*/true ? abs(delta_sides.x) < abs(delta_sides.z) ? vec3(sides.x, 0.0, 0.0) : vec3(0.0, 0.0, sides.z) : vec3(sides.x, 0.0, 0.0) : - // /*f_ao_vec.y < 1.0*/true ? - // /*f_ao_vec.z < 1.0*/true ? abs(delta_sides.y) < abs(delta_sides.z) ? vec3(0.0, sides.y, 0.0) : vec3(0.0, 0.0, sides.z) : vec3(0.0, sides.y, 0.0) : - // vec3(0.0, 0.0, sides.z); - /* vec3 voxel_norm = - f_ao_vec.x < 1.0 ? - f_ao_vec.y < 1.0 ? - abs(delta_sides.x) < abs(delta_sides.y) ? - f_ao_vec.z < 1.0 ? abs(delta_sides.x) < abs(delta_sides.z) ? vec3(sides.x, 0.0, 0.0) : vec3(0.0, 0.0, sides.z) : vec3(sides.x, 0.0, 0.0) : - f_ao_vec.z < 1.0 ? abs(delta_sides.y) < abs(delta_sides.z) ? vec3(0.0, sides.y, 0.0) : vec3(0.0, 0.0, sides.z) : vec3(0.0, sides.y, 0.0) : - f_ao_vec.z < 1.0 ? abs(delta_sides.x) < abs(delta_sides.z) ? vec3(sides.x, 0.0, 0.0) : vec3(0.0, 0.0, sides.z) : vec3(sides.x, 0.0, 0.0) : - f_ao_vec.y < 1.0 ? - f_ao_vec.z < 1.0 ? abs(delta_sides.y) < abs(delta_sides.z) ? vec3(0.0, sides.y, 0.0) : vec3(0.0, 0.0, sides.z) : vec3(0.0, sides.y, 0.0) : - f_ao_vec.z < 1.0 ? vec3(0.0, 0.0, sides.z) : vec3(0.0, 0.0, 0.0); */ - // vec3 voxel_norm = - // f_ao_vec.x < 1.0 ? - // f_ao_vec.y < 1.0 ? - // abs(delta_sides.x) * f_ao_vec.x < abs(delta_sides.y) * f_ao_vec.y ? - // f_ao_vec.z < 1.0 ? abs(delta_sides.x) * f_ao_vec.x < abs(delta_sides.z) * f_ao_vec.z ? vec3(sides.x, 0.0, 0.0) : vec3(0.0, 0.0, sides.z) : vec3(sides.x, 0.0, 0.0) : - // f_ao_vec.z < 1.0 ? abs(delta_sides.y) * f_ao_vec.y < abs(delta_sides.z) * f_ao_vec.z ? vec3(0.0, sides.y, 0.0) : vec3(0.0, 0.0, sides.z) : vec3(0.0, sides.y, 0.0) : - // f_ao_vec.z < 1.0 ? abs(delta_sides.x) * f_ao_vec.x < abs(delta_sides.z) * f_ao_vec.z ? vec3(sides.x, 0.0, 0.0) : vec3(0.0, 0.0, sides.z) : vec3(sides.x, 0.0, 0.0) : - // f_ao_vec.y < 1.0 ? - // f_ao_vec.z < 1.0 ? abs(delta_sides.y) * f_ao_vec.y < abs(delta_sides.z) * f_ao_vec.z ? vec3(0.0, sides.y, 0.0) : vec3(0.0, 0.0, sides.z) : vec3(0.0, sides.y, 0.0) : - // f_ao_vec.z < 1.0 ? vec3(0.0, 0.0, sides.z) : vec3(0.0, 0.0, 0.0); - // vec3 voxel_norm = vec3(0.0); - // voxel_norm = mix(voxel_norm, f_norm, dist_lerp); - /* vec3 sun_dir = get_sun_dir(time_of_day.x); vec3 moon_dir = get_moon_dir(time_of_day.x); */ // voxel_norm = vec3(0.0); @@ -475,7 +167,7 @@ void main() { #endif #if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP) - vec4 f_shadow = textureBicubic(t_horizon, s_horizon, pos_to_tex(f_pos.xy)); + vec4 f_shadow = textureMaybeBicubic(t_horizon, s_horizon, pos_to_tex(f_pos.xy)); float sun_shade_frac = horizon_at2(f_shadow, shadow_alt, f_pos, sun_dir); // float sun_shade_frac = 1.0; #elif (SHADOW_MODE == SHADOW_MODE_NONE) @@ -484,32 +176,32 @@ void main() { float moon_shade_frac = 1.0;//horizon_at2(f_shadow, shadow_alt, f_pos, moon_dir); // Magic stop-gap code without any physical justification. - vec3 lerpy_norm; - if (my_norm.z/*f_norm.z*/ > 0.99999) { - lerpy_norm = vec3(0, 0, 1); - } else { - vec3 side_norm = normalize(vec3(my_norm.xy, 0)); - // lerpy_norm = f_norm; - float mix_factor = clamp(abs(dot(f_orig_view_dir, side_norm)), 0, 1); - lerpy_norm = mix( - mix(my_norm, side_norm, clamp(dot(side_norm, my_norm) + 0.5, 0, 1)), - my_norm, - mix_factor - ); - } - const float DIST = 0.07; - voxel_norm = normalize(mix(voxel_norm, lerpy_norm, clamp(my_norm.z * my_norm.z - (1.0 - DIST), 0, 1) / DIST)); + //vec3 lerpy_norm; + //if (my_norm.z/*f_norm.z*/ > 0.99999) { + // lerpy_norm = vec3(0, 0, 1); + //} else { + // vec3 side_norm = normalize(vec3(my_norm.xy, 0)); + // // lerpy_norm = f_norm; + // float mix_factor = clamp(abs(dot(f_orig_view_dir, side_norm)), 0, 1); + // lerpy_norm = mix( + // mix(my_norm, side_norm, clamp(dot(side_norm, my_norm) + 0.5, 0, 1)), + // my_norm, + // mix_factor + // ); + //} + //const float DIST = 0.07; + /* 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 = mix(my_norm, voxel_norm == vec3(0.0) ? f_norm : voxel_norm, voxelize_factor); + //f_pos.xyz += abs(voxel_norm) * delta_sides; + /* voxel_norm = mix(my_norm, voxel_norm == vec3(0.0) ? f_norm : voxel_norm, voxelize_factor); */ - vec3 hash_pos = f_pos + focus_off.xyz; - const float A = 0.055; - const float W_INV = 1 / (1 + A); - const float W_2 = W_INV * W_INV;//pow(W_INV, 2.4); - const float NOISE_FACTOR = 0.02;//pow(0.02, 1.2); - float noise = hash(vec4(floor(hash_pos * 3.0 - voxel_norm * 0.5), 0));//0.005/* - 0.01*/; - vec3 noise_delta = (sqrt(f_col_raw) * W_INV + noise * NOISE_FACTOR); + //vec3 hash_pos = f_pos + focus_off.xyz; + //const float A = 0.055; + //const float W_INV = 1 / (1 + A); + //const float W_2 = W_INV * W_INV;//pow(W_INV, 2.4); + //const float NOISE_FACTOR = 0.02;//pow(0.02, 1.2); + //float noise = hash(vec4(floor(hash_pos * 3.0 - voxel_norm * 0.5), 0));//0.005/* - 0.01*/; + //vec3 noise_delta = (sqrt(f_col_raw) * W_INV + noise * NOISE_FACTOR); // noise_delta = noise_delta * noise_delta * W_2 - f_col; // lum = W ⋅ col // lum + noise = W ⋅ (col + delta) @@ -519,13 +211,13 @@ void main() { // vec3 col = (f_col + noise_delta); // vec3 col = noise_delta * noise_delta * W_2; - vec3 f_col = noise_delta * noise_delta * W_2; + vec3 f_col = f_col_raw;//noise_delta * noise_delta * W_2; // f_col = /*srgb_to_linear*/(f_col + hash(vec4(floor(hash_pos * 3.0 - voxel_norm * 0.5), 0)) * 0.01/* - 0.01*/); // Small-scale noise // f_ao = 1.0; // f_ao = dot(f_ao_vec, sqrt(1.0 - delta_sides * delta_sides)); - f_ao *= dot(f_ao_vec, abs(voxel_norm)); + //f_ao *= dot(f_ao_vec, abs(voxel_norm)); // f_ao = sqrt(dot(f_ao_vec * abs(voxel_norm), sqrt(1.0 - delta_sides * delta_sides)) / 3.0); // vec3 ao_pos2 = min(fract(f_pos), 1.0 - fract(f_pos)); @@ -558,8 +250,6 @@ void main() { mix(-1.0, 1.0, clamp(pow(f_norm.y * 0.5, 64), 0, 1)), mix(-1.0, 1.0, clamp(pow(f_norm.z * 0.5, 64), 0, 1)) )); */ - vec3 cam_to_frag = normalize(f_pos - cam_pos.xyz); - vec3 view_dir = -cam_to_frag; // vec3 view_dir = normalize(f_pos - cam_pos.xyz); @@ -569,7 +259,7 @@ void main() { // // float moon_light = get_moon_brightness(moon_dir); // // float my_alt = f_pos.z;//alt_at_real(f_pos.xy); // // vec3 f_norm = my_norm; - // // vec4 f_shadow = textureBicubic(t_horizon, pos_to_tex(f_pos.xy)); + // // vec4 f_shadow = textureMaybeBicubic(t_horizon, pos_to_tex(f_pos.xy)); // // float shadow_alt = /*f_pos.z;*/alt_at(f_pos.xy);//max(alt_at(f_pos.xy), f_pos.z); // // float my_alt = alt_at(f_pos.xy); // float sun_shade_frac = horizon_at2(f_shadow, shadow_alt, f_pos, sun_dir); @@ -612,7 +302,7 @@ void main() { float max_light = 0.0; 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); + 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, 0.0/*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; @@ -672,13 +362,12 @@ void main() { vec3 surf_color; float surf_alpha = 1.0; uint mat; - if (length(f_col_raw - vec3(0.02, 0.06, 0.22)) < 0.025 && dot(vec3(0, 0, 1), f_norm) > 0.9) { + if (dot(pow(f_col_raw - vec3(0.02, 0.06, 0.22), uvec3(2)), vec3(1)) < 0.01 && dot(vec3(0, 0, 1), f_norm) > 0.9) { mat = MAT_FLUID; vec3 reflect_ray = cam_to_frag * vec3(1, 1, -1); #if (FLUID_MODE >= FLUID_MODE_MEDIUM) vec3 water_color = (1.0 - MU_WATER) * MU_SCATTER; - float passthrough = dot(faceforward(f_norm, f_norm, cam_to_frag), -cam_to_frag); vec3 reflect_color; @@ -706,11 +395,6 @@ void main() { surf_color = illuminate(max_light, view_dir, f_col * emitted_light, f_col * reflected_light); } - // 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(surf_color, surf_alpha); tgt_mat = uvec4(uvec3((f_norm + 1.0) * 127.0), mat); } diff --git a/assets/voxygen/shaders/lod-terrain-vert.glsl b/assets/voxygen/shaders/lod-terrain-vert.glsl index 0cd3eccd11..533d537e95 100644 --- a/assets/voxygen/shaders/lod-terrain-vert.glsl +++ b/assets/voxygen/shaders/lod-terrain-vert.glsl @@ -44,7 +44,7 @@ void main() { // f_norm = lod_norm(f_pos.xy); - // f_shadow = textureBicubic(t_horizon, pos_to_tex(f_pos.xy)); + // f_shadow = textureMaybeBicubic(t_horizon, pos_to_tex(f_pos.xy)); // TODO: disabled because it isn't designed to work with reverse depth //float dist = distance(focus_pos.xy, f_pos.xy); diff --git a/assets/voxygen/shaders/particle-frag.glsl b/assets/voxygen/shaders/particle-frag.glsl index 40170aa99d..d5e07dd620 100644 --- a/assets/voxygen/shaders/particle-frag.glsl +++ b/assets/voxygen/shaders/particle-frag.glsl @@ -50,7 +50,7 @@ void main() { #endif #if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP) - vec4 f_shadow = textureBicubic(t_horizon, s_horizon, pos_to_tex(f_pos.xy)); + vec4 f_shadow = textureMaybeBicubic(t_horizon, s_horizon, pos_to_tex(f_pos.xy)); float sun_shade_frac = horizon_at2(f_shadow, f_alt, f_pos, sun_dir); #elif (SHADOW_MODE == SHADOW_MODE_NONE) float sun_shade_frac = 1.0; diff --git a/assets/voxygen/shaders/sprite-frag.glsl b/assets/voxygen/shaders/sprite-frag.glsl index 3c68424396..f3ddd9eb28 100644 --- a/assets/voxygen/shaders/sprite-frag.glsl +++ b/assets/voxygen/shaders/sprite-frag.glsl @@ -60,7 +60,7 @@ void main() { #endif #if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP) - vec4 f_shadow = textureBicubic(t_horizon, s_horizon, pos_to_tex(f_pos.xy)); + vec4 f_shadow = textureMaybeBicubic(t_horizon, s_horizon, pos_to_tex(f_pos.xy)); float sun_shade_frac = horizon_at2(f_shadow, f_alt, f_pos, sun_dir); #elif (SHADOW_MODE == SHADOW_MODE_NONE) float sun_shade_frac = 1.0; diff --git a/assets/voxygen/shaders/sprite-vert.glsl b/assets/voxygen/shaders/sprite-vert.glsl index a17f7be369..815f4c2a33 100644 --- a/assets/voxygen/shaders/sprite-vert.glsl +++ b/assets/voxygen/shaders/sprite-vert.glsl @@ -56,6 +56,7 @@ const float EXTRA_NEG_Z = 32768.0; const float VERT_EXTRA_NEG_XY = 128.0; const float VERT_EXTRA_NEG_Z = 128.0; const uint VERT_PAGE_SIZE = 256; +const uint VERT_PAGE_SIZE_BITS = VERT_PAGE_SIZE - 1; // vec4(vec3(position), distance) vec4 nearest_entity(in vec3 sprite_pos, const float entity_radius_factor) { @@ -104,22 +105,17 @@ void main() { f_inst_light = vec2(inst_light, inst_glow); // Index of the vertex data in the 1D vertex texture - int vertex_index = int(uint(gl_VertexIndex) % VERT_PAGE_SIZE + inst_vert_page * VERT_PAGE_SIZE); + int vertex_index = int((uint(gl_VertexIndex) & VERT_PAGE_SIZE_BITS) + inst_vert_page * VERT_PAGE_SIZE); uvec2 pos_atlas_pos_norm_ao = verts[vertex_index]; uint v_pos_norm = pos_atlas_pos_norm_ao.x; uint v_atlas_pos = pos_atlas_pos_norm_ao.y; // Expand the model vertex position bits into float values - vec3 v_pos = vec3( - float(v_pos_norm & 0xFFu) - VERT_EXTRA_NEG_XY, - float((v_pos_norm >> 8) & 0xFFu) - VERT_EXTRA_NEG_XY, - float((v_pos_norm >> 16) & 0x0FFFu) - VERT_EXTRA_NEG_Z - ); + vec3 v_pos = vec3(ivec3((uvec3(v_pos_norm) >> uvec3(0, 8, 16)) & uvec3(0xFFu, 0xFFu, 0x0FFFu)) - ivec3(VERT_EXTRA_NEG_XY, VERT_EXTRA_NEG_XY, VERT_EXTRA_NEG_Z)); // Position of the sprite block in the chunk // Used for highlighting the selected sprite, and for opening doors vec3 sprite_pos = inst_mat[3].xyz + chunk_offs; - float sprite_ori = (inst_pos_ori_door >> 29) & 0x7u; #ifndef EXPERIMENTAL_BAREMINIMUM if((inst_pos_ori_door & (1 << 28)) != 0) { @@ -128,6 +124,7 @@ void main() { float min_entity_dist = nearest_entity(sprite_pos, 1.0).w; if (min_entity_dist < MAX_OPEN_DIST) { + float sprite_ori = (inst_pos_ori_door >> 29) & 0x7u; float flip = sprite_ori <= 3 ? 1.0 : -1.0; float theta = mix(PI/2.0, 0, pow(max(0.0, min_entity_dist - MIN_OPEN_DIST) / (MAX_OPEN_DIST - MIN_OPEN_DIST), 1.0)); float costheta = cos(flip * theta); @@ -191,14 +188,7 @@ void main() { // Shader@0x000001AABD89BEE0(112,43-53): error X4576: Input array signature parameter cannot be indexed dynamically. //vec3 norm = (inst_mat[(v_pos_norm >> 30u) & 3u].xyz); uint index = v_pos_norm >> 30u & 3u; - vec3 norm; - if (index == 0) { - norm = (inst_mat[0].xyz); - } else if (index == 1) { - norm = (inst_mat[1].xyz); - } else { - norm = (inst_mat[2].xyz); - } + vec3 norm = (inst_mat[index].xyz); f_norm = normalize(mix(-norm, norm, v_pos_norm >> 29u & 1u)); diff --git a/assets/voxygen/shaders/terrain-frag.glsl b/assets/voxygen/shaders/terrain-frag.glsl index b0cbf811f2..cce1d308f8 100644 --- a/assets/voxygen/shaders/terrain-frag.glsl +++ b/assets/voxygen/shaders/terrain-frag.glsl @@ -245,7 +245,7 @@ void main() { #else const float f_alpha = 1.0; #endif - #if (CLOUD_MODE != CLOUD_MODE_NONE) + #if (CLOUD_MODE != CLOUD_MODE_NONE && REFLECTION_MODE >= REFLECTION_MODE_MEDIUM) if (rain_density > 0 && !faces_fluid && f_norm.z > 0.5) { vec3 pos = f_pos + focus_off.xyz; vec3 drop_density = vec3(2, 2, 2); @@ -311,9 +311,9 @@ void main() { /* float sun_shade_frac = horizon_at(f_pos, sun_dir); float moon_shade_frac = horizon_at(f_pos, moon_dir); */ // float f_alt = alt_at(f_pos.xy); - // vec4 f_shadow = textureBicubic(t_horizon, pos_to_tex(f_pos.xy)); + // vec4 f_shadow = textureMaybeBicubic(t_horizon, pos_to_tex(f_pos.xy)); #if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP) - vec4 f_shadow = textureBicubic(t_horizon, s_horizon, pos_to_tex(f_pos.xy)); + vec4 f_shadow = textureMaybeBicubic(t_horizon, s_horizon, pos_to_tex(f_pos.xy)); float sun_shade_frac = horizon_at2(f_shadow, f_alt, f_pos, sun_dir); #elif (SHADOW_MODE == SHADOW_MODE_NONE) float sun_shade_frac = 1.0;//horizon_at2(f_shadow, f_alt, f_pos, sun_dir); diff --git a/assets/voxygen/shaders/terrain-vert.glsl b/assets/voxygen/shaders/terrain-vert.glsl index 893c186ea2..ee9b2174db 100644 --- a/assets/voxygen/shaders/terrain-vert.glsl +++ b/assets/voxygen/shaders/terrain-vert.glsl @@ -71,8 +71,8 @@ const float EXTRA_NEG_Z = 32768.0; void main() { // over it (if this vertex to see if it intersects. - // f_chunk_pos = vec3(ivec3((uvec3(v_pos_norm) >> uvec3(0, 6, 12)) & uvec3(0x3Fu, 0x3Fu, 0xFFFFu)) - ivec3(0, 0, EXTRA_NEG_Z)); - vec3 f_chunk_pos = vec3(v_pos_norm & 0x3Fu, (v_pos_norm >> 6) & 0x3Fu, float((v_pos_norm >> 12) & 0xFFFFu) - EXTRA_NEG_Z); + vec3 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 = (model_mat * vec4(f_chunk_pos, 1.0)).xyz - focus_off.xyz; f_load_time = load_time; @@ -125,7 +125,7 @@ void main() { // Also precalculate shadow texture and estimated terrain altitude. // f_alt = alt_at(f_pos.xy); - // f_shadow = textureBicubic(t_horizon, pos_to_tex(f_pos.xy)); + // f_shadow = textureMaybeBicubic(t_horizon, pos_to_tex(f_pos.xy)); // IDEA: Cast a ray from the vertex to the camera (if this vertex is above the camera) or from the camera to the vertex (if this // vertex is below the camera) to see where it intersects the plane of water. All of this only applies if either the terrain