mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Adding shadows, greedy meshing, and more.
This commit is contained in:
parent
eaea83fe6a
commit
618a18c998
41
Cargo.lock
generated
41
Cargo.lock
generated
@ -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",
|
||||
]
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
48
assets/voxygen/shaders/light-shadows-directed-frag.glsl
Normal file
48
assets/voxygen/shaders/light-shadows-directed-frag.glsl
Normal 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
|
||||
}
|
||||
}
|
63
assets/voxygen/shaders/light-shadows-directed-vert.glsl
Normal file
63
assets/voxygen/shaders/light-shadows-directed-vert.glsl
Normal 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
|
||||
}
|
74
assets/voxygen/shaders/light-shadows-figure-vert.glsl
Normal file
74
assets/voxygen/shaders/light-shadows-figure-vert.glsl
Normal 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
|
||||
}
|
@ -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()
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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" }
|
||||
|
@ -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"
|
||||
|
@ -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>,
|
||||
|
@ -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,
|
||||
{
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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),
|
||||
|
@ -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();
|
||||
|
@ -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(),
|
||||
|
@ -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(),
|
||||
|
@ -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(),
|
||||
|
@ -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(),
|
||||
|
@ -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(),
|
||||
|
@ -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(),
|
||||
|
@ -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(),
|
||||
|
@ -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(),
|
||||
|
@ -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(),
|
||||
)
|
||||
|
@ -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(),
|
||||
|
@ -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);
|
||||
|
@ -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(),
|
||||
)
|
||||
|
@ -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(),
|
||||
|
@ -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(),
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
778
voxygen/src/mesh/greedy.rs
Normal 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), */
|
||||
)
|
||||
}
|
@ -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,
|
||||
);
|
||||
}
|
||||
|
@ -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, ()))
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
@ -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,
|
||||
));
|
||||
}
|
||||
}
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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>,
|
||||
);
|
||||
|
@ -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, */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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))),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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))),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
@ -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(
|
||||
|
@ -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() }
|
||||
|
||||
|
@ -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
@ -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
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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)));
|
||||
|
@ -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],
|
||||
|
@ -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,
|
||||
|
@ -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"
|
||||
|
@ -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);
|
||||
|
@ -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},
|
||||
};
|
||||
|
@ -1,3 +1,4 @@
|
||||
// pub mod boruvka;
|
||||
pub mod fast_noise;
|
||||
pub mod grid;
|
||||
pub mod random;
|
||||
|
Loading…
Reference in New Issue
Block a user