Adding shadows, greedy meshing, and more.

This commit is contained in:
Joshua Yanovski 2020-07-02 22:10:22 +02:00
parent eaea83fe6a
commit 618a18c998
93 changed files with 10072 additions and 4954 deletions

41
Cargo.lock generated
View File

@ -1274,25 +1274,13 @@ dependencies = [
[[package]]
name = "euclid"
version = "0.19.9"
version = "0.20.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "596b99621b9477e7a5f94d2d8dd13a9c5c302ac358b822c67a42b6f1054450e1"
checksum = "555d51b9a929edb14183fad621e2d5736fc8760707a24246047288d4c142b6bd"
dependencies = [
"euclid_macros",
"num-traits 0.2.11",
]
[[package]]
name = "euclid_macros"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdcb84c18ea5037a1c5a23039b4ff29403abce2e0d6b1daa11cf0bde2b30be15"
dependencies = [
"proc-macro2 0.4.30",
"quote 0.6.13",
"syn 0.15.44",
]
[[package]]
name = "failure"
version = "0.1.7"
@ -1952,8 +1940,9 @@ dependencies = [
[[package]]
name = "guillotiere"
version = "0.4.2"
source = "git+https://github.com/Imberflur/guillotiere#42c298f5bcf0f95f1a004360d05e25ca3711e9ed"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47065d052e2f000066c4ffbea7051e55bff5c1532c400fc1e269492b2474ccc1"
dependencies = [
"euclid",
"svg_fmt",
@ -4417,9 +4406,9 @@ checksum = "da5b4a0c9f3c7c8e891e445a7c776627e208e8bba23ab680798066dd283e6a15"
[[package]]
name = "svg_fmt"
version = "0.2.1"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20e5f95e89d737f30cd1f98a9af9a85c2a1cc162cfedfba5a0c54cf92d7206fc"
checksum = "8fb1df15f412ee2e9dfc1c504260fa695c1c3f10fe9f4a6ee2d2184d7d6450e2"
[[package]]
name = "syn"
@ -4945,9 +4934,9 @@ dependencies = [
[[package]]
name = "vek"
version = "0.10.0"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c98f7e1c1400d5b1704baee82cbc56a3fde406769555ead0f2306e43ebab967"
checksum = "2657d8704e5e0be82b60157c8dbc71a269273ad766984508fdc54030a0690c4d"
dependencies = [
"approx 0.3.2",
"num-integer",
@ -4981,7 +4970,7 @@ dependencies = [
"rayon",
"specs",
"uvth",
"vek 0.10.0",
"vek 0.11.2",
"veloren-common",
"veloren-world",
]
@ -5016,7 +5005,7 @@ dependencies = [
"specs",
"specs-idvs",
"sum_type",
"vek 0.10.0",
"vek 0.11.2",
]
[[package]]
@ -5045,7 +5034,7 @@ dependencies = [
"specs",
"specs-idvs",
"uvth",
"vek 0.10.0",
"vek 0.11.2",
"veloren-common",
"veloren-world",
]
@ -5083,6 +5072,7 @@ dependencies = [
"fern",
"gfx",
"gfx_device_gl",
"gfx_gl",
"gfx_window_glutin",
"gilrs",
"git2",
@ -5103,7 +5093,7 @@ dependencies = [
"specs-idvs",
"treeculler",
"uvth",
"vek 0.10.0",
"vek 0.11.2",
"veloren-client",
"veloren-common",
"veloren-server",
@ -5119,6 +5109,7 @@ dependencies = [
"arr_macro",
"bincode",
"bitvec",
"criterion",
"fxhash",
"hashbrown",
"image",
@ -5138,7 +5129,7 @@ dependencies = [
"roots",
"serde",
"serde_derive",
"vek 0.10.0",
"vek 0.11.2",
"veloren-common",
]

View File

@ -561,5 +561,33 @@
"generic": "Reddragon"
}
}
},
"object": {
"body": {
"keyword": "object",
"names": []
},
"species": null
},
"fish_small": {
"body": {
"keyword": "fish_small",
"names": []
},
"species": null
},
"fish_medium": {
"body": {
"keyword": "fish_medium",
"names": []
},
"species": null
},
"bird_small": {
"body": {
"keyword": "bird_small",
"names": []
},
"species": null
}
}

View File

@ -17,16 +17,40 @@
#include <globals.glsl>
in vec3 f_pos;
in vec3 f_col;
in float f_ao;
// in float dummy;
// in vec3 f_col;
// in float f_ao;
// flat in uint f_pos_norm;
flat in vec3 f_norm;
/*centroid */in vec2 f_uv_pos;
// in float f_alt;
// in vec4 f_shadow;
// in vec3 light_pos[2];
// #if (SHADOW_MODE == SHADOW_MODE_MAP)
// in vec4 sun_pos;
// #elif (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_NONE)
// const vec4 sun_pos = vec4(0.0);
// #endif
uniform sampler2D t_col_light;
//struct ShadowLocals {
// mat4 shadowMatrices;
// mat4 texture_mat;
//};
//
//layout (std140)
//uniform u_light_shadows {
// ShadowLocals shadowMats[/*MAX_LAYER_FACES*/192];
//};
layout (std140)
uniform u_locals {
mat4 model_mat;
vec4 model_col;
ivec4 atlas_offs;
vec3 model_pos;
// bit 0 - is player
// bit 1-31 - unused
int flags;
@ -34,6 +58,7 @@ uniform u_locals {
struct BoneData {
mat4 bone_mat;
mat4 normals_mat;
};
layout (std140)
@ -48,28 +73,81 @@ uniform u_bones {
out vec4 tgt_color;
void main() {
// vec2 texSize = textureSize(t_col_light, 0);
// vec4 col_light = texture(t_col_light, (f_uv_pos + 0.5) / texSize);
// vec3 f_col = col_light.rgb;
// float f_ao = col_light.a;
// vec4 f_col_light = texture(t_col_light, (f_uv_pos + 0.5) / textureSize(t_col_light, 0));
// vec3 f_col = f_col_light.rgb;
// float f_ao = f_col_light.a;
// vec2 f_uv_pos = f_uv_pos + atlas_offs.xy;
vec4 f_col_light = texelFetch(t_col_light, ivec2(f_uv_pos)/* + uv_delta*//* - f_norm * 0.00001*/, 0);
// vec4 f_col_light = texelFetch(t_col_light, ivec2(int(f_uv_pos.x), int(f_uv_pos.y)/* + uv_delta*//* - f_norm * 0.00001*/), 0);
vec3 f_col = /*linear_to_srgb*//*srgb_to_linear*/(f_col_light.rgb);
// vec3 f_col = vec3(1.0);
// vec2 texSize = textureSize(t_col_light, 0);
float f_ao = texture(t_col_light, (f_uv_pos + 0.5) / textureSize(t_col_light, 0)).a;//1.0;//f_col_light.a * 4.0;// f_light = float(v_col_light & 0x3Fu) / 64.0;
// float /*f_light*/f_ao = textureProj(t_col_light, vec3(f_uv_pos, texSize)).a;//1.0;//f_col_light.a * 4.0;// f_light = float(v_col_light & 0x3Fu) / 64.0;
// vec3 my_chunk_pos = (vec3((uvec3(f_pos_norm) >> uvec3(0, 9, 18)) & uvec3(0x1FFu)) - 256.0) / 2.0;
// tgt_color = vec4(hash(floor(vec4(my_chunk_pos.x, 0, 0, 0))), hash(floor(vec4(0, my_chunk_pos.y, 0, 1))), hash(floor(vec4(0, 0, my_chunk_pos.z, 2))), 1.0);
// float f_ao = 0;
// tgt_color = vec4(vec3(f_ao), 1.0);
// tgt_color = vec4(f_col, 1.0);
// return;
// vec3 du = dFdx(f_pos);
// vec3 dv = dFdy(f_pos);
// vec3 f_norm = normalize(cross(du, dv));
// vec4 light_pos[2];
//#if (SHADOW_MODE == SHADOW_MODE_MAP)
// // for (uint i = 0u; i < light_shadow_count.z; ++i) {
// // light_pos[i] = /*vec3(*/shadowMats[i].texture_mat * vec4(f_pos, 1.0)/*)*/;
// // }
// vec4 sun_pos = /*vec3(*/shadowMats[0].texture_mat * vec4(f_pos, 1.0)/*)*/;
//#elif (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_NONE)
// vec4 sun_pos = vec4(0.0);
//#endif
vec3 cam_to_frag = normalize(f_pos - cam_pos.xyz);
// vec4 vert_pos4 = view_mat * vec4(f_pos, 1.0);
// vec3 view_dir = normalize(-vec3(vert_pos4)/* / vert_pos4.w*/);
vec3 view_dir = -cam_to_frag;
vec3 sun_dir = get_sun_dir(time_of_day.x);
vec3 moon_dir = get_moon_dir(time_of_day.x);
/* vec3 sun_dir = get_sun_dir(time_of_day.x);
vec3 moon_dir = get_moon_dir(time_of_day.x); */
// float sun_light = get_sun_brightness(sun_dir);
// float moon_light = get_moon_brightness(moon_dir);
/* float sun_shade_frac = horizon_at(f_pos, sun_dir);
float moon_shade_frac = horizon_at(f_pos, moon_dir); */
#if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP || FLUID_MODE == FLUID_MODE_SHINY)
float f_alt = alt_at(f_pos.xy);
#elif (SHADOW_MODE == SHADOW_MODE_NONE || FLUID_MODE == FLUID_MODE_CHEAP)
float f_alt = f_pos.z;
#endif
#if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP)
vec4 f_shadow = textureBicubic(t_horizon, pos_to_tex(f_pos.xy));
float sun_shade_frac = horizon_at2(f_shadow, f_alt, f_pos, sun_dir);
float moon_shade_frac = horizon_at2(f_shadow, f_alt, f_pos, moon_dir);
#elif (SHADOW_MODE == SHADOW_MODE_NONE)
float sun_shade_frac = 1.0;//horizon_at2(f_shadow, f_alt, f_pos, sun_dir);
#endif
float moon_shade_frac = 1.0;// horizon_at2(f_shadow, f_alt, f_pos, moon_dir);
// Globbal illumination "estimate" used to light the faces of voxels which are parallel to the sun or moon (which is a very common occurrence).
// Will be attenuated by k_d, which is assumed to carry any additional ambient occlusion information (e.g. about shadowing).
// float ambient_sides = clamp(mix(0.5, 0.0, abs(dot(-f_norm, sun_dir)) * 10000.0), 0.0, 0.5);
// NOTE: current assumption is that moon and sun shouldn't be out at the sae time.
// This assumption is (or can at least easily be) wrong, but if we pretend it's true we avoids having to explicitly pass in a separate shadow
// for the sun and moon (since they have different brightnesses / colors so the shadows shouldn't attenuate equally).
float shade_frac = /*1.0;*/sun_shade_frac + moon_shade_frac;
// float shade_frac = /*1.0;*/sun_shade_frac + moon_shade_frac;
// DirectionalLight sun_info = get_sun_info(sun_dir, sun_shade_frac, light_pos);
float point_shadow = shadow_at(f_pos, f_norm);
DirectionalLight sun_info = get_sun_info(sun_dir, point_shadow * sun_shade_frac, /*sun_pos*/f_pos);
DirectionalLight moon_info = get_moon_info(moon_dir, point_shadow * moon_shade_frac/*, light_pos*/);
vec3 surf_color = /*srgb_to_linear*/(model_col.rgb * f_col);
float alpha = 1.0;
@ -86,20 +164,22 @@ void main() {
vec3 emitted_light, reflected_light;
float point_shadow = shadow_at(f_pos, f_norm);
// vec3 light_frac = /*vec3(1.0);*//*vec3(max(dot(f_norm, -sun_dir) * 0.5 + 0.5, 0.0));*/light_reflection_factor(f_norm, view_dir, vec3(0, 0, -1.0), vec3(1.0), vec3(R_s), alpha);
// vec3 point_light = light_at(f_pos, f_norm);
// vec3 light, diffuse_light, ambient_light;
//get_sun_diffuse(f_norm, time_of_day.x, view_dir, k_a * point_shadow * (shade_frac * 0.5 + light_frac * 0.5), k_d * point_shadow * shade_frac, k_s * point_shadow * shade_frac, alpha, emitted_light, reflected_light);
float max_light = 0.0;
max_light += get_sun_diffuse2(f_norm, sun_dir, moon_dir, view_dir, k_a/* * (shade_frac * 0.5 + light_frac * 0.5)*/, k_d, k_s, alpha, emitted_light, reflected_light);
reflected_light *= point_shadow * shade_frac;
emitted_light *= point_shadow * max(shade_frac, MIN_SHADOW);
max_light *= point_shadow * shade_frac;
max_light += get_sun_diffuse2(sun_info, moon_info, f_norm, view_dir, k_a/* * (shade_frac * 0.5 + light_frac * 0.5)*/, k_d, k_s, alpha, emitted_light, reflected_light);
// reflected_light *= point_shadow * shade_frac;
// emitted_light *= point_shadow * max(shade_frac, MIN_SHADOW);
// max_light *= point_shadow * shade_frac;
// reflected_light *= point_shadow;
// emitted_light *= point_shadow;
// max_light *= point_shadow;
max_light += lights_at(f_pos, f_norm, view_dir, k_a, k_d, k_s, alpha, emitted_light, reflected_light);
float ao = /*pow(f_ao, 0.5)*/f_ao * 0.85 + 0.15;
float ao = f_ao;//0.25 + f_ao * 0.75; ///*pow(f_ao, 0.5)*/f_ao * 0.85 + 0.15;
reflected_light *= ao;
emitted_light *= ao;
@ -118,21 +198,25 @@ void main() {
// vec3 surf_color = illuminate(srgb_to_linear(model_col.rgb * f_col), light, diffuse_light, ambient_light);
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/*view_dir*/, time_of_day.x, cam_pos.xyz, f_pos, 0.5, true, 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;
// if ((flags & 1) == 1 && int(cam_mode) == 1) {
// float distance = distance(vec3(cam_pos), focus_pos.xyz) - 2;
float opacity = clamp(distance / distance_divider, 0, 1);
// float opacity = clamp(distance / distance_divider, 0, 1);
if(threshold_matrix[int(gl_FragCoord.x) % 4][int(gl_FragCoord.y) % 4] > opacity) {
discard;
return;
}
}
// // if(threshold_matrix[int(gl_FragCoord.x) % 4][int(gl_FragCoord.y) % 4] > opacity) {
// // discard;
// // return;
// // }
// }
tgt_color = vec4(color, 1.0);
}

View File

@ -16,14 +16,19 @@
#include <lod.glsl>
in uint v_pos_norm;
in vec3 v_norm;
in uint v_col;
in uint v_ao_bone;
in uint v_atlas_pos;
// in vec3 v_norm;
/* in uint v_col;
// out vec3 light_pos[2];
in uint v_ao_bone; */
layout (std140)
uniform u_locals {
mat4 model_mat;
vec4 model_col;
ivec4 atlas_offs;
vec3 model_pos;
// bit 0 - is player
// bit 1-31 - unused
int flags;
@ -31,6 +36,7 @@ uniform u_locals {
struct BoneData {
mat4 bone_mat;
mat4 normals_mat;
};
layout (std140)
@ -39,46 +45,96 @@ uniform u_bones {
BoneData bones[16];
};
//struct ShadowLocals {
// mat4 shadowMatrices;
// mat4 texture_mat;
//};
//
//layout (std140)
//uniform u_light_shadows {
// ShadowLocals shadowMats[/*MAX_LAYER_FACES*/192];
//};
out vec3 f_pos;
out vec3 f_col;
out float f_ao;
// flat out uint f_pos_norm;
flat out vec3 f_norm;
// float dummy;
/*centroid */out vec2 f_uv_pos;
// out vec3 f_col;
// out float f_ao;
// out float f_alt;
// out vec4 f_shadow;
// #if (SHADOW_MODE == SHADOW_MODE_MAP)
// out vec4 sun_pos;
// #endif
void main() {
// Pre-calculate bone matrix
uint bone_idx = (v_ao_bone >> 2) & 0x3Fu;
mat4 combined_mat = model_mat * bones[bone_idx].bone_mat;
/* uint bone_idx = (v_ao_bone >> 2) & 0x3Fu; */
uint bone_idx = (v_pos_norm >> 27) & 0xFu;
BoneData bone_data = bones[bone_idx];
mat4 bone_mat = bone_data.bone_mat;
mat4 combined_mat = /*model_mat * */bone_mat;
vec3 pos = (vec3((uvec3(v_pos_norm) >> uvec3(0, 9, 18)) & uvec3(0x1FFu)) - 256.0) / 2.0;
// vec4 bone_pos = bones[bone_idx].bone_mat * vec4(pos, 1);
f_pos = (
combined_mat *
vec4(pos, 1)).xyz;
vec4(pos, 1.0)
).xyz + (model_pos - focus_off.xyz);
f_pos.z -= 25.0 * pow(distance(focus_pos.xy, f_pos.xy) / view_distance.x, 20.0);
/* f_pos.z -= 25.0 * pow(distance(focus_pos.xy, f_pos.xy) / view_distance.x, 20.0); */
f_col = srgb_to_linear(vec3((uvec3(v_col) >> uvec3(0, 8, 16)) & uvec3(0xFFu)) / 255.0);
f_uv_pos = vec2((uvec2(v_atlas_pos) >> uvec2(2, 17)) & uvec2(0x7FFFu, 0x7FFFu));
f_ao = float(v_ao_bone & 0x3u) / 4.0;
// f_col = srgb_to_linear(vec3((uvec3(v_col) >> uvec3(0, 8, 16)) & uvec3(0xFFu)) / 255.0);
// f_col = vec3(1.0);
// f_ao = float(v_ao_bone & 0x3u) / 4.0;
// f_ao = 1.0;
/* for (uint i = 0u; i < light_shadow_count.z; ++i) {
light_pos[i] = vec3(shadowMats[i].texture_mat * vec4(f_pos, 1.0));
} */
// First 3 normals are negative, next 3 are positive
vec3 normals[6] = vec3[](vec3(-1,0,0), vec3(1,0,0), vec3(0,-1,0), vec3(0,1,0), vec3(0,0,-1), vec3(0,0,1));
vec3 norm = normals[(v_pos_norm >> 29) & 0x7u];
// uint normal_idx = ((v_atlas_pos & 3u) << 1u) | (v_pos_norm >> 31u);
// const vec3 normals[6] = vec3[](vec3(-1,0,0), vec3(1,0,0), vec3(0,-1,0), vec3(0,1,0), vec3(0,0,-1), vec3(0,0,1));
// vec3 norm = normals[normal_idx];
uint axis_idx = v_atlas_pos & 3u;
// Calculate normal here rather than for each pixel in the fragment shader
f_norm = normalize((
combined_mat *
vec4(norm, 0.0)
).xyz);
vec3 norm = bone_data.normals_mat[axis_idx].xyz;
// norm = normalize(norm);
// vec3 norm = norm_mat * vec4(uvec3(1 << axis_idx) & uvec3(0x1u, 0x3u, 0x7u), 1);
// // Calculate normal here rather than for each pixel in the fragment shader
// f_norm = normalize((
// combined_mat *
// vec4(norm, 0)
// ).xyz);
f_norm = mix(-norm, norm, v_pos_norm >> 31u);
// #if (SHADOW_MODE == SHADOW_MODE_MAP)
// // for (uint i = 0u; i < light_shadow_count.z; ++i) {
// // light_pos[i] = /*vec3(*/shadowMats[i].texture_mat * vec4(f_pos, 1.0)/*)*/;
// // }
// sun_pos = /*vec3(*/shadowMats[0].texture_mat * vec4(f_pos, 1.0)/*)*/;
// // #elif (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_NONE)
// // vec4 sun_pos = vec4(0.0);
// #endif
// f_pos_norm = v_pos_norm;
// 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));
gl_Position = all_mat * vec4(f_pos, 1);
// gl_Position.z = -gl_Position.z / gl_Position.w;
gl_Position = all_mat/*shadowMats[0].shadowMatrices*/ * vec4(f_pos, 1);
// gl_Position.z = -gl_Position.z / 100.0 / gl_Position.w;
// gl_Position.z = -gl_Position.z / 100.0;
gl_Position.z = -1000.0 / (gl_Position.z + 10000.0);
// gl_Position.z = gl_Position.z / 100.0;
// gl_Position.z = -gl_Position.z;
// gl_Position.z = -1000.0 / (gl_Position.z + 10000.0);
}

View File

@ -23,14 +23,25 @@
in vec3 f_pos;
flat in uint f_pos_norm;
in vec3 f_col;
in float f_light;
// in vec3 f_col;
// in float f_light;
// in vec3 light_pos[2];
// struct ShadowLocals {
// mat4 shadowMatrices;
// mat4 texture_mat;
// };
//
// layout (std140)
// uniform u_light_shadows {
// ShadowLocals shadowMats[/*MAX_LAYER_FACES*/192];
// };
layout (std140)
uniform u_locals {
vec3 model_offs;
float load_time;
ivec4 atlas_offs;
};
uniform sampler2D t_waves;
@ -42,6 +53,8 @@ out vec4 tgt_color;
#include <lod.glsl>
void main() {
// tgt_color = vec4(1.0 - MU_WATER, 1.0);
// return;
// First 3 normals are negative, next 3 are positive
vec3 normals[6] = vec3[](vec3(-1,0,0), vec3(1,0,0), vec3(0,-1,0), vec3(0,1,0), vec3(0,0,-1), vec3(0,0,1));
@ -52,23 +65,47 @@ void main() {
// Use an array to avoid conditional branching
vec3 f_norm = normals[norm_axis + norm_dir];
// vec4 light_pos[2];
// #if (SHADOW_MODE == SHADOW_MODE_MAP)
// // for (uint i = 0u; i < light_shadow_count.z; ++i) {
// // light_pos[i] = /*vec3(*/shadowMats[i].texture_mat * vec4(f_pos, 1.0)/*)*/;
// // }
// vec4 sun_pos = /*vec3(*/shadowMats[0].texture_mat * vec4(f_pos, 1.0)/*)*/;
// #elif (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_NONE)
// vec4 sun_pos = vec4(0.0);
// #endif
vec3 cam_to_frag = normalize(f_pos - cam_pos.xyz);
// vec4 vert_pos4 = view_mat * vec4(f_pos, 1.0);
// vec3 view_dir = normalize(-vec3(vert_pos4)/* / vert_pos4.w*/);
vec3 view_dir = -cam_to_frag;
// vec3 surf_color = /*srgb_to_linear*/(vec3(0.4, 0.7, 2.0));
/*const */vec3 water_color = 1.0 - MU_WATER;//srgb_to_linear(vec3(0.2, 0.5, 1.0));
/*const */vec3 water_color = (1.0 - MU_WATER) * MU_SCATTER;//srgb_to_linear(vec3(0.2, 0.5, 1.0));
// /*const */vec3 water_color = srgb_to_linear(vec3(0.0, 0.25, 0.5));
vec3 sun_dir = get_sun_dir(time_of_day.x);
vec3 moon_dir = get_moon_dir(time_of_day.x);
/* 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 || FLUID_MODE == FLUID_MODE_SHINY)
float f_alt = alt_at(f_pos.xy);
#elif (SHADOW_MODE == SHADOW_MODE_NONE || FLUID_MODE == FLUID_MODE_CHEAP)
float f_alt = f_pos.z;
#endif
#if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP)
vec4 f_shadow = textureBicubic(t_horizon, pos_to_tex(f_pos.xy));
float sun_shade_frac = horizon_at2(f_shadow, f_alt, f_pos, sun_dir);
float moon_shade_frac = horizon_at2(f_shadow, f_alt, f_pos, moon_dir);
#elif (SHADOW_MODE == SHADOW_MODE_NONE)
float sun_shade_frac = 1.0;//horizon_at2(f_shadow, f_alt, f_pos, sun_dir);
#endif
float moon_shade_frac = 1.0;//horizon_at2(f_shadow, f_alt, f_pos, moon_dir);
// float sun_shade_frac = horizon_at(/*f_shadow, f_pos.z, */f_pos, sun_dir);
// float moon_shade_frac = horizon_at(/*f_shadow, f_pos.z, */f_pos, moon_dir);
float shade_frac = /*1.0;*/sun_shade_frac + moon_shade_frac;
// float shade_frac = /*1.0;*/sun_shade_frac + moon_shade_frac;
// DirectionalLight sun_info = get_sun_info(sun_dir, sun_shade_frac, light_pos);
float point_shadow = shadow_at(f_pos, f_norm);
DirectionalLight sun_info = get_sun_info(sun_dir, point_shadow * sun_shade_frac, /*sun_pos*/f_pos);
DirectionalLight moon_info = get_moon_info(moon_dir, point_shadow * moon_shade_frac/*, light_pos*/);
float fluid_alt = f_pos.z;//max(ceil(f_pos.z), floor(f_alt));// f_alt;//max(f_alt - f_pos.z, 0.0);
@ -100,18 +137,20 @@ void main() {
// vec3 cam_to_frag = normalize(f_pos - cam_pos.xyz);
// vec3 emitted_light, reflected_light;
// vec3 light, diffuse_light, ambient_light;
float point_shadow = shadow_at(f_pos,f_norm);
// Squared to account for prior saturation.
float f_light = pow(f_light, 1.5);
// float f_light = 1.0;// pow(f_light, 1.5);
// float vert_light = f_light;
// vec3 light_frac = /*vec3(1.0);*/light_reflection_factor(f_norm/*vec3(0, 0, 1.0)*/, view_dir, vec3(0, 0, -1.0), vec3(1.0), vec3(R_s), alpha);
// vec3 surf_color = /*srgb_to_linear*/(vec3(0.4, 0.7, 2.0));
float max_light = 0.0;
max_light += get_sun_diffuse2(f_norm, /*time_of_day.x*/sun_dir, moon_dir, /*-cam_to_frag*/sun_view_dir/*view_dir*/, f_pos, mu, cam_attenuation, fluid_alt, k_a/* * (shade_frac * 0.5 + light_frac * 0.5)*/, /*vec3(0.0)*/k_d, k_s, alpha, 1.0, emitted_light, reflected_light);
reflected_light *= f_light * point_shadow * shade_frac;
emitted_light *= f_light * point_shadow * max(shade_frac, MIN_SHADOW);
max_light *= f_light * point_shadow * shade_frac;
max_light += get_sun_diffuse2(sun_info, moon_info, f_norm, /*time_of_day.x*//*-cam_to_frag*/sun_view_dir/*view_dir*/, f_pos, mu, cam_attenuation, fluid_alt, k_a/* * (shade_frac * 0.5 + light_frac * 0.5)*/, /*vec3(0.0)*/k_d, k_s, alpha, f_norm, 1.0, emitted_light, reflected_light);
// reflected_light *= f_light * point_shadow * shade_frac;
// emitted_light *= f_light * point_shadow * max(shade_frac, MIN_SHADOW);
// max_light *= f_light * point_shadow * shade_frac;
// reflected_light *= f_light * point_shadow;
// emitted_light *= f_light * point_shadow;
// max_light *= f_light * point_shadow;
// get_sun_diffuse(f_norm, time_of_day.x, light, diffuse_light, ambient_light, 0.0);
// diffuse_light *= f_light * point_shadow;
// ambient_light *= f_light, point_shadow;
@ -126,11 +165,12 @@ void main() {
emitted_light += point_light;
reflected_light += point_light; */
max_light += lights_at(f_pos, /*f_norm*/cam_norm, view_dir, mu, cam_attenuation, fluid_alt, k_a, k_d, k_s, alpha, 1.0, emitted_light, reflected_light);
max_light += lights_at(f_pos, /*f_norm*/cam_norm, view_dir, mu, cam_attenuation, fluid_alt, k_a, k_d, k_s, alpha, f_norm, 1.0, emitted_light, reflected_light);
// vec3 diffuse_light_point = vec3(0.0);
// max_light += lights_at(f_pos, f_norm, view_dir, k_a, vec3(1.0), k_s, alpha, emitted_light, diffuse_light_point);
float reflected_light_point = length(reflected_light);///*length*/(diffuse_light_point.r) + f_light * point_shadow;
// float reflected_light_point = length(reflected_light);///*length*/(diffuse_light_point.r) + f_light * point_shadow;
// float reflected_light_point = dot(reflected_light, reflected_light) * 0.5;///*length*/(diffuse_light_point.r) + f_light * point_shadow;
// vec3 dump_light = vec3(0.0);
// vec3 specular_light_point = vec3(0.0);
// lights_at(f_pos, f_norm, view_dir, vec3(0.0), vec3(0.0), /*vec3(1.0)*/k_s, alpha, dump_light, specular_light_point);
@ -139,14 +179,20 @@ void main() {
// float reflected_light_point = /*length*/(diffuse_light_point.r) + f_light * point_shadow;
// reflected_light += k_d * (diffuse_light_point + f_light * point_shadow * shade_frac) + specular_light_point;
float passthrough = /*pow(*/dot(cam_norm, -cam_to_frag/*view_dir*/)/*, 0.5)*/;
float min_refl = min(emitted_light.r, min(emitted_light.g, emitted_light.b));
vec3 surf_color = illuminate(max_light, view_dir, water_color * /* fog_color * */emitted_light, /*surf_color * */water_color * reflected_light);
// 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, true, clouds);
float passthrough = /*pow(*/dot(cam_norm, -cam_to_frag/*view_dir*/)/*, 0.5)*/;
vec3 surf_color = illuminate(max_light, view_dir, water_color * fog_color * emitted_light, /*surf_color * */water_color * reflected_light);
vec4 color = mix(vec4(surf_color, 1.0), vec4(surf_color, 1.0 / (1.0 + /*diffuse_light*//*(f_light * point_shadow + point_light)*/4.0 * reflected_light_point/* * 0.25*/)), passthrough);
tgt_color = mix(mix(color, vec4(fog_color, 0.0), fog_level), vec4(clouds.rgb, 0.0), clouds.a);
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;
}

View File

@ -25,13 +25,25 @@
in vec3 f_pos;
flat in uint f_pos_norm;
in vec3 f_col;
in float f_light;
// in vec3 f_col;
// in float f_light;
// in vec3 light_pos[2];
//struct ShadowLocals {
// mat4 shadowMatrices;
// mat4 texture_mat;
//};
//
//layout (std140)
//uniform u_light_shadows {
// ShadowLocals shadowMats[/*MAX_LAYER_FACES*/192];
//};
layout (std140)
uniform u_locals {
vec3 model_offs;
float load_time;
ivec4 atlas_offs;
};
uniform sampler2D t_waves;
@ -89,6 +101,16 @@ void main() {
// Use an array to avoid conditional branching
vec3 f_norm = normals[norm_axis + norm_dir];
// vec4 light_pos[2];
//#if (SHADOW_MODE == SHADOW_MODE_MAP)
// // for (uint i = 0u; i < light_shadow_count.z; ++i) {
// // light_pos[i] = /*vec3(*/shadowMats[i].texture_mat * vec4(f_pos, 1.0)/*)*/;
// // }
// vec4 sun_pos = /*vec3(*/shadowMats[0].texture_mat * vec4(f_pos, 1.0)/*)*/;
//#elif (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_NONE)
// vec4 sun_pos = vec4(0.0);
//#endif
vec3 cam_to_frag = normalize(f_pos - cam_pos.xyz);
// vec4 vert_pos4 = view_mat * vec4(f_pos, 1.0);
// vec3 view_dir = normalize(-vec3(vert_pos4)/* / vert_pos4.w*/);
@ -121,7 +143,11 @@ void main() {
vec3 norm = vec3(0, 0, 1) * nmap.z + b_norm * nmap.x + c_norm * nmap.y;
// vec3 norm = f_norm;
#if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP || FLUID_MODE == FLUID_MODE_SHINY)
float f_alt = alt_at(f_pos.xy);
#elif (SHADOW_MODE == SHADOW_MODE_NONE || FLUID_MODE == FLUID_MODE_CHEAP)
float f_alt = f_pos.z;
#endif
float fluid_alt = max(ceil(f_pos.z), floor(f_alt));// f_alt;//max(f_alt - f_pos.z, 0.0);
const float alpha = 0.255/*/ / 4.0*//* / 4.0 / sqrt(2.0)*/;
@ -144,7 +170,7 @@ void main() {
reflect_ray_dir = normalize(vec3(reflect_ray_dir4) / reflect_ray_dir4.w); */
// vec3 cam_to_frag = normalize(f_pos - cam_pos.xyz);
// Squared to account for prior saturation.
float f_light = pow(f_light, 1.5);
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, false, _clouds) * f_light;
// /*const */vec3 water_color = srgb_to_linear(vec3(0.2, 0.5, 1.0));
// /*const */vec3 water_color = srgb_to_linear(vec3(0.8, 0.9, 1.0));
@ -153,14 +179,23 @@ void main() {
// /*const */vec3 water_attenuation = MU_WATER;// vec3(0.8, 0.05, 0.01);
// /*const */vec3 water_color = vec3(0.2, 0.95, 0.99);
vec3 sun_dir = get_sun_dir(time_of_day.x);
vec3 moon_dir = get_moon_dir(time_of_day.x);
/* 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, pos_to_tex(f_pos.xy));
float sun_shade_frac = horizon_at2(f_shadow, f_alt, f_pos, sun_dir);
float moon_shade_frac = horizon_at2(f_shadow, f_alt, f_pos, moon_dir);
#elif (SHADOW_MODE == SHADOW_MODE_NONE)
float sun_shade_frac = 1.0;//horizon_at2(f_shadow, f_alt, f_pos, sun_dir);
#endif
float moon_shade_frac = 1.0;// horizon_at2(f_shadow, f_alt, f_pos, moon_dir);
// float sun_shade_frac = horizon_at(/*f_shadow, f_pos.z, */f_pos, sun_dir);
// float moon_shade_frac = horizon_at(/*f_shadow, f_pos.z, */f_pos, moon_dir);
float shade_frac = /*1.0;*/sun_shade_frac + moon_shade_frac;
// float shade_frac = /*1.0;*/sun_shade_frac + moon_shade_frac;
// DirectionalLight sun_info = get_sun_info(sun_dir, sun_shade_frac, light_pos);
float point_shadow = shadow_at(f_pos, f_norm);
DirectionalLight sun_info = get_sun_info(sun_dir, point_shadow * sun_shade_frac, /*sun_pos*/f_pos);
DirectionalLight moon_info = get_moon_info(moon_dir, point_shadow * moon_shade_frac/*, light_pos*/);
// Hack to determine water depth: color goes down with distance through water, so
// we assume water color absorption from this point a to some other point b is the distance
@ -206,16 +241,18 @@ void main() {
vec3 emitted_light, reflected_light;
// vec3 light, diffuse_light, ambient_light;
float point_shadow = shadow_at(f_pos, f_norm);
// vec3 light_frac = /*vec3(1.0);*/light_reflection_factor(f_norm/*vec3(0, 0, 1.0)*/, view_dir, vec3(0, 0, -1.0), vec3(1.0), vec3(R_s), alpha);
// 0 = 100% reflection, 1 = translucent water
float passthrough = /*pow(*/dot(faceforward(norm, norm, cam_to_frag/*view_dir*/), -cam_to_frag/*view_dir*/)/*, 0.5)*/;
float max_light = 0.0;
max_light += get_sun_diffuse2(norm, /*time_of_day.x*/sun_dir, moon_dir, 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, 1.0, emitted_light, reflected_light);
reflected_light *= /*water_color_direct * */reflect_color * f_light * point_shadow * shade_frac;
emitted_light *= /*water_color_direct*//*ambient_attenuation * */f_light * point_shadow * max(shade_frac, MIN_SHADOW);
max_light *= f_light * point_shadow * shade_frac;
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);
// 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;
// reflected_light *= /*water_color_direct * */reflect_color * f_light * point_shadow;
// emitted_light *= /*water_color_direct*//*ambient_attenuation * */f_light * point_shadow;
// max_light *= f_light * point_shadow;
// vec3 diffuse_light_point = vec3(0.0);
// max_light += lights_at(f_pos, cam_norm, view_dir, mu, cam_attenuation, fluid_alt, k_a, vec3(1.0), /*vec3(0.0)*/k_s, alpha, emitted_light, diffuse_light_point);
@ -226,7 +263,7 @@ void main() {
// diffuse_light_point -= specular_light_point;
// max_light += lights_at(f_pos, cam_norm, view_dir, mu, cam_attenuation, fluid_alt, k_a, /*k_d*/vec3(0.0), /*vec3(0.0)*/k_s, alpha, emitted_light, /*diffuse_light*/reflected_light);
max_light += lights_at(f_pos, cam_norm, view_dir, mu, cam_attenuation, fluid_alt, k_a, /*k_d*//*vec3(0.0)*/k_d, /*vec3(0.0)*/k_s, alpha, 1.0, emitted_light, /*diffuse_light*/reflected_light);
max_light += lights_at(f_pos, cam_norm, view_dir, mu, cam_attenuation, fluid_alt, k_a, /*k_d*//*vec3(0.0)*/k_d, /*vec3(0.0)*/k_s, alpha, f_norm, 1.0, emitted_light, /*diffuse_light*/reflected_light);
float reflected_light_point = length(reflected_light);///*length*/(diffuse_light_point.r) + f_light * point_shadow;
// TODO: See if we can be smarter about this using point light distances.
@ -246,10 +283,6 @@ void main() {
// vec3 surf_color = srgb_to_linear(vec3(0.2, 0.5, 1.0)) * light * diffuse_light * ambient_light;
vec3 surf_color = illuminate(max_light, view_dir, emitted_light/* * log(1.0 - MU_WATER)*/, /*cam_attenuation * *//*water_color * */reflected_light/* * log(1.0 - MU_WATER)*/);
float fog_level = fog(f_pos.xyz, focus_pos.xyz, medium.x);
vec4 clouds;
vec3 fog_color = get_sky_color(cam_to_frag/*-view_dir*/, time_of_day.x, cam_pos.xyz, f_pos, 0.25, true, clouds);
// passthrough = pow(passthrough, 1.0 / (1.0 + water_depth_to_camera));
/* surf_color = cam_attenuation.g < 0.5 ?
vec3(1.0, 0.0, 0.0) :
@ -284,5 +317,13 @@ void main() {
vec4 color = mix(vec4(reflect_color, 1.0), vec4(vec3(0), 1.0 / (1.0 + diffuse_light * 0.25)), passthrough); */
tgt_color = mix(mix(color, vec4(fog_color, 0.0), fog_level), vec4(clouds.rgb, 0.0), clouds.a);
#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;
}

View File

@ -21,41 +21,56 @@
#include <random.glsl>
in uint v_pos_norm;
in uint v_col_light;
// in uint v_col_light;
layout (std140)
uniform u_locals {
vec3 model_offs;
float load_time;
ivec4 atlas_offs;
};
// struct ShadowLocals {
// mat4 shadowMatrices;
// mat4 texture_mat;
// };
//
// layout (std140)
// uniform u_light_shadows {
// ShadowLocals shadowMats[/*MAX_LAYER_FACES*/192];
// };
out vec3 f_pos;
flat out uint f_pos_norm;
out vec3 f_col;
out float f_light;
// out vec3 f_col;
// out float f_light;
// out vec3 light_pos[2];
const float EXTRA_NEG_Z = 65536.0;
const float EXTRA_NEG_Z = /*65536.0*/65536.1;
void main() {
f_pos = vec3((uvec3(v_pos_norm) >> uvec3(0, 6, 12)) & uvec3(0x3Fu, 0x3Fu, 0x1FFFFu)) - vec3(0, 0, EXTRA_NEG_Z) + model_offs;
f_pos = vec3((uvec3(v_pos_norm) >> uvec3(0, 6, 12)) & uvec3(0x3Fu, 0x3Fu, 0x1FFFFu)) - vec3(0, 0, EXTRA_NEG_Z) + model_offs - focus_off.xyz;
// f_pos.z -= 250.0 * (1.0 - min(1.0001 - 0.02 / pow(tick.x - load_time, 10.0), 1.0));
// f_pos.z -= min(32.0, 25.0 * pow(distance(focus_pos.xy, f_pos.xy) / view_distance.x, 20.0));
// Small waves
f_pos.xy += 0.01; // Avoid z-fighting
// f_pos.xy += 0.01; // Avoid z-fighting
// f_pos.x += 0.1 * sin(tick.x / 60 * hash(vec4(f_pos.xyz, 1.0)));
// f_pos.y += 0.1 * sin(tick.x / 60 * hash(vec4(f_pos.xyz, 2.0)));
#if (FLUID_MODE == FLUID_MODE_SHINY)
f_pos.z -= 0.1 + 0.1 * (sin(tick.x/* / 60.0*/* 2.0 + f_pos.x * 2.0 + f_pos.y * 2.0) + 1.0) * 0.5;
// f_pos.z -= 0.1 + 0.1 * (sin(tick.x/* / 60.0*/* 2.0 + f_pos.x * 2.0 + f_pos.y * 2.0) + 1.0) * 0.5;
#endif
f_col = vec3(
/* f_col = vec3(
float((v_col_light >> 8) & 0xFFu),
float((v_col_light >> 16) & 0xFFu),
float((v_col_light >> 24) & 0xFFu)
) / 255.0;
f_light = float(v_col_light & 0xFFu) / 255.0;
f_light = float(v_col_light & 0xFFu) / 255.0; */
/* for (uint i = 0u; i < light_shadow_count.z; ++i) {
light_pos[i] = vec3(shadowMats[i].texture_mat * vec4(f_pos, 1.0));
} */
f_pos_norm = v_pos_norm;
@ -64,5 +79,5 @@ void main() {
vec4(f_pos, 1);
// gl_Position.z = -gl_Position.z / gl_Position.w;
// gl_Position.z = -gl_Position.z / 100.0;
gl_Position.z = -1000.0 / (gl_Position.z + 10000.0);
// gl_Position.z = -1000.0 / (gl_Position.z + 10000.0);
}

View File

@ -16,6 +16,10 @@
#define LIGHTING_ALGORITHM_BLINN_PHONG 1u
#define LIGHTING_ALGORITHM_ASHIKHMIN 2u
#define SHADOW_MODE_NONE 0u
#define SHADOW_MODE_CHEAP 1u
#define SHADOW_MODE_MAP 2u
/* Unlike the other flags (for now anyway), these are bitmask values */
#define LIGHTING_TYPE_REFLECTION 0x01u
#define LIGHTING_TYPE_TRANSMISSION 0x02u
@ -43,6 +47,7 @@
#define FLUID_MODE <mode>
#define CLOUD_MODE <mode>
#define LIGHTING_ALGORITHM <algorithm>
#define SHADOW_MODE <mode>
*/
/* Constants expected to be defined by any shader that needs to perform lighting calculations
@ -56,3 +61,11 @@
#define LIGHTING_DISTRIBUTION_SCHEME <scheme>
#define LIGHTING_DISTRIBUTION <distribution>
*/
/* Constants that *may* be defined by any shader.
* (and whose values may take automatically defined constants into account): */
/*
// When sets, shadow maps are used to cast shadows.
#define HAS_SHADOW_MAPS
*/

View File

@ -4,9 +4,12 @@ uniform u_globals {
mat4 proj_mat;
mat4 all_mat;
vec4 cam_pos;
vec4 focus_off;
vec4 focus_pos;
vec4 view_distance;
vec4 time_of_day;
vec4 sun_dir;
vec4 moon_dir;
vec4 tick;
vec4 screen_res;
uvec4 light_shadow_count;

View File

@ -1,4 +1,5 @@
#include <srgb.glsl>
#include <shadows.glsl>
struct Light {
vec4 light_pos;
@ -8,7 +9,7 @@ struct Light {
layout (std140)
uniform u_lights {
Light lights[32];
Light lights[31];
};
struct Shadow {
@ -26,116 +27,6 @@ float attenuation_strength(vec3 rpos) {
return max(2.0 / pow(d2 + 10, 0.35) - pow(d2 / 50000.0, 0.8), 0.0);
}
#ifdef HAS_SHADOW_MAPS
// uniform samplerCubeArrayShadow t_shadow_maps;
// uniform samplerCubeArray t_shadow_maps;
uniform samplerCubeShadow t_shadow_maps;
// uniform samplerCube t_shadow_maps;
// uniform sampler2DArray t_directed_shadow_maps;
float VectorToDepth (vec3 Vec)
{
vec3 AbsVec = abs(Vec);
float LocalZcomp = max(AbsVec.x, max(AbsVec.y, AbsVec.z));
// float LocalZcomp = length(Vec);
// Replace f and n with the far and near plane values you used when
// you drew your cube map.
// const float f = 2048.0;
// const float n = 1.0;
// float NormZComp = (screen_res.w+screen_res.z) / (screen_res.w-screen_res.z) - (2*screen_res.w*screen_res.z)/(screen_res.w-screen_res.z)/LocalZcomp;
// float NormZComp = 1.0 - shadow_proj_factors.y / shadow_proj_factors.x / LocalZcomp;
float NormZComp = shadow_proj_factors.x - shadow_proj_factors.y / LocalZcomp;
// NormZComp = -1000.0 / (NormZComp + 10000.0);
return (NormZComp + 1.0) * 0.5;
// float NormZComp = length(LocalZcomp);
// NormZComp = -NormZComp / screen_res.w;
// // return (NormZComp + 1.0) * 0.5;
// return NormZComp;
}
const vec3 sampleOffsetDirections[20] = vec3[]
(
vec3( 1, 1, 1), vec3( 1, -1, 1), vec3(-1, -1, 1), vec3(-1, 1, 1),
vec3( 1, 1, -1), vec3( 1, -1, -1), vec3(-1, -1, -1), vec3(-1, 1, -1),
vec3( 1, 1, 0), vec3( 1, -1, 0), vec3(-1, -1, 0), vec3(-1, 1, 0),
vec3( 1, 0, 1), vec3(-1, 0, 1), vec3( 1, 0, -1), vec3(-1, 0, -1),
vec3( 0, 1, 1), vec3( 0, -1, 1), vec3( 0, -1, -1), vec3( 0, 1, -1)
// vec3(0, 0, 0)
);
float ShadowCalculation(uint lightIndex, vec3 fragToLight, /*float currentDepth*/vec3 fragPos)
{
if (lightIndex != 0u) {
return 1.0;
};
float shadow = 0.0;
float bias = 0.0;//-0.003;//-0.003;//-0.005;//0.001;//-1.0;//-0.001;//0.001;//0.003;//-0.05;//-0.1;//0.0;//0.1
{
float currentDepth = VectorToDepth(fragToLight);// + bias;
float visibility = texture(t_shadow_maps, vec4(fragToLight, currentDepth));// / (screen_res.w/* - screen_res.z*/)/*1.0 -bias*//*-(currentDepth - bias) / screen_res.w*//*-screen_res.w*/);
if (visibility == 1.0 || visibility == 0.0) {
return visibility;
}
// return visibility == 1.0 ? 1.0 : 0.0;
}
int samples = 20;
float lightDistance = length(fragToLight);
float viewDistance = length(cam_pos.xyz - fragPos);
// float diskRadius = 0.00001;
// float diskRadius = 1.0;
// float diskRadius = 0.05;
float diskRadius = (1.0 + (/*viewDistance*/viewDistance / screen_res.w)) / 25.0;
// float diskRadius = lightDistance;
for(int i = 0; i < samples; ++i)
{
float currentDepth = VectorToDepth(fragToLight + sampleOffsetDirections[i] * diskRadius) + bias;
// float closestDepth = texture(depthMap, fragToLight).r;
// closestDepth *= far_plane; // Undo mapping [0;1]
/* if(currentDepth - bias > closestDepth)
shadow += 1.0;*/
float visibility = texture(t_shadow_maps, vec4(fragToLight, currentDepth)/*, -2.5*/);
shadow += visibility;
// float closestDepth = texture(t_shadow_maps, vec3(fragToLight)/*, -2.5*/).r;
// shadow += closestDepth > currentDepth ? 1.0 : 0.0;
}
shadow /= float(samples);
// shadow = shadow * shadow * (3.0 - 2.0 * shadow);
// use the light to fragment vector to sample from the depth map
// float bias = 0.0;///*0.05*/0.01;//0.05;// 0.05;
// float closestDepth = texture(t_shadow_maps, /*vec4*/vec3(fragToLight/*, (lightIndex + 1)*//* * 6*/)/*, 0.0*//*, 0.0*//*, bias*/).r;
// // // float closestDepth = texture(t_shadow_maps, vec4(fragToLight, lightIndex), bias);
// // // it is currently in linear range between [0,1]. Re-transform back to original value
// closestDepth = (closestDepth + 0.0) * screen_res.w; // far plane
// // // now test for shadows
// // // float shadow = /*currentDepth*/(screen_res.w - bias) > closestDepth ? 1.0 : 0.0;
// float shadow = currentDepth - bias < closestDepth ? 1.0 : 0.0;
// float visibility = textureProj(t_shadow_maps, vec4(fragToLight, lightIndex), bias);
// float visibility = texture(t_shadow_maps, vec4(fragToLight, lightIndex + 1), -(currentDepth/* + screen_res.z*/) / screen_res.w);// / (screen_res.w/* - screen_res.z*/)/*1.0 -bias*//*-(currentDepth - bias) / screen_res.w*//*-screen_res.w*/);
// currentDepth += bias;
// currentDepth = -1000.0 / (currentDepth + 10000.0);
// currentDepth /= screen_res.w;
// float currentDepth = VectorToDepth(fragToLight) + bias;
// float visibility = texture(t_shadow_maps, vec4(fragToLight, currentDepth));// / (screen_res.w/* - screen_res.z*/)/*1.0 -bias*//*-(currentDepth - bias) / screen_res.w*//*-screen_res.w*/);
// return visibility == 1.0 ? 1.0 : 0.0;
return shadow;
}
#else
float ShadowCalculation(uint lightIndex, vec3 fragToLight, /*float currentDepth*/vec3 fragPos)
{
return 1.0;
}
#endif
// // Compute attenuation due to light passing through a substance that fills an area below a horizontal plane
// // (e.g. in most cases, water below the water surface depth).
// //
@ -177,7 +68,7 @@ vec3 light_at(vec3 wpos, vec3 wnorm) {
// Only access the array once
Light L = lights[i];
vec3 light_pos = L.light_pos.xyz;
vec3 light_pos = L.light_pos.xyz - focus_off.xyz;
// Pre-calculate difference between light and fragment
vec3 difference = light_pos - wpos;
@ -195,12 +86,15 @@ vec3 light_at(vec3 wpos, vec3 wnorm) {
float shadow_at(vec3 wpos, vec3 wnorm) {
float shadow = 1.0;
#if (SHADOW_MODE == SHADOW_MODE_NONE || SHADOW_MODE == SHADOW_MODE_MAP)
return shadow;
#elif (SHADOW_MODE == SHADOW_MODE_CHEAP)
for (uint i = 0u; i < light_shadow_count.y; i ++) {
// Only access the array once
Shadow S = shadows[i];
vec3 shadow_pos = S.shadow_pos_radius.xyz;
vec3 shadow_pos = S.shadow_pos_radius.xyz - focus_off.xyz;
float radius = S.shadow_pos_radius.w;
vec3 diff = shadow_pos - wpos;
@ -209,11 +103,15 @@ float shadow_at(vec3 wpos, vec3 wnorm) {
}
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);
// float shade = max(pow(dot(diff, diff) / (radius * radius * 0.5), 0.25), 0.5);
// float shade = dot(diff, diff) / (radius * radius * 0.5);
shadow = min(shadow, shade);
}
// NOTE: Squared to compenate for prior saturation.
return min(shadow * shadow, 1.0);
return min(shadow, 1.0);
// return min(shadow * shadow, 1.0);
#endif
}
// Returns computed maximum intensity.
@ -221,20 +119,21 @@ float shadow_at(vec3 wpos, vec3 wnorm) {
// mu is the attenuation coefficient for any substance on a horizontal plane.
// cam_attenuation is the total light attenuation due to the substance for beams between the point and the camera.
// surface_alt is the altitude of the attenuating surface.
float lights_at(vec3 wpos, vec3 wnorm, vec3 /*cam_to_frag*/view_dir, vec3 mu, vec3 cam_attenuation, float surface_alt, vec3 k_a, vec3 k_d, vec3 k_s, float alpha, float voxel_lighting, inout vec3 emitted_light, inout vec3 reflected_light/*, out float shadow*/) {
float lights_at(vec3 wpos, vec3 wnorm, vec3 /*cam_to_frag*/view_dir, vec3 mu, vec3 cam_attenuation, float surface_alt, vec3 k_a, vec3 k_d, vec3 k_s, float alpha, vec3 voxel_norm, float voxel_lighting, inout vec3 emitted_light, inout vec3 reflected_light/*, out float shadow*/) {
// return 0.0;
// shadow = 0.0;
vec3 ambient_light = vec3(0.0);
// vec3 ambient_light = vec3(0.0);
vec3 directed_light = vec3(0.0);
vec3 max_light = vec3(0.0);
const float LIGHT_AMBIENCE = 0.015625;
const float LIGHT_AMBIENCE = 0.0;//0.015625;
for (uint i = 0u; i < light_shadow_count.x/*32u*/; i ++) {
for (uint i = 0u; i < /*light_shadow_count.x*//*0u*/light_shadow_count.x/*32u*/; i ++) {
// Only access the array once
Light L = lights[i];
vec3 light_pos = L.light_pos.xyz;
vec3 light_pos = L.light_pos.xyz - focus_off.xyz;
// Pre-calculate difference between light and fragment
vec3 difference = light_pos - wpos;
@ -282,10 +181,10 @@ float lights_at(vec3 wpos, vec3 wnorm, vec3 /*cam_to_frag*/view_dir, vec3 mu, ve
#if (LIGHTING_TYPE & LIGHTING_TYPE_TRANSMISSION) != 0
is_direct = true;
#endif
vec3 direct_light = PI * color * strength * square_factor * light_reflection_factor(/*direct_norm_dir*/wnorm, /*cam_to_frag*/view_dir, direct_light_dir, k_d, k_s, alpha, voxel_lighting);
float computed_shadow = ShadowCalculation(i, -difference, wpos/*, light_distance*/);
directed_light += is_direct ? max(computed_shadow, /*LIGHT_AMBIENCE*/0.0) * direct_light * square_factor : vec3(0.0);
// directed_light += is_direct ? mix(LIGHT_AMBIENCE, 1.0, computed_shadow) * direct_light * square_factor : vec3(0.0);
vec3 direct_light = PI * color * strength * square_factor * light_reflection_factor(/*direct_norm_dir*/wnorm, /*cam_to_frag*/view_dir, direct_light_dir, k_d, k_s, alpha, voxel_norm, voxel_lighting);
float computed_shadow = ShadowCalculationPoint(i, -difference, wnorm, wpos/*, light_distance*/);
// directed_light += is_direct ? max(computed_shadow, /*LIGHT_AMBIENCE*/0.0) * direct_light * square_factor : vec3(0.0);
directed_light += is_direct ? mix(LIGHT_AMBIENCE, 1.0, computed_shadow) * direct_light * square_factor : vec3(0.0);
// ambient_light += is_direct ? vec3(0.0) : vec3(0.0); // direct_light * square_factor * LIGHT_AMBIENCE;
// ambient_light += is_direct ? direct_light * (1.0 - square_factor * LIGHT_AMBIENCE) : vec3(0.0);
@ -308,7 +207,7 @@ float lights_at(vec3 wpos, vec3 wnorm, vec3 /*cam_to_frag*/view_dir, vec3 mu, ve
// mix(cam_strength, strength, cam_distance_2 / (cam_distance_2 + distance_2));
// max(cam_strength, strength);//mix(cam_strength, strength, clamp(distance_2 / /*pos_distance_2*/cam_distance_2, 0.0, 1.0));
// float both_strength = mix(cam_strength, strength, cam_distance_2 / sqrt(cam_distance_2 + distance_2));
max_light += /*max(1.0, cam_strength)*//*min(cam_strength, 1.0)*//*max*//*max(both_strength, 1.0) * *//*cam_strength*//*computed_shadow * */both_strength * square_factor * square_factor * PI * color;
max_light += /*max(1.0, cam_strength)*//*min(cam_strength, 1.0)*//*max*//*max(both_strength, 1.0) * *//*cam_strength*/computed_shadow * both_strength * square_factor * square_factor * PI * color;
// max_light += /*max(1.0, cam_strength)*//*min(cam_strength, 1.0)*//*max*/max(cam_strength, 1.0/*, strength*//*1.0*/) * square_factor * square_factor * PI * color;
// light += color * (max(0, max(dot(normalize(difference), wnorm), 0.15)) + LIGHT_AMBIENCE);
// Compute emiittance.
@ -321,11 +220,11 @@ float lights_at(vec3 wpos, vec3 wnorm, vec3 /*cam_to_frag*/view_dir, vec3 mu, ve
// shadow = shadow_at(wpos, wnorm);
// float shadow = shadow_at(wpos, wnorm);
reflected_light += directed_light;
emitted_light += k_a * ambient_light/* * shadow*/;// min(shadow, 1.0);
// emitted_light += k_a * ambient_light/* * shadow*/;// min(shadow, 1.0);
return /*rel_luminance(ambient_light + directed_light)*/rel_luminance(max_light);//ambient_light;
}
// Same as lights_at, but with no assumed attenuation due to fluid.
float lights_at(vec3 wpos, vec3 wnorm, vec3 view_dir, vec3 k_a, vec3 k_d, vec3 k_s, float alpha, inout vec3 emitted_light, inout vec3 reflected_light) {
return lights_at(wpos, wnorm, view_dir, vec3(0.0), vec3(1.0), 0.0, k_a, k_d, k_s, alpha, 1.0, emitted_light, reflected_light);
return lights_at(wpos, wnorm, view_dir, vec3(0.0), vec3(1.0), 0.0, k_a, k_d, k_s, alpha, wnorm, 1.0, emitted_light, reflected_light);
}

View File

@ -10,13 +10,13 @@ const float MIN_SHADOW = 0.33;
vec2 pos_to_uv(sampler2D sampler, vec2 pos) {
// Want: (pixel + 0.5) / W
vec2 texSize = textureSize(sampler, 0);
vec2 uv_pos = (pos + 16) / (32.0 * texSize);
vec2 uv_pos = (focus_off.xy + pos + 16) / (32.0 * texSize);
return vec2(uv_pos.x, 1.0 - uv_pos.y);
}
vec2 pos_to_tex(vec2 pos) {
// Want: (pixel + 0.5)
vec2 uv_pos = (pos + 16) / 32.0;
vec2 uv_pos = (focus_off.xy + pos + 16) / 32.0;
return vec2(uv_pos.x, uv_pos.y);
}
@ -73,7 +73,7 @@ vec4 textureBicubic(sampler2D sampler, vec2 texCoords) {
}
float alt_at(vec2 pos) {
return (texture/*textureBicubic*/(t_map, pos_to_uv(t_map, pos)).a * (/*1300.0*//*1278.7266845703125*/view_distance.w) + /*140.0*/view_distance.z);
return (texture/*textureBicubic*/(t_map, pos_to_uv(t_map, pos)).a * (/*1300.0*//*1278.7266845703125*/view_distance.w) + /*140.0*/view_distance.z - focus_off.z);
//+ (texture(t_noise, pos * 0.002).x - 0.5) * 64.0;
// return 0.0
@ -87,7 +87,7 @@ float alt_at_real(vec2 pos) {
// #if (FLUID_MODE == FLUID_MODE_CHEAP)
// return alt_at(pos);
// #elif (FLUID_MODE == FLUID_MODE_SHINY)
return (textureBicubic(t_map, pos_to_tex(pos)).a * (/*1300.0*//*1278.7266845703125*/view_distance.w) + /*140.0*/view_distance.z);
return (textureBicubic(t_map, pos_to_tex(pos)).a * (/*1300.0*//*1278.7266845703125*/view_distance.w) + /*140.0*/view_distance.z - focus_off.z);
// #endif
//+ (texture(t_noise, pos * 0.002).x - 0.5) * 64.0;
@ -98,7 +98,7 @@ float alt_at_real(vec2 pos) {
}
float horizon_at2(vec4 f_horizons, float alt, vec3 pos, /*float time_of_day*/vec3 light_dir) {
float horizon_at2(vec4 f_horizons, float alt, vec3 pos, /*float time_of_day*/vec4 light_dir) {
// vec3 sun_dir = get_sun_dir(time_of_day);
const float PI_2 = 3.1415926535897932384626433832795 / 2.0;
const float MIN_LIGHT = 0.0;//0.115/*0.0*/;
@ -133,9 +133,9 @@ float horizon_at2(vec4 f_horizons, float alt, vec3 pos, /*float time_of_day*/vec
.unwrap_or(1.0);
*/
// vec2 f_horizon;
if (light_dir.z >= 0) {
/* if (light_dir.z >= 0) {
return 0.0;
}
} */
/* if (light_dir.x >= 0) {
f_horizon = f_horizons.rg;
// f_horizon = f_horizons.ba;
@ -159,7 +159,7 @@ float horizon_at2(vec4 f_horizons, float alt, vec3 pos, /*float time_of_day*/vec
} */
float height = f_horizon.y * /*1300.0*//*1278.7266845703125*/view_distance.w + view_distance.z;
const float w = 0.1;
float deltah = height - alt;
float deltah = height - alt - focus_off.z;
//if (deltah < 0.0001/* || angle < 0.0001 || abs(light_dir.x) < 0.0001*/) {
// return 1.0;
/*} else */{
@ -187,12 +187,12 @@ float horizon_at2(vec4 f_horizons, float alt, vec3 pos, /*float time_of_day*/vec
}
}
float horizon_at(vec3 pos, /*float time_of_day*/vec3 light_dir) {
vec4 f_horizons = textureBicubic(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);
}
// float horizon_at(vec3 pos, /*float time_of_day*/vec3 light_dir) {
// vec4 f_horizons = textureBicubic(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);
// }
vec2 splay(vec2 pos) {
// const float SPLAY_MULT = 1048576.0;

View File

@ -2,6 +2,15 @@
#include <srgb.glsl>
#include <cloud.glsl>
#include <srgb.glsl>
#include <shadows.glsl>
// Information about an approximately directional light, like the sun or moon.
struct DirectionalLight {
// vec3 dir;
float shadow;
// vec3 color;
// float brightness;
};
const float PI = 3.141592;
@ -32,39 +41,39 @@ const float SUN_COLOR_FACTOR = 6.0;//6.0;// * 1.5;//1.8;
const float UNDERWATER_MIST_DIST = 100.0;
vec3 get_sun_dir(float time_of_day) {
const float TIME_FACTOR = (PI * 2.0) / (3600.0 * 24.0);
float sun_angle_rad = time_of_day * TIME_FACTOR;
// return vec3(sin(sun_angle_rad), 0.0, cos(sun_angle_rad));
return vec3(sin(sun_angle_rad), 0.0, cos(sun_angle_rad));
}
vec3 get_moon_dir(float time_of_day) {
const float TIME_FACTOR = (PI * 2.0) / (3600.0 * 24.0);
float moon_angle_rad = time_of_day * TIME_FACTOR;
// -cos((60+60*4)/360*2*pi)-0.5 = 0
// -cos((60+60*5)/360*2*pi)-0.5 = -0.5
// -cos((60+60*6)/360*2*pi)-0.5 = 0
//
// i.e. moon out from (60*5)/360*24 = 20:00 to (60*7/360*24) = 28:00 = 04:00.
//
// Then sun out from 04:00 to 20:00.
return normalize(-vec3(sin(moon_angle_rad), 0.0, cos(moon_angle_rad) - 0.5));
}
const float PERSISTENT_AMBIANCE = 1.0 / 512;// 1.0 / 512; // 0.00125 // 0.1;// 0.025; // 0.1;
float get_sun_brightness(vec3 sun_dir) {
//vec3 get_sun_dir(float time_of_day) {
// const float TIME_FACTOR = (PI * 2.0) / (3600.0 * 24.0);
//
// float sun_angle_rad = time_of_day * TIME_FACTOR;
// // return vec3(sin(sun_angle_rad), 0.0, cos(sun_angle_rad));
// return vec3(sin(sun_angle_rad), 0.0, cos(sun_angle_rad));
//}
//
//vec3 get_moon_dir(float time_of_day) {
// const float TIME_FACTOR = (PI * 2.0) / (3600.0 * 24.0);
//
// float moon_angle_rad = time_of_day * TIME_FACTOR;
// // -cos((60+60*4)/360*2*pi)-0.5 = 0
// // -cos((60+60*5)/360*2*pi)-0.5 = -0.5
// // -cos((60+60*6)/360*2*pi)-0.5 = 0
// //
// // i.e. moon out from (60*5)/360*24 = 20:00 to (60*7/360*24) = 28:00 = 04:00.
// //
// // Then sun out from 04:00 to 20:00.
// return normalize(-vec3(sin(moon_angle_rad), 0.0, cos(moon_angle_rad) - 0.5));
//}
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) {
float get_moon_brightness(/*vec3 moon_dir*/) {
return max(-moon_dir.z + 0.6, 0.0) * 0.007;
}
vec3 get_sun_color(vec3 sun_dir) {
vec3 get_sun_color(/*vec3 sun_dir*/) {
return mix(
mix(
DUSK_LIGHT,
@ -76,10 +85,39 @@ vec3 get_sun_color(vec3 sun_dir) {
);
}
vec3 get_moon_color(vec3 moon_dir) {
vec3 get_moon_color(/*vec3 moon_dir*/) {
return vec3(0.05, 0.05, 0.6);
}
DirectionalLight get_sun_info(vec4 _dir, float shade_frac/*, vec4 light_pos[2]*/, /*vec4 sun_pos*/vec3 f_pos) {
float shadow = shade_frac;
#ifdef HAS_SHADOW_MAPS
#if (SHADOW_MODE == SHADOW_MODE_MAP)
if (sun_dir.z < /*0.6*/0.0) {
/* ShadowLocals sun_shadow = shadowMats[0];
vec4 sun_pos = sun_shadow.texture_mat * vec4(f_pos, 1.0); */
// #if (SHADOW_MODE == SHADOW_MODE_MAP)
// // for (uint i = 0u; i < light_shadow_count.z; ++i) {
// // light_pos[i] = /*vec3(*/shadowMats[i].texture_mat * vec4(f_pos, 1.0)/*)*/;
// // }
// #elif (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_NONE)
// vec4 sun_pos = vec4(0.0);
// #endif
shadow = min(shadow, ShadowCalculationDirected(/*sun_pos, *//*0u*/f_pos));
}
#endif
#endif
return DirectionalLight(/*dir, */shade_frac * shadow/*, get_sun_color(dir), get_sun_brightness(dir)*/);
}
DirectionalLight get_moon_info(vec4 _dir, float shade_frac/*, vec4 light_pos[2]*/) {
float shadow = shade_frac;
// #ifdef HAS_SHADOW_MAPS
// shadow = min(shade_frac, ShadowCalculationDirected(light_pos, 1u));
// #endif
return DirectionalLight(/*dir, */shadow/*, get_moon_color(dir), get_moon_brightness(dir)*/);
}
// // Calculates extra emission and reflectance (due to sunlight / moonlight).
// //
// // reflectence = k_a * i_a + i_a,persistent
@ -135,15 +173,21 @@ vec3 get_moon_color(vec3 moon_dir) {
// mu is the attenuation coefficient for any substance on a horizontal plane.
// cam_attenuation is the total light attenuation due to the substance for beams between the point and the camera.
// surface_alt is the altitude of the attenuating surface.
float get_sun_diffuse2(vec3 norm, vec3 sun_dir, vec3 moon_dir, vec3 dir, vec3 wpos, vec3 mu, vec3 cam_attenuation, float surface_alt, vec3 k_a, vec3 k_d, vec3 k_s, float alpha, float voxel_lighting, out vec3 emitted_light, out vec3 reflected_light) {
float get_sun_diffuse2(DirectionalLight sun_info, DirectionalLight moon_info, vec3 norm, vec3 dir, vec3 wpos, vec3 mu, vec3 cam_attenuation, float surface_alt, vec3 k_a, vec3 k_d, vec3 k_s, float alpha, vec3 voxel_norm, float voxel_lighting, out vec3 emitted_light, out vec3 reflected_light) {
const float MIN_SHADOW = 0.15;
const vec3 SUN_AMBIANCE = MU_SCATTER;//0.23;/* / 1.8*/;// 0.1 / 3.0;
const vec3 MOON_AMBIANCE = MU_SCATTER;//0.23;//0.1;
float sun_light = get_sun_brightness(sun_dir);
float moon_light = get_moon_brightness(moon_dir);
/* vec3 sun_dir = sun_info.dir;
vec3 moon_dir = moon_info.dir; */
vec3 sun_dir = sun_dir.xyz;
vec3 moon_dir = moon_dir.xyz;
vec3 sun_color = get_sun_color(sun_dir) * SUN_COLOR_FACTOR;
vec3 moon_color = get_moon_color(moon_dir);
float sun_light = get_sun_brightness(/*sun_dir*/);//sun_info.brightness;;
float moon_light = get_moon_brightness(/*moon_dir*/);//moon_info.brightness;
vec3 sun_color = get_sun_color(/*sun_dir*/) * SUN_COLOR_FACTOR;//sun_info.color * SUN_COLOR_FACTOR;
vec3 moon_color = get_moon_color(/*moon_dir*/);//moon_info.color;
// If the sun is facing the wrong way, we currently just want zero light, hence default point is wpos.
vec3 sun_attenuation = compute_attenuation(wpos, -sun_dir, mu, surface_alt, wpos);
@ -152,6 +196,16 @@ float get_sun_diffuse2(vec3 norm, vec3 sun_dir, vec3 moon_dir, vec3 dir, vec3 wp
vec3 sun_chroma = sun_color * sun_light * cam_attenuation * sun_attenuation;
vec3 moon_chroma = moon_color * moon_light * cam_attenuation * moon_attenuation;
// #ifdef HAS_SHADOW_MAPS
// float sun_shadow = ShadowCalculationDirected(light_pos, 0u);
// float moon_shadow = ShadowCalculationDirected(light_pos, 1u);
// #else
// float sun_shadow = 1.0;
// float moon_shadow = 1.0;
// #endif
float sun_shadow = sun_info.shadow;
float moon_shadow = moon_info.shadow;
// https://en.m.wikipedia.org/wiki/Diffuse_sky_radiation
//
// HdRd radiation should come in at angle normal to us.
@ -239,7 +293,7 @@ float get_sun_diffuse2(vec3 norm, vec3 sun_dir, vec3 moon_dir, vec3 dir, vec3 wp
vec3 R_t_r = R_d + R_r;
// vec3 half_vec = normalize(-norm + dir);
vec3 light_frac = R_t_b * (sun_chroma * SUN_AMBIANCE + moon_chroma * MOON_AMBIANCE) * light_reflection_factor(norm, /*norm*//*dir*/dir, /*-norm*/-dir, /*k_d*/k_d/* * (1.0 - k_s)*/, /*k_s*/vec3(0.0), alpha, voxel_lighting);
vec3 light_frac = R_t_b * (sun_chroma * SUN_AMBIANCE + moon_chroma * MOON_AMBIANCE) * light_reflection_factor(norm, /*norm*//*dir*/dir, /*-norm*/-/*dir*/norm, /*k_d*/k_d/* * (1.0 - k_s)*/, /*k_s*/vec3(0.0), alpha, voxel_norm, voxel_lighting);
// vec3 light_frac = /*vec3(1.0)*//*H_d * */
// SUN_AMBIANCE * /*sun_light*/sun_chroma * light_reflection_factor(norm, dir, /*vec3(0, 0, -1.0)*/-norm, vec3((1.0 + cos_sun) * 0.5), vec3(k_s * (1.0 - cos_sun) * 0.5), alpha) +
// MOON_AMBIANCE * /*sun_light*/moon_chroma * light_reflection_factor(norm, dir, /*vec3(0, 0, -1.0)*/-norm, vec3((1.0 + cos_moon) * 0.5), vec3(k_s * (1.0 - cos_moon) * 0.5), alpha);
@ -254,15 +308,14 @@ float get_sun_diffuse2(vec3 norm, vec3 sun_dir, vec3 moon_dir, vec3 dir, vec3 wp
// float ambient_sides = clamp(mix(0.5, 0.0, abs(dot(-norm, sun_dir)) * mix(0.0, 1.0, abs(sun_dir.z) * 10000.0) * 10000.0), 0.0, 0.5);
// float ambient_sides = clamp(mix(0.5, 0.0, abs(dot(-norm, sun_dir)) * mix(0.0, 1.0, abs(sun_dir.z) * 10000.0) * 10000.0), 0.0, 0.5);
emitted_light = k_a * light_frac + PERSISTENT_AMBIANCE;
emitted_light = light_frac + k_a * PERSISTENT_AMBIANCE;
// emitted_light = k_a * light_frac * (/*ambient_sides + */SUN_AMBIANCE * /*sun_light*/sun_chroma + /*vec3(moon_light)*/MOON_AMBIANCE * moon_chroma) + PERSISTENT_AMBIANCE;
// TODO: Add shadows.
reflected_light = R_t_r * (
(1.0 - SUN_AMBIANCE) * sun_chroma * (light_reflection_factor(norm, dir, sun_dir, k_d, k_s, alpha, voxel_lighting) /*+
(1.0 - SUN_AMBIANCE) * sun_chroma * sun_shadow * (light_reflection_factor(norm, dir, sun_dir, k_d, k_s, alpha, voxel_norm, voxel_lighting) /*+
light_reflection_factor(norm, dir, normalize(sun_dir + vec3(0.0, 0.1, 0.0)), k_d, k_s, alpha) +
light_reflection_factor(norm, dir, normalize(sun_dir - vec3(0.0, 0.1, 0.0)), k_d, k_s, alpha)*/) +
(1.0 - MOON_AMBIANCE) * moon_chroma * 1.0 * /*4.0 * */light_reflection_factor(norm, dir, moon_dir, k_d, k_s, alpha, voxel_lighting)
(1.0 - MOON_AMBIANCE) * moon_chroma * moon_shadow * 1.0 * /*4.0 * */light_reflection_factor(norm, dir, moon_dir, k_d, k_s, alpha, voxel_norm, voxel_lighting)
);
/* light = sun_chroma + moon_chroma + PERSISTENT_AMBIANCE;
@ -274,12 +327,12 @@ float get_sun_diffuse2(vec3 norm, vec3 sun_dir, vec3 moon_dir, vec3 dir, vec3 wp
return rel_luminance(emitted_light + reflected_light);//rel_luminance(emitted_light + reflected_light);//sun_chroma + moon_chroma + PERSISTENT_AMBIANCE;
}
float get_sun_diffuse2(vec3 norm, vec3 sun_dir, vec3 moon_dir, vec3 dir, vec3 k_a, vec3 k_d, vec3 k_s, float alpha, float voxel_lighting, out vec3 emitted_light, out vec3 reflected_light) {
return get_sun_diffuse2(norm, sun_dir, moon_dir, dir, vec3(0.0), vec3(0.0), vec3(1.0), 0.0, k_a, k_d, k_s, alpha, voxel_lighting, emitted_light, reflected_light);
float get_sun_diffuse2(DirectionalLight sun_info, DirectionalLight moon_info, vec3 norm, vec3 dir, vec3 k_a, vec3 k_d, vec3 k_s, float alpha, vec3 voxel_norm, float voxel_lighting, out vec3 emitted_light, out vec3 reflected_light) {
return get_sun_diffuse2(sun_info, moon_info, norm, dir, vec3(0.0), vec3(0.0), vec3(1.0), 0.0, k_a, k_d, k_s, alpha, voxel_norm, voxel_lighting, emitted_light, reflected_light);
}
float get_sun_diffuse2(vec3 norm, vec3 sun_dir, vec3 moon_dir, vec3 dir, vec3 k_a, vec3 k_d, vec3 k_s, float alpha, out vec3 emitted_light, out vec3 reflected_light) {
return get_sun_diffuse2(norm, sun_dir, moon_dir, dir, vec3(0.0), vec3(0.0), vec3(1.0), 0.0, k_a, k_d, k_s, alpha, 1.0, emitted_light, reflected_light);
float get_sun_diffuse2(DirectionalLight sun_info, DirectionalLight moon_info, vec3 norm, vec3 dir, vec3 k_a, vec3 k_d, vec3 k_s, float alpha, out vec3 emitted_light, out vec3 reflected_light) {
return get_sun_diffuse2(sun_info, moon_info, norm, dir, vec3(0.0), vec3(0.0), vec3(1.0), 0.0, k_a, k_d, k_s, alpha, norm, 1.0, emitted_light, reflected_light);
}
// This has been extracted into a function to allow quick exit when detecting a star.
@ -304,16 +357,25 @@ float is_star_at(vec3 dir) {
}
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) {
// Sky color
vec3 sun_dir = get_sun_dir(time_of_day);
vec3 moon_dir = get_moon_dir(time_of_day);
/* vec3 sun_dir = get_sun_dir(time_of_day);
vec3 moon_dir = get_moon_dir(time_of_day); */
vec3 sun_dir = sun_dir.xyz;
vec3 moon_dir = moon_dir.xyz;
// sun_dir = sun_dir.z <= 0 ? refract(sun_dir/*-view_dir*/, vec3(0.0, 0.0, 1.0), refractionIndex) : sun_dir;
// moon_dir = moon_dir.z <= 0 ? refract(moon_dir/*-view_dir*/, vec3(0.0, 0.0, 1.0), refractionIndex) : moon_dir;
// Add white dots for stars. Note these flicker and jump due to FXAA
float star = 0.0;
if (with_stars) {
if (with_stars || has_clouds) {
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);
}
@ -385,14 +447,21 @@ vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float q
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);
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);
}
}
vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float quality, bool with_stars, out vec4 clouds) {
@ -424,6 +493,7 @@ float fog(vec3 f_pos, vec3 focus_pos, uint medium) {
return ((color - avg_col) * light + (diffuse + ambience) * avg_col) * (diffuse + ambience);
} */
vec3 illuminate(float max_light, vec3 view_dir, /*vec3 max_light, */vec3 emitted, vec3 reflected) {
return emitted + reflected;
const float NIGHT_EXPOSURE = 10.0;
const float DUSK_EXPOSURE = 2.0;//0.8;
const float DAY_EXPOSURE = 1.0;//0.7;
@ -446,11 +516,11 @@ vec3 illuminate(float max_light, vec3 view_dir, /*vec3 max_light, */vec3 emitted
float lum = rel_luminance(color);
// float lum_sky = lum - max_light;
vec3 sun_dir = get_sun_dir(time_of_day.x);
vec3 moon_dir = get_moon_dir(time_of_day.x);
/* vec3 sun_dir = get_sun_dir(time_of_day.x);
vec3 moon_dir = get_moon_dir(time_of_day.x); */
float sky_light = rel_luminance(
get_sun_color(sun_dir) * get_sun_brightness(sun_dir) * SUN_COLOR_FACTOR +
get_moon_color(moon_dir) * get_moon_brightness(moon_dir));
get_sun_color(/*sun_dir*/) * get_sun_brightness(/*sun_dir*/) * SUN_COLOR_FACTOR +
get_moon_color(/*moon_dir*/) * get_moon_brightness(/*moon_dir*/));
// Tone mapped value.
// vec3 T = /*color*//*lum*/color;//normalize(color) * lum / (1.0 + lum);
@ -464,7 +534,7 @@ vec3 illuminate(float max_light, vec3 view_dir, /*vec3 max_light, */vec3 emitted
DAY_EXPOSURE,
max(-sun_dir.z, 0)
);
vec3 now_light = moon_dir.z < 0 ? moon_dir : sun_dir;
vec3 now_light = moon_dir.z < 0 ? moon_dir.xyz : sun_dir.xyz;
float cos_view_light = dot(-now_light, view_dir);
// alpha *= exp(1.0 - cos_view_light);
// sky_light *= 1.0 - log(1.0 + view_dir.z);

View File

@ -2,6 +2,23 @@
// See https://en.wikipedia.org/wiki/Electromagnetic_absorption_by_water
const vec3 MU_WATER = vec3(0.6, 0.04, 0.01);
// // NOTE: Automatic in v4.0
// float
// mip_map_level(in vec2 texture_coordinate)
// {
// // The OpenGL Graphics System: A Specification 4.2
// // - chapter 3.9.11, equation 3.21
//
//
// vec2 dx_vtc = dFdx(texture_coordinate);
// vec2 dy_vtc = dFdy(texture_coordinate);
// float delta_max_sqr = max(dot(dx_vtc, dx_vtc), dot(dy_vtc, dy_vtc));
//
//
// //return max(0.0, 0.5 * log2(delta_max_sqr) - 1.0); // == log2(sqrt(delta_max_sqr));
// return 0.5 * log2(delta_max_sqr); // == log2(sqrt(delta_max_sqr));
// }
//https://gamedev.stackexchange.com/questions/92015/optimized-linear-to-srgb-glsl
vec3 srgb_to_linear(vec3 srgb) {
bvec3 cutoff = lessThan(srgb, vec3(0.04045));
@ -53,8 +70,8 @@ float BeckmannDistribution_D(float NdotH, float alpha) {
}
// Voxel Distribution
float BeckmannDistribution_D_Voxel(vec3 wh, vec3 norm, float alpha) {
vec3 sides = sign(norm);
float BeckmannDistribution_D_Voxel(vec3 wh, vec3 voxel_norm, float alpha) {
vec3 sides = sign(voxel_norm);
// vec3 cos_sides_i = /*sides * */sides * norm;
// vec3 cos_sides_o = max(sides * view_dir, 0.0);
@ -64,7 +81,7 @@ float BeckmannDistribution_D_Voxel(vec3 wh, vec3 norm, float alpha) {
vec3 NdotH2 = NdotH * NdotH;
vec3 NdotH2m2 = NdotH2 * alpha * alpha;
vec3 k_spec = exp((NdotH2 - 1) / NdotH2m2) / (PI * NdotH2m2 * NdotH2);
return dot(mix(k_spec, /*cos_sides_o*/vec3(0.0), equal(NdotH, vec3(0.0))), /*cos_sides_i*/abs(norm));
return dot(mix(k_spec, /*cos_sides_o*/vec3(0.0), equal(NdotH, vec3(0.0))), /*cos_sides_i*/abs(voxel_norm));
// // const float PI = 3.1415926535897932384626433832795;
// const vec3 normals[6] = 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));
@ -100,8 +117,8 @@ float BeckmannDistribution_D_Voxel(vec3 wh, vec3 norm, float alpha) {
// return voxel_norm;
}
float TrowbridgeReitzDistribution_D_Voxel(vec3 wh, vec3 norm, float alpha) {
vec3 sides = sign(norm);
float TrowbridgeReitzDistribution_D_Voxel(vec3 wh, vec3 voxel_norm, float alpha) {
vec3 sides = sign(voxel_norm);
// vec3 cos_sides_i = /*sides * */sides * norm;
// vec3 cos_sides_o = max(sides * view_dir, 0.0);
@ -118,7 +135,7 @@ float TrowbridgeReitzDistribution_D_Voxel(vec3 wh, vec3 norm, float alpha) {
vec3 e = (1 - NdotH2) / NdotH2m2;
vec3 k_spec = 1.0 / (PI * NdotH2m2 * NdotH2 * (1 + e) * (1 + e));
// vec3 k_spec = exp((NdotH2 - 1) / NdotH2m2) / (PI * NdotH2m2 * NdotH2);
return dot(mix(k_spec, /*cos_sides_o*/vec3(0.0), equal(NdotH, vec3(0.0))), /*cos_sides_i*/abs(norm));
return dot(mix(k_spec, /*cos_sides_o*/vec3(0.0), equal(NdotH, vec3(0.0))), /*cos_sides_i*/abs(voxel_norm));
}
float BeckmannDistribution_Lambda(vec3 norm, vec3 dir, float alpha) {
@ -223,7 +240,7 @@ vec3 FresnelBlend_f(vec3 norm, vec3 dir, vec3 light_dir, vec3 R_d, vec3 R_s, flo
// http://www.pbr-book.org/3ed-2018/Reflection_Models/Microfacet_Models.html#fragment-MicrofacetDistributionPublicMethods-2
// and
// http://www.pbr-book.org/3ed-2018/Reflection_Models/Fresnel_Incidence_Effects.html
vec3 FresnelBlend_Voxel_f(vec3 norm, vec3 dir, vec3 light_dir, vec3 R_d, vec3 R_s, float alpha, float dist) {
vec3 FresnelBlend_Voxel_f(vec3 norm, vec3 dir, vec3 light_dir, vec3 R_d, vec3 R_s, float alpha, vec3 voxel_norm, float dist) {
const float PI = 3.1415926535897932384626433832795;
alpha = alpha * sqrt(2.0);
float cos_wi = /*max(*/dot(-light_dir, norm)/*, 0.0)*/;
@ -233,7 +250,7 @@ vec3 FresnelBlend_Voxel_f(vec3 norm, vec3 dir, vec3 light_dir, vec3 R_d, vec3 R_
vec4 AbsNdotL = abs(vec4(light_dir, cos_wi));
vec4 AbsNdotV = abs(vec4(dir, cos_wo));
#else
vec3 sides = sign(norm);
vec3 sides = sign(voxel_norm);
vec4 AbsNdotL = vec4(max(-light_dir * sides, 0.0), abs(cos_wi));
vec4 AbsNdotV = vec4(max(dir * sides, 0.0), abs(cos_wo));
#endif
@ -288,8 +305,8 @@ vec3 FresnelBlend_Voxel_f(vec3 norm, vec3 dir, vec3 light_dir, vec3 R_d, vec3 R_
}
wh = normalize(wh);//mix(normalize(wh), vec3(0.0), equal(light_dir, dir));
float dot_wi_wh = dot(-light_dir, wh);
// float distr = TrowbridgeReitzDistribution_D_Voxel(wh, norm, alpha);
float distr = BeckmannDistribution_D_Voxel(wh, norm, alpha);
// float distr = TrowbridgeReitzDistribution_D_Voxel(wh, voxel_norm, alpha);
float distr = BeckmannDistribution_D_Voxel(wh, voxel_norm, alpha);
// float distr = BeckmannDistribution_D(dot(wh, norm), alpha);
vec3 specular = distr /
(4 * abs(dot_wi_wh) *
@ -365,17 +382,17 @@ vec3 light_reflection_factor2(vec3 norm, vec3 dir, vec3 light_dir, vec3 k_d, vec
// // return vec3(0.0);
}
vec3 light_reflection_factor(vec3 norm, vec3 dir, vec3 light_dir, vec3 k_d, vec3 k_s, float alpha, float voxel_lighting) {
vec3 light_reflection_factor(vec3 norm, vec3 dir, vec3 light_dir, vec3 k_d, vec3 k_s, float alpha, vec3 voxel_norm, float voxel_lighting) {
#if (LIGHTING_ALGORITHM == LIGHTING_ALGORITHM_LAMBERTIAN)
const float PI = 3.141592;
#if (LIGHTING_DISTRIBUTION_SCHEME == LIGHTING_DISTRIBUTION_SCHEME_VOXEL)
#if (LIGHTING_TYPE & LIGHTING_TYPE_TRANSMISSION) != 0
vec4 AbsNdotL = abs(vec4(light_dir, dot(norm, light_dir)));
#else
vec3 sides = sign(norm);
vec3 sides = sign(voxel_norm);
vec4 AbsNdotL = max(vec4(-light_dir * sides, dot(norm, -light_dir)), 0.0);
#endif
float diffuse = dot(AbsNdotL, vec4(abs(norm) * (1.0 - voxel_lighting), voxel_lighting));
float diffuse = dot(AbsNdotL, vec4(abs(voxel_norm) * (1.0 - voxel_lighting), voxel_lighting));
#elif (LIGHTING_DISTRIBUTION_SCHEME == LIGHTING_DISTRIBUTION_SCHEME_MICROFACET)
#if (LIGHTING_TYPE & LIGHTING_TYPE_TRANSMISSION) != 0
float diffuse = abs(dot(norm, light_dir));
@ -398,10 +415,10 @@ vec3 light_reflection_factor(vec3 norm, vec3 dir, vec3 light_dir, vec3 k_d, vec3
#if (LIGHTING_TYPE & LIGHTING_TYPE_TRANSMISSION) != 0
vec4 AbsNdotL = abs(vec4(light_dir, ndotL));
#else
vec3 sides = sign(norm);
vec3 sides = sign(voxel_norm);
vec4 AbsNdotL = max(vec4(-light_dir * sides, ndotL), 0.0);
#endif
float diffuse = dot(AbsNdotL, vec4(abs(norm) * (1.0 - voxel_lighting), voxel_lighting));
float diffuse = dot(AbsNdotL, vec4(abs(voxel_norm) * (1.0 - voxel_lighting), voxel_lighting));
#elif (LIGHTING_DISTRIBUTION_SCHEME == LIGHTING_DISTRIBUTION_SCHEME_MICROFACET)
float diffuse = ndotL;
#endif
@ -418,7 +435,7 @@ vec3 light_reflection_factor(vec3 norm, vec3 dir, vec3 light_dir, vec3 k_d, vec3
return vec3(0.0);
#elif (LIGHTING_ALGORITHM == LIGHTING_ALGORITHM_ASHIKHMIN)
#if (LIGHTING_DISTRIBUTION_SCHEME == LIGHTING_DISTRIBUTION_SCHEME_VOXEL)
return FresnelBlend_Voxel_f(norm, dir, light_dir, k_d/* * max(dot(norm, -light_dir), 0.0)*/, k_s, alpha, voxel_lighting);
return FresnelBlend_Voxel_f(norm, dir, light_dir, k_d/* * max(dot(norm, -light_dir), 0.0)*/, k_s, alpha, voxel_norm, voxel_lighting);
#elif (LIGHTING_DISTRIBUTION_SCHEME == LIGHTING_DISTRIBUTION_SCHEME_MICROFACET)
//if (voxel_lighting < 1.0) {
return FresnelBlend_f(norm, dir, light_dir, k_d/* * max(dot(norm, -light_dir), 0.0)*/, k_s, alpha);
@ -530,3 +547,68 @@ vec3 compute_attenuation_point(vec3 wpos, vec3 ray_dir, vec3 mu, float surface_a
return exp(-mu * sqrt(depth2));
#endif
}
//#ifdef HAS_SHADOW_MAPS
// #if (SHADOW_MODE == SHADOW_MODE_MAP)
//uniform sampler2DShadow t_directed_shadow_maps;
//// uniform sampler2DArrayShadow t_directed_shadow_maps;
//
//float ShadowCalculationDirected(in vec4 /*light_pos[2]*/sun_pos, uint lightIndex)
//{
// float bias = 0.0;//-0.0001;// 0.05 / (2.0 * view_distance.x);
// // const vec3 sampleOffsetDirections[20] = vec3[]
// // (
// // vec3( 1, 1, 1), vec3( 1, -1, 1), vec3(-1, -1, 1), vec3(-1, 1, 1),
// // vec3( 1, 1, -1), vec3( 1, -1, -1), vec3(-1, -1, -1), vec3(-1, 1, -1),
// // vec3( 1, 1, 0), vec3( 1, -1, 0), vec3(-1, -1, 0), vec3(-1, 1, 0),
// // vec3( 1, 0, 1), vec3(-1, 0, 1), vec3( 1, 0, -1), vec3(-1, 0, -1),
// // vec3( 0, 1, 1), vec3( 0, -1, 1), vec3( 0, -1, -1), vec3( 0, 1, -1)
// // // vec3(0, 0, 0)
// // );
// /* if (lightIndex >= light_shadow_count.z) {
// return 1.0;
// } */
// // vec3 fragPos = sun_pos.xyz;// / sun_pos.w;//light_pos[lightIndex].xyz;
// float visibility = textureProj(t_directed_shadow_maps, sun_pos);
// // float visibility = textureProj(t_directed_shadow_maps, vec4(fragPos.xy, /*lightIndex, */fragPos.z + bias, sun_pos.w));
// return visibility;
// // return mix(visibility, 0.0, sun_pos.z < -1.0);
// // return mix(mix(0.0, 1.0, visibility == 1.0), 1.0, sign(sun_pos.w) * sun_pos.z > /*1.0*/abs(sun_pos.w));
// // return visibility == 1.0 ? 1.0 : 0.0;
// /* if (visibility == 1.0) {
// return 1.0;
// } */
// // return visibility;
// /* if (fragPos.z > 1.0) {
// return 1.0;
// } */
// // if (visibility <= 0.75) {
// // return 0.0;
// // }
// // int samples = 20;
// // float shadow = 0.0;
// // // float bias = 0.0001;
// // float viewDistance = length(cam_pos.xyz - fragPos);
// // // float diskRadius = 0.2 * (1.0 + (viewDistance / screen_res.w)) / 25.0;
// // float diskRadius = 0.0008;//0.005;// / (2.0 * view_distance.x);//(1.0 + (viewDistance / screen_res.w)) / 25.0;
// // for(int i = 0; i < samples; ++i)
// // {
// // vec3 currentDepth = fragPos + vec3(sampleOffsetDirections[i].xyz) * diskRadius + bias;
// // visibility = texture(t_directed_shadow_maps, vec4(currentDepth.xy, lightIndex, currentDepth.z)/*, -2.5*/);
// // shadow += mix(visibility, 1.0, visibility >= 0.5);
// // }
// // shadow /= float(samples);
// // return shadow;
//}
// #elif (SHADOW_MODE == SHADOW_MODE_NONE || SHADOW_MODE == SHADOW_MODE_CHEAP)
//float ShadowCalculationDirected(in vec4 light_pos[2], uint lightIndex)
//{
// return 1.0;
//}
// #endif
//#else
//float ShadowCalculationDirected(in vec4 light_pos[2], uint lightIndex)
//{
// return 1.0;
//}
//#endif

View File

@ -0,0 +1,48 @@
// NOTE: We currently do nothing, and just rely on the default shader behavior.
//
// However, in the future we might apply some depth transforms here.
#version 330 core
// #extension ARB_texture_storage : enable
#include <constants.glsl>
#define LIGHTING_TYPE LIGHTING_TYPE_REFLECTION
#define LIGHTING_REFLECTION_KIND LIGHTING_REFLECTION_KIND_GLOSSY
#if (FLUID_MODE == FLUID_MODE_CHEAP)
#define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_IMPORTANCE
#elif (FLUID_MODE == FLUID_MODE_SHINY)
#define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_RADIANCE
#endif
#define LIGHTING_DISTRIBUTION_SCHEME LIGHTING_DISTRIBUTION_SCHEME_MICROFACET
#define LIGHTING_DISTRIBUTION LIGHTING_DISTRIBUTION_BECKMANN
// // Currently, we only need globals for the far plane.
// #include <globals.glsl>
// // Currently, we only need lights for the light position
// #include <light.glsl>
// in vec3 FragPos; // FragPos from GS (output per emitvertex)
// flat in int FragLayer;
void main()
{
// Only need to do anything with point lights, since sun and moon should already have nonlinear
// distance.
/*if (FragLayer > 0) */{
// get distance between fragment and light source
// float lightDistance = length(FragPos - lights[FragLayer & 31].light_pos.xyz);
// // // map to [0;1] range by dividing by far_plane
// lightDistance = lightDistance / screen_res.w;//FragPos.w;//screen_res.w;
// // // write this as modified depth
// // // lightDistance = -1000.0 / (lightDistance + 10000.0);
// // // lightDistance /= screen_res.w;
// gl_FragDepth = lightDistance;// / /*FragPos.w;*/screen_res.w;//-1000.0 / (lightDistance + 1000.0);//lightDistance
}
}

View File

@ -0,0 +1,63 @@
#version 330 core
// #extension ARB_texture_storage : enable
#include <constants.glsl>
#define LIGHTING_TYPE LIGHTING_TYPE_REFLECTION
#define LIGHTING_REFLECTION_KIND LIGHTING_REFLECTION_KIND_GLOSSY
#if (FLUID_MODE == FLUID_MODE_CHEAP)
#define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_IMPORTANCE
#elif (FLUID_MODE == FLUID_MODE_SHINY)
#define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_RADIANCE
#endif
#define LIGHTING_DISTRIBUTION_SCHEME LIGHTING_DISTRIBUTION_SCHEME_MICROFACET
#define LIGHTING_DISTRIBUTION LIGHTING_DISTRIBUTION_BECKMANN
#define HAS_SHADOW_MAPS
// Currently, we only need globals for focus_off.
#include <globals.glsl>
// For shadow locals.
#include <shadows.glsl>
/* Accurate packed shadow maps for many lights at once!
*
* Ideally, we would just write to a bitmask...
*
* */
in uint v_pos_norm;
// in uint v_col_light;
// in vec4 v_pos;
// Light projection matrices.
layout (std140)
uniform u_locals {
vec3 model_offs;
float load_time;
ivec4 atlas_offs;
};
// out vec4 shadowMapCoord;
const int EXTRA_NEG_Z = 32768;
void main() {
#if (SHADOW_MODE == SHADOW_MODE_MAP)
vec3 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_pos = f_chunk_pos + model_offs - focus_off.xyz;
// f_pos = v_pos;
// vec3 f_pos = f_chunk_pos + model_offs;
// gl_Position = v_pos + vec4(model_offs, 0.0);
gl_Position = /*all_mat * */shadowMats[/*layer_face*/0].shadowMatrices * vec4(f_pos/*, 1.0*/, /*float(((f_pos_norm >> 29) & 0x7u) ^ 0x1)*//*uintBitsToFloat(v_pos_norm)*/1.0);
// gl_Position.z = -gl_Position.z;
// gl_Position.z = clamp(gl_Position.z, -abs(gl_Position.w), abs(gl_Position.w));
// shadowMapCoord = lights[gl_InstanceID].light_pos * gl_Vertex;
// vec4(v_pos, 0.0, 1.0);
#endif
}

View File

@ -0,0 +1,74 @@
#version 330 core
// #extension ARB_texture_storage : enable
#include <constants.glsl>
#define LIGHTING_TYPE LIGHTING_TYPE_REFLECTION
#define LIGHTING_REFLECTION_KIND LIGHTING_REFLECTION_KIND_GLOSSY
#if (FLUID_MODE == FLUID_MODE_CHEAP)
#define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_IMPORTANCE
#elif (FLUID_MODE == FLUID_MODE_SHINY)
#define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_RADIANCE
#endif
#define LIGHTING_DISTRIBUTION_SCHEME LIGHTING_DISTRIBUTION_SCHEME_MICROFACET
#define LIGHTING_DISTRIBUTION LIGHTING_DISTRIBUTION_BECKMANN
#define HAS_SHADOW_MAPS
// Currently, we only need globals for focus_off.
#include <globals.glsl>
// For shadow locals.
#include <shadows.glsl>
/* Accurate packed shadow maps for many lights at once!
*
* Ideally, we would just write to a bitmask...
*
* */
in uint v_pos_norm;
in uint v_atlas_pos;
// in uint v_col_light;
// in vec4 v_pos;
layout (std140)
uniform u_locals {
mat4 model_mat;
vec4 model_col;
ivec4 atlas_offs;
vec3 model_pos;
// bit 0 - is player
// bit 1-31 - unused
int flags;
};
struct BoneData {
mat4 bone_mat;
mat4 normals_mat;
};
layout (std140)
uniform u_bones {
// Warning: might not actually be 16 elements long. Don't index out of bounds!
BoneData bones[16];
};
// out vec4 shadowMapCoord;
void main() {
#if (SHADOW_MODE == SHADOW_MODE_MAP)
uint bone_idx = (v_pos_norm >> 27) & 0xFu;
vec3 pos = (vec3((uvec3(v_pos_norm) >> uvec3(0, 9, 18)) & uvec3(0x1FFu)) - 256.0) / 2.0;
vec3 f_pos = (
bones[bone_idx].bone_mat *
vec4(pos, 1.0)
).xyz + (model_pos - focus_off.xyz/* + vec3(0.0, 0.0, 0.0001)*/);
gl_Position = shadowMats[/*layer_face*/0].shadowMatrices * vec4(f_pos, 1.0);
#endif
}

View File

@ -21,12 +21,12 @@
#define LIGHTING_DISTRIBUTION LIGHTING_DISTRIBUTION_BECKMANN
// Currently, we only need globals for the far plane.
#include <globals.glsl>
// Currently, we only need lights for the light position
#include <light.glsl>
// // Currently, we only need globals for the far plane.
// #include <globals.glsl>
// // Currently, we only need lights for the light position
// #include <light.glsl>
in vec3 FragPos; // FragPos from GS (output per emitvertex)
// in vec3 FragPos; // FragPos from GS (output per emitvertex)
// flat in int FragLayer;
void main()

View File

@ -21,11 +21,14 @@
#define LIGHTING_DISTRIBUTION LIGHTING_DISTRIBUTION_BECKMANN
#define HAS_SHADOW_MAPS
// Currently, we only need globals for the max light count (light_shadow_count.x)
// and the far plane (scene_res.z).
#include <globals.glsl>
// Currently, we only need lights for the light position
#include <light.glsl>
#include <shadows.glsl>
// // Currently, we only need lights for the light position
// #include <light.glsl>
// Since our output primitive is a triangle strip, we have to render three vertices
// each.
@ -171,14 +174,15 @@ layout (triangles/*, invocations = 6*/) in;
layout (triangle_strip, max_vertices = /*MAX_LAYER_VERTICES_PER_FACE*//*96*/18) out;
struct ShadowLocals {
mat4 shadowMatrices;
};
layout (std140)
uniform u_light_shadows {
ShadowLocals shadowMats[/*MAX_LAYER_FACES*/192];
};
//struct ShadowLocals {
// mat4 shadowMatrices;
// mat4 texture_mat;
//};
//
//layout (std140)
//uniform u_light_shadows {
// ShadowLocals shadowMats[/*MAX_LAYER_FACES*/192];
//};
// NOTE: We choose not to output FragPos currently to save on space limitations
// (see extensive documentation above). However, as these limitations have been
@ -218,15 +222,17 @@ void main() {
/* if (light_shadow_count.x == 1) {
return;
} */
for (int layer = 1; layer <= /*light_shadow_count.x*/1; ++layer)
#if (SHADOW_MODE == SHADOW_MODE_MAP)
for (uint layer = 1u; layer <= min(light_shadow_count.x, 1u); ++layer)
{
int layer_base = layer * FACES_PER_POINT_LIGHT;
int layer_base = int(layer) * FACES_PER_POINT_LIGHT;
// We use instancing here in order to increase the number of emitted vertices.
// int face = gl_InvocationID;
for(int face = 0; face < FACES_PER_POINT_LIGHT; ++face)
{
// int layer_face = layer * FACES_PER_POINT_LIGHT + face;
// int layer_face = layer * FACES_PER_POINT_LIGHT + face;
// for(int i = VERTICES_PER_FACE - 1; i >= 0; --i) // for each triangle vertex
for(int i = 0; i < VERTICES_PER_FACE; ++i) // for each triangle vertex
{
// NOTE: See above, we don't make FragPos a uniform.
@ -256,4 +262,5 @@ void main() {
EndPrimitive();
}
}
#endif
}

View File

@ -17,7 +17,7 @@
#define LIGHTING_DISTRIBUTION LIGHTING_DISTRIBUTION_BECKMANN
// Currently, we only need globals for the all_mat matrix.
// Currently, we only need globals for focus_off.
#include <globals.glsl>
/* Accurate packed shadow maps for many lights at once!
@ -35,6 +35,7 @@ layout (std140)
uniform u_locals {
vec3 model_offs;
float load_time;
ivec4 atlas_offs;
};
// out vec4 shadowMapCoord;
@ -43,7 +44,7 @@ const int EXTRA_NEG_Z = 32768;
void main() {
vec3 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_pos = f_chunk_pos + model_offs;
vec3 f_pos = f_chunk_pos + model_offs - focus_off.xyz;
// f_pos = v_pos;
// vec3 f_pos = f_chunk_pos + model_offs;

View File

@ -12,7 +12,8 @@
#define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_RADIANCE
#endif
#define LIGHTING_DISTRIBUTION_SCHEME LIGHTING_DISTRIBUTION_SCHEME_VOXEL
// #define LIGHTING_DISTRIBUTION_SCHEME LIGHTING_DISTRIBUTION_SCHEME_VOXEL
#define LIGHTING_DISTRIBUTION_SCHEME LIGHTING_DISTRIBUTION_SCHEME_MICROFACET
#define LIGHTING_DISTRIBUTION LIGHTING_DISTRIBUTION_BECKMANN
@ -22,15 +23,20 @@
in vec3 f_pos;
in vec3 f_norm;
in vec2 v_pos_orig;
// in vec2 v_pos_orig;
// in vec4 f_shadow;
// in vec4 f_square;
out vec4 tgt_color;
/// const vec4 sun_pos = vec4(0);
// const vec4 light_pos[2] = vec4[](vec4(0), vec4(0)/*, vec3(00), vec3(0), vec3(0), vec3(0)*/);
#include <sky.glsl>
void main() {
// tgt_color = vec4(vec3(1.0), 1.0);
// return;
// vec3 f_pos = lod_pos(f_pos.xy);
// vec3 f_col = lod_col(f_pos.xy);
@ -49,7 +55,11 @@ void main() {
float which_norm = dot(my_norm, normalize(cam_pos.xyz - my_pos));
// which_norm = 0.5 + which_norm * 0.5;
which_norm = pow(max(0.0, which_norm), /*0.03125*/1 / 8.0);// * 0.5;
// which_norm = pow(max(0.0, which_norm), /*0.03125*/1 / 8.0);// * 0.5;
// smoothstep
which_norm = which_norm * which_norm * (3 - 2 * abs(which_norm));
// which_norm = mix(0.0, 1.0, which_norm > 0.0);
// vec3 normals[6] = vec3[](vec3(-1,0,0), vec3(1,0,0), vec3(0,-1,0), vec3(0,1,0), vec3(0,0,-1), vec3(0,0,1));
vec3 f_norm = mix(faceforward(f_norm, cam_pos.xyz - f_pos, -f_norm), my_norm, which_norm);
@ -95,6 +105,9 @@ void main() {
// vec3 old_coord = all_mat * vec4(f_pos.xyz, 1.0);
// vec4 new_f_pos = invfoo * (old_coord);//vec4(f_pos, 1.0);
vec3 f_col = lod_col(f_pos.xy);
// 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);
@ -168,7 +181,7 @@ void main() {
// }
// voxel_norm = normalize(voxel_norm); */
float dist_lerp = clamp(pow(max(distance(focus_pos.xy, f_pos.xy) - view_distance.x, 0.0) / 4096.0, 2.0), 0, 1);
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));
@ -198,9 +211,23 @@ void main() {
// 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(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);
@ -209,22 +236,96 @@ void main() {
// 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));
// 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))*/);
// f_ao_vec *= sign(max(view_dir * sides, 0.0));
// vec3 f_ao_view = max(vec3(dot(view_dir.yz, sides.yz), dot(view_dir.xz, sides.xz), dot(view_dir.xy, sides.xy)), 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 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(view_dir.yz, sides.yz), dot(view_dir.xz, sides.xz), dot(view_dir.xy, sides.xy)), 0.0));
// 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)));
@ -256,10 +357,21 @@ void main() {
// 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 + view_dir * sides), 0.0) * f_ao);
// 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 ?
@ -290,16 +402,39 @@ void main() {
// 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);
// vec3 voxel_norm = vec3(0.0);
// voxel_norm = mix(voxel_norm, f_norm, dist_lerp);
f_pos.xyz -= abs(voxel_norm) * delta_sides;
/* 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);
#if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP || FLUID_MODE == FLUID_MODE_SHINY)
float shadow_alt = /*f_pos.z;*/alt_at(f_pos.xy);//max(alt_at(f_pos.xy), f_pos.z);
// float shadow_alt = f_pos.z;
#elif (SHADOW_MODE == SHADOW_MODE_NONE || FLUID_MODE == FLUID_MODE_CHEAP)
float shadow_alt = f_pos.z;
#endif
#if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP)
vec4 f_shadow = textureBicubic(t_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)
float sun_shade_frac = 1.0;//horizon_at2(f_shadow, shadow_alt, f_pos, sun_dir);
#endif
float moon_shade_frac = 1.0;//horizon_at2(f_shadow, shadow_alt, f_pos, moon_dir);
f_pos.xyz += abs(voxel_norm) * delta_sides;
voxel_norm = voxel_norm == vec3(0.0) ? f_norm : voxel_norm;
f_col = /*srgb_to_linear*/(f_col + hash(vec4(floor(f_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 = sqrt(dot(f_ao_vec * abs(voxel_norm), sqrt(1.0 - delta_sides * delta_sides)) / 3.0);
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));
// f_ao = sqrt(dot(ao_pos2, ao_pos2));
@ -336,27 +471,31 @@ void main() {
// vec3 view_dir = normalize(f_pos - cam_pos.xyz);
vec3 sun_dir = get_sun_dir(time_of_day.x);
vec3 moon_dir = get_moon_dir(time_of_day.x);
// float sun_light = get_sun_brightness(sun_dir);
// 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));
// float my_alt = alt_at(f_pos.xy);
float shadow_alt = /*f_pos.z;*/alt_at(f_pos.xy);
float sun_shade_frac = horizon_at2(f_shadow, shadow_alt, f_pos, sun_dir);
float moon_shade_frac = horizon_at2(f_shadow, shadow_alt, f_pos, moon_dir);
// float sun_shade_frac = horizon_at(/*f_shadow, f_pos.z, */f_pos, sun_dir);
// float moon_shade_frac = horizon_at(/*f_shadow, f_pos.z, */f_pos, moon_dir);
// Globbal illumination "estimate" used to light the faces of voxels which are parallel to the sun or moon (which is a very common occurrence).
// Will be attenuated by k_d, which is assumed to carry any additional ambient occlusion information (e.g. about shadowing).
// float ambient_sides = clamp(mix(0.5, 0.0, abs(dot(-f_norm, sun_dir)) * 10000.0), 0.0, 0.5);
// NOTE: current assumption is that moon and sun shouldn't be out at the sae time.
// This assumption is (or can at least easily be) wrong, but if we pretend it's true we avoids having to explicitly pass in a separate shadow
// for the sun and moon (since they have different brightnesses / colors so the shadows shouldn't attenuate equally).
float shade_frac = sun_shade_frac + moon_shade_frac;
// float brightness_denominator = (ambient_sides + vec3(SUN_AMBIANCE * sun_light + moon_light);
// vec3 sun_dir = get_sun_dir(time_of_day.x);
// vec3 moon_dir = get_moon_dir(time_of_day.x);
// // float sun_light = get_sun_brightness(sun_dir);
// // 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));
// // 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);
// float moon_shade_frac = horizon_at2(f_shadow, shadow_alt, f_pos, moon_dir);
// // float sun_shade_frac = horizon_at(/*f_shadow, f_pos.z, */f_pos, sun_dir);
// // float moon_shade_frac = horizon_at(/*f_shadow, f_pos.z, */f_pos, moon_dir);
// // Globbal illumination "estimate" used to light the faces of voxels which are parallel to the sun or moon (which is a very common occurrence).
// // Will be attenuated by k_d, which is assumed to carry any additional ambient occlusion information (e.g. about shadowing).
// // float ambient_sides = clamp(mix(0.5, 0.0, abs(dot(-f_norm, sun_dir)) * 10000.0), 0.0, 0.5);
// // NOTE: current assumption is that moon and sun shouldn't be out at the sae time.
// // This assumption is (or can at least easily be) wrong, but if we pretend it's true we avoids having to explicitly pass in a separate shadow
// // for the sun and moon (since they have different brightnesses / colors so the shadows shouldn't attenuate equally).
// // float shade_frac = sun_shade_frac + moon_shade_frac;
// // float brightness_denominator = (ambient_sides + vec3(SUN_AMBIANCE * sun_light + moon_light);
// DirectionalLight sun_info = get_sun_info(sun_dir, sun_shade_frac, light_pos);
DirectionalLight sun_info = get_sun_info(sun_dir, sun_shade_frac, /*sun_pos*/f_pos);
DirectionalLight moon_info = get_moon_info(moon_dir, moon_shade_frac/*, light_pos*/);
float alpha = 1.0;//0.1;//0.2;///1.0;//sqrt(2.0);
const float n2 = 1.5;
@ -379,11 +518,11 @@ 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(/*f_norm*/voxel_norm/*l_norm*/, sun_dir, moon_dir, 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, 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, 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);
// emitted_light = vec3(1.0);
emitted_light *= max(shade_frac, MIN_SHADOW);
reflected_light *= shade_frac;
max_light *= shade_frac;
// emitted_light *= max(shade_frac, MIN_SHADOW);
// reflected_light *= shade_frac;
// max_light *= shade_frac;
// reflected_light = vec3(0.0);
// dot(diffuse_factor, /*R_r * */vec4(abs(norm) * (1.0 - dist), dist))
@ -423,7 +562,7 @@ void main() {
// f_ao = /*sqrt*/1.0 - (dot(ao_pos, ao_pos)/* / 2.0*/);
// f_ao = /*sqrt*/1.0 - 2.0 * (dot(ao_pos, ao_pos)/* / 2.0*/);
// f_ao = /*sqrt*/1.0 - 2.0 * sqrt(dot(ao_pos, ao_pos) / 2.0);
float ao = /*pow(f_ao, 0.5)*/f_ao * 0.9 + 0.1;
float ao = f_ao;// /*pow(f_ao, 0.5)*/f_ao * 0.9 + 0.1;
emitted_light *= ao;
reflected_light *= ao;
@ -440,10 +579,13 @@ void main() {
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, 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);
// vec3 color = surf_color;
#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;

View File

@ -29,7 +29,7 @@ uniform u_locals {
out vec3 f_pos;
out vec3 f_norm;
out vec2 v_pos_orig;
// out vec2 v_pos_orig;
// out vec4 f_square;
// out vec4 f_shadow;
// out float f_light;
@ -40,7 +40,7 @@ void main() {
vec2 dims = vec2(1.0 / view_distance.y);
vec4 f_square = focus_pos.xyxy + vec4(splay(v_pos - dims), splay(v_pos + dims));
f_norm = lod_norm(f_pos.xy, f_square);
v_pos_orig = v_pos;
// v_pos_orig = v_pos;
// f_pos = lod_pos(focus_pos.xy + splay(v_pos) * /*1000000.0*/(1 << 20), square);
@ -92,10 +92,13 @@ void main() {
// f_light = 1.0;
gl_Position =
proj_mat *
view_mat *
/* proj_mat *
view_mat * */
all_mat *
vec4(f_pos/*newRay*/, 1);
// gl_Position.z = -gl_Position.z / gl_Position.w;
// gl_Position.z = -gl_Position.z / gl_Position.w;
// gl_Position.z = -gl_Position.z * gl_Position.w;
// gl_Position.z = -gl_Position.z / 100.0;
gl_Position.z = -1000.0 / (gl_Position.z + 10000.0);
// gl_Position.z = -1000.0 / (gl_Position.z + 10000.0);
}

View File

@ -18,18 +18,21 @@ in vec3 f_pos;
in vec3 f_col;
flat in vec3 f_norm;
in float f_ao;
in float f_alt;
in vec4 f_shadow;
// in float f_alt;
// in vec4 f_shadow;
layout (std140)
uniform u_locals {
mat4 model_mat;
vec4 model_col;
ivec4 atlas_offs;
vec3 model_pos;
int flags;
};
struct BoneData {
mat4 bone_mat;
mat4 normals_mat;
};
layout (std140)
@ -44,17 +47,17 @@ uniform u_bones {
out vec4 tgt_color;
void main() {
float distance = distance(vec3(cam_pos), focus_pos.xyz) - 2;
// float distance = distance(vec3(cam_pos), focus_pos.xyz) - 2;
float opacity = clamp(distance / distance_divider, 0, 1);
// float opacity = clamp(distance / distance_divider, 0, 1);
if(threshold_matrix[int(gl_FragCoord.x) % 4][int(gl_FragCoord.y) % 4] > opacity) {
discard;
}
// if(threshold_matrix[int(gl_FragCoord.x) % 4][int(gl_FragCoord.y) % 4] > opacity) {
// discard;
// }
if(threshold_matrix[int(gl_FragCoord.x) % 4][int(gl_FragCoord.y) % 4] > shadow_dithering) {
discard;
}
// if(threshold_matrix[int(gl_FragCoord.x) % 4][int(gl_FragCoord.y) % 4] > shadow_dithering) {
// discard;
// }
tgt_color = vec4(0.0,0.0,0.0, 1.0);
}

View File

@ -144,9 +144,9 @@ vec3 illuminate(float max_light, vec3 view_dir, /*vec3 max_light, */vec3 emitted
void main() {
vec2 uv = (f_pos + 1.0) * 0.5;
if (medium.x == 1u) {
/* if (medium.x == 1u) {
uv = clamp(uv + vec2(sin(uv.y * 16.0 + tick.x), sin(uv.x * 24.0 + tick.x)) * 0.005, 0, 1);
}
} */
vec2 c_uv = vec2(0.5);//uv;//vec2(0.5);//uv;
vec2 delta = /*sqrt*//*sqrt(2.0) / 2.0*//*sqrt(2.0) / 2.0*//*0.5 - */min(uv, 1.0 - uv);//min(uv * (1.0 - uv), 0.25) * 2.0;
@ -186,9 +186,11 @@ void main() {
vec4 final_color = pow(aa_color, gamma);
/* if (medium.x == 1u) {
#if (FLUID_MODE == FLUID_MODE_CHEAP)
if (medium.x == 1u) {
final_color *= vec4(0.2, 0.2, 0.8, 1.0);
} */
}
#endif
tgt_color = vec4(final_color.rgb, 1);
}

View File

@ -30,5 +30,5 @@ out vec2 f_pos;
void main() {
f_pos = v_pos;
gl_Position = vec4(v_pos, 0.0, 1.0);
gl_Position = vec4(v_pos, -1.0, 1.0);
}

View File

@ -30,6 +30,8 @@ uniform u_locals {
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);

View File

@ -28,12 +28,22 @@ uniform u_locals {
out vec3 f_pos;
void main() {
/* vec3 v_pos = v_pos;
v_pos.y = -v_pos.y; */
f_pos = v_pos;
// TODO: Make this position-independent to avoid rounding error jittering
gl_Position =
proj_mat *
view_mat *
vec4(v_pos * 100000.0 + cam_pos.xyz, 1);
gl_Position.z = 0.0;
/* proj_mat *
view_mat * */
all_mat *
/* proj_mat *
view_mat * */
vec4(/*100000 * */v_pos + cam_pos.xyz, 1);
// vec4(v_pos * (100000.0/* + 0.5*/) + cam_pos.xyz, 1);
// gl_Position = vec4(gl_Position.xy, sign(gl_Position.z) * gl_Position.w, gl_Position.w);
gl_Position.z = gl_Position.w;
// gl_Position.z = gl_Position.w - 0.000001;//0.0;
// gl_Position.z = 1.0;
// gl_Position.z = -1.0;
}

View File

@ -12,15 +12,32 @@
#define LIGHTING_DISTRIBUTION LIGHTING_DISTRIBUTION_BECKMANN
// #define HAS_SHADOW_MAPS
#define HAS_SHADOW_MAPS
#include <globals.glsl>
in vec3 f_pos;
flat in vec3 f_norm;
in vec3 f_col;
in float f_ao;
flat in float f_light;
// flat in vec3 f_pos_norm;
in vec2 f_uv_pos;
// flat in uint f_atlas_pos;
// in vec3 f_col;
// in float f_ao;
// in float f_light;
// in vec4 light_pos[2];
uniform sampler2D t_col_light;
//struct ShadowLocals {
// mat4 shadowMatrices;
// mat4 texture_mat;
//};
//
//layout (std140)
//uniform u_light_shadows {
// ShadowLocals shadowMats[/*MAX_LAYER_FACES*/192];
//};
out vec4 tgt_color;
@ -31,19 +48,70 @@ out vec4 tgt_color;
const float FADE_DIST = 32.0;
void main() {
/* if (f_uv_pos.x < 757) {
discard;
} */
// vec2 f_uv_pos = vec2(768,1) + 0.5;
// vec2 f_uv_pos = vec2(760, 380);// + 0.5;
// vec2 f_uv_pos = vec2((uvec2(f_atlas_pos) >> uvec2(0, 16)) & uvec2(0xFFFFu, 0xFFFFu)) + 0.5;
/* if (f_uv_pos.x < 757) {
discard;
} */
// vec3 du = dFdx(f_pos);
// vec3 dv = dFdy(f_pos);
// vec3 f_norm = normalize(cross(du, dv));
// vec4 f_col_light = texture(t_col_light, (f_uv_pos + 0.5) / textureSize(t_col_light, 0)/* + uv_delta*//* - f_norm * 0.00001*/);
// vec4 f_col_light = textureGrad(t_col_light, (f_uv_pos + 0.5) / textureSize(t_col_light, 0), vec2(0.5), vec2(0.5));
vec4 f_col_light = texelFetch(t_col_light, ivec2(f_uv_pos)/* + uv_delta*//* - f_norm * 0.00001*/, 0);
vec3 f_col = /*linear_to_srgb*//*srgb_to_linear*/(f_col_light.rgb);
// vec3 f_col = vec3(1.0);
// vec2 texSize = textureSize(t_col_light, 0);
// float f_ao = f_col_light.a;
// float f_ao = f_col_light.a + length(vec2(dFdx(f_col_light.a), dFdy(f_col_light.a)));
float f_ao = texture(t_col_light, (f_uv_pos + 0.5) / textureSize(t_col_light, 0)).a;//1.0;//f_col_light.a * 4.0;// f_light = float(v_col_light & 0x3Fu) / 64.0;
// float f_ao = 1.0;
// float /*f_light*/f_ao = textureProj(t_col_light, vec3(f_uv_pos, texSize)).a;//1.0;//f_col_light.a * 4.0;// f_light = float(v_col_light & 0x3Fu) / 64.0;
// vec3 my_chunk_pos = f_pos_norm;
// tgt_color = vec4(hash(floor(vec4(my_chunk_pos.x, 0, 0, 0))), hash(floor(vec4(0, my_chunk_pos.y, 0, 1))), hash(floor(vec4(0, 0, my_chunk_pos.z, 2))), 1.0);
// tgt_color = vec4(f_uv_pos / texSize, 0.0, 1.0);
// tgt_color = vec4(f_col.rgb, 1.0);
// return;
// vec4 light_pos[2];
//#if (SHADOW_MODE == SHADOW_MODE_MAP)
// // for (uint i = 0u; i < light_shadow_count.z; ++i) {
// // light_pos[i] = /*vec3(*/shadowMats[i].texture_mat * vec4(f_pos, 1.0)/*)*/;
// // }
// vec4 sun_pos = /*vec3(*/shadowMats[0].texture_mat * vec4(f_pos, 1.0)/*)*/;
//#elif (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_NONE)
// vec4 sun_pos = vec4(0.0);
//#endif
vec3 cam_to_frag = normalize(f_pos - cam_pos.xyz);
// vec4 vert_pos4 = view_mat * vec4(f_pos, 1.0);
// vec3 view_dir = normalize(-vec3(vert_pos4)/* / vert_pos4.w*/);
vec3 view_dir = -cam_to_frag;
vec3 sun_dir = get_sun_dir(time_of_day.x);
vec3 moon_dir = get_moon_dir(time_of_day.x);
/* vec3 sun_dir = get_sun_dir(time_of_day.x);
vec3 moon_dir = get_moon_dir(time_of_day.x); */
// float sun_light = get_sun_brightness(sun_dir);
// float moon_light = get_moon_brightness(moon_dir);
#if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP || FLUID_MODE == FLUID_MODE_SHINY)
float f_alt = alt_at(f_pos.xy);
// float f_alt = f_pos.z;
#elif (SHADOW_MODE == SHADOW_MODE_NONE || FLUID_MODE == FLUID_MODE_CHEAP)
float f_alt = f_pos.z;
#endif
#if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP)
vec4 f_shadow = textureBicubic(t_horizon, pos_to_tex(f_pos.xy));
float sun_shade_frac = horizon_at2(f_shadow, f_alt, f_pos, sun_dir);
float moon_shade_frac = horizon_at2(f_shadow, f_alt, f_pos, moon_dir);
// float sun_shade_frac = 1.0;//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);
#endif
float moon_shade_frac = 1.0;//horizon_at2(f_shadow, f_alt, f_pos, moon_dir);
// float sun_shade_frac = horizon_at(f_pos, sun_dir);
// float moon_shade_frac = horizon_at(f_pos, moon_dir);
// Globbal illumination "estimate" used to light the faces of voxels which are parallel to the sun or moon (which is a very common occurrence).
@ -52,7 +120,12 @@ void main() {
// NOTE: current assumption is that moon and sun shouldn't be out at the sae time.
// This assumption is (or can at least easily be) wrong, but if we pretend it's true we avoids having to explicitly pass in a separate shadow
// for the sun and moon (since they have different brightnesses / colors so the shadows shouldn't attenuate equally).
float shade_frac = sun_shade_frac + moon_shade_frac;
// float shade_frac = sun_shade_frac + moon_shade_frac;
// DirectionalLight sun_info = get_sun_info(sun_dir, sun_shade_frac, light_pos);
float point_shadow = shadow_at(f_pos, f_norm);
DirectionalLight sun_info = get_sun_info(sun_dir, point_shadow * sun_shade_frac, /*sun_pos*/f_pos);
DirectionalLight moon_info = get_moon_info(moon_dir, point_shadow * moon_shade_frac/*, light_pos*/);
vec3 surf_color = /*srgb_to_linear*//*linear_to_srgb*/(f_col);
float alpha = 1.0;
@ -69,7 +142,6 @@ void main() {
vec3 emitted_light, reflected_light;
float point_shadow = shadow_at(f_pos, f_norm);
// To account for prior saturation.
// float vert_light = pow(f_light, 1.5);
// vec3 light_frac = light_reflection_factor(f_norm/*vec3(0, 0, 1.0)*/, view_dir, vec3(0, 0, -1.0), vec3(1.0), vec3(R_s), alpha);
@ -85,10 +157,13 @@ void main() {
// vec3 surf_color = srgb_to_linear(vec3(0.2, 0.5, 1.0));
// vec3 cam_to_frag = normalize(f_pos - cam_pos.xyz);
float max_light = 0.0;
max_light += get_sun_diffuse2(f_norm, /*time_of_day.x, */sun_dir, moon_dir, /*cam_to_frag*/view_dir, k_a/* * (shade_frac * 0.5 + light_frac * 0.5)*/, k_d, k_s, alpha, emitted_light, reflected_light);
reflected_light *= /*vert_light * */point_shadow * shade_frac;
emitted_light *= /*vert_light * */point_shadow * max(shade_frac, MIN_SHADOW);
max_light *= /*vert_light * */point_shadow * shade_frac;
max_light += get_sun_diffuse2(sun_info, moon_info, f_norm, /*time_of_day.x, *//*cam_to_frag*/view_dir, k_a * f_light/* * (shade_frac * 0.5 + light_frac * 0.5)*/, k_d, k_s, alpha, emitted_light, reflected_light);
// reflected_light *= /*vert_light * */point_shadow * shade_frac;
// emitted_light *= /*vert_light * */point_shadow * max(shade_frac, MIN_SHADOW);
// max_light *= /*vert_light * */point_shadow * shade_frac;
// emitted_light *= point_shadow;
// reflected_light *= point_shadow;
// max_light *= point_shadow;
// get_sun_diffuse(f_norm, time_of_day.x, light, diffuse_light, ambient_light, 1.0);
// float point_shadow = shadow_at(f_pos, f_norm);
// diffuse_light *= f_light * point_shadow;
@ -102,17 +177,23 @@ void main() {
emitted_light += point_light;
reflected_light += point_light; */
float ao = /*pow(f_ao, 0.5)*/f_ao * 0.85 + 0.15;
// float ao = /*pow(f_ao, 0.5)*/f_ao * 0.85 + 0.15;
float ao = f_ao;
emitted_light *= ao;
reflected_light *= ao;
surf_color = illuminate(max_light, view_dir, surf_color * emitted_light, surf_color * reflected_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, true, 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));
}

View File

@ -14,64 +14,223 @@
#include <globals.glsl>
#include <srgb.glsl>
#include <sky.glsl>
in vec3 v_pos;
in uint v_col;
in uint v_atlas_pos;
// in uint v_col;
in uint v_norm_ao;
in uint inst_pos_ori;
in vec4 inst_mat0;
in vec4 inst_mat1;
in vec4 inst_mat2;
in vec4 inst_mat3;
in vec3 inst_col;
// in vec3 inst_col;
in float inst_wind_sway;
struct SpriteLocals {
mat4 mat;
vec4 wind_sway;
vec4 offs;
};
layout (std140)
uniform u_locals {
mat4 mat;
vec4 wind_sway;
vec4 offs;
// SpriteLocals sprites[8];
};
// struct Instance {
// mat4 inst_mat;
// vec3 inst_col;
// float inst_wind_sway;
// };
//
// layout (std140)
// uniform u_ibuf {
// Instance sprite_instances[/*MAX_LAYER_FACES*/512];
// };
//struct ShadowLocals {
// mat4 shadowMatrices;
// mat4 texture_mat;
//};
//
//layout (std140)
//uniform u_light_shadows {
// ShadowLocals shadowMats[/*MAX_LAYER_FACES*/192];
//};
layout (std140)
uniform u_terrain_locals {
vec3 model_offs;
float load_time;
ivec4 atlas_offs;
};
out vec3 f_pos;
flat out vec3 f_norm;
out vec3 f_col;
out float f_ao;
flat out float f_light;
// flat out vec3 f_pos_norm;
// out vec3 f_col;
// out float f_ao;
out vec2 f_uv_pos;
// flat out uint f_atlas_pos;
// out vec3 light_pos[2];
// out float f_light;
const float SCALE = 1.0 / 11.0;
const float SCALE_FACTOR = pow(SCALE, 1.3) * 0.2;
const int EXTRA_NEG_Z = 32768;
void main() {
// vec3 inst_chunk_pos = vec3(ivec3((uvec3(inst_pos_ori) >> uvec3(0, 6, 12)) & uvec3(0x3Fu, 0x3Fu, 0xFFFFu)) - ivec3(0, 0, EXTRA_NEG_Z));
// uint inst_ori = (inst_pos_ori >> 29) & 0x7u;
// SpriteLocals locals = sprites[inst_ori];
// SpriteLocals locals = sprites;
// mat4 inst_mat = locals.mat;
// float inst_wind_sway = locals.wind_sway.w;
// mat4 inst_mat = mat4(vec4(1, 0, 0, 0), vec4(0, 1, 0, 0), vec4(0, 0, 1, 0), vec4(5.5, 5.5, 0, 1));
// float inst_wind_sway = 0.0;
mat4 inst_mat;
inst_mat[0] = inst_mat0;
inst_mat[1] = inst_mat1;
inst_mat[2] = inst_mat2;
inst_mat[3] = inst_mat3;
/* Instance instances = sprite_instances[gl_InstanceID & 1023];
mat4 inst_mat = instances.inst_mat;
vec3 inst_col = instances.inst_col;
float inst_wind_sway = instances.inst_wind_sway; */
vec3 inst_offs = model_offs - focus_off.xyz;
// mat3 inst_mat;
// inst_mat[0] = inst_mat0.xyz;
// inst_mat[1] = inst_mat1.xyz;
// inst_mat[2] = inst_mat2.xyz;
// /* Instance instances = sprite_instances[gl_InstanceID & 1023];
// mat4 inst_mat = instances.inst_mat;
// vec3 inst_col = instances.inst_col;
// float inst_wind_sway = instances.inst_wind_sway; */
// float inst_wind_sway = wind_sway.w;
// vec3 inst_offs = model_offs - focus_off.xyz;
vec3 sprite_pos = (inst_mat * vec4(0, 0, 0, 1)).xyz;
// vec3 sprite_pos = floor(inst_mat3.xyz * SCALE) + inst_offs;
f_pos = (inst_mat * vec4(v_pos * SCALE, 1)).xyz;
f_pos.z -= min(32.0, 25.0 * pow(distance(focus_pos.xy, f_pos.xy) / view_distance.x, 20.0));
// f_pos_norm = v_pos;
// vec3 sprite_pos = (inst_mat * vec4(0, 0, 0, 1)).xyz;
// vec3 sprite_pos = floor((inst_mat * vec4(0, 0, 0, 1)).xyz * SCALE/* - vec3(0.5, 0.5, 0.0)*/) + inst_offs;
// vec3 sprite_pos = /*round*/floor(((inst_mat * vec4(0, 0, 0, 1)).xyz - /* wind_sway.xyz * */offs.xyz) * SCALE/* - vec3(0.5, 0.5, 0.0)*/) - inst_offs;
// vec3 sprite_pos = /*round*/floor(((inst_mat * vec4(-offs.xyz, 1)).xyz) * SCALE/* - vec3(0.5, 0.5, 0.0)*/) + inst_offs;
// vec3 v_pos = vec3(gl_VertexID * 32, gl_VertexID % 32, 1.0);
// f_pos = v_pos + (model_offs - focus_off.xyz);
// vec3 v_pos = /*inst_mat*//*locals.*/wind_sway.xyz * v_pos;
vec3 v_pos_ = /*inst_mat*//*locals.*//*sprites[0].*/wind_sway.xyz * v_pos;
// vec3 v_pos = (/*inst_mat*/locals.mat * vec4(v_pos, 1)).xyz + vec3(0.5, 0.5, 0.0);
// f_pos = v_pos * SCALE + (inst_chunk_pos + model_offs - focus_off.xyz);
// vec3 v_pos_ = (inst_mat * vec4(v_pos/* * SCALE*/, 1)).xyz;
// vec3 v_pos = (inst_mat * vec4(v_pos, 1)).xyz;
// f_pos = v_pos + (model_offs - focus_off.xyz);
f_pos = (inst_mat * vec4(v_pos_, 1.0)).xyz * SCALE + inst_offs;
// f_pos = (inst_mat * v_pos_) * SCALE + sprite_pos;
// f_pos = (inst_mat * vec4(v_pos * SCALE, 1)).xyz + (model_offs - focus_off.xyz);
// f_pos = v_pos_ + (inst_chunk_pos + model_offs - focus_off.xyz + vec3(0.5, 0.5, 0.0));
// f_pos.z -= min(32.0, 25.0 * pow(distance(focus_pos.xy, f_pos.xy) / view_distance.x, 20.0));
// Wind waving
f_pos += inst_wind_sway * vec3(
/* const float x_scale = sin(tick.x * 1.5 + f_pos.x * 0.1);
const float y_scale = sin(tick.x * 1.5 + f_pos.y * 0.1);
const float z_scale = pow(abs(v_pos_.z), 1.3) * SCALE_FACTOR;
const float xy_bias = sin(tick.x * 0.25);
const float z_bias = xy_bias * t_scale;
mat3 shear = mat4(
vec3(x_scale , 0.0, 0.0, 0.0),
vec3(0.0, y_scale, 0.0, 0.0),
vec3(0.0, 0.0, z_bias, 0.0),
vec3(0.0, 0.0, (1.0 / z_bias), 0.0)
); */
// const float x_scale = sin(tick.x * 1.5 + f_pos.x * 0.1);
// const float y_scale = sin(tick.x * 1.5 + f_pos.y * 0.1);
// const float z_scale = pow(abs(v_pos_.z), 1.3) * SCALE_FACTOR;
// const float xy_bias = sin(tick.x * 0.25);
// const float z_bias = xy_bias * t_scale;
// vec3 rotate = inst_wind_sway * vec3(
// sin(tick.x * 1.5 + f_pos.y * 0.1) * sin(tick.x * 0.35),
// sin(tick.x * 1.5 + f_pos.x * 0.1) * sin(tick.x * 0.25),
// 0.0
// ) * pow(abs(v_pos_.z/* + sprites[0].offs.z*/)/* * SCALE*/, 1.3) * /*0.2;*/SCALE_FACTOR;
//
// mat3 shear = mat4(
// vec3(x_scale * , 0.0, 0.0, 0.0),
// vec3(0.0, y_scale, 0.0, 0.0),
// vec3(0.0, 0.0, z_bias, 0.0),
// vec3(0.0, 0.0, (1.0 / z_bias), 0.0)
// );
if (wind_sway.w >= 0.4) {
f_pos += /*inst_wind_sway*/wind_sway.w * vec3(
sin(tick.x * 1.5 + f_pos.y * 0.1) * sin(tick.x * 0.35),
sin(tick.x * 1.5 + f_pos.x * 0.1) * sin(tick.x * 0.25),
0.0
) * pow(abs(v_pos.z) * SCALE, 1.3) * 0.2;
// First 3 normals are negative, next 3 are positive
vec3 normals[6] = vec3[](vec3(-1,0,0), vec3(1,0,0), vec3(0,-1,0), vec3(0,1,0), vec3(0,0,-1), vec3(0,0,1));
f_norm = (inst_mat * vec4(normals[(v_norm_ao >> 0) & 0x7u], 0)).xyz;
vec3 col = vec3((uvec3(v_col) >> uvec3(0, 8, 16)) & uvec3(0xFFu)) / 255.0;
f_col = srgb_to_linear(col) * srgb_to_linear(inst_col);
f_ao = float((v_norm_ao >> 3) & 0x3u) / 4.0;
// Select glowing
if (select_pos.w > 0 && select_pos.xyz == floor(sprite_pos)) {
f_col *= 4.0;
) * pow(abs(v_pos_.z/* + sprites[0].offs.z*/)/* * SCALE*/, 1.3) * /*0.2;*/SCALE_FACTOR;
}
// First 3 normals are negative, next 3 are positive
// vec3 normals[6] = vec3[](vec3(-1,0,0), vec3(1,0,0), vec3(0,-1,0), vec3(0,1,0), vec3(0,0,-1), vec3(0,0,1));
// uint norm_idx = (v_norm_ao >> 0) & 0x7u;
// f_norm = (inst_mat * vec4(normals[], 0)).xyz;
// TODO: Consider adding a second, already-normalized (i.e. unscaled) matrix.
// vec3 norm = /*normalize*/(inst_mat/*locals.mat*/[(v_norm_ao >> 1u) & 3u].xyz);
// vec3 norm = /*normalize*/(inst_mat/*locals.mat*/[(v_norm_ao >> 1u) & 3u]);
// vec3 norm = bone_data.normals_mat[axis_idx].xyz;
// norm = normalize(norm);
// norm = norm / SCALE_FACTOR / locals.wind_sway.xyz;
// norm = norm / (norm.x + norm.y + norm.z);
// vec3 norm = norm_mat * vec4(uvec3(1 << axis_idx) & uvec3(0x1u, 0x3u, 0x7u), 1);
// // Calculate normal here rather than for each pixel in the fragment shader
// f_norm = normalize((
// combined_mat *
// vec4(norm, 0)
// ).xyz);
vec3 norm = /*normalize*/(inst_mat/*locals.mat*/[(v_norm_ao >> 1u) & 3u].xyz);
f_norm = mix(-norm, norm, v_norm_ao & 1u);
/* vec3 col = vec3((uvec3(v_col) >> uvec3(0, 8, 16)) & uvec3(0xFFu)) / 255.0;
f_col = srgb_to_linear(col) * srgb_to_linear(inst_col);
f_ao = float((v_norm_ao >> 3) & 0x3u) / 4.0; */
f_uv_pos = vec2((uvec2(v_atlas_pos) >> uvec2(0, 16)) & uvec2(0xFFFFu, 0xFFFFu));/* + 0.5*/;
// f_atlas_pos = v_atlas_pos;
/* for (uint i = 0u; i < light_shadow_count.z; ++i) {
light_pos[i] = vec3(shadowMats[i].texture_mat * vec4(f_pos, 1.0));
} */
// // Select glowing
// if (select_pos.w > 0 && select_pos.xyz == floor(sprite_pos)) {
// f_col *= 4.0;
// }
// f_light = 1.0;
// if (select_pos.w > 0) */{
vec3 sprite_pos = /*round*/floor(((inst_mat * vec4(-offs.xyz, 1)).xyz) * SCALE/* - vec3(0.5, 0.5, 0.0)*/) + inst_offs;
f_light = (select_pos.w > 0 && select_pos.xyz == sprite_pos/* - vec3(0.5, 0.5, 0.0) * SCALE*/) ? 1.0 / PERSISTENT_AMBIANCE : 1.0;
// }
gl_Position =
all_mat *
vec4(f_pos, 1);
// gl_Position.z = -gl_Position.z;
// gl_Position.z = -gl_Position.z / gl_Position.w;
// gl_Position.z = -gl_Position.z / 100.0;
// gl_Position.z = -gl_Position.z / 100.0;
gl_Position.z = -1000.0 / (gl_Position.z + 10000.0);
// gl_Position.z = -1000.0 / (gl_Position.z + 10000.0);
}

View File

@ -23,13 +23,35 @@
#include <random.glsl>
in vec3 f_pos;
in vec3 f_chunk_pos;
// in float f_ao;
// in vec3 f_chunk_pos;
// #ifdef FLUID_MODE_SHINY
flat in uint f_pos_norm;
// #else
// const uint f_pos_norm = 0u;
// #endif
// in float f_alt;
// in vec4 f_shadow;
in vec3 f_col;
in float f_light;
in float f_ao;
// in vec3 f_col;
// in float f_light;
/*centroid */in vec2 f_uv_pos;
// in vec3 light_pos[2];
// const vec3 light_pos[6] = vec3[](vec3(0), vec3(0), vec3(00), vec3(0), vec3(0), vec3(0));
/* #if (SHADOW_MODE == SHADOW_MODE_MAP)
in vec4 sun_pos;
#elif (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_NONE)
const vec4 sun_pos = vec4(0.0);
#endif */
uniform sampler2D t_col_light;
layout (std140)
uniform u_locals {
vec3 model_offs;
float load_time;
ivec4 atlas_offs;
};
out vec4 tgt_color;
@ -38,6 +60,44 @@ out vec4 tgt_color;
#include <lod.glsl>
void main() {
// discard;
// vec4 f_col_light = textureGrad(t_col_light, f_uv_pos / texSize, 0.25, 0.25);
// vec4 f_col_light = texture(t_col_light, (f_uv_pos) / texSize);
// First 3 normals are negative, next 3 are positive
const vec3 normals[8] = vec3[](vec3(-1,0,0), vec3(1,0,0), vec3(0,-1,0), vec3(0,1,0), vec3(0,0,-1), vec3(0,0,1), vec3(0,0,0), vec3(0,0,0));
// uint norm_index = (f_pos_norm >> 29) & 0x7u;
// vec2 uv_delta = (norm_index & 0u) == 0u ? vec2(-1.0) : vec2(0);
vec2 f_uv_pos = f_uv_pos + atlas_offs.xy;
// vec4 f_col_light = textureProj(t_col_light, vec3(f_uv_pos + 0.5, textureSize(t_col_light, 0)));//(f_uv_pos/* + 0.5*/) / texSize);
// float f_light = textureProj(t_col_light, vec3(f_uv_pos + 0.5, textureSize(t_col_light, 0))).a;//1.0;//f_col_light.a * 4.0;// f_light = float(v_col_light & 0x3Fu) / 64.0;
vec4 f_col_light = texelFetch(t_col_light, ivec2(f_uv_pos)/* + uv_delta*//* - f_norm * 0.00001*/, 0);
// float f_light = f_col_light.a;
// vec4 f_col_light = texelFetch(t_col_light, ivec2(int(f_uv_pos.x), int(f_uv_pos.y)/* + uv_delta*//* - f_norm * 0.00001*/), 0);
vec3 f_col = /*linear_to_srgb*//*srgb_to_linear*/(f_col_light.rgb);
// vec3 f_col = vec3(1.0);
float f_light = texture(t_col_light, (f_uv_pos + 0.5) / textureSize(t_col_light, 0)).a;//1.0;//f_col_light.a * 4.0;// f_light = float(v_col_light & 0x3Fu) / 64.0;
// vec2 texSize = textureSize(t_col_light, 0);
// float f_light = texture(t_col_light, f_uv_pos/* + vec2(atlas_offs.xy)*/).a;//1.0;//f_col_light.a * 4.0;// f_light = float(v_col_light & 0x3Fu) / 64.0;
// float f_light = textureProj(t_col_light, vec3(f_uv_pos/* + vec2(atlas_offs.xy)*/, texSize.x)).a;//1.0;//f_col_light.a * 4.0;// f_light = float(v_col_light & 0x3Fu) / 64.0;
// float f_light = textureProjLod(t_col_light, vec3(f_uv_pos/* + vec2(atlas_offs.xy)*/, texSize.x), 0).a;//1.0;//f_col_light.a * 4.0;// f_light = float(v_col_light & 0x3Fu) / 64.0;
// float f_light = textureGrad(t_col_light, (f_uv_pos + 0.5) / texSize, vec2(0.1, 0.0), vec2(0.0, 0.1)).a;//1.0;//f_col_light.a * 4.0;// f_light = float(v_col_light & 0x3Fu) / 64.0;
// f_light = sqrt(f_light);
// f_light = sqrt(f_light);
// f_col = vec3((uvec3(v_col_light) >> uvec3(8, 16, 24)) & uvec3(0xFFu)) / 255.0;
// vec3 f_col = light_col.rgb;//vec4(1.0, 0.0, 0.0, 1.0);
// float f_ao = 1.0;
// vec3 my_chunk_pos = vec3(ivec3((uvec3(f_pos_norm) >> uvec3(0, 6, 12)) & uvec3(0x3Fu, 0x3Fu, 0xFFFFu)));
// tgt_color = vec4(hash(floor(vec4(my_chunk_pos.x, 0, 0, 0))), hash(floor(vec4(0, my_chunk_pos.y, 0, 1))), hash(floor(vec4(0, 0, my_chunk_pos.z, 2))), 1.0);
// tgt_color.rgb *= f_light;
// tgt_color = vec4(vec3(f_light), 1.0);
// tgt_color = vec4(f_col, 1.0);
// return;
// vec4 light_pos[2];
// vec4 light_col = vec4(
// hash(floor(vec4(f_pos.x, 0, 0, 0))),
// hash(floor(vec4(0, f_pos.y, 0, 1))),
@ -46,7 +106,7 @@ void main() {
// );
// vec3 f_col = light_col.rgb;//vec4(1.0, 0.0, 0.0, 1.0);
// tgt_color = vec4(f_col, 1.0);
// return;
// tgt_color = vec4(light_shadow_count.x <= 31u ? f_col : vec3(0.0), 1.0);
// tgt_color = vec4(0.0, 0.0, 0.0, 1.0);
// float sum = 0.0;
// for (uint i = 0u; i < /* 6 * */light_shadow_count.x; i ++) {
@ -91,6 +151,18 @@ void main() {
// sum += light_strength;
// }
// TODO: last 3 bits in v_pos_norm should be a number between 0 and 5, rather than 0-2 and a direction.
// uint norm_axis = (f_pos_norm >> 30) & 0x3u;
// // Increase array access by 3 to access positive values
// uint norm_dir = ((f_pos_norm >> 29) & 0x1u) * 3u;
// Use an array to avoid conditional branching
// uint norm_index = (f_pos_norm >> 29) & 0x7u;
// vec3 f_norm = normals[norm_index];
vec3 f_norm = normals[(f_pos_norm >> 29) & 0x7u];
// vec3 du = dFdx(f_pos);
// vec3 dv = dFdy(f_pos);
// vec3 f_norm = normalize(cross(du, dv));
// /* if (light_shadow_count.x == 1) {
// tgt_color.rgb = vec3(0.0);
// } */
@ -98,16 +170,6 @@ void main() {
// tgt_color.rgb /= sum;
// }
// return;
// First 3 normals are negative, next 3 are positive
vec3 normals[6] = vec3[](vec3(-1,0,0), vec3(1,0,0), vec3(0,-1,0), vec3(0,1,0), vec3(0,0,-1), vec3(0,0,1));
// TODO: last 3 bits in v_pos_norm should be a number between 0 and 5, rather than 0-2 and a direction.
// uint norm_axis = (f_pos_norm >> 30) & 0x3u;
// // Increase array access by 3 to access positive values
// uint norm_dir = ((f_pos_norm >> 29) & 0x1u) * 3u;
// Use an array to avoid conditional branching
vec3 f_norm = normals[(f_pos_norm >> 29) & 0x7u];
// Whether this face is facing fluid or not.
bool faces_fluid = bool((f_pos_norm >> 28) & 0x1u);
@ -117,11 +179,14 @@ void main() {
vec3 view_dir = -cam_to_frag;
// vec3 view_dir = normalize(f_pos - cam_pos.xyz);
vec3 sun_dir = get_sun_dir(time_of_day.x);
vec3 moon_dir = get_moon_dir(time_of_day.x);
/* vec3 sun_dir = get_sun_dir(time_of_day.x);
vec3 moon_dir = get_moon_dir(time_of_day.x); */
#if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP || FLUID_MODE == FLUID_MODE_SHINY)
float f_alt = alt_at(f_pos.xy);
vec4 f_shadow = textureBicubic(t_horizon, pos_to_tex(f_pos.xy));
#elif (SHADOW_MODE == SHADOW_MODE_NONE || FLUID_MODE == FLUID_MODE_CHEAP)
float f_alt = f_pos.z;
#endif
float alpha = 1.0;//0.0001;//1.0;
// TODO: Possibly angle with water surface into account? Since we can basically assume it's horizontal.
@ -145,15 +210,25 @@ void main() {
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));
#if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP)
vec4 f_shadow = textureBicubic(t_horizon, pos_to_tex(f_pos.xy));
float sun_shade_frac = horizon_at2(f_shadow, f_alt, f_pos, sun_dir);
float moon_shade_frac = horizon_at2(f_shadow, f_alt, f_pos, moon_dir);
#elif (SHADOW_MODE == SHADOW_MODE_NONE)
float sun_shade_frac = 1.0;//horizon_at2(f_shadow, f_alt, f_pos, sun_dir);
#endif
float moon_shade_frac = 1.0;//horizon_at2(f_shadow, f_alt, f_pos, moon_dir);
// Globbal illumination "estimate" used to light the faces of voxels which are parallel to the sun or moon (which is a very common occurrence).
// Will be attenuated by k_d, which is assumed to carry any additional ambient occlusion information (e.g. about shadowing).
// float ambient_sides = clamp(mix(0.5, 0.0, abs(dot(-f_norm, sun_dir)) * 10000.0), 0.0, 0.5);
// NOTE: current assumption is that moon and sun shouldn't be out at the sae time.
// This assumption is (or can at least easily be) wrong, but if we pretend it's true we avoids having to explicitly pass in a separate shadow
// for the sun and moon (since they have different brightnesses / colors so the shadows shouldn't attenuate equally).
float shade_frac = /*1.0;*/sun_shade_frac + moon_shade_frac;
// float shade_frac = /*1.0;*/sun_shade_frac + moon_shade_frac;
// DirectionalLight sun_info = get_sun_info(sun_dir, sun_shade_frac, light_pos);
float point_shadow = shadow_at(f_pos, f_norm);
DirectionalLight sun_info = get_sun_info(sun_dir, point_shadow * sun_shade_frac, /*sun_pos*/f_pos);
DirectionalLight moon_info = get_moon_info(moon_dir, point_shadow * moon_shade_frac/*, light_pos*/);
float max_light = 0.0;
@ -171,21 +246,26 @@ void main() {
// Computing light attenuation from water.
vec3 emitted_light, reflected_light;
// To account for prior saturation
float f_light = faces_fluid ? 1.0 : pow(f_light, 1.5);
float point_shadow = shadow_at(f_pos, f_norm);
max_light += get_sun_diffuse2(f_norm, /*time_of_day.x, */sun_dir, moon_dir, view_dir, f_pos, mu, cam_attenuation, fluid_alt, k_a/* * (shade_frac * 0.5 + light_frac * 0.5)*/, k_d, k_s, alpha, 1.0, emitted_light, reflected_light);
/*float */f_light = faces_fluid ? 1.0 : pow(f_light, 1.5);
emitted_light *= f_light * point_shadow * max(shade_frac, MIN_SHADOW);
reflected_light *= f_light * point_shadow * shade_frac;
max_light *= f_light * point_shadow * shade_frac;
emitted_light = vec3(1.0);
reflected_light = vec3(1.0);
max_light += get_sun_diffuse2(/*time_of_day.x, */sun_info, moon_info, f_norm, view_dir, f_pos, mu, cam_attenuation, fluid_alt, k_a/* * (shade_frac * 0.5 + light_frac * 0.5)*/, k_d, k_s, alpha, f_norm, 1.0, emitted_light, reflected_light);
max_light += lights_at(f_pos, f_norm, view_dir, mu, cam_attenuation, fluid_alt, k_a, k_d, k_s, alpha, 1.0, emitted_light, reflected_light);
// emitted_light *= f_light * point_shadow * max(shade_frac, MIN_SHADOW);
// reflected_light *= f_light * point_shadow * shade_frac;
// max_light *= f_light * point_shadow * shade_frac;
emitted_light *= f_light;
reflected_light *= f_light;
max_light *= f_light;
max_light += lights_at(f_pos, f_norm, view_dir, mu, cam_attenuation, fluid_alt, k_a, k_d, k_s, alpha, f_norm, 1.0, emitted_light, reflected_light);
// float f_ao = 1.0;
float ao = /*pow(f_ao, 0.5)*/f_ao * 0.9 + 0.1;
emitted_light *= ao;
reflected_light *= ao;
// float ao = /*pow(f_ao, 0.5)*/f_ao * 0.9 + 0.1;
// emitted_light *= ao;
// reflected_light *= ao;
/* vec3 point_light = light_at(f_pos, f_norm);
emitted_light += point_light;
reflected_light += point_light; */
@ -208,14 +288,19 @@ void main() {
// light_reflection_factorplight_reflection_factor
// vec3 surf_color = illuminate(srgb_to_linear(f_col), light, diffuse_light, ambient_light);
vec3 col = srgb_to_linear(f_col + hash(vec4(floor(f_chunk_pos * 3.0 - f_norm * 0.5), 0)) * 0.02); // Small-scale noise
vec3 f_chunk_pos = f_pos - (model_offs - focus_off.xyz);
vec3 col = /*srgb_to_linear*/(f_col + hash(vec4(floor(f_chunk_pos * 3.0 - f_norm * 0.5), 0)) * 0.01/* - 0.01*/); // Small-scale noise
// 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, true, clouds);
// vec3 color = surf_color;
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);
}

View File

@ -16,52 +16,97 @@
#define LIGHTING_DISTRIBUTION LIGHTING_DISTRIBUTION_BECKMANN
// #define HAS_SHADOW_MAPS
#include <globals.glsl>
#include <srgb.glsl>
#include <lod.glsl>
#include <shadows.glsl>
in uint v_pos_norm;
in uint v_col_light;
// in uint v_col_light;
in uint v_atlas_pos;
layout (std140)
uniform u_locals {
vec3 model_offs;
float load_time;
ivec4 atlas_offs;
};
//struct ShadowLocals {
// mat4 shadowMatrices;
// mat4 texture_mat;
//};
//
//layout (std140)
//uniform u_light_shadows {
// ShadowLocals shadowMats[/*MAX_LAYER_FACES*/192];
//};
out vec3 f_pos;
out vec3 f_chunk_pos;
// #ifdef FLUID_MODE_SHINY
flat out uint f_pos_norm;
// #if (SHADOW_MODE == SHADOW_MODE_MAP)
// out vec4 sun_pos;
// #endif
// #endif
// out float f_alt;
// out vec4 f_shadow;
out vec3 f_col;
out float f_light;
out float f_ao;
// out vec3 f_col;
// out vec3 f_chunk_pos;
// out float f_ao;
/*centroid */out vec2 f_uv_pos;
// out vec3 light_pos[2];
// out float f_light;
// uniform sampler2DRect t_col_light;
const int EXTRA_NEG_Z = 32768;
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));
f_pos = f_chunk_pos + model_offs;
// 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(ivec3((uvec3(v_pos_norm) >> uvec3(0, 6, 12)) & uvec3(0x3Fu, 0x3Fu, 0xFFFFu)) - ivec3(0, 0, EXTRA_NEG_Z));
f_pos = f_chunk_pos + model_offs - focus_off.xyz;
// f_pos.z -= 250.0 * (1.0 - min(1.0001 - 0.02 / pow(tick.x - load_time, 10.0), 1.0));
// f_pos.z -= min(32.0, 25.0 * pow(distance(focus_pos.xy, f_pos.xy) / view_distance.x, 20.0));
// vec3 light_col = vec3(
// hash(floor(vec4(f_pos.x, 0, 0, 0))),
// hash(floor(vec4(0, f_pos.y, 0, 1))),
// hash(floor(vec4(0, 0, f_pos.z, 2)))
// hash(floor(vec4(f_chunk_pos.x, 0, 0, 0))),
// hash(floor(vec4(0, f_chunk_pos.y, 0, 1))),
// hash(floor(vec4(0, 0, f_chunk_pos.z, 2)))
// );
// f_col = light_col;// f_col = vec3((uvec3(v_col_light) >> uvec3(8, 16, 24)) & uvec3(0xFFu)) / 255.0;
// f_light = 1.0;//float(v_col_light & 0x3Fu) / 64.0;
// f_ao = 1.0;//float((v_col_light >> 6u) & 3u) / 4.0;
f_col = f_col = vec3((uvec3(v_col_light) >> uvec3(8, 16, 24)) & uvec3(0xFFu)) / 255.0;
f_light = float(v_col_light & 0x3Fu) / 64.0;
f_ao = float((v_col_light >> 6u) & 3u) / 4.0;
// f_col = f_col = vec3((uvec3(v_col_light) >> uvec3(8, 16, 24)) & uvec3(0xFFu)) / 255.0;
// f_light = float(v_col_light & 0x3Fu) / 64.0;
// f_ao = float((v_col_light >> 6u) & 3u) / 4.0;
// for (uint i = 0u; i < 1u/*light_shadow_count.z*/; ++i) {
// light_pos[i] = vec3(shadowMats[i].texture_mat * vec4(f_pos, 1.0));
// }
// vec2 texSize = textureSize(t_col_light, 0);
f_uv_pos = vec2((uvec2(v_atlas_pos) >> uvec2(0, 16)) & uvec2(0xFFFFu, 0xFFFFu));
// #if (SHADOW_MODE == SHADOW_MODE_MAP)
// // for (uint i = 0u; i < light_shadow_count.z; ++i) {
// // light_pos[i] = /*vec3(*/shadowMats[i].texture_mat * vec4(f_pos, 1.0)/*)*/;
// // }
// sun_pos = /*vec3(*/shadowMats[0].texture_mat * vec4(f_pos, 1.0)/*)*/;
// // #elif (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_NONE)
// // vec4 sun_pos = vec4(0.0);
// #endif
// #ifdef FLUID_MODE_SHINY
f_pos_norm = v_pos_norm;
// #endif
// Also precalculate shadow texture and estimated terrain altitude.
// f_alt = alt_at(f_pos.xy);
@ -104,11 +149,23 @@ void main() {
// // wPoint -= wRayDir3 * wRayLength * n2 / n1;
// vec3 newRay = dot(wRayDir, wRayNormal) < 0.0 && wIntersectsSurface ? wPoint - wRayDir3 * wRayLength * n2 / n1 : f_pos;// - (wRayfinal - wPoint) * n2 / n1; // wPoint + n2 * (wRayfinal - wPoint) - n2 / n1 * wRayLength * wRayDir3;
#ifdef HAS_SHADOW_MAPS
gl_Position =
all_mat *
/*all_mat*/shadowMats[0].shadowMatrices/*texture_mat*/ *
vec4(f_pos/*newRay*/, 1);
gl_Position.z = clamp(gl_Position.z, -abs(gl_Position.w), abs(gl_Position.w));
#else
gl_Position = all_mat * vec4(f_pos/*newRay*/, 1);
#endif
// gl_Position.y /= gl_Position.w;
// gl_Position.w = 1.0;
// gl_Position.z = -gl_Position.z;
// gl_Position.z = -gl_Position.z / gl_Position.w;
// gl_Position.z = -gl_Position.z / gl_Position.w;
// gl_Position.z = -gl_Position.z *gl_Position.w;
// gl_Position.z = gl_Position.z / 100.0;
// gl_Position.z = gl_Position.z / 10000.0;
// gl_Position.z = -gl_Position.z / 100.0;
// gl_Position.z = -gl_Position.z / 100.0;
gl_Position.z = -1000.0 / (gl_Position.z + 10000.0);
// gl_Position.z = -1000.0 / (gl_Position.z + 10000.0);
// gl_Position.z = -1000.0 / (gl_Position.z + 10000.0);
}

View File

@ -22,17 +22,21 @@ out vec4 f_color;
void main() {
f_color = v_color;
// vec2 v_pos = vec2(-1.0,1.0) * v_pos;
/* f_uv = vec2(1.0,1.0) * v_uv; */
// vec2 v_uv = vec2(1.0,-1.0) * v_uv;
if (w_pos.w == 1.0) {
f_uv = v_uv;
// Fixed scale In-game element
vec4 projected_pos = proj_mat * view_mat * vec4(w_pos.xyz, 1.0);
gl_Position = vec4(projected_pos.xy / projected_pos.w + v_pos, 0.0, 1.0);
vec4 projected_pos = /*proj_mat * view_mat*/all_mat * vec4(w_pos.xyz - focus_off.xyz, 1.0);
gl_Position = vec4(projected_pos.xy / projected_pos.w + v_pos/* * projected_pos.w*/, -1.0, /*projected_pos.w*/1.0);
} else if (v_mode == uint(3)) {
// HACK: North facing source rectangle.
vec2 look_at_dir = normalize(vec2(-view_mat[0][2], -view_mat[1][2]));
mat2 look_at = mat2(look_at_dir.y, look_at_dir.x, -look_at_dir.x, look_at_dir.y);
f_uv = v_center + look_at * (v_uv - v_center);
gl_Position = vec4(v_pos, 0.0, 1.0);
gl_Position = vec4(v_pos, -1.0, 1.0);
} else if (v_mode == uint(5)) {
// HACK: North facing target rectangle.
f_uv = v_uv;
@ -41,11 +45,11 @@ void main() {
mat2 look_at = mat2(look_at_dir.y, -look_at_dir.x, look_at_dir.x, look_at_dir.y);
vec2 v_len = v_pos - v_center;
vec2 v_proj = look_at * vec2(v_len.x, v_len.y / aspect_ratio);
gl_Position = vec4(v_center + vec2(v_proj.x, v_proj.y * aspect_ratio), 0.0, 1.0);
gl_Position = vec4(v_center + vec2(v_proj.x, v_proj.y * aspect_ratio), -1.0, 1.0);
} else {
// Interface element
f_uv = v_uv;
gl_Position = vec4(v_pos, 0.0, 1.0);
gl_Position = vec4(v_pos, -1.0, 1.0);
}
f_mode = v_mode;
}

View File

@ -16,6 +16,6 @@ num_cpus = "1.10.1"
log = "0.4.8"
rayon = "^1.3.0"
specs = "0.15.1"
vek = { version = "0.10.0", features = ["serde"] }
vek = { version = "0.11.2", features = ["serde"] }
hashbrown = { version = "0.6.2", features = ["rayon", "serde", "nightly"] }
authc = { git = "https://gitlab.com/veloren/auth.git", rev = "65571ade0d954a0e0bd995fdb314854ff146ab97" }

View File

@ -11,7 +11,7 @@ no-assets = []
specs-idvs = { git = "https://gitlab.com/veloren/specs-idvs.git" }
specs = { version = "0.15.1", features = ["serde", "nightly", "storage-event-control"] }
vek = { version = "0.10.0", features = ["serde"] }
vek = { version = "0.11.2", features = ["serde"] }
dot_vox = "4.0.0"
fxhash = "0.2.1"
image = "0.22.3"

View File

@ -19,6 +19,79 @@ use specs::{Component, FlaggedStorage};
use specs_idvs::IDVStorage;
use std::{fs::File, io::BufReader};
/* pub trait PerBody {
type Humanoid;
type QuadrupedSmall;
type QuadrupedMedium;
type BirdMedium;
type FishMedium;
type Dragon;
type BirdSmall;
type FishSmall;
type BipedLarge;
type Object;
type Golem;
type Critter;
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[repr(u32)]
pub enum Body<Meta = BodyType, BodyMeta = ()>
where Meta: PerBody,
{
Humanoid(Meta::Humanoid) = 0,
QuadrupedSmall(Meta::QuadrupedSmall) = 1,
QuadrupedMedium(Meta::QuadrupedMedium) = 2,
BirdMedium(Meta::BirdMedium) = 3,
FishMedium(Meta::FishMedium) = 4,
Dragon(Meta::Dragon) = 5,
BirdSmall(Meta::BirdSmall) = 6,
FishSmall(Meta::FishSmall) = 7,
BipedLarge(Meta::BipedLarge) = 8,
Object(Meta::Object) = 9,
Golem(Meta::Golem) = 10,
Critter(Meta::Critter) = 11,
}
/// Metadata intended to be stored per-body, together with data intended to be
/// stored for each species for each body.
///
/// NOTE: Deliberately don't (yet?) implement serialize.
#[derive(Clone, Debug, Deserialize)]
pub struct AllBodies<BodyMeta, PerBodyMeta: Meta> {
pub humanoid: BodyData<BodyMeta, humanoid::AllSpecies<SpeciesMeta>>,
pub quadruped_small: BodyData<BodyMeta, quadruped_small::AllSpecies<SpeciesMeta>>,
pub quadruped_medium: BodyData<BodyMeta, quadruped_medium::AllSpecies<SpeciesMeta>>,
pub bird_medium: BodyData<BodyMeta, bird_medium::AllSpecies<SpeciesMeta>>,
pub fish_medium: BodyData<BodyMeta, ()>,
pub dragon: BodyData<BodyMeta, dragon::AllSpecies<SpeciesMeta>>,
pub bird_small: BodyData<BodyMeta, ()>,
pub fish_small: BodyData<BodyMeta, ()>
pub biped_large: BodyData<BodyMeta, biped_large::AllSpecies<SpeciesMeta>>,
pub object: BodyData<BodyMeta, ()>,
pub golem: BodyData<BodyMeta, golem::AllSpecies<SpeciesMeta>>,
pub critter: BodyData<BodyMeta, critter::AllSpecies<SpeciesMeta>>,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct BodyType;
impl PerBody for BodyType {
type Humanoid = humanoid::Body;
type QuadrupedSmall = quadruped_small::Body;
type QuadrupedMedium = quadruped_medium::Body;
type BirdMedium = bird_medium::Body;
type FishMedium = fish_medium::Body;
type Dragon = dragon::Body;
type BirdSmall = bird_small::Body;
type FishSmall = fish_small::Body;
type BipedLarge = biped_large::Body;
type Object = object::Body;
type Golem = golem::Body;
type Critter = critter::Body;
}
*/
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[repr(u32)]
pub enum Body {
@ -57,10 +130,14 @@ pub struct AllBodies<BodyMeta, SpeciesMeta> {
pub quadruped_small: BodyData<BodyMeta, quadruped_small::AllSpecies<SpeciesMeta>>,
pub quadruped_medium: BodyData<BodyMeta, quadruped_medium::AllSpecies<SpeciesMeta>>,
pub bird_medium: BodyData<BodyMeta, bird_medium::AllSpecies<SpeciesMeta>>,
pub fish_medium: BodyData<BodyMeta, ()>,
pub dragon: BodyData<BodyMeta, dragon::AllSpecies<SpeciesMeta>>,
pub bird_small: BodyData<BodyMeta, ()>,
pub fish_small: BodyData<BodyMeta, ()>,
pub biped_large: BodyData<BodyMeta, biped_large::AllSpecies<SpeciesMeta>>,
pub object: BodyData<BodyMeta, ()>,
pub golem: BodyData<BodyMeta, golem::AllSpecies<SpeciesMeta>>,
pub critter: BodyData<BodyMeta, critter::AllSpecies<SpeciesMeta>>,
pub dragon: BodyData<BodyMeta, dragon::AllSpecies<SpeciesMeta>>,
}
/// Can only retrieve body metadata by direct index.
@ -82,6 +159,29 @@ impl<BodyMeta, SpeciesMeta> core::ops::Index<NpcKind> for AllBodies<BodyMeta, Sp
}
}
/// Can only retrieve body metadata by direct index.
impl<'a, BodyMeta, SpeciesMeta> core::ops::Index<&'a Body> for AllBodies<BodyMeta, SpeciesMeta> {
type Output = BodyMeta;
#[inline]
fn index(&self, index: &Body) -> &Self::Output {
match index {
Body::Humanoid(_) => &self.humanoid.body,
Body::QuadrupedSmall(_) => &self.quadruped_small.body,
Body::QuadrupedMedium(_) => &self.quadruped_medium.body,
Body::BirdMedium(_) => &self.bird_medium.body,
Body::FishMedium(_) => &self.fish_medium.body,
Body::Dragon(_) => &self.dragon.body,
Body::BirdSmall(_) => &self.bird_small.body,
Body::FishSmall(_) => &self.fish_small.body,
Body::BipedLarge(_) => &self.biped_large.body,
Body::Object(_) => &self.object.body,
Body::Golem(_) => &self.golem.body,
Body::Critter(_) => &self.critter.body,
}
}
}
impl<
BodyMeta: Send + Sync + for<'de> serde::Deserialize<'de>,
SpeciesMeta: Send + Sync + for<'de> serde::Deserialize<'de>,

View File

@ -25,7 +25,7 @@ pub trait BaseVol {
type Vox: Vox;
type Error: Debug;
fn scaled_by(&self, scale: Vec3<f32>) -> Scaled<Self>
fn scaled_by(self, scale: Vec3<f32>) -> Scaled<Self>
where
Self: Sized,
{

View File

@ -1,28 +1,36 @@
use crate::vol::{BaseVol, ReadVol, SizedVol, Vox};
use vek::*;
pub struct Scaled<'a, V> {
pub inner: &'a V,
pub struct Scaled<V> {
pub inner: V,
pub scale: Vec3<f32>,
}
impl<'a, V: BaseVol> BaseVol for Scaled<'a, V> {
impl<V: BaseVol> BaseVol for Scaled<V> {
type Error = V::Error;
type Vox = V::Vox;
}
impl<'a, V: ReadVol> ReadVol for Scaled<'a, V> {
impl<V: ReadVol> ReadVol for Scaled<V> {
#[inline(always)]
fn get(&self, pos: Vec3<i32>) -> Result<&Self::Vox, Self::Error> {
let ideal_pos = pos.map2(self.scale, |e, scale| e as f32 / scale);
let pos = ideal_pos.map(|e| e.trunc() as i32);
// let ideal_pos = pos.map2(self.scale, |e, scale| (e as f32 + 0.5) / scale);
// let pos = ideal_pos.map(|e| e.trunc() as i32);
let min_pos = pos.map2(self.scale, |e, scale| ((e as f32) / scale).floor() as i32);
let max_pos = pos.map2(self.scale, |e, scale| {
((e as f32 + 1.0) / scale).ceil() as i32
});
let pos = pos.map2(self.scale, |e, scale| {
(((e as f32 + 0.5) / scale) - 0.5).round() as i32
});
let ideal_search_size = Vec3::<f32>::one() / self.scale;
// let ideal_search_size = Vec3::<f32>::one() / self.scale;
let range_iter = |i: usize| {
std::iter::successors(Some(0), |p| Some(if *p < 0 { -*p } else { -(*p + 1) }))
.take_while(move |p| {
((ideal_pos[i] - ideal_search_size[i] / 2.0).round() as i32
..(ideal_pos[i] + ideal_search_size[i] / 2.0).round() as i32)
(min_pos[i]..max_pos[i])
/* ((ideal_pos[i] - ideal_search_size[i] / 2.0).ceil() as i32
..(ideal_pos[i] + ideal_search_size[i] / 2.0).ceil() as i32) */
.contains(&(pos[i] + *p))
})
};
@ -36,7 +44,7 @@ impl<'a, V: ReadVol> ReadVol for Scaled<'a, V> {
}
}
impl<'a, V: SizedVol> SizedVol for Scaled<'a, V> {
impl<V: SizedVol> SizedVol for Scaled<V> {
#[inline(always)]
fn lower_bound(&self) -> Vec3<i32> {
self.inner
@ -48,6 +56,6 @@ impl<'a, V: SizedVol> SizedVol for Scaled<'a, V> {
fn upper_bound(&self) -> Vec3<i32> {
self.inner
.upper_bound()
.map2(self.scale, |e, scale| (e as f32 * scale).ceil() as i32 + 1)
.map2(self.scale, |e, scale| (e as f32 * scale).ceil() as i32)
}
}

View File

@ -16,7 +16,7 @@ specs-idvs = { git = "https://gitlab.com/veloren/specs-idvs.git" }
log = "0.4.8"
specs = { version = "0.15.1", features = ["shred-derive"] }
vek = "0.10.0"
vek = { version = "0.11.2", features = ["serde"] }
uvth = "3.1.1"
lazy_static = "1.4.0"
scan_fmt = "0.2.4"

View File

@ -9,7 +9,7 @@ default-run = "veloren-voxygen"
# autobins = false
[features]
gl = ["gfx_device_gl"]
gl = ["gfx_device_gl", "gfx_gl"]
singleplayer = ["server"]
tweak = ["const-tweaker"]
@ -22,6 +22,7 @@ client = { package = "veloren-client", path = "../client" }
# Graphics
gfx = "0.18.2"
gfx_device_gl = { version = "0.16.2", optional = true }
gfx_gl = { version = "0.6.1", optional = true }
gfx_window_glutin = "0.31.0"
glutin = "0.21.1"
winit = { version = "0.19.4", features = ["serde"] }
@ -34,7 +35,7 @@ specs = "0.15.1"
specs-idvs = { git = "https://gitlab.com/veloren/specs-idvs.git" }
# Mathematics
vek = { version = "0.10.0", features = ["serde"] }
vek = { version = "0.11.2", features = ["serde"] }
# Controller
gilrs = { version = "0.7", features = ["serde"] }
@ -51,7 +52,7 @@ image = "0.22.3"
serde = "1.0.102"
serde_derive = "1.0.102"
ron = "0.5.1"
guillotiere = { git = "https://github.com/Imberflur/guillotiere" }
guillotiere = "0.5.2"
fern = { version = "0.5.8", features = ["colored"] }
msgbox = { git = "https://github.com/bekker/msgbox-rs.git", rev = "68fe39a", optional = true }
directories = "2.0.2"

View File

@ -131,7 +131,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
c.bench(
"meshing",
Benchmark::new(&format!("Terrain mesh {}, {}", x, y), move |b| {
b.iter(|| volume.generate_mesh(black_box(range)))
b.iter(|| volume.generate_mesh(black_box((range, Vec2::new(8192, 8192)))))
})
// Lower sample size to save time
.sample_size(15),

View File

@ -14,17 +14,8 @@ fn main() {
let (_context, device, factory, color_view, depth_view) = init_headless(context, dim);
let mut renderer = render::Renderer::new(
device,
factory,
color_view,
depth_view,
render::AaMode::SsaaX4,
render::CloudMode::Regular,
render::FluidMode::Shiny,
render::LightingMode::Ashikmin,
)
.unwrap();
let mut renderer =
render::Renderer::new(device, factory, color_view, depth_view, Default::default()).unwrap();
// Create character
let body = comp::humanoid::Body::random();
@ -62,7 +53,7 @@ fn main() {
scene
.camera_mut()
.update(0.0, 1.0 / 60.0, scene_data.mouse_smoothing);
scene.maintain(&mut renderer, scene_data);
scene.maintain(&mut renderer, scene_data, None);
// Render
renderer.clear();

View File

@ -8,7 +8,7 @@ pub use self::{idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation};
use super::{Bone, Skeleton};
use crate::render::FigureBoneData;
use common::comp::{self};
use vek::Vec3;
use vek::{Mat4, Vec3};
#[derive(Clone, Default)]
pub struct BipedLargeSkeleton {
@ -35,7 +35,10 @@ impl Skeleton for BipedLargeSkeleton {
fn bone_count(&self) -> usize { 11 }
fn compute_matrices(&self) -> ([FigureBoneData; 16], Vec3<f32>) {
fn compute_matrices<F: FnMut(Mat4<f32>) -> FigureBoneData>(
&self,
mut make_bone: F,
) -> ([FigureBoneData; 16], Vec3<f32>) {
let upper_torso_mat = self.upper_torso.compute_base_matrix();
let shoulder_l_mat = self.shoulder_l.compute_base_matrix();
let shoulder_r_mat = self.shoulder_r.compute_base_matrix();
@ -44,23 +47,17 @@ impl Skeleton for BipedLargeSkeleton {
let torso_mat = self.torso.compute_base_matrix();
(
[
FigureBoneData::new(torso_mat * upper_torso_mat * self.head.compute_base_matrix()),
FigureBoneData::new(torso_mat * upper_torso_mat),
FigureBoneData::new(
torso_mat * upper_torso_mat * self.lower_torso.compute_base_matrix(),
),
FigureBoneData::new(torso_mat * upper_torso_mat * shoulder_l_mat),
FigureBoneData::new(torso_mat * upper_torso_mat * shoulder_r_mat),
FigureBoneData::new(
torso_mat * upper_torso_mat * self.hand_l.compute_base_matrix(),
),
FigureBoneData::new(
torso_mat * upper_torso_mat * self.hand_r.compute_base_matrix(),
),
FigureBoneData::new(torso_mat * upper_torso_mat * leg_l_mat),
FigureBoneData::new(torso_mat * upper_torso_mat * leg_r_mat),
FigureBoneData::new(self.foot_l.compute_base_matrix()),
FigureBoneData::new(self.foot_r.compute_base_matrix()),
make_bone(torso_mat * upper_torso_mat * self.head.compute_base_matrix()),
make_bone(torso_mat * upper_torso_mat),
make_bone(torso_mat * upper_torso_mat * self.lower_torso.compute_base_matrix()),
make_bone(torso_mat * upper_torso_mat * shoulder_l_mat),
make_bone(torso_mat * upper_torso_mat * shoulder_r_mat),
make_bone(torso_mat * upper_torso_mat * self.hand_l.compute_base_matrix()),
make_bone(torso_mat * upper_torso_mat * self.hand_r.compute_base_matrix()),
make_bone(torso_mat * upper_torso_mat * leg_l_mat),
make_bone(torso_mat * upper_torso_mat * leg_r_mat),
make_bone(self.foot_l.compute_base_matrix()),
make_bone(self.foot_r.compute_base_matrix()),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),

View File

@ -8,7 +8,7 @@ pub use self::{fly::FlyAnimation, idle::IdleAnimation, run::RunAnimation};
use super::{Bone, Skeleton};
use crate::render::FigureBoneData;
use common::comp::{self};
use vek::Vec3;
use vek::{Mat4, Vec3};
#[derive(Clone, Default)]
pub struct BirdMediumSkeleton {
@ -30,18 +30,21 @@ impl Skeleton for BirdMediumSkeleton {
fn bone_count(&self) -> usize { 7 }
fn compute_matrices(&self) -> ([FigureBoneData; 16], Vec3<f32>) {
fn compute_matrices<F: FnMut(Mat4<f32>) -> FigureBoneData>(
&self,
mut make_bone: F,
) -> ([FigureBoneData; 16], Vec3<f32>) {
let torso_mat = self.torso.compute_base_matrix();
(
[
FigureBoneData::new(torso_mat * self.head.compute_base_matrix()),
FigureBoneData::new(torso_mat),
FigureBoneData::new(torso_mat * self.tail.compute_base_matrix()),
FigureBoneData::new(torso_mat * self.wing_l.compute_base_matrix()),
FigureBoneData::new(torso_mat * self.wing_r.compute_base_matrix()),
FigureBoneData::new(self.leg_l.compute_base_matrix()),
FigureBoneData::new(self.leg_r.compute_base_matrix()),
make_bone(torso_mat * self.head.compute_base_matrix()),
make_bone(torso_mat),
make_bone(torso_mat * self.tail.compute_base_matrix()),
make_bone(torso_mat * self.wing_l.compute_base_matrix()),
make_bone(torso_mat * self.wing_r.compute_base_matrix()),
make_bone(self.leg_l.compute_base_matrix()),
make_bone(self.leg_r.compute_base_matrix()),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),

View File

@ -8,7 +8,7 @@ pub use self::{idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation};
use super::{Bone, Skeleton};
use crate::render::FigureBoneData;
use common::comp::{self};
use vek::Vec3;
use vek::{Mat4, Vec3};
#[derive(Clone)]
pub struct BirdSmallSkeleton {
@ -34,15 +34,18 @@ impl Skeleton for BirdSmallSkeleton {
fn bone_count(&self) -> usize { 4 }
fn compute_matrices(&self) -> ([FigureBoneData; 16], Vec3<f32>) {
fn compute_matrices<F: FnMut(Mat4<f32>) -> FigureBoneData>(
&self,
mut make_bone: F,
) -> ([FigureBoneData; 16], Vec3<f32>) {
let torso_mat = self.torso.compute_base_matrix();
(
[
FigureBoneData::new(self.head.compute_base_matrix() * torso_mat),
FigureBoneData::new(torso_mat),
FigureBoneData::new(self.wing_l.compute_base_matrix() * torso_mat),
FigureBoneData::new(self.wing_r.compute_base_matrix() * torso_mat),
make_bone(self.head.compute_base_matrix() * torso_mat),
make_bone(torso_mat),
make_bone(self.wing_l.compute_base_matrix() * torso_mat),
make_bone(self.wing_r.compute_base_matrix() * torso_mat),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),

View File

@ -31,7 +31,7 @@ pub use self::{
use super::{Bone, Skeleton};
use crate::render::FigureBoneData;
use common::comp;
use vek::{Vec3, Vec4};
use vek::{Mat4, Vec3, Vec4};
#[derive(Clone, Default)]
pub struct CharacterSkeleton {
@ -65,7 +65,10 @@ impl Skeleton for CharacterSkeleton {
fn bone_count(&self) -> usize { 15 }
fn compute_matrices(&self) -> ([FigureBoneData; 16], Vec3<f32>) {
fn compute_matrices<F: FnMut(Mat4<f32>) -> FigureBoneData>(
&self,
mut make_bone: F,
) -> ([FigureBoneData; 16], Vec3<f32>) {
let chest_mat = self.chest.compute_base_matrix();
let torso_mat = self.torso.compute_base_matrix();
let l_hand_mat = self.l_hand.compute_base_matrix();
@ -83,27 +86,21 @@ impl Skeleton for CharacterSkeleton {
(
[
FigureBoneData::new(torso_mat * chest_mat * head_mat),
FigureBoneData::new(torso_mat * chest_mat),
FigureBoneData::new(torso_mat * chest_mat * self.belt.compute_base_matrix()),
FigureBoneData::new(torso_mat * chest_mat * self.back.compute_base_matrix()),
FigureBoneData::new(torso_mat * chest_mat * shorts_mat),
FigureBoneData::new(
torso_mat * chest_mat * control_mat * l_control_mat * l_hand_mat,
),
FigureBoneData::new(
torso_mat * chest_mat * control_mat * r_control_mat * r_hand_mat,
),
FigureBoneData::new(torso_mat * self.l_foot.compute_base_matrix()),
FigureBoneData::new(torso_mat * self.r_foot.compute_base_matrix()),
FigureBoneData::new(torso_mat * chest_mat * self.l_shoulder.compute_base_matrix()),
FigureBoneData::new(torso_mat * chest_mat * self.r_shoulder.compute_base_matrix()),
FigureBoneData::new(torso_mat * self.glider.compute_base_matrix()),
FigureBoneData::new(torso_mat * chest_mat * control_mat * l_control_mat * main_mat),
FigureBoneData::new(
torso_mat * chest_mat * control_mat * r_control_mat * second_mat,
),
FigureBoneData::new(lantern_final_mat),
make_bone(torso_mat * chest_mat * head_mat),
make_bone(torso_mat * chest_mat),
make_bone(torso_mat * chest_mat * self.belt.compute_base_matrix()),
make_bone(torso_mat * chest_mat * self.back.compute_base_matrix()),
make_bone(torso_mat * chest_mat * shorts_mat),
make_bone(torso_mat * chest_mat * control_mat * l_control_mat * l_hand_mat),
make_bone(torso_mat * chest_mat * control_mat * r_control_mat * r_hand_mat),
make_bone(torso_mat * self.l_foot.compute_base_matrix()),
make_bone(torso_mat * self.r_foot.compute_base_matrix()),
make_bone(torso_mat * chest_mat * self.l_shoulder.compute_base_matrix()),
make_bone(torso_mat * chest_mat * self.r_shoulder.compute_base_matrix()),
make_bone(torso_mat * self.glider.compute_base_matrix()),
make_bone(torso_mat * chest_mat * control_mat * l_control_mat * main_mat),
make_bone(torso_mat * chest_mat * control_mat * r_control_mat * second_mat),
make_bone(lantern_final_mat),
FigureBoneData::default(),
],
(lantern_final_mat * Vec4::new(0.0, 0.0, 0.0, 1.0)).xyz(),

View File

@ -8,7 +8,7 @@ pub use self::{idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation};
use super::{Bone, Skeleton};
use crate::render::FigureBoneData;
use common::comp::{self};
use vek::Vec3;
use vek::{Mat4, Vec3};
#[derive(Clone, Default)]
pub struct CritterSkeleton {
@ -35,14 +35,17 @@ impl Skeleton for CritterSkeleton {
fn bone_count(&self) -> usize { 5 }
fn compute_matrices(&self) -> ([FigureBoneData; 16], Vec3<f32>) {
fn compute_matrices<F: FnMut(Mat4<f32>) -> FigureBoneData>(
&self,
mut make_bone: F,
) -> ([FigureBoneData; 16], Vec3<f32>) {
(
[
FigureBoneData::new(self.head.compute_base_matrix()),
FigureBoneData::new(self.chest.compute_base_matrix()),
FigureBoneData::new(self.feet_f.compute_base_matrix()),
FigureBoneData::new(self.feet_b.compute_base_matrix()),
FigureBoneData::new(self.tail.compute_base_matrix()),
make_bone(self.head.compute_base_matrix()),
make_bone(self.chest.compute_base_matrix()),
make_bone(self.feet_f.compute_base_matrix()),
make_bone(self.feet_b.compute_base_matrix()),
make_bone(self.tail.compute_base_matrix()),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),

View File

@ -8,7 +8,7 @@ pub use self::{fly::FlyAnimation, idle::IdleAnimation, run::RunAnimation};
use super::{Bone, Skeleton};
use crate::render::FigureBoneData;
use common::comp::{self};
use vek::Vec3;
use vek::{Mat4, Vec3};
#[derive(Clone, Default)]
pub struct DragonSkeleton {
@ -38,7 +38,10 @@ impl Skeleton for DragonSkeleton {
fn bone_count(&self) -> usize { 15 }
fn compute_matrices(&self) -> ([FigureBoneData; 16], Vec3<f32>) {
fn compute_matrices<F: FnMut(Mat4<f32>) -> FigureBoneData>(
&self,
mut make_bone: F,
) -> ([FigureBoneData; 16], Vec3<f32>) {
let head_upper_mat = self.head_upper.compute_base_matrix();
let head_lower_mat = self.head_lower.compute_base_matrix();
let chest_front_mat = self.chest_front.compute_base_matrix();
@ -48,35 +51,31 @@ impl Skeleton for DragonSkeleton {
let tail_front_mat = self.tail_front.compute_base_matrix();
(
[
FigureBoneData::new(chest_front_mat * head_lower_mat * head_upper_mat),
FigureBoneData::new(chest_front_mat * head_lower_mat),
FigureBoneData::new(
make_bone(chest_front_mat * head_lower_mat * head_upper_mat),
make_bone(chest_front_mat * head_lower_mat),
make_bone(
chest_front_mat
* head_lower_mat
* head_upper_mat
* self.jaw.compute_base_matrix(),
),
FigureBoneData::new(chest_front_mat),
FigureBoneData::new(chest_front_mat * self.chest_rear.compute_base_matrix()),
FigureBoneData::new(chest_front_mat * chest_rear_mat * tail_front_mat),
FigureBoneData::new(
make_bone(chest_front_mat),
make_bone(chest_front_mat * self.chest_rear.compute_base_matrix()),
make_bone(chest_front_mat * chest_rear_mat * tail_front_mat),
make_bone(
chest_front_mat
* chest_rear_mat
* tail_front_mat
* self.tail_rear.compute_base_matrix(),
),
FigureBoneData::new(chest_front_mat * self.wing_in_l.compute_base_matrix()),
FigureBoneData::new(chest_front_mat * self.wing_in_r.compute_base_matrix()),
FigureBoneData::new(
chest_front_mat * wing_in_l_mat * self.wing_out_l.compute_base_matrix(),
),
FigureBoneData::new(
chest_front_mat * wing_in_r_mat * self.wing_out_r.compute_base_matrix(),
),
FigureBoneData::new(self.foot_fl.compute_base_matrix()),
FigureBoneData::new(self.foot_fr.compute_base_matrix()),
FigureBoneData::new(self.foot_bl.compute_base_matrix()),
FigureBoneData::new(self.foot_br.compute_base_matrix()),
make_bone(chest_front_mat * self.wing_in_l.compute_base_matrix()),
make_bone(chest_front_mat * self.wing_in_r.compute_base_matrix()),
make_bone(chest_front_mat * wing_in_l_mat * self.wing_out_l.compute_base_matrix()),
make_bone(chest_front_mat * wing_in_r_mat * self.wing_out_r.compute_base_matrix()),
make_bone(self.foot_fl.compute_base_matrix()),
make_bone(self.foot_fr.compute_base_matrix()),
make_bone(self.foot_bl.compute_base_matrix()),
make_bone(self.foot_br.compute_base_matrix()),
FigureBoneData::default(),
],
Vec3::default(),

View File

@ -8,7 +8,7 @@ pub use self::{idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation};
use super::{Bone, Skeleton};
use crate::render::FigureBoneData;
use common::comp::{self};
use vek::Vec3;
use vek::{Mat4, Vec3};
#[derive(Clone)]
pub struct FishMediumSkeleton {
@ -38,18 +38,21 @@ impl Skeleton for FishMediumSkeleton {
fn bone_count(&self) -> usize { 6 }
fn compute_matrices(&self) -> ([FigureBoneData; 16], Vec3<f32>) {
fn compute_matrices<F: FnMut(Mat4<f32>) -> FigureBoneData>(
&self,
mut make_bone: F,
) -> ([FigureBoneData; 16], Vec3<f32>) {
let torso_mat = self.torso.compute_base_matrix();
let rear_mat = self.rear.compute_base_matrix();
(
[
FigureBoneData::new(self.head.compute_base_matrix() * torso_mat),
FigureBoneData::new(torso_mat),
FigureBoneData::new(rear_mat * torso_mat),
FigureBoneData::new(self.tail.compute_base_matrix() * rear_mat),
FigureBoneData::new(self.fin_l.compute_base_matrix() * rear_mat),
FigureBoneData::new(self.fin_r.compute_base_matrix() * rear_mat),
make_bone(self.head.compute_base_matrix() * torso_mat),
make_bone(torso_mat),
make_bone(rear_mat * torso_mat),
make_bone(self.tail.compute_base_matrix() * rear_mat),
make_bone(self.fin_l.compute_base_matrix() * rear_mat),
make_bone(self.fin_r.compute_base_matrix() * rear_mat),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),

View File

@ -8,7 +8,7 @@ pub use self::{idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation};
use super::{Bone, Skeleton};
use crate::render::FigureBoneData;
use common::comp::{self};
use vek::Vec3;
use vek::{Mat4, Vec3};
#[derive(Clone)]
pub struct FishSmallSkeleton {
@ -30,13 +30,16 @@ impl Skeleton for FishSmallSkeleton {
fn bone_count(&self) -> usize { 2 }
fn compute_matrices(&self) -> ([FigureBoneData; 16], Vec3<f32>) {
fn compute_matrices<F: FnMut(Mat4<f32>) -> FigureBoneData>(
&self,
mut make_bone: F,
) -> ([FigureBoneData; 16], Vec3<f32>) {
let torso_mat = self.torso.compute_base_matrix();
(
[
FigureBoneData::new(torso_mat),
FigureBoneData::new(self.tail.compute_base_matrix() * torso_mat),
make_bone(torso_mat),
make_bone(self.tail.compute_base_matrix() * torso_mat),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),

View File

@ -1,6 +1,6 @@
use super::Skeleton;
use crate::render::FigureBoneData;
use vek::Vec3;
use vek::{Mat4, Vec3};
#[derive(Clone)]
pub struct FixtureSkeleton;
@ -16,25 +16,28 @@ impl Skeleton for FixtureSkeleton {
fn bone_count(&self) -> usize { 1 }
fn compute_matrices(&self) -> ([FigureBoneData; 16], Vec3<f32>) {
fn compute_matrices<F: FnMut(Mat4<f32>) -> FigureBoneData>(
&self,
_make_bone: F,
) -> ([FigureBoneData; 16], Vec3<f32>) {
(
[
FigureBoneData::new(vek::Mat4::identity()), // <-- This is actually a bone!
FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::default(), // <-- This is actually a bone!
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
],
Vec3::default(),
)

View File

@ -8,7 +8,7 @@ pub use self::{idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation};
use super::{Bone, Skeleton};
use crate::render::FigureBoneData;
use common::comp::{self};
use vek::Vec3;
use vek::{Mat4, Vec3};
#[derive(Clone)]
pub struct GolemSkeleton {
@ -46,7 +46,10 @@ impl GolemSkeleton {
impl Skeleton for GolemSkeleton {
type Attr = SkeletonAttr;
fn compute_matrices(&self) -> ([FigureBoneData; 16], Vec3<f32>) {
fn compute_matrices<F: FnMut(Mat4<f32>) -> FigureBoneData>(
&self,
mut make_bone: F,
) -> ([FigureBoneData; 16], Vec3<f32>) {
let upper_torso_mat = self.upper_torso.compute_base_matrix();
let shoulder_l_mat = self.shoulder_l.compute_base_matrix();
let shoulder_r_mat = self.shoulder_r.compute_base_matrix();
@ -57,20 +60,16 @@ impl Skeleton for GolemSkeleton {
let foot_r_mat = self.foot_r.compute_base_matrix();
(
[
FigureBoneData::new(torso_mat * upper_torso_mat * self.head.compute_base_matrix()),
FigureBoneData::new(torso_mat * upper_torso_mat),
FigureBoneData::new(torso_mat * upper_torso_mat * shoulder_l_mat),
FigureBoneData::new(torso_mat * upper_torso_mat * shoulder_r_mat),
FigureBoneData::new(
torso_mat * upper_torso_mat * self.hand_l.compute_base_matrix(),
),
FigureBoneData::new(
torso_mat * upper_torso_mat * self.hand_r.compute_base_matrix(),
),
FigureBoneData::new(foot_l_mat * leg_l_mat),
FigureBoneData::new(foot_r_mat * leg_r_mat),
FigureBoneData::new(foot_l_mat),
FigureBoneData::new(foot_r_mat),
make_bone(torso_mat * upper_torso_mat * self.head.compute_base_matrix()),
make_bone(torso_mat * upper_torso_mat),
make_bone(torso_mat * upper_torso_mat * shoulder_l_mat),
make_bone(torso_mat * upper_torso_mat * shoulder_r_mat),
make_bone(torso_mat * upper_torso_mat * self.hand_l.compute_base_matrix()),
make_bone(torso_mat * upper_torso_mat * self.hand_r.compute_base_matrix()),
make_bone(foot_l_mat * leg_l_mat),
make_bone(foot_r_mat * leg_r_mat),
make_bone(foot_l_mat),
make_bone(foot_r_mat),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),

View File

@ -54,7 +54,10 @@ pub trait Skeleton: Send + Sync + 'static {
fn bone_count(&self) -> usize { 16 }
fn compute_matrices(&self) -> ([FigureBoneData; 16], Vec3<f32>);
fn compute_matrices<F: FnMut(Mat4<f32>) -> FigureBoneData>(
&self,
make_bone: F,
) -> ([FigureBoneData; 16], Vec3<f32>);
/// Change the current skeleton to be more like `target`.
fn interpolate(&mut self, target: &Self, dt: f32);

View File

@ -17,25 +17,28 @@ impl Skeleton for ObjectSkeleton {
fn bone_count(&self) -> usize { 1 }
fn compute_matrices(&self) -> ([FigureBoneData; 16], Vec3<f32>) {
fn compute_matrices<F: FnMut(Mat4<f32>) -> FigureBoneData>(
&self,
mut make_bone: F,
) -> ([FigureBoneData; 16], Vec3<f32>) {
(
[
FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))),
FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()),
make_bone(Mat4::scaling_3d(Vec3::broadcast(SCALE))),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
],
Vec3::default(),
)

View File

@ -8,7 +8,7 @@ pub use self::{idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation};
use super::{Bone, Skeleton};
use crate::render::FigureBoneData;
use common::comp::{self};
use vek::Vec3;
use vek::{Mat4, Vec3};
#[derive(Clone, Default)]
pub struct QuadrupedMediumSkeleton {
@ -34,24 +34,27 @@ impl Skeleton for QuadrupedMediumSkeleton {
fn bone_count(&self) -> usize { 11 }
fn compute_matrices(&self) -> ([FigureBoneData; 16], Vec3<f32>) {
fn compute_matrices<F: FnMut(Mat4<f32>) -> FigureBoneData>(
&self,
mut make_bone: F,
) -> ([FigureBoneData; 16], Vec3<f32>) {
let ears_mat = self.ears.compute_base_matrix();
let head_upper_mat = self.head_upper.compute_base_matrix();
let head_lower_mat = self.head_lower.compute_base_matrix();
let torso_mid_mat = self.torso_mid.compute_base_matrix();
(
[
FigureBoneData::new(head_upper_mat),
FigureBoneData::new(head_upper_mat * head_lower_mat),
FigureBoneData::new(head_upper_mat * self.jaw.compute_base_matrix()),
FigureBoneData::new(torso_mid_mat * self.tail.compute_base_matrix()),
FigureBoneData::new(self.torso_back.compute_base_matrix()),
FigureBoneData::new(torso_mid_mat),
FigureBoneData::new(head_upper_mat * ears_mat),
FigureBoneData::new(self.foot_lf.compute_base_matrix()),
FigureBoneData::new(self.foot_rf.compute_base_matrix()),
FigureBoneData::new(self.foot_lb.compute_base_matrix()),
FigureBoneData::new(self.foot_rb.compute_base_matrix()),
make_bone(head_upper_mat),
make_bone(head_upper_mat * head_lower_mat),
make_bone(head_upper_mat * self.jaw.compute_base_matrix()),
make_bone(torso_mid_mat * self.tail.compute_base_matrix()),
make_bone(self.torso_back.compute_base_matrix()),
make_bone(torso_mid_mat),
make_bone(head_upper_mat * ears_mat),
make_bone(self.foot_lf.compute_base_matrix()),
make_bone(self.foot_rf.compute_base_matrix()),
make_bone(self.foot_lb.compute_base_matrix()),
make_bone(self.foot_rb.compute_base_matrix()),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),

View File

@ -8,7 +8,7 @@ pub use self::{idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation};
use super::{Bone, Skeleton};
use crate::render::FigureBoneData;
use common::comp::{self};
use vek::Vec3;
use vek::{Mat4, Vec3};
#[derive(Clone, Default)]
pub struct QuadrupedSmallSkeleton {
@ -29,15 +29,18 @@ impl Skeleton for QuadrupedSmallSkeleton {
fn bone_count(&self) -> usize { 6 }
fn compute_matrices(&self) -> ([FigureBoneData; 16], Vec3<f32>) {
fn compute_matrices<F: FnMut(Mat4<f32>) -> FigureBoneData>(
&self,
mut make_bone: F,
) -> ([FigureBoneData; 16], Vec3<f32>) {
(
[
FigureBoneData::new(self.head.compute_base_matrix()),
FigureBoneData::new(self.chest.compute_base_matrix()),
FigureBoneData::new(self.leg_lf.compute_base_matrix()),
FigureBoneData::new(self.leg_rf.compute_base_matrix()),
FigureBoneData::new(self.leg_lb.compute_base_matrix()),
FigureBoneData::new(self.leg_rb.compute_base_matrix()),
make_bone(self.head.compute_base_matrix()),
make_bone(self.chest.compute_base_matrix()),
make_bone(self.leg_lf.compute_base_matrix()),
make_bone(self.leg_rf.compute_base_matrix()),
make_bone(self.leg_lb.compute_base_matrix()),
make_bone(self.leg_rb.compute_base_matrix()),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),

View File

@ -37,7 +37,7 @@ use spell::Spell;
use crate::{
ecs::comp as vcomp,
i18n::{i18n_asset_key, LanguageMetadata, VoxygenLocalization},
render::{AaMode, CloudMode, Consts, FluidMode, Globals, LightingMode, Renderer},
render::{Consts, Globals, RenderMode, Renderer},
scene::camera::{self, Camera},
ui::{fonts::ConrodVoxygenFonts, slot, Graphic, Ingameable, ScaleMode, Ui},
window::{Event as WinEvent, GameInput},
@ -231,9 +231,6 @@ pub enum Event {
ChangeGamma(f32),
AdjustWindowSize([u16; 2]),
ToggleFullscreen,
ChangeAaMode(AaMode),
ChangeCloudMode(CloudMode),
ChangeFluidMode(FluidMode),
CrosshairTransp(f32),
ChatTransp(f32),
CrosshairType(CrosshairType),
@ -256,7 +253,7 @@ pub enum Event {
ChangeLanguage(LanguageMetadata),
ChangeBinding(GameInput),
ChangeFreeLookBehavior(PressBehavior),
ChangeLightingMode(LightingMode),
ChangeRenderMode(RenderMode),
}
// TODO: Are these the possible layouts we want?
@ -1897,20 +1894,11 @@ impl Hud {
settings_window::Event::AdjustGamma(new_gamma) => {
events.push(Event::ChangeGamma(new_gamma));
},
settings_window::Event::ChangeAaMode(new_aa_mode) => {
events.push(Event::ChangeAaMode(new_aa_mode));
},
settings_window::Event::ChangeCloudMode(new_cloud_mode) => {
events.push(Event::ChangeCloudMode(new_cloud_mode));
},
settings_window::Event::ChangeFluidMode(new_fluid_mode) => {
events.push(Event::ChangeFluidMode(new_fluid_mode));
},
settings_window::Event::ChangeLanguage(language) => {
events.push(Event::ChangeLanguage(language));
},
settings_window::Event::ChangeLightingMode(new_lighting_mode) => {
events.push(Event::ChangeLightingMode(new_lighting_mode));
settings_window::Event::ChangeRenderMode(new_render_mode) => {
events.push(Event::ChangeRenderMode(new_render_mode));
},
settings_window::Event::ToggleFullscreen => {
events.push(Event::ToggleFullscreen);

View File

@ -4,7 +4,7 @@ use super::{
};
use crate::{
i18n::{list_localizations, LanguageMetadata, VoxygenLocalization},
render::{AaMode, CloudMode, FluidMode, LightingMode},
render::{AaMode, CloudMode, FluidMode, LightingMode, RenderMode, ShadowMode},
ui::{fonts::ConrodVoxygenFonts, ImageSlider, ScaleMode, ToggleButton},
window::GameInput,
GlobalState,
@ -117,6 +117,8 @@ widget_ids! {
fullscreen_label,
lighting_mode_text,
lighting_mode_list,
shadow_mode_text,
shadow_mode_list,
save_window_size_button,
audio_volume_slider,
audio_volume_text,
@ -227,10 +229,7 @@ pub enum Event {
AdjustGamma(f32),
AdjustWindowSize([u16; 2]),
ToggleFullscreen,
ChangeAaMode(AaMode),
ChangeCloudMode(CloudMode),
ChangeFluidMode(FluidMode),
ChangeLightingMode(LightingMode),
ChangeRenderMode(RenderMode),
AdjustMusicVolume(f32),
AdjustSfxVolume(f32),
ChangeAudioDevice(String),
@ -1774,7 +1773,7 @@ impl<'a> Widget for SettingsWindow<'a> {
// Get which AA mode is currently active
let selected = mode_list
.iter()
.position(|x| *x == self.global_state.settings.graphics.aa_mode);
.position(|x| *x == self.global_state.settings.graphics.render_mode.aa);
if let Some(clicked) = DropDownList::new(&mode_label_list, selected)
.w_h(400.0, 22.0)
@ -1784,7 +1783,10 @@ impl<'a> Widget for SettingsWindow<'a> {
.down_from(state.ids.aa_mode_text, 8.0)
.set(state.ids.aa_mode_list, ui)
{
events.push(Event::ChangeAaMode(mode_list[clicked]));
events.push(Event::ChangeRenderMode(RenderMode {
aa: mode_list[clicked],
..self.global_state.settings.graphics.render_mode
}));
}
// CloudMode
@ -1810,7 +1812,7 @@ impl<'a> Widget for SettingsWindow<'a> {
// Get which cloud rendering mode is currently active
let selected = mode_list
.iter()
.position(|x| *x == self.global_state.settings.graphics.cloud_mode);
.position(|x| *x == self.global_state.settings.graphics.render_mode.cloud);
if let Some(clicked) = DropDownList::new(&mode_label_list, selected)
.w_h(400.0, 22.0)
@ -1820,7 +1822,10 @@ impl<'a> Widget for SettingsWindow<'a> {
.down_from(state.ids.cloud_mode_text, 8.0)
.set(state.ids.cloud_mode_list, ui)
{
events.push(Event::ChangeCloudMode(mode_list[clicked]));
events.push(Event::ChangeRenderMode(RenderMode {
cloud: mode_list[clicked],
..self.global_state.settings.graphics.render_mode
}));
}
// FluidMode
@ -1848,7 +1853,7 @@ impl<'a> Widget for SettingsWindow<'a> {
// Get which fluid rendering mode is currently active
let selected = mode_list
.iter()
.position(|x| *x == self.global_state.settings.graphics.fluid_mode);
.position(|x| *x == self.global_state.settings.graphics.render_mode.fluid);
if let Some(clicked) = DropDownList::new(&mode_label_list, selected)
.w_h(400.0, 22.0)
@ -1858,7 +1863,10 @@ impl<'a> Widget for SettingsWindow<'a> {
.down_from(state.ids.fluid_mode_text, 8.0)
.set(state.ids.fluid_mode_list, ui)
{
events.push(Event::ChangeFluidMode(mode_list[clicked]));
events.push(Event::ChangeRenderMode(RenderMode {
fluid: mode_list[clicked],
..self.global_state.settings.graphics.render_mode
}));
}
// LightingMode
@ -1893,7 +1901,7 @@ impl<'a> Widget for SettingsWindow<'a> {
// Get which lighting rendering mode is currently active
let selected = mode_list
.iter()
.position(|x| *x == self.global_state.settings.graphics.lighting_mode);
.position(|x| *x == self.global_state.settings.graphics.render_mode.lighting);
if let Some(clicked) = DropDownList::new(&mode_label_list, selected)
.w_h(400.0, 22.0)
@ -1903,14 +1911,61 @@ impl<'a> Widget for SettingsWindow<'a> {
.down_from(state.ids.lighting_mode_text, 8.0)
.set(state.ids.lighting_mode_list, ui)
{
events.push(Event::ChangeLightingMode(mode_list[clicked]));
events.push(Event::ChangeRenderMode(RenderMode {
lighting: mode_list[clicked],
..self.global_state.settings.graphics.render_mode
}));
}
// ShadowMode
Text::new(
&self
.localized_strings
.get("hud.settings.shadow_rendering_mode"),
)
.down_from(state.ids.lighting_mode_list, 8.0)
.font_size(self.fonts.cyri.scale(14))
.font_id(self.fonts.cyri.conrod_id)
.color(TEXT_COLOR)
.set(state.ids.shadow_mode_text, ui);
let mode_list = [ShadowMode::None, ShadowMode::Cheap, ShadowMode::Map];
let mode_label_list = [
&self
.localized_strings
.get("hud.settings.shadow_rendering_mode.none"),
&self
.localized_strings
.get("hud.settings.shadow_rendering_mode.cheap"),
&self
.localized_strings
.get("hud.settings.shadow_rendering_mode.map"),
];
// Get which shadow rendering mode is currently active
let selected = mode_list
.iter()
.position(|x| *x == self.global_state.settings.graphics.render_mode.shadow);
if let Some(clicked) = DropDownList::new(&mode_label_list, selected)
.w_h(400.0, 22.0)
.color(MENU_BG)
.label_color(TEXT_COLOR)
.label_font_id(self.fonts.cyri.conrod_id)
.down_from(state.ids.shadow_mode_text, 8.0)
.set(state.ids.shadow_mode_list, ui)
{
events.push(Event::ChangeRenderMode(RenderMode {
shadow: mode_list[clicked],
..self.global_state.settings.graphics.render_mode
}));
}
// Fullscreen
Text::new(&self.localized_strings.get("hud.settings.fullscreen"))
.font_size(self.fonts.cyri.scale(14))
.font_id(self.fonts.cyri.conrod_id)
.down_from(state.ids.lighting_mode_list, 8.0)
.down_from(state.ids.shadow_mode_list, 8.0)
.color(TEXT_COLOR)
.set(state.ids.fullscreen_label, ui);

View File

@ -61,7 +61,9 @@ impl PlayState for CharSelectionState {
}
}
global_state.window.renderer_mut().clear();
let renderer = global_state.window.renderer_mut();
renderer.clear();
renderer.clear_shadows();
// Maintain the UI.
let events = self
@ -123,6 +125,7 @@ impl PlayState for CharSelectionState {
});
// Maintain the scene.
let loadout = self.char_selection_ui.get_loadout();
{
let client = self.client.borrow();
let scene_data = scene::SceneData {
@ -138,12 +141,14 @@ impl PlayState for CharSelectionState {
.figure_lod_render_distance
as f32,
};
self.scene
.maintain(global_state.window.renderer_mut(), scene_data);
self.scene.maintain(
global_state.window.renderer_mut(),
scene_data,
loadout.as_ref(),
);
}
// Render the scene.
let loadout = self.char_selection_ui.get_loadout();
self.scene.render(
global_state.window.renderer_mut(),
self.client.borrow().get_tick(),

778
voxygen/src/mesh/greedy.rs Normal file
View File

@ -0,0 +1,778 @@
use crate::render::{self, mesh::Quad, ColLightFmt, ColLightInfo, TerrainPipeline};
use vek::*;
type TerrainVertex = <TerrainPipeline as render::Pipeline>::Vertex;
/// A suspended greedy mesh, with enough information to recover color data.
///
/// The reason this exists is that greedy meshing is split into two parts.
/// First, the meshing itself needs to be performed; secondly, we generate a
/// texture atlas. We do things in this order to avoid having to copy all the
/// old vertices to the correct location. However, when trying to use the same
/// texture atlas for more than one model, this approach runs into the
/// problem that enough model information needs to be remembered to be able to
/// generate the colors after the function returns, so we box up the actual
/// coloring part as a continuation. When called with a final tile size and
/// vector, the continuation will consume the color data and write it to the
/// vector.
pub type SuspendedMesh<'a> = dyn for<'r> FnOnce(&'r mut ColLightInfo) + 'a;
/// Shared state for a greedy mesh, potentially passed along to multiple models.
///
/// For an explanation of why we want this, see `SuspendedMesh`.
pub struct GreedyMesh<'a> {
atlas: guillotiere::SimpleAtlasAllocator,
col_lights_size: Vec2<u16>,
max_size: guillotiere::Size,
suspended: Vec<Box<SuspendedMesh<'a>>>,
}
impl<'a> GreedyMesh<'a> {
pub fn new(max_size: guillotiere::Size) -> Self {
let min_max_dim = max_size.width.min(max_size.height);
assert!(
min_max_dim >= 4,
"min_max_dim={:?} >= 4 ({:?}",
min_max_dim,
max_size
);
// TODO: Collect information to see if we can choose a good value here.
let large_size_threshold = 256.min(min_max_dim / 2 + 1);
let small_size_threshold = 33.min(large_size_threshold / 2 + 1);
let size = guillotiere::Size::new(32, 32).min(max_size);
let atlas =
guillotiere::SimpleAtlasAllocator::with_options(size, &guillotiere::AllocatorOptions {
snap_size: 1,
small_size_threshold,
large_size_threshold,
});
let col_lights_size = Vec2::new(1u16, 1u16);
Self {
atlas,
col_lights_size,
max_size,
suspended: Vec::new(),
}
}
pub fn push</* S: render::Pipeline, *//*O: render::Pipeline, */ M: PartialEq, D: 'a>(
&mut self,
data: D,
draw_delta: Vec3<i32>,
greedy_size: Vec3<usize>,
greedy_size_cross: Vec3<usize>,
get_light: impl for<'r> FnMut(&'r mut D, Vec3<i32>) -> f32 + 'a,
get_color: impl for<'r> FnMut(&'r mut D, Vec3<i32>) -> Rgb<u8> + 'a,
get_opacity: impl for<'r> FnMut(&'r mut D, Vec3<i32>) -> bool + 'a,
should_draw: impl for<'r> FnMut(
&'r mut D,
Vec3<i32>,
Vec3<i32>,
Vec2<Vec3<i32>>,
) -> Option<(bool, M)>,
// create_shadow: impl for<'r> Fn(Vec3<f32>, Vec3<f32>, &'r M) -> S::Vertex,
// create_opaque: impl for<'r> Fn(Vec2<u16>, Vec3<f32>, Vec3<f32>, &'r M) -> O::Vertex,
push_quad: impl FnMut(Vec2<u16>, Vec2<Vec2<u16>>, Vec3<f32>, Vec2<Vec3<f32>>, Vec3<f32>, &M),
) -> Aabb<u16> {
let (bounds, /* opaque, *//*shadow, */ cont) = greedy_mesh(
&mut self.atlas,
&mut self.col_lights_size,
self.max_size,
data,
draw_delta,
greedy_size,
greedy_size_cross,
get_light,
get_color,
get_opacity,
should_draw,
// create_shadow,
// create_opaque,
push_quad,
);
self.suspended.push(cont);
bounds
}
pub fn finalize(self) -> ColLightInfo {
let cur_size = self.col_lights_size;
let col_lights = vec![/*Default::default()*/TerrainVertex::make_col_light(254, Rgb::broadcast(254)); usize::from(cur_size.x) * usize::from(cur_size.y)];
let mut col_lights_info = (col_lights, cur_size);
self.suspended.into_iter().for_each(|cont| {
cont(&mut col_lights_info);
});
col_lights_info
}
pub fn max_size(&self) -> guillotiere::Size { self.max_size }
}
/// Perform greedy meshing on a model, separately producing "pure" model data
/// (the shadow mesh), raw light and color data ready to be used as a texture
/// (the returned vector of ColLights, together with their width and height),
/// and the atlas positions (the opaque mesh) used to connect the shadow
/// information with the light and color information.
///
/// The opaque and shadow data are in the same order and it is intended that
/// they be used together as vertex buffers for display purposes. Thus, if you
/// perform further manipulation on the meshes after this function returns, such
/// as merges, please be sure that all those operations preserve this
/// relationship.
///
/// TODO: Consider supporting shared texture atlases (this might come in handy
/// for mobs or sprites, for instance).a
///
/// TODO: Add assertions to make this more robust.
///
/// Parameter description:
///
/// `max_size`:
/// The maximum allowable size of the texture atlas used to store the
/// light/color data for this mesh.
///
/// NOTE: It is an error to pass any size > u16::MAX.
///
/// Even aside from the above limitation, this will not necessarily always be
/// the same as the maximum atlas size supported by the hardware. For instance,
/// since we want to reserve 4 bits for a bone index for figures in their shadow
/// vertex, the atlas parameter for figures has to have at least 2 bits of the
/// normal; thus, it can only take up at most 30 bits total, meaning we are
/// restricted to "only" at most 2^15 × 2^15 atlases even if the hardware
/// supports larger ones.
///
/// `draw_delta`: The minimum position to mesh, in the coordinate system used
/// for queries against the volume.
///
/// `greedy_size`:
/// For each dimension i, for faces drawn in planes *parallel* to i, represents
/// the number of voxels considered along dimenson i in those planes, starting
/// from `draw_delta`.
///
/// `greedy_size_cross`:
/// For each dimension i, represents the number of planes considered
/// *orthogonal* to dimension i, starting from `draw_delta`. This should
/// usually be the same as greedy_size.
///
/// An important exception is during chunk rendering (where vertical faces at
/// chunk boundaries would otherwise be rendered twice, and also force us to use
/// more than 5 bits to represent x and y positions--though there may be a
/// clever way aruond the latter). Thus, for chunk rendering we set the number
/// of *vertical* planes to one less than the chunk size along the
/// x and y dimensions, but keep the number of *horizontal* planes large enough
/// to cover the whole chunk.
///
/// `get_light`:
/// Given a position, return the lighting information for the voxel at that
/// position.
///
/// `get_color`:
/// Given a position, return the color information for the voxel at that
/// position.
///
/// `get_opacity`:
/// Given a position, return the opacity information for the voxel at that
/// position. Currently, we don't support real translucent lighting, so the
/// value should either be `false` (for opaque blocks) or `true` (otherwise).
///
/// `should_draw`:
/// Given a position and a normal, should we draw the face between the position
/// and position - normal (i.e. the voxel "below" this vertex)? If so, provide
/// its orientation, together with any other meta information required for the
/// mesh that needs to split up faces. For example, terrain faces currently
/// record a bit indicating whether they are exposed to water or not, so we
/// should not merge faces where one is submerged in water and the other is not,
/// even if they otherwise have the same orientation, dimensions, and are
/// next to each other.
///
/// `create_shadow`:
/// Create a shadow vertex (used for both shadow and display rendering)
/// given its position, normal, and meta information. Note that the position
/// received here is relative to `draw_delta`--it still needs to be translated
/// to mesh coordinates.
///
/// `create_opaque`:
/// Create an opauqe vertex (used for only display rendering) from an atlas
/// position, normal, and meta information.
fn greedy_mesh<
'a, /* , S: render::Pipeline*//*, O: render::Pipeline */
M: PartialEq,
D: 'a,
>(
atlas: &mut guillotiere::SimpleAtlasAllocator,
col_lights_size: &mut Vec2<u16>,
max_size: guillotiere::Size,
mut data: D,
draw_delta: Vec3<i32>,
greedy_size: Vec3<usize>,
greedy_size_cross: Vec3<usize>,
get_light: impl for<'r> FnMut(&'r mut D, Vec3<i32>) -> f32 + 'a,
get_color: impl for<'r> FnMut(&'r mut D, Vec3<i32>) -> Rgb<u8> + 'a,
get_opacity: impl for<'r> FnMut(&'r mut D, Vec3<i32>) -> bool + 'a,
mut should_draw: impl for<'r> FnMut(
&'r mut D,
Vec3<i32>,
Vec3<i32>,
Vec2<Vec3<i32>>,
) -> Option<(bool, M)>,
// create_shadow: impl Fn(Vec3<f32>, Vec3<f32>, &M) -> S::Vertex,
// create_opaque: impl Fn(Vec2<u16>, Vec3<f32>, Vec3<f32>, &M) -> O::Vertex,
mut push_quad: impl FnMut(Vec2<u16>, Vec2<Vec2<u16>>, Vec3<f32>, Vec2<Vec3<f32>>, Vec3<f32>, &M),
) -> (
Aabb<u16>,
// Mesh<O>,
// Mesh<S>,
Box<SuspendedMesh<'a>>,
) {
// let mut opaque_mesh = Mesh::new();
// let mut shadow_mesh = Mesh::new();
// TODO: Collect information to see if we can choose a good value here.
let mut todo_rects = Vec::with_capacity(1024);
/* let mut bounds = Aabb {
min: Vec3::zero(),
max: Vec3::zero(),
}; */
/* let compute_bounds = |pos: Vec3<usize>, dim: Vec2<usize>, uv: Vec2<Vec3<u16>>/*, norm: Vec3<u16>, faces_forward: bool*/| {
Aabb {
min: pos,
max: pos + uv.x.map(usize::from) * dim.x + uv.y.map(usize::from) * dim.y,
}
}; */
// x (u = y, v = z)
greedy_mesh_cross_section(
Vec3::new(greedy_size.y, greedy_size.z, greedy_size_cross.x),
|pos| {
should_draw(
&mut data,
draw_delta + Vec3::new(pos.z, pos.x, pos.y),
Vec3::unit_x(), /* , pos.z, 0, x_size */
Vec2::new(Vec3::unit_y(), Vec3::unit_z()),
)
},
|pos, dim, &(faces_forward, ref meta)| {
let pos = Vec3::new(pos.z, pos.x, pos.y);
let uv = Vec2::new(Vec3::unit_y(), Vec3::unit_z());
let norm = Vec3::unit_x();
// bounds.expand_to_contain(compute_bounds(pos, dim, uv));
let atlas_pos = if let Some(atlas_pos) = add_to_atlas(
atlas,
&mut todo_rects,
pos,
uv,
dim,
norm,
faces_forward,
max_size,
col_lights_size,
) {
// assert!(atlas_pos.max.x - atlas_pos.min.x == dim.x as i32);
// assert!(atlas_pos.max.y - atlas_pos.min.y == dim.y as i32);
atlas_pos
} else {
return;
};
create_quad_greedy(
// &mut shadow_mesh,
// &mut opaque_mesh,
/* Vec3::new(pos.z, pos.x, pos.y) */
pos,
dim,
uv,
norm,
faces_forward,
// Rgba::from_opaque(flat_get(pos).color),
// lightm
// ao,
meta,
atlas_pos,
// |pos| flat_get(pos),
// |pos, norm, meta| create_shadow(pos, norm, meta),
// |atlas_pos, pos, norm, meta| create_opaque(atlas_pos, pos, norm, meta),
|atlas_pos, dim, pos, draw_dim, norm, meta| {
push_quad(atlas_pos, dim, pos, draw_dim, norm, meta)
},
);
},
);
// y (u = z, v = x)
greedy_mesh_cross_section(
Vec3::new(greedy_size.z, greedy_size.x, greedy_size_cross.y),
|pos| {
should_draw(
&mut data,
draw_delta + Vec3::new(pos.y, pos.z, pos.x),
Vec3::unit_y(),
Vec2::new(Vec3::unit_z(), Vec3::unit_x()),
)
},
|pos, dim, &(faces_forward, ref meta)| {
let pos = Vec3::new(pos.y, pos.z, pos.x);
let uv = Vec2::new(Vec3::unit_z(), Vec3::unit_x());
let norm = Vec3::unit_y();
// bounds.expand_to_contain(compute_bounds(pos, dim, uv));
let atlas_pos = if let Some(atlas_pos) = add_to_atlas(
atlas,
&mut todo_rects,
pos,
uv,
dim,
norm,
faces_forward,
max_size,
col_lights_size,
) {
atlas_pos
} else {
return;
};
create_quad_greedy(
// &mut shadow_mesh,
// &mut opaque_mesh,
pos,
dim,
uv,
norm,
faces_forward,
// Rgba::from_opaque(flat_get(pos).color),
meta,
atlas_pos,
// |pos, norm, meta| create_shadow(pos, norm, meta),
// |atlas_pos, pos, norm, meta| create_opaque(atlas_pos, pos, norm, meta),
|atlas_pos, dim, pos, draw_dim, norm, meta| {
push_quad(atlas_pos, dim, pos, draw_dim, norm, meta)
},
);
},
);
// z (u = x, v = y)
greedy_mesh_cross_section(
Vec3::new(greedy_size.x, greedy_size.y, greedy_size_cross.z),
|pos| {
/* if pos.z == 0 {
let pos = pos.map(|e| e as i32) + draw_delta; // - delta;
let to = flat_get(pos).is_opaque(); //map(|v| v.is_opaque()).unwrap_or(false);
if to { Some(false) } else { None }
} else */
{
should_draw(
&mut data,
draw_delta + Vec3::new(pos.x, pos.y, pos.z),
Vec3::unit_z(),
Vec2::new(Vec3::unit_x(), Vec3::unit_y()),
)
}
},
|pos, dim, &(faces_forward, ref meta)| {
let pos = Vec3::new(pos.x, pos.y, pos.z);
let uv = Vec2::new(Vec3::unit_x(), Vec3::unit_y());
let norm = Vec3::unit_z();
// bounds.expand_to_contain(compute_bounds(pos, dim, uv));
let atlas_pos = if let Some(atlas_pos) = add_to_atlas(
atlas,
&mut todo_rects,
pos,
uv,
dim,
norm,
faces_forward,
max_size,
col_lights_size,
) {
atlas_pos
} else {
return;
};
create_quad_greedy(
// &mut shadow_mesh,
// &mut opaque_mesh,
pos,
dim,
uv,
norm,
faces_forward,
// Rgba::from_opaque(flat_get(pos).color),
meta,
atlas_pos,
// |pos, norm, meta| create_shadow(pos, norm, meta),
// |atlas_pos, pos, norm, meta| create_opaque(atlas_pos, pos, norm, meta),
|atlas_pos, dim, pos, draw_dim, norm, meta| {
push_quad(atlas_pos, dim, pos, draw_dim, norm, meta)
},
);
},
);
// NOTE: Safe because bound dimensions actually fit in a u16.
// let bounds = bounds.map(|e| e as u16);
// NOTE: Safe because draw_delta fits in i16.
let bounds = Aabb {
min: Vec3::zero(),
// NOTE: Safe because greedy_size fit in u16.
max: greedy_size.map(|e| e as u16),
};
(
bounds,
/* opaque_mesh, *//*shadow_mesh, */
Box::new(move |col_lights_info| {
let mut data = data;
draw_col_lights(
col_lights_info,
&mut data,
todo_rects,
draw_delta,
get_light,
get_color,
get_opacity,
TerrainVertex::make_col_light,
);
}),
)
}
// Greedy meshing a single cross-section.
fn greedy_mesh_cross_section<M: PartialEq>(
/* mask: &mut [bool], */
dims: Vec3<usize>,
// Should we draw a face here (below this vertex)? If so, provide its meta information.
mut draw_face: impl FnMut(Vec3<i32>) -> Option<M>,
// Vertex, width and height, and meta information about the block.
mut push_quads: impl FnMut(Vec3<usize>, Vec2<usize>, &M),
) {
// mask represents which faces are either set while the other is unset, or unset
// while the other is set.
let mut mask = (0..dims.y * dims.x).map(|_| None).collect::<Vec<_>>();
(0..dims.z + 1).for_each(|d| {
// Compute mask
mask.iter_mut().enumerate().for_each(|(posi, mask)| {
let i = posi % dims.x;
let j = posi / dims.x;
// NOTE: Safe because dims.z actually fits in a u16.
*mask = draw_face(Vec3::new(i as i32, j as i32, d as i32));
});
(0..dims.y).for_each(|j| {
let mut i = 0;
while i < dims.x {
// Compute width (number of set x bits for this row and layer, starting at the
// current minimum column).
if let Some(ori) = &mask[j * dims.x + i] {
let width = 1 + mask[j * dims.x + i + 1..j * dims.x + dims.x]
.iter()
.take_while(move |&mask| mask.as_ref() == Some(ori))
.count();
let max_x = i + width;
// Compute height (number of rows having w set x bits for this layer, starting
// at the current minimum column and row).
let height = 1
+ (j + 1..dims.y)
.take_while(|h| {
mask[h * dims.x + i..h * dims.x + max_x]
.iter()
.all(|mask| mask.as_ref() == Some(ori))
})
.count();
let max_y = j + height;
// Add quad.
push_quads(Vec3::new(i, j, d /* + 1 */), Vec2::new(width, height), ori);
// Unset mask bits in drawn region, so we don't try to re-draw them.
(j..max_y).for_each(|l| {
mask[l * dims.x + i..l * dims.x + max_x]
.iter_mut()
.for_each(|mask| {
*mask = None;
});
});
// Update x value.
i = max_x;
} else {
i += 1;
}
}
});
});
}
fn add_to_atlas(
atlas: &mut guillotiere::SimpleAtlasAllocator,
todo_rects: &mut Vec<(
Vec3<i32>,
Vec2<Vec3<u16>>,
guillotiere::Rectangle,
Vec3<i32>,
)>,
pos: Vec3<usize>,
uv: Vec2<Vec3<u16>>,
dim: Vec2<usize>,
norm: Vec3<i16>,
faces_forward: bool,
max_size: guillotiere::Size,
cur_size: &mut Vec2<u16>,
) -> Option<guillotiere::Rectangle> {
// TODO: Check this conversion.
let atlas_rect;
loop {
// NOTE: Conversion to i32 is safe because he x, y, and z dimensions for any
// chunk index must fit in at least an i16 (lower for x and y, probably
// lower for z).
let res = atlas.allocate(guillotiere::Size::new(dim.x as i32 + 1, dim.y as i32 + 1));
if let Some(atlas_rect_) = res {
atlas_rect = atlas_rect_;
break;
}
// Allocation failure.
let current_size = atlas.size();
if current_size == max_size {
// NOTE: Currently, if we fail to allocate a terrain chunk in the atlas and we
// have already reached the maximum texture size, we choose to just skip the
// geometry and log a warning, rather than panicking or trying to use a fallback
// technique (e.g. a texture array).
//
// FIXME: Either make more robust, or explicitly document that limits on texture
// size need to be respected for terrain data (the OpenGL minimum requirement is
// 1024 × 1024, but in practice almost all computers support 4096 × 4096 or
// higher; see
// https://feedback.wildfiregames.com/report/opengl/feature/GL_MAX_TEXTURE_SIZE).
panic!(
"Could not add texture to atlas using simple allocator (pos={:?}, dim={:?});we \
could not fit the whole model into a single texture on this machine
(max texture size={:?}, so we are discarding this rectangle.",
pos, dim, max_size
);
// return None;
}
// Otherwise, we haven't reached max size yet, so double the size (or reach the
// max texture size) and try again.
let new_size = guillotiere::Size::new(
max_size.width.min(current_size.width.saturating_mul(2)),
max_size.height.min(current_size.height.saturating_mul(2)),
);
atlas.grow(new_size);
// atlas.grow((current_size * 2).min(max_size));
}
// NOTE: Conversion is correct because our initial max size for the atlas was
// a u16 and we never grew the atlas, meaning all valid coordinates within the
// atlas also fit into a u16.
*cur_size = Vec2::new(
cur_size.x.max(atlas_rect.max.x as u16),
cur_size.y.max(atlas_rect.max.y as u16),
);
/* let (dim, uv, norm) = if faces_forward {
// NOTE: Conversion to u16 safe by function precondition.
(dim.map(|e| e as u16), uv, norm)
} else {
// NOTE: Conversion to u16 safe by function precondition.
(Vec2::new(dim.y as u16, dim.x as u16), Vec2::new(uv.y, uv.x), -norm)
}; */
// NOTE: pos can be converted safely from usize to i32 because all legal block
// coordinates in this chunk must fit in an i32 (actually we have the much
// stronger property that this holds across the whole map).
let norm = norm.map(i32::from);
todo_rects.push((
pos.map(|e| e as i32) + if faces_forward { -norm } else { Vec3::zero() },
uv,
atlas_rect,
if faces_forward { norm } else { -norm },
));
Some(atlas_rect)
}
/// We deferred actually recording the colors within the rectangles in order to
/// generate a texture of minimal size; we now proceed to create and populate
/// it.
///
/// TODO: Consider using the heavier interface (not the simple one) which seems
/// to provide builtin support for what we're doing here.
fn draw_col_lights<D>(
(col_lights, cur_size): &mut ColLightInfo,
data: &mut D,
todo_rects: Vec<(
Vec3<i32>,
Vec2<Vec3<u16>>,
guillotiere::Rectangle,
Vec3<i32>,
)>,
draw_delta: Vec3<i32>,
mut get_light: impl FnMut(&mut D, Vec3<i32>) -> f32,
mut get_color: impl FnMut(&mut D, Vec3<i32>) -> Rgb<u8>,
mut get_opacity: impl FnMut(&mut D, Vec3<i32>) -> bool,
mut make_col_light: impl FnMut(u8, Rgb<u8>) -> <<ColLightFmt as gfx::format::Formatted>::Surface as gfx::format::SurfaceTyped>::DataType,
) {
/* for i in 0..todo_rects.len() {
for j in 0..todo_rects.len() {
if i == j {
continue;
}
assert!(!todo_rects[i].2.intersects(&todo_rects[j].2));
}
} */
todo_rects
.into_iter()
// .rev()
.for_each(|(pos, uv, rect, delta)| {
// NOTE: Conversions are safe because width, height, and offset must be
// non-negative, and because every allocated coordinate in the atlas must be in
// bounds for the original size, max_texture_size, which fit into a u16.
let width = (rect.max.x - rect.min.x) as u16;//rect.width() as u16;
let height = (rect.max.y - rect.min.y) as u16;//rect.height() as u16;
/* if width > 32 || height > 32 {
println!("Rect: {:?}", rect);
} */
let left = rect.min.x as u16;
let top = rect.min.y as u16;
let uv = uv.map(|e| e.map(i32::from));
let pos = pos + draw_delta;//Vec3::new(0, 0, z_start - 1);// + mesh_delta;// + draw_delta;
(0..height).for_each(|v| {
let start = usize::from(cur_size.x) * usize::from(top + v) + usize::from(left);
(0..width).zip(&mut col_lights[start..start + usize::from(width)]).for_each(|(u, col_light)| {
let pos = pos + uv.x * i32::from(u) + uv.y * i32::from(v);
// TODO: Consider optimizing to take advantage of the fact that this whole
// face should be facing nothing but air (this is not currently true, but
// could be if we used the right AO strategy).
// Each indirect light needs to come in through the direct light.
// Thus, we assign each light a score based on opacity (currently just 0 or
// 1, but it could support transluscent lights in the future).
// Thus, indirect_u_opacity and indirect_v_opacity are multiplied by
// direct_opacity, and indirect_uv_opacity is multiplied by
// the maximum of both of u and v's indirect opacities (since there are
// two choices for how to get to the direct surface).
let pos = pos +
if u + 1 == width { -uv.x } else { Vec3::zero() } +
if v + 1 == height { -uv.y } else { Vec3::zero() };
let uv = Vec2::new(
if u + 1 == width { -uv.x } else { uv.x },
if v + 1 == height { -uv.y } else { uv.y },
);
let light_pos = pos + /*range.min + */delta;
// let block = flat_get(pos);
// Currently, we assume that direct_opacity is 1 (if it's 0, you can't see
// the face anyway, since it's blocked by the block directly in front of it).
// TODO: If we add non-0/1 opacities, fix this.
// top-left block
// let direct_opacity = !flat_get(pos + delta).is_opaque();
// bottom-left block
let direct_u_opacity = get_opacity(data, light_pos - uv.x);
// top-right block
let direct_v_opacity = get_opacity(data, light_pos - uv.y);
// top-left block
// NOTE: Currently, since we only have 0 / 1 opacities, we don't worry
// about whether the uv block itself is opaque, because if it is its light
// value will be 0 anyway. But if we add translucent objects, we'll need
// to care about uv's opacity as well.
// let direct_uv_opacity = !flat_get(pos + delta - uv.x - uv.y).is_opaque();
// let indirect_opacity = direct_uv_opacity && (direct_u_opacity || direct_v_opacity) && direct_opacity;
// NOTE: Since we only support 0/1 opacities currently, we asssume
// direct_opacity is 1, and the light value will be zero anyway for objects
// with opacity 0, we only "multiply" by indirect_uv_opacity for now (since
// it's the only one that could be 0 even if its light value is not).
// However, "spiritually" these light values are all being multiplied by
// their opacities.
let darkness = (
// Light from the bottom-right-front block to this vertex always
// appears on this face, since it's the block this face is facing (so
// it can't be blocked by anything).
if /*direct_u_opacity || direct_v_opacity*/true/* || !flat_get(pos - uv.x - uv.y).is_opaque()*//* || !block.is_opaque()*/ { get_light(data, light_pos) } else { 0.0 } +
if /*direct_opacity || direct_uv_opacity*/true/* || !flat_get(pos - uv.y).is_opaque()*/ { get_light(data, light_pos - uv.x) } else { 0.0 } +
if /*direct_opacity || direct_uv_opacity*/true/* || !flat_get(pos - uv.x).is_opaque()*/ { get_light(data, light_pos - uv.y) } else { 0.0 } +
if direct_u_opacity || direct_v_opacity/* || !block.is_opaque()*/ { get_light(data, light_pos - uv.x - uv.y) } else { 0.0 }
) / 4.0;
let col = get_color(data, pos);//.map(Rgba::from_opaque).unwrap_or(Rgba::zero());
let light = (darkness * 255.0) as u8;
*col_light = make_col_light(light, col);
});
});
});
}
/// Precondition: when this function is called, atlas_pos should reflect an
/// actual valid position in a texture atlas (meaning it should fit into a u16).
fn create_quad_greedy</* S: render::Pipeline, *//*O: render::Pipeline, */ M>(
// shadow_mesh: &mut Mesh<S>,
// opaque_mesh: &mut Mesh<O>,
origin: Vec3<usize>,
dim: Vec2<usize>,
uv: Vec2<Vec3<u16>>,
norm: Vec3<i16>,
faces_forward: bool,
meta: &M,
atlas_pos: guillotiere::Rectangle,
// origin, norm, meta
// create_shadow: impl Fn(Vec3<f32>, Vec3<f32>, &M) -> S::Vertex,
// create_opaque: impl Fn(Vec2<u16>, Vec3<f32>, Vec3<f32>, &M) -> O::Vertex,
mut push_quad: impl FnMut(Vec2<u16>, Vec2<Vec2<u16>>, Vec3<f32>, Vec2<Vec3<f32>>, Vec3<f32>, &M),
) /* -> Quad<ShadowPipeline> */
{
let origin = origin.map(|e| e as f32);
/* // NOTE: Conversion to u16 safe by function precondition.
let dim = uv.map2(dim.map(|e| e as u16), |e, f| e * f); */
// NOTE: Conversion to f32 safe by function precondition (u16 can losslessly
// cast to f32, and dim fits in a u16).
let draw_dim = uv.map2(dim.map(|e| e as f32), |e, f| e.map(f32::from) * f);
let dim = Vec2::new(Vec2::new(dim.x as u16, 0), Vec2::new(0, dim.y as u16));
let (draw_dim, dim, /* uv, */ norm) = if faces_forward {
/* // NOTE: Conversion to u16 safe by function precondition.
(dim.map(|e| e as u16), uv, norm) */
(draw_dim, dim, norm)
} else {
/* // NOTE: Conversion to u16 safe by function precondition.
(Vec2::new(dim.y as u16, dim.x as u16), Vec2::new(uv.y, uv.x), -norm) */
(
Vec2::new(draw_dim.y, draw_dim.x),
Vec2::new(dim.y, dim.x),
-norm,
)
};
let norm = norm.map(f32::from);
// let draw_dim = draw_dim.map(|e| e.map(f32::from));
// NOTE: Conversion to u16 safe by function precondition.
let atlas_pos = Vec2::new(atlas_pos.min.x as u16, atlas_pos.min.y as u16);
/* shadow_mesh.push_quad(Quad::new(
create_shadow(origin, norm, &meta/*, atlas_pos*/),
create_shadow(origin + draw_dim.x, norm, &meta/*, atlas_pos + dim.x*/),
create_shadow(origin + draw_dim.x + draw_dim.y, norm, &meta/*, atlas_pos + dim.x + dim.y*/),
create_shadow(origin + draw_dim.y, norm, &meta/*, atlas_pos + dim.y*/),
)); */
/* opaque_mesh.push_quad(Quad::new(
create_opaque(atlas_pos, origin, norm, &meta),
create_opaque(atlas_pos + dim.x, origin + draw_dim.x, norm, &meta),
create_opaque(atlas_pos + dim.x + dim.y, origin + draw_dim.x + draw_dim.y, norm, &meta),
create_opaque(atlas_pos + dim.y, origin + draw_dim.y, norm, &meta),
)); */
push_quad(atlas_pos, dim, origin, draw_dim, norm, meta);
}
pub fn create_quad<O: render::Pipeline, M>(
atlas_pos: Vec2<u16>,
dim: Vec2<Vec2<u16>>,
origin: Vec3<f32>,
draw_dim: Vec2<Vec3<f32>>,
norm: Vec3<f32>,
meta: &M,
create_vertex: impl Fn(Vec2<u16>, Vec3<f32>, Vec3<f32>, &M) -> O::Vertex,
) -> Quad<O> {
Quad::new(
create_vertex(atlas_pos, origin, norm, meta),
create_vertex(atlas_pos + dim.x, origin + draw_dim.x, norm, meta),
create_vertex(
atlas_pos + dim.x + dim.y,
origin + draw_dim.x + draw_dim.y,
norm,
meta,
),
create_vertex(atlas_pos + dim.y, origin + draw_dim.y, norm, meta),
/* create_vertex(atlas_pos, origin, norm, meta),
create_vertex(atlas_pos + dim.y, origin + draw_dim.y, norm, meta),
create_vertex(atlas_pos + dim.x + dim.y, origin + draw_dim.x + draw_dim.y, norm, meta),
create_vertex(atlas_pos + dim.x, origin + draw_dim.x, norm, meta), */
)
}

View File

@ -1,22 +1,24 @@
pub mod greedy;
pub mod segment;
pub mod terrain;
mod vol;
use crate::render::{self, Mesh};
pub trait Meshable<'a, P: render::Pipeline, T: render::Pipeline> {
pub trait Meshable<P: render::Pipeline, T> {
type Pipeline: render::Pipeline;
type TranslucentPipeline: render::Pipeline;
type ShadowPipeline: render::Pipeline;
type Supplement;
type Result;
// Generate meshes - one opaque, one translucent, one shadow
fn generate_mesh(
&'a self,
self,
supp: Self::Supplement,
) -> (
Mesh<Self::Pipeline>,
Mesh<Self::TranslucentPipeline>,
Mesh<Self::ShadowPipeline>,
Self::Result,
);
}

View File

@ -1,91 +1,118 @@
use crate::{
mesh::{vol, Meshable},
render::{self, FigurePipeline, Mesh, SpritePipeline},
mesh::{
greedy::{self, GreedyMesh},
Meshable,
},
render::{self, FigurePipeline, Mesh, ShadowPipeline, SpritePipeline, TerrainPipeline},
};
use common::{
figure::Cell,
util::{linear_to_srgb, srgb_to_linear},
vol::{BaseVol, ReadVol, SizedVol, Vox},
};
use vek::*;
type FigureVertex = <FigurePipeline as render::Pipeline>::Vertex;
type SpriteVertex = <SpritePipeline as render::Pipeline>::Vertex;
type TerrainVertex = <TerrainPipeline as render::Pipeline>::Vertex;
impl<'a, V: 'a> Meshable<'a, FigurePipeline, FigurePipeline> for V
impl<'a: 'b, 'b, V: 'a> Meshable<FigurePipeline, &'b mut GreedyMesh<'a>> for V
where
V: BaseVol<Vox = Cell> + ReadVol + SizedVol,
/* TODO: Use VolIterator instead of manually iterating
* &'a V: IntoVolIterator<'a> + IntoFullVolIterator<'a>,
* &'a V: BaseVol<Vox=Cell>, */
{
type Pipeline = FigurePipeline;
type ShadowPipeline = FigurePipeline;
type Supplement = (Vec3<f32>, Vec3<f32>);
type Pipeline = TerrainPipeline;
type Result = Aabb<f32>;
type ShadowPipeline = ShadowPipeline;
type Supplement = (&'b mut GreedyMesh<'a>, Vec3<f32>, Vec3<f32>);
type TranslucentPipeline = FigurePipeline;
// TODO: Make sprites cast shadows?
fn generate_mesh(
&'a self,
(offs, scale): Self::Supplement,
self,
(greedy, offs, scale): Self::Supplement,
) -> (
Mesh<Self::Pipeline>,
Mesh<Self::TranslucentPipeline>,
Mesh<Self::ShadowPipeline>,
Self::Result,
) {
let mut mesh = Mesh::new();
let max_size = greedy.max_size();
// NOTE: Required because we steal two bits from the normal in the shadow uint
// in order to store the bone index. The two bits are instead taken out
// of the atlas coordinates, which is why we "only" allow 1 << 15 per
// coordinate instead of 1 << 16.
assert!(max_size.width.max(max_size.height) < 1 << 15);
let vol_iter = (self.lower_bound().x..self.upper_bound().x)
.map(|i| {
(self.lower_bound().y..self.upper_bound().y).map(move |j| {
(self.lower_bound().z..self.upper_bound().z).map(move |k| Vec3::new(i, j, k))
})
})
.flatten()
.flatten()
.map(|pos| (pos, self.get(pos).map(|x| *x).unwrap_or(Vox::empty())));
let greedy_size = Vec3::new(
(self.upper_bound().x - self.lower_bound().x + 1) as usize,
(self.upper_bound().y - self.lower_bound().y + 1) as usize,
(self.upper_bound().z - self.lower_bound().z + 1) as usize,
);
let greedy_size_cross = greedy_size;
let draw_delta = Vec3::new(
self.lower_bound().x,
self.lower_bound().y,
self.lower_bound().z,
);
for (pos, vox) in vol_iter {
if let Some(col) = vox.get_color() {
vol::push_vox_verts(
&mut mesh,
faces_to_make(self, pos, true, |vox| vox.is_empty()),
offs + pos.map(|e| e as f32),
&[[[Rgba::from_opaque(col); 3]; 3]; 3],
|origin, norm, col, light, ao, _meta| {
FigureVertex::new(
origin * scale,
let get_light = |vol: &mut V, pos: Vec3<i32>| {
if vol.get(pos).map(|vox| vox.is_empty()).unwrap_or(true) {
1.0
} else {
0.0
}
};
let get_color = |vol: &mut V, pos: Vec3<i32>| {
vol.get(pos)
.ok()
.and_then(|vox| vox.get_color())
.unwrap_or(Rgb::zero())
};
let get_opacity =
|vol: &mut V, pos: Vec3<i32>| vol.get(pos).map(|vox| vox.is_empty()).unwrap_or(true);
let should_draw = |vol: &mut V, pos: Vec3<i32>, delta: Vec3<i32>, uv| {
should_draw_greedy(pos, delta, uv, |vox| {
vol.get(vox).map(|vox| *vox).unwrap_or(Vox::empty())
})
};
let create_opaque = |atlas_pos, pos, norm, _meta| {
TerrainVertex::new_figure(atlas_pos, (pos + offs) * scale, norm, 0)
};
let mut opaque_mesh = Mesh::new();
let bounds = greedy.push(
self,
draw_delta,
greedy_size,
greedy_size_cross,
get_light,
get_color,
get_opacity,
should_draw,
|atlas_origin, dim, origin, draw_dim, norm, meta| {
opaque_mesh.push_quad(greedy::create_quad(
atlas_origin,
dim,
origin,
draw_dim,
norm,
linear_to_srgb(srgb_to_linear(col) * light),
ao,
0,
)
},
&{
let mut ls = [[[None; 3]; 3]; 3];
for x in 0..3 {
for y in 0..3 {
for z in 0..3 {
ls[z][y][x] = self
.get(pos + Vec3::new(x as i32, y as i32, z as i32) - 1)
.map(|v| v.is_empty())
.unwrap_or(true)
.then_some(1.0);
}
}
}
ls
meta,
|atlas_pos, pos, norm, &meta| create_opaque(atlas_pos, pos, norm, meta),
));
},
);
let bounds = bounds.map(f32::from);
let bounds = Aabb {
min: (bounds.min + offs) * scale,
max: (bounds.max + offs) * scale,
}
.made_valid();
(opaque_mesh, Mesh::new(), Mesh::new(), bounds)
}
}
(mesh, Mesh::new(), Mesh::new())
}
}
impl<'a, V: 'a> Meshable<'a, SpritePipeline, SpritePipeline> for V
impl<'a: 'b, 'b, V: 'a> Meshable<SpritePipeline, /* SpritePipeline */ &'b mut GreedyMesh<'a>> for V
where
V: BaseVol<Vox = Cell> + ReadVol + SizedVol,
/* TODO: Use VolIterator instead of manually iterating
@ -93,92 +120,172 @@ where
* &'a V: BaseVol<Vox=Cell>, */
{
type Pipeline = SpritePipeline;
type ShadowPipeline = SpritePipeline;
type Supplement = (Vec3<f32>, Vec3<f32>);
type Result = ();
type ShadowPipeline = ShadowPipeline;
type Supplement = (&'b mut GreedyMesh<'a>, bool);
type TranslucentPipeline = SpritePipeline;
// TODO: Make sprites cast shadows?
fn generate_mesh(
&'a self,
(offs, scale): Self::Supplement,
self,
(greedy, vertical_stripes): Self::Supplement,
) -> (
Mesh<Self::Pipeline>,
Mesh<Self::TranslucentPipeline>,
Mesh<Self::ShadowPipeline>,
(),
) {
let mut mesh = Mesh::new();
let max_size = greedy.max_size();
// NOTE: Required because we steal two bits from the normal in the shadow uint
// in order to store the bone index. The two bits are instead taken out
// of the atlas coordinates, which is why we "only" allow 1 << 15 per
// coordinate instead of 1 << 16.
assert!(max_size.width.max(max_size.height) < 1 << 16);
let vol_iter = (self.lower_bound().x..self.upper_bound().x)
.map(|i| {
(self.lower_bound().y..self.upper_bound().y).map(move |j| {
(self.lower_bound().z..self.upper_bound().z).map(move |k| Vec3::new(i, j, k))
})
})
.flatten()
.flatten()
.map(|pos| (pos, self.get(pos).map(|x| *x).unwrap_or(Vox::empty())));
let greedy_size = Vec3::new(
(self.upper_bound().x - self.lower_bound().x + 1) as usize,
(self.upper_bound().y - self.lower_bound().y + 1) as usize,
(self.upper_bound().z - self.lower_bound().z + 1) as usize,
);
assert!(
greedy_size.x <= 16 && greedy_size.y <= 16 && greedy_size.z <= 64,
"Sprite size out of bounds: {:?} ≤ (15, 15, 63)",
greedy_size - 1
);
let greedy_size_cross = greedy_size;
let draw_delta = Vec3::new(
self.lower_bound().x,
self.lower_bound().y,
self.lower_bound().z,
);
for (pos, vox) in vol_iter {
if let Some(col) = vox.get_color() {
vol::push_vox_verts(
&mut mesh,
faces_to_make(self, pos, true, |vox| vox.is_empty()),
offs + pos.map(|e| e as f32),
&[[[Rgba::from_opaque(col); 3]; 3]; 3],
|origin, norm, col, light, ao, _meta| {
SpriteVertex::new(
origin * scale,
let get_light = |vol: &mut V, pos: Vec3<i32>| {
if vol.get(pos).map(|vox| vox.is_empty()).unwrap_or(true) {
1.0
} else {
0.0
}
};
let get_color = |vol: &mut V, pos: Vec3<i32>| {
vol.get(pos)
.ok()
.and_then(|vox| vox.get_color())
.unwrap_or(Rgb::zero())
};
let get_opacity =
|vol: &mut V, pos: Vec3<i32>| vol.get(pos).map(|vox| vox.is_empty()).unwrap_or(true);
let should_draw = |vol: &mut V, pos: Vec3<i32>, delta: Vec3<i32>, uv| {
should_draw_greedy_ao(vertical_stripes, pos, delta, uv, |vox| {
vol.get(vox).map(|vox| *vox).unwrap_or(Vox::empty())
})
};
// NOTE: Conversion to f32 is fine since this i32 is actually in bounds for u16.
// let create_shadow = |pos, norm, _meta| ShadowVertex::new_figure((pos + offs)
// * scale, norm, 0);
let create_opaque = |atlas_pos, pos: Vec3<f32>, norm, _meta| {
/* if pos.x >= 15.0 || pos.y >= 15.0 || pos.z >= 63.0 {
println!("{:?}", pos);
} */
SpriteVertex::new(atlas_pos, pos, norm /* , ao */)
};
let mut opaque_mesh = Mesh::new();
let _bounds = greedy.push(
self,
draw_delta,
greedy_size,
greedy_size_cross,
get_light,
get_color,
get_opacity,
should_draw,
|atlas_origin, dim, origin, draw_dim, norm, meta| {
opaque_mesh.push_quad(greedy::create_quad(
atlas_origin,
dim,
origin,
draw_dim,
norm,
linear_to_srgb(srgb_to_linear(col) * light),
ao,
)
},
&{
let mut ls = [[[None; 3]; 3]; 3];
for x in 0..3 {
for y in 0..3 {
for z in 0..3 {
ls[z][y][x] = self
.get(pos + Vec3::new(x as i32, y as i32, z as i32) - 1)
.map(|v| v.is_empty())
.unwrap_or(true)
.then_some(1.0);
}
}
}
ls
meta,
|atlas_pos, pos, norm, &meta| create_opaque(atlas_pos, pos, norm, meta),
));
},
);
}
}
(mesh, Mesh::new(), Mesh::new())
(opaque_mesh, Mesh::new(), Mesh::new(), ())
}
}
/// Use the 6 voxels/blocks surrounding the one at the specified position
/// to detemine which faces should be drawn
fn faces_to_make<V: ReadVol>(
seg: &V,
fn should_draw_greedy(
pos: Vec3<i32>,
error_makes_face: bool,
should_add: impl Fn(&V::Vox) -> bool,
) -> [Option<()>; 6] {
let (x, y, z) = (Vec3::unit_x(), Vec3::unit_y(), Vec3::unit_z());
let make_face = |offset| {
let res = seg
.get(pos + offset)
.map(|v| should_add(v))
.unwrap_or(error_makes_face);
if res { Some(()) } else { None }
};
[
make_face(-x),
make_face(x),
make_face(-y),
make_face(y),
make_face(-z),
make_face(z),
]
delta: Vec3<i32>,
_uv: Vec2<Vec3<i32>>,
flat_get: impl Fn(Vec3<i32>) -> Cell,
) -> Option<(bool, /* u8 */ ())> {
// TODO: Verify conversion.
// let pos = pos.map(|e| e as i32) + draw_delta; // - delta;
let from = flat_get(pos - delta); // map(|v| v.is_opaque()).unwrap_or(false);
let to = flat_get(pos); //map(|v| v.is_opaque()).unwrap_or(false);
let from_opaque = !from.is_empty();
if from_opaque == !to.is_empty() {
None
} else {
// If going from transparent to opaque, backward facing; otherwise, forward
// facing.
Some((from_opaque, ()))
}
}
fn should_draw_greedy_ao(
vertical_stripes: bool,
pos: Vec3<i32>,
delta: Vec3<i32>,
_uv: Vec2<Vec3<i32>>,
flat_get: impl Fn(Vec3<i32>) -> Cell,
) -> Option<(bool, /* u8 */ bool)> {
// TODO: Verify conversion.
// let pos = pos.map(|e| e as i32) + draw_delta; // - delta;
let from = flat_get(pos - delta); // map(|v| v.is_opaque()).unwrap_or(false);
let to = flat_get(pos); //map(|v| v.is_opaque()).unwrap_or(false);
let from_opaque = !from.is_empty();
if from_opaque == !to.is_empty() {
None
} else {
let faces_forward = from_opaque;
let ao = /* if delta.z != 0 {
0u8
} else {
(pos.z & 1) as u8
// (((pos.x & 1) as u8) << 1) | (pos.y & 1) as u8
}*/!vertical_stripes || /*((pos.x & 1) ^ (pos.y & 1))*/(pos.z & 1) != 0/* as u8*/;
/* let (from, delta, uv) = if faces_forward {
(pos - delta - uv.x - uv.y, delta, uv)
} else {
(pos, -delta, Vec2::new(-uv.y, -uv.x))
};
let ao_vertex = |from: Vec3<i32>, delta: Vec3<i32>, uv: Vec2<Vec3<i32>>| {
let corner = !flat_get(from + delta - uv.x - uv.y).is_empty();
let s1 = !flat_get(from + delta - uv.x).is_empty();
let s2 = !flat_get(from + delta - uv.y).is_empty();
if s1 && s2 {
0
} else {
3 - (if corner { 1 } else { 0 } + if s1 { 1 } else { 0 } + if s2 { 1 } else { 0 })
}
};
// We only care about the vertices we are *not* merging, since the shared vertices
// by definition have the same AO values. But snce we go both down and right we end up
// needing all but the bottom right vertex.
let ao_corner = ao_vertex(from, delta, uv);
let ao1 = ao_vertex(from + uv.x, delta, uv);
let ao2 = ao_vertex(from + uv.y, delta, uv);
let ao3 = ao_vertex(from + uv.x + uv.y, delta, uv);
// NOTE: ao's 4 values correspond (from 0 to 3) to 0.25, 0.5, 0.75, 1.0.
//
// 0.0 is the None case.
let ao = (ao_corner << 6) | (ao1 << 4) | (ao2 << 2) | ao3; */
// let ao = ao_vertex(from, delta, uv);
// If going from transparent to opaque, backward facing; otherwise, forward
// facing.
Some((faces_forward, ao))
// Some((faces_forward, ()))
}
}

View File

@ -1,6 +1,9 @@
use crate::{
mesh::{vol, Meshable},
render::{self, mesh::Quad, FluidPipeline, Mesh, ShadowPipeline, TerrainPipeline},
mesh::{
greedy::{self, GreedyMesh},
Meshable,
},
render::{self, ColLightInfo, FluidPipeline, Mesh, ShadowPipeline, TerrainPipeline},
};
use common::{
terrain::{Block, BlockKind},
@ -12,7 +15,16 @@ use vek::*;
type TerrainVertex = <TerrainPipeline as render::Pipeline>::Vertex;
type FluidVertex = <FluidPipeline as render::Pipeline>::Vertex;
type ShadowVertex = <ShadowPipeline as render::Pipeline>::Vertex;
#[derive(Clone, Copy, PartialEq)]
enum FaceKind {
/// Opaque face that is facing something non-opaque; either
/// water (Opaque(true)) or something else (Opaque(false)).
Opaque(bool),
/// Fluid face that is facing something non-opaque, non-tangible,
/// and non-fluid (most likely air).
Fluid,
}
trait Blendable {
fn is_blended(&self) -> bool;
@ -200,20 +212,22 @@ fn calc_light<V: RectRasterableVol<Vox = Block> + ReadVol + Debug>(
}
impl<'a, V: RectRasterableVol<Vox = Block> + ReadVol + Debug>
Meshable<'a, TerrainPipeline, FluidPipeline> for VolGrid2d<V>
Meshable<TerrainPipeline, FluidPipeline> for &'a VolGrid2d<V>
{
type Pipeline = TerrainPipeline;
type Result = (Aabb<f32>, ColLightInfo);
type ShadowPipeline = ShadowPipeline;
type Supplement = Aabb<i32>;
type Supplement = (Aabb<i32>, Vec2<u16>);
type TranslucentPipeline = FluidPipeline;
fn generate_mesh(
&'a self,
range: Self::Supplement,
self,
(range, max_texture_size): Self::Supplement,
) -> (
Mesh<Self::Pipeline>,
Mesh<Self::TranslucentPipeline>,
Mesh<Self::ShadowPipeline>,
Self::Result,
) {
let mut light = calc_light(range, self);
@ -262,7 +276,7 @@ impl<'a, V: RectRasterableVol<Vox = Block> + ReadVol + Debug>
let z = z + 1;
match flat.get((x * h * d + y * d + z) as usize).copied() {
Some(b) => b,
None => panic!("x {} y {} z {} d {} h {}"),
None => panic!("x {} y {} z {} d {} h {}", x, y, z, d, h),
}
}
};
@ -298,10 +312,10 @@ impl<'a, V: RectRasterableVol<Vox = Block> + ReadVol + Debug>
// similar z // levels together (better rendering performance)
// let mut opaque_meshes = vec![Mesh::new(); ((z_end + 1 - z_start).clamped(1,
// 60) as usize / 10).max(1)];
let mut opaque_mesh = Mesh::new();
let mut fluid_mesh = Mesh::new();
// let mut opaque_mesh = Mesh::new();
// let mut fluid_mesh = Mesh::new();
for x in 1..range.size().w - 1 {
/* for x in 1..range.size().w - 1 {
for y in 1..range.size().w - 1 {
let mut blocks = [[[None; 3]; 3]; 3];
for i in 0..3 {
@ -398,7 +412,7 @@ impl<'a, V: RectRasterableVol<Vox = Block> + ReadVol + Debug>
// + 1 - z_start).max(1)) as usize; let selected_opaque_mesh
// = &mut opaque_meshes[opaque_mesh_index]; Create mesh
// polygons
if block.map_or(false, |vox| vox.is_opaque()) {
/* if block.map_or(false, |vox| vox.is_opaque()) {
vol::push_vox_verts(
&mut opaque_mesh, //selected_opaque_mesh,
faces_to_make(&blocks, None, |vox| {
@ -425,7 +439,7 @@ impl<'a, V: RectRasterableVol<Vox = Block> + ReadVol + Debug>
},
&lights,
);
} else if block.map_or(false, |vox| vox.is_fluid()) {
} else */if block.map_or(false, |vox| vox.is_fluid()) {
vol::push_vox_verts(
&mut fluid_mesh,
// NOTE: want to skip blocks that aren't either next to air, or next to
@ -455,7 +469,7 @@ impl<'a, V: RectRasterableVol<Vox = Block> + ReadVol + Debug>
}
}
}
}
}*/
// let opaque_mesh = opaque_meshes
// .into_iter()
@ -468,286 +482,121 @@ impl<'a, V: RectRasterableVol<Vox = Block> + ReadVol + Debug>
// });
// opaque_mesh
// });
let mut shadow_mesh = Mesh::new();
let x_size = (range.size().w - 2) as usize;
let y_size = (range.size().h - 2) as usize;
let z_size = (z_end - z_start + 1) as usize;
let max_size =
guillotiere::Size::new(i32::from(max_texture_size.x), i32::from(max_texture_size.y));
let greedy_size = Vec3::new(
(range.size().w - 2) as usize,
(range.size().h - 2) as usize,
(z_end - z_start + 1) as usize,
);
let greedy_size_cross = Vec3::new(greedy_size.x - 1, greedy_size.y - 1, greedy_size.z);
let draw_delta = Vec3::new(1, 1, z_start);
let mesh_delta = Vec3::new(0, 0, z_start + range.min.z);
// x (u = y, v = z)
greedy_mesh_cross_section(
Vec3::new(y_size, z_size, x_size - 1),
|pos| {
should_draw_greedy(
Vec3::new(pos.z, pos.x, pos.y),
draw_delta,
Vec3::unit_x(), /* , pos.z, 0, x_size */
|pos| flat_get(pos),
)
},
|pos, dim, faces_forward| {
shadow_mesh.push_quad(create_quad_greedy(
Vec3::new(pos.z, pos.x, pos.y),
mesh_delta,
dim,
Vec2::new(Vec3::unit_y(), Vec3::unit_z()),
Vec3::unit_x(),
faces_forward,
));
},
);
// y (u = z, v = x)
greedy_mesh_cross_section(
Vec3::new(z_size, x_size, y_size - 1),
|pos| {
should_draw_greedy(
Vec3::new(pos.y, pos.z, pos.x),
draw_delta,
Vec3::unit_y(),
|pos| flat_get(pos),
)
},
|pos, dim, faces_forward| {
shadow_mesh.push_quad(create_quad_greedy(
Vec3::new(pos.y, pos.z, pos.x),
mesh_delta,
dim,
Vec2::new(Vec3::unit_z(), Vec3::unit_x()),
Vec3::unit_y(),
faces_forward,
));
},
);
// z (u = x, v = y)
greedy_mesh_cross_section(
Vec3::new(x_size, y_size, z_size),
|pos| {
if pos.z == 0 {
let pos = pos.map(|e| e as i32) + draw_delta; // - delta;
let to = flat_get(pos).is_opaque(); //map(|v| v.is_opaque()).unwrap_or(false);
if to { Some(false) } else { None }
} else {
should_draw_greedy(
Vec3::new(pos.x, pos.y, pos.z),
draw_delta,
Vec3::unit_z(),
|pos| flat_get(pos),
)
}
},
|pos, dim, faces_forward| {
shadow_mesh.push_quad(create_quad_greedy(
Vec3::new(pos.x, pos.y, pos.z),
mesh_delta,
dim,
Vec2::new(Vec3::unit_x(), Vec3::unit_y()),
Vec3::unit_z(),
faces_forward,
));
},
);
(opaque_mesh, fluid_mesh, shadow_mesh)
}
}
/// Use the 6 voxels/blocks surrounding the center
/// to detemine which faces should be drawn
/// Unlike the one in segments.rs this uses a provided array of blocks instead
/// of retrieving from a volume
/// blocks[z][y][x]
fn faces_to_make<M: Clone>(
blocks: &[[[Option<Block>; 3]; 3]; 3],
error_makes_face: Option<M>,
should_add: impl Fn(Block) -> Option<M>,
) -> [Option<M>; 6] {
// Faces to draw
let make_face = |opt_v: Option<Block>| {
opt_v
.map(|v| should_add(v))
.unwrap_or(error_makes_face.clone())
let get_light = |_: &mut (), pos: Vec3<i32>| light(pos + range.min);
let get_color =
|_: &mut (), pos: Vec3<i32>| flat_get(pos).get_color().unwrap_or(Rgb::zero());
let get_opacity = |_: &mut (), pos: Vec3<i32>| !flat_get(pos).is_opaque();
let should_draw = |_: &mut (), pos: Vec3<i32>, delta: Vec3<i32>, _uv| {
should_draw_greedy(pos, delta, |pos| flat_get(pos))
};
[
make_face(blocks[1][1][0]),
make_face(blocks[1][1][2]),
make_face(blocks[1][0][1]),
make_face(blocks[1][2][1]),
make_face(blocks[0][1][1]),
make_face(blocks[2][1][1]),
]
}
// Greedy meshing.
fn greedy_mesh_cross_section(
/* mask: &mut [bool], */
dims: Vec3<usize>,
// Should we draw a face here (below this vertex)? If so, is it front or back facing?
draw_face: impl Fn(Vec3<usize>) -> Option<bool>,
// Vertex, width and height, and whether it's front facing (face is implicit from the cross
// section).
mut push_quads: impl FnMut(Vec3<usize>, Vec2<usize>, bool),
) {
// mask represents which faces are either set while the other is unset, or unset
// while the other is set.
let mut mask = vec![None; dims.y * dims.x];
(0..dims.z + 1).for_each(|d| {
// Compute mask
mask.iter_mut().enumerate().for_each(|(posi, mask)| {
let i = posi % dims.x;
let j = posi / dims.x;
*mask = draw_face(Vec3::new(i, j, d));
});
(0..dims.y).for_each(|j| {
let mut i = 0;
while i < dims.x {
// Compute width (number of set x bits for this row and layer, starting at the
// current minimum column).
if let Some(ori) = mask[j * dims.x + i] {
let width = 1 + mask[j * dims.x + i + 1..j * dims.x + dims.x]
.iter()
.take_while(move |&&mask| mask == Some(ori))
.count();
let max_x = i + width;
// Compute height (number of rows having w set x bits for this layer, starting
// at the current minimum column and row).
let height = 1
+ (j + 1..dims.y)
.take_while(|h| {
mask[h * dims.x + i..h * dims.x + max_x]
.iter()
.all(|&mask| mask == Some(ori))
})
.count();
let max_y = j + height;
// Add quad.
push_quads(Vec3::new(i, j, d /* + 1 */), Vec2::new(width, height), ori);
// Unset mask bits in drawn region, so we don't try to re-draw them.
(j..max_y).for_each(|l| {
mask[l * dims.x + i..l * dims.x + max_x]
.iter_mut()
.for_each(|mask| {
*mask = None;
});
});
// Update x value.
i = max_x;
} else {
i += 1;
}
}
});
});
}
fn create_quad_greedy(
origin: Vec3<usize>,
mesh_delta: Vec3<i32>,
dim: Vec2<usize>,
uv: Vec2<Vec3<f32>>,
norm: Vec3<f32>,
faces_forward: bool,
) -> Quad<ShadowPipeline> {
let origin = (origin.map(|e| e as i32) + mesh_delta).map(|e| e as f32);
let dim = uv.map2(dim.map(|e| e as f32), |e, f| e * f);
let (dim, norm) = if faces_forward {
(dim, norm)
} else {
(Vec2::new(dim.y, dim.x), -norm)
// NOTE: Conversion to f32 is fine since this i32 is actually in bounds for u16.
// let create_shadow = |pos, norm, meta| ShadowVertex::new(pos + Vec3::new(0.0,
// 0.0, (z_start + range.min.z) as f32), norm, meta);
let mesh_delta = Vec3::new(0.0, 0.0, (z_start + range.min.z) as f32);
let create_opaque = |atlas_pos, pos, norm, meta| {
TerrainVertex::new(atlas_pos, pos + mesh_delta, norm, meta)
};
Quad::new(
ShadowVertex::new(origin, norm),
ShadowVertex::new(origin + dim.x, norm),
ShadowVertex::new(origin + dim.x + dim.y, norm),
ShadowVertex::new(origin + dim.y, norm),
let create_transparent =
|_atlas_pos, pos, norm, _meta| FluidVertex::new(pos + mesh_delta, norm);
let mut greedy = GreedyMesh::new(max_size);
let mut opaque_mesh = Mesh::new();
let mut fluid_mesh = Mesh::new();
let bounds = greedy.push(
(),
draw_delta,
greedy_size,
greedy_size_cross,
get_light,
get_color,
get_opacity,
should_draw,
|atlas_origin, dim, origin, draw_dim, norm, meta| match meta {
FaceKind::Opaque(meta) => {
opaque_mesh.push_quad(greedy::create_quad(
atlas_origin,
dim,
origin,
draw_dim,
norm,
meta,
|atlas_pos, pos, norm, &meta| create_opaque(atlas_pos, pos, norm, meta),
));
},
FaceKind::Fluid => {
fluid_mesh.push_quad(greedy::create_quad(
atlas_origin,
dim,
origin,
draw_dim,
norm,
&(),
|atlas_pos, pos, norm, &meta| {
create_transparent(atlas_pos, pos, norm, meta)
},
));
},
},
);
let bounds = bounds.map(f32::from);
let bounds = Aabb {
min: bounds.min + mesh_delta,
max: bounds.max + mesh_delta,
};
let (col_lights, col_lights_size) = greedy.finalize();
// println!("z_bounds{:?}, bounds: {:?}", (mesh_delta.z, mesh_delta.z +
(
opaque_mesh,
fluid_mesh,
Mesh::new(),
(bounds, (col_lights, col_lights_size)),
)
}
}
fn should_draw_greedy(
pos: Vec3<usize>,
draw_delta: Vec3<i32>,
pos: Vec3<i32>,
delta: Vec3<i32>,
flat_get: impl Fn(Vec3<i32>) -> Block,
) -> Option<bool> {
let pos = pos.map(|e| e as i32) + draw_delta; // - delta;
let from = flat_get(pos - delta).is_opaque(); // map(|v| v.is_opaque()).unwrap_or(false);
let to = flat_get(pos).is_opaque(); //map(|v| v.is_opaque()).unwrap_or(false);
if from == to {
) -> Option<(bool, FaceKind)> {
// TODO: Verify conversion.
// let pos = pos.map(|e| e as i32) + draw_delta; // - delta;
let from = flat_get(pos - delta); // map(|v| v.is_opaque()).unwrap_or(false);
let to = flat_get(pos); //map(|v| v.is_opaque()).unwrap_or(false);
let from_opaque = from.is_opaque();
if from_opaque == to.is_opaque() {
// Check the interface of fluid and non-tangible non-fluids (e.g. air).
let from_fluid = from.is_fluid();
if from_fluid == to.is_fluid() || from.is_tangible() || to.is_tangible() {
None
} else {
// If going from transparent to opaque, forward facing; otherwise, backward
// facing.
Some(from)
}
}
/*
impl<V: BaseVol<Vox = Block> + ReadVol + Debug> Meshable for VolGrid3d<V> {
type Pipeline = TerrainPipeline;
type Supplement = Aabb<i32>;
fn generate_mesh(&self, range: Self::Supplement) -> Mesh<Self::Pipeline> {
let mut mesh = Mesh::new();
let mut last_chunk_pos = self.pos_key(range.min);
let mut last_chunk = self.get_key(last_chunk_pos);
let size = range.max - range.min;
for x in 1..size.x - 1 {
for y in 1..size.y - 1 {
for z in 1..size.z - 1 {
let pos = Vec3::new(x, y, z);
let new_chunk_pos = self.pos_key(range.min + pos);
if last_chunk_pos != new_chunk_pos {
last_chunk = self.get_key(new_chunk_pos);
last_chunk_pos = new_chunk_pos;
}
let offs = pos.map(|e| e as f32 - 1.0);
if let Some(chunk) = last_chunk {
let chunk_pos = Self::chunk_offs(range.min + pos);
if let Some(col) = chunk.get(chunk_pos).ok().and_then(|vox| vox.get_color())
{
let col = col.map(|e| e as f32 / 255.0);
vol::push_vox_verts(
&mut mesh,
self,
range.min + pos,
offs,
col,
TerrainVertex::new,
false,
);
// While fluid is not culled, we still try to keep a consistent orientation as
// we do for land; if going from fluid to non-fluid,
// forwards-facing; otherwise, backwards-facing.
Some((from_fluid, FaceKind::Fluid))
}
} else {
if let Some(col) = self
.get(range.min + pos)
.ok()
.and_then(|vox| vox.get_color())
{
let col = col.map(|e| e as f32 / 255.0);
vol::push_vox_verts(
&mut mesh,
self,
range.min + pos,
offs,
col,
TerrainVertex::new,
false,
);
// If going from transparent to opaque, backward facing; otherwise, forward
// facing. Also, if either from or to is fluid, set the meta accordingly.
Some((
from_opaque,
FaceKind::Opaque(if from_opaque {
to.is_fluid()
} else {
from.is_fluid()
}),
))
}
}
}
}
}
mesh
}
}
*/

View File

@ -1,233 +0,0 @@
use vek::*;
use crate::render::{
mesh::{Mesh, Quad},
Pipeline,
};
/// Given volume, position, and cardinal directions, compute each vertex's AO
/// value. `dirs` should be a slice of length 5 so that the sliding window of
/// size 2 over the slice yields each vertex' adjacent positions.
#[allow(unsafe_code)]
fn get_ao_quad(
shift: Vec3<i32>,
dirs: &[Vec3<i32>],
darknesses: &[[[Option<f32>; 3]; 3]; 3],
) -> Vec4<(f32, f32)> {
dirs.windows(2)
.map(|offs| {
let vox_opaque = |pos: Vec3<i32>| {
let pos = (pos + 1).map(|e| e as usize);
darknesses[pos.z][pos.y][pos.x].is_none()
};
let (s1, s2) = (
vox_opaque(shift + offs[0]),
vox_opaque(shift + offs[1]),
/*
vol.get(pos + shift + offs[0])
.map(&is_opaque)
.unwrap_or(false),
vol.get(pos + shift + offs[1])
.map(&is_opaque)
.unwrap_or(false),
*/
);
let mut darkness = 0.0;
let mut total = 0.0f32;
for x in 0..2 {
for y in 0..2 {
let dark_pos = shift + offs[0] * x + offs[1] * y + 1;
if let Some(dark) =
darknesses[dark_pos.z as usize][dark_pos.y as usize][dark_pos.x as usize]
{
darkness += dark;
total += 1.0;
}
}
}
let darkness = darkness / total.max(1.0);
(
darkness,
if s1 && s2 {
0.0
} else {
let corner = vox_opaque(shift + offs[0] + offs[1]);
// Map both 1 and 2 neighbors to 0.5 occlusion.
if s1 || s2 || corner { 0.4 } else { 1.0 }
},
)
})
.collect::<Vec4<(f32, f32)>>()
}
#[allow(unsafe_code)]
fn get_col_quad(dirs: &[Vec3<i32>], cols: &[[[Rgba<u8>; 3]; 3]; 3]) -> Vec4<Rgb<f32>> {
dirs.windows(2)
.map(|offs| {
let primary_col = Rgb::from(cols[1][1][1]).map(|e: u8| e as f32);
let mut color = Rgb::zero();
let mut total = 0.0;
for x in 0..2 {
for y in 0..2 {
let col_pos = offs[0] * x + offs[1] * y + 1;
let col = unsafe {
cols.get_unchecked(col_pos.z as usize)
.get_unchecked(col_pos.y as usize)
.get_unchecked(col_pos.x as usize)
};
if col.a > 0 {
let col = Rgb::new(col.r, col.g, col.b).map(|e| e as f32);
if Vec3::<f32>::from(primary_col).distance_squared(Vec3::from(col))
< (0.025f32 * 256.0).powf(2.0)
{
color += col;
total += 256.0;
}
}
}
}
color / total
})
.collect()
}
// Utility function
fn create_quad<P: Pipeline, M, F: Fn(Vec3<f32>, Vec3<f32>, Rgb<f32>, f32, f32, &M) -> P::Vertex>(
origin: Vec3<f32>,
unit_x: Vec3<f32>,
unit_y: Vec3<f32>,
norm: Vec3<f32>,
cols: Vec4<Rgb<f32>>,
darkness_ao: Vec4<(f32, f32)>,
meta: &M,
vcons: &F,
) -> Quad<P> {
let darkness = darkness_ao.map(|e| e.0);
let ao = darkness_ao.map(|e| e.1);
let ao_map = ao;
if ao[0].min(ao[2]) < ao[1].min(ao[3]) {
Quad::new(
vcons(origin + unit_y, norm, cols[3], darkness[3], ao_map[3], meta),
vcons(origin, norm, cols[0], darkness[0], ao_map[0], meta),
vcons(origin + unit_x, norm, cols[1], darkness[1], ao_map[1], meta),
vcons(
origin + unit_x + unit_y,
norm,
cols[2],
darkness[2],
ao_map[2],
meta,
),
)
} else {
Quad::new(
vcons(origin, norm, cols[0], darkness[0], ao_map[0], meta),
vcons(origin + unit_x, norm, cols[1], darkness[1], ao_map[1], meta),
vcons(
origin + unit_x + unit_y,
norm,
cols[2],
darkness[2],
ao_map[2],
meta,
),
vcons(origin + unit_y, norm, cols[3], darkness[3], ao_map[3], meta),
)
}
}
pub fn push_vox_verts<P: Pipeline, M>(
mesh: &mut Mesh<P>,
faces: [Option<M>; 6],
offs: Vec3<f32>,
cols: &[[[Rgba<u8>; 3]; 3]; 3],
vcons: impl Fn(Vec3<f32>, Vec3<f32>, Rgb<f32>, f32, f32, &M) -> P::Vertex,
darknesses: &[[[Option<f32>; 3]; 3]; 3],
) {
let (x, y, z) = (Vec3::unit_x(), Vec3::unit_y(), Vec3::unit_z());
// -x
if let Some(meta) = &faces[0] {
mesh.push_quad(create_quad(
offs,
Vec3::unit_z(),
Vec3::unit_y(),
-Vec3::unit_x(),
get_col_quad(&[-z, -y, z, y, -z], cols),
get_ao_quad(-Vec3::unit_x(), &[-z, -y, z, y, -z], darknesses),
meta,
&vcons,
));
}
// +x
if let Some(meta) = &faces[1] {
mesh.push_quad(create_quad(
offs + Vec3::unit_x(),
Vec3::unit_y(),
Vec3::unit_z(),
Vec3::unit_x(),
get_col_quad(&[-y, -z, y, z, -y], cols),
get_ao_quad(Vec3::unit_x(), &[-y, -z, y, z, -y], darknesses),
meta,
&vcons,
));
}
// -y
if let Some(meta) = &faces[2] {
mesh.push_quad(create_quad(
offs,
Vec3::unit_x(),
Vec3::unit_z(),
-Vec3::unit_y(),
get_col_quad(&[-x, -z, x, z, -x], cols),
get_ao_quad(-Vec3::unit_y(), &[-x, -z, x, z, -x], darknesses),
meta,
&vcons,
));
}
// +y
if let Some(meta) = &faces[3] {
mesh.push_quad(create_quad(
offs + Vec3::unit_y(),
Vec3::unit_z(),
Vec3::unit_x(),
Vec3::unit_y(),
get_col_quad(&[-z, -x, z, x, -z], cols),
get_ao_quad(Vec3::unit_y(), &[-z, -x, z, x, -z], darknesses),
meta,
&vcons,
));
}
// -z
if let Some(meta) = &faces[4] {
mesh.push_quad(create_quad(
offs,
Vec3::unit_y(),
Vec3::unit_x(),
-Vec3::unit_z(),
get_col_quad(&[-y, -x, y, x, -y], cols),
get_ao_quad(-Vec3::unit_z(), &[-y, -x, y, x, -y], darknesses),
meta,
&vcons,
));
}
// +z
if let Some(meta) = &faces[5] {
mesh.push_quad(create_quad(
offs + Vec3::unit_z(),
Vec3::unit_x(),
Vec3::unit_y(),
Vec3::unit_z(),
get_col_quad(&[-x, -y, x, y, -x], cols),
get_ao_quad(Vec3::unit_z(), &[-x, -y, x, y, -x], darknesses),
meta,
&vcons,
));
}
}

View File

@ -17,14 +17,24 @@ impl<T: Copy + gfx::traits::Pod> Consts<T> {
}
}
/* /// Create a new immutable `Const<T>`.
pub fn new_immutable(factory: &mut gfx_backend::Factory, data: &[T]) -> Result<gfx::handle::RawBuffer<T>, RenderError> {
Ok(Self {
ibuf: factory
.create_buffer_immutable_raw(gfx::memory::cast_slice(data), core::mem::size_of::<T>(), gfx::buffer::Role::Constant, gfx::memory::Bind::empty())
.map_err(|err| RenderError::BufferCreationError(err))?,
})
} */
/// Update the GPU-side value represented by this constant handle.
pub fn update(
&mut self,
encoder: &mut gfx::Encoder<gfx_backend::Resources, gfx_backend::CommandBuffer>,
vals: &[T],
offset: usize,
) -> Result<(), RenderError> {
encoder
.update_buffer(&self.buf, vals, 0)
.update_buffer(&self.buf, vals, offset)
.map_err(|err| RenderError::UpdateError(err))
}
}

View File

@ -4,6 +4,7 @@ use std::iter::FromIterator;
/// A `Vec`-based mesh structure used to store mesh data on the CPU.
pub struct Mesh<P: Pipeline> {
verts: Vec<P::Vertex>,
// textures: Vec<>
}
impl<P: Pipeline> Clone for Mesh<P>

View File

@ -16,7 +16,10 @@ pub use self::{
mesh::{Mesh, Quad, Tri},
model::{DynamicModel, Model},
pipelines::{
figure::{BoneData as FigureBoneData, FigurePipeline, Locals as FigureLocals},
figure::{
BoneData as FigureBoneData, BoneMeshes, FigureModel, FigurePipeline,
Locals as FigureLocals,
},
fluid::FluidPipeline,
lod_terrain::{Locals as LodTerrainLocals, LodTerrainPipeline},
postprocess::{
@ -24,7 +27,7 @@ pub use self::{
},
shadow::{Locals as ShadowLocals, ShadowPipeline},
skybox::{create_mesh as create_skybox_mesh, Locals as SkyboxLocals, SkyboxPipeline},
sprite::{Instance as SpriteInstance, SpritePipeline},
sprite::{Instance as SpriteInstance, Locals as SpriteLocals, SpritePipeline},
terrain::{Locals as TerrainLocals, TerrainPipeline},
ui::{
create_quad as create_ui_quad, create_tri as create_ui_tri, Locals as UiLocals,
@ -33,8 +36,8 @@ pub use self::{
Globals, Light, Shadow,
},
renderer::{
LodColorFmt, LodTextureFmt, Renderer, ShadowDepthStencilFmt, TgtColorFmt,
TgtDepthStencilFmt, WinColorFmt, WinDepthFmt,
ColLightFmt, ColLightInfo, LodColorFmt, LodTextureFmt, Renderer, ShadowDepthStencilFmt,
TgtColorFmt, TgtDepthStencilFmt, WinColorFmt, WinDepthFmt,
},
texture::Texture,
};
@ -72,6 +75,10 @@ pub enum AaMode {
SsaaX4,
}
impl Default for AaMode {
fn default() -> Self { AaMode::Fxaa }
}
/// Cloud modes
#[derive(PartialEq, Eq, Clone, Copy, Debug, Serialize, Deserialize)]
pub enum CloudMode {
@ -79,6 +86,10 @@ pub enum CloudMode {
Regular,
}
impl Default for CloudMode {
fn default() -> Self { CloudMode::Regular }
}
/// Fluid modes
#[derive(PartialEq, Eq, Clone, Copy, Debug, Serialize, Deserialize)]
pub enum FluidMode {
@ -86,6 +97,10 @@ pub enum FluidMode {
Shiny,
}
impl Default for FluidMode {
fn default() -> Self { FluidMode::Shiny }
}
/// Lighting modes
#[derive(PartialEq, Eq, Clone, Copy, Debug, Serialize, Deserialize)]
pub enum LightingMode {
@ -93,3 +108,30 @@ pub enum LightingMode {
BlinnPhong,
Lambertian,
}
impl Default for LightingMode {
fn default() -> Self { LightingMode::BlinnPhong }
}
/// Shadow modes
#[derive(PartialEq, Eq, Clone, Copy, Debug, Serialize, Deserialize)]
pub enum ShadowMode {
None,
Cheap,
/// Multiple of resolution.
Map, /* (f32) */
}
impl Default for ShadowMode {
fn default() -> Self { ShadowMode::Cheap }
}
/// Render modes
#[derive(PartialEq, Eq, Clone, Copy, Debug, Default, Serialize, Deserialize)]
pub struct RenderMode {
pub aa: AaMode,
pub cloud: CloudMode,
pub fluid: FluidMode,
pub lighting: LightingMode,
pub shadow: ShadowMode,
}

View File

@ -1,11 +1,14 @@
use super::{
super::{util::arr_to_mat, Pipeline, TgtColorFmt, TgtDepthStencilFmt},
Globals, Light, Shadow,
super::{
util::arr_to_mat, ColLightFmt, Mesh, Model, Pipeline, TerrainPipeline, Texture,
TgtColorFmt, TgtDepthStencilFmt,
},
shadow, Globals, Light, Shadow,
};
use crate::mesh::greedy::GreedyMesh;
use gfx::{
self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta, gfx_pipeline,
gfx_pipeline_inner, gfx_vertex_struct_meta,
state::{ColorMask, Comparison, Stencil, StencilOp},
gfx_pipeline_inner, gfx_vertex_struct_meta, state::ColorMask,
};
use vek::*;
@ -22,15 +25,21 @@ gfx_defines! {
constant Locals {
model_mat: [[f32; 4]; 4] = "model_mat",
model_col: [f32; 4] = "model_col",
atlas_offs: [i32; 4] = "atlas_offs",
model_pos: [f32; 3] = "model_pos",
flags: u32 = "flags",
}
constant BoneData {
bone_mat: [[f32; 4]; 4] = "bone_mat",
normals_mat: [[f32; 4]; 4] = "normals_mat",
}
pipeline pipe {
vbuf: gfx::VertexBuffer<Vertex> = (),
// vbuf: gfx::VertexBuffer<Vertex> = (),
vbuf: gfx::VertexBuffer<<TerrainPipeline as Pipeline>::Vertex> = (),
// abuf: gfx::VertexBuffer<<TerrainPipeline as Pipeline>::Vertex> = (),
col_lights: gfx::TextureSampler<[f32; 4]> = "t_col_light",
locals: gfx::ConstantBuffer<Locals> = "u_locals",
globals: gfx::ConstantBuffer<Globals> = "u_globals",
@ -38,15 +47,20 @@ gfx_defines! {
lights: gfx::ConstantBuffer<Light> = "u_lights",
shadows: gfx::ConstantBuffer<Shadow> = "u_shadows",
shadow_maps: gfx::TextureSampler<f32> = "t_shadow_maps",
point_shadow_maps: gfx::TextureSampler<f32> = "t_point_shadow_maps",
directed_shadow_maps: gfx::TextureSampler<f32> = "t_directed_shadow_maps",
map: gfx::TextureSampler<[f32; 4]> = "t_map",
horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon",
noise: gfx::TextureSampler<f32> = "t_noise",
// Shadow stuff
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::DepthStencilTarget<TgtDepthStencilFmt> = (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff,(StencilOp::Keep,StencilOp::Keep,StencilOp::Replace))),
tgt_depth_stencil: gfx::DepthTarget<TgtDepthStencilFmt> = gfx::preset::depth::LESS_EQUAL_WRITE,
// tgt_depth_stencil: gfx::DepthStencilTarget<TgtDepthStencilFmt> = (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff,(StencilOp::Keep,StencilOp::Keep,StencilOp::Replace))),
}
}
@ -80,30 +94,49 @@ impl Vertex {
}
impl Locals {
pub fn new(model_mat: Mat4<f32>, col: Rgba<f32>, is_player: bool) -> Self {
pub fn new(
model_mat: Mat4<f32>,
col: Rgba<f32>,
pos: Vec3<f32>,
atlas_offs: Vec2<i32>,
is_player: bool,
) -> Self {
let mut flags = 0;
flags |= is_player as u32;
Self {
model_mat: arr_to_mat(model_mat.into_col_array()),
model_col: col.into_array(),
model_pos: pos.into_array(),
atlas_offs: Vec4::from(atlas_offs).into_array(),
flags,
}
}
}
impl Default for Locals {
fn default() -> Self { Self::new(Mat4::identity(), Rgba::broadcast(1.0), false) }
fn default() -> Self {
Self::new(
Mat4::identity(),
Rgba::broadcast(1.0),
Vec3::default(),
Vec2::default(),
false,
)
}
}
impl BoneData {
pub fn new(bone_mat: Mat4<f32>) -> Self {
pub fn new(bone_mat: Mat4<f32>, normals_mat: Mat4<f32>) -> Self {
Self {
bone_mat: arr_to_mat(bone_mat.into_col_array()),
normals_mat: arr_to_mat(normals_mat.into_col_array()),
}
}
}
pub fn default() -> Self { Self::new(Mat4::identity()) }
impl Default for BoneData {
fn default() -> Self { Self::new(Mat4::identity(), Mat4::identity()) }
}
pub struct FigurePipeline;
@ -111,3 +144,30 @@ pub struct FigurePipeline;
impl Pipeline for FigurePipeline {
type Vertex = Vertex;
}
pub struct FigureModel {
pub bounds: Aabb<f32>,
pub opaque: Model<TerrainPipeline>,
// pub shadow: Model<ShadowPipeline>,
// TODO: Consider using mipmaps instead of storing multiple texture atlases for different LOD
// levels.
pub col_lights: Texture<ColLightFmt>,
pub allocation: guillotiere::Allocation,
}
impl FigureModel {
/// Start a greedy mesh designed for figure bones.
pub fn make_greedy<'a>() -> GreedyMesh<'a> {
// NOTE: Required because we steal two bits from the normal in the shadow uint
// in order to store the bone index. The two bits are instead taken out
// of the atlas coordinates, which is why we "only" allow 1 << 15 per
// coordinate instead of 1 << 16.
let max_size = guillotiere::Size::new(1 << 15 - 1, 1 << 15 - 1);
GreedyMesh::new(max_size)
}
}
pub type BoneMeshes = (
Mesh</* FigurePipeline */ TerrainPipeline>, /* , Mesh<ShadowPipeline> */
Aabb<f32>,
);

View File

@ -1,19 +1,17 @@
use super::{
super::{Pipeline, TerrainLocals, TgtColorFmt, TgtDepthStencilFmt},
Globals, Light, Shadow,
shadow, Globals, Light, Shadow,
};
use gfx::{
self, gfx_defines, gfx_impl_struct_meta, gfx_pipeline, gfx_pipeline_inner,
gfx_vertex_struct_meta,
state::{ColorMask, Comparison, Stencil, StencilOp},
gfx_vertex_struct_meta, state::ColorMask,
};
use std::ops::Mul;
use vek::*;
gfx_defines! {
vertex Vertex {
pos_norm: u32 = "v_pos_norm",
col_light: u32 = "v_col_light",
// col_light: u32 = "v_col_light",
}
pipeline pipe {
@ -24,7 +22,8 @@ gfx_defines! {
lights: gfx::ConstantBuffer<Light> = "u_lights",
shadows: gfx::ConstantBuffer<Shadow> = "u_shadows",
shadow_maps: gfx::TextureSampler<f32> = "t_shadow_maps",
point_shadow_maps: gfx::TextureSampler<f32> = "t_point_shadow_maps",
directed_shadow_maps: gfx::TextureSampler<f32> = "t_directed_shadow_maps",
map: gfx::TextureSampler<[f32; 4]> = "t_map",
horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon",
@ -32,13 +31,17 @@ gfx_defines! {
noise: gfx::TextureSampler<f32> = "t_noise",
waves: gfx::TextureSampler<[f32; 4]> = "t_waves",
// Shadow stuff
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::DepthStencilTarget<TgtDepthStencilFmt> = (gfx::preset::depth::LESS_EQUAL_TEST,Stencil::new(Comparison::Always,0xff,(StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))),
tgt_depth_stencil: gfx::DepthTarget<TgtDepthStencilFmt> = gfx::preset::depth::LESS_EQUAL_TEST,
// tgt_depth_stencil: gfx::DepthStencilTarget<TgtDepthStencilFmt> = (gfx::preset::depth::LESS_EQUAL_TEST,Stencil::new(Comparison::Always,0xff,(StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))),
}
}
impl Vertex {
pub fn new(pos: Vec3<f32>, norm: Vec3<f32>, col: Rgb<f32>, light: f32, _opac: f32) -> Self {
/* pub fn new(pos: Vec3<f32>, norm: Vec3<f32>, col: Rgb<f32>, light: f32, _opac: f32) -> Self {
let (norm_axis, norm_dir) = norm
.as_slice()
.into_iter()
@ -62,6 +65,31 @@ impl Vertex {
| ((light.mul(255.0) as u32) & 0xFF) << 0,
//| ((opac.mul(0.4) as u32) & 0xFF) << 0,
}
} */
pub fn new(pos: Vec3<f32>, norm: Vec3<f32>) -> Self {
let (norm_axis, norm_dir) = norm
.as_slice()
.into_iter()
.enumerate()
.find(|(_i, e)| **e != 0.0)
.unwrap_or((0, &1.0));
let norm_bits = ((norm_axis << 1) | if *norm_dir > 0.0 { 1 } else { 0 }) as u32;
const EXTRA_NEG_Z: f32 = 65536.0;
Self {
pos_norm: 0
| ((pos.x as u32) & 0x003F) << 0
| ((pos.y as u32) & 0x003F) << 6
| (((pos.z + EXTRA_NEG_Z).max(0.0).min((1 << 17) as f32) as u32) & 0x1FFFF) << 12
| (norm_bits & 0x7) << 29,
/* col_light: 0
| ((col.r.mul(200.0) as u32) & 0xFF) << 8
| ((col.g.mul(200.0) as u32) & 0xFF) << 16
| ((col.b.mul(200.0) as u32) & 0xFF) << 24
| ((light.mul(255.0) as u32) & 0xFF) << 0,
//| ((opac.mul(0.4) as u32) & 0xFF) << 0, */
}
}
}

View File

@ -5,7 +5,6 @@ use super::{
use gfx::{
self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta, gfx_pipeline,
gfx_pipeline_inner, gfx_vertex_struct_meta,
state::{Comparison, Stencil, StencilOp},
};
use vek::*;
@ -29,7 +28,8 @@ gfx_defines! {
noise: gfx::TextureSampler<f32> = "t_noise",
tgt_color: gfx::RenderTarget<TgtColorFmt> = "tgt_color",
tgt_depth_stencil: gfx::DepthStencilTarget<TgtDepthStencilFmt> = (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff,(StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))),
tgt_depth_stencil: gfx::DepthTarget<TgtDepthStencilFmt> = gfx::preset::depth::LESS_EQUAL_WRITE,
// tgt_depth_stencil: gfx::DepthStencilTarget<TgtDepthStencilFmt> = (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff,(StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))),
}
}

View File

@ -14,7 +14,7 @@ use common::terrain::BlockKind;
use gfx::{self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta};
use vek::*;
pub const MAX_POINT_LIGHT_COUNT: usize = 32;
pub const MAX_POINT_LIGHT_COUNT: usize = 31;
pub const MAX_FIGURE_SHADOW_COUNT: usize = 24;
pub const MAX_DIRECTED_LIGHT_COUNT: usize = 6;
@ -24,6 +24,7 @@ gfx_defines! {
proj_mat: [[f32; 4]; 4] = "proj_mat",
all_mat: [[f32; 4]; 4] = "all_mat",
cam_pos: [f32; 4] = "cam_pos",
focus_off: [f32; 4] = "focus_off",
focus_pos: [f32; 4] = "focus_pos",
/// NOTE: max_intensity is computed as the ratio between the brightest and least bright
/// intensities among all lights in the scene.
@ -36,6 +37,8 @@ gfx_defines! {
/// TODO: Fix whatever alignment issue requires these uniforms to be aligned.
view_distance: [f32; 4] = "view_distance",
time_of_day: [f32; 4] = "time_of_day", // TODO: Make this f64.
sun_dir: [f32; 4] = "sun_dir",
moon_dir: [f32; 4] = "moon_dir",
tick: [f32; 4] = "tick",
/// x, y represent the resolution of the screen;
/// w, z represent the near and far planes of the shadow map.
@ -83,14 +86,24 @@ impl Globals {
cam_mode: CameraMode,
sprite_render_distance: f32,
) -> Self {
// Transform to left-handed homogeneous coordinates.
let proj_mat_lh = proj_mat;
// proj_mat_lh[(2, 2)] = -proj_mat[(2, 2)];
// proj_mat_lh[(3, 2)] = -proj_mat[(3, 2)];
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()),
all_mat: arr_to_mat(
((proj_mat_lh * view_mat)/* .scaled_3d(Vec3::new(0.0, 0.0, -1.0)) */)
.into_col_array(),
),
cam_pos: Vec4::from(cam_pos).into_array(),
focus_pos: Vec4::from(focus_pos).into_array(),
focus_off: Vec4::from(focus_pos).map(|e: f32| e.trunc()).into_array(),
focus_pos: Vec4::from(focus_pos).map(|e: f32| e.fract()).into_array(),
view_distance: [view_distance, tgt_detail, map_bounds.x, map_bounds.y],
time_of_day: [time_of_day as f32; 4],
sun_dir: Vec4::from_direction(Self::get_sun_dir(time_of_day)).into_array(),
moon_dir: Vec4::from_direction(Self::get_moon_dir(time_of_day)).into_array(),
tick: [tick as f32; 4],
// Provide the shadow map far plane as well.
screen_res: [
@ -100,9 +113,9 @@ impl Globals {
shadow_planes.y,
],
light_shadow_count: [
(light_count % MAX_POINT_LIGHT_COUNT) as u32,
(shadow_count % MAX_FIGURE_SHADOW_COUNT) as u32,
(directed_light_count % MAX_DIRECTED_LIGHT_COUNT) as u32,
(light_count % (MAX_POINT_LIGHT_COUNT + 1)) as u32,
(shadow_count % (MAX_FIGURE_SHADOW_COUNT + 1)) as u32,
(directed_light_count % (MAX_DIRECTED_LIGHT_COUNT + 1)) as u32,
0,
],
shadow_proj_factors: [
@ -121,6 +134,21 @@ impl Globals {
sprite_render_distance,
}
}
fn get_angle_rad(time_of_day: f64) -> f32 {
const TIME_FACTOR: f32 = (std::f32::consts::PI * 2.0) / (3600.0 * 24.0);
time_of_day as f32 * TIME_FACTOR
}
pub fn get_sun_dir(time_of_day: f64) -> Vec3<f32> {
let angle_rad = Self::get_angle_rad(time_of_day);
Vec3::new(angle_rad.sin(), 0.0, angle_rad.cos())
}
pub fn get_moon_dir(time_of_day: f64) -> Vec3<f32> {
let angle_rad = Self::get_angle_rad(time_of_day);
-Vec3::new(angle_rad.sin(), 0.0, angle_rad.cos() - 0.5)
}
}
impl Default for Globals {

View File

@ -1,6 +1,9 @@
use super::{
super::{util::arr_to_mat, Pipeline, ShadowDepthStencilFmt, TerrainLocals},
Globals, Light, Shadow,
super::{
util::arr_to_mat, ColLightFmt, ColLightInfo, Pipeline, RenderError, Renderer,
ShadowDepthStencilFmt, TerrainLocals, Texture,
},
figure, terrain, Globals,
};
use gfx::{
self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta, gfx_pipeline,
@ -13,35 +16,70 @@ gfx_defines! {
// pos: [f32; 4] = "v_pos",
pos_norm: u32 = "v_pos_norm",
// col_light: u32 = "v_col_light",
// atlas_pos: u32 = "v_atlas_pos",
}
constant Locals {
shadow_matrices: [[f32; 4]; 4] = "shadowMatrices",
texture_mats: [[f32; 4]; 4] = "texture_mat",
}
pipeline pipe {
// Terrain vertex stuff
vbuf: gfx::VertexBuffer<Vertex> = (),
vbuf: gfx::VertexBuffer</*Vertex*/terrain::Vertex> = (),
locals: gfx::ConstantBuffer<TerrainLocals> = "u_locals",
globals: gfx::ConstantBuffer<Globals> = "u_globals",
lights: gfx::ConstantBuffer<Light> = "u_lights",
shadows: gfx::ConstantBuffer<Shadow> = "u_shadows",
// lights: gfx::ConstantBuffer<Light> = "u_lights",
// shadows: gfx::ConstantBuffer<Shadow> = "u_shadows",
map: gfx::TextureSampler<[f32; 4]> = "t_map",
horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon",
// map: gfx::TextureSampler<[f32; 4]> = "t_map",
// horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon",
noise: gfx::TextureSampler<f32> = "t_noise",
// noise: gfx::TextureSampler<f32> = "t_noise",
// Shadow stuff
light_shadows: gfx::ConstantBuffer<Locals> = "u_light_shadows",
tgt_depth_stencil: gfx::DepthTarget<ShadowDepthStencilFmt> = gfx::preset::depth::LESS_EQUAL_WRITE,//,Stencil::new(Comparison::Always,0xff,(StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))),
tgt_depth_stencil: gfx::DepthTarget<ShadowDepthStencilFmt> = gfx::state::Depth {
fun: gfx::state::Comparison::Less,
write: true,
},
// tgt_depth_stencil: gfx::DepthTarget<ShadowDepthStencilFmt> = gfx::preset::depth::LESS_EQUAL_WRITE,//,Stencil::new(Comparison::Always,0xff,(StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))),
}
pipeline figure_pipe {
// Terrain vertex stuff
vbuf: gfx::VertexBuffer</*Vertex*/terrain::Vertex> = (),
locals: gfx::ConstantBuffer<figure::Locals> = "u_locals",
bones: gfx::ConstantBuffer<figure::BoneData> = "u_bones",
globals: gfx::ConstantBuffer<Globals> = "u_globals",
// lights: gfx::ConstantBuffer<Light> = "u_lights",
// shadows: gfx::ConstantBuffer<Shadow> = "u_shadows",
// map: gfx::TextureSampler<[f32; 4]> = "t_map",
// horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon",
// noise: gfx::TextureSampler<f32> = "t_noise",
// Shadow stuff
light_shadows: gfx::ConstantBuffer<Locals> = "u_light_shadows",
tgt_depth_stencil: gfx::DepthTarget<ShadowDepthStencilFmt> = gfx::state::Depth {
fun: gfx::state::Comparison::Less,
write: true,
},
// tgt_depth_stencil: gfx::DepthTarget<ShadowDepthStencilFmt> = gfx::preset::depth::LESS_WRITE,//,Stencil::new(Comparison::Always,0xff,(StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))),
}
}
impl Vertex {
pub fn new(pos: Vec3<f32>, norm: Vec3<f32>) -> Self {
pub fn new(
pos: Vec3<f32>,
norm: Vec3<f32>,
meta: bool, /* , atlas_pos: Vec2<u16> */
) -> Self {
let norm_bits = if norm.x != 0.0 {
if norm.x < 0.0 { 0 } else { 1 }
} else if norm.y != 0.0 {
@ -52,7 +90,7 @@ impl Vertex {
// let ao = 0xFFu32;
// let light = 0xFFu32;
// let col = Rgb::new(1.0f32, 0.0, 0.0);
let meta = true;
// let meta = true;
const EXTRA_NEG_Z: f32 = 32768.0;
@ -63,6 +101,9 @@ impl Vertex {
| (((pos + EXTRA_NEG_Z).z.max(0.0).min((1 << 16) as f32) as u32) & 0xFFFF) << 12
| if meta { 1 } else { 0 } << 28
| (norm_bits & 0x7) << 29,
/* atlas_pos: 0
| ((atlas_pos.x as u32) & 0xFFFF) << 0
| ((atlas_pos.y as u32) & 0xFFFF) << 16, */
/* col_light: 0
| (((col.r * 255.0) as u32) & 0xFF) << 8
| (((col.g * 255.0) as u32) & 0xFF) << 16
@ -71,20 +112,73 @@ impl Vertex {
| ((light >> 2) & 0x3F) << 0, */
}
}
pub fn new_figure(
pos: Vec3<f32>,
norm: Vec3<f32>,
/* col: Rgb<f32>, ao: f32, */ bone_idx: u8,
) -> Self {
let norm_bits = if norm.x.min(norm.y).min(norm.z) < 0.0 {
0
} else {
1
};
Self {
pos_norm: pos
.map2(Vec3::new(0, 9, 18), |e, shift| {
(((e * 2.0 + 256.0) as u32) & 0x1FF) << shift
})
.reduce_bitor()
| (((bone_idx & 0xF) as u32) << 27)
| (norm_bits << 31),
// col: col
// .map2(Rgb::new(0, 8, 16), |e, shift| ((e * 255.0) as u32) << shift)
// .reduce_bitor(),
// ao_bone: (bone_idx << 2) | ((ao * 3.9999) as u8),
}
}
pub fn with_bone_idx(self, bone_idx: u8) -> Self {
Self {
pos_norm: (self.pos_norm & !(0xF << 27)) | ((bone_idx as u32 & 0xF) << 27),
}
}
}
impl Locals {
pub fn new(shadow_mat: Mat4<f32>) -> Self {
pub fn new(shadow_mat: Mat4<f32>, texture_mat: Mat4<f32>) -> Self {
Self {
shadow_matrices: arr_to_mat(shadow_mat.into_col_array()),
texture_mats: arr_to_mat(texture_mat.into_col_array()),
}
}
pub fn default() -> Self { Self::new(Mat4::identity()) }
pub fn default() -> Self { Self::new(Mat4::identity(), Mat4::identity()) }
}
pub struct ShadowPipeline;
impl ShadowPipeline {
pub fn create_col_lights(
renderer: &mut Renderer,
(col_lights, col_lights_size): ColLightInfo,
) -> Result<Texture<ColLightFmt>, RenderError> {
renderer.create_texture_immutable_raw(
gfx::texture::Kind::D2(
col_lights_size.x,
col_lights_size.y,
gfx::texture::AaMode::Single,
),
gfx::texture::Mipmap::Provided,
&[&col_lights /* .raw_pixels() */],
gfx::texture::SamplerInfo::new(
gfx::texture::FilterMethod::Bilinear,
gfx::texture::WrapMode::Clamp,
),
)
}
}
impl Pipeline for ShadowPipeline {
type Vertex = Vertex;
}

View File

@ -5,7 +5,6 @@ use super::{
use gfx::{
self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta, gfx_pipeline,
gfx_pipeline_inner, gfx_vertex_struct_meta,
state::{Comparison, Stencil, StencilOp},
};
gfx_defines! {
@ -29,7 +28,9 @@ gfx_defines! {
noise: gfx::TextureSampler<f32> = "t_noise",
tgt_color: gfx::RenderTarget<TgtColorFmt> = "tgt_color",
tgt_depth_stencil: gfx::DepthStencilTarget<TgtDepthStencilFmt> = (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff,(StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))),
tgt_depth_stencil: gfx::DepthTarget<TgtDepthStencilFmt> = gfx::preset::depth::LESS_EQUAL_TEST,
// tgt_depth_stencil: gfx::DepthTarget<TgtDepthStencilFmt> = gfx::preset::depth::LESS_EQUAL_WRITE,
// tgt_depth_stencil: gfx::DepthStencilTarget<TgtDepthStencilFmt> = (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff,(StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))),
}
}

View File

@ -1,56 +1,104 @@
use super::{
super::{util::arr_to_mat, Pipeline, TgtColorFmt, TgtDepthStencilFmt},
Globals, Light, Shadow,
shadow, terrain, Globals, Light, Shadow,
};
use core::fmt;
use gfx::{
self, gfx_defines, gfx_impl_struct_meta, gfx_pipeline, gfx_pipeline_inner,
gfx_vertex_struct_meta,
state::{ColorMask, Comparison, Stencil, StencilOp},
self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta, gfx_pipeline,
gfx_pipeline_inner, gfx_vertex_struct_meta, state::ColorMask,
};
use vek::*;
gfx_defines! {
vertex Vertex {
pos: [f32; 3] = "v_pos",
// pos_norm: u32 = "v_pos_norm",
// Because we try to restrict terrain sprite data to a 128×128 block
// we need an offset into the texture atlas.
atlas_pos: u32 = "v_atlas_pos",
// ____BBBBBBBBGGGGGGGGRRRRRRRR
col: u32 = "v_col",
// col: u32 = "v_col",
// ...AANNN
// A = AO
// N = Normal
norm_ao: u32 = "v_norm_ao",
}
vertex Instance {
constant Locals {
// Each matrix performs rotatation, translation, and scaling, relative to the sprite
// origin, for all sprite instances. The matrix will be in an array indexed by the
// sprite instance's orientation (0 through 7).
mat: [[f32; 4]; 4] = "mat",
wind_sway: [f32; 4] = "wind_sway",
offs: [f32; 4] = "offs",
}
vertex/*constant*/ Instance {
// Terrain block position and orientation
pos_ori: u32 = "inst_pos_ori",
inst_mat0: [f32; 4] = "inst_mat0",
inst_mat1: [f32; 4] = "inst_mat1",
inst_mat2: [f32; 4] = "inst_mat2",
inst_mat3: [f32; 4] = "inst_mat3",
inst_col: [f32; 3] = "inst_col",
// inst_mat: [[f32; 4]; 4] = "inst_mat",
// inst_col: [f32; 3] = "inst_col",
inst_wind_sway: f32 = "inst_wind_sway",
}
pipeline pipe {
vbuf: gfx::VertexBuffer<Vertex> = (),
ibuf: gfx::InstanceBuffer<Instance> = (),
// ibuf: gfx::/*handle::RawBuffer*/ConstantBuffer<Instance> = "u_ibuf",
col_lights: gfx::TextureSampler<[f32; 4]> = "t_col_light",
locals: gfx::ConstantBuffer<Locals> = "u_locals",
// A sprite instance is a cross between a sprite and a terrain chunk.
terrain_locals: gfx::ConstantBuffer<terrain::Locals> = "u_terrain_locals",
// locals: gfx::ConstantBuffer<terrain::Locals> = "u_locals",
globals: gfx::ConstantBuffer<Globals> = "u_globals",
lights: gfx::ConstantBuffer<Light> = "u_lights",
shadows: gfx::ConstantBuffer<Shadow> = "u_shadows",
shadow_maps: gfx::TextureSampler<f32> = "t_shadow_maps",
point_shadow_maps: gfx::TextureSampler<f32> = "t_point_shadow_maps",
directed_shadow_maps: gfx::TextureSampler<f32> = "t_directed_shadow_maps",
map: gfx::TextureSampler<[f32; 4]> = "t_map",
horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon",
noise: gfx::TextureSampler<f32> = "t_noise",
// Shadow stuff
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::DepthStencilTarget<TgtDepthStencilFmt> = (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff,(StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))),
tgt_depth_stencil: gfx::DepthTarget<TgtDepthStencilFmt> = gfx::preset::depth::LESS_EQUAL_WRITE,
// tgt_depth_stencil: gfx::DepthStencilTarget<TgtDepthStencilFmt> = (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff,(StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))),
}
}
impl fmt::Display for Vertex {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Vertex")
.field("pos", &Vec3::<f32>::from(self.pos))
.field(
"atlas_pos",
&Vec2::new(
(self.atlas_pos >> 0) & 0xFFFF,
(self.atlas_pos >> 16) & 0xFFFF,
),
)
.field("norm_ao", &self.norm_ao)
.finish()
}
}
impl Vertex {
pub fn new(pos: Vec3<f32>, norm: Vec3<f32>, col: Rgb<f32>, ao: f32) -> Self {
// NOTE: Limit to 16 (x) × 16 (y) × 32 (z).
pub fn new(
atlas_pos: Vec2<u16>,
pos: Vec3<f32>,
norm: Vec3<f32>, /* , col: Rgb<f32>, ao: f32 */
) -> Self {
let norm_bits = if norm.x != 0.0 {
if norm.x < 0.0 { 0 } else { 1 }
} else if norm.y != 0.0 {
@ -60,31 +108,75 @@ impl Vertex {
};
Self {
// pos_norm: 0
// | ((pos.x as u32) & 0x003F) << 0
// | ((pos.y as u32) & 0x003F) << 6
// | (((pos + EXTRA_NEG_Z).z.max(0.0).min((1 << 16) as f32) as u32) & 0xFFFF) << 12
// | if meta { 1 } else { 0 } << 28
// | (norm_bits & 0x7) << 29,
pos: pos.into_array(),
col: col
/* col: col
.map2(Rgb::new(0, 8, 16), |e, shift| ((e * 255.0) as u32) << shift)
.reduce_bitor(),
norm_ao: norm_bits | (((ao * 3.9999) as u32) << 3),
.reduce_bitor(), */
atlas_pos: 0
| ((atlas_pos.x as u32) & 0xFFFF) << 0
| ((atlas_pos.y as u32) & 0xFFFF) << 16, /* | axis_bits & 3 */
norm_ao: norm_bits, /* | (((ao * 3.9999) as u32) << 3) */
}
}
}
impl Instance {
pub fn new(mat: Mat4<f32>, col: Rgb<f32>, wind_sway: f32) -> Self {
pub fn new(
mat: Mat4<f32>,
/* col: Rgb<f32>, */ wind_sway: f32,
pos: Vec3<i32>,
ori_bits: u8,
) -> Self {
const EXTRA_NEG_Z: i32 = 32768;
let mat_arr = arr_to_mat(mat.into_col_array());
Self {
pos_ori: 0
| ((pos.x as u32) & 0x003F) << 0
| ((pos.y as u32) & 0x003F) << 6
| (((pos + EXTRA_NEG_Z).z.max(0).min(1 << 16/* as f32*/) as u32) & 0xFFFF) << 12
// | if meta { 1 } else { 0 } << 28
| (u32::from(ori_bits) & 0x7) << 29,
inst_mat0: mat_arr[0],
inst_mat1: mat_arr[1],
inst_mat2: mat_arr[2],
inst_mat3: mat_arr[3],
inst_col: col.into_array(),
// inst_mat: mat_arr,
// inst_col: col.into_array(),
inst_wind_sway: wind_sway,
}
}
}
impl Default for Instance {
fn default() -> Self { Self::new(Mat4::identity(), Rgb::broadcast(1.0), 0.0) }
fn default() -> Self {
Self::new(
Mat4::identity(),
/* Rgb::broadcast(1.0), */ 0.0,
Vec3::zero(),
0,
)
}
}
impl Default for Locals {
fn default() -> Self { Self::new(Mat4::identity(), Vec3::one(), Vec3::zero(), 0.0) }
}
impl Locals {
pub fn new(mat: Mat4<f32>, scale: Vec3<f32>, offs: Vec3<f32>, wind_sway: f32) -> Self {
Self {
mat: arr_to_mat(mat.into_col_array()),
wind_sway: [scale.x, scale.y, scale.z, wind_sway],
offs: [offs.x, offs.y, offs.z, 0.0],
}
}
}
pub struct SpritePipeline;

View File

@ -1,48 +1,125 @@
use super::{
super::{Pipeline, TgtColorFmt, TgtDepthStencilFmt},
Globals, Light, Shadow,
super::{ColLightFmt, Pipeline, TgtColorFmt, TgtDepthStencilFmt},
shadow, Globals, Light, Shadow,
};
use gfx::{
self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta, gfx_pipeline,
gfx_pipeline_inner, gfx_vertex_struct_meta,
state::{Comparison, Stencil, StencilOp},
};
use std::ops::Mul;
use vek::*;
gfx_defines! {
vertex Vertex {
// pos_norm: u32 = "v_pos_norm",
// col_light: u32 = "v_col_light",
pos_norm: u32 = "v_pos_norm",
col_light: u32 = "v_col_light",
atlas_pos: u32 = "v_atlas_pos",
}
constant Locals {
model_offs: [f32; 3] = "model_offs",
load_time: f32 = "load_time",
atlas_offs: [i32; 4] = "atlas_offs",
}
pipeline pipe {
vbuf: gfx::VertexBuffer<Vertex> = (),
vbuf: gfx::VertexBuffer</*shadow::Vertex*/Vertex> = (),
// abuf: gfx::VertexBuffer<Vertex> = (),
col_lights: gfx::TextureSampler<[f32; 4]> = "t_col_light",
locals: gfx::ConstantBuffer<Locals> = "u_locals",
globals: gfx::ConstantBuffer<Globals> = "u_globals",
lights: gfx::ConstantBuffer<Light> = "u_lights",
shadows: gfx::ConstantBuffer<Shadow> = "u_shadows",
shadow_maps: gfx::TextureSampler<f32> = "t_shadow_maps",
point_shadow_maps: gfx::TextureSampler<f32> = "t_point_shadow_maps",
directed_shadow_maps: gfx::TextureSampler<f32> = "t_directed_shadow_maps",
map: gfx::TextureSampler<[f32; 4]> = "t_map",
horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon",
noise: gfx::TextureSampler<f32> = "t_noise",
// Shadow stuff
light_shadows: gfx::ConstantBuffer<shadow::Locals> = "u_light_shadows",
tgt_color: gfx::RenderTarget<TgtColorFmt> = "tgt_color",
tgt_depth_stencil: gfx::DepthStencilTarget<TgtDepthStencilFmt> = (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff,(StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))),
tgt_depth_stencil: gfx::DepthTarget<TgtDepthStencilFmt> = gfx::preset::depth::LESS_EQUAL_WRITE,
// tgt_depth_stencil: gfx::DepthStencilTarget<TgtDepthStencilFmt> = (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff,(StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))),
}
}
impl Vertex {
pub fn new(
pub fn new(atlas_pos: Vec2<u16>, pos: Vec3<f32>, norm: Vec3<f32>, meta: bool) -> Self {
const EXTRA_NEG_Z: f32 = 32768.0;
let norm_bits = if norm.x != 0.0 {
if norm.x < 0.0 { 0 } else { 1 }
} else if norm.y != 0.0 {
if norm.y < 0.0 { 2 } else { 3 }
} else {
if norm.z < 0.0 { 4 } else { 5 }
};
Self {
pos_norm: 0
| ((pos.x as u32) & 0x003F) << 0
| ((pos.y as u32) & 0x003F) << 6
| (((pos + EXTRA_NEG_Z).z.max(0.0).min((1 << 16) as f32) as u32) & 0xFFFF) << 12
| if meta { 1 } else { 0 } << 28
| (norm_bits & 0x7) << 29,
atlas_pos: 0
| ((atlas_pos.x as u32) & 0xFFFF) << 0
| ((atlas_pos.y as u32) & 0xFFFF) << 16,
/* col_light: 0
| (((col.r * 255.0) as u32) & 0xFF) << 8
| (((col.g * 255.0) as u32) & 0xFF) << 16
| (((col.b * 255.0) as u32) & 0xFF) << 24
| (ao >> 6) << 6
| ((light >> 2) & 0x3F) << 0, */
}
}
pub fn new_figure(
// norm: Vec3<f32>,
atlas_pos: Vec2<u16>,
pos: Vec3<f32>,
norm: Vec3<f32>,
bone_idx: u8,
) -> Self {
let norm_bits = if norm.x.min(norm.y).min(norm.z) < 0.0 {
0
} else {
1
};
let axis_bits = if norm.x != 0.0 {
0
} else if norm.y != 0.0 {
1
} else {
2
};
Self {
pos_norm: pos
.map2(Vec3::new(0, 9, 18), |e, shift| {
(((e * 2.0 + 256.0) as u32) & 0x1FF) << shift
})
.reduce_bitor()
| (((bone_idx & 0xF) as u32) << 27)
| (norm_bits << 31),
atlas_pos: 0
| ((atlas_pos.x as u32) & 0x7FFF) << 2
| ((atlas_pos.y as u32) & 0x7FFF) << 17
| axis_bits & 3,
/* col_light: 0
| (((col.r * 255.0) as u32) & 0xFF) << 8
| (((col.g * 255.0) as u32) & 0xFF) << 16
| (((col.b * 255.0) as u32) & 0xFF) << 24
| (ao >> 6) << 6
| ((light >> 2) & 0x3F) << 0, */
}
}
/* pub fn new(
norm_bits: u32,
light: u32,
ao: u32,
@ -66,6 +143,31 @@ impl Vertex {
| (ao >> 6) << 6
| ((light >> 2) & 0x3F) << 0,
}
} */
pub fn make_col_light(
light: /* u32 */ u8,
// ao: u32,
// col: Rgb<f32>,
col: Rgb<u8>,
) -> <<ColLightFmt as gfx::format::Formatted>::Surface as gfx::format::SurfaceTyped>::DataType
{
[
col.r, //.mul(255.0) as u8,
col.g, //.mul(255.0) as u8,
col.b, //.mul(255.0) as u8,
light,
/* | (ao as u8 >> 6) << 6
* | //((light as u8 >> 2) & 0x3F) << 0,
* | light */
]
}
pub fn with_bone_idx(self, bone_idx: u8) -> Self {
Self {
pos_norm: (self.pos_norm & !(0xF << 27)) | ((bone_idx as u32 & 0xF) << 27),
..self
}
}
}
@ -74,6 +176,7 @@ impl Locals {
Self {
model_offs: [0.0; 3],
load_time: 0.0,
atlas_offs: [0; 4],
}
}
}
@ -81,5 +184,5 @@ impl Locals {
pub struct TerrainPipeline;
impl Pipeline for TerrainPipeline {
type Vertex = Vertex;
type Vertex = Vertex; //<<ColLightFmt as gfx::format::Formatted>::Surface as gfx::format::SurfaceTyped>::DataType;
}

View File

@ -130,6 +130,18 @@ pub fn create_quad(
v([l, b], [uv_l, uv_b]),
v([r, b], [uv_r, uv_b]),
),
/* (true, true) | (false, false) => Quad::new(
v([l, t], [uv_l, uv_t]),
v([r, t], [uv_l, uv_b]),
v([r, b], [uv_r, uv_b]),
v([l, b], [uv_r, uv_t]),
),
_ => Quad::new(
v([l, t], [uv_l, uv_t]),
v([l, b], [uv_l, uv_b]),
v([r, b], [uv_r, uv_b]),
v([r, t], [uv_r, uv_t]),
) */
}
}

File diff suppressed because it is too large Load Diff

View File

@ -89,6 +89,58 @@ where
})
}
pub fn new_immutable_raw(
factory: &mut gfx_backend::Factory,
kind: gfx::texture::Kind,
mipmap: gfx::texture::Mipmap,
data: &[&[<F::Surface as gfx::format::SurfaceTyped>::DataType]],
sampler_info: gfx::texture::SamplerInfo,
) -> Result<Self, RenderError> {
let (tex, srv) = factory
.create_texture_immutable::<F>(kind, mipmap, data)
.map_err(|err| RenderError::CombinedError(err))?;
Ok(Self {
tex,
srv,
sampler: factory.create_sampler(sampler_info),
})
}
pub fn new_raw(
_device: &mut gfx_backend::Device,
factory: &mut gfx_backend::Factory,
kind: gfx::texture::Kind,
max_levels: u8,
bind: gfx::memory::Bind,
usage: gfx::memory::Usage,
levels: (u8, u8),
swizzle: gfx::format::Swizzle,
sampler_info: gfx::texture::SamplerInfo,
) -> Result<Self, RenderError> {
let tex = factory
.create_texture(
kind,
max_levels as gfx::texture::Level,
bind | gfx::memory::Bind::SHADER_RESOURCE,
usage,
Some(<<F as gfx::format::Formatted>::Channel as gfx::format::ChannelTyped>::get_channel_type())
)
.map_err(|err| RenderError::CombinedError(gfx::CombinedError::Texture(err)))?;
// device.cleanup();
let srv = factory
.view_texture_as_shader_resource::<F>(&tex, levels, swizzle)
.map_err(|err| RenderError::CombinedError(gfx::CombinedError::Resource(err)))?;
Ok(Self {
tex,
srv,
sampler: factory.create_sampler(sampler_info),
})
}
/// Update a texture with the given data (used for updating the glyph cache
/// texture).
pub fn update(

View File

@ -3,8 +3,8 @@ use std::f32::consts::PI;
use treeculler::Frustum;
use vek::*;
const NEAR_PLANE: f32 = 0.5;
const FAR_PLANE: f32 = 100000.0;
pub const NEAR_PLANE: f32 = 0.5;
pub const FAR_PLANE: f32 = 100000.0;
const FIRST_PERSON_INTERP_TIME: f32 = 0.1;
const THIRD_PERSON_INTERP_TIME: f32 = 0.1;
@ -43,6 +43,7 @@ pub struct Camera {
last_time: Option<f64>,
dependents: Dependents,
frustum: Frustum<f32>,
}
impl Camera {
@ -66,6 +67,7 @@ impl Camera {
proj_mat: Mat4::identity(),
cam_pos: Vec3::zero(),
},
frustum: Frustum::from_modelview_projection(Mat4::identity().into_col_arrays()),
}
}
@ -95,6 +97,7 @@ impl Camera {
(_, Err(_)) => self.dist,
}
.max(0.0)
// .max(NEAR_PLANE)
// self.dist.max(0.0)
};
@ -104,20 +107,22 @@ impl Camera {
* Mat4::rotation_x(self.ori.y)
* Mat4::rotation_y(self.ori.x)
* Mat4::rotation_3d(PI / 2.0, -Vec4::unit_x())
* Mat4::translation_3d(-self.focus);
* Mat4::translation_3d(-self.focus.map(|e| e.fract()));
self.dependents.proj_mat =
Mat4::perspective_rh_no(self.fov, self.aspect, NEAR_PLANE, FAR_PLANE);
// TODO: Make this more efficient.
self.dependents.cam_pos = Vec3::from(self.dependents.view_mat.inverted() * Vec4::unit_w());
self.frustum = Frustum::from_modelview_projection(
(self.dependents.proj_mat
* self.dependents.view_mat
* Mat4::translation_3d(-self.focus.map(|e| e.trunc())))
.into_col_arrays(),
);
}
pub fn frustum(&self) -> Frustum<f32> {
Frustum::from_modelview_projection(
(self.dependents.proj_mat * self.dependents.view_mat).into_col_arrays(),
)
}
pub fn frustum(&self) -> &Frustum<f32> { &self.frustum }
pub fn dependents(&self) -> Dependents { self.dependents.clone() }

View File

@ -1,8 +1,8 @@
use super::load::*;
use crate::{
anim::{self, Skeleton},
mesh::Meshable,
render::{FigurePipeline, Mesh, Model, Renderer},
mesh::{greedy::GreedyMesh, Meshable},
render::{BoneMeshes, FigureModel, FigurePipeline, Mesh, Renderer},
scene::camera::CameraMode,
};
use common::{
@ -21,6 +21,8 @@ use std::{
};
use vek::*;
pub type FigureModelEntry = [FigureModel; 3];
#[derive(PartialEq, Eq, Hash, Clone)]
enum FigureKey {
Simple(Body),
@ -68,7 +70,7 @@ pub struct FigureModelCache<Skel = anim::character::CharacterSkeleton>
where
Skel: Skeleton,
{
models: HashMap<FigureKey, (([Model<FigurePipeline>; 3], Skel::Attr), u64)>,
models: HashMap<FigureKey, ((FigureModelEntry, Skel::Attr), u64)>,
manifest_indicator: ReloadIndicator,
}
@ -86,8 +88,8 @@ impl<Skel: Skeleton> FigureModelCache<Skel> {
character_state: Option<&CharacterState>,
camera_mode: CameraMode,
manifest_indicator: &mut ReloadIndicator,
generate_mesh: fn(&Segment, Vec3<f32>) -> Mesh<FigurePipeline>,
) -> [Option<Mesh<FigurePipeline>>; 16] {
mut generate_mesh: impl FnMut(Segment, Vec3<f32>) -> BoneMeshes,
) -> [Option<BoneMeshes>; 16] {
match body {
Body::Humanoid(body) => {
let humanoid_head_spec = HumHeadSpec::load_watched(manifest_indicator);
@ -119,7 +121,7 @@ impl<Skel: Skeleton> FigureModelCache<Skel> {
body.skin,
body.eyebrows,
body.accessory,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
CameraMode::FirstPerson => None,
},
@ -127,27 +129,31 @@ impl<Skel: Skeleton> FigureModelCache<Skel> {
CameraMode::ThirdPerson => Some(humanoid_armor_chest_spec.mesh_chest(
&body,
loadout,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
CameraMode::FirstPerson => None,
},
match camera_mode {
CameraMode::ThirdPerson => {
Some(humanoid_armor_belt_spec.mesh_belt(&body, loadout, generate_mesh))
},
CameraMode::ThirdPerson => Some(humanoid_armor_belt_spec.mesh_belt(
&body,
loadout,
|segment, offset| generate_mesh(segment, offset),
)),
CameraMode::FirstPerson => None,
},
match camera_mode {
CameraMode::ThirdPerson => {
Some(humanoid_armor_back_spec.mesh_back(&body, loadout, generate_mesh))
},
CameraMode::ThirdPerson => Some(humanoid_armor_back_spec.mesh_back(
&body,
loadout,
|segment, offset| generate_mesh(segment, offset),
)),
CameraMode::FirstPerson => None,
},
match camera_mode {
CameraMode::ThirdPerson => Some(humanoid_armor_pants_spec.mesh_pants(
&body,
loadout,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
CameraMode::FirstPerson => None,
},
@ -156,7 +162,11 @@ impl<Skel: Skeleton> FigureModelCache<Skel> {
{
None
} else {
Some(humanoid_armor_hand_spec.mesh_left_hand(&body, loadout, generate_mesh))
Some(humanoid_armor_hand_spec.mesh_left_hand(
&body,
loadout,
|segment, offset| generate_mesh(segment, offset),
))
},
if character_state.map(|cs| cs.is_dodge()).unwrap_or_default() {
None
@ -164,14 +174,14 @@ impl<Skel: Skeleton> FigureModelCache<Skel> {
Some(humanoid_armor_hand_spec.mesh_right_hand(
&body,
loadout,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
))
},
match camera_mode {
CameraMode::ThirdPerson => Some(humanoid_armor_foot_spec.mesh_left_foot(
&body,
loadout,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
CameraMode::FirstPerson => None,
},
@ -179,7 +189,7 @@ impl<Skel: Skeleton> FigureModelCache<Skel> {
CameraMode::ThirdPerson => Some(humanoid_armor_foot_spec.mesh_right_foot(
&body,
loadout,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
CameraMode::FirstPerson => None,
},
@ -188,7 +198,7 @@ impl<Skel: Skeleton> FigureModelCache<Skel> {
Some(humanoid_armor_shoulder_spec.mesh_left_shoulder(
&body,
loadout,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
))
},
CameraMode::FirstPerson => None,
@ -198,12 +208,14 @@ impl<Skel: Skeleton> FigureModelCache<Skel> {
Some(humanoid_armor_shoulder_spec.mesh_right_shoulder(
&body,
loadout,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
))
},
CameraMode::FirstPerson => None,
},
Some(mesh_glider(generate_mesh)),
Some(mesh_glider(|segment, offset| {
generate_mesh(segment, offset)
})),
if camera_mode != CameraMode::FirstPerson
|| character_state
.map(|cs| cs.is_attack() || cs.is_block() || cs.is_wield())
@ -211,7 +223,7 @@ impl<Skel: Skeleton> FigureModelCache<Skel> {
{
Some(humanoid_main_weapon_spec.mesh_main_weapon(
loadout.active_item.as_ref().map(|i| &i.item.kind),
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
))
} else {
None
@ -231,32 +243,32 @@ impl<Skel: Skeleton> FigureModelCache<Skel> {
Some(quadruped_small_central_spec.mesh_head(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(quadruped_small_central_spec.mesh_chest(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(quadruped_small_lateral_spec.mesh_foot_lf(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(quadruped_small_lateral_spec.mesh_foot_rf(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(quadruped_small_lateral_spec.mesh_foot_lb(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(quadruped_small_lateral_spec.mesh_foot_rb(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
None,
None,
@ -280,57 +292,57 @@ impl<Skel: Skeleton> FigureModelCache<Skel> {
Some(quadruped_medium_central_spec.mesh_head_upper(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(quadruped_medium_central_spec.mesh_head_lower(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(quadruped_medium_central_spec.mesh_jaw(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(quadruped_medium_central_spec.mesh_tail(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(quadruped_medium_central_spec.mesh_torso_f(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(quadruped_medium_central_spec.mesh_torso_b(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(quadruped_medium_central_spec.mesh_ears(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(quadruped_medium_lateral_spec.mesh_foot_lf(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(quadruped_medium_lateral_spec.mesh_foot_rf(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(quadruped_medium_lateral_spec.mesh_foot_lb(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(quadruped_medium_lateral_spec.mesh_foot_rb(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
None,
None,
@ -349,37 +361,37 @@ impl<Skel: Skeleton> FigureModelCache<Skel> {
Some(bird_medium_center_spec.mesh_head(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(bird_medium_center_spec.mesh_torso(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(bird_medium_center_spec.mesh_tail(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(bird_medium_lateral_spec.mesh_wing_l(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(bird_medium_lateral_spec.mesh_wing_r(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(bird_medium_lateral_spec.mesh_foot_l(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(bird_medium_lateral_spec.mesh_foot_r(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
None,
None,
@ -393,12 +405,24 @@ impl<Skel: Skeleton> FigureModelCache<Skel> {
]
},
Body::FishMedium(body) => [
Some(mesh_fish_medium_head(body.head, generate_mesh)),
Some(mesh_fish_medium_torso(body.torso, generate_mesh)),
Some(mesh_fish_medium_rear(body.rear, generate_mesh)),
Some(mesh_fish_medium_tail(body.tail, generate_mesh)),
Some(mesh_fish_medium_fin_l(body.fin_l, generate_mesh)),
Some(mesh_fish_medium_fin_r(body.fin_r, generate_mesh)),
Some(mesh_fish_medium_head(body.head, |segment, offset| {
generate_mesh(segment, offset)
})),
Some(mesh_fish_medium_torso(body.torso, |segment, offset| {
generate_mesh(segment, offset)
})),
Some(mesh_fish_medium_rear(body.rear, |segment, offset| {
generate_mesh(segment, offset)
})),
Some(mesh_fish_medium_tail(body.tail, |segment, offset| {
generate_mesh(segment, offset)
})),
Some(mesh_fish_medium_fin_l(body.fin_l, |segment, offset| {
generate_mesh(segment, offset)
})),
Some(mesh_fish_medium_fin_r(body.fin_r, |segment, offset| {
generate_mesh(segment, offset)
})),
None,
None,
None,
@ -418,82 +442,94 @@ impl<Skel: Skeleton> FigureModelCache<Skel> {
Some(dragon_center_spec.mesh_head_upper(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(dragon_center_spec.mesh_head_lower(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(dragon_center_spec.mesh_jaw(
body.species,
body.body_type,
|segment, offset| generate_mesh(segment, offset),
)),
Some(dragon_center_spec.mesh_jaw(body.species, body.body_type, generate_mesh)),
Some(dragon_center_spec.mesh_chest_front(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(dragon_center_spec.mesh_chest_rear(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(dragon_center_spec.mesh_tail_front(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(dragon_center_spec.mesh_tail_rear(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(dragon_lateral_spec.mesh_wing_in_l(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(dragon_lateral_spec.mesh_wing_in_r(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(dragon_lateral_spec.mesh_wing_out_l(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(dragon_lateral_spec.mesh_wing_out_r(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(dragon_lateral_spec.mesh_foot_fl(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(dragon_lateral_spec.mesh_foot_fr(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(dragon_lateral_spec.mesh_foot_bl(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(dragon_lateral_spec.mesh_foot_br(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
None,
]
},
Body::BirdSmall(body) => [
Some(mesh_bird_small_head(body.head, generate_mesh)),
Some(mesh_bird_small_torso(body.torso, generate_mesh)),
Some(mesh_bird_small_wing_l(body.wing_l, generate_mesh)),
Some(mesh_bird_small_wing_r(body.wing_r, generate_mesh)),
Some(mesh_bird_small_head(body.head, |segment, offset| {
generate_mesh(segment, offset)
})),
Some(mesh_bird_small_torso(body.torso, |segment, offset| {
generate_mesh(segment, offset)
})),
Some(mesh_bird_small_wing_l(body.wing_l, |segment, offset| {
generate_mesh(segment, offset)
})),
Some(mesh_bird_small_wing_r(body.wing_r, |segment, offset| {
generate_mesh(segment, offset)
})),
None,
None,
None,
@ -508,8 +544,12 @@ impl<Skel: Skeleton> FigureModelCache<Skel> {
None,
],
Body::FishSmall(body) => [
Some(mesh_fish_small_torso(body.torso, generate_mesh)),
Some(mesh_fish_small_tail(body.tail, generate_mesh)),
Some(mesh_fish_small_torso(body.torso, |segment, offset| {
generate_mesh(segment, offset)
})),
Some(mesh_fish_small_tail(body.tail, |segment, offset| {
generate_mesh(segment, offset)
})),
None,
None,
None,
@ -535,57 +575,57 @@ impl<Skel: Skeleton> FigureModelCache<Skel> {
Some(biped_large_center_spec.mesh_head(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(biped_large_center_spec.mesh_torso_upper(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(biped_large_center_spec.mesh_torso_lower(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(biped_large_lateral_spec.mesh_shoulder_l(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(biped_large_lateral_spec.mesh_shoulder_r(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(biped_large_lateral_spec.mesh_hand_l(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(biped_large_lateral_spec.mesh_hand_r(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(biped_large_lateral_spec.mesh_leg_l(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(biped_large_lateral_spec.mesh_leg_r(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(biped_large_lateral_spec.mesh_foot_l(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(biped_large_lateral_spec.mesh_foot_r(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
None,
None,
@ -599,51 +639,55 @@ impl<Skel: Skeleton> FigureModelCache<Skel> {
let golem_lateral_spec = GolemLateralSpec::load_watched(manifest_indicator);
[
Some(golem_center_spec.mesh_head(body.species, body.body_type, generate_mesh)),
Some(golem_center_spec.mesh_head(
body.species,
body.body_type,
|segment, offset| generate_mesh(segment, offset),
)),
Some(golem_center_spec.mesh_torso_upper(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(golem_lateral_spec.mesh_shoulder_l(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(golem_lateral_spec.mesh_shoulder_r(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(golem_lateral_spec.mesh_hand_l(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(golem_lateral_spec.mesh_hand_r(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(golem_lateral_spec.mesh_leg_l(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(golem_lateral_spec.mesh_leg_r(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(golem_lateral_spec.mesh_foot_l(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(golem_lateral_spec.mesh_foot_r(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
None,
None,
@ -660,27 +704,27 @@ impl<Skel: Skeleton> FigureModelCache<Skel> {
Some(critter_center_spec.mesh_head(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(critter_center_spec.mesh_chest(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(critter_center_spec.mesh_feet_f(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(critter_center_spec.mesh_feet_b(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
Some(critter_center_spec.mesh_tail(
body.species,
body.body_type,
generate_mesh,
|segment, offset| generate_mesh(segment, offset),
)),
None,
None,
@ -719,12 +763,13 @@ impl<Skel: Skeleton> FigureModelCache<Skel> {
pub fn get_or_create_model(
&mut self,
renderer: &mut Renderer,
col_lights: &mut super::FigureColLights,
body: Body,
loadout: Option<&Loadout>,
tick: u64,
camera_mode: CameraMode,
character_state: Option<&CharacterState>,
) -> &([Model<FigurePipeline>; 3], Skel::Attr)
) -> &(FigureModelEntry, Skel::Attr)
where
for<'a> &'a common::comp::Body: std::convert::TryInto<Skel::Attr>,
Skel::Attr: Default,
@ -754,58 +799,72 @@ impl<Skel: Skeleton> FigureModelCache<Skel> {
.unwrap_or_else(<Skel::Attr as Default>::default);
let manifest_indicator = &mut self.manifest_indicator;
let mut make_model = |generate_mesh| {
let mut mesh = Mesh::new();
let mut make_model = |generate_mesh: for<'a> fn(&mut GreedyMesh<'a>, _, _) -> _| {
let mut greedy = FigureModel::make_greedy();
let mut opaque = Mesh::new();
let mut figure_bounds = Aabb {
min: Vec3::zero(),
max: Vec3::zero(),
};
// let mut shadow = Mesh::new();
Self::bone_meshes(
body,
loadout,
character_state,
camera_mode,
manifest_indicator,
generate_mesh,
|segment, offset| generate_mesh(&mut greedy, segment, offset),
)
.iter()
// .zip(&mut figure_bounds)
.enumerate()
.filter_map(|(i, bm)| bm.as_ref().map(|bm| (i, bm)))
.for_each(|(i, bone_mesh)| {
mesh.push_mesh_map(bone_mesh, |vert| vert.with_bone_idx(i as u8))
.for_each(|(i, (opaque_mesh/*, shadow_mesh*/, bounds)/*, bone_bounds*/)| {
// opaque.push_mesh_map(opaque_mesh, |vert| vert.with_bone_idx(i as u8));
opaque.push_mesh_map(opaque_mesh, |vert| vert.with_bone_idx(i as u8));
figure_bounds.expand_to_contain(*bounds);
// shadow.push_mesh_map(shadow_mesh, |vert| vert.with_bone_idx(i as u8));
});
renderer.create_model(&mesh).unwrap()
col_lights.create_figure(renderer, greedy, (opaque/*, shadow*/, figure_bounds)).unwrap()
};
fn generate_mesh(
segment: &Segment,
fn generate_mesh<'a>(
greedy: &mut GreedyMesh<'a>,
segment: Segment,
offset: Vec3<f32>,
) -> Mesh<FigurePipeline> {
Meshable::<FigurePipeline, FigurePipeline>::generate_mesh(
) -> BoneMeshes {
let (opaque, _, /*shadow*/_, bounds) = Meshable::<FigurePipeline, &mut GreedyMesh>::generate_mesh(
segment,
(offset, Vec3::one()),
)
.0
(greedy, offset, Vec3::one()),
);
(opaque/*, shadow*/, bounds)
}
fn generate_mesh_lod_mid(
segment: &Segment,
fn generate_mesh_lod_mid<'a>(
greedy: &mut GreedyMesh<'a>,
segment: Segment,
offset: Vec3<f32>,
) -> Mesh<FigurePipeline> {
) -> BoneMeshes {
let lod_scale = Vec3::broadcast(0.6);
Meshable::<FigurePipeline, FigurePipeline>::generate_mesh(
&segment.scaled_by(lod_scale),
(offset * lod_scale, Vec3::one() / lod_scale),
)
.0
let (opaque, _, /*shadow*/_, bounds) = Meshable::<FigurePipeline, &mut GreedyMesh>::generate_mesh(
segment.scaled_by(lod_scale),
(greedy, offset * lod_scale, Vec3::one() / lod_scale),
);
(opaque/*, shadow*/, bounds)
}
fn generate_mesh_lod_low(
segment: &Segment,
fn generate_mesh_lod_low<'a>(
greedy: &mut GreedyMesh<'a>,
segment: Segment,
offset: Vec3<f32>,
) -> Mesh<FigurePipeline> {
) -> BoneMeshes {
let lod_scale = Vec3::broadcast(0.3);
Meshable::<FigurePipeline, FigurePipeline>::generate_mesh(
&segment.scaled_by(lod_scale),
(offset * lod_scale, Vec3::one() / lod_scale),
)
.0
let segment = segment.scaled_by(lod_scale);
let (opaque, _, /*shadow*/_, bounds) = Meshable::<FigurePipeline, &mut GreedyMesh>::generate_mesh(
segment,
(greedy, offset * lod_scale, Vec3::one() / lod_scale),
);
(opaque/*, shadow*/, bounds)
}
(
@ -824,14 +883,24 @@ impl<Skel: Skeleton> FigureModelCache<Skel> {
}
}
pub fn clean(&mut self, tick: u64) {
pub fn clean(&mut self, col_lights: &mut super::FigureColLights, tick: u64) {
// Check for reloaded manifests
// TODO: maybe do this in a different function, maintain?
if self.manifest_indicator.reloaded() {
col_lights.atlas.clear();
self.models.clear();
}
// TODO: Don't hard-code this.
self.models
.retain(|_, (_, last_used)| *last_used + 60 > tick);
if tick % 60 == 0 {
self.models.retain(|_, ((models, _), last_used)| {
let alive = *last_used + 60 > tick;
if !alive {
models.iter().for_each(|model| {
col_lights.atlas.deallocate(model.allocation.id);
});
}
alive
});
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -4,14 +4,15 @@ use crate::{
fixture::FixtureSkeleton,
Animation, Skeleton,
},
mesh::Meshable,
mesh::{greedy::GreedyMesh, Meshable},
render::{
create_pp_mesh, create_skybox_mesh, Consts, FigurePipeline, Globals, Light, Mesh, Model,
PostProcessLocals, PostProcessPipeline, Renderer, Shadow, SkyboxLocals, SkyboxPipeline,
create_pp_mesh, create_skybox_mesh, BoneMeshes, Consts, FigureModel, FigurePipeline,
Globals, Light, Model, PostProcessLocals, PostProcessPipeline, Renderer, Shadow,
ShadowLocals, SkyboxLocals, SkyboxPipeline,
},
scene::{
camera::{self, Camera, CameraMode},
figure::{load_mesh, FigureModelCache, FigureState},
figure::{load_mesh, FigureColLights, FigureModelCache, FigureState},
LodData,
},
window::{Event, PressState},
@ -43,8 +44,17 @@ impl ReadVol for VoidVol {
fn get<'a>(&'a self, _pos: Vec3<i32>) -> Result<&'a Self::Vox, Self::Error> { Ok(&VoidVox) }
}
fn generate_mesh(segment: &Segment, offset: Vec3<f32>) -> Mesh<FigurePipeline> {
Meshable::<FigurePipeline, FigurePipeline>::generate_mesh(segment, (offset, Vec3::one())).0
fn generate_mesh<'a>(
greedy: &mut GreedyMesh<'a>,
segment: Segment,
offset: Vec3<f32>,
) -> BoneMeshes {
let (opaque, _, /* shadow */ _, bounds) =
Meshable::<FigurePipeline, &mut GreedyMesh>::generate_mesh(
segment,
(greedy, offset, Vec3::one()),
);
(opaque /* , shadow */, bounds)
}
struct Skybox {
@ -61,14 +71,16 @@ pub struct Scene {
globals: Consts<Globals>,
lights: Consts<Light>,
shadows: Consts<Shadow>,
shadow_mats: Consts<ShadowLocals>,
camera: Camera,
skybox: Skybox,
postprocess: PostProcess,
lod: LodData,
map_bounds: Vec2<f32>,
backdrop: Option<(Model<FigurePipeline>, FigureState<FixtureSkeleton>)>,
col_lights: FigureColLights,
backdrop: Option<(FigureModel, FigureState<FixtureSkeleton>)>,
figure_model_cache: FigureModelCache,
figure_state: FigureState<CharacterSkeleton>,
@ -109,11 +121,13 @@ impl Scene {
camera.set_distance(3.4);
camera.set_orientation(Vec3::new(start_angle, 0.0, 0.0));
let mut col_lights = FigureColLights::new(renderer);
Self {
globals: renderer.create_consts(&[Globals::default()]).unwrap(),
lights: renderer.create_consts(&[Light::default(); 32]).unwrap(),
shadows: renderer.create_consts(&[Shadow::default(); 32]).unwrap(),
camera,
shadow_mats: renderer.create_consts(&[ShadowLocals::default(); 6]).unwrap(),
skybox: Skybox {
model: renderer.create_model(&create_skybox_mesh()).unwrap(),
@ -133,6 +147,13 @@ impl Scene {
backdrop: backdrop.map(|specifier| {
let mut state = FigureState::new(renderer, FixtureSkeleton::new());
let mut greedy = FigureModel::make_greedy();
let mesh = load_mesh(
specifier,
Vec3::new(-55.0, -49.5, -2.0),
|segment, offset| generate_mesh(&mut greedy, segment, offset),
);
let model = col_lights.create_figure(renderer, greedy, mesh).unwrap();
state.update(
renderer,
Vec3::zero(),
@ -141,21 +162,20 @@ impl Scene {
Rgba::broadcast(1.0),
15.0, // Want to get there immediately.
1.0,
&model,
0,
true,
false,
&camera,
);
(
renderer
.create_model(&load_mesh(
specifier,
Vec3::new(-55.0, -49.5, -2.0),
generate_mesh,
))
.unwrap(),
state
model,
state,
)
}),
col_lights,
camera,
turning: false,
char_ori: /*0.0*/-start_angle,
@ -190,7 +210,12 @@ impl Scene {
}
}
pub fn maintain(&mut self, renderer: &mut Renderer, scene_data: SceneData) {
pub fn maintain(
&mut self,
renderer: &mut Renderer,
scene_data: SceneData,
loadout: Option<&Loadout>,
) {
self.camera.update(
scene_data.time,
/* 1.0 / 60.0 */ scene_data.delta_time,
@ -233,7 +258,8 @@ impl Scene {
error!("Renderer failed to update: {:?}", err);
}
self.figure_model_cache.clean(scene_data.tick);
self.figure_model_cache
.clean(&mut self.col_lights, scene_data.tick);
if let Some(body) = scene_data.body {
let tgt_skeleton = IdleAnimation::update_skeleton(
@ -246,8 +272,19 @@ impl Scene {
self.figure_state
.skeleton_mut()
.interpolate(&tgt_skeleton, scene_data.delta_time);
}
let model = &self
.figure_model_cache
.get_or_create_model(
renderer,
&mut self.col_lights,
Body::Humanoid(body),
loadout,
scene_data.tick,
CameraMode::default(),
None,
)
.0;
self.figure_state.update(
renderer,
Vec3::zero(),
@ -256,11 +293,14 @@ impl Scene {
Rgba::broadcast(1.0),
scene_data.delta_time,
1.0,
&model[0],
0,
true,
false,
&self.camera,
);
}
}
pub fn render(
&mut self,
@ -282,6 +322,7 @@ impl Scene {
.figure_model_cache
.get_or_create_model(
renderer,
&mut self.col_lights,
Body::Humanoid(body),
loadout,
tick,
@ -292,11 +333,13 @@ impl Scene {
renderer.render_figure(
&model[0],
&self.col_lights.texture(),
&self.globals,
self.figure_state.locals(),
self.figure_state.bone_consts(),
&self.lights,
&self.shadows,
&self.shadow_mats,
&self.lod.map,
&self.lod.horizon,
);
@ -305,11 +348,13 @@ impl Scene {
if let Some((model, state)) = &self.backdrop {
renderer.render_figure(
model,
&self.col_lights.texture(),
&self.globals,
state.locals(),
state.bone_consts(),
&self.lights,
&self.shadows,
&self.shadow_mats,
&self.lod.map,
&self.lod.horizon,
);

File diff suppressed because it is too large Load Diff

View File

@ -157,6 +157,9 @@ impl PlayState for SessionState {
let camera::Dependents {
view_mat, cam_pos, ..
} = self.scene.camera().dependents();
let focus_pos = self.scene.camera().get_focus_pos();
let focus_off = focus_pos.map(|e| e.trunc());
let cam_pos = cam_pos + focus_off;
// Choose a spot above the player's head for item distance checks
let player_pos = match self
@ -189,7 +192,9 @@ impl PlayState for SessionState {
)
};
let cam_dir: Vec3<f32> = Vec3::from(view_mat.inverted() * -Vec4::unit_z());
let cam_dir: Vec3<f32> = Vec3::from(
(view_mat/* * Mat4::translation_3d(-focus_off */).inverted() * -Vec4::unit_z(),
);
// Check to see whether we're aiming at anything
let (build_pos, select_pos) = {
@ -695,34 +700,15 @@ impl PlayState for SessionState {
global_state.settings.graphics.gamma = new_gamma;
global_state.settings.save_to_file_warn();
},
HudEvent::ChangeAaMode(new_aa_mode) => {
HudEvent::ChangeRenderMode(new_render_mode) => {
// Do this first so if it crashes the setting isn't saved :)
println!("Changing render mode: {:?}", new_render_mode);
global_state
.window
.renderer_mut()
.set_aa_mode(new_aa_mode)
.set_render_mode(new_render_mode)
.unwrap();
global_state.settings.graphics.aa_mode = new_aa_mode;
global_state.settings.save_to_file_warn();
},
HudEvent::ChangeCloudMode(new_cloud_mode) => {
// Do this first so if it crashes the setting isn't saved :)
global_state
.window
.renderer_mut()
.set_cloud_mode(new_cloud_mode)
.unwrap();
global_state.settings.graphics.cloud_mode = new_cloud_mode;
global_state.settings.save_to_file_warn();
},
HudEvent::ChangeFluidMode(new_fluid_mode) => {
// Do this first so if it crashes the setting isn't saved :)
global_state
.window
.renderer_mut()
.set_fluid_mode(new_fluid_mode)
.unwrap();
global_state.settings.graphics.fluid_mode = new_fluid_mode;
global_state.settings.graphics.render_mode = new_render_mode;
global_state.settings.save_to_file_warn();
},
HudEvent::ChangeLanguage(new_language) => {
@ -736,16 +722,6 @@ impl PlayState for SessionState {
localized_strings.log_missing_entries();
self.hud.update_language(localized_strings.clone());
},
HudEvent::ChangeLightingMode(new_lighting_mode) => {
// Do this first so if it crashes the setting isn't saved :)
global_state
.window
.renderer_mut()
.set_lighting_mode(new_lighting_mode)
.unwrap();
global_state.settings.graphics.lighting_mode = new_lighting_mode;
global_state.settings.save_to_file_warn();
},
HudEvent::ToggleFullscreen => {
global_state
.window
@ -799,9 +775,8 @@ impl PlayState for SessionState {
let renderer = global_state.window.renderer_mut();
// Flush renderer to synchronize commands sent on the main encoder with the
// start of the shadow encoder.
renderer.flush();
// Clear the shadow maps.
renderer.clear_shadows();
// Clear the screen
renderer.clear();
// Render the screen using the global renderer
@ -824,6 +799,12 @@ impl PlayState for SessionState {
.swap_buffers()
.expect("Failed to swap window buffers!");
/* let renderer = global_state.window.renderer_mut();
// Clear the shadow maps.
renderer.clear_shadows();
// Clear the screen
renderer.clear(); */
// Wait for the next tick.
clock.tick(Duration::from_millis(
1000 / global_state.settings.graphics.max_fps as u64,

View File

@ -1,7 +1,7 @@
use crate::{
hud::{BarNumbers, CrosshairType, Intro, PressBehavior, ShortcutNumbers, XpBar},
i18n,
render::{AaMode, CloudMode, FluidMode, LightingMode},
render::RenderMode,
ui::ScaleMode,
window::{GameInput, KeyMouse},
};
@ -548,7 +548,7 @@ impl Default for Log {
/// `GraphicsSettings` contains settings related to framerate and in-game
/// visuals.
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
#[serde(default)]
pub struct GraphicsSettings {
pub view_distance: u32,
@ -557,34 +557,12 @@ pub struct GraphicsSettings {
pub max_fps: u32,
pub fov: u16,
pub gamma: f32,
pub aa_mode: AaMode,
pub cloud_mode: CloudMode,
pub fluid_mode: FluidMode,
pub lighting_mode: LightingMode,
pub render_mode: RenderMode,
pub window_size: [u16; 2],
pub fullscreen: bool,
pub lod_detail: u32,
}
impl Default for GraphicsSettings {
fn default() -> Self {
Self {
view_distance: 10,
sprite_render_distance: 250,
figure_lod_render_distance: 250,
max_fps: 60,
fov: 50,
gamma: 1.0,
aa_mode: AaMode::Fxaa,
cloud_mode: CloudMode::Regular,
fluid_mode: FluidMode::Shiny,
lighting_mode: LightingMode::Ashikmin,
window_size: [1920, 1080],
fullscreen: false,
lod_detail: 500,
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum AudioOutput {
/// Veloren's audio system wont work on some systems,

View File

@ -26,7 +26,7 @@ impl Cache {
let max_texture_size = renderer.max_texture_size();
let glyph_cache_dims =
Vec2::new(w, h).map(|e| (e * GLYPH_CACHE_SIZE).min(max_texture_size as u16).max(512));
Vec2::new(w, h).map(|e| (e * GLYPH_CACHE_SIZE).min(max_texture_size).max(512));
Ok(Self {
glyph_cache: GlyphCache::builder()
@ -67,7 +67,7 @@ impl Cache {
let max_texture_size = renderer.max_texture_size();
let cache_dims = renderer
.get_resolution()
.map(|e| (e * GLYPH_CACHE_SIZE).min(max_texture_size as u16).max(512));
.map(|e| (e * GLYPH_CACHE_SIZE).min(max_texture_size).max(512));
self.glyph_cache = GlyphCache::builder()
.dimensions(cache_dims.x as u32, cache_dims.y as u32)
.scale_tolerance(SCALE_TOLERANCE)

View File

@ -226,6 +226,7 @@ impl GraphicCache {
// Fit into an atlas
let mut loc = None;
for (atlas_idx, (ref mut atlas, _)) in self.atlases.iter_mut().enumerate() {
let dims = dims.map(|e| e.max(1));
if let Some(rectangle) = atlas.allocate(size2(i32::from(dims.x), i32::from(dims.y)))
{
let aabr = aabr_from_alloc_rect(rectangle);
@ -239,6 +240,7 @@ impl GraphicCache {
// Create a new atlas
None => {
let (mut atlas, texture) = create_atlas_texture(renderer);
let dims = dims.map(|e| e.max(1));
let aabr = atlas
.allocate(size2(i32::from(dims.x), i32::from(dims.y)))
.map(aabr_from_alloc_rect)
@ -314,7 +316,7 @@ fn create_atlas_texture(renderer: &mut Renderer) -> (SimpleAtlasAllocator, Textu
let size = Vec2::new(w, h).map(|e| {
(e * GRAPHIC_CACHE_RELATIVE_SIZE)
.max(512)
.min(max_texture_size as u16)
.min(max_texture_size)
});
let atlas = SimpleAtlasAllocator::new(size2(i32::from(size.x), i32::from(size.y)));

View File

@ -664,6 +664,13 @@ impl Ui {
} else {
[p2.into_array(), p1.into_array(), p3.into_array()]
};
/* // If triangle is counter-clockwise, reverse it.
let (v1, v2): (Vec3<f32>, Vec3<f32>) = ((p2 - p1).into(), (p3 - p1).into());
let triangle = if v1.cross(v2).z > 0.0 {
[p2.into_array(), p1.into_array(), p3.into_array()]
} else {
[p1.into_array(), p2.into_array(), p3.into_array()]
}; */
mesh.push_tri(create_ui_tri(
triangle,
[[0.0; 2]; 3],

View File

@ -450,10 +450,7 @@ impl Window {
factory,
win_color_view,
win_depth_view,
settings.graphics.aa_mode,
settings.graphics.cloud_mode,
settings.graphics.fluid_mode,
settings.graphics.lighting_mode,
settings.graphics.render_mode,
)?,
window,
cursor_grabbed: false,

View File

@ -11,7 +11,7 @@ bitvec = "0.17.4"
fxhash = "0.2.1"
image = "0.22.3"
itertools = "0.8.2"
vek = "0.10.0"
vek = { version = "0.11.2", features = ["serde"] }
noise = { version = "0.6.0", default-features = false }
num = "0.2.0"
ordered-float = "1.0"
@ -29,5 +29,6 @@ serde_derive = "1.0.102"
ron = "0.5.1"
[dev-dependencies]
criterion = "0.3"
pretty_env_logger = "0.3.0"
minifb = "0.14.0"

View File

@ -72,6 +72,8 @@ impl Civs {
pub fn generate(seed: u32, sim: &mut WorldSim) -> Self {
let mut this = Self::default();
let rng = ChaChaRng::from_seed(seed_expan::rng_state(seed));
// let path_rng = RandomField::new(rng.gen());
let mut ctx = GenCtx { sim, rng };
for _ in 0..INITIAL_CIV_COUNT {
@ -81,6 +83,30 @@ impl Civs {
}
}
/* {
let v = (0..sim.chunks.len() as i32).collect::<Vec<_>>();
// Find edge wewghts.
let e = (0..sim.chunks.len() as i32)
.into_par_iter()
.flat_map(|posi| {
let pos = uniform_idx_as_vec2(posi);
NEIGHBORS
.iter()
.enumerate()
.filter_map(|(idx, dir)| walk_in_dir(sim, pos, dir).map(|w| (w, (posi * NEIGHBORS.len() + idx) as i32)))
})
.collect::<Vec<_>>();
// Connect all civiizations with paths simultaneously using a minimum spanning tree.
let mst = par_boruvka(
v, e,
|u, v| vec2_as_uniform_idx(u, v) as i32,
|posi| uniform_idx_as_vec2(posi).x,
|posi| uniform_idx_as_vec2(posi).y,
);
// Add path connections for all edges.
G
} */
for _ in 0..INITIAL_CIV_COUNT * 3 {
attempt(5, || {
let loc = find_site_loc(&mut ctx, None)?;
@ -440,6 +466,62 @@ impl Civs {
Some(site)
}
/* fn write_paths(&mut self, ctx: &mut GenCtx<impl Rng>, path_rng: &Vec2<RandomField>, paths: impl Iterator<(i32, i32, usize)>) {
paths.for_each(|(i, j, neighbor)| {
let neighbor = neighbor & 7;
let to_neighbor_dir = NEIGHBORS[neighbor];
let from_neighbor_dir = NEIGHBORS[7 - neighbor];
let from_idx = Vec2::new(i, j);
let to_idx = from_idx + to_neighbor_dir;
let from_chunk = ctx.sim.get_mut(from_idx).unwrap();
from_chunk.path.neighbors |= 1 << to_neighbor_dir;
from_chunk.path.offset = path_rng.map(|rng| (rng.get(from_idx) & 31) as f32);
let to_chunk = ctx.sim.get_mut(to_idx).unwrap();
to_chunk.path.neighbors |= 1 << from_neighbor_dir;
to_chunk.path.offset = path_rng.map(|rng| (rng.get(to_idx) & 31) as f32);
// from_idx.path.neighbors |= 1 << ((to_prev_idx as u8 + 4) % 8);
// ctx.sim.get_mut(locs[2]).unwrap().path.neighbors |=
// 1 << ((to_next_idx as u8 + 4) % 8);
// let mut chunk = ctx.sim.get_mut(locs[1]).unwrap();
// TODO: Split out so we don't run these repeatedly on the same chunk.
// to_idx.path.offset = path_rng.map(|rng| (rng.get(to_idx) & 31) as f32);
});
/* for locs in path.nodes().windows(3) {
let to_prev_idx = NEIGHBORS
.iter()
.enumerate()
.find(|(_, dir)| **dir == locs[0] - locs[1])
.expect("Track locations must be neighbors")
.0;
let to_next_idx = NEIGHBORS
.iter()
.enumerate()
.find(|(_, dir)| **dir == locs[2] - locs[1])
.expect("Track locations must be neighbors")
.0;
ctx.sim.get_mut(locs[0]).unwrap().path.neighbors |=
1 << ((to_prev_idx as u8 + 4) % 8);
ctx.sim.get_mut(locs[2]).unwrap().path.neighbors |=
1 << ((to_next_idx as u8 + 4) % 8);
let mut chunk = ctx.sim.get_mut(locs[1]).unwrap();
chunk.path.neighbors |=
(1 << (to_prev_idx as u8)) | (1 << (to_next_idx as u8));
chunk.path.offset = Vec2::new(
ctx.rng.gen_range(-16.0, 16.0),
ctx.rng.gen_range(-16.0, 16.0),
);
} */
/* // Take note of the track
let track = self.tracks.insert(Track { cost, path });
self.track_map
.entry(site)
.or_default()
.insert(nearby, track); */
} */
fn tick(&mut self, _ctx: &mut GenCtx<impl Rng>, years: f32) {
for site in self.sites.iter_mut() {
site.simulate(years, &self.places.get(site.place).nat_res);

View File

@ -14,9 +14,9 @@ pub mod util;
// Reexports
pub use crate::config::CONFIG;
pub use block::BlockGen;
use crate::{
block::BlockGen,
column::{ColumnGen, ColumnSample},
util::{Grid, Sampler},
};

View File

@ -1,3 +1,4 @@
// pub mod boruvka;
pub mod fast_noise;
pub mod grid;
pub mod random;