mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Almost implement instance merging for sprites (validation error), rebase
fix
This commit is contained in:
parent
cfd8606b04
commit
b85e9eae89
105
Cargo.lock
generated
105
Cargo.lock
generated
@ -211,11 +211,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ash"
|
||||
version = "0.31.0"
|
||||
version = "0.32.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c69a8137596e84c22d57f3da1b5de1d4230b1742a710091c85f4d7ce50f00f38"
|
||||
checksum = "06063a002a77d2734631db74e8f4ce7148b77fe522e6bca46f2ae7774fd48112"
|
||||
dependencies = [
|
||||
"libloading 0.6.7",
|
||||
"libloading 0.7.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -693,6 +693,16 @@ dependencies = [
|
||||
"objc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "codespan-reporting"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
|
||||
dependencies = [
|
||||
"termcolor",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "color_quant"
|
||||
version = "1.1.0"
|
||||
@ -1227,11 +1237,10 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "d3d12"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0a60cceb22c7c53035f8980524fdc7f17cf49681a3c154e6757d30afbec6ec4"
|
||||
source = "git+https://github.com/gfx-rs/d3d12-rs?rev=be19a243b86e0bafb9937d661fc8eabb3e42b44e#be19a243b86e0bafb9937d661fc8eabb3e42b44e"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"libloading 0.6.7",
|
||||
"libloading 0.7.0",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
@ -1886,8 +1895,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gfx-auxil"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7b33ecf067f2117668d91c9b0f2e5f223ebd1ffec314caa2f3de27bb580186d"
|
||||
source = "git+https://github.com/gfx-rs/gfx?rev=2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45#2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45"
|
||||
dependencies = [
|
||||
"fxhash",
|
||||
"gfx-hal",
|
||||
@ -1897,14 +1905,13 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gfx-backend-dx11"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f851d03c2e8f117e3702bf41201a4fafa447d5cb1276d5375870ae7573d069dd"
|
||||
source = "git+https://github.com/gfx-rs/gfx?rev=2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45#2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bitflags",
|
||||
"gfx-auxil",
|
||||
"gfx-hal",
|
||||
"libloading 0.6.7",
|
||||
"libloading 0.7.0",
|
||||
"log",
|
||||
"parking_lot 0.11.1",
|
||||
"range-alloc",
|
||||
@ -1918,9 +1925,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "gfx-backend-dx12"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5032d716a2a5f4dafb4675a794c5dc32081af8fbc7303c93ad93ff5413c6559f"
|
||||
version = "0.7.0"
|
||||
source = "git+https://github.com/gfx-rs/gfx?rev=2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45#2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bit-set",
|
||||
@ -1941,8 +1947,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gfx-backend-empty"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f07ef26a65954cfdd7b4c587f485100d1bb3b0bd6a51b02d817d6c87cca7a91"
|
||||
source = "git+https://github.com/gfx-rs/gfx?rev=2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45#2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45"
|
||||
dependencies = [
|
||||
"gfx-hal",
|
||||
"log",
|
||||
@ -1951,18 +1956,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "gfx-backend-gl"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c6717c50ab601efe4a669bfb44db615e3888695ac8263222aeaa702642b9fbc2"
|
||||
version = "0.7.0"
|
||||
source = "git+https://github.com/gfx-rs/gfx?rev=2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45#2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bitflags",
|
||||
"fxhash",
|
||||
"gfx-auxil",
|
||||
"gfx-hal",
|
||||
"glow",
|
||||
"js-sys",
|
||||
"khronos-egl",
|
||||
"libloading 0.6.7",
|
||||
"libloading 0.7.0",
|
||||
"log",
|
||||
"naga",
|
||||
"parking_lot 0.11.1",
|
||||
@ -1975,8 +1980,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gfx-backend-metal"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8dc54b456ece69ef49f8893269ebf24ac70969ed34ba2719c3f3abcc8fbff14e"
|
||||
source = "git+https://github.com/gfx-rs/gfx?rev=2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45#2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bitflags",
|
||||
@ -1984,6 +1988,7 @@ dependencies = [
|
||||
"cocoa-foundation",
|
||||
"copyless",
|
||||
"foreign-types",
|
||||
"fxhash",
|
||||
"gfx-auxil",
|
||||
"gfx-hal",
|
||||
"log",
|
||||
@ -2000,8 +2005,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gfx-backend-vulkan"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dabe88b1a5c91e0f969b441cc57e70364858066e4ba937deeb62065654ef9bd9"
|
||||
source = "git+https://github.com/gfx-rs/gfx?rev=2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45#2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"ash",
|
||||
@ -2021,8 +2025,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gfx-hal"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1d9cc8d3b573dda62d0baca4f02e0209786e22c562caff001d77c389008781d"
|
||||
source = "git+https://github.com/gfx-rs/gfx?rev=2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45#2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"naga",
|
||||
@ -2170,7 +2173,6 @@ checksum = "1e7724b9aef57ea36d70faf54e0ee6265f86e41de16bed8333efdeab5b00e16b"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"gpu-alloc-types",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2191,7 +2193,6 @@ dependencies = [
|
||||
"bitflags",
|
||||
"gpu-descriptor-types",
|
||||
"hashbrown",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2656,12 +2657,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "khronos-egl"
|
||||
version = "3.0.2"
|
||||
version = "4.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b19cc4a81304db2a0ad69740e83cdc3a9364e3f9bd6d88a87288a4c2deec927b"
|
||||
checksum = "8c2352bd1d0bceb871cb9d40f24360c8133c11d7486b68b5381c1dd1a32015e3"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"libloading 0.6.7",
|
||||
"libloading 0.7.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2957,8 +2958,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "metal"
|
||||
version = "0.21.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4598d719460ade24c7d91f335daf055bf2a7eec030728ce751814c50cdd6a26c"
|
||||
source = "git+https://github.com/gfx-rs/metal-rs?rev=439c986eb7a9b91e88b61def2daa66e4043fcbef#439c986eb7a9b91e88b61def2daa66e4043fcbef"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"block",
|
||||
@ -3085,12 +3085,12 @@ checksum = "0debeb9fcf88823ea64d64e4a815ab1643f33127d995978e099942ce38f25238"
|
||||
|
||||
[[package]]
|
||||
name = "naga"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05089b2acdf0e6a962cdbf5e328402345a27f59fcde1a59fe97a73e8149d416f"
|
||||
version = "0.3.1"
|
||||
source = "git+https://github.com/gfx-rs/naga?tag=gfx-15#196523de7820d4907a14bd22517c4d572d26b0be"
|
||||
dependencies = [
|
||||
"bit-set",
|
||||
"bitflags",
|
||||
"codespan-reporting",
|
||||
"fxhash",
|
||||
"log",
|
||||
"num-traits",
|
||||
@ -3973,6 +3973,12 @@ dependencies = [
|
||||
"unicode-xid 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "profiling"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0c71198452babfbba7419e716d29853c462d59da73c41485ab7dc8b4dc0c4be"
|
||||
|
||||
[[package]]
|
||||
name = "prometheus"
|
||||
version = "0.12.0"
|
||||
@ -4136,8 +4142,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "range-alloc"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "63e935c45e09cc6dcf00d2f0b2d630a58f4095320223d47fc68918722f0538b6"
|
||||
source = "git+https://github.com/gfx-rs/gfx?rev=2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45#2125c1d96b09f97faaa0d7a8a0d1c5315acc8c45"
|
||||
|
||||
[[package]]
|
||||
name = "raw-window-handle"
|
||||
@ -6531,18 +6536,16 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wgpu"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79a0a0a63fac9492cfaf6e7e4bdf9729c128f1e94124b9e4cbc4004b8cb6d1d8"
|
||||
version = "0.7.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu-rs.git?rev=a7e03546c1584cefef5b926f923108ea2cd1c146#a7e03546c1584cefef5b926f923108ea2cd1c146"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"js-sys",
|
||||
"naga",
|
||||
"parking_lot 0.11.1",
|
||||
"profiling",
|
||||
"raw-window-handle",
|
||||
"smallvec",
|
||||
"syn 1.0.65",
|
||||
"tracing",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
@ -6552,9 +6555,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wgpu-core"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c89fa2cc5d72236461ac09c5be967012663e29cb62f1a972654cbf35e49dffa8"
|
||||
version = "0.7.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=2f3b398e3887a336c963c43e7954f94cae42dd31#2f3b398e3887a336c963c43e7954f94cae42dd31"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bitflags",
|
||||
@ -6570,12 +6572,13 @@ dependencies = [
|
||||
"gfx-hal",
|
||||
"gpu-alloc",
|
||||
"gpu-descriptor",
|
||||
"log",
|
||||
"naga",
|
||||
"parking_lot 0.11.1",
|
||||
"profiling",
|
||||
"raw-window-handle",
|
||||
"smallvec",
|
||||
"thiserror",
|
||||
"tracing",
|
||||
"wgpu-types",
|
||||
]
|
||||
|
||||
@ -6592,8 +6595,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "wgpu-types"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72fa9ba80626278fd87351555c363378d08122d7601e58319be3d6fa85a87747"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=2f3b398e3887a336c963c43e7954f94cae42dd31#2f3b398e3887a336c963c43e7954f94cae42dd31"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
@ -6862,8 +6864,3 @@ name = "xml-rs"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b07db065a5cf61a7e4ba64f29e67db906fb1787316516c4e6e5ff0fea1efcd8a"
|
||||
|
||||
[[patch.unused]]
|
||||
name = "wgpu"
|
||||
version = "0.7.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu-rs.git?rev=a7e03546c1584cefef5b926f923108ea2cd1c146#a7e03546c1584cefef5b926f923108ea2cd1c146"
|
||||
|
@ -22,9 +22,9 @@ layout(location = 2) flat in float f_select;
|
||||
layout(location = 3) in vec2 f_uv_pos;
|
||||
layout(location = 4) in vec2 f_inst_light;
|
||||
|
||||
layout(set = 4, binding = 0)
|
||||
layout(set = 3, binding = 0)
|
||||
uniform texture2D t_col_light;
|
||||
layout(set = 4, binding = 1)
|
||||
layout(set = 3, binding = 1)
|
||||
uniform sampler s_col_light;
|
||||
|
||||
layout(location = 0) out vec4 tgt_color;
|
||||
|
@ -16,29 +16,22 @@
|
||||
#include <srgb.glsl>
|
||||
#include <sky.glsl>
|
||||
|
||||
layout(location = 0) in vec3 v_pos;
|
||||
layout(location = 1) in uint v_atlas_pos;
|
||||
layout(location = 2) in uint v_norm_ao;
|
||||
layout(location = 3) in uint inst_pos_ori;
|
||||
layout(location = 4) in vec4 inst_mat0;
|
||||
layout(location = 5) in vec4 inst_mat1;
|
||||
layout(location = 6) in vec4 inst_mat2;
|
||||
layout(location = 7) in vec4 inst_mat3;
|
||||
layout(location = 8) in vec4 inst_light;
|
||||
layout(location = 9) in float inst_wind_sway;
|
||||
layout(location = 0) in vec4 inst_mat0;
|
||||
layout(location = 1) in vec4 inst_mat1;
|
||||
layout(location = 2) in vec4 inst_mat2;
|
||||
layout(location = 3) in vec4 inst_mat3;
|
||||
// TODO: is there a better way to pack the various vertex attributes?
|
||||
// TODO: ori is unused
|
||||
layout(location = 4) in uint inst_pos_ori;
|
||||
layout(location = 5) in uint inst_vert_page; // NOTE: this could fit in less bits
|
||||
// TODO: do we need this many bits for light and glow?
|
||||
layout(location = 6) in float inst_light;
|
||||
layout(location = 7) in float inst_glow;
|
||||
layout(location = 8) in float model_wind_sway; // NOTE: this only varies per model
|
||||
layout(location = 9) in float model_z_scale; // NOTE: this only varies per model
|
||||
|
||||
struct SpriteLocals {
|
||||
mat4 mat;
|
||||
vec4 wind_sway;
|
||||
vec4 offs;
|
||||
};
|
||||
|
||||
layout(std140, set = 3, binding = 0)
|
||||
uniform u_locals {
|
||||
mat4 mat;
|
||||
vec4 wind_sway;
|
||||
vec4 offs;
|
||||
};
|
||||
layout(set = 0, binding = 12) uniform utexture2D t_sprite_verts;
|
||||
layout(set = 0, binding = 13) uniform sampler s_sprite_verts;
|
||||
|
||||
layout (std140, set = 2, binding = 0)
|
||||
uniform u_terrain_locals {
|
||||
@ -47,6 +40,7 @@ uniform u_terrain_locals {
|
||||
ivec4 atlas_offs;
|
||||
};
|
||||
|
||||
// TODO: consider grouping into vec4's
|
||||
layout(location = 0) out vec3 f_pos;
|
||||
layout(location = 1) flat out vec3 f_norm;
|
||||
layout(location = 2) flat out float f_select;
|
||||
@ -57,40 +51,64 @@ const float SCALE = 1.0 / 11.0;
|
||||
const float SCALE_FACTOR = pow(SCALE, 1.3) * 0.2;
|
||||
|
||||
const int EXTRA_NEG_Z = 32768;
|
||||
//const int VERT_EXTRA_NEG_Z = 128;
|
||||
const int VERT_EXTRA_NEG_Z = 128;
|
||||
const int VERT_PAGE_SIZE = 256;
|
||||
//const int VERT_PAGE_SIZE = 256;
|
||||
|
||||
void main() {
|
||||
// Matrix to transform this sprite instance from model space to chunk space
|
||||
mat4 inst_mat;
|
||||
inst_mat[0] = inst_mat0;
|
||||
inst_mat[1] = inst_mat1;
|
||||
inst_mat[2] = inst_mat2;
|
||||
inst_mat[3] = inst_mat3;
|
||||
vec3 inst_offs = model_offs - focus_off.xyz;
|
||||
|
||||
f_inst_light = inst_light.xy;
|
||||
// Worldpos of the chunk that this sprite is in
|
||||
vec3 chunk_offs = model_offs - focus_off.xyz;
|
||||
|
||||
vec3 v_pos_ = wind_sway.xyz * v_pos;
|
||||
f_inst_light = vec2(inst_light, inst_glow);
|
||||
|
||||
f_pos = (inst_mat * vec4(v_pos_, 1.0)).xyz * SCALE + inst_offs;
|
||||
// Index of the vertex data in the 1D vertex texture
|
||||
int vertex_index = int(gl_VertexIndex % VERT_PAGE_SIZE + inst_vert_page);
|
||||
const int WIDTH = 16384; // TODO: temp
|
||||
ivec2 tex_coords = ivec2(vertex_index % WIDTH, vertex_index / WIDTH);
|
||||
uvec2 pos_atlas_pos_norm_ao = texelFetch(usampler2D(t_sprite_verts, s_sprite_verts), tex_coords, 0).xy;
|
||||
uint v_pos_norm = pos_atlas_pos_norm_ao.x;
|
||||
uint v_atlas_pos = pos_atlas_pos_norm_ao.y;
|
||||
|
||||
// Expand the model vertex position bits into float values
|
||||
vec3 v_pos = vec3(ivec3((uvec3(v_pos_norm) >> uvec3(0, 8, 16)) & uvec3(0xFu, 0xFu, 0x0FFFu)) - ivec3(0, 0, VERT_EXTRA_NEG_Z));
|
||||
|
||||
// Transform into chunk space and scale
|
||||
f_pos = (inst_mat * vec4(v_pos, 1.0)).xyz;
|
||||
// Transform info world space
|
||||
f_pos += chunk_offs;
|
||||
|
||||
// Terrain 'pop-in' effect
|
||||
f_pos.z -= 250.0 * (1.0 - min(1.0001 - 0.02 / pow(tick.x - load_time, 10.0), 1.0));
|
||||
|
||||
f_pos += wind_sway.w * vec3(
|
||||
// Wind sway effect
|
||||
f_pos += model_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), 1.3) * SCALE_FACTOR;
|
||||
) * v_pos_.z * SCALE_FACTOR;
|
||||
// NOTE: could potentially replace `v_pos.z * model_z_scale` with a calculation using `inst_chunk_pos` from below
|
||||
//) * pow(abs(v_pos.z * model_z_scale), 1.3) * SCALE_FACTOR;
|
||||
) * v_pos.z * model_z_scale * SCALE_FACTOR;
|
||||
|
||||
vec3 norm = (inst_mat[(v_norm_ao >> 1u) & 3u].xyz);
|
||||
f_norm = mix(-norm, norm, v_norm_ao & 1u);
|
||||
// Determine normal
|
||||
vec3 norm = (inst_mat[(v_pos_norm >> 30u) & 3u].xyz);
|
||||
f_norm = mix(-norm, norm, v_pos_norm >> 29u & 1u);
|
||||
|
||||
f_uv_pos = vec2((uvec2(v_atlas_pos) >> uvec2(0, 16)) & uvec2(0xFFFFu, 0xFFFFu));/* + 0.5*/;
|
||||
// Expand atlas tex coords to floats
|
||||
// NOTE: Could defer to fragment shader if we are vert heavy
|
||||
f_uv_pos = vec2((uvec2(v_atlas_pos) >> uvec2(0, 16)) & uvec2(0xFFFFu, 0xFFFFu));;
|
||||
|
||||
// Position of the sprite block in the chunk
|
||||
// Used solely for highlighting the selected sprite
|
||||
vec3 inst_chunk_pos = vec3(ivec3((uvec3(inst_pos_ori) >> uvec3(0, 6, 12)) & uvec3(0x3Fu, 0x3Fu, 0xFFFFu)) - ivec3(0, 0, EXTRA_NEG_Z));
|
||||
// Select glowing
|
||||
vec3 sprite_pos = floor(((inst_mat * vec4(-offs.xyz, 1)).xyz) * SCALE) + inst_offs;
|
||||
vec3 sprite_pos = inst_chunk_pos + chunk_offs;
|
||||
f_light = (select_pos.w > 0 && select_pos.xyz == sprite_pos) ? 1.0 : 0.0;
|
||||
|
||||
gl_Position =
|
||||
|
@ -28,6 +28,9 @@ impl<V: Vertex> Mesh<V> {
|
||||
/// Get a mutable slice referencing the vertices of this mesh.
|
||||
pub fn vertices_mut(&mut self) -> &mut [V] { &mut self.verts }
|
||||
|
||||
/// Get a mutable vec referencing the vertices of this mesh.
|
||||
pub fn vertices_mut_vec(&mut self) -> &mut Vec<V> { &mut self.verts }
|
||||
|
||||
/// Push a new vertex onto the end of this mesh.
|
||||
pub fn push(&mut self, vert: V) { self.verts.push(vert); }
|
||||
|
||||
|
@ -31,7 +31,11 @@ pub use self::{
|
||||
postprocess::Locals as PostProcessLocals,
|
||||
shadow::{Locals as ShadowLocals, PointLightMatrix},
|
||||
skybox::{create_mesh as create_skybox_mesh, Vertex as SkyboxVertex},
|
||||
sprite::{Instance as SpriteInstance, Locals as SpriteLocals, Vertex as SpriteVertex},
|
||||
sprite::{
|
||||
create_verts_texture as create_sprite_verts_texture, Instance as SpriteInstance,
|
||||
SpriteGlobalsBindGroup, Vertex as SpriteVertex,
|
||||
VERT_PAGE_SIZE as SPRITE_VERT_PAGE_SIZE,
|
||||
},
|
||||
terrain::{Locals as TerrainLocals, TerrainLayout, Vertex as TerrainVertex},
|
||||
ui::{
|
||||
create_quad as create_ui_quad,
|
||||
@ -43,9 +47,9 @@ pub use self::{
|
||||
},
|
||||
renderer::{
|
||||
drawer::{
|
||||
ChunkSpriteDrawer, Drawer, FigureDrawer, FigureShadowDrawer, FirstPassDrawer,
|
||||
ParticleDrawer, PreparedUiDrawer, SecondPassDrawer, ShadowPassDrawer, SpriteDrawer,
|
||||
TerrainDrawer, TerrainShadowDrawer, ThirdPassDrawer, UiDrawer,
|
||||
Drawer, FigureDrawer, FigureShadowDrawer, FirstPassDrawer, ParticleDrawer,
|
||||
PreparedUiDrawer, SecondPassDrawer, ShadowPassDrawer, SpriteDrawer, TerrainDrawer,
|
||||
TerrainShadowDrawer, ThirdPassDrawer, UiDrawer,
|
||||
},
|
||||
ColLightInfo, Renderer,
|
||||
},
|
||||
|
@ -105,7 +105,7 @@ impl LodData {
|
||||
array_layer_count: None,
|
||||
};
|
||||
|
||||
renderer.create_texture_with_data_raw(
|
||||
renderer.create_texture_with_data_raw::<4>(
|
||||
&texture_info,
|
||||
&view_info,
|
||||
&sampler_info,
|
||||
|
@ -253,142 +253,146 @@ pub struct GlobalsLayouts {
|
||||
}
|
||||
|
||||
pub struct ColLights<Locals> {
|
||||
pub bind_group: wgpu::BindGroup,
|
||||
pub(super) bind_group: wgpu::BindGroup,
|
||||
pub texture: Texture,
|
||||
phantom: std::marker::PhantomData<Locals>,
|
||||
}
|
||||
|
||||
impl GlobalsLayouts {
|
||||
pub fn base_globals_layout() -> Vec<wgpu::BindGroupLayoutEntry> {
|
||||
vec![
|
||||
// Global uniform
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Buffer {
|
||||
ty: wgpu::BufferBindingType::Uniform,
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: None,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
// Noise tex
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Texture {
|
||||
sample_type: wgpu::TextureSampleType::Float { filterable: true },
|
||||
view_dimension: wgpu::TextureViewDimension::D2,
|
||||
multisampled: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 2,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Sampler {
|
||||
filtering: true,
|
||||
comparison: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
// Light uniform
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 3,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Buffer {
|
||||
ty: wgpu::BufferBindingType::Uniform,
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: None,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
// Shadow uniform
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 4,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Buffer {
|
||||
ty: wgpu::BufferBindingType::Uniform,
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: None,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
// Alt texture
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 5,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Texture {
|
||||
sample_type: wgpu::TextureSampleType::Float { filterable: true },
|
||||
view_dimension: wgpu::TextureViewDimension::D2,
|
||||
multisampled: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 6,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Sampler {
|
||||
filtering: true,
|
||||
comparison: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
// Horizon texture
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 7,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Texture {
|
||||
sample_type: wgpu::TextureSampleType::Float { filterable: true },
|
||||
view_dimension: wgpu::TextureViewDimension::D2,
|
||||
multisampled: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 8,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Sampler {
|
||||
filtering: true,
|
||||
comparison: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
// light shadows (ie shadows from a light?)
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 9,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
// TODO: is this relevant?
|
||||
ty: wgpu::BindingType::Buffer {
|
||||
ty: wgpu::BufferBindingType::Uniform,
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: None,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
// lod map (t_map)
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 10,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Texture {
|
||||
sample_type: wgpu::TextureSampleType::Float { filterable: true },
|
||||
view_dimension: wgpu::TextureViewDimension::D2,
|
||||
multisampled: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 11,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Sampler {
|
||||
filtering: true,
|
||||
comparison: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
pub fn new(device: &wgpu::Device) -> Self {
|
||||
let globals = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
label: Some("Globals layout"),
|
||||
entries: &[
|
||||
// Global uniform
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Buffer {
|
||||
ty: wgpu::BufferBindingType::Uniform,
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: None,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
// Noise tex
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Texture {
|
||||
sample_type: wgpu::TextureSampleType::Float { filterable: true },
|
||||
view_dimension: wgpu::TextureViewDimension::D2,
|
||||
multisampled: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 2,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Sampler {
|
||||
filtering: true,
|
||||
comparison: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
// Light uniform
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 3,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Buffer {
|
||||
ty: wgpu::BufferBindingType::Uniform,
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: None,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
// Shadow uniform
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 4,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Buffer {
|
||||
ty: wgpu::BufferBindingType::Uniform,
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: None,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
// Alt texture
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 5,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Texture {
|
||||
sample_type: wgpu::TextureSampleType::Float { filterable: true },
|
||||
view_dimension: wgpu::TextureViewDimension::D2,
|
||||
multisampled: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 6,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Sampler {
|
||||
filtering: true,
|
||||
comparison: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
// Horizon texture
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 7,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Texture {
|
||||
sample_type: wgpu::TextureSampleType::Float { filterable: true },
|
||||
view_dimension: wgpu::TextureViewDimension::D2,
|
||||
multisampled: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 8,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Sampler {
|
||||
filtering: true,
|
||||
comparison: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
// light shadows (ie shadows from a light?)
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 9,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
// TODO: is this relevant?
|
||||
ty: wgpu::BindingType::Buffer {
|
||||
ty: wgpu::BufferBindingType::Uniform,
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: None,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
// lod map (t_map)
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 10,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Texture {
|
||||
sample_type: wgpu::TextureSampleType::Float { filterable: true },
|
||||
view_dimension: wgpu::TextureViewDimension::D2,
|
||||
multisampled: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 11,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Sampler {
|
||||
filtering: true,
|
||||
comparison: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
],
|
||||
entries: &Self::base_globals_layout(),
|
||||
});
|
||||
|
||||
let col_light = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
@ -470,6 +474,72 @@ impl GlobalsLayouts {
|
||||
}
|
||||
}
|
||||
|
||||
// Note: this allocation serves the purpose of not having to duplicate code
|
||||
pub fn bind_base_globals<'a>(
|
||||
global_model: &'a GlobalModel,
|
||||
lod_data: &'a lod_terrain::LodData,
|
||||
noise: &'a Texture,
|
||||
) -> Vec<wgpu::BindGroupEntry<'a>> {
|
||||
vec![
|
||||
// Global uniform
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 0,
|
||||
resource: global_model.globals.buf().as_entire_binding(),
|
||||
},
|
||||
// Noise tex
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 1,
|
||||
resource: wgpu::BindingResource::TextureView(&noise.view),
|
||||
},
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 2,
|
||||
resource: wgpu::BindingResource::Sampler(&noise.sampler),
|
||||
},
|
||||
// Light uniform
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 3,
|
||||
resource: global_model.lights.buf().as_entire_binding(),
|
||||
},
|
||||
// Shadow uniform
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 4,
|
||||
resource: global_model.shadows.buf().as_entire_binding(),
|
||||
},
|
||||
// Alt texture
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 5,
|
||||
resource: wgpu::BindingResource::TextureView(&lod_data.alt.view),
|
||||
},
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 6,
|
||||
resource: wgpu::BindingResource::Sampler(&lod_data.alt.sampler),
|
||||
},
|
||||
// Horizon texture
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 7,
|
||||
resource: wgpu::BindingResource::TextureView(&lod_data.horizon.view),
|
||||
},
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 8,
|
||||
resource: wgpu::BindingResource::Sampler(&lod_data.horizon.sampler),
|
||||
},
|
||||
// light shadows
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 9,
|
||||
resource: global_model.shadow_mats.buf().as_entire_binding(),
|
||||
},
|
||||
// lod map (t_map)
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 10,
|
||||
resource: wgpu::BindingResource::TextureView(&lod_data.map.view),
|
||||
},
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 11,
|
||||
resource: wgpu::BindingResource::Sampler(&lod_data.map.sampler),
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
pub fn bind(
|
||||
&self,
|
||||
device: &wgpu::Device,
|
||||
@ -480,64 +550,7 @@ impl GlobalsLayouts {
|
||||
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
label: None,
|
||||
layout: &self.globals,
|
||||
entries: &[
|
||||
// Global uniform
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 0,
|
||||
resource: global_model.globals.buf().as_entire_binding(),
|
||||
},
|
||||
// Noise tex
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 1,
|
||||
resource: wgpu::BindingResource::TextureView(&noise.view),
|
||||
},
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 2,
|
||||
resource: wgpu::BindingResource::Sampler(&noise.sampler),
|
||||
},
|
||||
// Light uniform
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 3,
|
||||
resource: global_model.lights.buf().as_entire_binding(),
|
||||
},
|
||||
// Shadow uniform
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 4,
|
||||
resource: global_model.shadows.buf().as_entire_binding(),
|
||||
},
|
||||
// Alt texture
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 5,
|
||||
resource: wgpu::BindingResource::TextureView(&lod_data.alt.view),
|
||||
},
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 6,
|
||||
resource: wgpu::BindingResource::Sampler(&lod_data.alt.sampler),
|
||||
},
|
||||
// Horizon texture
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 7,
|
||||
resource: wgpu::BindingResource::TextureView(&lod_data.horizon.view),
|
||||
},
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 8,
|
||||
resource: wgpu::BindingResource::Sampler(&lod_data.horizon.sampler),
|
||||
},
|
||||
// light shadows
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 9,
|
||||
resource: global_model.shadow_mats.buf().as_entire_binding(),
|
||||
},
|
||||
// lod map (t_map)
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 10,
|
||||
resource: wgpu::BindingResource::TextureView(&lod_data.map.view),
|
||||
},
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 11,
|
||||
resource: wgpu::BindingResource::Sampler(&lod_data.map.sampler),
|
||||
},
|
||||
],
|
||||
entries: &Self::bind_base_globals(global_model, lod_data, noise),
|
||||
});
|
||||
|
||||
GlobalsBindGroup { bind_group }
|
||||
|
@ -116,7 +116,7 @@ pub fn create_col_lights(
|
||||
array_layer_count: None,
|
||||
};
|
||||
|
||||
renderer.create_texture_with_data_raw(
|
||||
renderer.create_texture_with_data_raw::<4>(
|
||||
&texture_info,
|
||||
&view_info,
|
||||
&sampler_info,
|
||||
|
@ -1,47 +1,52 @@
|
||||
use super::super::{AaMode, Bound, Consts, GlobalsLayouts, TerrainLayout, Vertex as VertexTrait};
|
||||
use super::{
|
||||
super::{
|
||||
AaMode, Bound, Consts, GlobalsLayouts, Mesh, Renderer, TerrainLayout, Texture,
|
||||
Vertex as VertexTrait,
|
||||
},
|
||||
lod_terrain, GlobalModel,
|
||||
};
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
use core::fmt;
|
||||
use std::mem;
|
||||
use vek::*;
|
||||
|
||||
pub const VERT_PAGE_SIZE: u32 = 256;
|
||||
// pub const VERT_PAGE_SIZE: u32 = 256;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Zeroable, Pod)]
|
||||
pub struct Vertex {
|
||||
pos: [f32; 3],
|
||||
pos_norm: u32,
|
||||
// Because we try to restrict terrain sprite data to a 128×128 block
|
||||
// we need an offset into the texture atlas.
|
||||
atlas_pos: u32,
|
||||
// ____BBBBBBBBGGGGGGGGRRRRRRRR
|
||||
// col: u32 = "v_col",
|
||||
// ...AANNN
|
||||
// A = AO
|
||||
// N = Normal
|
||||
norm_ao: u32,
|
||||
/* ____BBBBBBBBGGGGGGGGRRRRRRRR
|
||||
* col: u32 = "v_col",
|
||||
* .....NNN
|
||||
* A = AO
|
||||
* N = Normal
|
||||
*norm: u32, */
|
||||
}
|
||||
|
||||
impl fmt::Display for Vertex {
|
||||
// TODO: fix?
|
||||
/*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("pos_norm", &Vec3::<f32>::from(self.pos))
|
||||
.field(
|
||||
"atlas_pos",
|
||||
&Vec2::new(self.atlas_pos & 0xFFFF, (self.atlas_pos >> 16) & 0xFFFF),
|
||||
)
|
||||
.field("norm_ao", &self.norm_ao)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
impl Vertex {
|
||||
// NOTE: Limit to 16 (x) × 16 (y) × 32 (z).
|
||||
#[allow(clippy::collapsible_else_if)]
|
||||
pub fn new(
|
||||
atlas_pos: Vec2<u16>,
|
||||
pos: Vec3<f32>,
|
||||
norm: Vec3<f32>, /* , col: Rgb<f32>, ao: f32 */
|
||||
) -> Self {
|
||||
pub fn new(atlas_pos: Vec2<u16>, pos: Vec3<f32>, norm: Vec3<f32>) -> Self {
|
||||
const VERT_EXTRA_NEG_Z: i32 = 128; // NOTE: change if number of bits changes below, also we might not need this if meshing always produces positives values for sprites (I have no idea)
|
||||
|
||||
let norm_bits = if norm.x != 0.0 {
|
||||
if norm.x < 0.0 { 0 } else { 1 }
|
||||
} else if norm.y != 0.0 {
|
||||
@ -56,13 +61,15 @@ 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,
|
||||
pos: pos.into_array(),
|
||||
pos_norm: ((pos.x as u32) & 0x00FF) // NOTE: temp hack, this doesn't need 8 bits
|
||||
| ((pos.y as u32) & 0x00FF) << 8
|
||||
| (((pos.z as i32 + VERT_EXTRA_NEG_Z).max(0).min(1 << 12) as u32) & 0x0FFF) << 16
|
||||
| (norm_bits & 0x7) << 29,
|
||||
atlas_pos: ((atlas_pos.x as u32) & 0xFFFF) | ((atlas_pos.y as u32) & 0xFFFF) << 16,
|
||||
norm_ao: norm_bits,
|
||||
}
|
||||
}
|
||||
|
||||
fn desc<'a>() -> wgpu::VertexBufferLayout<'a> {
|
||||
/*fn desc<'a>() -> wgpu::VertexBufferLayout<'a> {
|
||||
const ATTRIBUTES: [wgpu::VertexAttribute; 3] =
|
||||
wgpu::vertex_attr_array![0 => Float32x3, 1 => Uint32, 2 => Uint32];
|
||||
wgpu::VertexBufferLayout {
|
||||
@ -70,7 +77,11 @@ impl Vertex {
|
||||
step_mode: wgpu::InputStepMode::Vertex,
|
||||
attributes: &ATTRIBUTES,
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
impl Default for Vertex {
|
||||
fn default() -> Self { Self::new(Vec2::zero(), Vec3::zero(), Vec3::zero()) }
|
||||
}
|
||||
|
||||
impl VertexTrait for Vertex {
|
||||
@ -78,29 +89,29 @@ impl VertexTrait for Vertex {
|
||||
const STRIDE: wgpu::BufferAddress = mem::size_of::<Self>() as wgpu::BufferAddress;
|
||||
}
|
||||
|
||||
/* pub fn create_verts_buffer(renderer: &mut Renderer, mut mesh: Mesh<Vertex>) -> Buffer<Vertex> {
|
||||
renderer.ensure_sufficient_index_length::<Vertex>(VERT_PAGE_SIZE as usize);
|
||||
pub fn create_verts_texture(renderer: &mut Renderer, mut mesh: Mesh<Vertex>) -> Texture {
|
||||
//renderer.ensure_sufficient_index_length::<Vertex>(VERT_PAGE_SIZE as usize);
|
||||
// TODO: type buffer by Usage
|
||||
Buffer::new(
|
||||
/*Buffer::new(
|
||||
&renderer.device,
|
||||
wgpu::BufferUsage::STORAGE,
|
||||
mesh.vertices(),
|
||||
)
|
||||
//let mut verts = mesh.vertices_mut_vec();
|
||||
//let format = wgpu::TextureFormat::Rg32Uint;
|
||||
)*/
|
||||
let mut verts = mesh.vertices_mut_vec();
|
||||
let format = wgpu::TextureFormat::Rg32Uint;
|
||||
|
||||
// TODO: temp
|
||||
//const WIDTH: u32 = 8192;
|
||||
//let height = verts.len() as u32 / WIDTH;
|
||||
const WIDTH: u32 = 16384;
|
||||
let height = verts.len() as u32 / WIDTH;
|
||||
// Fill in verts to full texture size
|
||||
//verts.resize_with(height as usize * WIDTH as usize, Vertex::default);
|
||||
verts.resize_with(height as usize * WIDTH as usize, Vertex::default);
|
||||
|
||||
/*let texture_info = wgpu::TextureDescriptor {
|
||||
let texture_info = wgpu::TextureDescriptor {
|
||||
label: Some("Sprite verts"),
|
||||
size: wgpu::Extent3d {
|
||||
width: WIDTH,
|
||||
height,
|
||||
depth: 1,
|
||||
depth_or_array_layers: 1,
|
||||
},
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
@ -136,56 +147,66 @@ impl VertexTrait for Vertex {
|
||||
&view_info,
|
||||
&sampler_info,
|
||||
bytemuck::cast_slice(verts),
|
||||
)*/
|
||||
)
|
||||
}
|
||||
*/
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Zeroable, Pod)]
|
||||
pub struct Instance {
|
||||
pos_ori: u32,
|
||||
inst_mat0: [f32; 4],
|
||||
inst_mat1: [f32; 4],
|
||||
inst_mat2: [f32; 4],
|
||||
inst_mat3: [f32; 4],
|
||||
inst_light: [f32; 4],
|
||||
inst_wind_sway: f32,
|
||||
pos_ori: u32,
|
||||
inst_vert_page: u32,
|
||||
inst_light: f32,
|
||||
inst_glow: f32,
|
||||
model_wind_sway: f32,
|
||||
model_z_scale: f32,
|
||||
}
|
||||
|
||||
impl Instance {
|
||||
pub fn new(
|
||||
mat: Mat4<f32>,
|
||||
wind_sway: f32,
|
||||
z_scale: f32,
|
||||
pos: Vec3<i32>,
|
||||
ori_bits: u8,
|
||||
light: f32,
|
||||
glow: f32,
|
||||
vert_page: u32,
|
||||
) -> Self {
|
||||
const EXTRA_NEG_Z: i32 = 32768;
|
||||
|
||||
let mat_arr = mat.into_col_arrays();
|
||||
Self {
|
||||
pos_ori: ((pos.x as u32) & 0x003F)
|
||||
| ((pos.y as u32) & 0x003F) << 6
|
||||
| (((pos + EXTRA_NEG_Z).z.max(0).min(1 << 16) as u32) & 0xFFFF) << 12
|
||||
| (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_light: [light, glow, 1.0, 1.0],
|
||||
inst_wind_sway: wind_sway,
|
||||
pos_ori: ((pos.x as u32) & 0x003F)
|
||||
| ((pos.y as u32) & 0x003F) << 6
|
||||
| (((pos.z + EXTRA_NEG_Z).max(0).min(1 << 16) as u32) & 0xFFFF) << 12
|
||||
| (u32::from(ori_bits) & 0x7) << 29,
|
||||
inst_vert_page: vert_page,
|
||||
inst_light: light,
|
||||
inst_glow: glow,
|
||||
model_wind_sway: wind_sway,
|
||||
model_z_scale: z_scale,
|
||||
}
|
||||
}
|
||||
|
||||
fn desc<'a>() -> wgpu::VertexBufferLayout<'a> {
|
||||
const ATTRIBUTES: [wgpu::VertexAttribute; 7] = wgpu::vertex_attr_array![
|
||||
3 => Uint32,
|
||||
4 => Float32x4,
|
||||
5 => Float32x4,
|
||||
6 => Float32x4,
|
||||
7 => Float32x4,
|
||||
8 => Float32x4,
|
||||
const ATTRIBUTES: [wgpu::VertexAttribute; 10] = wgpu::vertex_attr_array![
|
||||
0 => Float32x4,
|
||||
1 => Float32x4,
|
||||
2 => Float32x4,
|
||||
3 => Float32x4,
|
||||
4 => Uint32,
|
||||
5 => Uint32,
|
||||
6 => Float32,
|
||||
7 => Float32,
|
||||
8 => Float32,
|
||||
9 => Float32,
|
||||
];
|
||||
wgpu::VertexBufferLayout {
|
||||
@ -197,10 +218,12 @@ impl Instance {
|
||||
}
|
||||
|
||||
impl Default for Instance {
|
||||
fn default() -> Self { Self::new(Mat4::identity(), 0.0, Vec3::zero(), 0, 1.0, 0.0) }
|
||||
fn default() -> Self { Self::new(Mat4::identity(), 0.0, 0.0, Vec3::zero(), 0, 1.0, 0.0, 0) }
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
// TODO: ColLightsWrapper instead?
|
||||
pub struct Locals;
|
||||
/*#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Zeroable, Pod)]
|
||||
pub struct Locals {
|
||||
// Each matrix performs rotatation, translation, and scaling, relative to the sprite
|
||||
@ -211,8 +234,6 @@ pub struct Locals {
|
||||
offs: [f32; 4],
|
||||
}
|
||||
|
||||
pub type BoundLocals = Bound<Consts<Locals>>;
|
||||
|
||||
impl Default for Locals {
|
||||
fn default() -> Self { Self::new(Mat4::identity(), Vec3::one(), Vec3::zero(), 0.0) }
|
||||
}
|
||||
@ -225,16 +246,52 @@ impl Locals {
|
||||
offs: [offs.x, offs.y, offs.z, 0.0],
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
pub struct SpriteGlobalsBindGroup {
|
||||
pub(in super::super) bind_group: wgpu::BindGroup,
|
||||
}
|
||||
|
||||
//pub type BoundLocals = Bound<Consts<Locals>>;
|
||||
|
||||
pub struct SpriteLayout {
|
||||
pub locals: wgpu::BindGroupLayout,
|
||||
pub globals: wgpu::BindGroupLayout,
|
||||
//pub locals: wgpu::BindGroupLayout,
|
||||
}
|
||||
|
||||
impl SpriteLayout {
|
||||
pub fn new(device: &wgpu::Device) -> Self {
|
||||
let mut entries = GlobalsLayouts::base_globals_layout();
|
||||
debug_assert_eq!(12, entries.len()); // To remember to adjust the bindings below
|
||||
entries.extend_from_slice(&[
|
||||
// sprite verts (t_sprite_verts)
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 12,
|
||||
visibility: wgpu::ShaderStage::VERTEX,
|
||||
ty: wgpu::BindingType::Texture {
|
||||
sample_type: wgpu::TextureSampleType::Uint,
|
||||
view_dimension: wgpu::TextureViewDimension::D1,
|
||||
multisampled: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 13,
|
||||
visibility: wgpu::ShaderStage::VERTEX,
|
||||
ty: wgpu::BindingType::Sampler {
|
||||
filtering: false,
|
||||
comparison: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
]);
|
||||
|
||||
Self {
|
||||
locals: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
globals: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
label: None,
|
||||
entries: &entries,
|
||||
}),
|
||||
/*locals: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
label: None,
|
||||
entries: &[
|
||||
// locals
|
||||
@ -250,18 +307,61 @@ impl SpriteLayout {
|
||||
},
|
||||
// instance buffer
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
binding: 1,
|
||||
visibility: wgpu::ShaderStage::Vertex,
|
||||
ty: wgpu::BufferBindingType::Buffer {
|
||||
ty: wgpu::BufferBindingType::
|
||||
ty: wgpu::BufferBindingType::
|
||||
}
|
||||
},
|
||||
],
|
||||
}),
|
||||
}),*/
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bind_locals(&self, device: &wgpu::Device, locals: Consts<Locals>) -> BoundLocals {
|
||||
fn bind_globals_inner(
|
||||
&self,
|
||||
device: &wgpu::Device,
|
||||
global_model: &GlobalModel,
|
||||
lod_data: &lod_terrain::LodData,
|
||||
noise: &Texture,
|
||||
sprite_verts: &Texture,
|
||||
) -> wgpu::BindGroup {
|
||||
let mut entries = GlobalsLayouts::bind_base_globals(global_model, lod_data, noise);
|
||||
|
||||
entries.extend_from_slice(&[
|
||||
// sprite verts (t_sprite_verts)
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 12,
|
||||
resource: wgpu::BindingResource::TextureView(&sprite_verts.view),
|
||||
},
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 13,
|
||||
resource: wgpu::BindingResource::Sampler(&sprite_verts.sampler),
|
||||
},
|
||||
]);
|
||||
|
||||
device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
label: None,
|
||||
layout: &self.globals,
|
||||
entries: &entries,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn bind_globals(
|
||||
&self,
|
||||
device: &wgpu::Device,
|
||||
global_model: &GlobalModel,
|
||||
lod_data: &lod_terrain::LodData,
|
||||
noise: &Texture,
|
||||
sprite_verts: &Texture,
|
||||
) -> SpriteGlobalsBindGroup {
|
||||
let bind_group =
|
||||
self.bind_globals_inner(device, global_model, lod_data, noise, sprite_verts);
|
||||
|
||||
SpriteGlobalsBindGroup { bind_group }
|
||||
}
|
||||
|
||||
/*pub fn bind_locals(&self, device: &wgpu::Device, locals: Consts<Locals>) -> BoundLocals {
|
||||
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
label: None,
|
||||
layout: &self.locals,
|
||||
@ -275,7 +375,7 @@ impl SpriteLayout {
|
||||
bind_group,
|
||||
with: locals,
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
pub struct SpritePipeline {
|
||||
@ -299,10 +399,11 @@ impl SpritePipeline {
|
||||
label: Some("Sprite pipeline layout"),
|
||||
push_constant_ranges: &[],
|
||||
bind_group_layouts: &[
|
||||
&global_layout.globals,
|
||||
&layout.globals,
|
||||
&global_layout.shadow_textures,
|
||||
&terrain_layout.locals,
|
||||
&layout.locals,
|
||||
//&layout.locals,
|
||||
// Note: mergable with globals
|
||||
&global_layout.col_light,
|
||||
],
|
||||
});
|
||||
@ -321,7 +422,7 @@ impl SpritePipeline {
|
||||
vertex: wgpu::VertexState {
|
||||
module: vs_module,
|
||||
entry_point: "main",
|
||||
buffers: &[],
|
||||
buffers: &[Instance::desc()],
|
||||
},
|
||||
primitive: wgpu::PrimitiveState {
|
||||
topology: wgpu::PrimitiveTopology::TriangleList,
|
||||
|
@ -152,7 +152,6 @@ impl Renderer {
|
||||
.ok_or(RenderError::CouldNotFindAdapter)?;
|
||||
|
||||
let limits = wgpu::Limits {
|
||||
max_bind_groups: 5,
|
||||
max_push_constant_size: 64,
|
||||
..Default::default()
|
||||
};
|
||||
@ -1009,7 +1008,7 @@ impl Renderer {
|
||||
}
|
||||
|
||||
/// Create a new immutable texture from the provided image.
|
||||
pub fn create_texture_with_data_raw(
|
||||
pub fn create_texture_with_data_raw<const BYTES_PER_PIXEL: u32>(
|
||||
&mut self,
|
||||
texture_info: &wgpu::TextureDescriptor,
|
||||
view_info: &wgpu::TextureViewDescriptor,
|
||||
@ -1018,7 +1017,7 @@ impl Renderer {
|
||||
) -> Texture {
|
||||
let tex = Texture::new_raw(&self.device, &texture_info, &view_info, &sampler_info);
|
||||
|
||||
tex.update(
|
||||
tex.update::<BYTES_PER_PIXEL>(
|
||||
&self.device,
|
||||
&self.queue,
|
||||
[0; 2],
|
||||
@ -1084,7 +1083,7 @@ impl Renderer {
|
||||
// texture.update(&mut self.encoder, offset, size, data)
|
||||
data: &[[u8; 4]],
|
||||
) {
|
||||
texture.update(
|
||||
texture.update::<4>(
|
||||
&self.device,
|
||||
&self.queue,
|
||||
offset,
|
||||
|
@ -20,6 +20,21 @@ impl Renderer {
|
||||
.bind(&self.device, global_model, lod_data, &self.noise_tex)
|
||||
}
|
||||
|
||||
pub fn bind_sprite_globals(
|
||||
&self,
|
||||
global_model: &GlobalModel,
|
||||
lod_data: &lod_terrain::LodData,
|
||||
sprite_verts: &Texture,
|
||||
) -> sprite::SpriteGlobalsBindGroup {
|
||||
self.layouts.sprite.bind_globals(
|
||||
&self.device,
|
||||
global_model,
|
||||
lod_data,
|
||||
&self.noise_tex,
|
||||
sprite_verts,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn create_ui_bound_locals(&mut self, vals: &[ui::Locals]) -> ui::BoundLocals {
|
||||
let locals = self.create_consts(vals);
|
||||
self.layouts.ui.bind_locals(&self.device, locals)
|
||||
@ -54,10 +69,10 @@ impl Renderer {
|
||||
self.layouts.shadow.bind_locals(&self.device, locals)
|
||||
}
|
||||
|
||||
pub fn create_sprite_bound_locals(&mut self, locals: &[sprite::Locals]) -> sprite::BoundLocals {
|
||||
let locals = self.create_consts(locals);
|
||||
self.layouts.sprite.bind_locals(&self.device, locals)
|
||||
}
|
||||
//pub fn create_sprite_bound_locals(&mut self, locals: &[sprite::Locals]) ->
|
||||
// sprite::BoundLocals { let locals = self.create_consts(locals);
|
||||
// self.layouts.sprite.bind_locals(&self.device, locals)
|
||||
//}
|
||||
|
||||
pub fn figure_bind_col_light(&self, col_light: Texture) -> ColLights<figure::Locals> {
|
||||
self.layouts.global.bind_col_light(&self.device, col_light)
|
||||
|
@ -132,6 +132,7 @@ impl<'frame> Drawer<'frame> {
|
||||
FirstPassDrawer {
|
||||
render_pass,
|
||||
borrow: &self.borrow,
|
||||
globals: self.globals,
|
||||
}
|
||||
}
|
||||
|
||||
@ -406,6 +407,7 @@ impl<'pass_ref, 'pass: 'pass_ref> TerrainShadowDrawer<'pass_ref, 'pass> {
|
||||
pub struct FirstPassDrawer<'pass> {
|
||||
pub(super) render_pass: OwningScope<'pass, wgpu::RenderPass<'pass>>,
|
||||
borrow: &'pass RendererBorrow<'pass>,
|
||||
globals: &'pass GlobalsBindGroup,
|
||||
}
|
||||
|
||||
impl<'pass> FirstPassDrawer<'pass> {
|
||||
@ -459,15 +461,20 @@ impl<'pass> FirstPassDrawer<'pass> {
|
||||
|
||||
pub fn draw_sprites<'data: 'pass>(
|
||||
&mut self,
|
||||
globals: &'data sprite::SpriteGlobalsBindGroup,
|
||||
col_lights: &'data ColLights<sprite::Locals>,
|
||||
) -> SpriteDrawer<'_, 'pass> {
|
||||
let mut render_pass = self.render_pass.scope(self.borrow.device, "sprites");
|
||||
|
||||
render_pass.set_pipeline(&self.borrow.pipelines.sprite.pipeline);
|
||||
set_quad_index_buffer::<particle::Vertex>(&mut render_pass, &self.borrow);
|
||||
render_pass.set_bind_group(4, &col_lights.bind_group, &[]);
|
||||
render_pass.set_bind_group(0, &globals.bind_group, &[]);
|
||||
render_pass.set_bind_group(3, &col_lights.bind_group, &[]);
|
||||
|
||||
SpriteDrawer { render_pass }
|
||||
SpriteDrawer {
|
||||
render_pass,
|
||||
globals: self.globals,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_fluid<'data: 'pass>(
|
||||
@ -561,49 +568,37 @@ impl<'pass_ref, 'pass: 'pass_ref> ParticleDrawer<'pass_ref, 'pass> {
|
||||
|
||||
pub struct SpriteDrawer<'pass_ref, 'pass: 'pass_ref> {
|
||||
render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>,
|
||||
globals: &'pass GlobalsBindGroup,
|
||||
}
|
||||
|
||||
impl<'pass_ref, 'pass: 'pass_ref> SpriteDrawer<'pass_ref, 'pass> {
|
||||
pub fn in_chunk<'data: 'pass>(
|
||||
pub fn draw<'data: 'pass>(
|
||||
&mut self,
|
||||
terrain_locals: &'data terrain::BoundLocals,
|
||||
) -> ChunkSpriteDrawer<'_, 'pass> {
|
||||
//model: &'data Model<sprite::Vertex>,
|
||||
//locals: &'data sprite::BoundLocals,
|
||||
instances: &'data Instances<sprite::Instance>,
|
||||
) {
|
||||
self.render_pass
|
||||
.set_bind_group(2, &terrain_locals.bind_group, &[]);
|
||||
//self.render_pass.set_bind_group(3, &locals.bind_group, &[]);
|
||||
|
||||
ChunkSpriteDrawer {
|
||||
render_pass: &mut self.render_pass,
|
||||
}
|
||||
/* //self.render_pass.set_vertex_buffer(0, model.buf().slice(..));
|
||||
//self.render_pass.set_vertex_buffer(0, model.buf().slice(..));
|
||||
self.render_pass
|
||||
.set_vertex_buffer(0, instances.buf().slice(..));
|
||||
self.render_pass.draw_indexed(
|
||||
0..sprite::VERT_PAGE_SIZE / 4 * 6,
|
||||
0,
|
||||
0..instances.count() as u32,
|
||||
); */
|
||||
);
|
||||
}
|
||||
}
|
||||
pub struct ChunkSpriteDrawer<'pass_ref, 'pass: 'pass_ref> {
|
||||
render_pass: &'pass_ref mut wgpu::RenderPass<'pass>,
|
||||
}
|
||||
|
||||
impl<'pass_ref, 'pass: 'pass_ref> ChunkSpriteDrawer<'pass_ref, 'pass> {
|
||||
pub fn draw<'data: 'pass>(
|
||||
&mut self,
|
||||
model: &'data Model<sprite::Vertex>,
|
||||
instances: &'data Instances<sprite::Instance>,
|
||||
locals: &'data sprite::BoundLocals,
|
||||
) {
|
||||
self.render_pass.set_vertex_buffer(0, model.buf().slice(..));
|
||||
impl<'pass_ref, 'pass: 'pass_ref> Drop for SpriteDrawer<'pass_ref, 'pass> {
|
||||
fn drop(&mut self) {
|
||||
// Reset to regular globals
|
||||
self.render_pass
|
||||
.set_vertex_buffer(1, instances.buf().slice(..));
|
||||
self.render_pass.set_bind_group(3, &locals.bind_group, &[]);
|
||||
self.render_pass.draw_indexed(
|
||||
0..model.len() as u32 / 4 * 6,
|
||||
0,
|
||||
0..instances.count() as u32,
|
||||
);
|
||||
.set_bind_group(0, &self.globals.bind_group, &[]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -170,7 +170,9 @@ impl Texture {
|
||||
|
||||
/// Update a texture with the given data (used for updating the glyph cache
|
||||
/// texture).
|
||||
pub fn update(
|
||||
/// TODO: using generic here seems a bit hacky, consider storing this info
|
||||
/// in the texture type or pass in wgpu::TextureFormat
|
||||
pub fn update<const BYTES_PER_PIXEL: u32>(
|
||||
&self,
|
||||
device: &wgpu::Device,
|
||||
queue: &wgpu::Queue,
|
||||
@ -178,9 +180,10 @@ impl Texture {
|
||||
size: [u32; 2],
|
||||
data: &[u8],
|
||||
) {
|
||||
// Note: we only accept 4 bytes per pixel
|
||||
// (enforce this in API?)
|
||||
debug_assert_eq!(data.len(), size[0] as usize * size[1] as usize * 4);
|
||||
debug_assert_eq!(
|
||||
data.len(),
|
||||
size[0] as usize * size[1] as usize * BYTES_PER_PIXEL as usize
|
||||
);
|
||||
// TODO: Only works for 2D images
|
||||
queue.write_texture(
|
||||
wgpu::TextureCopyViewBase {
|
||||
@ -195,7 +198,7 @@ impl Texture {
|
||||
data,
|
||||
wgpu::TextureDataLayout {
|
||||
offset: 0,
|
||||
bytes_per_row: size[0] * 4,
|
||||
bytes_per_row: size[0] * BYTES_PER_PIXEL,
|
||||
rows_per_image: size[1],
|
||||
},
|
||||
wgpu::Extent3d {
|
||||
|
@ -276,6 +276,8 @@ impl Scene {
|
||||
|
||||
let globals_bind_group = renderer.bind_globals(&data, lod.get_data());
|
||||
|
||||
let terrain = Terrain::new(renderer, &data, lod.get_data(), sprite_render_context);
|
||||
|
||||
Self {
|
||||
data,
|
||||
globals_bind_group,
|
||||
@ -286,7 +288,7 @@ impl Scene {
|
||||
skybox: Skybox {
|
||||
model: renderer.create_model(&create_skybox_mesh()).unwrap(),
|
||||
},
|
||||
terrain: Terrain::new(renderer, sprite_render_context),
|
||||
terrain,
|
||||
lod,
|
||||
loaded_distance: 0.0,
|
||||
map_bounds: Vec2::new(
|
||||
|
@ -1,4 +1,5 @@
|
||||
mod watcher;
|
||||
|
||||
pub use self::watcher::{BlocksOfInterest, Interaction};
|
||||
|
||||
use crate::{
|
||||
@ -8,10 +9,11 @@ use crate::{
|
||||
terrain::{generate_mesh, SUNLIGHT},
|
||||
},
|
||||
render::{
|
||||
create_sprite_verts_texture,
|
||||
pipelines::{self, ColLights},
|
||||
ColLightInfo, Consts, Drawer, FirstPassDrawer, FluidVertex, FluidWaves, GlobalModel,
|
||||
Instances, LodData, Mesh, Model, RenderError, Renderer, SpriteInstance, SpriteLocals,
|
||||
SpriteVertex, TerrainLocals, TerrainShadowDrawer, TerrainVertex, Texture,
|
||||
Instances, LodData, Mesh, Model, RenderError, Renderer, SpriteGlobalsBindGroup,
|
||||
SpriteInstance, SpriteVertex, TerrainLocals, TerrainShadowDrawer, TerrainVertex, Texture,
|
||||
},
|
||||
};
|
||||
|
||||
@ -42,6 +44,8 @@ use treeculler::{BVol, Frustum, AABB};
|
||||
use vek::*;
|
||||
|
||||
const SPRITE_SCALE: Vec3<f32> = Vec3::new(1.0 / 11.0, 1.0 / 11.0, 1.0 / 11.0);
|
||||
const SPRITE_LOD_LEVELS: usize = 5;
|
||||
const SPRITE_VERT_PAGE_SIZE: usize = 256;
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
struct Visibility {
|
||||
@ -79,7 +83,7 @@ pub struct TerrainChunkData {
|
||||
col_lights: Arc<ColLights<pipelines::terrain::Locals>>,
|
||||
light_map: Box<dyn Fn(Vec3<i32>) -> f32 + Send + Sync>,
|
||||
glow_map: Box<dyn Fn(Vec3<i32>) -> f32 + Send + Sync>,
|
||||
sprite_instances: HashMap<(SpriteKind, usize), Instances<SpriteInstance>>,
|
||||
sprite_instances: [Instances<SpriteInstance>; SPRITE_LOD_LEVELS],
|
||||
locals: pipelines::terrain::BoundLocals,
|
||||
pub blocks_of_interest: BlocksOfInterest,
|
||||
|
||||
@ -107,7 +111,7 @@ struct MeshWorkerResponse {
|
||||
col_lights_info: ColLightInfo,
|
||||
light_map: Box<dyn Fn(Vec3<i32>) -> f32 + Send + Sync>,
|
||||
glow_map: Box<dyn Fn(Vec3<i32>) -> f32 + Send + Sync>,
|
||||
sprite_instances: HashMap<(SpriteKind, usize), Vec<SpriteInstance>>,
|
||||
sprite_instances: [Vec<SpriteInstance>; SPRITE_LOD_LEVELS],
|
||||
started_tick: u64,
|
||||
blocks_of_interest: BlocksOfInterest,
|
||||
}
|
||||
@ -162,7 +166,7 @@ fn mesh_worker<V: BaseVol<Vox = Block> + RectRasterableVol + ReadVol + Debug + '
|
||||
max_texture_size: u16,
|
||||
chunk: Arc<TerrainChunk>,
|
||||
range: Aabb<i32>,
|
||||
sprite_data: &HashMap<(SpriteKind, usize), Vec<SpriteData>>,
|
||||
sprite_data: &HashMap<(SpriteKind, usize), [SpriteData; SPRITE_LOD_LEVELS]>,
|
||||
sprite_config: &SpriteSpec,
|
||||
) -> MeshWorkerResponse {
|
||||
span!(_guard, "mesh_worker");
|
||||
@ -185,7 +189,7 @@ fn mesh_worker<V: BaseVol<Vox = Block> + RectRasterableVol + ReadVol + Debug + '
|
||||
// Extract sprite locations from volume
|
||||
sprite_instances: {
|
||||
span!(_guard, "extract sprite_instances");
|
||||
let mut instances = HashMap::new();
|
||||
let mut instances = [Vec::new(), Vec::new(), Vec::new(), Vec::new(), Vec::new()];
|
||||
|
||||
for x in 0..V::RECT_SIZE.x as i32 {
|
||||
for y in 0..V::RECT_SIZE.y as i32 {
|
||||
@ -213,23 +217,43 @@ fn mesh_worker<V: BaseVol<Vox = Block> + RectRasterableVol + ReadVol + Debug + '
|
||||
let key = (sprite, variation);
|
||||
// NOTE: Safe because we called sprite_config_for already.
|
||||
// NOTE: Safe because 0 ≤ ori < 8
|
||||
let sprite_data = &sprite_data[&key][0];
|
||||
let instance = SpriteInstance::new(
|
||||
Mat4::identity()
|
||||
.translated_3d(sprite_data.offset)
|
||||
let sprite_data_lod_0 = &sprite_data[&key][0];
|
||||
let mat = Mat4::identity()
|
||||
// NOTE: offset doesn't change with lod level
|
||||
// TODO: pull out of per lod level info or remove lod levels
|
||||
// for sprites entirely
|
||||
.translated_3d(sprite_data_lod_0.offset)
|
||||
// Lod scaling etc is baked during meshing
|
||||
.scaled_3d(SPRITE_SCALE)
|
||||
.rotated_z(f32::consts::PI * 0.25 * ori as f32)
|
||||
.translated_3d(
|
||||
(rel_pos.map(|e| e as f32) + Vec3::new(0.5, 0.5, 0.0))
|
||||
/ SPRITE_SCALE,
|
||||
),
|
||||
cfg.wind_sway,
|
||||
rel_pos,
|
||||
ori,
|
||||
light_map(wpos),
|
||||
glow_map(wpos),
|
||||
);
|
||||
);
|
||||
let light = light_map(wpos);
|
||||
let glow = glow_map(wpos);
|
||||
|
||||
instances.entry(key).or_insert(Vec::new()).push(instance);
|
||||
for lod_level in 0..SPRITE_LOD_LEVELS {
|
||||
let sprite_data = &sprite_data[&key][lod_level];
|
||||
// Add an instance for each page in the sprite model
|
||||
for page in sprite_data.vert_pages.clone() {
|
||||
// TODO: could be more efficient to create once and clone while
|
||||
// modifying vert_page
|
||||
let instance = SpriteInstance::new(
|
||||
mat,
|
||||
cfg.wind_sway,
|
||||
sprite_data.scale.z,
|
||||
rel_pos,
|
||||
ori,
|
||||
light,
|
||||
glow,
|
||||
page,
|
||||
);
|
||||
instances[lod_level].push(instance);
|
||||
}
|
||||
}
|
||||
|
||||
//instances.entry(key).or_insert(Vec::new()).
|
||||
// push(instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -244,11 +268,18 @@ fn mesh_worker<V: BaseVol<Vox = Block> + RectRasterableVol + ReadVol + Debug + '
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: may be unecessary
|
||||
struct ChunkSpriteData {
|
||||
// Instances
|
||||
model: Instances<SpriteInstance>,
|
||||
}
|
||||
|
||||
struct SpriteData {
|
||||
/* mat: Mat4<f32>, */
|
||||
locals: pipelines::sprite::BoundLocals,
|
||||
model: Model<SpriteVertex>,
|
||||
/* scale: Vec3<f32>, */
|
||||
// Sprite vert page ranges that need to be drawn
|
||||
vert_pages: core::ops::Range<u32>,
|
||||
// Scale
|
||||
scale: Vec3<f32>,
|
||||
// Offset
|
||||
offset: Vec3<f32>,
|
||||
}
|
||||
|
||||
@ -298,8 +329,10 @@ pub struct Terrain<V: RectRasterableVol = TerrainChunk> {
|
||||
mesh_todos_active: Arc<AtomicU64>,
|
||||
|
||||
// GPU data
|
||||
sprite_data: Arc<HashMap<(SpriteKind, usize), Vec<SpriteData>>>,
|
||||
sprite_col_lights: ColLights<pipelines::sprite::Locals>,
|
||||
// Maps sprite kind + variant to data detailing how to render it
|
||||
sprite_data: Arc<HashMap<(SpriteKind, usize), [SpriteData; SPRITE_LOD_LEVELS]>>,
|
||||
sprite_globals: SpriteGlobalsBindGroup,
|
||||
sprite_col_lights: Arc<ColLights<pipelines::sprite::Locals>>,
|
||||
/// As stated previously, this is always the very latest texture into which
|
||||
/// we allocate. Code cannot assume that this is the assigned texture
|
||||
/// for any particular chunk; look at the `texture` field in
|
||||
@ -317,8 +350,10 @@ impl TerrainChunkData {
|
||||
#[derive(Clone)]
|
||||
pub struct SpriteRenderContext {
|
||||
sprite_config: Arc<SpriteSpec>,
|
||||
sprite_data: Arc<HashMap<(SpriteKind, usize), Vec<SpriteData>>>,
|
||||
sprite_col_lights: Texture, /* <ColLightFmt> */
|
||||
// Maps sprite kind + variant to data detailing how to render it
|
||||
sprite_data: Arc<HashMap<(SpriteKind, usize), [SpriteData; SPRITE_LOD_LEVELS]>>,
|
||||
sprite_col_lights: Arc<ColLights<pipelines::sprite::Locals>>,
|
||||
sprite_verts_texture: Arc<Texture>,
|
||||
}
|
||||
|
||||
pub type SpriteRenderContextLazy = Box<dyn FnMut(&mut Renderer) -> SpriteRenderContext>;
|
||||
@ -328,16 +363,11 @@ impl SpriteRenderContext {
|
||||
pub fn new(renderer: &mut Renderer) -> SpriteRenderContextLazy {
|
||||
let max_texture_size = renderer.max_texture_size();
|
||||
|
||||
struct SpriteDataResponse {
|
||||
locals: [SpriteLocals; 8],
|
||||
model: Mesh<SpriteVertex>,
|
||||
offset: Vec3<f32>,
|
||||
}
|
||||
|
||||
struct SpriteWorkerResponse {
|
||||
sprite_config: Arc<SpriteSpec>,
|
||||
sprite_data: HashMap<(SpriteKind, usize), Vec<SpriteDataResponse>>,
|
||||
sprite_data: HashMap<(SpriteKind, usize), [SpriteData; SPRITE_LOD_LEVELS]>,
|
||||
sprite_col_lights: ColLightInfo,
|
||||
sprite_mesh: Mesh<SpriteVertex>,
|
||||
}
|
||||
|
||||
let join_handle = std::thread::spawn(move || {
|
||||
@ -347,7 +377,8 @@ impl SpriteRenderContext {
|
||||
|
||||
let max_size = guillotiere::Size::new(max_texture_size as i32, max_texture_size as i32);
|
||||
let mut greedy = GreedyMesh::new(max_size);
|
||||
let mut locals_buffer = [SpriteLocals::default(); 8];
|
||||
// let mut locals_buffer = [SpriteLocals::default(); 8];
|
||||
let mut sprite_mesh = Mesh::new();
|
||||
let sprite_config_ = &sprite_config;
|
||||
// NOTE: Tracks the start vertex of the next model to be meshed.
|
||||
let sprite_data: HashMap<(SpriteKind, usize), _> = SpriteKind::into_enum_iter()
|
||||
@ -390,62 +421,68 @@ impl SpriteRenderContext {
|
||||
scale
|
||||
}
|
||||
});
|
||||
let sprite_mat: Mat4<f32> =
|
||||
Mat4::translation_3d(offset).scaled_3d(SPRITE_SCALE);
|
||||
move |greedy: &mut GreedyMesh| {
|
||||
(
|
||||
(kind, variation),
|
||||
scaled
|
||||
.iter()
|
||||
.map(|&lod_scale_orig| {
|
||||
let lod_scale = model_scale
|
||||
* if lod_scale_orig == 1.0 {
|
||||
Vec3::broadcast(1.0)
|
||||
} else {
|
||||
lod_axes * lod_scale_orig
|
||||
+ lod_axes.map(|e| {
|
||||
if e == 0.0 { 1.0 } else { 0.0 }
|
||||
})
|
||||
};
|
||||
// Mesh generation exclusively acts using side effects;
|
||||
// it has no
|
||||
// interesting return value, but updates the mesh.
|
||||
let mut opaque_mesh = Mesh::new();
|
||||
generate_mesh_base_vol_sprite(
|
||||
Segment::from(&model.read().0).scaled_by(lod_scale),
|
||||
(greedy, &mut opaque_mesh, false),
|
||||
);
|
||||
//let sprite_mat: Mat4<f32> =
|
||||
// Mat4::translation_3d(offset).scaled_3d(SPRITE_SCALE);
|
||||
move |greedy: &mut GreedyMesh, sprite_mesh: &mut Mesh<SpriteVertex>| {
|
||||
let lod_sprite_data = scaled.map(|lod_scale_orig| {
|
||||
let lod_scale = model_scale
|
||||
* if lod_scale_orig == 1.0 {
|
||||
Vec3::broadcast(1.0)
|
||||
} else {
|
||||
lod_axes * lod_scale_orig
|
||||
+ lod_axes.map(|e| if e == 0.0 { 1.0 } else { 0.0 })
|
||||
};
|
||||
|
||||
let sprite_scale = Vec3::one() / lod_scale;
|
||||
let sprite_mat: Mat4<f32> =
|
||||
sprite_mat * Mat4::scaling_3d(sprite_scale);
|
||||
locals_buffer.iter_mut().enumerate().for_each(
|
||||
|(ori, locals)| {
|
||||
let sprite_mat = sprite_mat.rotated_z(
|
||||
f32::consts::PI * 0.25 * ori as f32,
|
||||
);
|
||||
*locals = SpriteLocals::new(
|
||||
sprite_mat,
|
||||
sprite_scale,
|
||||
offset,
|
||||
wind_sway,
|
||||
);
|
||||
},
|
||||
);
|
||||
// Get starting page count of opaque mesh
|
||||
let start_page_num =
|
||||
sprite_mesh.vertices().len() / SPRITE_VERT_PAGE_SIZE;
|
||||
// Mesh generation exclusively acts using side effects; it
|
||||
// has no interesting return value, but updates the mesh.
|
||||
generate_mesh_base_vol_sprite(
|
||||
Segment::from(&model.read().0).scaled_by(lod_scale),
|
||||
(greedy, sprite_mesh, false),
|
||||
);
|
||||
// Get the number of pages after the model was meshed
|
||||
let end_page_num =
|
||||
(sprite_mesh.vertices().len() + SPRITE_VERT_PAGE_SIZE - 1)
|
||||
/ SPRITE_VERT_PAGE_SIZE;
|
||||
// Fill the current last page up with degenerate verts
|
||||
sprite_mesh.vertices_mut_vec().resize_with(
|
||||
end_page_num * SPRITE_VERT_PAGE_SIZE,
|
||||
SpriteVertex::default,
|
||||
);
|
||||
|
||||
SpriteDataResponse {
|
||||
model: opaque_mesh,
|
||||
let sprite_scale = Vec3::one() / lod_scale;
|
||||
//let sprite_mat: Mat4<f32> =
|
||||
// sprite_mat * Mat4::scaling_3d(sprite_scale);
|
||||
/*locals_buffer.iter_mut().enumerate().for_each(
|
||||
|(ori, locals)| {
|
||||
let sprite_mat = sprite_mat.rotated_z(
|
||||
f32::consts::PI * 0.25 * ori as f32,
|
||||
);
|
||||
*locals = SpriteLocals::new(
|
||||
sprite_mat,
|
||||
sprite_scale,
|
||||
offset,
|
||||
locals: locals_buffer,
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
wind_sway,
|
||||
);
|
||||
},
|
||||
);*/
|
||||
|
||||
SpriteData {
|
||||
vert_pages: start_page_num as u32..end_page_num as u32,
|
||||
scale: sprite_scale,
|
||||
offset,
|
||||
//locals: locals_buffer,
|
||||
}
|
||||
});
|
||||
|
||||
((kind, variation), lod_sprite_data)
|
||||
}
|
||||
},
|
||||
)
|
||||
})
|
||||
.map(|mut f| f(&mut greedy))
|
||||
.map(|mut f| f(&mut greedy, &mut sprite_mesh))
|
||||
.collect();
|
||||
|
||||
let sprite_col_lights = greedy.finalize();
|
||||
@ -454,6 +491,7 @@ impl SpriteRenderContext {
|
||||
sprite_config,
|
||||
sprite_data,
|
||||
sprite_col_lights,
|
||||
sprite_mesh,
|
||||
}
|
||||
});
|
||||
|
||||
@ -468,6 +506,7 @@ impl SpriteRenderContext {
|
||||
sprite_config,
|
||||
sprite_data,
|
||||
sprite_col_lights,
|
||||
sprite_mesh,
|
||||
} = join_handle
|
||||
.take()
|
||||
.expect(
|
||||
@ -477,39 +516,19 @@ impl SpriteRenderContext {
|
||||
.join()
|
||||
.unwrap();
|
||||
|
||||
let sprite_data = sprite_data
|
||||
.into_iter()
|
||||
.map(|(key, models)| {
|
||||
(
|
||||
key,
|
||||
models
|
||||
.into_iter()
|
||||
.map(
|
||||
|SpriteDataResponse {
|
||||
locals: locals_buffer,
|
||||
model,
|
||||
offset,
|
||||
}| {
|
||||
SpriteData {
|
||||
locals: renderer.create_sprite_bound_locals(&locals_buffer),
|
||||
model: renderer.create_model(&model).expect(
|
||||
"Failed to upload sprite model data to the GPU!",
|
||||
),
|
||||
offset,
|
||||
}
|
||||
},
|
||||
)
|
||||
.collect(),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
let sprite_col_lights =
|
||||
pipelines::shadow::create_col_lights(renderer, &sprite_col_lights);
|
||||
let sprite_col_lights = renderer.sprite_bind_col_light(sprite_col_lights);
|
||||
|
||||
// Write sprite model to a 1D texture
|
||||
let sprite_verts_texture = create_sprite_verts_texture(renderer, sprite_mesh);
|
||||
|
||||
Self {
|
||||
// TODO: this are all Arcs, would it makes sense to factor out the Arc?
|
||||
sprite_config: Arc::clone(&sprite_config),
|
||||
sprite_data: Arc::new(sprite_data),
|
||||
sprite_col_lights,
|
||||
sprite_col_lights: Arc::new(sprite_col_lights),
|
||||
sprite_verts_texture: Arc::new(sprite_verts_texture),
|
||||
}
|
||||
};
|
||||
Box::new(move |renderer| init.get_or_init(|| closure(renderer)).clone())
|
||||
@ -517,7 +536,12 @@ impl SpriteRenderContext {
|
||||
}
|
||||
|
||||
impl<V: RectRasterableVol> Terrain<V> {
|
||||
pub fn new(renderer: &mut Renderer, sprite_render_context: SpriteRenderContext) -> Self {
|
||||
pub fn new(
|
||||
renderer: &mut Renderer,
|
||||
global_model: &GlobalModel,
|
||||
lod_data: &LodData,
|
||||
sprite_render_context: SpriteRenderContext,
|
||||
) -> Self {
|
||||
// Create a new mpsc (Multiple Produced, Single Consumer) pair for communicating
|
||||
// with worker threads that are meshing chunks.
|
||||
let (send, recv) = channel::unbounded();
|
||||
@ -535,8 +559,13 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
mesh_todo: HashMap::default(),
|
||||
mesh_todos_active: Arc::new(AtomicU64::new(0)),
|
||||
sprite_data: sprite_render_context.sprite_data,
|
||||
sprite_col_lights: renderer
|
||||
.sprite_bind_col_light(sprite_render_context.sprite_col_lights),
|
||||
sprite_col_lights: sprite_render_context.sprite_col_lights,
|
||||
sprite_globals: renderer.bind_sprite_globals(
|
||||
global_model,
|
||||
lod_data,
|
||||
&sprite_render_context.sprite_verts_texture,
|
||||
),
|
||||
col_lights: Arc::new(col_lights),
|
||||
waves: {
|
||||
let waves_tex = renderer
|
||||
.create_texture(
|
||||
@ -548,7 +577,6 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
|
||||
renderer.fluid_bind_waves(waves_tex)
|
||||
},
|
||||
col_lights: Arc::new(col_lights),
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
@ -1027,18 +1055,20 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
col_lights: Arc::clone(&self.col_lights),
|
||||
light_map: response.light_map,
|
||||
glow_map: response.glow_map,
|
||||
sprite_instances: response
|
||||
.sprite_instances
|
||||
.into_iter()
|
||||
.map(|(kind, instances)| {
|
||||
(
|
||||
kind,
|
||||
renderer.create_instances(&instances).expect(
|
||||
"Failed to upload chunk sprite instances to the GPU!",
|
||||
),
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
sprite_instances: {
|
||||
let mut iter = response.sprite_instances.iter().map(|instances| {
|
||||
renderer
|
||||
.create_instances(instances)
|
||||
.expect("Failed to upload chunk sprite instances to the GPU!")
|
||||
});
|
||||
[
|
||||
iter.next().unwrap(),
|
||||
iter.next().unwrap(),
|
||||
iter.next().unwrap(),
|
||||
iter.next().unwrap(),
|
||||
iter.next().unwrap(),
|
||||
]
|
||||
},
|
||||
locals: renderer.create_terrain_bound_locals(&[TerrainLocals {
|
||||
model_offs: Vec3::from(
|
||||
response.pos.map2(VolGrid2d::<V>::chunk_size(), |e, sz| {
|
||||
@ -1363,15 +1393,21 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
span!(guard, "Terrain sprites");
|
||||
let chunk_size = V::RECT_SIZE.map(|e| e as f32);
|
||||
let chunk_mag = (chunk_size * (f32::consts::SQRT_2 * 0.5)).magnitude_squared();
|
||||
let mut sprite_drawer = drawer.draw_sprites(&self.sprite_col_lights);
|
||||
|
||||
let sprite_low_detail_distance = sprite_render_distance * 0.75;
|
||||
let sprite_mid_detail_distance = sprite_render_distance * 0.5;
|
||||
let sprite_hid_detail_distance = sprite_render_distance * 0.35;
|
||||
let sprite_high_detail_distance = sprite_render_distance * 0.15;
|
||||
|
||||
let mut sprite_drawer = drawer.draw_sprites(&self.sprite_globals, &self.sprite_col_lights);
|
||||
chunk_iter
|
||||
.clone()
|
||||
.filter(|(_, c)| c.visible.is_visible())
|
||||
.for_each(|(pos, chunk)| {
|
||||
let sprite_low_detail_distance = sprite_render_distance * 0.75;
|
||||
let sprite_mid_detail_distance = sprite_render_distance * 0.5;
|
||||
let sprite_hid_detail_distance = sprite_render_distance * 0.35;
|
||||
let sprite_high_detail_distance = sprite_render_distance * 0.15;
|
||||
// Skip chunk if it has no sprites
|
||||
if chunk.sprite_instances[0].count() == 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
let chunk_center = pos.map2(chunk_size, |e, sz| (e as f32 + 0.5) * sz);
|
||||
let focus_dist_sqrd = Vec2::from(focus_pos).distance_squared(chunk_center);
|
||||
@ -1389,31 +1425,27 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
chunk_center + chunk_size.x * 0.5 - chunk_size.y * 0.5,
|
||||
));
|
||||
if focus_dist_sqrd < sprite_render_distance.powi(2) {
|
||||
// TODO: skip if sprite_instances is empty
|
||||
let mut chunk_sprite_drawer = sprite_drawer.in_chunk(&chunk.locals);
|
||||
for (kind, instances) in (&chunk.sprite_instances).into_iter() {
|
||||
let SpriteData { model, locals, .. } = if kind
|
||||
.0
|
||||
.elim_case_pure(&self.sprite_config.0)
|
||||
.as_ref()
|
||||
.map(|config| config.wind_sway >= 0.4)
|
||||
.unwrap_or(false)
|
||||
&& dist_sqrd <= chunk_mag
|
||||
|| dist_sqrd < sprite_high_detail_distance.powi(2)
|
||||
{
|
||||
&self.sprite_data[&kind][0]
|
||||
} else if dist_sqrd < sprite_hid_detail_distance.powi(2) {
|
||||
&self.sprite_data[&kind][1]
|
||||
} else if dist_sqrd < sprite_mid_detail_distance.powi(2) {
|
||||
&self.sprite_data[&kind][2]
|
||||
} else if dist_sqrd < sprite_low_detail_distance.powi(2) {
|
||||
&self.sprite_data[&kind][3]
|
||||
} else {
|
||||
&self.sprite_data[&kind][4]
|
||||
};
|
||||
let lod_level = /*let SpriteData { model, locals, .. } = if kind
|
||||
.0
|
||||
.elim_case_pure(&self.sprite_config.0)
|
||||
.as_ref()
|
||||
.map(|config| config.wind_sway >= 0.4)
|
||||
.unwrap_or(false)
|
||||
&&*/ if dist_sqrd <= chunk_mag
|
||||
|| dist_sqrd < sprite_high_detail_distance.powi(2)
|
||||
{
|
||||
0
|
||||
} else if dist_sqrd < sprite_hid_detail_distance.powi(2) {
|
||||
1
|
||||
} else if dist_sqrd < sprite_mid_detail_distance.powi(2) {
|
||||
2
|
||||
} else if dist_sqrd < sprite_low_detail_distance.powi(2) {
|
||||
3
|
||||
} else {
|
||||
4
|
||||
};
|
||||
|
||||
chunk_sprite_drawer.draw(model, instances, locals);
|
||||
}
|
||||
sprite_drawer.draw(&chunk.locals, &chunk.sprite_instances[lod_level]);
|
||||
}
|
||||
});
|
||||
drop(sprite_drawer);
|
||||
|
@ -598,7 +598,7 @@ impl Window {
|
||||
|
||||
let scale_factor = window.scale_factor();
|
||||
|
||||
let key_layout = match KeyLayout::new_from_window(window.window()) {
|
||||
let key_layout = match KeyLayout::new_from_window(&window) {
|
||||
Ok(kl) => Some(kl),
|
||||
Err(err) => {
|
||||
warn!(
|
||||
|
Loading…
Reference in New Issue
Block a user