From e11ee195972faa0e522a6ca2feecff161b9f8935 Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Sat, 4 May 2024 14:30:06 +0200 Subject: [PATCH 01/51] rip out some parts of glium --- Cargo.lock | 832 +++++++++++++++++++++++++++------- kubi/Cargo.toml | 9 +- kubi/src/hui_integration.rs | 12 +- kubi/src/prefabs.rs | 20 +- kubi/src/rendering.rs | 89 +--- kubi/src/rendering/shaders.rs | 0 6 files changed, 684 insertions(+), 278 deletions(-) create mode 100644 kubi/src/rendering/shaders.rs diff --git a/Cargo.lock b/Cargo.lock index ef609d4..18d8023 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18,15 +18,6 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046" -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -dependencies = [ - "gimli", -] - [[package]] name = "adler" version = "1.0.2" @@ -75,9 +66,30 @@ dependencies = [ "jni-sys", "libc", "log", - "ndk", + "ndk 0.8.0", "ndk-context", - "ndk-sys", + "ndk-sys 0.5.0+25.2.9519653", + "num_enum", + "thiserror", +] + +[[package]] +name = "android-activity" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046" +dependencies = [ + "android-properties", + "bitflags 2.5.0", + "cc", + "cesu8", + "jni", + "jni-sys", + "libc", + "log", + "ndk 0.9.0", + "ndk-context", + "ndk-sys 0.6.0+11769913", "num_enum", "thiserror", ] @@ -145,6 +157,15 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b" +[[package]] +name = "ash" +version = "0.37.3+1.3.251" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39e9c3835d686b0a6084ab4234fcd1b07dbf6e4767dce60874b12356a25ecd4a" +dependencies = [ + "libloading 0.7.4", +] + [[package]] name = "atomic" version = "0.6.0" @@ -175,21 +196,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" -[[package]] -name = "backtrace" -version = "0.3.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - [[package]] name = "base64" version = "0.22.0" @@ -205,6 +211,21 @@ dependencies = [ "serde", ] +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + [[package]] name = "bitflags" version = "1.3.2" @@ -217,6 +238,12 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + [[package]] name = "block-sys" version = "0.2.1" @@ -233,7 +260,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15b55663a85f33501257357e6421bb33e769d5c9ffb5ba0921c975a123e35e68" dependencies = [ "block-sys", - "objc2", + "objc2 0.4.1", +] + +[[package]] +name = "block2" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43ff7d91d3c1d568065b06c899777d1e48dcf76103a672a0adbc238a7f247f1e" +dependencies = [ + "objc2 0.5.1", ] [[package]] @@ -330,13 +366,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" [[package]] -name = "cgl" -version = "0.3.2" +name = "cfg_aliases" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ced0551234e87afee12411d535648dd89d2e7f34c78b753395567aff3d447ff" -dependencies = [ - "libc", -] +checksum = "77e53693616d3075149f4ead59bdeecd204ac6b8192d8969757601b74bddf00f" [[package]] name = "chrono" @@ -357,6 +390,47 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" +[[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 = "com" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e17887fd17353b65b1b2ef1c526c83e26cd72e74f598a8dc1bee13a48f3d9f6" +dependencies = [ + "com_macros", +] + +[[package]] +name = "com_macros" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d375883580a668c7481ea6631fc1a8863e33cc335bf56bfad8d7e6d4b04b13a5" +dependencies = [ + "com_macros_support", + "proc-macro2", + "syn 1.0.109", +] + +[[package]] +name = "com_macros_support" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad899a1087a9296d5644792d7cb72b8e34c1bec8e7d4fbc002230169a6e8710c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "combine" version = "4.6.7" @@ -468,6 +542,17 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991" +[[package]] +name = "d3d12" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b28bfe653d79bd16c77f659305b195b82bb5ce0c0eb2a4846b82ddbd77586813" +dependencies = [ + "bitflags 2.5.0", + "libloading 0.8.3", + "winapi", +] + [[package]] name = "darling" version = "0.20.8" @@ -550,7 +635,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" dependencies = [ - "libloading", + "libloading 0.8.3", ] [[package]] @@ -568,6 +653,12 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" +[[package]] +name = "dpi" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f25c0e292a7ca6d6498557ff1df68f32c99850012b6ea401cf8daf771f22ff53" + [[package]] name = "either" version = "1.11.0" @@ -762,12 +853,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "gimli" -version = "0.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" - [[package]] name = "gl_generator" version = "0.14.0" @@ -789,77 +874,15 @@ dependencies = [ ] [[package]] -name = "glium" -version = "0.34.0" -source = "git+https://github.com/glium/glium?rev=a352c667#a352c667c145e2dda1f5fe1fc2482cbe99de23be" -dependencies = [ - "backtrace", - "fnv", - "gl_generator", - "glutin", - "glutin-winit", - "lazy_static", - "memoffset", - "raw-window-handle 0.5.2", - "smallvec", - "takeable-option", - "winit", -] - -[[package]] -name = "glutin" -version = "0.31.3" +name = "glow" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fcd4ae4e86d991ad1300b8f57166e5be0c95ef1f63f3f5b827f8a164548746" +checksum = "bd348e04c43b32574f2de31c8bb397d96c9fcfa1371bd4ca6d8bdc464ab121b1" dependencies = [ - "bitflags 2.5.0", - "cfg_aliases", - "cgl", - "core-foundation", - "dispatch", - "glutin_egl_sys", - "glutin_glx_sys", - "glutin_wgl_sys", - "icrate", - "libloading", - "objc2", - "once_cell", - "raw-window-handle 0.5.2", - "wayland-sys", - "windows-sys 0.48.0", - "x11-dl", -] - -[[package]] -name = "glutin-winit" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebcdfba24f73b8412c5181e56f092b5eff16671c514ce896b258a0a64bd7735" -dependencies = [ - "cfg_aliases", - "glutin", - "raw-window-handle 0.5.2", - "winit", -] - -[[package]] -name = "glutin_egl_sys" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77cc5623f5309ef433c3dd4ca1223195347fe62c413da8e2fdd0eb76db2d9bcd" -dependencies = [ - "gl_generator", - "windows-sys 0.48.0", -] - -[[package]] -name = "glutin_glx_sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a165fd686c10dcc2d45380b35796e577eacfd43d4660ee741ec8ebe2201b3b4f" -dependencies = [ - "gl_generator", - "x11-dl", + "js-sys", + "slotmap", + "wasm-bindgen", + "web-sys", ] [[package]] @@ -871,6 +894,58 @@ dependencies = [ "gl_generator", ] +[[package]] +name = "gpu-alloc" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171" +dependencies = [ + "bitflags 2.5.0", + "gpu-alloc-types", +] + +[[package]] +name = "gpu-alloc-types" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4" +dependencies = [ + "bitflags 2.5.0", +] + +[[package]] +name = "gpu-allocator" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f56f6318968d03c18e1bcf4857ff88c61157e9da8e47c5f29055d60e1228884" +dependencies = [ + "log", + "presser", + "thiserror", + "winapi", + "windows", +] + +[[package]] +name = "gpu-descriptor" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c08c1f623a8d0b722b8b99f821eb0ba672a1618f0d3b16ddbee1cedd2dd8557" +dependencies = [ + "bitflags 2.5.0", + "gpu-descriptor-types", + "hashbrown 0.14.3", +] + +[[package]] +name = "gpu-descriptor-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91" +dependencies = [ + "bitflags 2.5.0", +] + [[package]] name = "hash32" version = "0.2.1" @@ -897,6 +972,21 @@ dependencies = [ "serde", ] +[[package]] +name = "hassle-rs" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af2a7e73e1f34c48da31fb668a907f250794837e08faa144fd24f0b8b741e890" +dependencies = [ + "bitflags 2.5.0", + "com", + "libc", + "libloading 0.8.3", + "thiserror", + "widestring", + "winapi", +] + [[package]] name = "heapless" version = "0.7.17" @@ -929,6 +1019,12 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hexf-parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" + [[package]] name = "hui" version = "0.1.0-alpha.4" @@ -957,17 +1053,6 @@ dependencies = [ "syn 2.0.60", ] -[[package]] -name = "hui-glium" -version = "0.1.0-alpha.4" -source = "git+https://github.com/griffi-gh/hui?rev=dd5af8b9e2#dd5af8b9e2dc4cb2beb0b130d82167258ea2bd4e" -dependencies = [ - "glam", - "glium", - "hui", - "log", -] - [[package]] name = "hui-winit" version = "0.1.0-alpha.4" @@ -976,7 +1061,7 @@ dependencies = [ "glam", "hui", "log", - "winit", + "winit 0.29.15", ] [[package]] @@ -1014,9 +1099,9 @@ version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d3aaff8a54577104bafdf686ff18565c3b6903ca5782a2026ef06e2c7aa319" dependencies = [ - "block2", + "block2 0.3.0", "dispatch", - "objc2", + "objc2 0.4.1", ] [[package]] @@ -1146,6 +1231,17 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "khronos-egl" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76" +dependencies = [ + "libc", + "libloading 0.8.3", + "pkg-config", +] + [[package]] name = "khronos_api" version = "3.1.0" @@ -1156,29 +1252,25 @@ checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" name = "kubi" version = "0.0.0" dependencies = [ - "android-activity", + "android-activity 0.5.2", "anyhow", "atomic", "flume", "gilrs", "glam", - "glium", - "glutin", - "glutin-winit", "hashbrown 0.14.3", "hui", - "hui-glium", "hui-winit", "image", "kubi-logging", "kubi-shared", "log", "lz4_flex", - "ndk", + "ndk 0.8.0", "nohash-hasher", "postcard", "rand", - "raw-window-handle 0.5.2", + "raw-window-handle", "rayon", "serde_json", "shipyard", @@ -1186,8 +1278,9 @@ dependencies = [ "strum", "tinyset", "uflow", + "wgpu", "winapi", - "winit", + "winit 0.30.0", ] [[package]] @@ -1257,6 +1350,16 @@ version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + [[package]] name = "libloading" version = "0.8.3" @@ -1337,6 +1440,15 @@ dependencies = [ "libc", ] +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + [[package]] name = "memchr" version = "2.7.2" @@ -1353,12 +1465,18 @@ dependencies = [ ] [[package]] -name = "memoffset" -version = "0.9.1" +name = "metal" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +checksum = "5637e166ea14be6063a3f8ba5ccb9a4159df7d8f6d61c02fc3d480b1f90dcfcb" dependencies = [ - "autocfg", + "bitflags 2.5.0", + "block", + "core-graphics-types", + "foreign-types", + "log", + "objc", + "paste", ] [[package]] @@ -1371,6 +1489,27 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "naga" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e536ae46fcab0876853bd4a632ede5df4b1c2527a58f6c5a4150fe86be858231" +dependencies = [ + "arrayvec", + "bit-set", + "bitflags 2.5.0", + "codespan-reporting", + "hexf-parse", + "indexmap 2.2.6", + "log", + "num-traits", + "rustc-hash", + "spirv", + "termcolor", + "thiserror", + "unicode-xid", +] + [[package]] name = "nanorand" version = "0.7.0" @@ -1389,10 +1528,24 @@ dependencies = [ "bitflags 2.5.0", "jni-sys", "log", - "ndk-sys", + "ndk-sys 0.5.0+25.2.9519653", "num_enum", - "raw-window-handle 0.5.2", - "raw-window-handle 0.6.1", + "raw-window-handle", + "thiserror", +] + +[[package]] +name = "ndk" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" +dependencies = [ + "bitflags 2.5.0", + "jni-sys", + "log", + "ndk-sys 0.6.0+11769913", + "num_enum", + "raw-window-handle", "thiserror", ] @@ -1411,6 +1564,15 @@ dependencies = [ "jni-sys", ] +[[package]] +name = "ndk-sys" +version = "0.6.0+11769913" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" +dependencies = [ + "jni-sys", +] + [[package]] name = "nix" version = "0.28.0" @@ -1419,7 +1581,7 @@ checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" dependencies = [ "bitflags 2.5.0", "cfg-if", - "cfg_aliases", + "cfg_aliases 0.1.1", "libc", ] @@ -1471,6 +1633,15 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb749eec2b3be2f169dd4facfec40a28cc40f2b02ad3c4d2c51ce578c3f635b0" +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + [[package]] name = "objc-sys" version = "0.3.3" @@ -1484,7 +1655,40 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "559c5a40fdd30eb5e344fbceacf7595a81e242529fb4e21cf5f43fb4f11ff98d" dependencies = [ "objc-sys", - "objc2-encode", + "objc2-encode 3.0.0", +] + +[[package]] +name = "objc2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4b25e1034d0e636cd84707ccdaa9f81243d399196b8a773946dcffec0401659" +dependencies = [ + "objc-sys", + "objc2-encode 4.0.1", +] + +[[package]] +name = "objc2-app-kit" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb79768a710a9a1798848179edb186d1af7e8a8679f369e4b8d201dd2a034047" +dependencies = [ + "block2 0.5.0", + "objc2 0.5.1", + "objc2-core-data", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-data" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e092bc42eaf30a08844e6a076938c60751225ec81431ab89f5d1ccd9f958d6c" +dependencies = [ + "block2 0.5.0", + "objc2 0.5.1", + "objc2-foundation", ] [[package]] @@ -1494,12 +1698,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d079845b37af429bfe5dfa76e6d087d788031045b25cfc6fd898486fd9847666" [[package]] -name = "object" -version = "0.32.2" +name = "objc2-encode" +version = "4.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "88658da63e4cc2c8adb1262902cd6af51094df0488b760d6fd27194269c0950a" + +[[package]] +name = "objc2-foundation" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfaefe14254871ea16c7d88968c0ff14ba554712a20d76421eec52f0a7fb8904" dependencies = [ - "memchr", + "block2 0.5.0", + "dispatch", + "objc2 0.5.1", ] [[package]] @@ -1536,12 +1748,61 @@ dependencies = [ "libm", ] +[[package]] +name = "parking_lot" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.5.1", + "smallvec", + "windows-targets 0.52.5", +] + +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + [[package]] name = "percent-encoding" version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + [[package]] name = "pin-project-lite" version = "0.2.14" @@ -1606,6 +1867,12 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "presser" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa" + [[package]] name = "proc-macro-crate" version = "3.1.0" @@ -1624,6 +1891,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "profiling" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d84d1d7a6ac92673717f9f6d1518374ef257669c24ebc5ac25d5033828be58" + [[package]] name = "quick-xml" version = "0.31.0" @@ -1683,10 +1956,10 @@ dependencies = [ ] [[package]] -name = "raw-window-handle" -version = "0.5.2" +name = "range-alloc" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" +checksum = "9c8a99fddc9f0ba0a85884b8d14e3592853e787d581ca1816c91349b10e4eeab" [[package]] name = "raw-window-handle" @@ -1738,6 +2011,15 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "redox_syscall" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" +dependencies = [ + "bitflags 2.5.0", +] + [[package]] name = "regex" version = "1.10.4" @@ -1768,10 +2050,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] -name = "rustc-demangle" -version = "0.1.23" +name = "renderdoc-sys" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc_version" @@ -1841,9 +2129,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sctk-adwaita" -version = "0.8.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b2eaf3a5b264a521b988b2e73042e742df700c4f962cde845d1541adb46550" +checksum = "7de61fa7334ee8ee1f5c3c58dcc414fb9361e7e8f5bff9d45f4d69eeb89a7169" dependencies = [ "ab_glyph", "log", @@ -1972,6 +2260,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "slotmap" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" +dependencies = [ + "version_check", +] + [[package]] name = "smallvec" version = "1.13.2" @@ -2021,6 +2318,15 @@ dependencies = [ "lock_api", ] +[[package]] +name = "spirv" +version = "0.3.0+sdk-1.3.268.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" +dependencies = [ + "bitflags 2.5.0", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -2089,12 +2395,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "takeable-option" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36ae8932fcfea38b7d3883ae2ab357b0d57a02caaa18ebb4f5ece08beaec4aa0" - [[package]] name = "termcolor" version = "1.4.1" @@ -2277,6 +2577,18 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +[[package]] +name = "unicode-width" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + [[package]] name = "uuid" version = "1.8.0" @@ -2506,6 +2818,131 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wgpu" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32ff1bfee408e1028e2e3acbf6d32d98b08a5a059ccbf5f33305534453ba5d3e" +dependencies = [ + "arrayvec", + "cfg-if", + "cfg_aliases 0.1.1", + "document-features", + "js-sys", + "log", + "naga", + "parking_lot", + "profiling", + "raw-window-handle", + "smallvec", + "static_assertions", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "wgpu-core", + "wgpu-hal", + "wgpu-types", +] + +[[package]] +name = "wgpu-core" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac6a86eaa5e763e59c73cf9e97d55fffd4dfda69fd8bda19589fcf851ddfef1f" +dependencies = [ + "arrayvec", + "bit-vec", + "bitflags 2.5.0", + "cfg_aliases 0.1.1", + "codespan-reporting", + "document-features", + "indexmap 2.2.6", + "log", + "naga", + "once_cell", + "parking_lot", + "profiling", + "raw-window-handle", + "rustc-hash", + "smallvec", + "thiserror", + "web-sys", + "wgpu-hal", + "wgpu-types", +] + +[[package]] +name = "wgpu-hal" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d71c8ae05170583049b65ee562fd839fdc0b3e9ddb84f4e40c9d5f8ea0d4c8c" +dependencies = [ + "android_system_properties", + "arrayvec", + "ash", + "bit-set", + "bitflags 2.5.0", + "block", + "cfg_aliases 0.1.1", + "core-graphics-types", + "d3d12", + "glow", + "glutin_wgl_sys", + "gpu-alloc", + "gpu-allocator", + "gpu-descriptor", + "hassle-rs", + "js-sys", + "khronos-egl", + "libc", + "libloading 0.8.3", + "log", + "metal", + "naga", + "ndk-sys 0.5.0+25.2.9519653", + "objc", + "once_cell", + "parking_lot", + "profiling", + "range-alloc", + "raw-window-handle", + "renderdoc-sys", + "rustc-hash", + "smallvec", + "thiserror", + "wasm-bindgen", + "web-sys", + "wgpu-types", + "winapi", +] + +[[package]] +name = "wgpu-types" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1353d9a46bff7f955a680577f34c69122628cc2076e1d6f3a9be6ef00ae793ef" +dependencies = [ + "bitflags 2.5.0", + "js-sys", + "web-sys", +] + +[[package]] +name = "widestring" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" + [[package]] name = "winapi" version = "0.3.9" @@ -2537,6 +2974,16 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" +dependencies = [ + "windows-core", + "windows-targets 0.52.5", +] + [[package]] name = "windows-core" version = "0.52.0" @@ -2757,13 +3204,11 @@ version = "0.29.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d59ad965a635657faf09c8f062badd885748428933dad8e8bdd64064d92e5ca" dependencies = [ - "ahash", - "android-activity", + "android-activity 0.5.2", "atomic-waker", "bitflags 2.5.0", - "bytemuck", "calloop", - "cfg_aliases", + "cfg_aliases 0.1.1", "core-foundation", "core-graphics", "cursor-icon", @@ -2771,20 +3216,58 @@ dependencies = [ "js-sys", "libc", "log", - "memmap2", - "ndk", - "ndk-sys", - "objc2", + "ndk 0.8.0", + "ndk-sys 0.5.0+25.2.9519653", + "objc2 0.4.1", "once_cell", "orbclient", - "percent-encoding", - "raw-window-handle 0.5.2", - "raw-window-handle 0.6.1", "redox_syscall 0.3.5", "rustix", + "smol_str", + "unicode-segmentation", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "web-time 0.2.4", + "windows-sys 0.48.0", + "xkbcommon-dl", +] + +[[package]] +name = "winit" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea9e6d5d66cbf702e0dd820302144f51b69a95acdc495dd98ca280ff206562b1" +dependencies = [ + "ahash", + "android-activity 0.6.0", + "atomic-waker", + "bitflags 2.5.0", + "bytemuck", + "calloop", + "cfg_aliases 0.2.0", + "concurrent-queue", + "core-foundation", + "core-graphics", + "cursor-icon", + "dpi", + "js-sys", + "libc", + "memmap2", + "ndk 0.9.0", + "objc2 0.5.1", + "objc2-app-kit", + "objc2-foundation", + "orbclient", + "percent-encoding", + "pin-project", + "raw-window-handle", + "redox_syscall 0.4.1", + "rustix", "sctk-adwaita", "smithay-client-toolkit", "smol_str", + "tracing", "unicode-segmentation", "wasm-bindgen", "wasm-bindgen-futures", @@ -2793,8 +3276,8 @@ dependencies = [ "wayland-protocols", "wayland-protocols-plasma", "web-sys", - "web-time", - "windows-sys 0.48.0", + "web-time 1.1.0", + "windows-sys 0.52.0", "x11-dl", "x11rb", "xkbcommon-dl", @@ -2838,7 +3321,7 @@ dependencies = [ "as-raw-xcb-connection", "gethostname", "libc", - "libloading", + "libloading 0.8.3", "once_cell", "rustix", "x11rb-protocol", @@ -2900,3 +3383,8 @@ dependencies = [ "quote", "syn 2.0.60", ] + +[[patch.unused]] +name = "glium" +version = "0.34.0" +source = "git+https://github.com/glium/glium?rev=a352c667#a352c667c145e2dda1f5fe1fc2482cbe99de23be" diff --git a/kubi/Cargo.toml b/kubi/Cargo.toml index ed59a2c..20dd548 100644 --- a/kubi/Cargo.toml +++ b/kubi/Cargo.toml @@ -12,14 +12,11 @@ crate-type = ["lib", "cdylib"] kubi-shared = { path = "../kubi-shared" } kubi-logging = { path = "../kubi-logging" } hui = { version = "0.1.0-alpha.4", git = "https://github.com/griffi-gh/hui", rev = "dd5af8b9e2" } -hui-glium = { version = "0.1.0-alpha.4", git = "https://github.com/griffi-gh/hui", rev = "dd5af8b9e2" } hui-winit = { version = "0.1.0-alpha.4", git = "https://github.com/griffi-gh/hui", rev = "dd5af8b9e2" } log = "0.4" -glium = { git = "https://github.com/glium/glium", rev = "a352c667" } -glutin = "0.31" -winit = { version = "0.29", features = ["android-native-activity"] } -glutin-winit = "0.4" -raw-window-handle = "=0.5.*" +wgpu = { version = "0.20", features = ["webgl"] } +winit = { version = "0.30", features = ["android-native-activity"] } +raw-window-handle = "0.6" glam = { version = "0.27", features = ["debug-glam-assert", "fast-math"] } image = { version = "0.25", default_features = false, features = ["png"] } strum = { version = "0.26", features = ["derive"] } diff --git a/kubi/src/hui_integration.rs b/kubi/src/hui_integration.rs index 28a8583..f28c05e 100644 --- a/kubi/src/hui_integration.rs +++ b/kubi/src/hui_integration.rs @@ -1,12 +1,12 @@ use hui::UiInstance; -use hui_glium::GliumUiRenderer; +//use hui_glium::GliumUiRenderer; use shipyard::{AllStoragesView, Unique, UniqueView, NonSendSync, UniqueViewMut}; use crate::rendering::{RenderTarget, Renderer, WindowSize}; #[derive(Unique)] pub struct UiState { pub hui: UiInstance, - pub renderer: GliumUiRenderer + //pub renderer: GliumUiRenderer } pub fn kubi_ui_init( @@ -15,7 +15,7 @@ pub fn kubi_ui_init( let renderer = storages.borrow::>>().unwrap(); storages.add_unique_non_send_sync(UiState { hui: UiInstance::new(), - renderer: GliumUiRenderer::new(&renderer.display), + //renderer: GliumUiRenderer::new(&renderer.display), }); } @@ -29,9 +29,9 @@ pub fn kubi_ui_end( mut ui: NonSendSync> ) { let ui: &mut UiState = &mut ui; - let UiState { hui, renderer, .. } = ui; + let UiState { hui, /*renderer,*/ .. } = ui; hui.end(); - renderer.update(hui); + //renderer.update(hui); } pub fn kubi_ui_draw( @@ -39,7 +39,7 @@ pub fn kubi_ui_draw( mut target: NonSendSync>, size: UniqueView ) { - ui.renderer.draw(&mut target.0, size.0.as_vec2()); + //ui.renderer.draw(&mut target.0, size.0.as_vec2()); } pub fn hui_process_winit_events( diff --git a/kubi/src/prefabs.rs b/kubi/src/prefabs.rs index ac7669e..4f5d9be 100644 --- a/kubi/src/prefabs.rs +++ b/kubi/src/prefabs.rs @@ -43,17 +43,17 @@ impl AssetPaths for BlockTexture { #[repr(transparent)] pub struct BlockTexturesPrefab(pub SrgbTexture2dArray); -#[derive(Unique)] -#[repr(transparent)] -pub struct ChunkShaderPrefab(pub Program); +// #[derive(Unique)] +// #[repr(transparent)] +// pub struct ChunkShaderPrefab(pub Program); -#[derive(Unique)] -#[repr(transparent)] -pub struct ColoredShaderPrefab(pub Program); +// #[derive(Unique)] +// #[repr(transparent)] +// pub struct ColoredShaderPrefab(pub Program); -#[derive(Unique)] -#[repr(transparent)] -pub struct Colored2ShaderPrefab(pub Program); +// #[derive(Unique)] +// #[repr(transparent)] +// pub struct Colored2ShaderPrefab(pub Program); #[derive(Unique)] #[repr(transparent)] @@ -113,5 +113,5 @@ pub fn load_prefabs( log::info!("releasing shader compiler"); - renderer.display.release_shader_compiler(); + //renderer.display.release_shader_compiler(); } diff --git a/kubi/src/rendering.rs b/kubi/src/rendering.rs index 7ad278b..1a393cc 100644 --- a/kubi/src/rendering.rs +++ b/kubi/src/rendering.rs @@ -1,16 +1,9 @@ -use std::num::NonZeroU32; -use raw_window_handle::HasRawWindowHandle; use shipyard::{Unique, NonSendSync, UniqueView, UniqueViewMut, View, IntoIter, AllStoragesView}; use winit::{ - event_loop::EventLoopWindowTarget, - window::{WindowBuilder, Fullscreen, Window}, + event_loop::ActiveEventLoop, + window::{WindowAttributes, Fullscreen, Window}, dpi::PhysicalSize }; -use glium::{Display, Surface, Version, Api as GlApiTy}; -use glutin::{ - config::{Api, ConfigTemplateBuilder}, context::{ContextAttributesBuilder, GlProfile}, display::GetGlDisplay, prelude::*, surface::{SurfaceAttributesBuilder, WindowSurface} -}; -use glutin_winit::DisplayBuilder; use glam::{Vec3, UVec2}; use crate::{events::WindowResizedEvent, settings::{GameSettings, FullscreenMode}}; @@ -20,10 +13,6 @@ pub mod selection_box; pub mod entities; pub mod sumberge; -#[derive(Unique)] -#[repr(transparent)] -pub struct RenderTarget(pub glium::Frame); - #[derive(Unique)] #[repr(transparent)] pub struct BackgroundColor(pub Vec3); @@ -35,14 +24,13 @@ pub struct WindowSize(pub UVec2); #[derive(Unique)] pub struct Renderer { pub window: Window, - pub display: Display, } impl Renderer { - pub fn init(event_loop: &EventLoopWindowTarget<()>, settings: &GameSettings) -> Self { + pub fn init(event_loop: &ActiveEventLoop, settings: &GameSettings) -> Self { log::info!("initializing display"); - let wb = WindowBuilder::new() + let wb = WindowAttributes::new() .with_title("kubi") .with_maximized(true) .with_min_inner_size(PhysicalSize::new(640, 480)) @@ -88,74 +76,7 @@ impl Renderer { } }); - let display_builder = DisplayBuilder::new() - .with_window_builder(Some(wb)); - - let config_template_builder = ConfigTemplateBuilder::new() - .with_api(Api::GLES3) - .prefer_hardware_accelerated(Some(true)) - .with_depth_size(24) - .with_multisampling(settings.msaa.unwrap_or_default()); - - let (window, gl_config) = display_builder - .build(event_loop, config_template_builder, |mut configs| { - configs.next().unwrap() - }) - .unwrap(); - - let window = window.expect("no window"); - - // Now we get the window size to use as the initial size of the Surface - let (width, height): (u32, u32) = window.inner_size().into(); - let attrs = SurfaceAttributesBuilder::::new().build( - window.raw_window_handle(), - NonZeroU32::new(width).unwrap(), - NonZeroU32::new(height).unwrap(), - ); - - // Finally we can create a Surface, use it to make a PossiblyCurrentContext and create the glium Display - let surface = unsafe { - gl_config.display().create_window_surface(&gl_config, &attrs).unwrap() - }; - - let context_attributes = ContextAttributesBuilder::new() - .with_debug(cfg!(debug_assertions)) - .with_context_api(glutin::context::ContextApi::Gles(None)) - .with_profile(GlProfile::Core) - .build(Some(window.raw_window_handle())); - - let current_context = unsafe { - gl_config.display() - .create_context(&gl_config, &context_attributes) - .expect("failed to create context") - }.make_current(&surface).unwrap(); - - let display = Display::from_context_surface(current_context, surface).unwrap(); - - //TODO MIGRATION - // let cb = ContextBuilder::new() - // //.with_srgb(false) - // .with_depth_buffer(24) - // .with_multisampling(settings.msaa.unwrap_or_default()) - // .with_vsync(settings.vsync) - // .with_gl_profile(GlProfile::Core) - // .with_gl(GlRequest::Latest); - - // let display = Display::new(wb, cb) - // .expect("Failed to create a glium Display"); - - log::info!("Vendor: {}", display.get_opengl_vendor_string()); - log::info!("Renderer: {}", display.get_opengl_renderer_string()); - log::info!("OpenGL: {}", display.get_opengl_version_string()); - log::info!("Supports GLSL: {:?}", display.get_supported_glsl_version()); - log::info!("Framebuffer dimensions: {:?}", display.get_framebuffer_dimensions()); - if display.is_context_loss_possible() { log::warn!("OpenGL context loss possible") } - if display.is_robust() { log::warn!("OpenGL implementation is not robust") } - if display.is_debug() { log::info!("OpenGL context is in debug mode") } - - assert!(display.is_glsl_version_supported(&Version(GlApiTy::GlEs, 3, 0)), "GLSL ES 3.0 is not supported"); - - Self { window, display } + Self { window } } } diff --git a/kubi/src/rendering/shaders.rs b/kubi/src/rendering/shaders.rs new file mode 100644 index 0000000..e69de29 From 4ff284288ebc3d0b049ff5227f90ac3e5e7237a2 Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Sat, 4 May 2024 14:32:21 +0200 Subject: [PATCH 02/51] . --- kubi/src/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/kubi/src/lib.rs b/kubi/src/lib.rs index a401cf7..8d1b5bc 100644 --- a/kubi/src/lib.rs +++ b/kubi/src/lib.rs @@ -105,8 +105,7 @@ use chat_ui::render_chat; use chat::init_chat_manager; use crosshair_ui::{init_crosshair_image, draw_crosshair}; use settings_ui::render_settings_ui; - -use crate::hui_integration::hui_process_winit_events; +use hui_integration::hui_process_winit_events; /// stuff required to init the renderer and other basic systems fn pre_startup() -> Workload { From 0e22bccbaca9a415573b3732331076523c244d8c Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Sat, 4 May 2024 17:24:19 +0200 Subject: [PATCH 03/51] init wgpu stuff --- Cargo.lock | 7 +++++ kubi/Cargo.toml | 2 ++ kubi/src/rendering.rs | 65 +++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 18d8023..6c2f356 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1268,6 +1268,7 @@ dependencies = [ "lz4_flex", "ndk 0.8.0", "nohash-hasher", + "pollster", "postcard", "rand", "raw-window-handle", @@ -1843,6 +1844,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "pollster" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22686f4785f02a4fcc856d3b3bb19bf6c8160d103f7a99cc258bddd0251dc7f2" + [[package]] name = "postcard" version = "1.0.8" diff --git a/kubi/Cargo.toml b/kubi/Cargo.toml index 20dd548..057fcc7 100644 --- a/kubi/Cargo.toml +++ b/kubi/Cargo.toml @@ -15,6 +15,7 @@ hui = { version = "0.1.0-alpha.4", git = "https://github.com/griffi-gh/hui", rev hui-winit = { version = "0.1.0-alpha.4", git = "https://github.com/griffi-gh/hui", rev = "dd5af8b9e2" } log = "0.4" wgpu = { version = "0.20", features = ["webgl"] } +pollster = "0.3" winit = { version = "0.30", features = ["android-native-activity"] } raw-window-handle = "0.6" glam = { version = "0.27", features = ["debug-glam-assert", "fast-math"] } @@ -36,6 +37,7 @@ serde_json = { version = "1.0", optional = true } #only used for `generate_visua rand = { version = "0.8", features = ["alloc", "small_rng"]} atomic = "0.6" + [target.'cfg(target_os = "android")'.dependencies] android-activity = "^0.5.2" ndk = "0.8" diff --git a/kubi/src/rendering.rs b/kubi/src/rendering.rs index 1a393cc..1da5fd0 100644 --- a/kubi/src/rendering.rs +++ b/kubi/src/rendering.rs @@ -1,3 +1,4 @@ +use pollster::FutureExt; use shipyard::{Unique, NonSendSync, UniqueView, UniqueViewMut, View, IntoIter, AllStoragesView}; use winit::{ event_loop::ActiveEventLoop, @@ -19,18 +20,27 @@ pub struct BackgroundColor(pub Vec3); #[derive(Unique, Clone, Copy)] #[repr(transparent)] +#[deprecated = "use Renderer.size instead"] +#[allow(deprecated)] pub struct WindowSize(pub UVec2); #[derive(Unique)] pub struct Renderer { pub window: Window, + pub instance: wgpu::Instance, + pub surface: wgpu::Surface<'static>, + pub device: wgpu::Device, + pub queue: wgpu::Queue, + pub surface_config: wgpu::SurfaceConfiguration, + pub size: PhysicalSize, + // pub depth_texture: wgpu::Texture, } impl Renderer { pub fn init(event_loop: &ActiveEventLoop, settings: &GameSettings) -> Self { log::info!("initializing display"); - let wb = WindowAttributes::new() + let window_attributes = Window::default_attributes() .with_title("kubi") .with_maximized(true) .with_min_inner_size(PhysicalSize::new(640, 480)) @@ -44,6 +54,7 @@ impl Renderer { let monitor = event_loop.primary_monitor().or_else(|| { event_loop.available_monitors().next() }); + if let Some(monitor) = monitor { log::info!("monitor: {}", monitor.name().unwrap_or_else(|| "generic".into())); match fs_settings.mode { @@ -75,8 +86,58 @@ impl Renderer { None } }); + let window = event_loop.create_window(window_attributes).unwrap(); - Self { window } + let size = window.inner_size(); + + let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { + backends: wgpu::Backends::all(), + ..Default::default() + }); + + let surface = instance.create_surface(window).unwrap(); + + let adapter = instance.request_adapter( + &wgpu::RequestAdapterOptions { + power_preference: wgpu::PowerPreference::HighPerformance, + compatible_surface: Some(&surface), + force_fallback_adapter: false, + }, + ).block_on().unwrap(); + + let (device, queue) = adapter.request_device( + &wgpu::DeviceDescriptor { + label: None, + required_features: wgpu::Features::empty(), + required_limits: wgpu::Limits::downlevel_defaults(), + }, + None, + ).block_on().unwrap(); + + let surface_config = surface.get_default_config(&adapter, size.width, size.height).unwrap(); + surface.configure(&device, &surface_config); + + Self { window, instance, surface, device, queue, surface_config, size } + } + + pub fn resize(&mut self, size: PhysicalSize) { + if size.width == 0 || size.height == 0 { + log::warn!("Ignoring resize event with zero width or height"); + return + } + if self.size == size { + log::warn!("Ignoring resize event with same size"); + return + } + log::debug!("resizing surface to {:?}", size); + self.size = size; + self.surface_config.width = size.width; + self.surface_config.height = size.height; + self.surface.configure(&self.device, &self.surface_config); + } + + pub fn reconfigure(&self) { + self.surface.configure(&self.device, &self.surface_config); } } From eaad06863fcf4c7edc685cb06e2fe5f78be231b2 Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Sat, 4 May 2024 22:10:40 +0200 Subject: [PATCH 04/51] "fix" compile errs --- Cargo.lock | 146 ++------- Cargo.toml | 7 +- kubi-logging/src/lib.rs | 128 ++++---- kubi/Cargo.toml | 4 +- kubi/src/cursor_lock.rs | 9 +- kubi/src/events.rs | 2 +- kubi/src/hui_integration.rs | 16 +- kubi/src/lib.rs | 69 ++-- kubi/src/prefabs.rs | 76 +++-- kubi/src/prefabs/texture.rs | 91 +++--- kubi/src/rendering.rs | 115 ++++++- kubi/src/rendering/entities.rs | 116 +++---- kubi/src/rendering/primitives.rs | 50 +-- kubi/src/rendering/primitives/cube.rs | 170 +++++----- kubi/src/rendering/primitives/rect.rs | 62 ++-- kubi/src/rendering/primitives/stri.rs | 54 ++-- kubi/src/rendering/selection_box.rs | 118 +++---- kubi/src/rendering/sumberge.rs | 74 ++--- kubi/src/rendering/world.rs | 441 +++++++++++++------------- kubi/src/ui/loading_screen.rs | 8 +- kubi/src/ui/settings_ui.rs | 4 +- kubi/src/world/chunk.rs | 9 +- kubi/src/world/loading.rs | 31 +- 23 files changed, 886 insertions(+), 914 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6c2f356..91cadc2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -244,32 +244,13 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" -[[package]] -name = "block-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae85a0696e7ea3b835a453750bf002770776609115e6d25c6d2ff28a8200f7e7" -dependencies = [ - "objc-sys", -] - -[[package]] -name = "block2" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15b55663a85f33501257357e6421bb33e769d5c9ffb5ba0921c975a123e35e68" -dependencies = [ - "block-sys", - "objc2 0.4.1", -] - [[package]] name = "block2" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43ff7d91d3c1d568065b06c899777d1e48dcf76103a672a0adbc238a7f247f1e" dependencies = [ - "objc2 0.5.1", + "objc2", ] [[package]] @@ -1027,8 +1008,8 @@ checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" [[package]] name = "hui" -version = "0.1.0-alpha.4" -source = "git+https://github.com/griffi-gh/hui?rev=dd5af8b9e2#dd5af8b9e2dc4cb2beb0b130d82167258ea2bd4e" +version = "0.1.0-alpha.5" +source = "git+https://github.com/griffi-gh/hui?rev=3a50d2d0dde#3a50d2d0dde7044d02860dac9ab059bd353657a2" dependencies = [ "derive_more", "derive_setters", @@ -1041,13 +1022,14 @@ dependencies = [ "log", "nohash-hasher", "rect_packer", + "rustc-hash", "tinyset", ] [[package]] name = "hui-derive" -version = "0.1.0-alpha.4" -source = "git+https://github.com/griffi-gh/hui?rev=dd5af8b9e2#dd5af8b9e2dc4cb2beb0b130d82167258ea2bd4e" +version = "0.1.0-alpha.5" +source = "git+https://github.com/griffi-gh/hui?rev=3a50d2d0dde#3a50d2d0dde7044d02860dac9ab059bd353657a2" dependencies = [ "quote", "syn 2.0.60", @@ -1055,13 +1037,13 @@ dependencies = [ [[package]] name = "hui-winit" -version = "0.1.0-alpha.4" -source = "git+https://github.com/griffi-gh/hui?rev=dd5af8b9e2#dd5af8b9e2dc4cb2beb0b130d82167258ea2bd4e" +version = "0.1.0-alpha.5" +source = "git+https://github.com/griffi-gh/hui?rev=3a50d2d0dde#3a50d2d0dde7044d02860dac9ab059bd353657a2" dependencies = [ "glam", "hui", "log", - "winit 0.29.15", + "winit", ] [[package]] @@ -1093,17 +1075,6 @@ dependencies = [ "cc", ] -[[package]] -name = "icrate" -version = "0.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d3aaff8a54577104bafdf686ff18565c3b6903ca5782a2026ef06e2c7aa319" -dependencies = [ - "block2 0.3.0", - "dispatch", - "objc2 0.4.1", -] - [[package]] name = "ident_case" version = "1.0.1" @@ -1281,7 +1252,7 @@ dependencies = [ "uflow", "wgpu", "winapi", - "winit 0.30.0", + "winit", ] [[package]] @@ -1649,16 +1620,6 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da284c198fb9b7b0603f8635185e85fbd5b64ee154b1ed406d489077de2d6d60" -[[package]] -name = "objc2" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "559c5a40fdd30eb5e344fbceacf7595a81e242529fb4e21cf5f43fb4f11ff98d" -dependencies = [ - "objc-sys", - "objc2-encode 3.0.0", -] - [[package]] name = "objc2" version = "0.5.1" @@ -1666,7 +1627,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4b25e1034d0e636cd84707ccdaa9f81243d399196b8a773946dcffec0401659" dependencies = [ "objc-sys", - "objc2-encode 4.0.1", + "objc2-encode", ] [[package]] @@ -1675,8 +1636,8 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb79768a710a9a1798848179edb186d1af7e8a8679f369e4b8d201dd2a034047" dependencies = [ - "block2 0.5.0", - "objc2 0.5.1", + "block2", + "objc2", "objc2-core-data", "objc2-foundation", ] @@ -1687,17 +1648,11 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e092bc42eaf30a08844e6a076938c60751225ec81431ab89f5d1ccd9f958d6c" dependencies = [ - "block2 0.5.0", - "objc2 0.5.1", + "block2", + "objc2", "objc2-foundation", ] -[[package]] -name = "objc2-encode" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d079845b37af429bfe5dfa76e6d087d788031045b25cfc6fd898486fd9847666" - [[package]] name = "objc2-encode" version = "4.0.1" @@ -1710,9 +1665,9 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfaefe14254871ea16c7d88968c0ff14ba554712a20d76421eec52f0a7fb8904" dependencies = [ - "block2 0.5.0", + "block2", "dispatch", - "objc2 0.5.1", + "objc2", ] [[package]] @@ -2000,15 +1955,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8ffb4dfda4b01cc420847665dc480760d596ce186f2772a66ed32fe9acb1c45" -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "redox_syscall" version = "0.4.1" @@ -2815,16 +2761,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "web-time" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa30049b1c872b72c89866d458eae9f20380ab280ffd1b1e18df2d3e2d98cfe0" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - [[package]] name = "web-time" version = "1.1.0" @@ -3009,15 +2945,6 @@ dependencies = [ "windows-targets 0.42.2", ] -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - [[package]] name = "windows-sys" version = "0.52.0" @@ -3205,41 +3132,6 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" -[[package]] -name = "winit" -version = "0.29.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d59ad965a635657faf09c8f062badd885748428933dad8e8bdd64064d92e5ca" -dependencies = [ - "android-activity 0.5.2", - "atomic-waker", - "bitflags 2.5.0", - "calloop", - "cfg_aliases 0.1.1", - "core-foundation", - "core-graphics", - "cursor-icon", - "icrate", - "js-sys", - "libc", - "log", - "ndk 0.8.0", - "ndk-sys 0.5.0+25.2.9519653", - "objc2 0.4.1", - "once_cell", - "orbclient", - "redox_syscall 0.3.5", - "rustix", - "smol_str", - "unicode-segmentation", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "web-time 0.2.4", - "windows-sys 0.48.0", - "xkbcommon-dl", -] - [[package]] name = "winit" version = "0.30.0" @@ -3262,7 +3154,7 @@ dependencies = [ "libc", "memmap2", "ndk 0.9.0", - "objc2 0.5.1", + "objc2", "objc2-app-kit", "objc2-foundation", "orbclient", @@ -3283,7 +3175,7 @@ dependencies = [ "wayland-protocols", "wayland-protocols-plasma", "web-sys", - "web-time 1.1.0", + "web-time", "windows-sys 0.52.0", "x11-dl", "x11rb", diff --git a/Cargo.toml b/Cargo.toml index ae628a0..1a981bf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,10 +21,13 @@ opt-level = 1 [profile.dev.package.uflow] opt-level = 3 -[profile.dev.package.glium] +[profile.dev.package.wgpu] opt-level = 3 -[profile.dev.package.bracket-noise] +[profile.dev.package.wgpu-core] +opt-level = 3 + +[profile.dev.package.wgpu-hal] opt-level = 3 [profile.dev.package.fastnoise-lite] diff --git a/kubi-logging/src/lib.rs b/kubi-logging/src/lib.rs index 34b8a89..71242dc 100644 --- a/kubi-logging/src/lib.rs +++ b/kubi-logging/src/lib.rs @@ -1,64 +1,64 @@ -//! Custom env_logger options and styling - -/// Custom env_logger options and styling -#[inline] -#[cfg(not(target_os = "android"))] -pub fn init() { - use log::Level; - use std::io::Write; - use env_logger::{fmt::Color, Builder, Env}; - - let env = Env::default() - .filter_or("RUST_LOG", "trace,gilrs=warn,rusty_xinput=warn"); - Builder::from_env(env) - .format(|buf, record| { - let mut level_style = buf.style(); - level_style.set_color(match record.level() { - Level::Error => Color::Red, - Level::Warn => Color::Yellow, - Level::Debug | Level::Trace => Color::Cyan, - _ => Color::Blue - }).set_bold(true); - - let mut bold_style = buf.style(); - bold_style.set_bold(true); - - let mut location_style = buf.style(); - location_style.set_bold(true); - location_style.set_dimmed(true); - - let mut location_line_style = buf.style(); - location_line_style.set_dimmed(true); - - let text = format!("{}", record.args()); - - writeln!( - buf, - "{} {:<50}\t{}{}{}{}", - level_style.value(match record.level() { - Level::Error => "[e]", - Level::Warn => "[w]", - Level::Info => "[i]", - Level::Debug => "[d]", - Level::Trace => "[t]", - }), - text, - bold_style.value((text.len() > 50).then_some("\n ╰─ ").unwrap_or_default()), - location_style.value(record.target()), - location_line_style.value(" :"), - location_line_style.value(record.line().unwrap_or(0)) - ) - }) - .init(); -} - -/// Custom env_logger options and styling -#[inline] -#[cfg(target_os = "android")] -pub fn init() { - use log::LevelFilter; - use android_logger::Config; - android_logger::init_once( - Config::default().with_max_level(LevelFilter::Trace), - ); -} +//! Custom env_logger options and styling + +/// Custom env_logger options and styling +#[inline] +#[cfg(not(target_os = "android"))] +pub fn init() { + use log::Level; + use std::io::Write; + use env_logger::{fmt::Color, Builder, Env}; + + let env = Env::default() + .filter_or("RUST_LOG", "trace,gilrs=warn,rusty_xinput=warn,wgpu=warn,wgpu_core=warn,wgpu_hal=warn,hui=info,hui-winit=info,hui-glium=info,hui-wgpu=info"); + Builder::from_env(env) + .format(|buf, record| { + let mut level_style = buf.style(); + level_style.set_color(match record.level() { + Level::Error => Color::Red, + Level::Warn => Color::Yellow, + Level::Debug | Level::Trace => Color::Cyan, + _ => Color::Blue + }).set_bold(true); + + let mut bold_style = buf.style(); + bold_style.set_bold(true); + + let mut location_style = buf.style(); + location_style.set_bold(true); + location_style.set_dimmed(true); + + let mut location_line_style = buf.style(); + location_line_style.set_dimmed(true); + + let text = format!("{}", record.args()); + + writeln!( + buf, + "{} {:<50}\t{}{}{}{}", + level_style.value(match record.level() { + Level::Error => "[e]", + Level::Warn => "[w]", + Level::Info => "[i]", + Level::Debug => "[d]", + Level::Trace => "[t]", + }), + text, + bold_style.value((text.len() > 50).then_some("\n ╰─ ").unwrap_or_default()), + location_style.value(record.target()), + location_line_style.value(" :"), + location_line_style.value(record.line().unwrap_or(0)) + ) + }) + .init(); +} + +/// Custom env_logger options and styling +#[inline] +#[cfg(target_os = "android")] +pub fn init() { + use log::LevelFilter; + use android_logger::Config; + android_logger::init_once( + Config::default().with_max_level(LevelFilter::Trace), + ); +} diff --git a/kubi/Cargo.toml b/kubi/Cargo.toml index 057fcc7..27e7864 100644 --- a/kubi/Cargo.toml +++ b/kubi/Cargo.toml @@ -11,8 +11,8 @@ crate-type = ["lib", "cdylib"] [dependencies] kubi-shared = { path = "../kubi-shared" } kubi-logging = { path = "../kubi-logging" } -hui = { version = "0.1.0-alpha.4", git = "https://github.com/griffi-gh/hui", rev = "dd5af8b9e2" } -hui-winit = { version = "0.1.0-alpha.4", git = "https://github.com/griffi-gh/hui", rev = "dd5af8b9e2" } +hui = { git = "https://github.com/griffi-gh/hui", rev = "3a50d2d0dde" } +hui-winit = { git = "https://github.com/griffi-gh/hui", rev = "3a50d2d0dde", features = ["winit_30"] } log = "0.4" wgpu = { version = "0.20", features = ["webgl"] } pollster = "0.3" diff --git a/kubi/src/cursor_lock.rs b/kubi/src/cursor_lock.rs index 11c572a..8e195d7 100644 --- a/kubi/src/cursor_lock.rs +++ b/kubi/src/cursor_lock.rs @@ -1,5 +1,5 @@ use shipyard::{AllStoragesView, IntoIter, NonSendSync, Unique, UniqueView, UniqueViewMut, View}; -use crate::{events::InputDeviceEvent, rendering::{Renderer, WindowSize}}; +use crate::{events::InputDeviceEvent, rendering::Renderer}; use winit::{ dpi::PhysicalPosition, event::{DeviceEvent, ElementState, RawKeyEvent}, keyboard::{KeyCode, PhysicalKey}, window::CursorGrabMode }; @@ -16,7 +16,7 @@ pub fn update_cursor_lock_state( } if lock.is_inserted_or_modified() { //TODO MIGRATION - let window = &display.window; + let window = display.window(); window.set_cursor_grab(match lock.0 { true => CursorGrabMode::Confined, false => CursorGrabMode::None, @@ -42,7 +42,6 @@ pub fn debug_toggle_lock( mut lock: UniqueViewMut, device_events: View, ren: NonSendSync>, - size: UniqueView, ) { for evt in device_events.iter() { if let DeviceEvent::Key(RawKeyEvent { @@ -51,8 +50,8 @@ pub fn debug_toggle_lock( }) = evt.event { lock.0 = !lock.0; if !lock.0 { - let center = PhysicalPosition::new(size.0.x as f64 / 2., size.0.y as f64 / 2.); - let _ = ren.window.set_cursor_position(center); + let center = PhysicalPosition::new(ren.size().width as f64 / 2., ren.size().height as f64 / 2.); + let _ = ren.window().set_cursor_position(center); } } } diff --git a/kubi/src/events.rs b/kubi/src/events.rs index fe03a7b..84bad45 100644 --- a/kubi/src/events.rs +++ b/kubi/src/events.rs @@ -91,7 +91,7 @@ pub fn initial_resize_event( ) { let (w, h) = { let renderer = storages.borrow::>>().unwrap(); - renderer.display.get_framebuffer_dimensions() + (renderer.size().width, renderer.size().height) }; storages.add_entity(( EventComponent, diff --git a/kubi/src/hui_integration.rs b/kubi/src/hui_integration.rs index f28c05e..15b862c 100644 --- a/kubi/src/hui_integration.rs +++ b/kubi/src/hui_integration.rs @@ -1,7 +1,7 @@ use hui::UiInstance; //use hui_glium::GliumUiRenderer; use shipyard::{AllStoragesView, Unique, UniqueView, NonSendSync, UniqueViewMut}; -use crate::rendering::{RenderTarget, Renderer, WindowSize}; +use crate::rendering::{Renderer, WindowSize}; #[derive(Unique)] pub struct UiState { @@ -34,13 +34,13 @@ pub fn kubi_ui_end( //renderer.update(hui); } -pub fn kubi_ui_draw( - ui: NonSendSync>, - mut target: NonSendSync>, - size: UniqueView -) { - //ui.renderer.draw(&mut target.0, size.0.as_vec2()); -} +// pub fn kubi_ui_draw( +// ui: NonSendSync>, +// mut target: NonSendSync>, +// size: UniqueView +// ) { +// ui.renderer.draw(&mut target.0, size.0.as_vec2()); +// } pub fn hui_process_winit_events( event: &winit::event::Event<()>, diff --git a/kubi/src/lib.rs b/kubi/src/lib.rs index 8d1b5bc..90b3559 100644 --- a/kubi/src/lib.rs +++ b/kubi/src/lib.rs @@ -75,18 +75,12 @@ use events::{ }; use input::{init_input, process_inputs}; use player_controller::{debug_switch_ctl_type, update_player_controllers}; +// use rendering::{ +// clear_background, entities::render_entities, init_window_size, primitives::init_primitives, resize_renderer, selection_box::render_selection_box, sumberge::render_submerged_view, update_window_size, world::{draw_current_chunk_border, draw_world, draw_world_trans, init_trans_chunk_queue}, BackgroundColor, RenderTarget, Renderer +// }; use rendering::{ - Renderer, - RenderTarget, - BackgroundColor, - clear_background, - init_window_size, - update_window_size, - primitives::init_primitives, - world::{init_trans_chunk_queue, draw_world, draw_world_trans, draw_current_chunk_border}, - selection_box::render_selection_box, - entities::render_entities, - sumberge::render_submerged_view, + init_window_size, resize_renderer, update_window_size, + BackgroundColor, Renderer }; use block_placement::update_block_placement; use delta_time::{DeltaTime, init_delta_time}; @@ -95,7 +89,7 @@ use control_flow::{exit_on_esc, insert_control_flow_unique, RequestExit}; use state::{is_ingame, is_ingame_or_loading, is_loading, init_state, update_state, is_connecting}; use networking::{update_networking, update_networking_late, is_multiplayer, disconnect_on_exit, is_singleplayer}; use init::initialize_from_args; -use hui_integration::{kubi_ui_begin, kubi_ui_draw, kubi_ui_end, kubi_ui_init}; +use hui_integration::{kubi_ui_begin, /*kubi_ui_draw,*/ kubi_ui_end, kubi_ui_init}; use loading_screen::update_loading_screen; use connecting_screen::update_connecting_screen; use fixed_timestamp::init_fixed_timestamp_storage; @@ -121,7 +115,7 @@ fn startup() -> Workload { init_window_size, kubi_ui_init, load_prefabs, - init_primitives, + //init_primitives, insert_lock_state, init_state, initialize_from_args, @@ -132,7 +126,7 @@ fn startup() -> Workload { init_client_physics, init_chat_manager, init_crosshair_image, - init_trans_chunk_queue, + //init_trans_chunk_queue, ).into_sequential_workload() } @@ -140,6 +134,7 @@ fn update() -> Workload { ( debug_toggle_lock, update_window_size, + resize_renderer, update_cursor_lock_state, process_inputs, kubi_ui_begin, @@ -181,20 +176,20 @@ fn update() -> Workload { ).into_sequential_workload() } -fn render() -> Workload { - ( - clear_background, - ( - draw_world, - draw_current_chunk_border, - render_selection_box, - render_entities, - draw_world_trans, - render_submerged_view, - ).into_sequential_workload().run_if(is_ingame), - kubi_ui_draw, - ).into_sequential_workload() -} +// fn render() -> Workload { +// ( +// clear_background, +// ( +// draw_world, +// draw_current_chunk_border, +// render_selection_box, +// render_entities, +// draw_world_trans, +// render_submerged_view, +// ).into_sequential_workload().run_if(is_ingame), +// kubi_ui_draw, +// ).into_sequential_workload() +// } fn after_frame_end() -> Workload { ( @@ -244,7 +239,7 @@ pub fn kubi_main( world.add_workload(pre_startup); world.add_workload(startup); world.add_workload(update); - world.add_workload(render); + //world.add_workload(render); world.add_workload(after_frame_end); //Save _visualizer.json @@ -326,18 +321,18 @@ pub fn kubi_main( world.run_workload(update).unwrap(); //Start rendering (maybe use custom views for this?) - let target = { - let renderer = world.borrow::>>().unwrap(); - renderer.display.draw() - }; - world.add_unique_non_send_sync(RenderTarget(target)); + // let target = { + // let renderer = world.borrow::>>().unwrap(); + // renderer.display.draw() + // }; + // world.add_unique_non_send_sync(RenderTarget(target)); //Run render workflow - world.run_workload(render).unwrap(); + //world.run_workload(render).unwrap(); //Finish rendering - let target = world.remove_unique::().unwrap(); - target.0.finish().unwrap(); + // let target = world.remove_unique::().unwrap(); + // target.0.finish().unwrap(); //After frame end world.run_workload(after_frame_end).unwrap(); diff --git a/kubi/src/prefabs.rs b/kubi/src/prefabs.rs index 4f5d9be..7b9583e 100644 --- a/kubi/src/prefabs.rs +++ b/kubi/src/prefabs.rs @@ -1,15 +1,13 @@ use std::{io::{BufReader, Read}, path::Path}; use hui::text::FontHandle; use shipyard::{AllStoragesView, NonSendSync, Unique, UniqueView, UniqueViewMut}; -use glium::{texture::{SrgbTexture2dArray, MipmapsOption}, Program}; use kubi_shared::block::BlockTexture; use crate::{filesystem::AssetManager, hui_integration::UiState, rendering::Renderer}; mod texture; mod shaders; -use texture::load_texture2darray_prefab; -use shaders::include_shader_prefab; +//use texture::load_texture2darray_prefab; pub trait AssetPaths { fn file_name(self) -> &'static str; @@ -41,7 +39,7 @@ impl AssetPaths for BlockTexture { #[derive(Unique)] #[repr(transparent)] -pub struct BlockTexturesPrefab(pub SrgbTexture2dArray); +pub struct BlockTexturesPrefab(pub wgpu::Texture); // #[derive(Unique)] // #[repr(transparent)] @@ -65,15 +63,15 @@ pub fn load_prefabs( mut ui: NonSendSync>, assman: UniqueView ) { - log::info!("Loading textures..."); - storages.add_unique_non_send_sync(BlockTexturesPrefab( - load_texture2darray_prefab::( - &assman, - "blocks".into(), - &renderer.display, - MipmapsOption::AutoGeneratedMipmaps - ) - )); + // log::info!("Loading textures..."); + // storages.add_unique_non_send_sync(BlockTexturesPrefab( + // load_texture2darray_prefab::( + // &assman, + // "blocks".into(), + // &renderer.display, + // MipmapsOption::AutoGeneratedMipmaps + // ) + // )); log::info!("Loading the UI stuff..."); { @@ -85,33 +83,33 @@ pub fn load_prefabs( storages.add_unique(UiFontPrefab(font_handle)); } - log::info!("Compiling shaders..."); - storages.add_unique_non_send_sync(ChunkShaderPrefab( - include_shader_prefab!( - "world", - "../shaders/world.vert", - "../shaders/world.frag", - &renderer.display - ) - )); - storages.add_unique_non_send_sync(ColoredShaderPrefab( - include_shader_prefab!( - "colored", - "../shaders/colored.vert", - "../shaders/colored.frag", - &renderer.display - ) - )); - storages.add_unique_non_send_sync(Colored2ShaderPrefab( - include_shader_prefab!( - "colored", - "../shaders/colored2.vert", - "../shaders/colored2.frag", - &renderer.display - ) - )); + //log::info!("Compiling shaders..."); + // storages.add_unique_non_send_sync(ChunkShaderPrefab( + // include_shader_prefab!( + // "world", + // "../shaders/world.vert", + // "../shaders/world.frag", + // &renderer.display + // ) + // )); + // storages.add_unique_non_send_sync(ColoredShaderPrefab( + // include_shader_prefab!( + // "colored", + // "../shaders/colored.vert", + // "../shaders/colored.frag", + // &renderer.display + // ) + // )); + // storages.add_unique_non_send_sync(Colored2ShaderPrefab( + // include_shader_prefab!( + // "colored", + // "../shaders/colored2.vert", + // "../shaders/colored2.frag", + // &renderer.display + // ) + // )); - log::info!("releasing shader compiler"); + //log::info!("releasing shader compiler"); //renderer.display.release_shader_compiler(); } diff --git a/kubi/src/prefabs/texture.rs b/kubi/src/prefabs/texture.rs index 0bd7e8d..c10c71c 100644 --- a/kubi/src/prefabs/texture.rs +++ b/kubi/src/prefabs/texture.rs @@ -1,46 +1,45 @@ -use strum::IntoEnumIterator; -use rayon::prelude::*; -use std::{path::PathBuf, io::BufReader}; -use glium::{texture::{SrgbTexture2dArray, RawImage2d, MipmapsOption}, backend::Facade}; -use crate::filesystem::AssetManager; -use super::AssetPaths; - -pub fn load_texture2darray_prefab< - T: AssetPaths + IntoEnumIterator, - E: Facade ->( - assman: &AssetManager, - directory: PathBuf, - facade: &E, - mipmaps: MipmapsOption, -) -> SrgbTexture2dArray { - log::info!("started loading {}", directory.as_os_str().to_str().unwrap()); - //Load raw images - let tex_files: Vec<&'static str> = T::iter().map(|x| x.file_name()).collect(); - let raw_images: Vec> = tex_files.par_iter().map(|&file_name| { - log::info!("loading texture {}", file_name); - //Get path to the image and open the file - let reader = { - let path = directory.join(file_name); - BufReader::new(assman.open_asset(&path).expect("Failed to open texture file")) - }; - //Parse image data - let (image_data, dimensions) = { - let image = image::load( - reader, - image::ImageFormat::Png - ).unwrap().to_rgba8(); - let dimensions = image.dimensions(); - (image.into_raw(), dimensions) - }; - //Create a glium RawImage - RawImage2d::from_raw_rgba_reversed( - &image_data, - dimensions - ) - }).collect(); - log::info!("done loading texture files, uploading to the gpu"); - //Upload images to the GPU - SrgbTexture2dArray::with_mipmaps(facade, raw_images, mipmaps) - .expect("Failed to upload texture array to GPU") -} +// use strum::IntoEnumIterator; +// use rayon::prelude::*; +// use std::{path::PathBuf, io::BufReader}; +// use crate::filesystem::AssetManager; +// use super::AssetPaths; + +// pub fn load_texture2darray_prefab< +// T: AssetPaths + IntoEnumIterator, +// E: Facade +// >( +// assman: &AssetManager, +// directory: PathBuf, +// facade: &E, +// mipmaps: MipmapsOption, +// ) -> SrgbTexture2dArray { +// log::info!("started loading {}", directory.as_os_str().to_str().unwrap()); +// //Load raw images +// let tex_files: Vec<&'static str> = T::iter().map(|x| x.file_name()).collect(); +// let raw_images: Vec> = tex_files.par_iter().map(|&file_name| { +// log::info!("loading texture {}", file_name); +// //Get path to the image and open the file +// let reader = { +// let path = directory.join(file_name); +// BufReader::new(assman.open_asset(&path).expect("Failed to open texture file")) +// }; +// //Parse image data +// let (image_data, dimensions) = { +// let image = image::load( +// reader, +// image::ImageFormat::Png +// ).unwrap().to_rgba8(); +// let dimensions = image.dimensions(); +// (image.into_raw(), dimensions) +// }; +// //Create a glium RawImage +// RawImage2d::from_raw_rgba_reversed( +// &image_data, +// dimensions +// ) +// }).collect(); +// log::info!("done loading texture files, uploading to the gpu"); +// //Upload images to the GPU +// SrgbTexture2dArray::with_mipmaps(facade, raw_images, mipmaps) +// .expect("Failed to upload texture array to GPU") +// } diff --git a/kubi/src/rendering.rs b/kubi/src/rendering.rs index 1da5fd0..409fbf0 100644 --- a/kubi/src/rendering.rs +++ b/kubi/src/rendering.rs @@ -1,5 +1,7 @@ use pollster::FutureExt; -use shipyard::{Unique, NonSendSync, UniqueView, UniqueViewMut, View, IntoIter, AllStoragesView}; +use raw_window_handle::HasRawWindowHandle; +use shipyard::{AllStoragesView, AllStoragesViewMut, IntoIter, NonSendSync, Unique, UniqueView, UniqueViewMut, View}; +use wgpu::SurfaceTargetUnsafe; use winit::{ event_loop::ActiveEventLoop, window::{WindowAttributes, Fullscreen, Window}, @@ -14,6 +16,11 @@ pub mod selection_box; pub mod entities; pub mod sumberge; +pub struct BufferPair { + pub index: wgpu::Buffer, + pub vertex: wgpu::Buffer, +} + #[derive(Unique)] #[repr(transparent)] pub struct BackgroundColor(pub Vec3); @@ -26,14 +33,16 @@ pub struct WindowSize(pub UVec2); #[derive(Unique)] pub struct Renderer { - pub window: Window, - pub instance: wgpu::Instance, - pub surface: wgpu::Surface<'static>, - pub device: wgpu::Device, - pub queue: wgpu::Queue, - pub surface_config: wgpu::SurfaceConfiguration, - pub size: PhysicalSize, + instance: wgpu::Instance, + surface: wgpu::Surface<'static>, + device: wgpu::Device, + queue: wgpu::Queue, + surface_config: wgpu::SurfaceConfiguration, + size: PhysicalSize, // pub depth_texture: wgpu::Texture, + + //must be last due to drop order + window: Window, } impl Renderer { @@ -95,7 +104,11 @@ impl Renderer { ..Default::default() }); - let surface = instance.create_surface(window).unwrap(); + // Create a surface with `create_surface_unsafe` to get a surface with 'static lifetime + // It should never outlive the window it's created from + let surface = unsafe { + instance.create_surface_unsafe(SurfaceTargetUnsafe::from_window(&window).unwrap()).unwrap() + }; let adapter = instance.request_adapter( &wgpu::RequestAdapterOptions { @@ -139,13 +152,89 @@ impl Renderer { pub fn reconfigure(&self) { self.surface.configure(&self.device, &self.surface_config); } + + //getters: + pub fn size(&self) -> PhysicalSize { + self.size + } + + pub fn window(&self) -> &Window { + &self.window + } + + pub fn surface(&self) -> &wgpu::Surface<'static> { + &self.surface + } + + pub fn device(&self) -> &wgpu::Device { + &self.device + } + + pub fn queue(&self) -> &wgpu::Queue { + &self.queue + } + + pub fn surface_config(&self) -> &wgpu::SurfaceConfiguration { + &self.surface_config + } } -pub fn clear_background( - mut target: NonSendSync>, - color: UniqueView, +pub fn render_master(storages: AllStoragesViewMut) { + let renderer = storages.borrow::>().unwrap(); + + let mut encoder = renderer.device.create_command_encoder(&wgpu::CommandEncoderDescriptor { + label: Some("main_encoder"), + }); + let surface_texture = renderer.surface().get_current_texture().unwrap(); + let surface_view = surface_texture.texture.create_view(&wgpu::TextureViewDescriptor::default()); + + { + let bg_color = storages.borrow::>().unwrap(); + let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + label: Some("main0_pass"), + color_attachments: &[Some(wgpu::RenderPassColorAttachment { + view: &surface_view, + resolve_target: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Clear(wgpu::Color { + r: bg_color.0.x as f64, + g: bg_color.0.y as f64, + b: bg_color.0.z as f64, + a: 1.0, + }), + store: wgpu::StoreOp::Store, + }, + })], + depth_stencil_attachment: None, + ..Default::default() + }); + + // render_pass.set_pipeline(&renderer.pipeline); + // render_pass.set_bind_group(0, &renderer.bind_group, &[]); + // render_pass.set_vertex_buffer(0, renderer.vertex_buffer.slice(..)); + // render_pass.set_index_buffer(renderer.index_buffer.slice(..)); + // render_pass.draw_indexed(0..renderer.num_indices, 0, 0..1); + } + + renderer.queue().submit(Some(encoder.finish())); +} + +// pub fn clear_background( +// mut target: NonSendSync>, +// color: UniqueView, +// ) { +// target.0.clear_color_srgb_and_depth((color.0.x, color.0.y, color.0.z, 1.), 1.); +// } + +//Resize the renderer + +pub fn resize_renderer( + mut renderer: UniqueViewMut, + resize: View, ) { - target.0.clear_color_srgb_and_depth((color.0.x, color.0.y, color.0.z, 1.), 1.); + if let Some(size) = resize.iter().last() { + renderer.resize(PhysicalSize::new(size.0.x, size.0.y)); + } } //not sure if this belongs here diff --git a/kubi/src/rendering/entities.rs b/kubi/src/rendering/entities.rs index 0135edf..3282cc9 100644 --- a/kubi/src/rendering/entities.rs +++ b/kubi/src/rendering/entities.rs @@ -1,58 +1,58 @@ -use shipyard::{NonSendSync, UniqueViewMut, UniqueView, View, IntoIter, IntoWithId}; -use glium::{DepthTest, Depth, PolygonMode, BackfaceCullingMode, DrawParameters, Surface, uniform}; -use kubi_shared::{entity::Entity, transform::Transform}; -use crate::{ - prefabs::ColoredShaderPrefab, - camera::Camera, - settings::GameSettings -}; -use super::{ - RenderTarget, - primitives::cube::CenteredCubePrimitive -}; - -// TODO: entity models -pub fn render_entities( - mut target: NonSendSync>, - buffers: NonSendSync>, - program: NonSendSync>, - camera: View, - settings: UniqueView, - entities: View, - transform: View, -) { - let (camera_id, camera) = camera.iter().with_id().next().expect("No cameras in the scene"); - - let draw_parameters = DrawParameters { - depth: Depth { - test: DepthTest::IfLess, - write: true, - ..Default::default() - }, - multisampling: settings.msaa.is_some(), - polygon_mode: PolygonMode::Fill, - backface_culling: BackfaceCullingMode::CullClockwise, - ..Default::default() - }; - let view = camera.view_matrix.to_cols_array_2d(); - let perspective = camera.perspective_matrix.to_cols_array_2d(); - - for (entity_id, (_, trans)) in (&entities, &transform).iter().with_id() { - //skip rendering camera holder (as the entity would block the view) - if entity_id == camera_id { continue } - - //render entity - target.0.draw( - &buffers.0, - &buffers.1, - &program.0, - &uniform! { - color: [1.0, 1.0, 1.0, 1.0_f32], - model: trans.0.to_cols_array_2d(), - view: view, - perspective: perspective, - }, - &draw_parameters - ).unwrap(); - } -} +// use shipyard::{NonSendSync, UniqueViewMut, UniqueView, View, IntoIter, IntoWithId}; +// use glium::{DepthTest, Depth, PolygonMode, BackfaceCullingMode, DrawParameters, Surface, uniform}; +// use kubi_shared::{entity::Entity, transform::Transform}; +// use crate::{ +// prefabs::ColoredShaderPrefab, +// camera::Camera, +// settings::GameSettings +// }; +// use super::{ +// RenderTarget, +// primitives::cube::CenteredCubePrimitive +// }; + +// // TODO: entity models +// pub fn render_entities( +// mut target: NonSendSync>, +// buffers: NonSendSync>, +// program: NonSendSync>, +// camera: View, +// settings: UniqueView, +// entities: View, +// transform: View, +// ) { +// let (camera_id, camera) = camera.iter().with_id().next().expect("No cameras in the scene"); + +// let draw_parameters = DrawParameters { +// depth: Depth { +// test: DepthTest::IfLess, +// write: true, +// ..Default::default() +// }, +// multisampling: settings.msaa.is_some(), +// polygon_mode: PolygonMode::Fill, +// backface_culling: BackfaceCullingMode::CullClockwise, +// ..Default::default() +// }; +// let view = camera.view_matrix.to_cols_array_2d(); +// let perspective = camera.perspective_matrix.to_cols_array_2d(); + +// for (entity_id, (_, trans)) in (&entities, &transform).iter().with_id() { +// //skip rendering camera holder (as the entity would block the view) +// if entity_id == camera_id { continue } + +// //render entity +// target.0.draw( +// &buffers.0, +// &buffers.1, +// &program.0, +// &uniform! { +// color: [1.0, 1.0, 1.0, 1.0_f32], +// model: trans.0.to_cols_array_2d(), +// view: view, +// perspective: perspective, +// }, +// &draw_parameters +// ).unwrap(); +// } +// } diff --git a/kubi/src/rendering/primitives.rs b/kubi/src/rendering/primitives.rs index 26666bd..115ff49 100644 --- a/kubi/src/rendering/primitives.rs +++ b/kubi/src/rendering/primitives.rs @@ -1,30 +1,30 @@ -use shipyard::{Workload, IntoWorkload}; -use glium::implement_vertex; +// use shipyard::{Workload, IntoWorkload}; +// use glium::implement_vertex; -pub mod cube; -pub mod rect; -pub mod stri; +// pub mod cube; +// pub mod rect; +// pub mod stri; -use cube::init_cube_primitive; -use rect::init_rect_primitive; -use stri::init_stri_primitive; +// use cube::init_cube_primitive; +// use rect::init_rect_primitive; +// use stri::init_stri_primitive; -#[derive(Clone, Copy, Default)] -pub struct PositionOnlyVertex { - pub position: [f32; 3], -} -implement_vertex!(PositionOnlyVertex, position); +// #[derive(Clone, Copy, Default)] +// pub struct PositionOnlyVertex { +// pub position: [f32; 3], +// } +// implement_vertex!(PositionOnlyVertex, position); -#[derive(Clone, Copy, Default)] -pub struct PositionOnlyVertex2d { - pub position: [f32; 2], -} -implement_vertex!(PositionOnlyVertex2d, position); +// #[derive(Clone, Copy, Default)] +// pub struct PositionOnlyVertex2d { +// pub position: [f32; 2], +// } +// implement_vertex!(PositionOnlyVertex2d, position); -pub fn init_primitives() -> Workload { - ( - init_cube_primitive, - init_rect_primitive, - init_stri_primitive, - ).into_workload() -} +// pub fn init_primitives() -> Workload { +// ( +// init_cube_primitive, +// init_rect_primitive, +// init_stri_primitive, +// ).into_workload() +// } diff --git a/kubi/src/rendering/primitives/cube.rs b/kubi/src/rendering/primitives/cube.rs index 20f8616..2e3b5c8 100644 --- a/kubi/src/rendering/primitives/cube.rs +++ b/kubi/src/rendering/primitives/cube.rs @@ -1,85 +1,85 @@ -use shipyard::{AllStoragesView, NonSendSync, UniqueView, Unique}; -use glium::{VertexBuffer, IndexBuffer, index::PrimitiveType}; -use crate::rendering::Renderer; -use super::PositionOnlyVertex; - -#[derive(Unique)] -pub struct CubePrimitive(pub VertexBuffer, pub IndexBuffer); - -#[derive(Unique)] -pub struct CenteredCubePrimitive(pub VertexBuffer, pub IndexBuffer); - -const CENTERED_CUBE_VERTICES: &[PositionOnlyVertex] = &[ - // front - PositionOnlyVertex { position: [-0.5, -0.5, 0.5] }, - PositionOnlyVertex { position: [ 0.5, -0.5, 0.5] }, - PositionOnlyVertex { position: [ 0.5, 0.5, 0.5] }, - PositionOnlyVertex { position: [-0.5, 0.5, 0.5] }, - // back - PositionOnlyVertex { position: [-0.5, -0.5, -0.5] }, - PositionOnlyVertex { position: [ 0.5, -0.5, -0.5] }, - PositionOnlyVertex { position: [ 0.5, 0.5, -0.5] }, - PositionOnlyVertex { position: [-0.5, 0.5, -0.5] }, -]; -const CUBE_VERTICES: &[PositionOnlyVertex] = &[ - // front - PositionOnlyVertex { position: [0.0, 0.0, 1.0] }, - PositionOnlyVertex { position: [1.0, 0.0, 1.0] }, - PositionOnlyVertex { position: [1.0, 1.0, 1.0] }, - PositionOnlyVertex { position: [0.0, 1.0, 1.0] }, - // back - PositionOnlyVertex { position: [0.0, 0.0, 0.0] }, - PositionOnlyVertex { position: [1.0, 0.0, 0.0] }, - PositionOnlyVertex { position: [1.0, 1.0, 0.0] }, - PositionOnlyVertex { position: [0.0, 1.0, 0.0] }, -]; -const CUBE_INDICES: &[u16] = &[ - // front - 0, 1, 2, - 2, 3, 0, - // right - 1, 5, 6, - 6, 2, 1, - // back - 7, 6, 5, - 5, 4, 7, - // left - 4, 0, 3, - 3, 7, 4, - // bottom - 4, 5, 1, - 1, 0, 4, - // top - 3, 2, 6, - 6, 7, 3 -]; - -pub(super) fn init_cube_primitive( - storages: AllStoragesView, - display: NonSendSync> -) { - { - let vert = VertexBuffer::immutable( - &display.display, - CUBE_VERTICES - ).unwrap(); - let index = IndexBuffer::immutable( - &display.display, - PrimitiveType::TrianglesList, - CUBE_INDICES - ).unwrap(); - storages.add_unique_non_send_sync(CubePrimitive(vert, index)); - } - { - let vert = VertexBuffer::immutable( - &display.display, - CENTERED_CUBE_VERTICES - ).unwrap(); - let index = IndexBuffer::immutable( - &display.display, - PrimitiveType::TrianglesList, - CUBE_INDICES - ).unwrap(); - storages.add_unique_non_send_sync(CenteredCubePrimitive(vert, index)); - } -} +// use shipyard::{AllStoragesView, NonSendSync, UniqueView, Unique}; +// use glium::{VertexBuffer, IndexBuffer, index::PrimitiveType}; +// use crate::rendering::Renderer; +// use super::PositionOnlyVertex; + +// #[derive(Unique)] +// pub struct CubePrimitive(pub VertexBuffer, pub IndexBuffer); + +// #[derive(Unique)] +// pub struct CenteredCubePrimitive(pub VertexBuffer, pub IndexBuffer); + +// const CENTERED_CUBE_VERTICES: &[PositionOnlyVertex] = &[ +// // front +// PositionOnlyVertex { position: [-0.5, -0.5, 0.5] }, +// PositionOnlyVertex { position: [ 0.5, -0.5, 0.5] }, +// PositionOnlyVertex { position: [ 0.5, 0.5, 0.5] }, +// PositionOnlyVertex { position: [-0.5, 0.5, 0.5] }, +// // back +// PositionOnlyVertex { position: [-0.5, -0.5, -0.5] }, +// PositionOnlyVertex { position: [ 0.5, -0.5, -0.5] }, +// PositionOnlyVertex { position: [ 0.5, 0.5, -0.5] }, +// PositionOnlyVertex { position: [-0.5, 0.5, -0.5] }, +// ]; +// const CUBE_VERTICES: &[PositionOnlyVertex] = &[ +// // front +// PositionOnlyVertex { position: [0.0, 0.0, 1.0] }, +// PositionOnlyVertex { position: [1.0, 0.0, 1.0] }, +// PositionOnlyVertex { position: [1.0, 1.0, 1.0] }, +// PositionOnlyVertex { position: [0.0, 1.0, 1.0] }, +// // back +// PositionOnlyVertex { position: [0.0, 0.0, 0.0] }, +// PositionOnlyVertex { position: [1.0, 0.0, 0.0] }, +// PositionOnlyVertex { position: [1.0, 1.0, 0.0] }, +// PositionOnlyVertex { position: [0.0, 1.0, 0.0] }, +// ]; +// const CUBE_INDICES: &[u16] = &[ +// // front +// 0, 1, 2, +// 2, 3, 0, +// // right +// 1, 5, 6, +// 6, 2, 1, +// // back +// 7, 6, 5, +// 5, 4, 7, +// // left +// 4, 0, 3, +// 3, 7, 4, +// // bottom +// 4, 5, 1, +// 1, 0, 4, +// // top +// 3, 2, 6, +// 6, 7, 3 +// ]; + +// pub(super) fn init_cube_primitive( +// storages: AllStoragesView, +// display: NonSendSync> +// ) { +// { +// let vert = VertexBuffer::immutable( +// &display.display, +// CUBE_VERTICES +// ).unwrap(); +// let index = IndexBuffer::immutable( +// &display.display, +// PrimitiveType::TrianglesList, +// CUBE_INDICES +// ).unwrap(); +// storages.add_unique_non_send_sync(CubePrimitive(vert, index)); +// } +// { +// let vert = VertexBuffer::immutable( +// &display.display, +// CENTERED_CUBE_VERTICES +// ).unwrap(); +// let index = IndexBuffer::immutable( +// &display.display, +// PrimitiveType::TrianglesList, +// CUBE_INDICES +// ).unwrap(); +// storages.add_unique_non_send_sync(CenteredCubePrimitive(vert, index)); +// } +// } diff --git a/kubi/src/rendering/primitives/rect.rs b/kubi/src/rendering/primitives/rect.rs index 3a30575..4eca75c 100644 --- a/kubi/src/rendering/primitives/rect.rs +++ b/kubi/src/rendering/primitives/rect.rs @@ -1,31 +1,31 @@ -use shipyard::{Unique, AllStoragesView, NonSendSync, UniqueView}; -use glium::{VertexBuffer, IndexBuffer, index::PrimitiveType}; -use crate::rendering::Renderer; -use super::PositionOnlyVertex2d; - -#[derive(Unique)] -pub struct RectPrimitive(pub VertexBuffer, pub IndexBuffer); - -const RECT_VERTEX: &[PositionOnlyVertex2d] = &[ - PositionOnlyVertex2d { position: [0., 0.] }, - PositionOnlyVertex2d { position: [1., 0.] }, - PositionOnlyVertex2d { position: [0., 1.] }, - PositionOnlyVertex2d { position: [1., 1.] }, -]; -const RECT_INDEX: &[u16] = &[0, 1, 2, 1, 3, 2]; - -pub(super) fn init_rect_primitive( - storages: AllStoragesView, - display: NonSendSync> -) { - let vert = VertexBuffer::immutable( - &display.display, - RECT_VERTEX - ).unwrap(); - let index = IndexBuffer::immutable( - &display.display, - PrimitiveType::TrianglesList, - RECT_INDEX - ).unwrap(); - storages.add_unique_non_send_sync(RectPrimitive(vert, index)); -} +// use shipyard::{Unique, AllStoragesView, NonSendSync, UniqueView}; +// use glium::{VertexBuffer, IndexBuffer, index::PrimitiveType}; +// use crate::rendering::Renderer; +// use super::PositionOnlyVertex2d; + +// #[derive(Unique)] +// pub struct RectPrimitive(pub VertexBuffer, pub IndexBuffer); + +// const RECT_VERTEX: &[PositionOnlyVertex2d] = &[ +// PositionOnlyVertex2d { position: [0., 0.] }, +// PositionOnlyVertex2d { position: [1., 0.] }, +// PositionOnlyVertex2d { position: [0., 1.] }, +// PositionOnlyVertex2d { position: [1., 1.] }, +// ]; +// const RECT_INDEX: &[u16] = &[0, 1, 2, 1, 3, 2]; + +// pub(super) fn init_rect_primitive( +// storages: AllStoragesView, +// display: NonSendSync> +// ) { +// let vert = VertexBuffer::immutable( +// &display.display, +// RECT_VERTEX +// ).unwrap(); +// let index = IndexBuffer::immutable( +// &display.display, +// PrimitiveType::TrianglesList, +// RECT_INDEX +// ).unwrap(); +// storages.add_unique_non_send_sync(RectPrimitive(vert, index)); +// } diff --git a/kubi/src/rendering/primitives/stri.rs b/kubi/src/rendering/primitives/stri.rs index dbc5c40..2cafaf9 100644 --- a/kubi/src/rendering/primitives/stri.rs +++ b/kubi/src/rendering/primitives/stri.rs @@ -1,30 +1,30 @@ -use shipyard::{Unique, AllStoragesView, NonSendSync, UniqueView}; -use glium::{VertexBuffer, IndexBuffer, index::PrimitiveType}; -use crate::rendering::Renderer; -use super::PositionOnlyVertex2d; +// use shipyard::{Unique, AllStoragesView, NonSendSync, UniqueView}; +// use glium::{VertexBuffer, IndexBuffer, index::PrimitiveType}; +// use crate::rendering::Renderer; +// use super::PositionOnlyVertex2d; -#[derive(Unique)] -pub struct STriPrimitive(pub VertexBuffer, pub IndexBuffer); +// #[derive(Unique)] +// pub struct STriPrimitive(pub VertexBuffer, pub IndexBuffer); -const STRI_VERTEX: &[PositionOnlyVertex2d] = &[ - PositionOnlyVertex2d { position: [-1., -1.] }, - PositionOnlyVertex2d { position: [ 3., -1.] }, - PositionOnlyVertex2d { position: [-1., 3.] }, -]; -const STRI_INDEX: &[u16] = &[0, 1, 2]; +// const STRI_VERTEX: &[PositionOnlyVertex2d] = &[ +// PositionOnlyVertex2d { position: [-1., -1.] }, +// PositionOnlyVertex2d { position: [ 3., -1.] }, +// PositionOnlyVertex2d { position: [-1., 3.] }, +// ]; +// const STRI_INDEX: &[u16] = &[0, 1, 2]; -pub(super) fn init_stri_primitive( - storages: AllStoragesView, - display: NonSendSync> -) { - let vert = VertexBuffer::immutable( - &display.display, - STRI_VERTEX - ).unwrap(); - let index = IndexBuffer::immutable( - &display.display, - PrimitiveType::TrianglesList, - STRI_INDEX - ).unwrap(); - storages.add_unique_non_send_sync(STriPrimitive(vert, index)); -} +// pub(super) fn init_stri_primitive( +// storages: AllStoragesView, +// display: NonSendSync> +// ) { +// let vert = VertexBuffer::immutable( +// &display.display, +// STRI_VERTEX +// ).unwrap(); +// let index = IndexBuffer::immutable( +// &display.display, +// PrimitiveType::TrianglesList, +// STRI_INDEX +// ).unwrap(); +// storages.add_unique_non_send_sync(STriPrimitive(vert, index)); +// } diff --git a/kubi/src/rendering/selection_box.rs b/kubi/src/rendering/selection_box.rs index 8f0e2eb..ad89716 100644 --- a/kubi/src/rendering/selection_box.rs +++ b/kubi/src/rendering/selection_box.rs @@ -1,59 +1,59 @@ -use glam::{Mat4, Vec3, Quat}; -use shipyard::{View, IntoIter, NonSendSync, UniqueViewMut, UniqueView}; -use glium::{ - Surface, - DrawParameters, - BackfaceCullingMode, - Blend, Depth, DepthTest, - uniform, -}; -use crate::{ - world::raycast::LookingAtBlock, - camera::Camera, - prefabs::ColoredShaderPrefab -}; -use super::{ - RenderTarget, - primitives::cube::CubePrimitive, -}; - -const SMOL: f32 = 0.0025; - -pub fn render_selection_box( - lookat: View, - camera: View, - mut target: NonSendSync>, - program: NonSendSync>, - buffers: NonSendSync>, -) { - let camera = camera.iter().next().unwrap(); - let Some(lookat) = lookat.iter().next() else { return }; - let Some(lookat) = lookat.0 else { return }; - - //Darken block - target.0.draw( - &buffers.0, - &buffers.1, - &program.0, - &uniform! { - color: [0., 0., 0., 0.5_f32], - model: Mat4::from_scale_rotation_translation( - Vec3::splat(1. + SMOL * 2.), - Quat::default(), - lookat.block_position.as_vec3() - Vec3::splat(SMOL) - ).to_cols_array_2d(), - perspective: camera.perspective_matrix.to_cols_array_2d(), - view: camera.view_matrix.to_cols_array_2d(), - }, - &DrawParameters { - backface_culling: BackfaceCullingMode::CullClockwise, - blend: Blend::alpha_blending(), - depth: Depth { - //this may be unreliable... unless scale is applied! hacky... - test: DepthTest::IfLessOrEqual, - ..Default::default() - }, - ..Default::default() - } - ).unwrap(); -} +// use glam::{Mat4, Vec3, Quat}; +// use shipyard::{View, IntoIter, NonSendSync, UniqueViewMut, UniqueView}; +// use glium::{ +// Surface, +// DrawParameters, +// BackfaceCullingMode, +// Blend, Depth, DepthTest, +// uniform, +// }; +// use crate::{ +// world::raycast::LookingAtBlock, +// camera::Camera, +// prefabs::ColoredShaderPrefab +// }; +// use super::{ +// RenderTarget, +// primitives::cube::CubePrimitive, +// }; + +// const SMOL: f32 = 0.0025; + +// pub fn render_selection_box( +// lookat: View, +// camera: View, +// mut target: NonSendSync>, +// program: NonSendSync>, +// buffers: NonSendSync>, +// ) { +// let camera = camera.iter().next().unwrap(); +// let Some(lookat) = lookat.iter().next() else { return }; +// let Some(lookat) = lookat.0 else { return }; + +// //Darken block +// target.0.draw( +// &buffers.0, +// &buffers.1, +// &program.0, +// &uniform! { +// color: [0., 0., 0., 0.5_f32], +// model: Mat4::from_scale_rotation_translation( +// Vec3::splat(1. + SMOL * 2.), +// Quat::default(), +// lookat.block_position.as_vec3() - Vec3::splat(SMOL) +// ).to_cols_array_2d(), +// perspective: camera.perspective_matrix.to_cols_array_2d(), +// view: camera.view_matrix.to_cols_array_2d(), +// }, +// &DrawParameters { +// backface_culling: BackfaceCullingMode::CullClockwise, +// blend: Blend::alpha_blending(), +// depth: Depth { +// //this may be unreliable... unless scale is applied! hacky... +// test: DepthTest::IfLessOrEqual, +// ..Default::default() +// }, +// ..Default::default() +// } +// ).unwrap(); +// } diff --git a/kubi/src/rendering/sumberge.rs b/kubi/src/rendering/sumberge.rs index b947b9c..a44da40 100644 --- a/kubi/src/rendering/sumberge.rs +++ b/kubi/src/rendering/sumberge.rs @@ -1,39 +1,39 @@ -use glium::{uniform, Blend, DrawParameters, Surface}; -use kubi_shared::transform::Transform; -use shipyard::{IntoIter, NonSendSync, UniqueView, UniqueViewMut, View}; -use crate::{ - player::MainPlayer, - prefabs::Colored2ShaderPrefab, - rendering::primitives::stri::STriPrimitive, - world::ChunkStorage, -}; -use super::RenderTarget; +// use glium::{uniform, Blend, DrawParameters, Surface}; +// use kubi_shared::transform::Transform; +// use shipyard::{IntoIter, NonSendSync, UniqueView, UniqueViewMut, View}; +// use crate::{ +// player::MainPlayer, +// prefabs::Colored2ShaderPrefab, +// rendering::primitives::stri::STriPrimitive, +// world::ChunkStorage, +// }; +// use super::RenderTarget; -pub fn render_submerged_view( - mut target: NonSendSync>, - primitive: NonSendSync>, - program: NonSendSync>, - plr: View, - trans: View, - world: UniqueView, -) { - let (_, plr_trans) = (&plr, &trans).iter().next().expect("Main player MIA"); - let plr_pos = plr_trans.0.to_scale_rotation_translation().2; - let block_at_pos = world.get_block(plr_pos.floor().as_ivec3()); - let Some(block_at_pos) = block_at_pos else { return }; - let Some(color) = block_at_pos.descriptor().submerge else { return }; +// pub fn render_submerged_view( +// mut target: NonSendSync>, +// primitive: NonSendSync>, +// program: NonSendSync>, +// plr: View, +// trans: View, +// world: UniqueView, +// ) { +// let (_, plr_trans) = (&plr, &trans).iter().next().expect("Main player MIA"); +// let plr_pos = plr_trans.0.to_scale_rotation_translation().2; +// let block_at_pos = world.get_block(plr_pos.floor().as_ivec3()); +// let Some(block_at_pos) = block_at_pos else { return }; +// let Some(color) = block_at_pos.descriptor().submerge else { return }; - let draw_parameters = DrawParameters { - blend: Blend::alpha_blending(), - ..Default::default() - }; - target.0.draw( - &primitive.0, - &primitive.1, - &program.0, - &uniform! { - color: color.to_array(), - }, - &draw_parameters, - ).unwrap(); -} +// let draw_parameters = DrawParameters { +// blend: Blend::alpha_blending(), +// ..Default::default() +// }; +// target.0.draw( +// &primitive.0, +// &primitive.1, +// &program.0, +// &uniform! { +// color: color.to_array(), +// }, +// &draw_parameters, +// ).unwrap(); +// } diff --git a/kubi/src/rendering/world.rs b/kubi/src/rendering/world.rs index 3deb600..9f3dffc 100644 --- a/kubi/src/rendering/world.rs +++ b/kubi/src/rendering/world.rs @@ -1,28 +1,28 @@ -use glam::{ivec3, IVec3, Mat4, Quat, Vec3}; -use shipyard::{track, AllStoragesView, IntoIter, NonSendSync, Unique, UniqueView, UniqueViewMut, View}; -use glium::{ - draw_parameters::{ - BackfaceCullingMode, Depth, DepthTest, PolygonMode - }, implement_vertex, uniform, uniforms::{ - MagnifySamplerFilter, MinifySamplerFilter, Sampler, SamplerBehavior, SamplerWrapFunction - }, Blend, DrawParameters, Smooth, Surface -}; -use crate::{ - camera::Camera, - player::MainPlayer, - transform::Transform, - prefabs::{ - ChunkShaderPrefab, - BlockTexturesPrefab, - ColoredShaderPrefab, - }, - world::{ - ChunkStorage, - ChunkMeshStorage, - chunk::CHUNK_SIZE, - }, settings::GameSettings, -}; -use super::{RenderTarget, primitives::cube::CubePrimitive}; +// use glam::{ivec3, IVec3, Mat4, Quat, Vec3}; +// use shipyard::{track, AllStoragesView, IntoIter, NonSendSync, Unique, UniqueView, UniqueViewMut, View}; +// use glium::{ +// draw_parameters::{ +// BackfaceCullingMode, Depth, DepthTest, PolygonMode +// }, implement_vertex, uniform, uniforms::{ +// MagnifySamplerFilter, MinifySamplerFilter, Sampler, SamplerBehavior, SamplerWrapFunction +// }, Blend, DrawParameters, Smooth, Surface +// }; +// use crate::{ +// camera::Camera, +// player::MainPlayer, +// transform::Transform, +// prefabs::{ +// ChunkShaderPrefab, +// BlockTexturesPrefab, +// ColoredShaderPrefab, +// }, +// world::{ +// ChunkStorage, +// ChunkMeshStorage, +// chunk::CHUNK_SIZE, +// }, settings::GameSettings, +// }; +// use super::{RenderTarget, primitives::cube::CubePrimitive}; #[derive(Clone, Copy)] #[repr(C)] @@ -32,217 +32,216 @@ pub struct ChunkVertex { pub uv: [f32; 2], pub tex_index: u8, } -implement_vertex!(ChunkVertex, position, normal, uv, tex_index); -#[derive(Unique)] -pub struct TransChunkQueue(pub Vec); +// #[derive(Unique)] +// pub struct TransChunkQueue(pub Vec); -pub fn init_trans_chunk_queue(storages: AllStoragesView) { - storages.add_unique(TransChunkQueue(Vec::with_capacity(512))); -} +// pub fn init_trans_chunk_queue(storages: AllStoragesView) { +// storages.add_unique(TransChunkQueue(Vec::with_capacity(512))); +// } -fn draw_params(settings: &GameSettings) -> DrawParameters { - DrawParameters { - depth: Depth { - test: DepthTest::IfLess, - write: true, - ..Default::default() - }, - multisampling: settings.msaa.is_some(), - polygon_mode: PolygonMode::Fill, //Change to Line for wireframe - backface_culling: BackfaceCullingMode::CullClockwise, - ..Default::default() - } -} +// fn draw_params(settings: &GameSettings) -> DrawParameters { +// DrawParameters { +// depth: Depth { +// test: DepthTest::IfLess, +// write: true, +// ..Default::default() +// }, +// multisampling: settings.msaa.is_some(), +// polygon_mode: PolygonMode::Fill, //Change to Line for wireframe +// backface_culling: BackfaceCullingMode::CullClockwise, +// ..Default::default() +// } +// } -fn texture_sampler<'a, T>(texture: &'a T, settings: &GameSettings) -> Sampler<'a, T> { - Sampler(texture, SamplerBehavior { - minify_filter: MinifySamplerFilter::LinearMipmapLinear, - magnify_filter: MagnifySamplerFilter::Nearest, - max_anisotropy: settings.max_anisotropy.unwrap_or_default(), - wrap_function: (SamplerWrapFunction::Clamp, SamplerWrapFunction::Clamp, SamplerWrapFunction::Clamp), - depth_texture_comparison: None, - }) -} +// fn texture_sampler<'a, T>(texture: &'a T, settings: &GameSettings) -> Sampler<'a, T> { +// Sampler(texture, SamplerBehavior { +// minify_filter: MinifySamplerFilter::LinearMipmapLinear, +// magnify_filter: MagnifySamplerFilter::Nearest, +// max_anisotropy: settings.max_anisotropy.unwrap_or_default(), +// wrap_function: (SamplerWrapFunction::Clamp, SamplerWrapFunction::Clamp, SamplerWrapFunction::Clamp), +// depth_texture_comparison: None, +// }) +// } -pub fn draw_world( - mut target: NonSendSync>, - chunks: UniqueView, - meshes: NonSendSync>, - program: NonSendSync>, - texture: NonSendSync>, - transform: View, - camera: View, - settings: UniqueView, - mut trans_queue: UniqueViewMut, -) { - // let (camera, transform) = (&camera, &transform).iter().next().expect("No cameras in the scene"); - // let camera_position = transform.0.to_scale_rotation_translation().2; +// pub fn draw_world( +// mut target: NonSendSync>, +// chunks: UniqueView, +// meshes: NonSendSync>, +// program: NonSendSync>, +// texture: NonSendSync>, +// transform: View, +// camera: View, +// settings: UniqueView, +// mut trans_queue: UniqueViewMut, +// ) { +// // let (camera, transform) = (&camera, &transform).iter().next().expect("No cameras in the scene"); +// // let camera_position = transform.0.to_scale_rotation_translation().2; - let camera = camera.iter().next().expect("No cameras in the scene"); - let view = camera.view_matrix.to_cols_array_2d(); - let perspective = camera.perspective_matrix.to_cols_array_2d(); +// let camera = camera.iter().next().expect("No cameras in the scene"); +// let view = camera.view_matrix.to_cols_array_2d(); +// let perspective = camera.perspective_matrix.to_cols_array_2d(); - let draw_parameters = draw_params(&settings); - let texture_sampler = texture_sampler(&texture.0, &settings); +// let draw_parameters = draw_params(&settings); +// let texture_sampler = texture_sampler(&texture.0, &settings); - for (&position, chunk) in &chunks.chunks { - if let Some(key) = chunk.mesh_index { - let mesh = meshes.get(key).expect("Mesh index pointing to nothing"); - let world_position = position.as_vec3() * CHUNK_SIZE as f32; +// for (&position, chunk) in &chunks.chunks { +// if let Some(key) = chunk.mesh_index { +// let mesh = meshes.get(key).expect("Mesh index pointing to nothing"); +// let world_position = position.as_vec3() * CHUNK_SIZE as f32; - //Skip mesh if its empty - if mesh.index_buffer.len() == 0 && mesh.trans_index_buffer.len() == 0 { - continue - } +// //Skip mesh if its empty +// if mesh.index_buffer.len() == 0 && mesh.trans_index_buffer.len() == 0 { +// continue +// } - //Frustum culling - { - let minp = world_position; - let maxp = world_position + Vec3::splat(CHUNK_SIZE as f32); - if !camera.frustum.is_box_visible(minp, maxp) { - continue - } - } +// //Frustum culling +// { +// let minp = world_position; +// let maxp = world_position + Vec3::splat(CHUNK_SIZE as f32); +// if !camera.frustum.is_box_visible(minp, maxp) { +// continue +// } +// } - //Draw chunk mesh - if mesh.index_buffer.len() > 0 { - target.0.draw( - &mesh.vertex_buffer, - &mesh.index_buffer, - &program.0, - &uniform! { - position_offset: world_position.to_array(), - view: view, - perspective: perspective, - tex: texture_sampler, - discard_alpha: true, - }, - &draw_parameters - ).unwrap(); - } +// //Draw chunk mesh +// if mesh.index_buffer.len() > 0 { +// target.0.draw( +// &mesh.vertex_buffer, +// &mesh.index_buffer, +// &program.0, +// &uniform! { +// position_offset: world_position.to_array(), +// view: view, +// perspective: perspective, +// tex: texture_sampler, +// discard_alpha: true, +// }, +// &draw_parameters +// ).unwrap(); +// } - if mesh.trans_index_buffer.len() > 0 { - trans_queue.0.push(position); - } - } - } +// if mesh.trans_index_buffer.len() > 0 { +// trans_queue.0.push(position); +// } +// } +// } - // const HALF_CHUNK_SIZE: IVec3 = IVec3::splat((CHUNK_SIZE >> 1) as i32); - // trans_queue.0.sort_by_cached_key(|&pos| -( - // (pos + HALF_CHUNK_SIZE).distance_squared(camera_position.as_ivec3()) - // )); -} +// // const HALF_CHUNK_SIZE: IVec3 = IVec3::splat((CHUNK_SIZE >> 1) as i32); +// // trans_queue.0.sort_by_cached_key(|&pos| -( +// // (pos + HALF_CHUNK_SIZE).distance_squared(camera_position.as_ivec3()) +// // )); +// } -pub fn draw_world_trans( - mut target: NonSendSync>, - chunks: UniqueView, - meshes: NonSendSync>, - program: NonSendSync>, - texture: NonSendSync>, - camera: View, - settings: UniqueView, - mut trans_queue: UniqueViewMut, -) { - let camera = camera.iter().next().expect("No cameras in the scene"); - let view = camera.view_matrix.to_cols_array_2d(); - let perspective = camera.perspective_matrix.to_cols_array_2d(); +// pub fn draw_world_trans( +// mut target: NonSendSync>, +// chunks: UniqueView, +// meshes: NonSendSync>, +// program: NonSendSync>, +// texture: NonSendSync>, +// camera: View, +// settings: UniqueView, +// mut trans_queue: UniqueViewMut, +// ) { +// let camera = camera.iter().next().expect("No cameras in the scene"); +// let view = camera.view_matrix.to_cols_array_2d(); +// let perspective = camera.perspective_matrix.to_cols_array_2d(); - let mut draw_parameters = draw_params(&settings); - draw_parameters.blend = Blend::alpha_blending(); - draw_parameters.backface_culling = BackfaceCullingMode::CullingDisabled; - draw_parameters.smooth = Some(Smooth::Fastest); +// let mut draw_parameters = draw_params(&settings); +// draw_parameters.blend = Blend::alpha_blending(); +// draw_parameters.backface_culling = BackfaceCullingMode::CullingDisabled; +// draw_parameters.smooth = Some(Smooth::Fastest); - let texture_sampler = texture_sampler(&texture.0, &settings); +// let texture_sampler = texture_sampler(&texture.0, &settings); - for position in trans_queue.0.drain(..).rev() { - let world_position = position.as_vec3() * CHUNK_SIZE as f32; - let mesh_idx = chunks.chunks[&position].mesh_index.expect("No mesh index"); - let mesh = meshes.get(mesh_idx).expect("Mesh index pointing to nothing"); - target.0.draw( - &mesh.trans_vertex_buffer, - &mesh.trans_index_buffer, - &program.0, - &uniform! { - position_offset: world_position.to_array(), - view: view, - perspective: perspective, - tex: texture_sampler, - discard_alpha: false, - }, - &draw_parameters - ).unwrap(); - } -} +// for position in trans_queue.0.drain(..).rev() { +// let world_position = position.as_vec3() * CHUNK_SIZE as f32; +// let mesh_idx = chunks.chunks[&position].mesh_index.expect("No mesh index"); +// let mesh = meshes.get(mesh_idx).expect("Mesh index pointing to nothing"); +// target.0.draw( +// &mesh.trans_vertex_buffer, +// &mesh.trans_index_buffer, +// &program.0, +// &uniform! { +// position_offset: world_position.to_array(), +// view: view, +// perspective: perspective, +// tex: texture_sampler, +// discard_alpha: false, +// }, +// &draw_parameters +// ).unwrap(); +// } +// } -pub fn draw_current_chunk_border( - mut target: NonSendSync>, - player: View, - transforms: View, - buffers: NonSendSync>, - program: NonSendSync>, - camera: View, - settings: UniqueView, -) { - if cfg!(target_os = "android") { - return - } - if !settings.debug_draw_current_chunk_border { - return - } - let camera = camera.iter().next().expect("No cameras in the scene"); - let view = camera.view_matrix.to_cols_array_2d(); - let perspective = camera.perspective_matrix.to_cols_array_2d(); - let (_, &player_transform) = (&player, &transforms).iter().next().expect("No player"); - let (_, _, player_position) = player_transform.0.to_scale_rotation_translation(); - let player_in_chunk = ivec3( - (player_position.x as i32).div_euclid(CHUNK_SIZE as i32), - (player_position.y as i32).div_euclid(CHUNK_SIZE as i32), - (player_position.z as i32).div_euclid(CHUNK_SIZE as i32), - ); - let world_position = player_in_chunk.as_vec3() * CHUNK_SIZE as f32; - target.0.draw( - &buffers.0, - &buffers.1, - &program.0, - &uniform! { - model: Mat4::from_scale_rotation_translation( - Vec3::splat(CHUNK_SIZE as f32), - Quat::default(), - world_position - ).to_cols_array_2d(), - color: [0.25f32; 4], - view: view, - perspective: perspective, - }, - &DrawParameters { - depth: Depth { - test: DepthTest::IfLess, - ..Default::default() - }, - blend: Blend::alpha_blending(), - ..Default::default() - } - ).unwrap(); - target.0.draw( - &buffers.0, - &buffers.1, - &program.0, - &uniform! { - model: Mat4::from_scale_rotation_translation( - Vec3::splat(CHUNK_SIZE as f32), - Quat::default(), - world_position - ).to_cols_array_2d(), - color: [0.0f32; 4], - view: view, - perspective: perspective, - }, - &DrawParameters { - polygon_mode: PolygonMode::Point, - line_width: Some(2.), - point_size: Some(5.), - ..Default::default() - } - ).unwrap(); -} +// pub fn draw_current_chunk_border( +// mut target: NonSendSync>, +// player: View, +// transforms: View, +// buffers: NonSendSync>, +// program: NonSendSync>, +// camera: View, +// settings: UniqueView, +// ) { +// if cfg!(target_os = "android") { +// return +// } +// if !settings.debug_draw_current_chunk_border { +// return +// } +// let camera = camera.iter().next().expect("No cameras in the scene"); +// let view = camera.view_matrix.to_cols_array_2d(); +// let perspective = camera.perspective_matrix.to_cols_array_2d(); +// let (_, &player_transform) = (&player, &transforms).iter().next().expect("No player"); +// let (_, _, player_position) = player_transform.0.to_scale_rotation_translation(); +// let player_in_chunk = ivec3( +// (player_position.x as i32).div_euclid(CHUNK_SIZE as i32), +// (player_position.y as i32).div_euclid(CHUNK_SIZE as i32), +// (player_position.z as i32).div_euclid(CHUNK_SIZE as i32), +// ); +// let world_position = player_in_chunk.as_vec3() * CHUNK_SIZE as f32; +// target.0.draw( +// &buffers.0, +// &buffers.1, +// &program.0, +// &uniform! { +// model: Mat4::from_scale_rotation_translation( +// Vec3::splat(CHUNK_SIZE as f32), +// Quat::default(), +// world_position +// ).to_cols_array_2d(), +// color: [0.25f32; 4], +// view: view, +// perspective: perspective, +// }, +// &DrawParameters { +// depth: Depth { +// test: DepthTest::IfLess, +// ..Default::default() +// }, +// blend: Blend::alpha_blending(), +// ..Default::default() +// } +// ).unwrap(); +// target.0.draw( +// &buffers.0, +// &buffers.1, +// &program.0, +// &uniform! { +// model: Mat4::from_scale_rotation_translation( +// Vec3::splat(CHUNK_SIZE as f32), +// Quat::default(), +// world_position +// ).to_cols_array_2d(), +// color: [0.0f32; 4], +// view: view, +// perspective: perspective, +// }, +// &DrawParameters { +// polygon_mode: PolygonMode::Point, +// line_width: Some(2.), +// point_size: Some(5.), +// ..Default::default() +// } +// ).unwrap(); +// } diff --git a/kubi/src/ui/loading_screen.rs b/kubi/src/ui/loading_screen.rs index 805c641..be71392 100644 --- a/kubi/src/ui/loading_screen.rs +++ b/kubi/src/ui/loading_screen.rs @@ -7,7 +7,7 @@ use hui::{ UiElementExt, }, layout::{Alignment, Direction}, - frame_rect, size, + rect_frame, size, }; use shipyard::{UniqueView, UniqueViewMut, Workload, NonSendSync, IntoWorkload}; use winit::keyboard::KeyCode; @@ -28,7 +28,7 @@ pub fn loading_screen_base(bg_alpha: f32, xui: impl FnOnce(&mut ElementList)) -> .with_children(|ui| { Container::default() .with_size(size!(400, auto)) - .with_background(frame_rect! { + .with_background(rect_frame! { color: (0.2, 0.2, 0.2), corner_radius: 8. }) @@ -63,11 +63,11 @@ fn render_loading_ui( ProgressBar::default() .with_value(value) .with_size(size!(100%, 15)) - .with_background(frame_rect! { + .with_background(rect_frame! { color: (0.1, 0.1, 0.1), corner_radius: 2. }) - .with_foreground(frame_rect! { + .with_foreground(rect_frame! { color: (0.4, 0.4, 1.0), corner_radius: 2. }) diff --git a/kubi/src/ui/settings_ui.rs b/kubi/src/ui/settings_ui.rs index 640e393..b863da8 100644 --- a/kubi/src/ui/settings_ui.rs +++ b/kubi/src/ui/settings_ui.rs @@ -2,7 +2,7 @@ use hui::{ element::{br::Break, container::Container, slider::Slider, text::Text, UiElementExt}, layout::{Alignment, Direction}, signal::Signal, - frame_rect, size, + rect_frame, size, }; use shipyard::{NonSendSync, UniqueView, UniqueViewMut}; use winit::keyboard::KeyCode; @@ -34,7 +34,7 @@ pub fn render_settings_ui( .with_align(Alignment::Center) .with_children(|ui| { Container::default() - .with_background(frame_rect! { + .with_background(rect_frame! { color: (0.2, 0.2, 0.2), corner_radius: 8. }) diff --git a/kubi/src/world/chunk.rs b/kubi/src/world/chunk.rs index e8ddd3a..27c52a9 100644 --- a/kubi/src/world/chunk.rs +++ b/kubi/src/world/chunk.rs @@ -1,9 +1,8 @@ use std::sync::Arc; use glam::IVec3; use atomic::Atomic; -use glium::{VertexBuffer, IndexBuffer}; use kubi_shared::worldgen::AbortState; -use crate::rendering::world::ChunkVertex; +use crate::rendering::{world::ChunkVertex, BufferPair}; pub use kubi_shared::chunk::{CHUNK_SIZE, BlockData}; @@ -18,10 +17,8 @@ impl ChunkData { } pub struct ChunkMesh { - pub vertex_buffer: VertexBuffer, - pub index_buffer: IndexBuffer, - pub trans_vertex_buffer: VertexBuffer, - pub trans_index_buffer: IndexBuffer, + pub main: BufferPair, + pub trans: BufferPair, } #[derive(Clone, Copy, Debug, PartialEq, Eq, Default)] diff --git a/kubi/src/world/loading.rs b/kubi/src/world/loading.rs index aa0d774..c0b2f85 100644 --- a/kubi/src/world/loading.rs +++ b/kubi/src/world/loading.rs @@ -1,7 +1,6 @@ use std::sync::Arc; use atomic::{Atomic, Ordering}; use glam::{IVec3, ivec3}; -use glium::{VertexBuffer, IndexBuffer, index::PrimitiveType}; use kubi_shared::{networking::{channels::Channel, messages::ClientToServerMessage}, worldgen::AbortState}; use shipyard::{View, UniqueView, UniqueViewMut, IntoIter, Workload, IntoWorkload, NonSendSync, track}; use uflow::SendMode; @@ -327,21 +326,23 @@ fn process_completed_tasks( //apply the mesh //TODO: Skip if mesh is empty? (i.e. set to None) - let mesh = ChunkMesh { - vertex_buffer: VertexBuffer::immutable(&renderer.display, &vertices).unwrap(), - index_buffer: IndexBuffer::immutable(&renderer.display, PrimitiveType::TrianglesList, &indices).unwrap(), - trans_vertex_buffer: VertexBuffer::immutable(&renderer.display, &trans_vertices).unwrap(), - trans_index_buffer: IndexBuffer::immutable(&renderer.display, PrimitiveType::TrianglesList, &trans_indices).unwrap(), - }; - if let Some(index) = chunk.mesh_index { - meshes.update(index, mesh).expect("Mesh update failed"); - } else { - let mesh_index = meshes.insert(mesh); - chunk.mesh_index = Some(mesh_index); - } + unimplemented!(); - //update chunk state - chunk.current_state = CurrentChunkState::Rendered; + // let mesh = ChunkMesh { + // vertex_buffer: VertexBuffer::immutable(&renderer.display, &vertices).unwrap(), + // index_buffer: IndexBuffer::immutable(&renderer.display, PrimitiveType::TrianglesList, &indices).unwrap(), + // trans_vertex_buffer: VertexBuffer::immutable(&renderer.display, &trans_vertices).unwrap(), + // trans_index_buffer: IndexBuffer::immutable(&renderer.display, PrimitiveType::TrianglesList, &trans_indices).unwrap(), + // }; + // if let Some(index) = chunk.mesh_index { + // meshes.update(index, mesh).expect("Mesh update failed"); + // } else { + // let mesh_index = meshes.insert(mesh); + // chunk.mesh_index = Some(mesh_index); + // } + + // //update chunk state + // chunk.current_state = CurrentChunkState::Rendered; //increase ops counter ops += 1; From 8373d2be54067d33bd16151741856ff9fbcce437 Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Sat, 4 May 2024 23:17:12 +0200 Subject: [PATCH 05/51] create buffers --- Cargo.lock | 146 +++++++++++++----------------------- Cargo.toml | 3 - kubi-server/Cargo.toml | 2 +- kubi/Cargo.toml | 7 +- kubi/src/lib.rs | 4 +- kubi/src/rendering.rs | 5 +- kubi/src/rendering/world.rs | 18 ++++- kubi/src/world/loading.rs | 74 +++++++++++++----- 8 files changed, 134 insertions(+), 125 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 91cadc2..2194bb8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -52,27 +52,6 @@ version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" -[[package]] -name = "android-activity" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee91c0c2905bae44f84bfa4e044536541df26b7703fd0888deeb9060fcc44289" -dependencies = [ - "android-properties", - "bitflags 2.5.0", - "cc", - "cesu8", - "jni", - "jni-sys", - "libc", - "log", - "ndk 0.8.0", - "ndk-context", - "ndk-sys 0.5.0+25.2.9519653", - "num_enum", - "thiserror", -] - [[package]] name = "android-activity" version = "0.6.0" @@ -87,7 +66,7 @@ dependencies = [ "jni-sys", "libc", "log", - "ndk 0.9.0", + "ndk", "ndk-context", "ndk-sys 0.6.0+11769913", "num_enum", @@ -192,15 +171,15 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "base64" -version = "0.22.0" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bincode" @@ -270,9 +249,9 @@ dependencies = [ [[package]] name = "bytemuck_derive" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "965ab7eb5f8f97d2a083c799f3a1b994fc397b2fe2da5d1da1626ce15a39f2b1" +checksum = "4da9a32f3fed317401fa3c862968128267c3106685286e15d5aaa3d7389c2f60" dependencies = [ "proc-macro2", "quote", @@ -319,9 +298,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.95" +version = "1.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d32a725bc159af97c3e629873bb9f88fb8cf8a4867175f76dc987815ea07c83b" +checksum = "065a29261d53ba54260972629f9ca6bffa69bac13cd1fed61420f7fa68b9f8bd" dependencies = [ "jobserver", "libc", @@ -424,9 +403,9 @@ dependencies = [ [[package]] name = "concurrent-queue" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" dependencies = [ "crossbeam-utils", ] @@ -701,9 +680,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.28" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" dependencies = [ "crc32fast", "miniz_oxide", @@ -733,7 +712,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9099a2f86b8e674b75d03ff154b3fe4c5208ed249ced8d69cc313a9fa40bb488" dependencies = [ - "hashbrown 0.14.3", + "hashbrown 0.14.5", "ttf-parser", ] @@ -801,9 +780,9 @@ dependencies = [ [[package]] name = "gilrs" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "499067aa54af19f88732dc418f61f23d5912de1518665bb0eca034ca0d07574c" +checksum = "b54e5e39844ab5cddaf3bbbdfdc2923a6cb34e36818b95618da4e3f26302c24c" dependencies = [ "fnv", "gilrs-core", @@ -915,7 +894,7 @@ checksum = "9c08c1f623a8d0b722b8b99f821eb0ba672a1618f0d3b16ddbee1cedd2dd8557" dependencies = [ "bitflags 2.5.0", "gpu-descriptor-types", - "hashbrown 0.14.3", + "hashbrown 0.14.5", ] [[package]] @@ -944,9 +923,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash", "allocator-api2", @@ -1016,7 +995,7 @@ dependencies = [ "document-features", "fontdue", "glam", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "hui-derive", "image", "log", @@ -1111,7 +1090,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "serde", ] @@ -1223,13 +1202,14 @@ checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" name = "kubi" version = "0.0.0" dependencies = [ - "android-activity 0.5.2", + "android-activity", "anyhow", "atomic", + "bytemuck", "flume", "gilrs", "glam", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "hui", "hui-winit", "image", @@ -1237,7 +1217,7 @@ dependencies = [ "kubi-shared", "log", "lz4_flex", - "ndk 0.8.0", + "ndk", "nohash-hasher", "pollster", "postcard", @@ -1271,7 +1251,7 @@ dependencies = [ "anyhow", "flume", "glam", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "kubi-logging", "kubi-shared", "log", @@ -1296,7 +1276,7 @@ dependencies = [ "bytemuck", "fastnoise-lite", "glam", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "nohash-hasher", "num_enum", "nz", @@ -1318,9 +1298,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.153" +version = "0.2.154" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" [[package]] name = "libloading" @@ -1383,9 +1363,9 @@ checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -1491,21 +1471,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "ndk" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7" -dependencies = [ - "bitflags 2.5.0", - "jni-sys", - "log", - "ndk-sys 0.5.0+25.2.9519653", - "num_enum", - "raw-window-handle", - "thiserror", -] - [[package]] name = "ndk" version = "0.9.0" @@ -1571,9 +1536,9 @@ checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] @@ -1601,9 +1566,9 @@ dependencies = [ [[package]] name = "nz" -version = "0.3.3" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb749eec2b3be2f169dd4facfec40a28cc40f2b02ad3c4d2c51ce578c3f635b0" +checksum = "d1e9655df3f51323812726b25a00d787562c5fa64177d286603429787b4386a9" [[package]] name = "objc" @@ -2101,18 +2066,18 @@ checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" [[package]] name = "serde" -version = "1.0.198" +version = "1.0.200" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc" +checksum = "ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.198" +version = "1.0.200" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9" +checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb" dependencies = [ "proc-macro2", "quote", @@ -2141,9 +2106,9 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.8.0" +version = "3.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c85f8e96d1d6857f13768fcbd895fcb06225510022a2774ed8b5150581847b0" +checksum = "0ad483d2ab0149d5a5ebcd9972a3852711e0153d863bf5a5d0391d28883c4a20" dependencies = [ "base64", "chrono", @@ -2159,9 +2124,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.8.0" +version = "3.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8b3a576c4eb2924262d5951a3b737ccaf16c931e39a2810c36f9a7e25575557" +checksum = "65569b702f41443e8bc8bbb1c5779bd0450bbe723b56198980e80ec45780bce2" dependencies = [ "darling", "proc-macro2", @@ -2174,7 +2139,7 @@ name = "shipyard" version = "0.6.0" source = "git+https://github.com/leudz/shipyard?rev=aacf3b1df5#aacf3b1df540c7d9d384830d7431ba618eee75c9" dependencies = [ - "hashbrown 0.14.3", + "hashbrown 0.14.5", "lock_api", "rayon", "serde", @@ -2484,7 +2449,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.6", + "winnow 0.6.7", ] [[package]] @@ -3139,7 +3104,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea9e6d5d66cbf702e0dd820302144f51b69a95acdc495dd98ca280ff206562b1" dependencies = [ "ahash", - "android-activity 0.6.0", + "android-activity", "atomic-waker", "bitflags 2.5.0", "bytemuck", @@ -3153,7 +3118,7 @@ dependencies = [ "js-sys", "libc", "memmap2", - "ndk 0.9.0", + "ndk", "objc2", "objc2-app-kit", "objc2-foundation", @@ -3193,9 +3158,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.6.6" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0c976aaaa0e1f90dbb21e9587cdaf1d9679a1cde8875c0d6bd83ab96a208352" +checksum = "14b9415ee827af173ebb3f15f9083df5a122eb93572ec28741fb153356ea2578" dependencies = [ "memchr", ] @@ -3213,9 +3178,9 @@ dependencies = [ [[package]] name = "x11rb" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8f25ead8c7e4cba123243a6367da5d3990e0d3affa708ea19dce96356bd9f1a" +checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12" dependencies = [ "as-raw-xcb-connection", "gethostname", @@ -3228,9 +3193,9 @@ dependencies = [ [[package]] name = "x11rb-protocol" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e63e71c4b8bd9ffec2c963173a4dc4cbde9ee96961d4fcb4429db9929b606c34" +checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d" [[package]] name = "xcursor" @@ -3282,8 +3247,3 @@ dependencies = [ "quote", "syn 2.0.60", ] - -[[patch.unused]] -name = "glium" -version = "0.34.0" -source = "git+https://github.com/glium/glium?rev=a352c667#a352c667c145e2dda1f5fe1fc2482cbe99de23be" diff --git a/Cargo.toml b/Cargo.toml index 1a981bf..ae8076d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,6 +40,3 @@ opt-level = 3 #enabling debug assertions here causes the game to abort [profile.dev.package.android-activity] debug-assertions = false - -[patch.crates-io] -glium = { git = "https://github.com/glium/glium", rev = "a352c667" } diff --git a/kubi-server/Cargo.toml b/kubi-server/Cargo.toml index 075eced..51a4f43 100644 --- a/kubi-server/Cargo.toml +++ b/kubi-server/Cargo.toml @@ -15,7 +15,7 @@ glam = { version = "0.27", features = ["debug-glam-assert", "fast-math"] } hashbrown = "0.14" nohash-hasher = "0.2" anyhow = "1.0" -rayon = "1.7" +rayon = "1.10" flume = "0.11" rand = "0.8" uflow = "0.7" diff --git a/kubi/Cargo.toml b/kubi/Cargo.toml index 27e7864..6542e1d 100644 --- a/kubi/Cargo.toml +++ b/kubi/Cargo.toml @@ -16,6 +16,7 @@ hui-winit = { git = "https://github.com/griffi-gh/hui", rev = "3a50d2d0dde", fea log = "0.4" wgpu = { version = "0.20", features = ["webgl"] } pollster = "0.3" +bytemuck = { version = "1.15", features = ["derive"] } winit = { version = "0.30", features = ["android-native-activity"] } raw-window-handle = "0.6" glam = { version = "0.27", features = ["debug-glam-assert", "fast-math"] } @@ -23,7 +24,7 @@ image = { version = "0.25", default_features = false, features = ["png"] } strum = { version = "0.26", features = ["derive"] } hashbrown = "0.14" nohash-hasher = "0.2" -rayon = "1.7" +rayon = "1.10" shipyard = { git = "https://github.com/leudz/shipyard", rev = "aacf3b1df5", default-features = false, features = ["std", "proc", "thread_local"] } anyhow = "1.0" flume = "0.11" @@ -39,8 +40,8 @@ atomic = "0.6" [target.'cfg(target_os = "android")'.dependencies] -android-activity = "^0.5.2" -ndk = "0.8" +android-activity = "0.6" +ndk = "0.9" [target.'cfg(target_os = "windows")'.dependencies] winapi = { version = "0.3", features = ["wincon"] } diff --git a/kubi/src/lib.rs b/kubi/src/lib.rs index 90b3559..b40872d 100644 --- a/kubi/src/lib.rs +++ b/kubi/src/lib.rs @@ -79,7 +79,7 @@ use player_controller::{debug_switch_ctl_type, update_player_controllers}; // clear_background, entities::render_entities, init_window_size, primitives::init_primitives, resize_renderer, selection_box::render_selection_box, sumberge::render_submerged_view, update_window_size, world::{draw_current_chunk_border, draw_world, draw_world_trans, init_trans_chunk_queue}, BackgroundColor, RenderTarget, Renderer // }; use rendering::{ - init_window_size, resize_renderer, update_window_size, + render_master, init_window_size, resize_renderer, update_window_size, BackgroundColor, Renderer }; use block_placement::update_block_placement; @@ -320,6 +320,8 @@ pub fn kubi_main( //Run update workflows world.run_workload(update).unwrap(); + world.run(render_master); + //Start rendering (maybe use custom views for this?) // let target = { // let renderer = world.borrow::>>().unwrap(); diff --git a/kubi/src/rendering.rs b/kubi/src/rendering.rs index 409fbf0..fdafbed 100644 --- a/kubi/src/rendering.rs +++ b/kubi/src/rendering.rs @@ -100,7 +100,7 @@ impl Renderer { let size = window.inner_size(); let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { - backends: wgpu::Backends::all(), + backends: wgpu::Backends::BROWSER_WEBGPU | wgpu::Backends::VULKAN | wgpu::Backends::GL, ..Default::default() }); @@ -216,7 +216,8 @@ pub fn render_master(storages: AllStoragesViewMut) { // render_pass.draw_indexed(0..renderer.num_indices, 0, 0..1); } - renderer.queue().submit(Some(encoder.finish())); + renderer.queue().submit(std::iter::once(encoder.finish())); + surface_texture.present(); } // pub fn clear_background( diff --git a/kubi/src/rendering/world.rs b/kubi/src/rendering/world.rs index 9f3dffc..9c66c34 100644 --- a/kubi/src/rendering/world.rs +++ b/kubi/src/rendering/world.rs @@ -23,9 +23,10 @@ // }, settings::GameSettings, // }; // use super::{RenderTarget, primitives::cube::CubePrimitive}; +use bytemuck::{Pod, Zeroable}; -#[derive(Clone, Copy)] -#[repr(C)] +#[derive(Clone, Copy, Pod, Zeroable)] +#[repr(C, packed)] pub struct ChunkVertex { pub position: [f32; 3], pub normal: [f32; 3], @@ -33,6 +34,19 @@ pub struct ChunkVertex { pub tex_index: u8, } +impl ChunkVertex { + pub const LAYOUT: wgpu::VertexBufferLayout<'static> = wgpu::VertexBufferLayout { + array_stride: std::mem::size_of::() as wgpu::BufferAddress, + step_mode: wgpu::VertexStepMode::Vertex, + attributes: &wgpu::vertex_attr_array![ + 0 => Float32x3, + 1 => Float32x3, + 2 => Float32x2, + 3 => Uint32, + ], + }; +} + // #[derive(Unique)] // pub struct TransChunkQueue(pub Vec); diff --git a/kubi/src/world/loading.rs b/kubi/src/world/loading.rs index c0b2f85..3defe94 100644 --- a/kubi/src/world/loading.rs +++ b/kubi/src/world/loading.rs @@ -4,13 +4,14 @@ use glam::{IVec3, ivec3}; use kubi_shared::{networking::{channels::Channel, messages::ClientToServerMessage}, worldgen::AbortState}; use shipyard::{View, UniqueView, UniqueViewMut, IntoIter, Workload, IntoWorkload, NonSendSync, track}; use uflow::SendMode; +use wgpu::util::DeviceExt; use crate::{ - player::MainPlayer, - transform::Transform, - settings::GameSettings, - rendering::Renderer, - state::GameState, networking::UdpClient, + player::MainPlayer, + rendering::{world::ChunkVertex, BufferPair, Renderer}, + settings::GameSettings, + state::GameState, + transform::Transform, }; use super::{ ChunkStorage, ChunkMeshStorage, @@ -326,23 +327,56 @@ fn process_completed_tasks( //apply the mesh //TODO: Skip if mesh is empty? (i.e. set to None) - unimplemented!(); + //TODO - // let mesh = ChunkMesh { - // vertex_buffer: VertexBuffer::immutable(&renderer.display, &vertices).unwrap(), - // index_buffer: IndexBuffer::immutable(&renderer.display, PrimitiveType::TrianglesList, &indices).unwrap(), - // trans_vertex_buffer: VertexBuffer::immutable(&renderer.display, &trans_vertices).unwrap(), - // trans_index_buffer: IndexBuffer::immutable(&renderer.display, PrimitiveType::TrianglesList, &trans_indices).unwrap(), - // }; - // if let Some(index) = chunk.mesh_index { - // meshes.update(index, mesh).expect("Mesh update failed"); - // } else { - // let mesh_index = meshes.insert(mesh); - // chunk.mesh_index = Some(mesh_index); - // } + let vtx_buffer = renderer.device().create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("chunk_vertex_buffer"), + contents: bytemuck::cast_slice(&vertices), + usage: wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::VERTEX, + }); - // //update chunk state - // chunk.current_state = CurrentChunkState::Rendered; + let idx_buffer = renderer.device().create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("chunk_vertex_buffer"), + contents: bytemuck::cast_slice(&indices), + usage: wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::INDEX, + }); + + let vtx_buffer_trans = renderer.device().create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("chunk_trans_vertex_buffer"), + contents: todo!(), + usage: wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::VERTEX, + }); + + let idx_buffer_trans = renderer.device().create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("chunk_trans_index_buffer"), + contents: todo!(), + usage: wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::INDEX, + }); + + let main_buffer_pair = BufferPair { + vertex: vtx_buffer, + index: idx_buffer, + }; + + let trans_buffer_pair = BufferPair { + vertex: vtx_buffer_trans, + index: idx_buffer_trans, + }; + + let mesh = ChunkMesh { + main: main_buffer_pair, + trans: trans_buffer_pair, + }; + + if let Some(index) = chunk.mesh_index { + meshes.update(index, mesh).expect("Mesh update failed"); + } else { + let mesh_index = meshes.insert(mesh); + chunk.mesh_index = Some(mesh_index); + } + + //update chunk state + chunk.current_state = CurrentChunkState::Rendered; //increase ops counter ops += 1; From 1d4cbcc2b15929c92983793ef273a0e7b014575c Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Sat, 4 May 2024 23:18:27 +0200 Subject: [PATCH 06/51] oops forgor to cast trans buffers --- kubi/src/world/loading.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kubi/src/world/loading.rs b/kubi/src/world/loading.rs index 3defe94..48be8d1 100644 --- a/kubi/src/world/loading.rs +++ b/kubi/src/world/loading.rs @@ -343,13 +343,13 @@ fn process_completed_tasks( let vtx_buffer_trans = renderer.device().create_buffer_init(&wgpu::util::BufferInitDescriptor { label: Some("chunk_trans_vertex_buffer"), - contents: todo!(), + contents: bytemuck::cast_slice(&trans_vertices), usage: wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::VERTEX, }); let idx_buffer_trans = renderer.device().create_buffer_init(&wgpu::util::BufferInitDescriptor { label: Some("chunk_trans_index_buffer"), - contents: todo!(), + contents: bytemuck::cast_slice(&trans_indices), usage: wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::INDEX, }); From c32568af1c4824b4681168c75136bd5a287af350 Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Sun, 5 May 2024 00:16:55 +0200 Subject: [PATCH 07/51] :3 --- kubi/src/lib.rs | 7 ++--- kubi/src/rendering.rs | 8 ++++-- kubi/src/rendering/world.rs | 53 ++++++++++++++++--------------------- kubi/src/world.rs | 1 + 4 files changed, 34 insertions(+), 35 deletions(-) diff --git a/kubi/src/lib.rs b/kubi/src/lib.rs index b40872d..e708b19 100644 --- a/kubi/src/lib.rs +++ b/kubi/src/lib.rs @@ -79,8 +79,9 @@ use player_controller::{debug_switch_ctl_type, update_player_controllers}; // clear_background, entities::render_entities, init_window_size, primitives::init_primitives, resize_renderer, selection_box::render_selection_box, sumberge::render_submerged_view, update_window_size, world::{draw_current_chunk_border, draw_world, draw_world_trans, init_trans_chunk_queue}, BackgroundColor, RenderTarget, Renderer // }; use rendering::{ - render_master, init_window_size, resize_renderer, update_window_size, - BackgroundColor, Renderer + init_window_size, render_master, resize_renderer, update_window_size, + world::{init_trans_chunk_queue, TransChunkQueue}, + BackgroundColor, Renderer, }; use block_placement::update_block_placement; use delta_time::{DeltaTime, init_delta_time}; @@ -126,7 +127,6 @@ fn startup() -> Workload { init_client_physics, init_chat_manager, init_crosshair_image, - //init_trans_chunk_queue, ).into_sequential_workload() } @@ -139,6 +139,7 @@ fn update() -> Workload { process_inputs, kubi_ui_begin, ( + init_trans_chunk_queue.run_if_missing_unique::(), init_game_world.run_if_missing_unique::(), ( spawn_player.run_if_storage_empty::(), diff --git a/kubi/src/rendering.rs b/kubi/src/rendering.rs index fdafbed..16c3f1a 100644 --- a/kubi/src/rendering.rs +++ b/kubi/src/rendering.rs @@ -8,7 +8,7 @@ use winit::{ dpi::PhysicalSize }; use glam::{Vec3, UVec2}; -use crate::{events::WindowResizedEvent, settings::{GameSettings, FullscreenMode}}; +use crate::{events::WindowResizedEvent, settings::{FullscreenMode, GameSettings}, state::is_ingame}; pub mod primitives; pub mod world; @@ -188,7 +188,7 @@ pub fn render_master(storages: AllStoragesViewMut) { let surface_texture = renderer.surface().get_current_texture().unwrap(); let surface_view = surface_texture.texture.create_view(&wgpu::TextureViewDescriptor::default()); - { + if storages.run(is_ingame) { let bg_color = storages.borrow::>().unwrap(); let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { label: Some("main0_pass"), @@ -209,6 +209,10 @@ pub fn render_master(storages: AllStoragesViewMut) { ..Default::default() }); + let data = (&mut render_pass, &*renderer); + + storages.run_with_data(world::draw_world, data); + // render_pass.set_pipeline(&renderer.pipeline); // render_pass.set_bind_group(0, &renderer.bind_group, &[]); // render_pass.set_vertex_buffer(0, renderer.vertex_buffer.slice(..)); diff --git a/kubi/src/rendering/world.rs b/kubi/src/rendering/world.rs index 9c66c34..c83dde9 100644 --- a/kubi/src/rendering/world.rs +++ b/kubi/src/rendering/world.rs @@ -1,29 +1,9 @@ -// use glam::{ivec3, IVec3, Mat4, Quat, Vec3}; -// use shipyard::{track, AllStoragesView, IntoIter, NonSendSync, Unique, UniqueView, UniqueViewMut, View}; -// use glium::{ -// draw_parameters::{ -// BackfaceCullingMode, Depth, DepthTest, PolygonMode -// }, implement_vertex, uniform, uniforms::{ -// MagnifySamplerFilter, MinifySamplerFilter, Sampler, SamplerBehavior, SamplerWrapFunction -// }, Blend, DrawParameters, Smooth, Surface -// }; -// use crate::{ -// camera::Camera, -// player::MainPlayer, -// transform::Transform, -// prefabs::{ -// ChunkShaderPrefab, -// BlockTexturesPrefab, -// ColoredShaderPrefab, -// }, -// world::{ -// ChunkStorage, -// ChunkMeshStorage, -// chunk::CHUNK_SIZE, -// }, settings::GameSettings, -// }; -// use super::{RenderTarget, primitives::cube::CubePrimitive}; use bytemuck::{Pod, Zeroable}; +use glam::IVec3; +use shipyard::{AllStoragesView, NonSendSync, Unique, UniqueView, UniqueViewMut, View}; +use kubi_shared::transform::Transform; +use crate::{camera::Camera, settings::GameSettings, world::{ChunkMeshStorage, ChunkStorage}}; +use super::Renderer; #[derive(Clone, Copy, Pod, Zeroable)] #[repr(C, packed)] @@ -47,12 +27,25 @@ impl ChunkVertex { }; } -// #[derive(Unique)] -// pub struct TransChunkQueue(pub Vec); +#[derive(Unique)] +pub struct TransChunkQueue(pub Vec); + +pub fn init_trans_chunk_queue(storages: AllStoragesView) { + storages.add_unique(TransChunkQueue(Vec::with_capacity(512))); +} + +pub fn draw_world( + (render_pass, renderer): (&mut wgpu::RenderPass, &Renderer), + chunks: UniqueView, + meshes: NonSendSync>, + transform: View, + camera: View, + settings: UniqueView, + mut trans_queue: UniqueViewMut, +) { + //TODO +} -// pub fn init_trans_chunk_queue(storages: AllStoragesView) { -// storages.add_unique(TransChunkQueue(Vec::with_capacity(512))); -// } // fn draw_params(settings: &GameSettings) -> DrawParameters { // DrawParameters { diff --git a/kubi/src/world.rs b/kubi/src/world.rs index 50664d2..1626d17 100644 --- a/kubi/src/world.rs +++ b/kubi/src/world.rs @@ -102,6 +102,7 @@ impl ChunkMeshStorage { pub fn init_game_world( storages: AllStoragesView, ) { + log::info!("init_game_world called"); storages.add_unique_non_send_sync(ChunkMeshStorage::new()); storages.add_unique(ChunkStorage::new()); storages.add_unique(ChunkTaskManager::new()); From 906f4882a24423b5743bbaf1b25c8ca9cb9e836a Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Sun, 5 May 2024 00:17:27 +0200 Subject: [PATCH 08/51] throw away glsl shaders --- kubi/shaders/colored.frag | 12 ------------ kubi/shaders/colored.vert | 13 ------------- kubi/shaders/colored2.frag | 10 ---------- kubi/shaders/colored2.vert | 9 --------- kubi/shaders/world.frag | 26 -------------------------- kubi/shaders/world.vert | 27 --------------------------- 6 files changed, 97 deletions(-) delete mode 100644 kubi/shaders/colored.frag delete mode 100644 kubi/shaders/colored.vert delete mode 100644 kubi/shaders/colored2.frag delete mode 100644 kubi/shaders/colored2.vert delete mode 100644 kubi/shaders/world.frag delete mode 100644 kubi/shaders/world.vert diff --git a/kubi/shaders/colored.frag b/kubi/shaders/colored.frag deleted file mode 100644 index 7ab85c6..0000000 --- a/kubi/shaders/colored.frag +++ /dev/null @@ -1,12 +0,0 @@ -#version 300 es - -precision highp float; - -out vec4 out_color; -uniform vec4 color; - -void main() { - // discard fully transparent pixels - if (color.w <= 0.) discard; - out_color = color; -} diff --git a/kubi/shaders/colored.vert b/kubi/shaders/colored.vert deleted file mode 100644 index c6b3ef8..0000000 --- a/kubi/shaders/colored.vert +++ /dev/null @@ -1,13 +0,0 @@ -#version 300 es - -precision highp float; - -in vec3 position; -uniform mat4 model; -uniform mat4 perspective; -uniform mat4 view; - -void main() { - mat4 modelview = view * model; - gl_Position = perspective * modelview * vec4(position, 1.); -} diff --git a/kubi/shaders/colored2.frag b/kubi/shaders/colored2.frag deleted file mode 100644 index cddd0d4..0000000 --- a/kubi/shaders/colored2.frag +++ /dev/null @@ -1,10 +0,0 @@ -#version 300 es - -precision highp float; - -out vec4 out_color; -uniform vec4 color; - -void main() { - out_color = color; -} diff --git a/kubi/shaders/colored2.vert b/kubi/shaders/colored2.vert deleted file mode 100644 index db908de..0000000 --- a/kubi/shaders/colored2.vert +++ /dev/null @@ -1,9 +0,0 @@ -#version 300 es - -precision highp float; - -in vec2 position; - -void main() { - gl_Position = vec4(position, 0.0, 1.0); -} diff --git a/kubi/shaders/world.frag b/kubi/shaders/world.frag deleted file mode 100644 index 48d2df0..0000000 --- a/kubi/shaders/world.frag +++ /dev/null @@ -1,26 +0,0 @@ -#version 300 es - -precision highp float; -precision lowp sampler2DArray; - -in vec3 v_normal; -in vec2 v_uv; -flat in uint v_tex_index; -out vec4 color; -uniform sampler2DArray tex; -uniform bool discard_alpha; - -void main() { - // base color from texture - color = texture(tex, vec3(v_uv, v_tex_index)); - - // discard fully transparent pixels - if (discard_alpha ? (color.w < 0.5) : (color.w == 0.)) discard; - - //basic "lighting" - float light = abs(v_normal.x) + .8 * abs(v_normal.y) + .6 * abs(v_normal.z); - color *= vec4(vec3(light), 1.); - - //discard alpha - if (discard_alpha) color.w = 1.; -} diff --git a/kubi/shaders/world.vert b/kubi/shaders/world.vert deleted file mode 100644 index 996a1ec..0000000 --- a/kubi/shaders/world.vert +++ /dev/null @@ -1,27 +0,0 @@ -#version 300 es - -precision highp float; - -//TODO pack this data: -// uint position_normal_uv -// XXYYZZNU -// wehere Normal and Uv are enums -// maybe somehow pack in tex index too - -in vec3 position; -in vec3 normal; -in vec2 uv; -in uint tex_index; -out vec2 v_uv; -out vec3 v_normal; -flat out uint v_tex_index; -uniform vec3 position_offset; -uniform mat4 perspective; -uniform mat4 view; - -void main() { - v_normal = normal; - v_tex_index = tex_index; - v_uv = uv; - gl_Position = perspective * view * vec4(position + position_offset, 1.); -} From 324270ed7d4c11a51587c930d0fddc2c74abef7f Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Sun, 5 May 2024 01:06:43 +0200 Subject: [PATCH 09/51] write some dumb shader code --- kubi/shaders/world.wgsl | 42 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 kubi/shaders/world.wgsl diff --git a/kubi/shaders/world.wgsl b/kubi/shaders/world.wgsl new file mode 100644 index 0000000..6587883 --- /dev/null +++ b/kubi/shaders/world.wgsl @@ -0,0 +1,42 @@ +// struct Uniforms { +// transform: mat4x4; +// }; + +// @group(1) @binding(0) +// var uniforms: Uniforms; + +struct VertexInput { + @location(0) position: vec3, + @location(1) normal: vec3, + @location(2) uv: vec2, + @location(3) @interpolate(flat) tex_index: u32, +} + +struct VertexOutput { + @builtin(position) clip_position: vec4, + @location(0) uv: vec2, + @location(1) normal: vec3, + @location(2) color: vec4, + @location(3) @interpolate(flat) tex_index: u32, +}; + +@vertex +fn vs_main( + in: VertexInput, +) -> VertexOutput { + var out: VertexOutput; + out.uv = in.uv; + out.clip_position = vec4(in.position, 1.0); + return out; +} + +@group(0) @binding(0) +var t_diffuse: texture_2d_array; + +@group(0) @binding(1) +var s_diffuse: sampler; + +@fragment +fn fs_main(in: VertexOutput) -> @location(0) vec4 { + return textureSample(t_diffuse, s_diffuse, in.uv, in.tex_index); +} From 0b6937786582a7676ddabce590fc8789b7712264 Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Sun, 5 May 2024 01:25:44 +0200 Subject: [PATCH 10/51] copy over world render --- kubi/src/rendering/world.rs | 38 +++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/kubi/src/rendering/world.rs b/kubi/src/rendering/world.rs index c83dde9..5d0c57e 100644 --- a/kubi/src/rendering/world.rs +++ b/kubi/src/rendering/world.rs @@ -1,7 +1,7 @@ use bytemuck::{Pod, Zeroable}; -use glam::IVec3; -use shipyard::{AllStoragesView, NonSendSync, Unique, UniqueView, UniqueViewMut, View}; -use kubi_shared::transform::Transform; +use glam::{IVec3, Vec3}; +use shipyard::{AllStoragesView, IntoIter, NonSendSync, Unique, UniqueView, UniqueViewMut, View}; +use kubi_shared::{chunk::CHUNK_SIZE, transform::Transform}; use crate::{camera::Camera, settings::GameSettings, world::{ChunkMeshStorage, ChunkStorage}}; use super::Renderer; @@ -43,7 +43,37 @@ pub fn draw_world( settings: UniqueView, mut trans_queue: UniqueViewMut, ) { - //TODO + let camera = camera.iter().next().expect("No cameras in the scene"); + let camera_matrix = camera.view_matrix * camera.perspective_matrix; + + for (&position, chunk) in &chunks.chunks { + if let Some(key) = chunk.mesh_index { + let mesh = meshes.get(key).expect("Mesh index pointing to nothing"); + let world_position = position.as_vec3() * CHUNK_SIZE as f32; + + //Skip if mesh is empty + if mesh.main.index.size() == 0 && mesh.trans.index.size() == 0 { + continue + } + + //Frustum culling + let minp = world_position; + let maxp = world_position + Vec3::splat(CHUNK_SIZE as f32); + if !camera.frustum.is_box_visible(minp, maxp) { + continue + } + + //Draw chunk mesh + if mesh.main.index.size() > 0 { + //TODO + } + + //TODO trans chunks + // if mesh.trans_index_buffer.len() > 0 { + // trans_queue.0.push(position); + // } + } + } } From 7ac045f013b958029ed2b028b1d2b5e4edb08fef Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Sun, 5 May 2024 01:30:07 +0200 Subject: [PATCH 11/51] move renderer into it's own file --- kubi/src/rendering.rs | 165 ++------------------------------- kubi/src/rendering/renderer.rs | 157 +++++++++++++++++++++++++++++++ 2 files changed, 163 insertions(+), 159 deletions(-) create mode 100644 kubi/src/rendering/renderer.rs diff --git a/kubi/src/rendering.rs b/kubi/src/rendering.rs index 16c3f1a..e109e41 100644 --- a/kubi/src/rendering.rs +++ b/kubi/src/rendering.rs @@ -1,21 +1,16 @@ -use pollster::FutureExt; -use raw_window_handle::HasRawWindowHandle; -use shipyard::{AllStoragesView, AllStoragesViewMut, IntoIter, NonSendSync, Unique, UniqueView, UniqueViewMut, View}; -use wgpu::SurfaceTargetUnsafe; -use winit::{ - event_loop::ActiveEventLoop, - window::{WindowAttributes, Fullscreen, Window}, - dpi::PhysicalSize -}; +use shipyard::{AllStoragesView, AllStoragesViewMut, IntoIter, Unique, UniqueView, UniqueViewMut, View}; +use winit::dpi::PhysicalSize; use glam::{Vec3, UVec2}; -use crate::{events::WindowResizedEvent, settings::{FullscreenMode, GameSettings}, state::is_ingame}; +use crate::{events::WindowResizedEvent, state::is_ingame}; +pub mod renderer; pub mod primitives; pub mod world; pub mod selection_box; pub mod entities; pub mod sumberge; +pub use renderer::Renderer; pub struct BufferPair { pub index: wgpu::Buffer, pub vertex: wgpu::Buffer, @@ -31,158 +26,10 @@ pub struct BackgroundColor(pub Vec3); #[allow(deprecated)] pub struct WindowSize(pub UVec2); -#[derive(Unique)] -pub struct Renderer { - instance: wgpu::Instance, - surface: wgpu::Surface<'static>, - device: wgpu::Device, - queue: wgpu::Queue, - surface_config: wgpu::SurfaceConfiguration, - size: PhysicalSize, - // pub depth_texture: wgpu::Texture, - - //must be last due to drop order - window: Window, -} - -impl Renderer { - pub fn init(event_loop: &ActiveEventLoop, settings: &GameSettings) -> Self { - log::info!("initializing display"); - - let window_attributes = Window::default_attributes() - .with_title("kubi") - .with_maximized(true) - .with_min_inner_size(PhysicalSize::new(640, 480)) - .with_fullscreen({ - //this has no effect on android, so skip this pointless stuff - #[cfg(target_os = "android")] { - None - } - #[cfg(not(target_os = "android"))] - if let Some(fs_settings) = &settings.fullscreen { - let monitor = event_loop.primary_monitor().or_else(|| { - event_loop.available_monitors().next() - }); - - if let Some(monitor) = monitor { - log::info!("monitor: {}", monitor.name().unwrap_or_else(|| "generic".into())); - match fs_settings.mode { - FullscreenMode::Borderless => { - log::info!("starting in borderless fullscreen mode"); - Some(Fullscreen::Borderless(Some(monitor))) - }, - FullscreenMode::Exclusive => { - log::warn!("exclusive fullscreen mode is experimental"); - log::info!("starting in exclusive fullscreen mode"); - //TODO: grabbing the first video mode is probably not the best idea... - monitor.video_modes().next() - .map(|vmode| { - log::info!("video mode: {}", vmode.to_string()); - Some(Fullscreen::Exclusive(vmode)) - }) - .unwrap_or_else(|| { - log::warn!("no valid video modes found, falling back to windowed mode instead"); - None - }) - } - } - } else { - log::warn!("no monitors found, falling back to windowed mode"); - None - } - } else { - log::info!("starting in windowed mode"); - None - } - }); - let window = event_loop.create_window(window_attributes).unwrap(); - - let size = window.inner_size(); - - let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { - backends: wgpu::Backends::BROWSER_WEBGPU | wgpu::Backends::VULKAN | wgpu::Backends::GL, - ..Default::default() - }); - - // Create a surface with `create_surface_unsafe` to get a surface with 'static lifetime - // It should never outlive the window it's created from - let surface = unsafe { - instance.create_surface_unsafe(SurfaceTargetUnsafe::from_window(&window).unwrap()).unwrap() - }; - - let adapter = instance.request_adapter( - &wgpu::RequestAdapterOptions { - power_preference: wgpu::PowerPreference::HighPerformance, - compatible_surface: Some(&surface), - force_fallback_adapter: false, - }, - ).block_on().unwrap(); - - let (device, queue) = adapter.request_device( - &wgpu::DeviceDescriptor { - label: None, - required_features: wgpu::Features::empty(), - required_limits: wgpu::Limits::downlevel_defaults(), - }, - None, - ).block_on().unwrap(); - - let surface_config = surface.get_default_config(&adapter, size.width, size.height).unwrap(); - surface.configure(&device, &surface_config); - - Self { window, instance, surface, device, queue, surface_config, size } - } - - pub fn resize(&mut self, size: PhysicalSize) { - if size.width == 0 || size.height == 0 { - log::warn!("Ignoring resize event with zero width or height"); - return - } - if self.size == size { - log::warn!("Ignoring resize event with same size"); - return - } - log::debug!("resizing surface to {:?}", size); - self.size = size; - self.surface_config.width = size.width; - self.surface_config.height = size.height; - self.surface.configure(&self.device, &self.surface_config); - } - - pub fn reconfigure(&self) { - self.surface.configure(&self.device, &self.surface_config); - } - - //getters: - pub fn size(&self) -> PhysicalSize { - self.size - } - - pub fn window(&self) -> &Window { - &self.window - } - - pub fn surface(&self) -> &wgpu::Surface<'static> { - &self.surface - } - - pub fn device(&self) -> &wgpu::Device { - &self.device - } - - pub fn queue(&self) -> &wgpu::Queue { - &self.queue - } - - pub fn surface_config(&self) -> &wgpu::SurfaceConfiguration { - &self.surface_config - } -} - pub fn render_master(storages: AllStoragesViewMut) { let renderer = storages.borrow::>().unwrap(); - let mut encoder = renderer.device.create_command_encoder(&wgpu::CommandEncoderDescriptor { + let mut encoder = renderer.device().create_command_encoder(&wgpu::CommandEncoderDescriptor { label: Some("main_encoder"), }); let surface_texture = renderer.surface().get_current_texture().unwrap(); diff --git a/kubi/src/rendering/renderer.rs b/kubi/src/rendering/renderer.rs new file mode 100644 index 0000000..5f251a8 --- /dev/null +++ b/kubi/src/rendering/renderer.rs @@ -0,0 +1,157 @@ +use pollster::FutureExt; +use shipyard::Unique; +use winit::{ + event_loop::ActiveEventLoop, + window::{Fullscreen, Window}, + dpi::PhysicalSize +}; +use crate::settings::{GameSettings, FullscreenMode}; + +#[derive(Unique)] +pub struct Renderer { + instance: wgpu::Instance, + surface: wgpu::Surface<'static>, + device: wgpu::Device, + queue: wgpu::Queue, + surface_config: wgpu::SurfaceConfiguration, + size: PhysicalSize, + // pub depth_texture: wgpu::Texture, + + //must be last due to drop order + window: Window, +} + +impl Renderer { + pub fn init(event_loop: &ActiveEventLoop, settings: &GameSettings) -> Self { + log::info!("initializing display"); + + let window_attributes = Window::default_attributes() + .with_title("kubi") + .with_maximized(true) + .with_min_inner_size(PhysicalSize::new(640, 480)) + .with_fullscreen({ + //this has no effect on android, so skip this pointless stuff + #[cfg(target_os = "android")] { + None + } + #[cfg(not(target_os = "android"))] + if let Some(fs_settings) = &settings.fullscreen { + let monitor = event_loop.primary_monitor().or_else(|| { + event_loop.available_monitors().next() + }); + + if let Some(monitor) = monitor { + log::info!("monitor: {}", monitor.name().unwrap_or_else(|| "generic".into())); + match fs_settings.mode { + FullscreenMode::Borderless => { + log::info!("starting in borderless fullscreen mode"); + Some(Fullscreen::Borderless(Some(monitor))) + }, + FullscreenMode::Exclusive => { + log::warn!("exclusive fullscreen mode is experimental"); + log::info!("starting in exclusive fullscreen mode"); + //TODO: grabbing the first video mode is probably not the best idea... + monitor.video_modes().next() + .map(|vmode| { + log::info!("video mode: {}", vmode.to_string()); + Some(Fullscreen::Exclusive(vmode)) + }) + .unwrap_or_else(|| { + log::warn!("no valid video modes found, falling back to windowed mode instead"); + None + }) + } + } + } else { + log::warn!("no monitors found, falling back to windowed mode"); + None + } + } else { + log::info!("starting in windowed mode"); + None + } + }); + let window = event_loop.create_window(window_attributes).unwrap(); + + let size = window.inner_size(); + + let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { + backends: wgpu::Backends::BROWSER_WEBGPU | wgpu::Backends::VULKAN | wgpu::Backends::GL, + ..Default::default() + }); + + // Create a surface with `create_surface_unsafe` to get a surface with 'static lifetime + // It should never outlive the window it's created from + let surface = unsafe { + let target = wgpu::SurfaceTargetUnsafe::from_window(&window).unwrap(); + instance.create_surface_unsafe(target).unwrap() + }; + + let adapter = instance.request_adapter( + &wgpu::RequestAdapterOptions { + power_preference: wgpu::PowerPreference::HighPerformance, + compatible_surface: Some(&surface), + force_fallback_adapter: false, + }, + ).block_on().unwrap(); + + let (device, queue) = adapter.request_device( + &wgpu::DeviceDescriptor { + label: None, + required_features: wgpu::Features::empty(), + required_limits: wgpu::Limits::downlevel_defaults(), + }, + None, + ).block_on().unwrap(); + + let surface_config = surface.get_default_config(&adapter, size.width, size.height).unwrap(); + surface.configure(&device, &surface_config); + + Self { window, instance, surface, device, queue, surface_config, size } + } + + pub fn resize(&mut self, size: PhysicalSize) { + if size.width == 0 || size.height == 0 { + log::warn!("Ignoring resize event with zero width or height"); + return + } + if self.size == size { + log::warn!("Ignoring resize event with same size"); + return + } + log::debug!("resizing surface to {:?}", size); + self.size = size; + self.surface_config.width = size.width; + self.surface_config.height = size.height; + self.surface.configure(&self.device, &self.surface_config); + } + + pub fn reconfigure(&self) { + self.surface.configure(&self.device, &self.surface_config); + } + + //getters: + pub fn size(&self) -> PhysicalSize { + self.size + } + + pub fn window(&self) -> &Window { + &self.window + } + + pub fn surface(&self) -> &wgpu::Surface<'static> { + &self.surface + } + + pub fn device(&self) -> &wgpu::Device { + &self.device + } + + pub fn queue(&self) -> &wgpu::Queue { + &self.queue + } + + pub fn surface_config(&self) -> &wgpu::SurfaceConfiguration { + &self.surface_config + } +} From 35ff06a43932f55c07998e6a5d26c4a45d971c5d Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Sun, 5 May 2024 01:34:27 +0200 Subject: [PATCH 12/51] minor changes to rendering.rs --- kubi/src/rendering.rs | 42 +++++++++++++----------------------------- 1 file changed, 13 insertions(+), 29 deletions(-) diff --git a/kubi/src/rendering.rs b/kubi/src/rendering.rs index e109e41..cc3df5f 100644 --- a/kubi/src/rendering.rs +++ b/kubi/src/rendering.rs @@ -35,8 +35,9 @@ pub fn render_master(storages: AllStoragesViewMut) { let surface_texture = renderer.surface().get_current_texture().unwrap(); let surface_view = surface_texture.texture.create_view(&wgpu::TextureViewDescriptor::default()); + //Main in-game render pass if storages.run(is_ingame) { - let bg_color = storages.borrow::>().unwrap(); + let bg = storages.borrow::>().unwrap().0; let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { label: Some("main0_pass"), color_attachments: &[Some(wgpu::RenderPassColorAttachment { @@ -44,9 +45,9 @@ pub fn render_master(storages: AllStoragesViewMut) { resolve_target: None, ops: wgpu::Operations { load: wgpu::LoadOp::Clear(wgpu::Color { - r: bg_color.0.x as f64, - g: bg_color.0.y as f64, - b: bg_color.0.z as f64, + r: bg.x as f64, + g: bg.y as f64, + b: bg.z as f64, a: 1.0, }), store: wgpu::StoreOp::Store, @@ -59,27 +60,13 @@ pub fn render_master(storages: AllStoragesViewMut) { let data = (&mut render_pass, &*renderer); storages.run_with_data(world::draw_world, data); - - // render_pass.set_pipeline(&renderer.pipeline); - // render_pass.set_bind_group(0, &renderer.bind_group, &[]); - // render_pass.set_vertex_buffer(0, renderer.vertex_buffer.slice(..)); - // render_pass.set_index_buffer(renderer.index_buffer.slice(..)); - // render_pass.draw_indexed(0..renderer.num_indices, 0, 0..1); } renderer.queue().submit(std::iter::once(encoder.finish())); surface_texture.present(); } -// pub fn clear_background( -// mut target: NonSendSync>, -// color: UniqueView, -// ) { -// target.0.clear_color_srgb_and_depth((color.0.x, color.0.y, color.0.z, 1.), 1.); -// } - -//Resize the renderer - +/// Resize the renderer when the window is resized pub fn resize_renderer( mut renderer: UniqueViewMut, resize: View, @@ -89,11 +76,8 @@ pub fn resize_renderer( } } -//not sure if this belongs here - -pub fn init_window_size( - storages: AllStoragesView, -) { +//Deprecated WindowSize thingy +pub fn init_window_size(storages: AllStoragesView) { let size = storages.borrow::>().unwrap().iter().next().unwrap().0; storages.add_unique(WindowSize(size)) } @@ -107,8 +91,8 @@ pub fn update_window_size( } } -pub fn if_resized ( - resize: View, -) -> bool { - resize.len() > 0 -} +// pub fn if_resized ( +// resize: View, +// ) -> bool { +// resize.len() > 0 +// } From 260f4b4232c75cf52facce03508d9c300181fe49 Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Sun, 5 May 2024 02:00:06 +0200 Subject: [PATCH 13/51] load block textures --- kubi/src/prefabs.rs | 35 +++-------- kubi/src/prefabs/shaders.rs | 19 ------ kubi/src/prefabs/texture.rs | 118 ++++++++++++++++++++++-------------- 3 files changed, 84 insertions(+), 88 deletions(-) delete mode 100644 kubi/src/prefabs/shaders.rs diff --git a/kubi/src/prefabs.rs b/kubi/src/prefabs.rs index 7b9583e..d7503dc 100644 --- a/kubi/src/prefabs.rs +++ b/kubi/src/prefabs.rs @@ -5,9 +5,7 @@ use kubi_shared::block::BlockTexture; use crate::{filesystem::AssetManager, hui_integration::UiState, rendering::Renderer}; mod texture; -mod shaders; - -//use texture::load_texture2darray_prefab; +use texture::load_texture2darray_prefab; pub trait AssetPaths { fn file_name(self) -> &'static str; @@ -39,19 +37,7 @@ impl AssetPaths for BlockTexture { #[derive(Unique)] #[repr(transparent)] -pub struct BlockTexturesPrefab(pub wgpu::Texture); - -// #[derive(Unique)] -// #[repr(transparent)] -// pub struct ChunkShaderPrefab(pub Program); - -// #[derive(Unique)] -// #[repr(transparent)] -// pub struct ColoredShaderPrefab(pub Program); - -// #[derive(Unique)] -// #[repr(transparent)] -// pub struct Colored2ShaderPrefab(pub Program); +pub struct BlockDiffuseTexture(pub wgpu::Texture); #[derive(Unique)] #[repr(transparent)] @@ -63,15 +49,14 @@ pub fn load_prefabs( mut ui: NonSendSync>, assman: UniqueView ) { - // log::info!("Loading textures..."); - // storages.add_unique_non_send_sync(BlockTexturesPrefab( - // load_texture2darray_prefab::( - // &assman, - // "blocks".into(), - // &renderer.display, - // MipmapsOption::AutoGeneratedMipmaps - // ) - // )); + log::info!("Loading textures..."); + storages.add_unique_non_send_sync(BlockDiffuseTexture( + load_texture2darray_prefab::( + &renderer, + &assman, + "blocks".into(), + ) + )); log::info!("Loading the UI stuff..."); { diff --git a/kubi/src/prefabs/shaders.rs b/kubi/src/prefabs/shaders.rs deleted file mode 100644 index 7496a2f..0000000 --- a/kubi/src/prefabs/shaders.rs +++ /dev/null @@ -1,19 +0,0 @@ -macro_rules! include_shader_prefab { - ($name: literal, $vert: literal, $frag: literal, $facade: expr) => { - { - use ::glium::{Program, program::ProgramCreationInput}; - log::info!("compiling shader {}", $name); - Program::new(&*$facade, ProgramCreationInput::SourceCode { - vertex_shader: include_str!($vert), - fragment_shader: include_str!($frag), - geometry_shader: None, - tessellation_control_shader: None, - tessellation_evaluation_shader: None, - transform_feedback_varyings: None, - outputs_srgb: false, - uses_point_size: false, - }).expect("Failed to compile gpu program") - } - }; -} -pub(crate) use include_shader_prefab; diff --git a/kubi/src/prefabs/texture.rs b/kubi/src/prefabs/texture.rs index c10c71c..caa23dd 100644 --- a/kubi/src/prefabs/texture.rs +++ b/kubi/src/prefabs/texture.rs @@ -1,45 +1,75 @@ -// use strum::IntoEnumIterator; -// use rayon::prelude::*; -// use std::{path::PathBuf, io::BufReader}; -// use crate::filesystem::AssetManager; -// use super::AssetPaths; +use glam::UVec2; +use strum::IntoEnumIterator; +use rayon::prelude::*; +use wgpu::util::{DeviceExt, TextureDataOrder}; +use std::{io::BufReader, path::PathBuf}; +use crate::{filesystem::AssetManager, rendering::Renderer}; +use super::AssetPaths; -// pub fn load_texture2darray_prefab< -// T: AssetPaths + IntoEnumIterator, -// E: Facade -// >( -// assman: &AssetManager, -// directory: PathBuf, -// facade: &E, -// mipmaps: MipmapsOption, -// ) -> SrgbTexture2dArray { -// log::info!("started loading {}", directory.as_os_str().to_str().unwrap()); -// //Load raw images -// let tex_files: Vec<&'static str> = T::iter().map(|x| x.file_name()).collect(); -// let raw_images: Vec> = tex_files.par_iter().map(|&file_name| { -// log::info!("loading texture {}", file_name); -// //Get path to the image and open the file -// let reader = { -// let path = directory.join(file_name); -// BufReader::new(assman.open_asset(&path).expect("Failed to open texture file")) -// }; -// //Parse image data -// let (image_data, dimensions) = { -// let image = image::load( -// reader, -// image::ImageFormat::Png -// ).unwrap().to_rgba8(); -// let dimensions = image.dimensions(); -// (image.into_raw(), dimensions) -// }; -// //Create a glium RawImage -// RawImage2d::from_raw_rgba_reversed( -// &image_data, -// dimensions -// ) -// }).collect(); -// log::info!("done loading texture files, uploading to the gpu"); -// //Upload images to the GPU -// SrgbTexture2dArray::with_mipmaps(facade, raw_images, mipmaps) -// .expect("Failed to upload texture array to GPU") -// } +pub fn load_texture2darray_prefab( + renderer: &Renderer, + assman: &AssetManager, + directory: PathBuf, +) -> wgpu::Texture { + log::info!("started loading {}", directory.as_os_str().to_str().unwrap()); + + //Load raw images + let tex_files: Vec<&'static str> = T::iter().map(|x| x.file_name()).collect(); + let raw_images: Vec<(Vec, UVec2)> = tex_files.par_iter().map(|&file_name| { + log::info!("loading texture {}", file_name); + + //Get path to the image and open the file + let reader = { + let path = directory.join(file_name); + BufReader::new(assman.open_asset(&path).expect("Failed to open texture file")) + }; + + //Parse image data + let (image_data, dimensions) = { + let image = image::load( + reader, + image::ImageFormat::Png + ).unwrap().to_rgba8(); + let dimensions = image.dimensions(); + (image.into_raw(), dimensions) + }; + (image_data, UVec2::from(dimensions)) + }).collect(); + + assert!(!raw_images.is_empty(), "no images loaded"); + //TODO: check same size + + log::info!("done loading texture files, uploading to the gpu"); + + let size = raw_images[0].1; + let layers = raw_images.len() as u32; + + //Concat data into a single vec + let mut data = Vec::with_capacity((size.x * size.y * layers * 4) as usize); + for (layer_data, _) in raw_images { + data.extend_from_slice(&layer_data); + } + + //Upload images to the GPU + let desc = &wgpu::TextureDescriptor { + label: Some("block_diffuse_texture"), + size: wgpu::Extent3d { + width: size.x, + height: size.y, + depth_or_array_layers: layers, + }, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::Rgba8UnormSrgb, + usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST, + mip_level_count: 1, + sample_count: 1, + view_formats: &[], + }; + + renderer.device().create_texture_with_data( + renderer.queue(), + desc, + TextureDataOrder::MipMajor, + &data + ) +} From 90784e21dd47d5dd87c150da9663a84edb5270bb Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Sun, 5 May 2024 02:02:30 +0200 Subject: [PATCH 14/51] minor changes --- kubi/src/rendering.rs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/kubi/src/rendering.rs b/kubi/src/rendering.rs index cc3df5f..33a052a 100644 --- a/kubi/src/rendering.rs +++ b/kubi/src/rendering.rs @@ -3,29 +3,23 @@ use winit::dpi::PhysicalSize; use glam::{Vec3, UVec2}; use crate::{events::WindowResizedEvent, state::is_ingame}; -pub mod renderer; +mod renderer; +pub use renderer::Renderer; + pub mod primitives; pub mod world; pub mod selection_box; pub mod entities; pub mod sumberge; -pub use renderer::Renderer; pub struct BufferPair { pub index: wgpu::Buffer, pub vertex: wgpu::Buffer, } #[derive(Unique)] -#[repr(transparent)] pub struct BackgroundColor(pub Vec3); -#[derive(Unique, Clone, Copy)] -#[repr(transparent)] -#[deprecated = "use Renderer.size instead"] -#[allow(deprecated)] -pub struct WindowSize(pub UVec2); - pub fn render_master(storages: AllStoragesViewMut) { let renderer = storages.borrow::>().unwrap(); @@ -77,6 +71,13 @@ pub fn resize_renderer( } //Deprecated WindowSize thingy + +#[derive(Unique, Clone, Copy)] +#[repr(transparent)] +#[deprecated = "use Renderer.size instead"] +#[allow(deprecated)] +pub struct WindowSize(pub UVec2); + pub fn init_window_size(storages: AllStoragesView) { let size = storages.borrow::>().unwrap().iter().next().unwrap().0; storages.add_unique(WindowSize(size)) From 58e4eed14e0efd849ba4aebb2f6467e4532b0970 Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Sun, 5 May 2024 13:16:48 +0200 Subject: [PATCH 15/51] init texture prefab --- .gitignore | 4 ++ kubi/src/prefabs.rs | 70 +++++++++++++++++++++++++++++----- kubi/src/rendering/renderer.rs | 9 +++++ 3 files changed, 74 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index f868fe4..0b9b7c9 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,7 @@ _visualizer.json *.so *.dylib *.rlib + +#but keep the dxcompiler.dll/dxil.dll +!dxcompiler.dll +!dxil.dll diff --git a/kubi/src/prefabs.rs b/kubi/src/prefabs.rs index d7503dc..b091c7b 100644 --- a/kubi/src/prefabs.rs +++ b/kubi/src/prefabs.rs @@ -36,8 +36,10 @@ impl AssetPaths for BlockTexture { } #[derive(Unique)] -#[repr(transparent)] -pub struct BlockDiffuseTexture(pub wgpu::Texture); +pub struct Textures { + pub block_diffuse_texture: wgpu::Texture, + pub block_diffuse_bind_group: wgpu::BindGroup, +} #[derive(Unique)] #[repr(transparent)] @@ -50,13 +52,63 @@ pub fn load_prefabs( assman: UniqueView ) { log::info!("Loading textures..."); - storages.add_unique_non_send_sync(BlockDiffuseTexture( - load_texture2darray_prefab::( - &renderer, - &assman, - "blocks".into(), - ) - )); + let block_diffuse_texture = load_texture2darray_prefab::( + &renderer, + &assman, + "blocks".into(), + ); + + log::info!("Creating bing groups"); + let block_diffuse_view = block_diffuse_texture.create_view(&wgpu::TextureViewDescriptor::default()); + let block_diffuse_sampler = renderer.device().create_sampler(&wgpu::SamplerDescriptor { + address_mode_u: wgpu::AddressMode::ClampToEdge, + address_mode_v: wgpu::AddressMode::ClampToEdge, + address_mode_w: wgpu::AddressMode::ClampToEdge, + mag_filter: wgpu::FilterMode::Nearest, + min_filter: wgpu::FilterMode::Nearest, //TODO min_filter Linear, requires filtering sampler + mipmap_filter: wgpu::FilterMode::Nearest, + ..Default::default() + }); + let block_diffuse_bind_group_layout = renderer.device() + .create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: Some("block_diffuse_bind_group_layout"), + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStages::FRAGMENT, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { filterable: false }, + view_dimension: wgpu::TextureViewDimension::D2Array, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStages::FRAGMENT, + ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::NonFiltering), + count: None, + } + ] + }); + let block_diffuse_bind_group = renderer.device().create_bind_group(&wgpu::BindGroupDescriptor { + label: Some("block_diffuse_bind_group"), + layout: &block_diffuse_bind_group_layout, + entries: &[ + wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::TextureView(&block_diffuse_view), + }, + wgpu::BindGroupEntry { + binding: 1, + resource: wgpu::BindingResource::Sampler(&block_diffuse_sampler), + } + ] + }); + storages.add_unique_non_send_sync(Textures { + block_diffuse_texture, + block_diffuse_bind_group, + }); log::info!("Loading the UI stuff..."); { diff --git a/kubi/src/rendering/renderer.rs b/kubi/src/rendering/renderer.rs index 5f251a8..ba85c94 100644 --- a/kubi/src/rendering/renderer.rs +++ b/kubi/src/rendering/renderer.rs @@ -1,5 +1,6 @@ use pollster::FutureExt; use shipyard::Unique; +use winapi::shared::cfg; use winit::{ event_loop::ActiveEventLoop, window::{Fullscreen, Window}, @@ -77,6 +78,14 @@ impl Renderer { let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { backends: wgpu::Backends::BROWSER_WEBGPU | wgpu::Backends::VULKAN | wgpu::Backends::GL, + //Disable validation layer + flags: wgpu::InstanceFlags::default() & !wgpu::InstanceFlags::VALIDATION, + //we're using vulkan on windows + // #[cfg(all(target_os = "windows", target_arch = "x86_64"))] + // dx12_shader_compiler: wgpu::Dx12Compiler::Dxc { + // dxil_path: Some("./dxil.dll".into()), + // dxc_path: Some("./dxcompiler.dll".into()), + // }, ..Default::default() }); From 1d9fafd408ca3c0941c2e5f4ed4fc00ee91f4e1e Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Sun, 5 May 2024 13:25:54 +0200 Subject: [PATCH 16/51] =?UTF-8?q?lifetime=20errors=20:=D1=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kubi/src/prefabs.rs | 4 ++-- kubi/src/rendering/world.rs | 10 +++++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/kubi/src/prefabs.rs b/kubi/src/prefabs.rs index b091c7b..5d521e5 100644 --- a/kubi/src/prefabs.rs +++ b/kubi/src/prefabs.rs @@ -36,7 +36,7 @@ impl AssetPaths for BlockTexture { } #[derive(Unique)] -pub struct Textures { +pub struct TexturePrefabs { pub block_diffuse_texture: wgpu::Texture, pub block_diffuse_bind_group: wgpu::BindGroup, } @@ -105,7 +105,7 @@ pub fn load_prefabs( } ] }); - storages.add_unique_non_send_sync(Textures { + storages.add_unique_non_send_sync(TexturePrefabs { block_diffuse_texture, block_diffuse_bind_group, }); diff --git a/kubi/src/rendering/world.rs b/kubi/src/rendering/world.rs index 5d0c57e..e3ec66d 100644 --- a/kubi/src/rendering/world.rs +++ b/kubi/src/rendering/world.rs @@ -2,7 +2,13 @@ use bytemuck::{Pod, Zeroable}; use glam::{IVec3, Vec3}; use shipyard::{AllStoragesView, IntoIter, NonSendSync, Unique, UniqueView, UniqueViewMut, View}; use kubi_shared::{chunk::CHUNK_SIZE, transform::Transform}; -use crate::{camera::Camera, settings::GameSettings, world::{ChunkMeshStorage, ChunkStorage}}; +use wgpu::util::RenderEncoder; +use crate::{ + camera::Camera, + prefabs::TexturePrefabs, + settings::GameSettings, + world::{ChunkMeshStorage, ChunkStorage}, +}; use super::Renderer; #[derive(Clone, Copy, Pod, Zeroable)] @@ -36,6 +42,7 @@ pub fn init_trans_chunk_queue(storages: AllStoragesView) { pub fn draw_world( (render_pass, renderer): (&mut wgpu::RenderPass, &Renderer), + textures: UniqueView, chunks: UniqueView, meshes: NonSendSync>, transform: View, @@ -66,6 +73,7 @@ pub fn draw_world( //Draw chunk mesh if mesh.main.index.size() > 0 { //TODO + render_pass.set_bind_group(0, &textures.block_diffuse_bind_group, &[]); } //TODO trans chunks From 2c2199d520a13bbe5cadf767711d53a94c6ef55f Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Sun, 5 May 2024 15:19:09 +0200 Subject: [PATCH 17/51] ... --- kubi/src/rendering/world.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kubi/src/rendering/world.rs b/kubi/src/rendering/world.rs index e3ec66d..96fd83c 100644 --- a/kubi/src/rendering/world.rs +++ b/kubi/src/rendering/world.rs @@ -73,7 +73,9 @@ pub fn draw_world( //Draw chunk mesh if mesh.main.index.size() > 0 { //TODO - render_pass.set_bind_group(0, &textures.block_diffuse_bind_group, &[]); + // render_pass.set_index_buffer(mesh.main.index.slice(..), wgpu::IndexFormat::Uint32); + // render_pass.set_vertex_buffer(0, mesh.main.vertex.slice(..)); + // render_pass.set_bind_group(0, &textures.block_diffuse_bind_group, &[]); } //TODO trans chunks From baf037d4a58040db48eaa699411da5371bf5fb36 Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Sun, 5 May 2024 15:20:44 +0200 Subject: [PATCH 18/51] use `Arc` instead of `create_surface_unsafe` --- kubi/src/rendering/renderer.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/kubi/src/rendering/renderer.rs b/kubi/src/rendering/renderer.rs index ba85c94..4cecbf9 100644 --- a/kubi/src/rendering/renderer.rs +++ b/kubi/src/rendering/renderer.rs @@ -1,6 +1,6 @@ +use std::sync::Arc; use pollster::FutureExt; use shipyard::Unique; -use winapi::shared::cfg; use winit::{ event_loop::ActiveEventLoop, window::{Fullscreen, Window}, @@ -10,6 +10,7 @@ use crate::settings::{GameSettings, FullscreenMode}; #[derive(Unique)] pub struct Renderer { + window: Arc, instance: wgpu::Instance, surface: wgpu::Surface<'static>, device: wgpu::Device, @@ -17,9 +18,6 @@ pub struct Renderer { surface_config: wgpu::SurfaceConfiguration, size: PhysicalSize, // pub depth_texture: wgpu::Texture, - - //must be last due to drop order - window: Window, } impl Renderer { @@ -72,7 +70,7 @@ impl Renderer { None } }); - let window = event_loop.create_window(window_attributes).unwrap(); + let window = Arc::new(event_loop.create_window(window_attributes).unwrap()); let size = window.inner_size(); @@ -91,10 +89,11 @@ impl Renderer { // Create a surface with `create_surface_unsafe` to get a surface with 'static lifetime // It should never outlive the window it's created from - let surface = unsafe { - let target = wgpu::SurfaceTargetUnsafe::from_window(&window).unwrap(); - instance.create_surface_unsafe(target).unwrap() - }; + // let surface = unsafe { + // let target = wgpu::SurfaceTargetUnsafe::from_window(&window).unwrap(); + // instance.create_surface_unsafe(target).unwrap() + // }; + let surface = instance.create_surface(Arc::clone(&window)).unwrap(); let adapter = instance.request_adapter( &wgpu::RequestAdapterOptions { From 3f768a8318b3f103c04f59c99ff6a10df5e69a7b Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Sun, 5 May 2024 15:42:25 +0200 Subject: [PATCH 19/51] do rpass in world.rs --- kubi/src/rendering.rs | 25 +++++++++++++++++++------ kubi/src/rendering/world.rs | 24 +++++++++++++++++++----- kubi/src/world/loading.rs | 4 ++++ 3 files changed, 42 insertions(+), 11 deletions(-) diff --git a/kubi/src/rendering.rs b/kubi/src/rendering.rs index 33a052a..843e93b 100644 --- a/kubi/src/rendering.rs +++ b/kubi/src/rendering.rs @@ -14,12 +14,20 @@ pub mod sumberge; pub struct BufferPair { pub index: wgpu::Buffer, + pub index_len: u32, pub vertex: wgpu::Buffer, + pub vertex_len: u32, } #[derive(Unique)] pub struct BackgroundColor(pub Vec3); +pub struct RenderCtx<'a> { + pub renderer: &'a Renderer, + pub encoder: &'a mut wgpu::CommandEncoder, + pub surface_view: &'a wgpu::TextureView, +} + pub fn render_master(storages: AllStoragesViewMut) { let renderer = storages.borrow::>().unwrap(); @@ -29,11 +37,10 @@ pub fn render_master(storages: AllStoragesViewMut) { let surface_texture = renderer.surface().get_current_texture().unwrap(); let surface_view = surface_texture.texture.create_view(&wgpu::TextureViewDescriptor::default()); - //Main in-game render pass - if storages.run(is_ingame) { + { let bg = storages.borrow::>().unwrap().0; - let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { - label: Some("main0_pass"), + let _render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + label: Some("rpass_background"), color_attachments: &[Some(wgpu::RenderPassColorAttachment { view: &surface_view, resolve_target: None, @@ -50,10 +57,16 @@ pub fn render_master(storages: AllStoragesViewMut) { depth_stencil_attachment: None, ..Default::default() }); + } - let data = (&mut render_pass, &*renderer); + let mut data = RenderCtx { + renderer: &renderer, + encoder: &mut encoder, + surface_view: &surface_view, + }; - storages.run_with_data(world::draw_world, data); + if storages.run(is_ingame) { + storages.run_with_data(world::draw_world, &mut data); } renderer.queue().submit(std::iter::once(encoder.finish())); diff --git a/kubi/src/rendering/world.rs b/kubi/src/rendering/world.rs index 96fd83c..17d20ec 100644 --- a/kubi/src/rendering/world.rs +++ b/kubi/src/rendering/world.rs @@ -9,7 +9,7 @@ use crate::{ settings::GameSettings, world::{ChunkMeshStorage, ChunkStorage}, }; -use super::Renderer; +use super::{RenderCtx, Renderer}; #[derive(Clone, Copy, Pod, Zeroable)] #[repr(C, packed)] @@ -41,7 +41,7 @@ pub fn init_trans_chunk_queue(storages: AllStoragesView) { } pub fn draw_world( - (render_pass, renderer): (&mut wgpu::RenderPass, &Renderer), + ctx: &mut RenderCtx, textures: UniqueView, chunks: UniqueView, meshes: NonSendSync>, @@ -53,6 +53,19 @@ pub fn draw_world( let camera = camera.iter().next().expect("No cameras in the scene"); let camera_matrix = camera.view_matrix * camera.perspective_matrix; + let mut render_pass = ctx.encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + label: Some("draw_world"), + color_attachments: &[Some(wgpu::RenderPassColorAttachment { + view: ctx.surface_view, + resolve_target: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Load, + store: wgpu::StoreOp::Store, + }, + })], + ..Default::default() + }); + for (&position, chunk) in &chunks.chunks { if let Some(key) = chunk.mesh_index { let mesh = meshes.get(key).expect("Mesh index pointing to nothing"); @@ -73,9 +86,10 @@ pub fn draw_world( //Draw chunk mesh if mesh.main.index.size() > 0 { //TODO - // render_pass.set_index_buffer(mesh.main.index.slice(..), wgpu::IndexFormat::Uint32); - // render_pass.set_vertex_buffer(0, mesh.main.vertex.slice(..)); - // render_pass.set_bind_group(0, &textures.block_diffuse_bind_group, &[]); + render_pass.set_index_buffer(mesh.main.index.slice(..), wgpu::IndexFormat::Uint32); + render_pass.set_vertex_buffer(0, mesh.main.vertex.slice(..)); + render_pass.set_bind_group(0, &textures.block_diffuse_bind_group, &[]); + render_pass.draw_indexed(0..mesh.main.index_len, 0, 0..1); } //TODO trans chunks diff --git a/kubi/src/world/loading.rs b/kubi/src/world/loading.rs index 48be8d1..6037473 100644 --- a/kubi/src/world/loading.rs +++ b/kubi/src/world/loading.rs @@ -355,12 +355,16 @@ fn process_completed_tasks( let main_buffer_pair = BufferPair { vertex: vtx_buffer, + vertex_len: vertices.len() as u32, index: idx_buffer, + index_len: indices.len() as u32, }; let trans_buffer_pair = BufferPair { vertex: vtx_buffer_trans, + vertex_len: vertices.len() as u32, index: idx_buffer_trans, + index_len: indices.len() as u32, }; let mesh = ChunkMesh { From f4e4886d33f293a30d7a942bd17f4f5f506d4661 Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Mon, 6 May 2024 13:32:44 +0200 Subject: [PATCH 20/51] i see... something? --- kubi-logging/src/lib.rs | 2 +- kubi/shaders/world.wgsl | 12 +- kubi/src/lib.rs | 10 +- kubi/src/prefabs.rs | 2 + kubi/src/rendering.rs | 57 ++++- kubi/src/rendering/camera.rs | 84 +++++++ kubi/src/rendering/shaders.rs | 0 kubi/src/rendering/world.rs | 53 ++-- kubi/src/rendering/world/pipeline.rs | 59 +++++ kubi/src/rendering/world/vertex.rs | 23 ++ kubi/src/world/mesh.rs | 6 +- kubi/src/world/mesh/builder.rs | 358 ++++++++++++++------------- kubi/src/world/tasks.rs | 2 +- 13 files changed, 439 insertions(+), 229 deletions(-) create mode 100644 kubi/src/rendering/camera.rs delete mode 100644 kubi/src/rendering/shaders.rs create mode 100644 kubi/src/rendering/world/pipeline.rs create mode 100644 kubi/src/rendering/world/vertex.rs diff --git a/kubi-logging/src/lib.rs b/kubi-logging/src/lib.rs index 71242dc..0b03e77 100644 --- a/kubi-logging/src/lib.rs +++ b/kubi-logging/src/lib.rs @@ -9,7 +9,7 @@ pub fn init() { use env_logger::{fmt::Color, Builder, Env}; let env = Env::default() - .filter_or("RUST_LOG", "trace,gilrs=warn,rusty_xinput=warn,wgpu=warn,wgpu_core=warn,wgpu_hal=warn,hui=info,hui-winit=info,hui-glium=info,hui-wgpu=info"); + .filter_or("RUST_LOG", "trace,gilrs=warn,rusty_xinput=warn,wgpu=warn,wgpu_core=warn,wgpu_hal=warn,hui=info,hui-winit=info,hui-glium=info,hui-wgpu=info,naga=warn"); Builder::from_env(env) .format(|buf, record| { let mut level_style = buf.style(); diff --git a/kubi/shaders/world.wgsl b/kubi/shaders/world.wgsl index 6587883..cfe54ae 100644 --- a/kubi/shaders/world.wgsl +++ b/kubi/shaders/world.wgsl @@ -1,9 +1,9 @@ -// struct Uniforms { -// transform: mat4x4; -// }; +struct CameraUniform { + view_proj: mat4x4, +}; -// @group(1) @binding(0) -// var uniforms: Uniforms; +@group(1) @binding(0) +var camera: CameraUniform; struct VertexInput { @location(0) position: vec3, @@ -26,7 +26,7 @@ fn vs_main( ) -> VertexOutput { var out: VertexOutput; out.uv = in.uv; - out.clip_position = vec4(in.position, 1.0); + out.clip_position = camera.view_proj * vec4(in.position, 1.0); return out; } diff --git a/kubi/src/lib.rs b/kubi/src/lib.rs index e708b19..ba75b14 100644 --- a/kubi/src/lib.rs +++ b/kubi/src/lib.rs @@ -79,8 +79,11 @@ use player_controller::{debug_switch_ctl_type, update_player_controllers}; // clear_background, entities::render_entities, init_window_size, primitives::init_primitives, resize_renderer, selection_box::render_selection_box, sumberge::render_submerged_view, update_window_size, world::{draw_current_chunk_border, draw_world, draw_world_trans, init_trans_chunk_queue}, BackgroundColor, RenderTarget, Renderer // }; use rendering::{ - init_window_size, render_master, resize_renderer, update_window_size, - world::{init_trans_chunk_queue, TransChunkQueue}, + init_render_states, + init_window_size, + render_master, + resize_renderer, + update_window_size, BackgroundColor, Renderer, }; use block_placement::update_block_placement; @@ -116,7 +119,7 @@ fn startup() -> Workload { init_window_size, kubi_ui_init, load_prefabs, - //init_primitives, + init_render_states, insert_lock_state, init_state, initialize_from_args, @@ -139,7 +142,6 @@ fn update() -> Workload { process_inputs, kubi_ui_begin, ( - init_trans_chunk_queue.run_if_missing_unique::(), init_game_world.run_if_missing_unique::(), ( spawn_player.run_if_storage_empty::(), diff --git a/kubi/src/prefabs.rs b/kubi/src/prefabs.rs index 5d521e5..d4060e4 100644 --- a/kubi/src/prefabs.rs +++ b/kubi/src/prefabs.rs @@ -38,6 +38,7 @@ impl AssetPaths for BlockTexture { #[derive(Unique)] pub struct TexturePrefabs { pub block_diffuse_texture: wgpu::Texture, + pub block_diffuse_bind_group_layout: wgpu::BindGroupLayout, pub block_diffuse_bind_group: wgpu::BindGroup, } @@ -107,6 +108,7 @@ pub fn load_prefabs( }); storages.add_unique_non_send_sync(TexturePrefabs { block_diffuse_texture, + block_diffuse_bind_group_layout, block_diffuse_bind_group, }); diff --git a/kubi/src/rendering.rs b/kubi/src/rendering.rs index 843e93b..8a7b89f 100644 --- a/kubi/src/rendering.rs +++ b/kubi/src/rendering.rs @@ -1,16 +1,50 @@ -use shipyard::{AllStoragesView, AllStoragesViewMut, IntoIter, Unique, UniqueView, UniqueViewMut, View}; +use shipyard::{AllStoragesView, AllStoragesViewMut, IntoIter, IntoWorkload, Unique, UniqueView, UniqueViewMut, View, Workload}; use winit::dpi::PhysicalSize; -use glam::{Vec3, UVec2}; +use glam::{mat4, vec4, Mat4, UVec2, Vec3}; use crate::{events::WindowResizedEvent, state::is_ingame}; mod renderer; pub use renderer::Renderer; -pub mod primitives; +use self::camera::update_camera_unform_buffer; + pub mod world; -pub mod selection_box; -pub mod entities; -pub mod sumberge; +pub mod camera; +//pub mod primitives; +//pub mod selection_box; +//pub mod entities; +//pub mod sumberge; + +pub const WGPU_COORDINATE_SYSTEM: Mat4 = mat4( + vec4(1.0, 0.0, 0.0, 0.0), + vec4(0.0, 1.0, 0.0, 0.0), + vec4(0.0, 0.0, 0.5, 0.5), + vec4(0.0, 0.0, 0.0, 1.0), +); + +// #[repr(C)] +// #[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] +// struct TrasnformUniformData { +// pub transform: [[f32; 4]; 4], +// } + +// impl TrasnformUniformData { +// pub const LAYOUT: &wgpu::Layou +// } + +// impl From for TrasnformUniformData { +// fn from(mat: Mat4) -> Self { +// Self { +// transform: mat.to_cols_array_2d(), +// } +// } +// } + +// impl From for TrasnformUniformData { +// fn from(value: Transform) -> Self { +// value.0.into() +// } +// } pub struct BufferPair { pub index: wgpu::Buffer, @@ -28,6 +62,13 @@ pub struct RenderCtx<'a> { pub surface_view: &'a wgpu::TextureView, } +pub fn init_render_states() -> Workload { + ( + camera::init_camera_uniform_buffer, + world::init_world_render_state, + ).into_workload() +} + pub fn render_master(storages: AllStoragesViewMut) { let renderer = storages.borrow::>().unwrap(); @@ -66,6 +107,10 @@ pub fn render_master(storages: AllStoragesViewMut) { }; if storages.run(is_ingame) { + //XXX: probably should be in pre_update or sth + storages.run(update_camera_unform_buffer); + + //TODO init world render state on demand storages.run_with_data(world::draw_world, &mut data); } diff --git a/kubi/src/rendering/camera.rs b/kubi/src/rendering/camera.rs new file mode 100644 index 0000000..0fb47b9 --- /dev/null +++ b/kubi/src/rendering/camera.rs @@ -0,0 +1,84 @@ +use bytemuck::{Pod, Zeroable}; +use kubi_shared::transform::Transform; +use shipyard::{AllStoragesView, IntoIter, Unique, UniqueView, View}; +use wgpu::util::DeviceExt; +use crate::camera::{self, Camera}; + +use super::{Renderer, WGPU_COORDINATE_SYSTEM}; + +#[derive(Debug, Clone, Copy, Default, Pod, Zeroable)] +#[repr(C, packed)] +pub struct CameraUniformData { + pub view_proj: [[f32; 4]; 4], +} + + +//TODO if multiple cameras, buffer per camera +#[derive(Unique)] +pub struct CameraUniformBuffer { + pub camera_uniform_buffer: wgpu::Buffer, + pub camera_bind_group_layout: wgpu::BindGroupLayout, + pub camera_bind_group: wgpu::BindGroup, +} + +impl CameraUniformBuffer { + pub fn init(renderer: &Renderer, data: CameraUniformData) -> Self { + let camera_uniform_buffer = renderer.device().create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("camera_uniform_buffer"), + contents: bytemuck::cast_slice(&[data]), + usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, + }); + + let camera_bind_group_layout = renderer.device().create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: Some("camera_bind_group_layout"), + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStages::VERTEX, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, + min_binding_size: None, + }, + count: None, + }, + ], + }); + + let camera_bind_group = renderer.device().create_bind_group(&wgpu::BindGroupDescriptor { + label: Some("camera_bind_group"), + layout: &camera_bind_group_layout, + entries: &[ + wgpu::BindGroupEntry { + binding: 0, + resource: camera_uniform_buffer.as_entire_binding(), + }, + ], + }); + + Self { camera_uniform_buffer, camera_bind_group_layout, camera_bind_group } + } + + pub fn init_default(renderer: &Renderer) -> Self { + Self::init(renderer, CameraUniformData::default()) + } + + pub fn update(&self, renderer: &Renderer, data: CameraUniformData) { + renderer.queue().write_buffer(&self.camera_uniform_buffer, 0, bytemuck::cast_slice(&[data])); + } +} + +pub fn init_camera_uniform_buffer(storages: AllStoragesView) { + let renderer = storages.borrow::>().unwrap(); + storages.add_unique(CameraUniformBuffer::init_default(&renderer)); +} + +pub fn update_camera_unform_buffer( + renderer: UniqueView, + camera_uniform_buffer: UniqueView, + camera: View, +) { + let Some(camera) = camera.iter().next() else { return }; + let proj = camera.view_matrix * camera.perspective_matrix * WGPU_COORDINATE_SYSTEM; + camera_uniform_buffer.update(&renderer, CameraUniformData { view_proj: proj.to_cols_array_2d() }); +} diff --git a/kubi/src/rendering/shaders.rs b/kubi/src/rendering/shaders.rs deleted file mode 100644 index e69de29..0000000 diff --git a/kubi/src/rendering/world.rs b/kubi/src/rendering/world.rs index 17d20ec..33ea5fe 100644 --- a/kubi/src/rendering/world.rs +++ b/kubi/src/rendering/world.rs @@ -1,57 +1,44 @@ -use bytemuck::{Pod, Zeroable}; use glam::{IVec3, Vec3}; use shipyard::{AllStoragesView, IntoIter, NonSendSync, Unique, UniqueView, UniqueViewMut, View}; use kubi_shared::{chunk::CHUNK_SIZE, transform::Transform}; -use wgpu::util::RenderEncoder; use crate::{ camera::Camera, prefabs::TexturePrefabs, settings::GameSettings, world::{ChunkMeshStorage, ChunkStorage}, }; -use super::{RenderCtx, Renderer}; +use super::{camera::CameraUniformBuffer, RenderCtx, WGPU_COORDINATE_SYSTEM}; -#[derive(Clone, Copy, Pod, Zeroable)] -#[repr(C, packed)] -pub struct ChunkVertex { - pub position: [f32; 3], - pub normal: [f32; 3], - pub uv: [f32; 2], - pub tex_index: u8, -} - -impl ChunkVertex { - pub const LAYOUT: wgpu::VertexBufferLayout<'static> = wgpu::VertexBufferLayout { - array_stride: std::mem::size_of::() as wgpu::BufferAddress, - step_mode: wgpu::VertexStepMode::Vertex, - attributes: &wgpu::vertex_attr_array![ - 0 => Float32x3, - 1 => Float32x3, - 2 => Float32x2, - 3 => Uint32, - ], - }; -} +mod pipeline; +mod vertex; +pub use vertex::ChunkVertex; #[derive(Unique)] -pub struct TransChunkQueue(pub Vec); +pub struct WorldRenderState { + pub pipeline: wgpu::RenderPipeline, + pub trans_chunk_queue: Vec, +} -pub fn init_trans_chunk_queue(storages: AllStoragesView) { - storages.add_unique(TransChunkQueue(Vec::with_capacity(512))); +pub fn init_world_render_state(storages: AllStoragesView) { + storages.add_unique(WorldRenderState { + pipeline: storages.run(pipeline::init_world_pipeline), + trans_chunk_queue: Vec::with_capacity(512), + }) } pub fn draw_world( ctx: &mut RenderCtx, + mut state: UniqueViewMut, textures: UniqueView, chunks: UniqueView, meshes: NonSendSync>, - transform: View, + //transform: View, camera: View, + camera_ubo: UniqueView, settings: UniqueView, - mut trans_queue: UniqueViewMut, ) { let camera = camera.iter().next().expect("No cameras in the scene"); - let camera_matrix = camera.view_matrix * camera.perspective_matrix; + let matrix = WGPU_COORDINATE_SYSTEM * camera.view_matrix * camera.perspective_matrix; let mut render_pass = ctx.encoder.begin_render_pass(&wgpu::RenderPassDescriptor { label: Some("draw_world"), @@ -66,6 +53,10 @@ pub fn draw_world( ..Default::default() }); + render_pass.set_pipeline(&state.pipeline); + render_pass.set_bind_group(0, &textures.block_diffuse_bind_group, &[]); + render_pass.set_bind_group(1, &camera_ubo.camera_bind_group, &[]); + for (&position, chunk) in &chunks.chunks { if let Some(key) = chunk.mesh_index { let mesh = meshes.get(key).expect("Mesh index pointing to nothing"); @@ -85,10 +76,8 @@ pub fn draw_world( //Draw chunk mesh if mesh.main.index.size() > 0 { - //TODO render_pass.set_index_buffer(mesh.main.index.slice(..), wgpu::IndexFormat::Uint32); render_pass.set_vertex_buffer(0, mesh.main.vertex.slice(..)); - render_pass.set_bind_group(0, &textures.block_diffuse_bind_group, &[]); render_pass.draw_indexed(0..mesh.main.index_len, 0, 0..1); } diff --git a/kubi/src/rendering/world/pipeline.rs b/kubi/src/rendering/world/pipeline.rs new file mode 100644 index 0000000..f6b1a80 --- /dev/null +++ b/kubi/src/rendering/world/pipeline.rs @@ -0,0 +1,59 @@ +use shipyard::{Unique, UniqueView}; +use crate::{ + prefabs::TexturePrefabs, + rendering::{camera::CameraUniformBuffer, world::ChunkVertex, Renderer} +}; + +pub fn init_world_pipeline( + ren: UniqueView, + textures: UniqueView, + camera_ubo: UniqueView, +) -> wgpu::RenderPipeline { + let shader = ren.device().create_shader_module( + wgpu::include_wgsl!("../../../shaders/world.wgsl") + ); + + let world_pipeline_layout = ren.device().create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("world_pipeline_layout"), + bind_group_layouts: &[ + &textures.block_diffuse_bind_group_layout, + &camera_ubo.camera_bind_group_layout, + ], + push_constant_ranges: &[], + }); + + ren.device().create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("world_pipeline"), + layout: Some(&world_pipeline_layout), + fragment: Some(wgpu::FragmentState { + module: &shader, + entry_point: "fs_main", + compilation_options: wgpu::PipelineCompilationOptions::default(), + targets: &[Some(wgpu::ColorTargetState { + format: ren.surface_config().format, + blend: Some(wgpu::BlendState::REPLACE), + write_mask: wgpu::ColorWrites::ALL, + })], + }), + vertex: wgpu::VertexState { + module: &shader, + entry_point: "vs_main", + compilation_options: wgpu::PipelineCompilationOptions::default(), + buffers: &[ + ChunkVertex::LAYOUT, + ], + }, + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleList, + strip_index_format: None, + cull_mode: Some(wgpu::Face::Back), + front_face: wgpu::FrontFace::Cw, + unclipped_depth: false, + polygon_mode: wgpu::PolygonMode::Fill, + conservative: false, + }, + depth_stencil: None, + multisample: wgpu::MultisampleState::default(), + multiview: None, + }) +} diff --git a/kubi/src/rendering/world/vertex.rs b/kubi/src/rendering/world/vertex.rs new file mode 100644 index 0000000..ad1544c --- /dev/null +++ b/kubi/src/rendering/world/vertex.rs @@ -0,0 +1,23 @@ +use bytemuck::{Pod, Zeroable}; + +#[derive(Clone, Copy, Pod, Zeroable)] +#[repr(C, packed)] +pub struct ChunkVertex { + pub position: [f32; 3], + pub normal: [f32; 3], + pub uv: [f32; 2], + pub tex_index: u32, +} + +impl ChunkVertex { + pub const LAYOUT: wgpu::VertexBufferLayout<'static> = wgpu::VertexBufferLayout { + array_stride: std::mem::size_of::() as wgpu::BufferAddress, + step_mode: wgpu::VertexStepMode::Vertex, + attributes: &wgpu::vertex_attr_array![ + 0 => Float32x3, + 1 => Float32x3, + 2 => Float32x2, + 3 => Uint32, + ], + }; +} diff --git a/kubi/src/world/mesh.rs b/kubi/src/world/mesh.rs index 24e2f2d..3b43116 100644 --- a/kubi/src/world/mesh.rs +++ b/kubi/src/world/mesh.rs @@ -1,4 +1,4 @@ -use glam::{IVec3, ivec3}; +use glam::{ivec3, IVec3, Vec3}; use strum::IntoEnumIterator; use kubi_shared::block::{Block, RenderType, Transparency}; use crate::world::chunk::CHUNK_SIZE; @@ -10,7 +10,7 @@ mod builder; use data::MeshGenData; use builder::{MeshBuilder, CubeFace, DiagonalFace}; -pub fn generate_mesh(data: MeshGenData) -> ( +pub fn generate_mesh(position: IVec3, data: MeshGenData) -> ( (Vec, Vec), (Vec, Vec), ) { @@ -32,7 +32,7 @@ pub fn generate_mesh(data: MeshGenData) -> ( } }; - let mut builder = MeshBuilder::new(); + let mut builder = MeshBuilder::new_with_offset((position * CHUNK_SIZE as i32).as_vec3()); let mut trans_builder = MeshBuilder::new(); for x in 0..CHUNK_SIZE as i32 { diff --git a/kubi/src/world/mesh/builder.rs b/kubi/src/world/mesh/builder.rs index 561342c..88cddf5 100644 --- a/kubi/src/world/mesh/builder.rs +++ b/kubi/src/world/mesh/builder.rs @@ -1,176 +1,182 @@ -use strum::EnumIter; -use glam::{Vec3, vec3, IVec3, ivec3}; -use std::f32::consts::FRAC_1_SQRT_2; -use crate::rendering::world::ChunkVertex; - -#[repr(usize)] -#[derive(Clone, Copy, Debug, EnumIter)] -pub enum CubeFace { - Top = 0, - Front = 4, - Left = 2, - Right = 3, - Back = 1, - Bottom = 5, -} -impl CubeFace { - pub const fn normal(self) -> IVec3 { - CUBE_FACE_NORMALS_IVEC3[self as usize] - } -} - -const CUBE_FACE_VERTICES: [[Vec3; 4]; 6] = [ - [vec3(0., 1., 0.), vec3(0., 1., 1.), vec3(1., 1., 0.), vec3(1., 1., 1.)], - [vec3(0., 0., 0.), vec3(0., 1., 0.), vec3(1., 0., 0.), vec3(1., 1., 0.)], - [vec3(0., 0., 1.), vec3(0., 1., 1.), vec3(0., 0., 0.), vec3(0., 1., 0.)], - [vec3(1., 0., 0.), vec3(1., 1., 0.), vec3(1., 0., 1.), vec3(1., 1., 1.)], - [vec3(1., 0., 1.), vec3(1., 1., 1.), vec3(0., 0., 1.), vec3(0., 1., 1.)], - [vec3(0., 0., 1.), vec3(0., 0., 0.), vec3(1., 0., 1.), vec3(1., 0., 0.)], -]; -const CUBE_FACE_NORMALS_IVEC3: [IVec3; 6] = [ - ivec3( 0, 1, 0), - ivec3( 0, 0, -1), - ivec3(-1, 0, 0), - ivec3( 1, 0, 0), - ivec3( 0, 0, 1), - ivec3( 0, -1, 0) -]; -const CUBE_FACE_NORMALS: [Vec3; 6] = [ - vec3(0., 1., 0.), - vec3(0., 0., -1.), - vec3(-1.,0., 0.), - vec3(1., 0., 0.), - vec3(0., 0., 1.), - vec3(0., -1.,0.) -]; -const CUBE_FACE_INDICES: [u32; 6] = [0, 1, 2, 2, 1, 3]; - -#[repr(usize)] -pub enum DiagonalFace { - RigthZ = 0, - LeftZ = 1, -} -const CROSS_FACES: [[Vec3; 4]; 2] = [ - [ - vec3(0., 0., 0.), - vec3(0., 1., 0.), - vec3(1., 0., 1.), - vec3(1., 1., 1.), - ], - [ - vec3(0., 0., 1.), - vec3(0., 1., 1.), - vec3(1., 0., 0.), - vec3(1., 1., 0.), - ] -]; -const CROSS_FACE_NORMALS: [Vec3; 2] = [ - vec3(-FRAC_1_SQRT_2, 0., FRAC_1_SQRT_2), - vec3( FRAC_1_SQRT_2, 0., FRAC_1_SQRT_2), -]; -const CROSS_FACE_NORMALS_BACK: [Vec3; 2] = [ - vec3( FRAC_1_SQRT_2, 0., -FRAC_1_SQRT_2), - vec3(-FRAC_1_SQRT_2, 0., -FRAC_1_SQRT_2), -]; -const CROSS_FACE_INDICES: [u32; 12] = [ - 0, 1, 2, 2, 1, 3, //Front side - 6, 5, 4, 7, 5, 6, //Back side -]; - - -const UV_COORDS: [[f32; 2]; 4] = [ - [0., 0.], - [0., 1.], - [1., 0.], - [1., 1.], -]; - -#[derive(Default)] -pub struct MeshBuilder { - vertex_buffer: Vec, - index_buffer: Vec, - idx_counter: u32, -} -impl MeshBuilder { - pub fn new() -> Self { - Self::default() - } - - pub fn add_face(&mut self, face: CubeFace, coord: IVec3, texture: u8) { - let coord = coord.as_vec3(); - let face_index = face as usize; - - //Push vertices - let norm = CUBE_FACE_NORMALS[face_index]; - let vert = CUBE_FACE_VERTICES[face_index]; - self.vertex_buffer.reserve(4); - for i in 0..4 { - self.vertex_buffer.push(ChunkVertex { - position: (coord + vert[i]).to_array(), - normal: norm.to_array(), - uv: UV_COORDS[i], - tex_index: texture - }); - } - - //Push indices - self.index_buffer.extend_from_slice(&CUBE_FACE_INDICES.map(|x| x + self.idx_counter)); - - //Increment idx counter - self.idx_counter += 4; - } - - pub fn add_diagonal_face(&mut self, coord: IVec3, face_type: DiagonalFace, front_texture: u8, back_texture: u8) { - //Push vertices - let face_type = face_type as usize; - let vertices = CROSS_FACES[face_type]; - let normal_front = CROSS_FACE_NORMALS[face_type].to_array(); - let normal_back = CROSS_FACE_NORMALS_BACK[face_type].to_array(); - self.vertex_buffer.reserve(8); - for i in 0..4 { //push front vertices - self.vertex_buffer.push(ChunkVertex { - position: (coord.as_vec3() + vertices[i]).to_array(), - normal: normal_front, - uv: UV_COORDS[i], - tex_index: front_texture - }) - } - for i in 0..4 { //push back vertices - self.vertex_buffer.push(ChunkVertex { - position: (coord.as_vec3() + vertices[i]).to_array(), - normal: normal_back, - uv: UV_COORDS[i], - tex_index: back_texture - }) - } - - //Push indices - self.index_buffer.extend_from_slice(&CROSS_FACE_INDICES.map(|x| x + self.idx_counter)); - - //Increment idx counter - self.idx_counter += 8; - } - - pub fn add_model(&mut self, position: Vec3, vertices: &[ChunkVertex], indices: Option<&[u32]>) { - //push vertices - self.vertex_buffer.extend(vertices.iter().map(|vertex| { - let mut vertex = *vertex; - vertex.position[0] += position.x; - vertex.position[0] += position.y; - vertex.position[0] += position.z; - vertex - })); - //push indices - if let Some(indices) = indices { - self.index_buffer.extend(indices.iter().map(|x| x + self.idx_counter)); - } else { - self.index_buffer.extend(0..(self.vertex_buffer.len() as u32)); - } - //increment idx counter - self.idx_counter += vertices.len() as u32; - } - - pub fn finish(self) -> (Vec, Vec) { - (self.vertex_buffer, self.index_buffer) - } -} +use strum::EnumIter; +use glam::{ivec3, vec3, IVec3, Vec3}; +use std::f32::consts::FRAC_1_SQRT_2; +use crate::rendering::world::ChunkVertex; + +#[repr(usize)] +#[derive(Clone, Copy, Debug, EnumIter)] +pub enum CubeFace { + Top = 0, + Front = 4, + Left = 2, + Right = 3, + Back = 1, + Bottom = 5, +} +impl CubeFace { + pub const fn normal(self) -> IVec3 { + CUBE_FACE_NORMALS_IVEC3[self as usize] + } +} + +const CUBE_FACE_VERTICES: [[Vec3; 4]; 6] = [ + [vec3(0., 1., 0.), vec3(0., 1., 1.), vec3(1., 1., 0.), vec3(1., 1., 1.)], + [vec3(0., 0., 0.), vec3(0., 1., 0.), vec3(1., 0., 0.), vec3(1., 1., 0.)], + [vec3(0., 0., 1.), vec3(0., 1., 1.), vec3(0., 0., 0.), vec3(0., 1., 0.)], + [vec3(1., 0., 0.), vec3(1., 1., 0.), vec3(1., 0., 1.), vec3(1., 1., 1.)], + [vec3(1., 0., 1.), vec3(1., 1., 1.), vec3(0., 0., 1.), vec3(0., 1., 1.)], + [vec3(0., 0., 1.), vec3(0., 0., 0.), vec3(1., 0., 1.), vec3(1., 0., 0.)], +]; +const CUBE_FACE_NORMALS_IVEC3: [IVec3; 6] = [ + ivec3( 0, 1, 0), + ivec3( 0, 0, -1), + ivec3(-1, 0, 0), + ivec3( 1, 0, 0), + ivec3( 0, 0, 1), + ivec3( 0, -1, 0) +]; +const CUBE_FACE_NORMALS: [Vec3; 6] = [ + vec3(0., 1., 0.), + vec3(0., 0., -1.), + vec3(-1.,0., 0.), + vec3(1., 0., 0.), + vec3(0., 0., 1.), + vec3(0., -1.,0.) +]; +const CUBE_FACE_INDICES: [u32; 6] = [0, 1, 2, 2, 1, 3]; + +#[repr(usize)] +pub enum DiagonalFace { + RigthZ = 0, + LeftZ = 1, +} +const CROSS_FACES: [[Vec3; 4]; 2] = [ + [ + vec3(0., 0., 0.), + vec3(0., 1., 0.), + vec3(1., 0., 1.), + vec3(1., 1., 1.), + ], + [ + vec3(0., 0., 1.), + vec3(0., 1., 1.), + vec3(1., 0., 0.), + vec3(1., 1., 0.), + ] +]; +const CROSS_FACE_NORMALS: [Vec3; 2] = [ + vec3(-FRAC_1_SQRT_2, 0., FRAC_1_SQRT_2), + vec3( FRAC_1_SQRT_2, 0., FRAC_1_SQRT_2), +]; +const CROSS_FACE_NORMALS_BACK: [Vec3; 2] = [ + vec3( FRAC_1_SQRT_2, 0., -FRAC_1_SQRT_2), + vec3(-FRAC_1_SQRT_2, 0., -FRAC_1_SQRT_2), +]; +const CROSS_FACE_INDICES: [u32; 12] = [ + 0, 1, 2, 2, 1, 3, //Front side + 6, 5, 4, 7, 5, 6, //Back side +]; + + +const UV_COORDS: [[f32; 2]; 4] = [ + [0., 0.], + [0., 1.], + [1., 0.], + [1., 1.], +]; + +#[derive(Default)] +pub struct MeshBuilder { + offset: Vec3, + vertex_buffer: Vec, + index_buffer: Vec, + idx_counter: u32, +} +impl MeshBuilder { + pub fn new() -> Self { + Self::default() + } + + pub fn new_with_offset(offset: Vec3) -> Self { + Self { offset, ..Self::new() } + } + + pub fn add_face(&mut self, face: CubeFace, coord: IVec3, texture: u8) { + let coord = coord.as_vec3(); + let face_index = face as usize; + + //Push vertices + let norm = CUBE_FACE_NORMALS[face_index]; + let vert = CUBE_FACE_VERTICES[face_index]; + self.vertex_buffer.reserve(4); + for i in 0..4 { + self.vertex_buffer.push(ChunkVertex { + position: (coord + vert[i] + self.offset).to_array(), + normal: norm.to_array(), + uv: UV_COORDS[i], + tex_index: texture as u32 + }); + } + + //Push indices + self.index_buffer.extend_from_slice(&CUBE_FACE_INDICES.map(|x| x + self.idx_counter)); + + //Increment idx counter + self.idx_counter += 4; + } + + pub fn add_diagonal_face(&mut self, coord: IVec3, face_type: DiagonalFace, front_texture: u8, back_texture: u8) { + //Push vertices + let face_type = face_type as usize; + let vertices = CROSS_FACES[face_type]; + let normal_front = CROSS_FACE_NORMALS[face_type].to_array(); + let normal_back = CROSS_FACE_NORMALS_BACK[face_type].to_array(); + self.vertex_buffer.reserve(8); + for i in 0..4 { //push front vertices + self.vertex_buffer.push(ChunkVertex { + position: (coord.as_vec3() + vertices[i] + self.offset).to_array(), + normal: normal_front, + uv: UV_COORDS[i], + tex_index: front_texture as u32 + }) + } + for i in 0..4 { //push back vertices + self.vertex_buffer.push(ChunkVertex { + position: (coord.as_vec3() + vertices[i] + self.offset).to_array(), + normal: normal_back, + uv: UV_COORDS[i], + tex_index: back_texture as u32 + }) + } + + //Push indices + self.index_buffer.extend_from_slice(&CROSS_FACE_INDICES.map(|x| x + self.idx_counter)); + + //Increment idx counter + self.idx_counter += 8; + } + + //XXX: needs offset supprt + // pub fn add_model(&mut self, position: Vec3, vertices: &[ChunkVertex], indices: Option<&[u32]>) { + // //push vertices + // self.vertex_buffer.extend(vertices.iter().map(|vertex| { + // let mut vertex = *vertex; + // vertex.position[0] += position.x; + // vertex.position[0] += position.y; + // vertex.position[0] += position.z; + // vertex + // })); + // //push indices + // if let Some(indices) = indices { + // self.index_buffer.extend(indices.iter().map(|x| x + self.idx_counter)); + // } else { + // self.index_buffer.extend(0..(self.vertex_buffer.len() as u32)); + // } + // //increment idx counter + // self.idx_counter += vertices.len() as u32; + // } + + pub fn finish(self) -> (Vec, Vec) { + (self.vertex_buffer, self.index_buffer) + } +} diff --git a/kubi/src/world/tasks.rs b/kubi/src/world/tasks.rs index 87bda90..a481f5f 100644 --- a/kubi/src/world/tasks.rs +++ b/kubi/src/world/tasks.rs @@ -63,7 +63,7 @@ impl ChunkTaskManager { let ( (vertices, indices), (trans_vertices, trans_indices), - ) = generate_mesh(data); + ) = generate_mesh(position, data); ChunkTaskResponse::GeneratedMesh { position, vertices, indices, From d14b5e1b40b0fb5a19fb6734acfb6ab288b413a7 Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Mon, 6 May 2024 14:29:07 +0200 Subject: [PATCH 21/51] ok this is better --- kubi/src/camera/matrices.rs | 2 +- kubi/src/rendering.rs | 12 ++++++------ kubi/src/rendering/camera.rs | 9 ++++----- kubi/src/rendering/world.rs | 17 ++++++----------- 4 files changed, 17 insertions(+), 23 deletions(-) diff --git a/kubi/src/camera/matrices.rs b/kubi/src/camera/matrices.rs index 44c359f..2309724 100644 --- a/kubi/src/camera/matrices.rs +++ b/kubi/src/camera/matrices.rs @@ -21,7 +21,7 @@ fn update_perspective_matrix( size: UniqueView, ) { for mut camera in (&mut vm_camera).iter() { - camera.perspective_matrix = Mat4::perspective_rh_gl( + camera.perspective_matrix = Mat4::perspective_rh( camera.fov, size.0.x as f32 / size.0.y as f32, camera.z_near, diff --git a/kubi/src/rendering.rs b/kubi/src/rendering.rs index 8a7b89f..e42a91b 100644 --- a/kubi/src/rendering.rs +++ b/kubi/src/rendering.rs @@ -15,12 +15,12 @@ pub mod camera; //pub mod entities; //pub mod sumberge; -pub const WGPU_COORDINATE_SYSTEM: Mat4 = mat4( - vec4(1.0, 0.0, 0.0, 0.0), - vec4(0.0, 1.0, 0.0, 0.0), - vec4(0.0, 0.0, 0.5, 0.5), - vec4(0.0, 0.0, 0.0, 1.0), -); +// pub const WGPU_COORDINATE_SYSTEM: Mat4 = mat4( +// vec4(1.0, 0.0, 0.0, 0.0), +// vec4(0.0, 1.0, 0.0, 0.0), +// vec4(0.0, 0.0, 0.5, 0.5), +// vec4(0.0, 0.0, 0.0, 1.0), +// ); // #[repr(C)] // #[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] diff --git a/kubi/src/rendering/camera.rs b/kubi/src/rendering/camera.rs index 0fb47b9..918f224 100644 --- a/kubi/src/rendering/camera.rs +++ b/kubi/src/rendering/camera.rs @@ -3,13 +3,12 @@ use kubi_shared::transform::Transform; use shipyard::{AllStoragesView, IntoIter, Unique, UniqueView, View}; use wgpu::util::DeviceExt; use crate::camera::{self, Camera}; - -use super::{Renderer, WGPU_COORDINATE_SYSTEM}; +use super::Renderer; #[derive(Debug, Clone, Copy, Default, Pod, Zeroable)] #[repr(C, packed)] pub struct CameraUniformData { - pub view_proj: [[f32; 4]; 4], + pub view_proj: [f32; 4 * 4], } @@ -79,6 +78,6 @@ pub fn update_camera_unform_buffer( camera: View, ) { let Some(camera) = camera.iter().next() else { return }; - let proj = camera.view_matrix * camera.perspective_matrix * WGPU_COORDINATE_SYSTEM; - camera_uniform_buffer.update(&renderer, CameraUniformData { view_proj: proj.to_cols_array_2d() }); + let proj = camera.perspective_matrix * camera.view_matrix; + camera_uniform_buffer.update(&renderer, CameraUniformData { view_proj: proj.to_cols_array() }); } diff --git a/kubi/src/rendering/world.rs b/kubi/src/rendering/world.rs index 33ea5fe..b2a78d7 100644 --- a/kubi/src/rendering/world.rs +++ b/kubi/src/rendering/world.rs @@ -7,7 +7,7 @@ use crate::{ settings::GameSettings, world::{ChunkMeshStorage, ChunkStorage}, }; -use super::{camera::CameraUniformBuffer, RenderCtx, WGPU_COORDINATE_SYSTEM}; +use super::{camera::CameraUniformBuffer, RenderCtx}; mod pipeline; mod vertex; @@ -32,14 +32,9 @@ pub fn draw_world( textures: UniqueView, chunks: UniqueView, meshes: NonSendSync>, - //transform: View, - camera: View, camera_ubo: UniqueView, settings: UniqueView, ) { - let camera = camera.iter().next().expect("No cameras in the scene"); - let matrix = WGPU_COORDINATE_SYSTEM * camera.view_matrix * camera.perspective_matrix; - let mut render_pass = ctx.encoder.begin_render_pass(&wgpu::RenderPassDescriptor { label: Some("draw_world"), color_attachments: &[Some(wgpu::RenderPassColorAttachment { @@ -68,11 +63,11 @@ pub fn draw_world( } //Frustum culling - let minp = world_position; - let maxp = world_position + Vec3::splat(CHUNK_SIZE as f32); - if !camera.frustum.is_box_visible(minp, maxp) { - continue - } + // let minp = world_position; + // let maxp = world_position + Vec3::splat(CHUNK_SIZE as f32); + // if !camera.frustum.is_box_visible(minp, maxp) { + // continue + // } //Draw chunk mesh if mesh.main.index.size() > 0 { From dd386acea10e9b2a9d1b27ded25c358c47e8d822 Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Mon, 6 May 2024 15:48:36 +0200 Subject: [PATCH 22/51] owo --- kubi/shaders/world.wgsl | 7 ++++--- kubi/src/prefabs.rs | 6 +++++- kubi/src/rendering/world.rs | 15 +++++++++------ kubi/src/rendering/world/pipeline.rs | 2 +- 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/kubi/shaders/world.wgsl b/kubi/shaders/world.wgsl index cfe54ae..7cf22b5 100644 --- a/kubi/shaders/world.wgsl +++ b/kubi/shaders/world.wgsl @@ -9,15 +9,14 @@ struct VertexInput { @location(0) position: vec3, @location(1) normal: vec3, @location(2) uv: vec2, - @location(3) @interpolate(flat) tex_index: u32, + @location(3) tex_index: u32, } struct VertexOutput { @builtin(position) clip_position: vec4, @location(0) uv: vec2, @location(1) normal: vec3, - @location(2) color: vec4, - @location(3) @interpolate(flat) tex_index: u32, + @location(2) @interpolate(flat) tex_index: u32, }; @vertex @@ -26,6 +25,8 @@ fn vs_main( ) -> VertexOutput { var out: VertexOutput; out.uv = in.uv; + out.normal = in.normal; + out.tex_index = in.tex_index; out.clip_position = camera.view_proj * vec4(in.position, 1.0); return out; } diff --git a/kubi/src/prefabs.rs b/kubi/src/prefabs.rs index d4060e4..08bd3e9 100644 --- a/kubi/src/prefabs.rs +++ b/kubi/src/prefabs.rs @@ -60,8 +60,12 @@ pub fn load_prefabs( ); log::info!("Creating bing groups"); - let block_diffuse_view = block_diffuse_texture.create_view(&wgpu::TextureViewDescriptor::default()); + let block_diffuse_view = block_diffuse_texture.create_view(&wgpu::TextureViewDescriptor { + label: Some("block_texture_view"), + ..Default::default() + }); let block_diffuse_sampler = renderer.device().create_sampler(&wgpu::SamplerDescriptor { + label: Some("block_diffuse_sampler"), address_mode_u: wgpu::AddressMode::ClampToEdge, address_mode_v: wgpu::AddressMode::ClampToEdge, address_mode_w: wgpu::AddressMode::ClampToEdge, diff --git a/kubi/src/rendering/world.rs b/kubi/src/rendering/world.rs index b2a78d7..829705c 100644 --- a/kubi/src/rendering/world.rs +++ b/kubi/src/rendering/world.rs @@ -7,7 +7,7 @@ use crate::{ settings::GameSettings, world::{ChunkMeshStorage, ChunkStorage}, }; -use super::{camera::CameraUniformBuffer, RenderCtx}; +use super::{camera::{self, CameraUniformBuffer}, RenderCtx}; mod pipeline; mod vertex; @@ -30,11 +30,14 @@ pub fn draw_world( ctx: &mut RenderCtx, mut state: UniqueViewMut, textures: UniqueView, + camera: View, chunks: UniqueView, meshes: NonSendSync>, camera_ubo: UniqueView, settings: UniqueView, ) { + let camera = camera.iter().next().expect("No cameras in the scene"); + let mut render_pass = ctx.encoder.begin_render_pass(&wgpu::RenderPassDescriptor { label: Some("draw_world"), color_attachments: &[Some(wgpu::RenderPassColorAttachment { @@ -63,11 +66,11 @@ pub fn draw_world( } //Frustum culling - // let minp = world_position; - // let maxp = world_position + Vec3::splat(CHUNK_SIZE as f32); - // if !camera.frustum.is_box_visible(minp, maxp) { - // continue - // } + let minp = world_position; + let maxp = world_position + Vec3::splat(CHUNK_SIZE as f32); + if !camera.frustum.is_box_visible(minp, maxp) { + continue + } //Draw chunk mesh if mesh.main.index.size() > 0 { diff --git a/kubi/src/rendering/world/pipeline.rs b/kubi/src/rendering/world/pipeline.rs index f6b1a80..80fe6b1 100644 --- a/kubi/src/rendering/world/pipeline.rs +++ b/kubi/src/rendering/world/pipeline.rs @@ -47,7 +47,7 @@ pub fn init_world_pipeline( topology: wgpu::PrimitiveTopology::TriangleList, strip_index_format: None, cull_mode: Some(wgpu::Face::Back), - front_face: wgpu::FrontFace::Cw, + front_face: wgpu::FrontFace::Ccw, unclipped_depth: false, polygon_mode: wgpu::PolygonMode::Fill, conservative: false, From f04542ac02f4772df262e378f8869118a1d71480 Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Mon, 6 May 2024 15:52:59 +0200 Subject: [PATCH 23/51] discard fully transparent --- kubi/shaders/world.wgsl | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/kubi/shaders/world.wgsl b/kubi/shaders/world.wgsl index 7cf22b5..2577187 100644 --- a/kubi/shaders/world.wgsl +++ b/kubi/shaders/world.wgsl @@ -16,7 +16,7 @@ struct VertexOutput { @builtin(position) clip_position: vec4, @location(0) uv: vec2, @location(1) normal: vec3, - @location(2) @interpolate(flat) tex_index: u32, + @location(2) @interpolate(flat)tex_index: u32, }; @vertex @@ -28,7 +28,7 @@ fn vs_main( out.normal = in.normal; out.tex_index = in.tex_index; out.clip_position = camera.view_proj * vec4(in.position, 1.0); - return out; + out } @group(0) @binding(0) @@ -39,5 +39,9 @@ var s_diffuse: sampler; @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4 { - return textureSample(t_diffuse, s_diffuse, in.uv, in.tex_index); + let color: vec4 = textureSample(t_diffuse, s_diffuse, in.uv, in.tex_index); + if (color.a == 0.) { + discard + } + color } From 674ec97a6e8c7bbb5f1ffd6071671605545d6f16 Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Mon, 6 May 2024 15:53:47 +0200 Subject: [PATCH 24/51] oops --- kubi/shaders/world.wgsl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kubi/shaders/world.wgsl b/kubi/shaders/world.wgsl index 2577187..df7a7b3 100644 --- a/kubi/shaders/world.wgsl +++ b/kubi/shaders/world.wgsl @@ -28,7 +28,7 @@ fn vs_main( out.normal = in.normal; out.tex_index = in.tex_index; out.clip_position = camera.view_proj * vec4(in.position, 1.0); - out + return out; } @group(0) @binding(0) @@ -41,7 +41,7 @@ var s_diffuse: sampler; fn fs_main(in: VertexOutput) -> @location(0) vec4 { let color: vec4 = textureSample(t_diffuse, s_diffuse, in.uv, in.tex_index); if (color.a == 0.) { - discard + discard; } - color + return color; } From 8fd1930ce6a5f7c34cf9e5e23bb88ec5af0bad30 Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Mon, 6 May 2024 15:54:17 +0200 Subject: [PATCH 25/51] forgor vec4 type --- kubi/shaders/world.wgsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kubi/shaders/world.wgsl b/kubi/shaders/world.wgsl index df7a7b3..d9b6069 100644 --- a/kubi/shaders/world.wgsl +++ b/kubi/shaders/world.wgsl @@ -39,7 +39,7 @@ var s_diffuse: sampler; @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4 { - let color: vec4 = textureSample(t_diffuse, s_diffuse, in.uv, in.tex_index); + let color: vec4 = textureSample(t_diffuse, s_diffuse, in.uv, in.tex_index); if (color.a == 0.) { discard; } From 9a01ecd6f2b06098697791b1955887cdfa317fd9 Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Mon, 6 May 2024 16:17:01 +0200 Subject: [PATCH 26/51] depth, wip --- kubi/src/rendering.rs | 5 ++- kubi/src/rendering/depth.rs | 67 +++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 kubi/src/rendering/depth.rs diff --git a/kubi/src/rendering.rs b/kubi/src/rendering.rs index e42a91b..215e597 100644 --- a/kubi/src/rendering.rs +++ b/kubi/src/rendering.rs @@ -10,6 +10,8 @@ use self::camera::update_camera_unform_buffer; pub mod world; pub mod camera; +pub mod depth; + //pub mod primitives; //pub mod selection_box; //pub mod entities; @@ -107,9 +109,6 @@ pub fn render_master(storages: AllStoragesViewMut) { }; if storages.run(is_ingame) { - //XXX: probably should be in pre_update or sth - storages.run(update_camera_unform_buffer); - //TODO init world render state on demand storages.run_with_data(world::draw_world, &mut data); } diff --git a/kubi/src/rendering/depth.rs b/kubi/src/rendering/depth.rs new file mode 100644 index 0000000..6c0f840 --- /dev/null +++ b/kubi/src/rendering/depth.rs @@ -0,0 +1,67 @@ +use glam::{uvec2, UVec2}; + +use super::Renderer; + +pub struct DepthTexture { + pub depth_texture: wgpu::Texture, + pub depth_view: wgpu::TextureView, + pub depth_sampler: wgpu::Sampler, +} + +impl DepthTexture { + fn desc(size: UVec2) -> wgpu::TextureDescriptor<'static> { + wgpu::TextureDescriptor { + label: Some("depth_texture"), + size: wgpu::Extent3d { + width: size.x, + height: size.y, + depth_or_array_layers: 1, + }, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::Depth32Float, + usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING, + view_formats: &[wgpu::TextureFormat::Depth32Float], + } + } + + pub fn init(renderer: &Renderer) -> Self { + let size = uvec2(renderer.size().width, renderer.size().height); + let depth_texture_desc = Self::desc(size); + let depth_texture = renderer.device().create_texture(&depth_texture_desc); + let depth_view = depth_texture.create_view(&wgpu::TextureViewDescriptor::default()); + let depth_sampler = renderer.device().create_sampler(&wgpu::SamplerDescriptor { + label: Some("depth_sampler"), + address_mode_u: wgpu::AddressMode::ClampToEdge, + address_mode_v: wgpu::AddressMode::ClampToEdge, + address_mode_w: wgpu::AddressMode::ClampToEdge, + mag_filter: wgpu::FilterMode::Nearest, + min_filter: wgpu::FilterMode::Nearest, + mipmap_filter: wgpu::FilterMode::Nearest, + compare: Some(wgpu::CompareFunction::LessEqual), + ..Default::default() + }); + Self { depth_texture, depth_view, depth_sampler } + } + + pub fn resize(&mut self, renderer: &Renderer) { + let old_size = uvec2(self.depth_texture.size().width, self.depth_texture.size().height); + let new_size = uvec2(renderer.size().width, renderer.size().height); + if old_size == new_size { return } + let depth_texture_desc = Self::desc(new_size); + self.depth_texture = renderer.device().create_texture(&depth_texture_desc); + self.depth_view = self.depth_texture.create_view(&wgpu::TextureViewDescriptor::default()); + } +} + +pub fn init_depth_texture(renderer: &Renderer) -> DepthTexture { + DepthTexture::init(renderer) +} + +pub fn resize_depth_texture( + renderer: &Renderer, + depth_texture: &mut DepthTexture, +) { + depth_texture.resize(renderer); +} From 6f25cb728fe1164ae98b6a438965833e0699fd09 Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Mon, 6 May 2024 16:24:44 +0200 Subject: [PATCH 27/51] remove `WindowSize` --- kubi/src/camera/matrices.rs | 9 +++++---- kubi/src/hui_integration.rs | 2 +- kubi/src/input.rs | 6 +++--- kubi/src/lib.rs | 7 ------- kubi/src/rendering.rs | 34 ++++++++++++++++---------------- kubi/src/rendering/renderer.rs | 8 ++++++++ kubi/src/ui/chat_ui.rs | 6 +++--- kubi/src/ui/connecting_screen.rs | 6 +++--- kubi/src/ui/crosshair_ui.rs | 9 ++++++--- kubi/src/ui/loading_screen.rs | 6 +++--- kubi/src/ui/settings_ui.rs | 6 +++--- 11 files changed, 52 insertions(+), 47 deletions(-) diff --git a/kubi/src/camera/matrices.rs b/kubi/src/camera/matrices.rs index 2309724..6230447 100644 --- a/kubi/src/camera/matrices.rs +++ b/kubi/src/camera/matrices.rs @@ -1,6 +1,6 @@ use glam::{Vec3, Mat4}; use shipyard::{ViewMut, View, IntoIter, Workload, IntoWorkload, track, UniqueView, SystemModificator}; -use crate::{transform::Transform, rendering::WindowSize, events::WindowResizedEvent}; +use crate::{transform::Transform, rendering::Renderer, events::WindowResizedEvent}; use super::Camera; //maybe parallelize these two? @@ -18,14 +18,15 @@ fn update_view_matrix( fn update_perspective_matrix( mut vm_camera: ViewMut, - size: UniqueView, + ren: UniqueView, ) { + let sz = ren.size_vec2(); for mut camera in (&mut vm_camera).iter() { camera.perspective_matrix = Mat4::perspective_rh( camera.fov, - size.0.x as f32 / size.0.y as f32, + sz.x / sz.y, camera.z_near, - camera.z_far, + camera.z_far, ) } } diff --git a/kubi/src/hui_integration.rs b/kubi/src/hui_integration.rs index 15b862c..95fcfae 100644 --- a/kubi/src/hui_integration.rs +++ b/kubi/src/hui_integration.rs @@ -1,7 +1,7 @@ use hui::UiInstance; //use hui_glium::GliumUiRenderer; use shipyard::{AllStoragesView, Unique, UniqueView, NonSendSync, UniqueViewMut}; -use crate::rendering::{Renderer, WindowSize}; +use crate::rendering::Renderer; #[derive(Unique)] pub struct UiState { diff --git a/kubi/src/input.rs b/kubi/src/input.rs index c24081e..1cfcf57 100644 --- a/kubi/src/input.rs +++ b/kubi/src/input.rs @@ -10,7 +10,7 @@ use nohash_hasher::BuildNoHashHasher; use shipyard::{AllStoragesView, Unique, View, IntoIter, UniqueViewMut, Workload, IntoWorkload, UniqueView, NonSendSync}; use crate::{ events::{InputDeviceEvent, TouchEvent}, - rendering::WindowSize + rendering::Renderer, }; #[derive(Unique, Clone, Copy, Default, Debug)] @@ -211,10 +211,10 @@ fn update_input_state_gamepad ( fn update_input_state_touch ( touch_state: UniqueView, - win_size: UniqueView, + renderer: UniqueView, mut inputs: UniqueViewMut, ) { - let w = win_size.0.as_dvec2(); + let w = renderer.size_uvec2().as_dvec2(); //Movement if let Some(finger) = touch_state.query_area( diff --git a/kubi/src/lib.rs b/kubi/src/lib.rs index ba75b14..2bb336d 100644 --- a/kubi/src/lib.rs +++ b/kubi/src/lib.rs @@ -75,15 +75,10 @@ use events::{ }; use input::{init_input, process_inputs}; use player_controller::{debug_switch_ctl_type, update_player_controllers}; -// use rendering::{ -// clear_background, entities::render_entities, init_window_size, primitives::init_primitives, resize_renderer, selection_box::render_selection_box, sumberge::render_submerged_view, update_window_size, world::{draw_current_chunk_border, draw_world, draw_world_trans, init_trans_chunk_queue}, BackgroundColor, RenderTarget, Renderer -// }; use rendering::{ init_render_states, - init_window_size, render_master, resize_renderer, - update_window_size, BackgroundColor, Renderer, }; use block_placement::update_block_placement; @@ -116,7 +111,6 @@ fn startup() -> Workload { ( init_fixed_timestamp_storage, initial_resize_event, - init_window_size, kubi_ui_init, load_prefabs, init_render_states, @@ -136,7 +130,6 @@ fn startup() -> Workload { fn update() -> Workload { ( debug_toggle_lock, - update_window_size, resize_renderer, update_cursor_lock_state, process_inputs, diff --git a/kubi/src/rendering.rs b/kubi/src/rendering.rs index 215e597..e34f7b0 100644 --- a/kubi/src/rendering.rs +++ b/kubi/src/rendering.rs @@ -129,25 +129,25 @@ pub fn resize_renderer( //Deprecated WindowSize thingy -#[derive(Unique, Clone, Copy)] -#[repr(transparent)] -#[deprecated = "use Renderer.size instead"] -#[allow(deprecated)] -pub struct WindowSize(pub UVec2); +// #[derive(Unique, Clone, Copy)] +// #[repr(transparent)] +// #[deprecated = "use Renderer.size instead"] +// #[allow(deprecated)] +// pub struct WindowSize(pub UVec2); -pub fn init_window_size(storages: AllStoragesView) { - let size = storages.borrow::>().unwrap().iter().next().unwrap().0; - storages.add_unique(WindowSize(size)) -} +// pub fn init_window_size(storages: AllStoragesView) { +// let size = storages.borrow::>().unwrap().iter().next().unwrap().0; +// storages.add_unique(WindowSize(size)) +// } -pub fn update_window_size( - mut win_size: UniqueViewMut, - resize: View, -) { - if let Some(resize) = resize.iter().next() { - win_size.0 = resize.0; - } -} +// pub fn update_window_size( +// mut win_size: UniqueViewMut, +// resize: View, +// ) { +// if let Some(resize) = resize.iter().next() { +// win_size.0 = resize.0; +// } +// } // pub fn if_resized ( // resize: View, diff --git a/kubi/src/rendering/renderer.rs b/kubi/src/rendering/renderer.rs index 4cecbf9..8b4bf91 100644 --- a/kubi/src/rendering/renderer.rs +++ b/kubi/src/rendering/renderer.rs @@ -143,6 +143,14 @@ impl Renderer { self.size } + pub fn size_uvec2(&self) -> glam::UVec2 { + glam::UVec2::new(self.size.width, self.size.height) + } + + pub fn size_vec2(&self) -> glam::Vec2 { + glam::Vec2::new(self.size.width as f32, self.size.height as f32) + } + pub fn window(&self) -> &Window { &self.window } diff --git a/kubi/src/ui/chat_ui.rs b/kubi/src/ui/chat_ui.rs index d419ed6..0c34131 100644 --- a/kubi/src/ui/chat_ui.rs +++ b/kubi/src/ui/chat_ui.rs @@ -1,10 +1,10 @@ use hui::{color, element::{container::Container, text::Text, UiElementExt}, layout::Alignment, size}; use shipyard::{NonSendSync, UniqueView, UniqueViewMut}; -use crate::{chat::{ChatHistory, ChatMessage}, hui_integration::UiState, rendering::WindowSize}; +use crate::{chat::{ChatHistory, ChatMessage}, hui_integration::UiState, rendering::Renderer}; pub fn render_chat( mut hui: NonSendSync>, - size: UniqueView, + ren: UniqueView, chat: UniqueView, ) { let messages = chat.get_messages(); @@ -39,5 +39,5 @@ pub fn render_chat( .add_child(ui); } }) - .add_root(&mut hui.hui, size.0.as_vec2()); + .add_root(&mut hui.hui, ren.size_vec2()); } diff --git a/kubi/src/ui/connecting_screen.rs b/kubi/src/ui/connecting_screen.rs index 0ceab5f..d01ad5d 100644 --- a/kubi/src/ui/connecting_screen.rs +++ b/kubi/src/ui/connecting_screen.rs @@ -5,7 +5,7 @@ use crate::{ hui_integration::UiState, loading_screen::loading_screen_base, networking::{ConnectionRejectionReason, ServerAddress}, - rendering::WindowSize, + rendering::Renderer, state::{GameState, NextState} }; @@ -14,7 +14,7 @@ fn render_connecting_ui( rejection: Option>, join_state: UniqueView, mut ui: NonSendSync>, - size: UniqueView, + ren: UniqueView, ) { let text = match (rejection, *join_state) { (Some(err), _) => { @@ -32,7 +32,7 @@ fn render_connecting_ui( Text::new(text) .with_text_size(16) .add_child(ui); - }).add_root(&mut ui.hui, size.0.as_vec2()) + }).add_root(&mut ui.hui, ren.size_vec2()) } fn switch_to_loading_if_connected( diff --git a/kubi/src/ui/crosshair_ui.rs b/kubi/src/ui/crosshair_ui.rs index 353429e..39df924 100644 --- a/kubi/src/ui/crosshair_ui.rs +++ b/kubi/src/ui/crosshair_ui.rs @@ -6,7 +6,7 @@ use hui::{ size }; use shipyard::{AllStoragesViewMut, IntoIter, NonSendSync, Unique, UniqueView, UniqueViewMut, View}; -use crate::{hui_integration::UiState, player::MainPlayer, rendering::WindowSize, settings::GameSettings, world::raycast::LookingAtBlock}; +use crate::{hui_integration::UiState, player::MainPlayer, rendering::Renderer, settings::GameSettings, world::raycast::LookingAtBlock}; const CROSSHAIR_SIZE: usize = 9; const CROSSHAIR: &[u8] = &[ @@ -45,7 +45,7 @@ pub fn init_crosshair_image(storages: AllStoragesViewMut) { pub fn draw_crosshair( mut ui: NonSendSync>, crosshair: UniqueView, - size: UniqueView, + ren: UniqueView, player: View, raycast: View, settings: UniqueView, @@ -57,6 +57,9 @@ pub fn draw_crosshair( } } + let size = ren.size_uvec2(); + let size_rounded = uvec2(size.x & !1, size.y & !1).as_vec2(); + Container::default() .with_size(size!(100%)) .with_align(Alignment::Center) @@ -66,5 +69,5 @@ pub fn draw_crosshair( .with_size(size!((CROSSHAIR_SIZE * 2))) .add_child(ui); }) - .add_root(&mut ui.hui, uvec2(size.0.x & !1, size.0.y & !1).as_vec2()); + .add_root(&mut ui.hui, size_rounded); } diff --git a/kubi/src/ui/loading_screen.rs b/kubi/src/ui/loading_screen.rs index be71392..df03aec 100644 --- a/kubi/src/ui/loading_screen.rs +++ b/kubi/src/ui/loading_screen.rs @@ -15,7 +15,7 @@ use crate::{ hui_integration::UiState, input::RawKbmInputState, networking::ServerAddress, - rendering::WindowSize, + rendering::Renderer, state::{GameState, NextState}, world::ChunkStorage, }; @@ -43,7 +43,7 @@ fn render_loading_ui( addr: Option>, world: UniqueView, mut ui: NonSendSync>, - size: UniqueView + ren: UniqueView, ) { let loaded = world.chunks.iter().fold(0, |acc, (&_, chunk)| { acc + chunk.desired_state.matches_current(chunk.current_state) as usize @@ -83,7 +83,7 @@ fn render_loading_ui( .add_child(ui) }) .add_child(ui); - }).add_root(&mut ui.hui, size.0.as_vec2()); + }).add_root(&mut ui.hui, ren.size_vec2()); } fn switch_to_ingame_if_loaded( diff --git a/kubi/src/ui/settings_ui.rs b/kubi/src/ui/settings_ui.rs index b863da8..6211c6d 100644 --- a/kubi/src/ui/settings_ui.rs +++ b/kubi/src/ui/settings_ui.rs @@ -6,7 +6,7 @@ use hui::{ }; use shipyard::{NonSendSync, UniqueView, UniqueViewMut}; use winit::keyboard::KeyCode; -use crate::{hui_integration::UiState, input::RawKbmInputState, rendering::WindowSize, settings::GameSettings}; +use crate::{hui_integration::UiState, input::RawKbmInputState, rendering::Renderer, settings::GameSettings}; #[derive(Signal)] enum SettingsSignal { @@ -18,7 +18,7 @@ enum SettingsSignal { pub fn render_settings_ui( mut ui: NonSendSync>, - size: UniqueView, + ren: UniqueView, mut settings: UniqueViewMut, kbd: UniqueView, ) { @@ -99,7 +99,7 @@ pub fn render_settings_ui( }) .add_child(ui); }) - .add_root(&mut ui.hui, size.0.as_vec2()); + .add_root(&mut ui.hui, ren.size_vec2()); ui.hui.process_signals(|signal: SettingsSignal| match signal { SettingsSignal::SetRenderDistance(value) => settings.render_distance = value, From 8a4549efeaa8f9a940fb3f2ec546b3d1e618f987 Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Mon, 6 May 2024 16:53:40 +0200 Subject: [PATCH 28/51] restructure stuff and fix some warnings --- kubi-shared/src/worldgen/steps/_04_layers.rs | 1 - kubi/src/chat.rs | 2 +- kubi/src/client_physics.rs | 4 +- kubi/src/events.rs | 24 ++++---- kubi/src/lib.rs | 32 ++++------ kubi/src/rendering.rs | 61 ++++++-------------- kubi/src/rendering/camera.rs | 2 +- kubi/src/rendering/depth.rs | 15 +++-- 8 files changed, 56 insertions(+), 85 deletions(-) diff --git a/kubi-shared/src/worldgen/steps/_04_layers.rs b/kubi-shared/src/worldgen/steps/_04_layers.rs index f6d873d..52204b9 100644 --- a/kubi-shared/src/worldgen/steps/_04_layers.rs +++ b/kubi-shared/src/worldgen/steps/_04_layers.rs @@ -1,4 +1,3 @@ -use fastnoise_lite::FastNoiseLite; use glam::ivec3; use crate::{block::Block, chunk::CHUNK_SIZE, worldgen::SeedThingy}; use super::{ diff --git a/kubi/src/chat.rs b/kubi/src/chat.rs index 24b1949..90f4ee1 100644 --- a/kubi/src/chat.rs +++ b/kubi/src/chat.rs @@ -1,5 +1,5 @@ use kubi_shared::networking::client::ClientId; -use shipyard::{AllStoragesView, Unique, UniqueViewMut}; +use shipyard::{AllStoragesView, Unique}; pub enum ChatMessage { PlayerMessage { diff --git a/kubi/src/client_physics.rs b/kubi/src/client_physics.rs index ac79175..f6ef9e6 100644 --- a/kubi/src/client_physics.rs +++ b/kubi/src/client_physics.rs @@ -1,7 +1,7 @@ //TODO client-side physics //TODO move this to shared -use glam::{vec3, IVec3, Mat4, Vec3, Vec3Swizzles}; -use shipyard::{track, AllStoragesView, Component, IntoIter, Unique, UniqueView, View, ViewMut}; +use glam::{vec3, Mat4, Vec3, Vec3Swizzles}; +use shipyard::{track, AllStoragesView, Component, IntoIter, Unique, UniqueView, ViewMut}; use kubi_shared::{block::{Block, CollisionType}, transform::Transform}; use crate::{delta_time::DeltaTime, world::ChunkStorage}; diff --git a/kubi/src/events.rs b/kubi/src/events.rs index 84bad45..fcd4c83 100644 --- a/kubi/src/events.rs +++ b/kubi/src/events.rs @@ -86,18 +86,18 @@ pub fn process_winit_events(world: &mut World, event: &Event<()>) { } } -pub fn initial_resize_event( - mut storages: AllStoragesViewMut, -) { - let (w, h) = { - let renderer = storages.borrow::>>().unwrap(); - (renderer.size().width, renderer.size().height) - }; - storages.add_entity(( - EventComponent, - WindowResizedEvent(UVec2::new(w, h)) - )); -} +// pub fn initial_resize_event( +// mut storages: AllStoragesViewMut, +// ) { +// let (w, h) = { +// let renderer = storages.borrow::>>().unwrap(); +// (renderer.size().width, renderer.size().height) +// }; +// storages.add_entity(( +// EventComponent, +// WindowResizedEvent(UVec2::new(w, h)) +// )); +// } pub fn clear_events( mut all_storages: AllStoragesViewMut, diff --git a/kubi/src/lib.rs b/kubi/src/lib.rs index 2bb336d..b59a073 100644 --- a/kubi/src/lib.rs +++ b/kubi/src/lib.rs @@ -13,7 +13,7 @@ use shipyard::{ World, Workload, IntoWorkload, UniqueView, UniqueViewMut, - NonSendSync, WorkloadModificator, + WorkloadModificator, SystemModificator }; use winit::{ @@ -58,29 +58,19 @@ pub(crate) mod chat; use world::{ init_game_world, - loading::update_loaded_world_around_player, + loading::update_loaded_world_around_player, raycast::update_raycasts, - queue::apply_queued_blocks, + queue::apply_queued_blocks, tasks::ChunkTaskManager, }; use player::{spawn_player, MainPlayer}; use prefabs::load_prefabs; use settings::{load_settings, GameSettings}; use camera::compute_cameras; -use events::{ - clear_events, - process_winit_events, - initial_resize_event, - player_actions::generate_move_events, -}; +use events::{clear_events, process_winit_events, player_actions::generate_move_events}; use input::{init_input, process_inputs}; use player_controller::{debug_switch_ctl_type, update_player_controllers}; -use rendering::{ - init_render_states, - render_master, - resize_renderer, - BackgroundColor, Renderer, -}; +use rendering::{BackgroundColor, Renderer, init_rendering, render_master, update_rendering_early, update_rendering_late}; use block_placement::update_block_placement; use delta_time::{DeltaTime, init_delta_time}; use cursor_lock::{debug_toggle_lock, insert_lock_state, lock_cursor_now, update_cursor_lock_state}; @@ -110,10 +100,9 @@ fn pre_startup() -> Workload { fn startup() -> Workload { ( init_fixed_timestamp_storage, - initial_resize_event, kubi_ui_init, load_prefabs, - init_render_states, + init_rendering, insert_lock_state, init_state, initialize_from_args, @@ -129,8 +118,8 @@ fn startup() -> Workload { fn update() -> Workload { ( + update_rendering_early, debug_toggle_lock, - resize_renderer, update_cursor_lock_state, process_inputs, kubi_ui_begin, @@ -169,6 +158,7 @@ fn update() -> Workload { update_state, exit_on_esc, disconnect_on_exit.run_if(is_multiplayer), + update_rendering_late, ).into_sequential_workload() } @@ -187,7 +177,7 @@ fn update() -> Workload { // ).into_sequential_workload() // } -fn after_frame_end() -> Workload { +fn after_render() -> Workload { ( clear_events, ).into_sequential_workload() @@ -236,7 +226,7 @@ pub fn kubi_main( world.add_workload(startup); world.add_workload(update); //world.add_workload(render); - world.add_workload(after_frame_end); + world.add_workload(after_render); //Save _visualizer.json #[cfg(feature = "generate_visualizer_data")] @@ -333,7 +323,7 @@ pub fn kubi_main( // target.0.finish().unwrap(); //After frame end - world.run_workload(after_frame_end).unwrap(); + world.run_workload(after_render).unwrap(); //Process control flow changes if world.borrow::>().unwrap().0 { diff --git a/kubi/src/rendering.rs b/kubi/src/rendering.rs index e34f7b0..a7caa31 100644 --- a/kubi/src/rendering.rs +++ b/kubi/src/rendering.rs @@ -1,53 +1,17 @@ -use shipyard::{AllStoragesView, AllStoragesViewMut, IntoIter, IntoWorkload, Unique, UniqueView, UniqueViewMut, View, Workload}; +use shipyard::{AllStoragesViewMut, IntoIter, IntoWorkload, SystemModificator, Unique, UniqueView, UniqueViewMut, View, Workload, WorkloadModificator}; use winit::dpi::PhysicalSize; -use glam::{mat4, vec4, Mat4, UVec2, Vec3}; +use glam::Vec3; use crate::{events::WindowResizedEvent, state::is_ingame}; mod renderer; pub use renderer::Renderer; -use self::camera::update_camera_unform_buffer; +use self::{camera::CameraUniformBuffer, world::WorldRenderState}; pub mod world; pub mod camera; pub mod depth; -//pub mod primitives; -//pub mod selection_box; -//pub mod entities; -//pub mod sumberge; - -// pub const WGPU_COORDINATE_SYSTEM: Mat4 = mat4( -// vec4(1.0, 0.0, 0.0, 0.0), -// vec4(0.0, 1.0, 0.0, 0.0), -// vec4(0.0, 0.0, 0.5, 0.5), -// vec4(0.0, 0.0, 0.0, 1.0), -// ); - -// #[repr(C)] -// #[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] -// struct TrasnformUniformData { -// pub transform: [[f32; 4]; 4], -// } - -// impl TrasnformUniformData { -// pub const LAYOUT: &wgpu::Layou -// } - -// impl From for TrasnformUniformData { -// fn from(mat: Mat4) -> Self { -// Self { -// transform: mat.to_cols_array_2d(), -// } -// } -// } - -// impl From for TrasnformUniformData { -// fn from(value: Transform) -> Self { -// value.0.into() -// } -// } - pub struct BufferPair { pub index: wgpu::Buffer, pub index_len: u32, @@ -64,10 +28,24 @@ pub struct RenderCtx<'a> { pub surface_view: &'a wgpu::TextureView, } -pub fn init_render_states() -> Workload { +pub fn init_rendering() -> Workload { ( + depth::init_depth_texture, camera::init_camera_uniform_buffer, - world::init_world_render_state, + world::init_world_render_state, //TODO run only once ingame + ).into_sequential_workload() +} + +pub fn update_rendering_early() -> Workload { + ( + resize_renderer, + depth::resize_depth_texture, + ).into_sequential_workload() +} + +pub fn update_rendering_late() -> Workload { + ( + camera::update_camera_uniform_buffer, ).into_workload() } @@ -109,7 +87,6 @@ pub fn render_master(storages: AllStoragesViewMut) { }; if storages.run(is_ingame) { - //TODO init world render state on demand storages.run_with_data(world::draw_world, &mut data); } diff --git a/kubi/src/rendering/camera.rs b/kubi/src/rendering/camera.rs index 918f224..8cd815b 100644 --- a/kubi/src/rendering/camera.rs +++ b/kubi/src/rendering/camera.rs @@ -72,7 +72,7 @@ pub fn init_camera_uniform_buffer(storages: AllStoragesView) { storages.add_unique(CameraUniformBuffer::init_default(&renderer)); } -pub fn update_camera_unform_buffer( +pub fn update_camera_uniform_buffer( renderer: UniqueView, camera_uniform_buffer: UniqueView, camera: View, diff --git a/kubi/src/rendering/depth.rs b/kubi/src/rendering/depth.rs index 6c0f840..830b10c 100644 --- a/kubi/src/rendering/depth.rs +++ b/kubi/src/rendering/depth.rs @@ -1,7 +1,9 @@ use glam::{uvec2, UVec2}; +use shipyard::{AllStoragesView, Unique, UniqueView, UniqueViewMut}; use super::Renderer; +#[derive(Unique)] pub struct DepthTexture { pub depth_texture: wgpu::Texture, pub depth_view: wgpu::TextureView, @@ -55,13 +57,16 @@ impl DepthTexture { } } -pub fn init_depth_texture(renderer: &Renderer) -> DepthTexture { - DepthTexture::init(renderer) +pub fn init_depth_texture( + storages: AllStoragesView, +) { + let renderer = storages.borrow::>().unwrap(); + storages.add_unique(DepthTexture::init(&renderer)); } pub fn resize_depth_texture( - renderer: &Renderer, - depth_texture: &mut DepthTexture, + mut depth_texture: UniqueViewMut, + renderer: UniqueView, ) { - depth_texture.resize(renderer); + depth_texture.resize(&renderer); } From 6e9e3fa445d94c4ac7e3eaba1373bab1bc7056ba Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Mon, 6 May 2024 17:09:13 +0200 Subject: [PATCH 29/51] enable depth texture --- kubi/src/rendering/world.rs | 15 ++++++++++++--- kubi/src/rendering/world/pipeline.rs | 13 ++++++++++--- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/kubi/src/rendering/world.rs b/kubi/src/rendering/world.rs index 829705c..3df4b11 100644 --- a/kubi/src/rendering/world.rs +++ b/kubi/src/rendering/world.rs @@ -7,7 +7,7 @@ use crate::{ settings::GameSettings, world::{ChunkMeshStorage, ChunkStorage}, }; -use super::{camera::{self, CameraUniformBuffer}, RenderCtx}; +use super::{camera::{self, CameraUniformBuffer}, depth::DepthTexture, RenderCtx}; mod pipeline; mod vertex; @@ -29,12 +29,13 @@ pub fn init_world_render_state(storages: AllStoragesView) { pub fn draw_world( ctx: &mut RenderCtx, mut state: UniqueViewMut, + camera_ubo: UniqueView, + depth: UniqueView, textures: UniqueView, camera: View, chunks: UniqueView, meshes: NonSendSync>, - camera_ubo: UniqueView, - settings: UniqueView, + //settings: UniqueView, ) { let camera = camera.iter().next().expect("No cameras in the scene"); @@ -48,6 +49,14 @@ pub fn draw_world( store: wgpu::StoreOp::Store, }, })], + depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment { + view: &depth.depth_view, + depth_ops: Some(wgpu::Operations { + load: wgpu::LoadOp::Clear(1.0), + store: wgpu::StoreOp::Store, + }), + stencil_ops: None, + }), ..Default::default() }); diff --git a/kubi/src/rendering/world/pipeline.rs b/kubi/src/rendering/world/pipeline.rs index 80fe6b1..040ed4d 100644 --- a/kubi/src/rendering/world/pipeline.rs +++ b/kubi/src/rendering/world/pipeline.rs @@ -1,11 +1,12 @@ -use shipyard::{Unique, UniqueView}; +use shipyard::UniqueView; use crate::{ prefabs::TexturePrefabs, - rendering::{camera::CameraUniformBuffer, world::ChunkVertex, Renderer} + rendering::{camera::CameraUniformBuffer, depth::DepthTexture, world::ChunkVertex, Renderer} }; pub fn init_world_pipeline( ren: UniqueView, + depth: UniqueView, textures: UniqueView, camera_ubo: UniqueView, ) -> wgpu::RenderPipeline { @@ -52,7 +53,13 @@ pub fn init_world_pipeline( polygon_mode: wgpu::PolygonMode::Fill, conservative: false, }, - depth_stencil: None, + depth_stencil: Some(wgpu::DepthStencilState { + format: depth.depth_texture.format(), + depth_write_enabled: true, + depth_compare: wgpu::CompareFunction::Less, + stencil: wgpu::StencilState::default(), + bias: wgpu::DepthBiasState::default(), + }), multisample: wgpu::MultisampleState::default(), multiview: None, }) From 85c64c90644147018c8d4d80cebf091db6d1a954 Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Mon, 6 May 2024 17:19:11 +0200 Subject: [PATCH 30/51] flip uvs --- kubi/src/world/mesh/builder.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kubi/src/world/mesh/builder.rs b/kubi/src/world/mesh/builder.rs index 88cddf5..708d5f3 100644 --- a/kubi/src/world/mesh/builder.rs +++ b/kubi/src/world/mesh/builder.rs @@ -79,10 +79,10 @@ const CROSS_FACE_INDICES: [u32; 12] = [ const UV_COORDS: [[f32; 2]; 4] = [ - [0., 0.], [0., 1.], - [1., 0.], + [0., 0.], [1., 1.], + [1., 0.], ]; #[derive(Default)] From 99cc2d1e72609db2e116a3accc2b3aebd3aa3275 Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Mon, 6 May 2024 17:21:18 +0200 Subject: [PATCH 31/51] enable all backends --- kubi/src/rendering/renderer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kubi/src/rendering/renderer.rs b/kubi/src/rendering/renderer.rs index 8b4bf91..5028b70 100644 --- a/kubi/src/rendering/renderer.rs +++ b/kubi/src/rendering/renderer.rs @@ -75,7 +75,7 @@ impl Renderer { let size = window.inner_size(); let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { - backends: wgpu::Backends::BROWSER_WEBGPU | wgpu::Backends::VULKAN | wgpu::Backends::GL, + backends: wgpu::Backends::all(), //Disable validation layer flags: wgpu::InstanceFlags::default() & !wgpu::InstanceFlags::VALIDATION, //we're using vulkan on windows From 811bd8d8b414888794ce336582123c24030e27f0 Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Mon, 6 May 2024 17:38:58 +0200 Subject: [PATCH 32/51] use linear for min --- kubi/shaders/world.wgsl | 2 +- kubi/src/prefabs.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/kubi/shaders/world.wgsl b/kubi/shaders/world.wgsl index d9b6069..185b3bd 100644 --- a/kubi/shaders/world.wgsl +++ b/kubi/shaders/world.wgsl @@ -40,7 +40,7 @@ var s_diffuse: sampler; @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4 { let color: vec4 = textureSample(t_diffuse, s_diffuse, in.uv, in.tex_index); - if (color.a == 0.) { + if (color.a < 0.5) { discard; } return color; diff --git a/kubi/src/prefabs.rs b/kubi/src/prefabs.rs index 08bd3e9..9932999 100644 --- a/kubi/src/prefabs.rs +++ b/kubi/src/prefabs.rs @@ -70,7 +70,7 @@ pub fn load_prefabs( address_mode_v: wgpu::AddressMode::ClampToEdge, address_mode_w: wgpu::AddressMode::ClampToEdge, mag_filter: wgpu::FilterMode::Nearest, - min_filter: wgpu::FilterMode::Nearest, //TODO min_filter Linear, requires filtering sampler + min_filter: wgpu::FilterMode::Linear, mipmap_filter: wgpu::FilterMode::Nearest, ..Default::default() }); @@ -82,7 +82,7 @@ pub fn load_prefabs( binding: 0, visibility: wgpu::ShaderStages::FRAGMENT, ty: wgpu::BindingType::Texture { - sample_type: wgpu::TextureSampleType::Float { filterable: false }, + sample_type: wgpu::TextureSampleType::Float { filterable: true }, view_dimension: wgpu::TextureViewDimension::D2Array, multisampled: false, }, @@ -91,7 +91,7 @@ pub fn load_prefabs( wgpu::BindGroupLayoutEntry { binding: 1, visibility: wgpu::ShaderStages::FRAGMENT, - ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::NonFiltering), + ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), count: None, } ] From d738b228f2b1bbc9bd25fad7599994d615c2cd4a Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Mon, 6 May 2024 18:07:29 +0200 Subject: [PATCH 33/51] fix compilation for android --- kubi/src/events.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kubi/src/events.rs b/kubi/src/events.rs index fcd4c83..4bed070 100644 --- a/kubi/src/events.rs +++ b/kubi/src/events.rs @@ -41,7 +41,7 @@ pub fn process_winit_events(world: &mut World, event: &Event<()>) { EventComponent, InputDeviceEvent { device_id: *device_id, - event: DeviceEvent::Key(RawKeyEvent { + event: DeviceEvent::Key(winit::event::RawKeyEvent { physical_key: event.physical_key, state: event.state, }) From c8cacafab5fbd76a83b2581ddd72d3a5cc13bdc8 Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Mon, 6 May 2024 18:21:19 +0200 Subject: [PATCH 34/51] use default limits --- kubi/src/rendering/renderer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kubi/src/rendering/renderer.rs b/kubi/src/rendering/renderer.rs index 5028b70..c491e0f 100644 --- a/kubi/src/rendering/renderer.rs +++ b/kubi/src/rendering/renderer.rs @@ -107,7 +107,7 @@ impl Renderer { &wgpu::DeviceDescriptor { label: None, required_features: wgpu::Features::empty(), - required_limits: wgpu::Limits::downlevel_defaults(), + required_limits: wgpu::Limits::default(), }, None, ).block_on().unwrap(); From 196a7010b6dc4365e240fad51e50fd85f0853425 Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Tue, 7 May 2024 00:13:14 +0200 Subject: [PATCH 35/51] separate clear_bg pass --- kubi/src/rendering.rs | 30 ++++-------------------------- kubi/src/rendering/background.rs | 25 +++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 26 deletions(-) create mode 100644 kubi/src/rendering/background.rs diff --git a/kubi/src/rendering.rs b/kubi/src/rendering.rs index a7caa31..5593aae 100644 --- a/kubi/src/rendering.rs +++ b/kubi/src/rendering.rs @@ -1,4 +1,4 @@ -use shipyard::{AllStoragesViewMut, IntoIter, IntoWorkload, SystemModificator, Unique, UniqueView, UniqueViewMut, View, Workload, WorkloadModificator}; +use shipyard::{AllStoragesViewMut, IntoIter, IntoWorkload, Unique, UniqueView, UniqueViewMut, View, Workload, WorkloadModificator}; use winit::dpi::PhysicalSize; use glam::Vec3; use crate::{events::WindowResizedEvent, state::is_ingame}; @@ -6,8 +6,7 @@ use crate::{events::WindowResizedEvent, state::is_ingame}; mod renderer; pub use renderer::Renderer; -use self::{camera::CameraUniformBuffer, world::WorldRenderState}; - +pub mod background; pub mod world; pub mod camera; pub mod depth; @@ -58,39 +57,18 @@ pub fn render_master(storages: AllStoragesViewMut) { let surface_texture = renderer.surface().get_current_texture().unwrap(); let surface_view = surface_texture.texture.create_view(&wgpu::TextureViewDescriptor::default()); - { - let bg = storages.borrow::>().unwrap().0; - let _render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { - label: Some("rpass_background"), - color_attachments: &[Some(wgpu::RenderPassColorAttachment { - view: &surface_view, - resolve_target: None, - ops: wgpu::Operations { - load: wgpu::LoadOp::Clear(wgpu::Color { - r: bg.x as f64, - g: bg.y as f64, - b: bg.z as f64, - a: 1.0, - }), - store: wgpu::StoreOp::Store, - }, - })], - depth_stencil_attachment: None, - ..Default::default() - }); - } - let mut data = RenderCtx { renderer: &renderer, encoder: &mut encoder, surface_view: &surface_view, }; + storages.run_with_data(background::clear_bg, &mut data); if storages.run(is_ingame) { storages.run_with_data(world::draw_world, &mut data); } - renderer.queue().submit(std::iter::once(encoder.finish())); + renderer.queue().submit([encoder.finish()]); surface_texture.present(); } diff --git a/kubi/src/rendering/background.rs b/kubi/src/rendering/background.rs new file mode 100644 index 0000000..29240d2 --- /dev/null +++ b/kubi/src/rendering/background.rs @@ -0,0 +1,25 @@ +use shipyard::UniqueView; +use super::{BackgroundColor, RenderCtx}; + +pub fn clear_bg( + ctx: &mut RenderCtx, + bg: UniqueView, +) { + let _rpass = ctx.encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + label: Some("clear_bg"), + color_attachments: &[Some(wgpu::RenderPassColorAttachment { + view: ctx.surface_view, + resolve_target: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Clear(wgpu::Color { + r: bg.0.x as f64, + g: bg.0.y as f64, + b: bg.0.z as f64, + a: 1.0, + }), + store: wgpu::StoreOp::Store, + }, + })], + ..Default::default() + }); +} From 7aa91b64142ce949e400f1f27d8c82ff3b4370af Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Tue, 7 May 2024 01:11:05 +0200 Subject: [PATCH 36/51] add cube primitive --- kubi/src/rendering.rs | 32 ++----- kubi/src/rendering/primitives.rs | 46 ++++------ kubi/src/rendering/primitives/cube.rs | 126 +++++++++----------------- kubi/src/rendering/primitives/rect.rs | 31 ------- kubi/src/rendering/primitives/stri.rs | 30 ------ 5 files changed, 71 insertions(+), 194 deletions(-) delete mode 100644 kubi/src/rendering/primitives/rect.rs delete mode 100644 kubi/src/rendering/primitives/stri.rs diff --git a/kubi/src/rendering.rs b/kubi/src/rendering.rs index 5593aae..e194906 100644 --- a/kubi/src/rendering.rs +++ b/kubi/src/rendering.rs @@ -4,6 +4,7 @@ use glam::Vec3; use crate::{events::WindowResizedEvent, state::is_ingame}; mod renderer; +mod primitives; pub use renderer::Renderer; pub mod background; @@ -27,11 +28,14 @@ pub struct RenderCtx<'a> { pub surface_view: &'a wgpu::TextureView, } +//TODO run init_world_render_state only once ingame? + pub fn init_rendering() -> Workload { ( depth::init_depth_texture, camera::init_camera_uniform_buffer, - world::init_world_render_state, //TODO run only once ingame + world::init_world_render_state, //requires depth and camera buffers + primitives::init_primitives, ).into_sequential_workload() } @@ -82,30 +86,6 @@ pub fn resize_renderer( } } -//Deprecated WindowSize thingy - -// #[derive(Unique, Clone, Copy)] -// #[repr(transparent)] -// #[deprecated = "use Renderer.size instead"] -// #[allow(deprecated)] -// pub struct WindowSize(pub UVec2); - -// pub fn init_window_size(storages: AllStoragesView) { -// let size = storages.borrow::>().unwrap().iter().next().unwrap().0; -// storages.add_unique(WindowSize(size)) -// } - -// pub fn update_window_size( -// mut win_size: UniqueViewMut, -// resize: View, -// ) { -// if let Some(resize) = resize.iter().next() { -// win_size.0 = resize.0; -// } -// } - -// pub fn if_resized ( -// resize: View, -// ) -> bool { +// pub fn if_resized (resize: View,) -> bool { // resize.len() > 0 // } diff --git a/kubi/src/rendering/primitives.rs b/kubi/src/rendering/primitives.rs index 115ff49..8dfbfa4 100644 --- a/kubi/src/rendering/primitives.rs +++ b/kubi/src/rendering/primitives.rs @@ -1,30 +1,24 @@ -// use shipyard::{Workload, IntoWorkload}; -// use glium::implement_vertex; +use bytemuck::{Pod, Zeroable}; +use shipyard::{IntoWorkload, Workload}; -// pub mod cube; -// pub mod rect; -// pub mod stri; +mod cube; -// use cube::init_cube_primitive; -// use rect::init_rect_primitive; -// use stri::init_stri_primitive; +pub fn init_primitives() -> Workload { + ( + cube::init_cube_primitive, + ).into_workload() +} -// #[derive(Clone, Copy, Default)] -// pub struct PositionOnlyVertex { -// pub position: [f32; 3], -// } -// implement_vertex!(PositionOnlyVertex, position); +#[derive(Clone, Copy, Default, Pod, Zeroable)] +#[repr(C, packed)] +pub struct PrimitiveVertex { + pub position: [f32; 3], +} -// #[derive(Clone, Copy, Default)] -// pub struct PositionOnlyVertex2d { -// pub position: [f32; 2], -// } -// implement_vertex!(PositionOnlyVertex2d, position); - -// pub fn init_primitives() -> Workload { -// ( -// init_cube_primitive, -// init_rect_primitive, -// init_stri_primitive, -// ).into_workload() -// } +impl PrimitiveVertex { + pub const LAYOUT: wgpu::VertexBufferLayout<'static> = wgpu::VertexBufferLayout { + array_stride: std::mem::size_of::() as wgpu::BufferAddress, + step_mode: wgpu::VertexStepMode::Vertex, + attributes: &wgpu::vertex_attr_array![0 => Float32x3], + }; +} diff --git a/kubi/src/rendering/primitives/cube.rs b/kubi/src/rendering/primitives/cube.rs index 2e3b5c8..3abd3e2 100644 --- a/kubi/src/rendering/primitives/cube.rs +++ b/kubi/src/rendering/primitives/cube.rs @@ -1,85 +1,49 @@ -// use shipyard::{AllStoragesView, NonSendSync, UniqueView, Unique}; -// use glium::{VertexBuffer, IndexBuffer, index::PrimitiveType}; -// use crate::rendering::Renderer; -// use super::PositionOnlyVertex; +use shipyard::{AllStoragesView, Unique, UniqueView}; +use wgpu::util::DeviceExt; +use crate::rendering::{BufferPair, Renderer}; +use super::PrimitiveVertex; -// #[derive(Unique)] -// pub struct CubePrimitive(pub VertexBuffer, pub IndexBuffer); +#[derive(Unique)] +pub struct CubePrimitive(pub BufferPair); -// #[derive(Unique)] -// pub struct CenteredCubePrimitive(pub VertexBuffer, pub IndexBuffer); +/// Vertices for a centered cube with a side length of 1 +const CUBE_VERTICES: &[PrimitiveVertex] = &[ + // front + PrimitiveVertex { position: [-0.5, -0.5, 0.5] }, + PrimitiveVertex { position: [ 0.5, -0.5, 0.5] }, + PrimitiveVertex { position: [ 0.5, 0.5, 0.5] }, + PrimitiveVertex { position: [-0.5, 0.5, 0.5] }, + // back + PrimitiveVertex { position: [-0.5, -0.5, -0.5] }, + PrimitiveVertex { position: [ 0.5, -0.5, -0.5] }, + PrimitiveVertex { position: [ 0.5, 0.5, -0.5] }, + PrimitiveVertex { position: [-0.5, 0.5, -0.5] }, +]; -// const CENTERED_CUBE_VERTICES: &[PositionOnlyVertex] = &[ -// // front -// PositionOnlyVertex { position: [-0.5, -0.5, 0.5] }, -// PositionOnlyVertex { position: [ 0.5, -0.5, 0.5] }, -// PositionOnlyVertex { position: [ 0.5, 0.5, 0.5] }, -// PositionOnlyVertex { position: [-0.5, 0.5, 0.5] }, -// // back -// PositionOnlyVertex { position: [-0.5, -0.5, -0.5] }, -// PositionOnlyVertex { position: [ 0.5, -0.5, -0.5] }, -// PositionOnlyVertex { position: [ 0.5, 0.5, -0.5] }, -// PositionOnlyVertex { position: [-0.5, 0.5, -0.5] }, -// ]; -// const CUBE_VERTICES: &[PositionOnlyVertex] = &[ -// // front -// PositionOnlyVertex { position: [0.0, 0.0, 1.0] }, -// PositionOnlyVertex { position: [1.0, 0.0, 1.0] }, -// PositionOnlyVertex { position: [1.0, 1.0, 1.0] }, -// PositionOnlyVertex { position: [0.0, 1.0, 1.0] }, -// // back -// PositionOnlyVertex { position: [0.0, 0.0, 0.0] }, -// PositionOnlyVertex { position: [1.0, 0.0, 0.0] }, -// PositionOnlyVertex { position: [1.0, 1.0, 0.0] }, -// PositionOnlyVertex { position: [0.0, 1.0, 0.0] }, -// ]; -// const CUBE_INDICES: &[u16] = &[ -// // front -// 0, 1, 2, -// 2, 3, 0, -// // right -// 1, 5, 6, -// 6, 2, 1, -// // back -// 7, 6, 5, -// 5, 4, 7, -// // left -// 4, 0, 3, -// 3, 7, 4, -// // bottom -// 4, 5, 1, -// 1, 0, 4, -// // top -// 3, 2, 6, -// 6, 7, 3 -// ]; +/// Indices for a cube primitive +const CUBE_INDICES: &[u16] = &[ + 0, 1, 2, 2, 3, 0, // front + 1, 5, 6, 6, 2, 1, // right + 7, 6, 5, 5, 4, 7, // back + 4, 0, 3, 3, 7, 4, // left + 4, 5, 1, 1, 0, 4, // bottom + 3, 2, 6, 6, 7, 3, // top +]; -// pub(super) fn init_cube_primitive( -// storages: AllStoragesView, -// display: NonSendSync> -// ) { -// { -// let vert = VertexBuffer::immutable( -// &display.display, -// CUBE_VERTICES -// ).unwrap(); -// let index = IndexBuffer::immutable( -// &display.display, -// PrimitiveType::TrianglesList, -// CUBE_INDICES -// ).unwrap(); -// storages.add_unique_non_send_sync(CubePrimitive(vert, index)); -// } -// { -// let vert = VertexBuffer::immutable( -// &display.display, -// CENTERED_CUBE_VERTICES -// ).unwrap(); -// let index = IndexBuffer::immutable( -// &display.display, -// PrimitiveType::TrianglesList, -// CUBE_INDICES -// ).unwrap(); -// storages.add_unique_non_send_sync(CenteredCubePrimitive(vert, index)); -// } -// } +pub fn init_cube_primitive(storages: AllStoragesView) { + let renderer = storages.borrow::>().unwrap(); + storages.add_unique(CubePrimitive(BufferPair { + index: renderer.device().create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("cube_index_buffer"), + contents: bytemuck::cast_slice(CUBE_INDICES), + usage: wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::INDEX, + }), + index_len: CUBE_INDICES.len() as u32, + vertex: renderer.device().create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("cube_vertex_buffer"), + contents: bytemuck::cast_slice(CUBE_VERTICES), + usage: wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::VERTEX, + }), + vertex_len: CUBE_VERTICES.len() as u32, + })); +} diff --git a/kubi/src/rendering/primitives/rect.rs b/kubi/src/rendering/primitives/rect.rs deleted file mode 100644 index 4eca75c..0000000 --- a/kubi/src/rendering/primitives/rect.rs +++ /dev/null @@ -1,31 +0,0 @@ -// use shipyard::{Unique, AllStoragesView, NonSendSync, UniqueView}; -// use glium::{VertexBuffer, IndexBuffer, index::PrimitiveType}; -// use crate::rendering::Renderer; -// use super::PositionOnlyVertex2d; - -// #[derive(Unique)] -// pub struct RectPrimitive(pub VertexBuffer, pub IndexBuffer); - -// const RECT_VERTEX: &[PositionOnlyVertex2d] = &[ -// PositionOnlyVertex2d { position: [0., 0.] }, -// PositionOnlyVertex2d { position: [1., 0.] }, -// PositionOnlyVertex2d { position: [0., 1.] }, -// PositionOnlyVertex2d { position: [1., 1.] }, -// ]; -// const RECT_INDEX: &[u16] = &[0, 1, 2, 1, 3, 2]; - -// pub(super) fn init_rect_primitive( -// storages: AllStoragesView, -// display: NonSendSync> -// ) { -// let vert = VertexBuffer::immutable( -// &display.display, -// RECT_VERTEX -// ).unwrap(); -// let index = IndexBuffer::immutable( -// &display.display, -// PrimitiveType::TrianglesList, -// RECT_INDEX -// ).unwrap(); -// storages.add_unique_non_send_sync(RectPrimitive(vert, index)); -// } diff --git a/kubi/src/rendering/primitives/stri.rs b/kubi/src/rendering/primitives/stri.rs deleted file mode 100644 index 2cafaf9..0000000 --- a/kubi/src/rendering/primitives/stri.rs +++ /dev/null @@ -1,30 +0,0 @@ -// use shipyard::{Unique, AllStoragesView, NonSendSync, UniqueView}; -// use glium::{VertexBuffer, IndexBuffer, index::PrimitiveType}; -// use crate::rendering::Renderer; -// use super::PositionOnlyVertex2d; - -// #[derive(Unique)] -// pub struct STriPrimitive(pub VertexBuffer, pub IndexBuffer); - -// const STRI_VERTEX: &[PositionOnlyVertex2d] = &[ -// PositionOnlyVertex2d { position: [-1., -1.] }, -// PositionOnlyVertex2d { position: [ 3., -1.] }, -// PositionOnlyVertex2d { position: [-1., 3.] }, -// ]; -// const STRI_INDEX: &[u16] = &[0, 1, 2]; - -// pub(super) fn init_stri_primitive( -// storages: AllStoragesView, -// display: NonSendSync> -// ) { -// let vert = VertexBuffer::immutable( -// &display.display, -// STRI_VERTEX -// ).unwrap(); -// let index = IndexBuffer::immutable( -// &display.display, -// PrimitiveType::TrianglesList, -// STRI_INDEX -// ).unwrap(); -// storages.add_unique_non_send_sync(STriPrimitive(vert, index)); -// } From 487cf3184385181a6395f0bc81e5d7be63d62d04 Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Tue, 7 May 2024 01:14:36 +0200 Subject: [PATCH 37/51] wip --- kubi/src/rendering/selection_box.rs | 66 +++----------------- kubi/src/rendering/selection_box/pipeline.rs | 0 2 files changed, 8 insertions(+), 58 deletions(-) create mode 100644 kubi/src/rendering/selection_box/pipeline.rs diff --git a/kubi/src/rendering/selection_box.rs b/kubi/src/rendering/selection_box.rs index ad89716..c434527 100644 --- a/kubi/src/rendering/selection_box.rs +++ b/kubi/src/rendering/selection_box.rs @@ -1,59 +1,9 @@ -// use glam::{Mat4, Vec3, Quat}; -// use shipyard::{View, IntoIter, NonSendSync, UniqueViewMut, UniqueView}; -// use glium::{ -// Surface, -// DrawParameters, -// BackfaceCullingMode, -// Blend, Depth, DepthTest, -// uniform, -// }; -// use crate::{ -// world::raycast::LookingAtBlock, -// camera::Camera, -// prefabs::ColoredShaderPrefab -// }; -// use super::{ -// RenderTarget, -// primitives::cube::CubePrimitive, -// }; +mod pipeline; -// const SMOL: f32 = 0.0025; - -// pub fn render_selection_box( -// lookat: View, -// camera: View, -// mut target: NonSendSync>, -// program: NonSendSync>, -// buffers: NonSendSync>, -// ) { -// let camera = camera.iter().next().unwrap(); -// let Some(lookat) = lookat.iter().next() else { return }; -// let Some(lookat) = lookat.0 else { return }; - -// //Darken block -// target.0.draw( -// &buffers.0, -// &buffers.1, -// &program.0, -// &uniform! { -// color: [0., 0., 0., 0.5_f32], -// model: Mat4::from_scale_rotation_translation( -// Vec3::splat(1. + SMOL * 2.), -// Quat::default(), -// lookat.block_position.as_vec3() - Vec3::splat(SMOL) -// ).to_cols_array_2d(), -// perspective: camera.perspective_matrix.to_cols_array_2d(), -// view: camera.view_matrix.to_cols_array_2d(), -// }, -// &DrawParameters { -// backface_culling: BackfaceCullingMode::CullClockwise, -// blend: Blend::alpha_blending(), -// depth: Depth { -// //this may be unreliable... unless scale is applied! hacky... -// test: DepthTest::IfLessOrEqual, -// ..Default::default() -// }, -// ..Default::default() -// } -// ).unwrap(); -// } +pub fn draw_selection_box( + ctx: &mut RenderCtx, + lookat: View, + camera: View, +) { + //TODO +} diff --git a/kubi/src/rendering/selection_box/pipeline.rs b/kubi/src/rendering/selection_box/pipeline.rs new file mode 100644 index 0000000..e69de29 From 75cb0ead6b4257bc79f53b64f4f1c14e825e808f Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Tue, 7 May 2024 01:15:44 +0200 Subject: [PATCH 38/51] clean up world renderer --- kubi/src/rendering/world.rs | 222 ++---------------------------------- 1 file changed, 7 insertions(+), 215 deletions(-) diff --git a/kubi/src/rendering/world.rs b/kubi/src/rendering/world.rs index 3df4b11..e25d545 100644 --- a/kubi/src/rendering/world.rs +++ b/kubi/src/rendering/world.rs @@ -1,13 +1,12 @@ -use glam::{IVec3, Vec3}; -use shipyard::{AllStoragesView, IntoIter, NonSendSync, Unique, UniqueView, UniqueViewMut, View}; -use kubi_shared::{chunk::CHUNK_SIZE, transform::Transform}; +use glam::Vec3; +use shipyard::{AllStoragesView, IntoIter, NonSendSync, Unique, UniqueView, View}; +use kubi_shared::chunk::CHUNK_SIZE; use crate::{ camera::Camera, prefabs::TexturePrefabs, - settings::GameSettings, world::{ChunkMeshStorage, ChunkStorage}, }; -use super::{camera::{self, CameraUniformBuffer}, depth::DepthTexture, RenderCtx}; +use super::{camera::CameraUniformBuffer, depth::DepthTexture, RenderCtx}; mod pipeline; mod vertex; @@ -16,19 +15,19 @@ pub use vertex::ChunkVertex; #[derive(Unique)] pub struct WorldRenderState { pub pipeline: wgpu::RenderPipeline, - pub trans_chunk_queue: Vec, + //pub trans_chunk_queue: Vec, } pub fn init_world_render_state(storages: AllStoragesView) { storages.add_unique(WorldRenderState { pipeline: storages.run(pipeline::init_world_pipeline), - trans_chunk_queue: Vec::with_capacity(512), + //trans_chunk_queue: Vec::with_capacity(512), }) } pub fn draw_world( ctx: &mut RenderCtx, - mut state: UniqueViewMut, + state: UniqueView, camera_ubo: UniqueView, depth: UniqueView, textures: UniqueView, @@ -95,210 +94,3 @@ pub fn draw_world( } } } - - -// fn draw_params(settings: &GameSettings) -> DrawParameters { -// DrawParameters { -// depth: Depth { -// test: DepthTest::IfLess, -// write: true, -// ..Default::default() -// }, -// multisampling: settings.msaa.is_some(), -// polygon_mode: PolygonMode::Fill, //Change to Line for wireframe -// backface_culling: BackfaceCullingMode::CullClockwise, -// ..Default::default() -// } -// } - -// fn texture_sampler<'a, T>(texture: &'a T, settings: &GameSettings) -> Sampler<'a, T> { -// Sampler(texture, SamplerBehavior { -// minify_filter: MinifySamplerFilter::LinearMipmapLinear, -// magnify_filter: MagnifySamplerFilter::Nearest, -// max_anisotropy: settings.max_anisotropy.unwrap_or_default(), -// wrap_function: (SamplerWrapFunction::Clamp, SamplerWrapFunction::Clamp, SamplerWrapFunction::Clamp), -// depth_texture_comparison: None, -// }) -// } - -// pub fn draw_world( -// mut target: NonSendSync>, -// chunks: UniqueView, -// meshes: NonSendSync>, -// program: NonSendSync>, -// texture: NonSendSync>, -// transform: View, -// camera: View, -// settings: UniqueView, -// mut trans_queue: UniqueViewMut, -// ) { -// // let (camera, transform) = (&camera, &transform).iter().next().expect("No cameras in the scene"); -// // let camera_position = transform.0.to_scale_rotation_translation().2; - -// let camera = camera.iter().next().expect("No cameras in the scene"); -// let view = camera.view_matrix.to_cols_array_2d(); -// let perspective = camera.perspective_matrix.to_cols_array_2d(); - -// let draw_parameters = draw_params(&settings); -// let texture_sampler = texture_sampler(&texture.0, &settings); - -// for (&position, chunk) in &chunks.chunks { -// if let Some(key) = chunk.mesh_index { -// let mesh = meshes.get(key).expect("Mesh index pointing to nothing"); -// let world_position = position.as_vec3() * CHUNK_SIZE as f32; - -// //Skip mesh if its empty -// if mesh.index_buffer.len() == 0 && mesh.trans_index_buffer.len() == 0 { -// continue -// } - -// //Frustum culling -// { -// let minp = world_position; -// let maxp = world_position + Vec3::splat(CHUNK_SIZE as f32); -// if !camera.frustum.is_box_visible(minp, maxp) { -// continue -// } -// } - -// //Draw chunk mesh -// if mesh.index_buffer.len() > 0 { -// target.0.draw( -// &mesh.vertex_buffer, -// &mesh.index_buffer, -// &program.0, -// &uniform! { -// position_offset: world_position.to_array(), -// view: view, -// perspective: perspective, -// tex: texture_sampler, -// discard_alpha: true, -// }, -// &draw_parameters -// ).unwrap(); -// } - -// if mesh.trans_index_buffer.len() > 0 { -// trans_queue.0.push(position); -// } -// } -// } - -// // const HALF_CHUNK_SIZE: IVec3 = IVec3::splat((CHUNK_SIZE >> 1) as i32); -// // trans_queue.0.sort_by_cached_key(|&pos| -( -// // (pos + HALF_CHUNK_SIZE).distance_squared(camera_position.as_ivec3()) -// // )); -// } - -// pub fn draw_world_trans( -// mut target: NonSendSync>, -// chunks: UniqueView, -// meshes: NonSendSync>, -// program: NonSendSync>, -// texture: NonSendSync>, -// camera: View, -// settings: UniqueView, -// mut trans_queue: UniqueViewMut, -// ) { -// let camera = camera.iter().next().expect("No cameras in the scene"); -// let view = camera.view_matrix.to_cols_array_2d(); -// let perspective = camera.perspective_matrix.to_cols_array_2d(); - -// let mut draw_parameters = draw_params(&settings); -// draw_parameters.blend = Blend::alpha_blending(); -// draw_parameters.backface_culling = BackfaceCullingMode::CullingDisabled; -// draw_parameters.smooth = Some(Smooth::Fastest); - -// let texture_sampler = texture_sampler(&texture.0, &settings); - -// for position in trans_queue.0.drain(..).rev() { -// let world_position = position.as_vec3() * CHUNK_SIZE as f32; -// let mesh_idx = chunks.chunks[&position].mesh_index.expect("No mesh index"); -// let mesh = meshes.get(mesh_idx).expect("Mesh index pointing to nothing"); -// target.0.draw( -// &mesh.trans_vertex_buffer, -// &mesh.trans_index_buffer, -// &program.0, -// &uniform! { -// position_offset: world_position.to_array(), -// view: view, -// perspective: perspective, -// tex: texture_sampler, -// discard_alpha: false, -// }, -// &draw_parameters -// ).unwrap(); -// } -// } - -// pub fn draw_current_chunk_border( -// mut target: NonSendSync>, -// player: View, -// transforms: View, -// buffers: NonSendSync>, -// program: NonSendSync>, -// camera: View, -// settings: UniqueView, -// ) { -// if cfg!(target_os = "android") { -// return -// } -// if !settings.debug_draw_current_chunk_border { -// return -// } -// let camera = camera.iter().next().expect("No cameras in the scene"); -// let view = camera.view_matrix.to_cols_array_2d(); -// let perspective = camera.perspective_matrix.to_cols_array_2d(); -// let (_, &player_transform) = (&player, &transforms).iter().next().expect("No player"); -// let (_, _, player_position) = player_transform.0.to_scale_rotation_translation(); -// let player_in_chunk = ivec3( -// (player_position.x as i32).div_euclid(CHUNK_SIZE as i32), -// (player_position.y as i32).div_euclid(CHUNK_SIZE as i32), -// (player_position.z as i32).div_euclid(CHUNK_SIZE as i32), -// ); -// let world_position = player_in_chunk.as_vec3() * CHUNK_SIZE as f32; -// target.0.draw( -// &buffers.0, -// &buffers.1, -// &program.0, -// &uniform! { -// model: Mat4::from_scale_rotation_translation( -// Vec3::splat(CHUNK_SIZE as f32), -// Quat::default(), -// world_position -// ).to_cols_array_2d(), -// color: [0.25f32; 4], -// view: view, -// perspective: perspective, -// }, -// &DrawParameters { -// depth: Depth { -// test: DepthTest::IfLess, -// ..Default::default() -// }, -// blend: Blend::alpha_blending(), -// ..Default::default() -// } -// ).unwrap(); -// target.0.draw( -// &buffers.0, -// &buffers.1, -// &program.0, -// &uniform! { -// model: Mat4::from_scale_rotation_translation( -// Vec3::splat(CHUNK_SIZE as f32), -// Quat::default(), -// world_position -// ).to_cols_array_2d(), -// color: [0.0f32; 4], -// view: view, -// perspective: perspective, -// }, -// &DrawParameters { -// polygon_mode: PolygonMode::Point, -// line_width: Some(2.), -// point_size: Some(5.), -// ..Default::default() -// } -// ).unwrap(); -// } From 18e35b3ea4101e32792a328f5c89a2e6e16e56b9 Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Tue, 7 May 2024 20:12:07 +0200 Subject: [PATCH 39/51] Selection Box --- kubi/shaders/selection_box.wgsl | 27 +++++++ kubi/src/rendering.rs | 16 ++-- .../{camera.rs => camera_uniform.rs} | 1 - kubi/src/rendering/primitives.rs | 1 + kubi/src/rendering/selection_box.rs | 60 +++++++++++++- kubi/src/rendering/selection_box/pipeline.rs | 68 ++++++++++++++++ kubi/src/rendering/selection_box/uniform.rs | 79 +++++++++++++++++++ kubi/src/rendering/world.rs | 4 +- kubi/src/rendering/world/pipeline.rs | 4 +- 9 files changed, 247 insertions(+), 13 deletions(-) create mode 100644 kubi/shaders/selection_box.wgsl rename kubi/src/rendering/{camera.rs => camera_uniform.rs} (97%) create mode 100644 kubi/src/rendering/selection_box/uniform.rs diff --git a/kubi/shaders/selection_box.wgsl b/kubi/shaders/selection_box.wgsl new file mode 100644 index 0000000..09a097e --- /dev/null +++ b/kubi/shaders/selection_box.wgsl @@ -0,0 +1,27 @@ +struct CameraUniform { + view_proj: mat4x4, +}; + +@group(0) @binding(0) +var camera: CameraUniform; + +struct SboxUniform { + position: vec3, +}; + +@group(1) @binding(0) +var sbox: SboxUniform; + +@vertex +fn vs_main( + @location(0) position: vec3, +) -> @builtin(position) vec4 { + return camera.view_proj * vec4(position + sbox.position, 1.0); +} + +@fragment +fn fs_main( + @builtin(position) in: vec4, +) -> @location(0) vec4 { + return vec4(0.0, 0.0, 0.0, 0.5); +} diff --git a/kubi/src/rendering.rs b/kubi/src/rendering.rs index e194906..688aa9d 100644 --- a/kubi/src/rendering.rs +++ b/kubi/src/rendering.rs @@ -1,15 +1,16 @@ -use shipyard::{AllStoragesViewMut, IntoIter, IntoWorkload, Unique, UniqueView, UniqueViewMut, View, Workload, WorkloadModificator}; +use shipyard::{AllStoragesViewMut, IntoIter, IntoWorkload, SystemModificator, Unique, UniqueView, UniqueViewMut, View, Workload, WorkloadModificator}; use winit::dpi::PhysicalSize; use glam::Vec3; use crate::{events::WindowResizedEvent, state::is_ingame}; mod renderer; mod primitives; +mod selection_box; pub use renderer::Renderer; pub mod background; pub mod world; -pub mod camera; +pub mod camera_uniform; pub mod depth; pub struct BufferPair { @@ -28,14 +29,15 @@ pub struct RenderCtx<'a> { pub surface_view: &'a wgpu::TextureView, } -//TODO run init_world_render_state only once ingame? +//TODO run init_world_render_state, init_selection_box_state, etc. only once ingame? pub fn init_rendering() -> Workload { ( depth::init_depth_texture, - camera::init_camera_uniform_buffer, - world::init_world_render_state, //requires depth and camera buffers + camera_uniform::init_camera_uniform_buffer, + world::init_world_render_state, //req: depth, camera primitives::init_primitives, + selection_box::init_selection_box_render_state, //req: depth, camera, primitives ).into_sequential_workload() } @@ -48,7 +50,8 @@ pub fn update_rendering_early() -> Workload { pub fn update_rendering_late() -> Workload { ( - camera::update_camera_uniform_buffer, + camera_uniform::update_camera_uniform_buffer, + selection_box::update_selection_box_render_state.run_if(is_ingame), ).into_workload() } @@ -70,6 +73,7 @@ pub fn render_master(storages: AllStoragesViewMut) { storages.run_with_data(background::clear_bg, &mut data); if storages.run(is_ingame) { storages.run_with_data(world::draw_world, &mut data); + storages.run_with_data(selection_box::draw_selection_box, &mut data); } renderer.queue().submit([encoder.finish()]); diff --git a/kubi/src/rendering/camera.rs b/kubi/src/rendering/camera_uniform.rs similarity index 97% rename from kubi/src/rendering/camera.rs rename to kubi/src/rendering/camera_uniform.rs index 8cd815b..03bb3d7 100644 --- a/kubi/src/rendering/camera.rs +++ b/kubi/src/rendering/camera_uniform.rs @@ -11,7 +11,6 @@ pub struct CameraUniformData { pub view_proj: [f32; 4 * 4], } - //TODO if multiple cameras, buffer per camera #[derive(Unique)] pub struct CameraUniformBuffer { diff --git a/kubi/src/rendering/primitives.rs b/kubi/src/rendering/primitives.rs index 8dfbfa4..c7e85f3 100644 --- a/kubi/src/rendering/primitives.rs +++ b/kubi/src/rendering/primitives.rs @@ -2,6 +2,7 @@ use bytemuck::{Pod, Zeroable}; use shipyard::{IntoWorkload, Workload}; mod cube; +pub use cube::CubePrimitive; pub fn init_primitives() -> Workload { ( diff --git a/kubi/src/rendering/selection_box.rs b/kubi/src/rendering/selection_box.rs index c434527..d33b4c7 100644 --- a/kubi/src/rendering/selection_box.rs +++ b/kubi/src/rendering/selection_box.rs @@ -1,9 +1,65 @@ +use shipyard::{AllStoragesView, IntoIter, Unique, UniqueView, View}; +use wgpu::RenderPassDescriptor; +use crate::{player::MainPlayer, world::raycast::LookingAtBlock}; +use super::{camera_uniform::CameraUniformBuffer, depth::DepthTexture, primitives::CubePrimitive, RenderCtx}; + mod pipeline; +mod uniform; + +use uniform::SelectionBoxUniform; + +#[derive(Unique)] +pub struct SboxRenderState { + pipeline: wgpu::RenderPipeline, + uniform: SelectionBoxUniform, +} + +pub fn init_selection_box_render_state(storages: AllStoragesView) { + let uniform = storages.run(uniform::init_selection_box_uniform); + let pipeline = storages.run_with_data(pipeline::init_selection_box_pipeline, &uniform); + storages.add_unique(SboxRenderState { pipeline, uniform }); +} + +pub use uniform::update_selection_box_uniform + as update_selection_box_render_state; pub fn draw_selection_box( ctx: &mut RenderCtx, + state: UniqueView, + depth: UniqueView, + cube: UniqueView, + camera_ubo: UniqueView, lookat: View, - camera: View, + player: View, ) { - //TODO + let Some((LookingAtBlock(Some(_)), _)) = (&lookat, &player).iter().next() else { + return + }; + let mut rpass = ctx.encoder.begin_render_pass(&RenderPassDescriptor { + label: Some("rpass_selection_box"), + color_attachments: &[Some(wgpu::RenderPassColorAttachment { + view: ctx.surface_view, + resolve_target: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Load, + store: wgpu::StoreOp::Store, + }, + })], + depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment { + view: &depth.depth_view, + depth_ops: Some(wgpu::Operations { + load: wgpu::LoadOp::Load, + store: wgpu::StoreOp::Discard, + }), + stencil_ops: None, + }), + ..Default::default() + }); + + rpass.set_pipeline(&state.pipeline); + rpass.set_bind_group(0, &camera_ubo.camera_bind_group, &[]); + rpass.set_bind_group(1, &state.uniform.bind_group, &[]); + rpass.set_index_buffer(cube.0.index.slice(..), wgpu::IndexFormat::Uint16); + rpass.set_vertex_buffer(0, cube.0.vertex.slice(..)); + rpass.draw_indexed(0..cube.0.index_len, 0, 0..1); } diff --git a/kubi/src/rendering/selection_box/pipeline.rs b/kubi/src/rendering/selection_box/pipeline.rs index e69de29..352ce83 100644 --- a/kubi/src/rendering/selection_box/pipeline.rs +++ b/kubi/src/rendering/selection_box/pipeline.rs @@ -0,0 +1,68 @@ +use shipyard::UniqueView; +use crate::rendering::{ + camera_uniform::CameraUniformBuffer, + depth::DepthTexture, + primitives::PrimitiveVertex, + Renderer +}; + +pub fn init_selection_box_pipeline( + uniform: &super::uniform::SelectionBoxUniform, + ren: UniqueView, + depth: UniqueView, + camera_ubo: UniqueView, +) -> wgpu::RenderPipeline { + let shader = ren.device().create_shader_module( + wgpu::include_wgsl!("../../../shaders/selection_box.wgsl") + ); + + let selection_box_pipeline_layout = ren.device().create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("selection_box_pipeline_layout"), + bind_group_layouts: &[ + &camera_ubo.camera_bind_group_layout, + &uniform.bind_group_layout, + ], + push_constant_ranges: &[], + }); + + ren.device().create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("selection_box_pipeline"), + layout: Some(&selection_box_pipeline_layout), + fragment: Some(wgpu::FragmentState { + module: &shader, + entry_point: "fs_main", + compilation_options: wgpu::PipelineCompilationOptions::default(), + targets: &[Some(wgpu::ColorTargetState { + format: ren.surface_config().format, + blend: Some(wgpu::BlendState::ALPHA_BLENDING), + write_mask: wgpu::ColorWrites::COLOR, + })], + }), + vertex: wgpu::VertexState { + module: &shader, + entry_point: "vs_main", + compilation_options: wgpu::PipelineCompilationOptions::default(), + buffers: &[ + PrimitiveVertex::LAYOUT, + ], + }, + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleList, + strip_index_format: None, + cull_mode: Some(wgpu::Face::Back), + front_face: wgpu::FrontFace::Ccw, + unclipped_depth: false, + polygon_mode: wgpu::PolygonMode::Fill, + conservative: false, + }, + depth_stencil: Some(wgpu::DepthStencilState { + format: depth.depth_texture.format(), + depth_write_enabled: false, + depth_compare: wgpu::CompareFunction::LessEqual, + stencil: wgpu::StencilState::default(), + bias: wgpu::DepthBiasState::default(), + }), + multisample: wgpu::MultisampleState::default(), + multiview: None, + }) +} diff --git a/kubi/src/rendering/selection_box/uniform.rs b/kubi/src/rendering/selection_box/uniform.rs new file mode 100644 index 0000000..8ee8f5e --- /dev/null +++ b/kubi/src/rendering/selection_box/uniform.rs @@ -0,0 +1,79 @@ +use glam::Vec3; +use shipyard::{IntoIter, UniqueView, View}; +use bytemuck::{Pod, Zeroable}; +use crate::{ + player::MainPlayer, + rendering::Renderer, + world::raycast::LookingAtBlock, +}; +use super::SboxRenderState; + +#[derive(Clone, Copy, Pod, Zeroable)] +#[repr(C, packed)] +pub struct SelectionBoxUniformData { + pub position: [f32; 3], + pub _padding: u32, +} + +pub struct SelectionBoxUniform { + pub buffer: wgpu::Buffer, + pub bind_group_layout: wgpu::BindGroupLayout, + pub bind_group: wgpu::BindGroup, +} + +pub fn init_selection_box_uniform(renderer: UniqueView) -> SelectionBoxUniform { + let buffer = renderer.device().create_buffer(&wgpu::BufferDescriptor { + label: Some("selection_box_uniform"), + size: std::mem::size_of::() as u64, + usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, + mapped_at_creation: false, + }); + + let bind_group_layout = renderer.device().create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: Some("selection_box_bind_group_layout"), + entries: &[wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStages::VERTEX, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, + min_binding_size: None, + }, + count: None, + }], + }); + + let bind_group = renderer.device().create_bind_group(&wgpu::BindGroupDescriptor { + label: Some("selection_box_bind_group"), + layout: &bind_group_layout, + entries: &[wgpu::BindGroupEntry { + binding: 0, + resource: buffer.as_entire_binding(), + }], + }); + + SelectionBoxUniform { + buffer, + bind_group_layout, + bind_group, + } +} + +pub fn update_selection_box_uniform( + renderer: UniqueView, + state: UniqueView, + lookat: View, + player: View, +) { + //TODO: only update if changed + if let Some((LookingAtBlock(Some(lookat)), _)) = (&lookat, &player).iter().next() { + renderer.queue().write_buffer( + &state.uniform.buffer, + 0, + bytemuck::cast_slice(&[SelectionBoxUniformData { + position: (lookat.position.floor() + Vec3::splat(0.5)).to_array(), + _padding: 0, + }]), + ); + }; +} diff --git a/kubi/src/rendering/world.rs b/kubi/src/rendering/world.rs index e25d545..5e57781 100644 --- a/kubi/src/rendering/world.rs +++ b/kubi/src/rendering/world.rs @@ -6,7 +6,7 @@ use crate::{ prefabs::TexturePrefabs, world::{ChunkMeshStorage, ChunkStorage}, }; -use super::{camera::CameraUniformBuffer, depth::DepthTexture, RenderCtx}; +use super::{camera_uniform::CameraUniformBuffer, depth::DepthTexture, RenderCtx}; mod pipeline; mod vertex; @@ -39,7 +39,7 @@ pub fn draw_world( let camera = camera.iter().next().expect("No cameras in the scene"); let mut render_pass = ctx.encoder.begin_render_pass(&wgpu::RenderPassDescriptor { - label: Some("draw_world"), + label: Some("rpass_draw_world"), color_attachments: &[Some(wgpu::RenderPassColorAttachment { view: ctx.surface_view, resolve_target: None, diff --git a/kubi/src/rendering/world/pipeline.rs b/kubi/src/rendering/world/pipeline.rs index 040ed4d..9a63f65 100644 --- a/kubi/src/rendering/world/pipeline.rs +++ b/kubi/src/rendering/world/pipeline.rs @@ -1,7 +1,7 @@ use shipyard::UniqueView; use crate::{ prefabs::TexturePrefabs, - rendering::{camera::CameraUniformBuffer, depth::DepthTexture, world::ChunkVertex, Renderer} + rendering::{camera_uniform::CameraUniformBuffer, depth::DepthTexture, world::ChunkVertex, Renderer} }; pub fn init_world_pipeline( @@ -33,7 +33,7 @@ pub fn init_world_pipeline( targets: &[Some(wgpu::ColorTargetState { format: ren.surface_config().format, blend: Some(wgpu::BlendState::REPLACE), - write_mask: wgpu::ColorWrites::ALL, + write_mask: wgpu::ColorWrites::COLOR, })], }), vertex: wgpu::VertexState { From c98f504310aba8467474880caad200470befe592 Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Tue, 7 May 2024 20:50:59 +0200 Subject: [PATCH 40/51] print adapter info on start --- kubi/src/rendering/camera_uniform.rs | 3 +-- kubi/src/rendering/renderer.rs | 6 +++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/kubi/src/rendering/camera_uniform.rs b/kubi/src/rendering/camera_uniform.rs index 03bb3d7..1d18bcd 100644 --- a/kubi/src/rendering/camera_uniform.rs +++ b/kubi/src/rendering/camera_uniform.rs @@ -1,8 +1,7 @@ use bytemuck::{Pod, Zeroable}; -use kubi_shared::transform::Transform; use shipyard::{AllStoragesView, IntoIter, Unique, UniqueView, View}; use wgpu::util::DeviceExt; -use crate::camera::{self, Camera}; +use crate::camera::Camera; use super::Renderer; #[derive(Debug, Clone, Copy, Default, Pod, Zeroable)] diff --git a/kubi/src/rendering/renderer.rs b/kubi/src/rendering/renderer.rs index c491e0f..2da1be3 100644 --- a/kubi/src/rendering/renderer.rs +++ b/kubi/src/rendering/renderer.rs @@ -103,11 +103,15 @@ impl Renderer { }, ).block_on().unwrap(); + log::info!("Adapter: {:?}", adapter.get_info()); + log::info!("Features: {:?}", adapter.features()); + log::info!("Limits: {:?}", adapter.limits()); + let (device, queue) = adapter.request_device( &wgpu::DeviceDescriptor { label: None, required_features: wgpu::Features::empty(), - required_limits: wgpu::Limits::default(), + required_limits: wgpu::Limits::downlevel_webgl2_defaults().using_resolution(adapter.limits()), }, None, ).block_on().unwrap(); From ec23cedb7a9341616e0207b4f9e9f6e8f383f8d0 Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Tue, 7 May 2024 21:04:50 +0200 Subject: [PATCH 41/51] use proper srgb color for background --- kubi/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kubi/src/lib.rs b/kubi/src/lib.rs index b59a073..516c1cf 100644 --- a/kubi/src/lib.rs +++ b/kubi/src/lib.rs @@ -266,7 +266,7 @@ pub fn kubi_main( let settings = world.borrow::>().unwrap(); world.add_unique_non_send_sync(Renderer::init(window_target, &settings)); } - world.add_unique(BackgroundColor(vec3(0.5, 0.5, 1.))); + world.add_unique(BackgroundColor(vec3(0.21, 0.21, 1.))); //Run startup systems world.run_workload(startup).unwrap(); From 7eafea521f3f7d405a20a015b9e84fecac0a02c1 Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Wed, 8 May 2024 03:04:50 +0200 Subject: [PATCH 42/51] kubiui integration update --- Cargo.lock | 19 ++++++++++++++++--- kubi/Cargo.toml | 5 +++-- kubi/src/hui_integration.rs | 27 ++++++++++++++------------- kubi/src/rendering.rs | 10 ++++++---- 4 files changed, 39 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2194bb8..1f05822 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -988,7 +988,7 @@ checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" [[package]] name = "hui" version = "0.1.0-alpha.5" -source = "git+https://github.com/griffi-gh/hui?rev=3a50d2d0dde#3a50d2d0dde7044d02860dac9ab059bd353657a2" +source = "git+https://github.com/griffi-gh/hui?rev=b6dc8f370b6#b6dc8f370b6dac971394e8cb82fdb505b529e964" dependencies = [ "derive_more", "derive_setters", @@ -1008,16 +1008,28 @@ dependencies = [ [[package]] name = "hui-derive" version = "0.1.0-alpha.5" -source = "git+https://github.com/griffi-gh/hui?rev=3a50d2d0dde#3a50d2d0dde7044d02860dac9ab059bd353657a2" +source = "git+https://github.com/griffi-gh/hui?rev=b6dc8f370b6#b6dc8f370b6dac971394e8cb82fdb505b529e964" dependencies = [ "quote", "syn 2.0.60", ] +[[package]] +name = "hui-wgpu" +version = "0.1.0-alpha.5" +source = "git+https://github.com/griffi-gh/hui?rev=b6dc8f370b6#b6dc8f370b6dac971394e8cb82fdb505b529e964" +dependencies = [ + "bytemuck", + "glam", + "hui", + "log", + "wgpu", +] + [[package]] name = "hui-winit" version = "0.1.0-alpha.5" -source = "git+https://github.com/griffi-gh/hui?rev=3a50d2d0dde#3a50d2d0dde7044d02860dac9ab059bd353657a2" +source = "git+https://github.com/griffi-gh/hui?rev=b6dc8f370b6#b6dc8f370b6dac971394e8cb82fdb505b529e964" dependencies = [ "glam", "hui", @@ -1211,6 +1223,7 @@ dependencies = [ "glam", "hashbrown 0.14.5", "hui", + "hui-wgpu", "hui-winit", "image", "kubi-logging", diff --git a/kubi/Cargo.toml b/kubi/Cargo.toml index 6542e1d..5b58b3b 100644 --- a/kubi/Cargo.toml +++ b/kubi/Cargo.toml @@ -11,8 +11,9 @@ crate-type = ["lib", "cdylib"] [dependencies] kubi-shared = { path = "../kubi-shared" } kubi-logging = { path = "../kubi-logging" } -hui = { git = "https://github.com/griffi-gh/hui", rev = "3a50d2d0dde" } -hui-winit = { git = "https://github.com/griffi-gh/hui", rev = "3a50d2d0dde", features = ["winit_30"] } +hui = { git = "https://github.com/griffi-gh/hui", rev = "b6dc8f370b6" } +hui-wgpu = { git = "https://github.com/griffi-gh/hui", rev = "b6dc8f370b6" } +hui-winit = { git = "https://github.com/griffi-gh/hui", rev = "b6dc8f370b6", features = ["winit_30"] } log = "0.4" wgpu = { version = "0.20", features = ["webgl"] } pollster = "0.3" diff --git a/kubi/src/hui_integration.rs b/kubi/src/hui_integration.rs index 95fcfae..78f0b02 100644 --- a/kubi/src/hui_integration.rs +++ b/kubi/src/hui_integration.rs @@ -1,12 +1,13 @@ use hui::UiInstance; +use hui_wgpu::WgpuUiRenderer; //use hui_glium::GliumUiRenderer; use shipyard::{AllStoragesView, Unique, UniqueView, NonSendSync, UniqueViewMut}; -use crate::rendering::Renderer; +use crate::rendering::{RenderCtx, Renderer}; #[derive(Unique)] pub struct UiState { pub hui: UiInstance, - //pub renderer: GliumUiRenderer + pub renderer: WgpuUiRenderer, } pub fn kubi_ui_init( @@ -15,7 +16,7 @@ pub fn kubi_ui_init( let renderer = storages.borrow::>>().unwrap(); storages.add_unique_non_send_sync(UiState { hui: UiInstance::new(), - //renderer: GliumUiRenderer::new(&renderer.display), + renderer: WgpuUiRenderer::new(renderer.device(), renderer.surface_config().format), }); } @@ -26,21 +27,21 @@ pub fn kubi_ui_begin( } pub fn kubi_ui_end( - mut ui: NonSendSync> + mut ui: NonSendSync>, + renderer: UniqueView, ) { let ui: &mut UiState = &mut ui; - let UiState { hui, /*renderer,*/ .. } = ui; + let UiState { hui, renderer: ui_renderer } = ui; hui.end(); - //renderer.update(hui); + ui_renderer.update(hui, renderer.queue(), renderer.device(), renderer.size_vec2()); } -// pub fn kubi_ui_draw( -// ui: NonSendSync>, -// mut target: NonSendSync>, -// size: UniqueView -// ) { -// ui.renderer.draw(&mut target.0, size.0.as_vec2()); -// } +pub fn kubi_ui_draw( + ctx: &mut RenderCtx, + ui: NonSendSync>, +) { + ui.renderer.draw(ctx.encoder, ctx.surface_view); +} pub fn hui_process_winit_events( event: &winit::event::Event<()>, diff --git a/kubi/src/rendering.rs b/kubi/src/rendering.rs index 688aa9d..f3342ab 100644 --- a/kubi/src/rendering.rs +++ b/kubi/src/rendering.rs @@ -1,7 +1,7 @@ -use shipyard::{AllStoragesViewMut, IntoIter, IntoWorkload, SystemModificator, Unique, UniqueView, UniqueViewMut, View, Workload, WorkloadModificator}; +use shipyard::{AllStoragesViewMut, IntoIter, IntoWorkload, SystemModificator, Unique, UniqueView, UniqueViewMut, View, Workload}; use winit::dpi::PhysicalSize; use glam::Vec3; -use crate::{events::WindowResizedEvent, state::is_ingame}; +use crate::{events::WindowResizedEvent, hui_integration::kubi_ui_draw, state::is_ingame}; mod renderer; mod primitives; @@ -24,7 +24,7 @@ pub struct BufferPair { pub struct BackgroundColor(pub Vec3); pub struct RenderCtx<'a> { - pub renderer: &'a Renderer, + //pub renderer: &'a Renderer, pub encoder: &'a mut wgpu::CommandEncoder, pub surface_view: &'a wgpu::TextureView, } @@ -65,7 +65,7 @@ pub fn render_master(storages: AllStoragesViewMut) { let surface_view = surface_texture.texture.create_view(&wgpu::TextureViewDescriptor::default()); let mut data = RenderCtx { - renderer: &renderer, + //renderer: &renderer, encoder: &mut encoder, surface_view: &surface_view, }; @@ -76,6 +76,8 @@ pub fn render_master(storages: AllStoragesViewMut) { storages.run_with_data(selection_box::draw_selection_box, &mut data); } + storages.run_with_data(kubi_ui_draw, &mut data); + renderer.queue().submit([encoder.finish()]); surface_texture.present(); } From 3f0697d57302eef6e632a98f872059c8a92f97d0 Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Wed, 8 May 2024 03:22:41 +0200 Subject: [PATCH 43/51] use latest hui --- Cargo.lock | 8 ++++---- Cargo.toml | 5 +++++ kubi/Cargo.toml | 6 +++--- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1f05822..1d20dc1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -988,7 +988,7 @@ checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" [[package]] name = "hui" version = "0.1.0-alpha.5" -source = "git+https://github.com/griffi-gh/hui?rev=b6dc8f370b6#b6dc8f370b6dac971394e8cb82fdb505b529e964" +source = "git+https://github.com/griffi-gh/hui?rev=6eb3d98ad4#6eb3d98ad4747b34a366d6d92ba6f1df3bec4ba4" dependencies = [ "derive_more", "derive_setters", @@ -1008,7 +1008,7 @@ dependencies = [ [[package]] name = "hui-derive" version = "0.1.0-alpha.5" -source = "git+https://github.com/griffi-gh/hui?rev=b6dc8f370b6#b6dc8f370b6dac971394e8cb82fdb505b529e964" +source = "git+https://github.com/griffi-gh/hui?rev=6eb3d98ad4#6eb3d98ad4747b34a366d6d92ba6f1df3bec4ba4" dependencies = [ "quote", "syn 2.0.60", @@ -1017,7 +1017,7 @@ dependencies = [ [[package]] name = "hui-wgpu" version = "0.1.0-alpha.5" -source = "git+https://github.com/griffi-gh/hui?rev=b6dc8f370b6#b6dc8f370b6dac971394e8cb82fdb505b529e964" +source = "git+https://github.com/griffi-gh/hui?rev=6eb3d98ad4#6eb3d98ad4747b34a366d6d92ba6f1df3bec4ba4" dependencies = [ "bytemuck", "glam", @@ -1029,7 +1029,7 @@ dependencies = [ [[package]] name = "hui-winit" version = "0.1.0-alpha.5" -source = "git+https://github.com/griffi-gh/hui?rev=b6dc8f370b6#b6dc8f370b6dac971394e8cb82fdb505b529e964" +source = "git+https://github.com/griffi-gh/hui?rev=6eb3d98ad4#6eb3d98ad4747b34a366d6d92ba6f1df3bec4ba4" dependencies = [ "glam", "hui", diff --git a/Cargo.toml b/Cargo.toml index ae8076d..8e1cac3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,3 +40,8 @@ opt-level = 3 #enabling debug assertions here causes the game to abort [profile.dev.package.android-activity] debug-assertions = false + +# [patch.'https://github.com/griffi-gh/hui'] +# hui = { path = "X:/Projects/hui/hui" } +# hui-winit = { path = "X:/Projects/hui/hui-winit" } +# hui-wgpu = { path = "X:/Projects/hui/hui-wgpu" } diff --git a/kubi/Cargo.toml b/kubi/Cargo.toml index 5b58b3b..eb7b284 100644 --- a/kubi/Cargo.toml +++ b/kubi/Cargo.toml @@ -11,9 +11,9 @@ crate-type = ["lib", "cdylib"] [dependencies] kubi-shared = { path = "../kubi-shared" } kubi-logging = { path = "../kubi-logging" } -hui = { git = "https://github.com/griffi-gh/hui", rev = "b6dc8f370b6" } -hui-wgpu = { git = "https://github.com/griffi-gh/hui", rev = "b6dc8f370b6" } -hui-winit = { git = "https://github.com/griffi-gh/hui", rev = "b6dc8f370b6", features = ["winit_30"] } +hui = { git = "https://github.com/griffi-gh/hui", rev = "6eb3d98ad4" } +hui-wgpu = { git = "https://github.com/griffi-gh/hui", rev = "6eb3d98ad4" } +hui-winit = { git = "https://github.com/griffi-gh/hui", rev = "6eb3d98ad4", features = ["winit_30"] } log = "0.4" wgpu = { version = "0.20", features = ["webgl"] } pollster = "0.3" From eec672d6659405eec0c40957821af55319c16338 Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Wed, 8 May 2024 13:12:58 +0200 Subject: [PATCH 44/51] kitty? kitty! --- Cargo.lock | 10 ++ assets-src/playermodel1.blend | Bin 0 -> 1127008 bytes assets/playermodel1.obj | 64 +++++++++ assets/playermodel1.png | Bin 0 -> 140471 bytes kubi/Cargo.toml | 2 +- kubi/shaders/entities.wgsl | 40 ++++++ kubi/src/prefabs.rs | 99 +++++++++++++- kubi/src/prefabs/loader.rs | 164 ++++++++++++++++++++++++ kubi/src/prefabs/texture.rs | 75 ----------- kubi/src/rendering.rs | 7 +- kubi/src/rendering/entities.rs | 119 +++++++++-------- kubi/src/rendering/entities/pipeline.rs | 61 +++++++++ kubi/src/rendering/selection_box.rs | 2 +- kubi/src/rendering/world.rs | 4 +- kubi/src/rendering/world/pipeline.rs | 4 +- 15 files changed, 507 insertions(+), 144 deletions(-) create mode 100644 assets-src/playermodel1.blend create mode 100644 assets/playermodel1.obj create mode 100644 assets/playermodel1.png create mode 100644 kubi/shaders/entities.wgsl create mode 100644 kubi/src/prefabs/loader.rs delete mode 100644 kubi/src/prefabs/texture.rs create mode 100644 kubi/src/rendering/entities/pipeline.rs diff --git a/Cargo.lock b/Cargo.lock index 1d20dc1..098f774 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1242,6 +1242,7 @@ dependencies = [ "static_assertions", "strum", "tinyset", + "tobj", "uflow", "wgpu", "winapi", @@ -2420,6 +2421,15 @@ dependencies = [ "rand", ] +[[package]] +name = "tobj" +version = "4.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3bd4ba05f29e4c65b6c0c11a58b6465ffa820bac890d76ad407b4e81d8372e8" +dependencies = [ + "ahash", +] + [[package]] name = "toml" version = "0.8.12" diff --git a/assets-src/playermodel1.blend b/assets-src/playermodel1.blend new file mode 100644 index 0000000000000000000000000000000000000000..4818ac7cce2c5b680c9cb895ea2109f6bda0f2f0 GIT binary patch literal 1127008 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%0AyOZt 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≀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

DNMb()-0GB?Blz{&bE~fe1!L&By`Uo&J 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 z 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%0Du5VL_t&n6OIvKh=ghKF;3c3Bp}fuQ+7D%_OU-6 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 G)BgeRdDGVb literal 0 HcmV?d00001 diff --git a/kubi/Cargo.toml b/kubi/Cargo.toml index eb7b284..b08759c 100644 --- a/kubi/Cargo.toml +++ b/kubi/Cargo.toml @@ -38,7 +38,7 @@ tinyset = "0.4" serde_json = { version = "1.0", optional = true } #only used for `generate_visualizer_data` rand = { version = "0.8", features = ["alloc", "small_rng"]} atomic = "0.6" - +tobj = "4.0" [target.'cfg(target_os = "android")'.dependencies] android-activity = "0.6" diff --git a/kubi/shaders/entities.wgsl b/kubi/shaders/entities.wgsl new file mode 100644 index 0000000..83eb27e --- /dev/null +++ b/kubi/shaders/entities.wgsl @@ -0,0 +1,40 @@ +struct CameraUniform { + view_proj: mat4x4, +}; + +@group(1) @binding(0) +var camera: CameraUniform; + +struct VertexInput { + @location(0) uv: vec2, + @location(1) position: vec3, + @location(2) normal: vec3, +} + +struct VertexOutput { + @builtin(position) clip_position: vec4, + @location(0) uv: vec2, + @location(1) normal: vec3, +}; + +@vertex +fn vs_main( + in: VertexInput, +) -> VertexOutput { + var out: VertexOutput; + out.clip_position = camera.view_proj * vec4(in.position, 1.0); + out.uv = in.uv; + out.normal = in.normal; + return out; +} + +@group(0) @binding(0) +var t_diffuse: texture_2d; + +@group(0) @binding(1) +var s_diffuse: sampler; + +@fragment +fn fs_main(in: VertexOutput) -> @location(0) vec4 { + return textureSample(t_diffuse, s_diffuse, in.uv); +} diff --git a/kubi/src/prefabs.rs b/kubi/src/prefabs.rs index 9932999..2fb3514 100644 --- a/kubi/src/prefabs.rs +++ b/kubi/src/prefabs.rs @@ -1,11 +1,35 @@ -use std::{io::{BufReader, Read}, path::Path}; +use std::{io::{BufReader, Read}, path::{Path, PathBuf}}; +use bytemuck::{Pod, Zeroable}; use hui::text::FontHandle; use shipyard::{AllStoragesView, NonSendSync, Unique, UniqueView, UniqueViewMut}; use kubi_shared::block::BlockTexture; -use crate::{filesystem::AssetManager, hui_integration::UiState, rendering::Renderer}; +use crate::{filesystem::AssetManager, hui_integration::UiState, rendering::{BufferPair, Renderer}}; -mod texture; -use texture::load_texture2darray_prefab; +//TODO move to rendering module + +mod loader; +use loader::{load_texture2darray_prefab, load_texture2d_prefab, load_obj_prefab}; + +#[derive(Clone, Copy, Default, Pod, Zeroable)] +#[repr(C, packed)] +pub struct ModelVertex { + pub tex_coords: [f32; 2], + pub position: [f32; 3], + pub _padding: u32, + pub normal: [f32; 3], +} + +impl ModelVertex { + pub const LAYOUT: wgpu::VertexBufferLayout<'static> = wgpu::VertexBufferLayout { + array_stride: std::mem::size_of::() as wgpu::BufferAddress, + step_mode: wgpu::VertexStepMode::Vertex, + attributes: &wgpu::vertex_attr_array![ + 0 => Float32x2, + 1 => Float32x3, + 2 => Float32x3, + ], + }; +} pub trait AssetPaths { fn file_name(self) -> &'static str; @@ -36,10 +60,14 @@ impl AssetPaths for BlockTexture { } #[derive(Unique)] -pub struct TexturePrefabs { +pub struct GpuPrefabs { pub block_diffuse_texture: wgpu::Texture, pub block_diffuse_bind_group_layout: wgpu::BindGroupLayout, pub block_diffuse_bind_group: wgpu::BindGroup, + pub player_model_diffuse_texture: wgpu::Texture, + pub player_model_diffuse_bind_group_layout: wgpu::BindGroupLayout, + pub player_model_diffuse_bind_group: wgpu::BindGroup, + pub player_model: BufferPair, } #[derive(Unique)] @@ -110,10 +138,69 @@ pub fn load_prefabs( } ] }); - storages.add_unique_non_send_sync(TexturePrefabs { + + let player_model_diffuse_texture = load_texture2d_prefab(&renderer, &assman, &PathBuf::from("playermodel1.png")); + let player_model_diffuse_view = player_model_diffuse_texture.create_view(&wgpu::TextureViewDescriptor { + label: Some("player_model_texture_view"), + ..Default::default() + }); + let player_model_diffuse_sampler = renderer.device().create_sampler(&wgpu::SamplerDescriptor { + label: Some("player_model_sampler"), + address_mode_u: wgpu::AddressMode::ClampToEdge, + address_mode_v: wgpu::AddressMode::ClampToEdge, + address_mode_w: wgpu::AddressMode::ClampToEdge, + mag_filter: wgpu::FilterMode::Linear, + min_filter: wgpu::FilterMode::Linear, + mipmap_filter: wgpu::FilterMode::Nearest, + ..Default::default() + }); + let player_model_diffuse_bind_group_layout = renderer.device() + .create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: Some("player_model_bind_group_layout"), + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStages::FRAGMENT, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + view_dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStages::FRAGMENT, + ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), + count: None, + } + ] + }); + let player_model_diffuse_bind_group = renderer.device().create_bind_group(&wgpu::BindGroupDescriptor { + label: Some("player_model_bind_group"), + layout: &player_model_diffuse_bind_group_layout, + entries: &[ + wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::TextureView(&player_model_diffuse_view), + }, + wgpu::BindGroupEntry { + binding: 1, + resource: wgpu::BindingResource::Sampler(&player_model_diffuse_sampler), + } + ] + }); + + let player_model = load_obj_prefab(&renderer, &assman, &PathBuf::from("playermodel1.obj")); + + storages.add_unique_non_send_sync(GpuPrefabs { block_diffuse_texture, block_diffuse_bind_group_layout, block_diffuse_bind_group, + player_model_diffuse_texture, + player_model_diffuse_bind_group_layout, + player_model_diffuse_bind_group, + player_model, }); log::info!("Loading the UI stuff..."); diff --git a/kubi/src/prefabs/loader.rs b/kubi/src/prefabs/loader.rs new file mode 100644 index 0000000..f32834b --- /dev/null +++ b/kubi/src/prefabs/loader.rs @@ -0,0 +1,164 @@ +use glam::UVec2; +use strum::IntoEnumIterator; +use rayon::prelude::*; +use wgpu::util::{DeviceExt, TextureDataOrder}; +use std::{io::{BufReader, Read}, path::{Path, PathBuf}}; +use crate::{filesystem::AssetManager, prefabs::ModelVertex, rendering::{BufferPair, Renderer}}; +use super::AssetPaths; + +pub fn load_texture2darray_prefab( + renderer: &Renderer, + assman: &AssetManager, + directory: PathBuf, +) -> wgpu::Texture { + log::info!("started loading {}", directory.as_os_str().to_str().unwrap()); + + //Load raw images + let tex_files: Vec<&'static str> = T::iter().map(|x| x.file_name()).collect(); + let raw_images: Vec<(Vec, UVec2)> = tex_files.par_iter().map(|&file_name| { + log::info!("loading texture {}", file_name); + + //Get path to the image and open the file + let reader = { + let path = directory.join(file_name); + BufReader::new(assman.open_asset(&path).expect("Failed to open texture file")) + }; + + //Parse image data + let (image_data, dimensions) = { + let image = image::load( + reader, + image::ImageFormat::Png + ).unwrap().to_rgba8(); + let dimensions = image.dimensions(); + (image.into_raw(), dimensions) + }; + (image_data, UVec2::from(dimensions)) + }).collect(); + + assert!(!raw_images.is_empty(), "no images loaded"); + //TODO: check same size + + log::info!("done loading texture files, uploading to the gpu"); + + let size = raw_images[0].1; + let layers = raw_images.len() as u32; + + //Concat data into a single vec + let mut data = Vec::with_capacity((size.x * size.y * layers * 4) as usize); + for (layer_data, _) in raw_images { + data.extend_from_slice(&layer_data); + } + + //Upload images to the GPU + let label = format!("texture2darray_prefab_{}", directory.as_os_str().to_str().unwrap()); + let desc = &wgpu::TextureDescriptor { + label: Some(&label), + size: wgpu::Extent3d { + width: size.x, + height: size.y, + depth_or_array_layers: layers, + }, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::Rgba8UnormSrgb, + usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST, + mip_level_count: 1, + sample_count: 1, + view_formats: &[], + }; + + renderer.device().create_texture_with_data( + renderer.queue(), + desc, + TextureDataOrder::MipMajor, + &data + ) +} + +pub fn load_texture2d_prefab( + renderer: &Renderer, + assman: &AssetManager, + path: &Path, +) -> wgpu::Texture { + let image = image::load( + BufReader::new(assman.open_asset(path).expect("Failed to open texture file")), + image::ImageFormat::Png + ).unwrap().to_rgba8(); + let size = image.dimensions(); + let data = image.into_raw(); + + let label = format!("texture2d_prefab_{}", path.file_name().unwrap().to_str().unwrap()); + let desc = wgpu::TextureDescriptor { + label: Some(&label), + size: wgpu::Extent3d { + width: size.0, + height: size.1, + depth_or_array_layers: 1, + }, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::Rgba8UnormSrgb, + usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST, + mip_level_count: 1, + sample_count: 1, + view_formats: &[], + }; + + renderer.device().create_texture_with_data( + renderer.queue(), + &desc, + TextureDataOrder::MipMajor, + &data + ) +} + +pub fn load_obj_prefab( + renderer: &Renderer, + assman: &AssetManager, + path: &Path, +) -> BufferPair { + let mut reader = BufReader::new( + assman.open_asset(path).expect("Failed to open texture file") + ); + + let (model, _) = tobj::load_obj_buf( + &mut reader, + &tobj::GPU_LOAD_OPTIONS, + |_| unimplemented!() + ).unwrap(); + + assert_eq!(model.len(), 1, "only single model supported at the moment, sowwy :3"); + let mesh = &model[0].mesh; + debug_assert!(mesh.normal_indices.is_empty() && mesh.texcoord_indices.is_empty(), "forgor single_index"); + + let tex_coords = bytemuck::cast_slice::(&mesh.texcoords); + let positions = bytemuck::cast_slice::(&mesh.positions); + let normals = bytemuck::cast_slice::(&mesh.normals); + + let vertex_buffer: Vec<_> = (0..positions.len()).map(|i| { + ModelVertex { + tex_coords: [tex_coords[i][0], 1. - tex_coords[i][1]], + position: positions[i], + _padding: 0, + normal: normals[i], + } + }).collect(); + + let vertex_buffer = renderer.device().create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("obj_vertex_buffer"), + contents: bytemuck::cast_slice(&vertex_buffer), + usage: wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::VERTEX, + }); + + let index_buffer = renderer.device().create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("obj_index_buffer"), + contents: bytemuck::cast_slice(&mesh.indices), + usage: wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::INDEX, + }); + + BufferPair { + vertex: vertex_buffer, + vertex_len: positions.len() as u32, + index: index_buffer, + index_len: mesh.indices.len() as u32, + } +} diff --git a/kubi/src/prefabs/texture.rs b/kubi/src/prefabs/texture.rs deleted file mode 100644 index caa23dd..0000000 --- a/kubi/src/prefabs/texture.rs +++ /dev/null @@ -1,75 +0,0 @@ -use glam::UVec2; -use strum::IntoEnumIterator; -use rayon::prelude::*; -use wgpu::util::{DeviceExt, TextureDataOrder}; -use std::{io::BufReader, path::PathBuf}; -use crate::{filesystem::AssetManager, rendering::Renderer}; -use super::AssetPaths; - -pub fn load_texture2darray_prefab( - renderer: &Renderer, - assman: &AssetManager, - directory: PathBuf, -) -> wgpu::Texture { - log::info!("started loading {}", directory.as_os_str().to_str().unwrap()); - - //Load raw images - let tex_files: Vec<&'static str> = T::iter().map(|x| x.file_name()).collect(); - let raw_images: Vec<(Vec, UVec2)> = tex_files.par_iter().map(|&file_name| { - log::info!("loading texture {}", file_name); - - //Get path to the image and open the file - let reader = { - let path = directory.join(file_name); - BufReader::new(assman.open_asset(&path).expect("Failed to open texture file")) - }; - - //Parse image data - let (image_data, dimensions) = { - let image = image::load( - reader, - image::ImageFormat::Png - ).unwrap().to_rgba8(); - let dimensions = image.dimensions(); - (image.into_raw(), dimensions) - }; - (image_data, UVec2::from(dimensions)) - }).collect(); - - assert!(!raw_images.is_empty(), "no images loaded"); - //TODO: check same size - - log::info!("done loading texture files, uploading to the gpu"); - - let size = raw_images[0].1; - let layers = raw_images.len() as u32; - - //Concat data into a single vec - let mut data = Vec::with_capacity((size.x * size.y * layers * 4) as usize); - for (layer_data, _) in raw_images { - data.extend_from_slice(&layer_data); - } - - //Upload images to the GPU - let desc = &wgpu::TextureDescriptor { - label: Some("block_diffuse_texture"), - size: wgpu::Extent3d { - width: size.x, - height: size.y, - depth_or_array_layers: layers, - }, - dimension: wgpu::TextureDimension::D2, - format: wgpu::TextureFormat::Rgba8UnormSrgb, - usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST, - mip_level_count: 1, - sample_count: 1, - view_formats: &[], - }; - - renderer.device().create_texture_with_data( - renderer.queue(), - desc, - TextureDataOrder::MipMajor, - &data - ) -} diff --git a/kubi/src/rendering.rs b/kubi/src/rendering.rs index f3342ab..4b8c2f9 100644 --- a/kubi/src/rendering.rs +++ b/kubi/src/rendering.rs @@ -6,6 +6,7 @@ use crate::{events::WindowResizedEvent, hui_integration::kubi_ui_draw, state::is mod renderer; mod primitives; mod selection_box; +mod entities; pub use renderer::Renderer; pub mod background; @@ -35,8 +36,9 @@ pub fn init_rendering() -> Workload { ( depth::init_depth_texture, camera_uniform::init_camera_uniform_buffer, - world::init_world_render_state, //req: depth, camera primitives::init_primitives, + world::init_world_render_state, //req: depth, camera + entities::init_entities_render_state, //req: depth, camera selection_box::init_selection_box_render_state, //req: depth, camera, primitives ).into_sequential_workload() } @@ -65,7 +67,6 @@ pub fn render_master(storages: AllStoragesViewMut) { let surface_view = surface_texture.texture.create_view(&wgpu::TextureViewDescriptor::default()); let mut data = RenderCtx { - //renderer: &renderer, encoder: &mut encoder, surface_view: &surface_view, }; @@ -74,8 +75,8 @@ pub fn render_master(storages: AllStoragesViewMut) { if storages.run(is_ingame) { storages.run_with_data(world::draw_world, &mut data); storages.run_with_data(selection_box::draw_selection_box, &mut data); + storages.run_with_data(entities::render_entities, &mut data); } - storages.run_with_data(kubi_ui_draw, &mut data); renderer.queue().submit([encoder.finish()]); diff --git a/kubi/src/rendering/entities.rs b/kubi/src/rendering/entities.rs index 3282cc9..a91e2bb 100644 --- a/kubi/src/rendering/entities.rs +++ b/kubi/src/rendering/entities.rs @@ -1,58 +1,69 @@ -// use shipyard::{NonSendSync, UniqueViewMut, UniqueView, View, IntoIter, IntoWithId}; -// use glium::{DepthTest, Depth, PolygonMode, BackfaceCullingMode, DrawParameters, Surface, uniform}; -// use kubi_shared::{entity::Entity, transform::Transform}; -// use crate::{ -// prefabs::ColoredShaderPrefab, -// camera::Camera, -// settings::GameSettings -// }; -// use super::{ -// RenderTarget, -// primitives::cube::CenteredCubePrimitive -// }; +use shipyard::{AllStoragesView, IntoIter, IntoWithId, Unique, UniqueView, View}; +use kubi_shared::{entity::Entity, transform::Transform}; +use crate::{ + camera::Camera, prefabs::GpuPrefabs, settings::GameSettings +}; -// // TODO: entity models -// pub fn render_entities( -// mut target: NonSendSync>, -// buffers: NonSendSync>, -// program: NonSendSync>, -// camera: View, -// settings: UniqueView, -// entities: View, -// transform: View, -// ) { -// let (camera_id, camera) = camera.iter().with_id().next().expect("No cameras in the scene"); +use super::{camera_uniform::CameraUniformBuffer, depth::DepthTexture, RenderCtx}; -// let draw_parameters = DrawParameters { -// depth: Depth { -// test: DepthTest::IfLess, -// write: true, -// ..Default::default() -// }, -// multisampling: settings.msaa.is_some(), -// polygon_mode: PolygonMode::Fill, -// backface_culling: BackfaceCullingMode::CullClockwise, -// ..Default::default() -// }; -// let view = camera.view_matrix.to_cols_array_2d(); -// let perspective = camera.perspective_matrix.to_cols_array_2d(); +mod pipeline; -// for (entity_id, (_, trans)) in (&entities, &transform).iter().with_id() { -// //skip rendering camera holder (as the entity would block the view) -// if entity_id == camera_id { continue } +#[derive(Unique)] +pub struct EntitiesRenderState { + pub pipeline: wgpu::RenderPipeline, +} -// //render entity -// target.0.draw( -// &buffers.0, -// &buffers.1, -// &program.0, -// &uniform! { -// color: [1.0, 1.0, 1.0, 1.0_f32], -// model: trans.0.to_cols_array_2d(), -// view: view, -// perspective: perspective, -// }, -// &draw_parameters -// ).unwrap(); -// } -// } +pub fn init_entities_render_state(storages: AllStoragesView) { + storages.add_unique(EntitiesRenderState { + pipeline: storages.run(pipeline::init_entities_pipeline), + }); +} + +// TODO: entity models +pub fn render_entities( + ctx: &mut RenderCtx, + state: UniqueView, + depth: UniqueView, + prefabs: UniqueView, + camera_ubo: UniqueView, + camera: View, + settings: UniqueView, + entities: View, + transform: View, +) { + let mut rpass = ctx.encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + label: Some("rpass_draw_entities"), + color_attachments: &[Some(wgpu::RenderPassColorAttachment { + view: ctx.surface_view, + resolve_target: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Load, + store: wgpu::StoreOp::Store, + }, + })], + depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment { + view: &depth.depth_view, + depth_ops: Some(wgpu::Operations { + load: wgpu::LoadOp::Load, + store: wgpu::StoreOp::Store, + }), + stencil_ops: None, + }), + ..Default::default() + }); + + rpass.set_pipeline(&state.pipeline); + rpass.set_bind_group(0, &prefabs.player_model_diffuse_bind_group, &[]); + rpass.set_bind_group(1, &camera_ubo.camera_bind_group, &[]); + rpass.set_vertex_buffer(0, prefabs.player_model.vertex.slice(..)); + rpass.set_index_buffer(prefabs.player_model.index.slice(..), wgpu::IndexFormat::Uint32); + rpass.draw_indexed(0..prefabs.player_model.index_len, 0, 0..1); + + // let (camera_id, _camera) = camera.iter().with_id().next().expect("No cameras in the scene"); + + // for (entity_id, (_, trans)) in (&entities, &transform).iter().with_id() { + // //skip rendering camera holder (as the entity would block the view) + // if entity_id == camera_id { continue } + + // } +} diff --git a/kubi/src/rendering/entities/pipeline.rs b/kubi/src/rendering/entities/pipeline.rs new file mode 100644 index 0000000..bb963ec --- /dev/null +++ b/kubi/src/rendering/entities/pipeline.rs @@ -0,0 +1,61 @@ +use shipyard::UniqueView; +use wgpu::include_wgsl; +use crate::{prefabs::{GpuPrefabs, ModelVertex}, rendering::{camera_uniform::CameraUniformBuffer, Renderer}}; + +pub fn init_entities_pipeline( + renderer: UniqueView, + prefabs: UniqueView, + camera_ubo: UniqueView, +) -> wgpu::RenderPipeline { + let module = renderer.device().create_shader_module(include_wgsl!("../../../shaders/entities.wgsl")); + + let pipeline_layout = renderer.device().create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("entities_pipeline_layout"), + bind_group_layouts: &[ + &prefabs.player_model_diffuse_bind_group_layout, + &camera_ubo.camera_bind_group_layout, + ], + push_constant_ranges: &[], + }); + + renderer.device().create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("entities_pipeline"), + layout: Some(&pipeline_layout), + vertex: wgpu::VertexState { + module: &module, + compilation_options: wgpu::PipelineCompilationOptions::default(), + entry_point: "vs_main", + buffers: &[ + ModelVertex::LAYOUT, + ], + }, + fragment: Some(wgpu::FragmentState { + module: &module, + compilation_options: wgpu::PipelineCompilationOptions::default(), + entry_point: "fs_main", + targets: &[Some(wgpu::ColorTargetState { + format: renderer.surface_config().format, + blend: Some(wgpu::BlendState::REPLACE), + write_mask: wgpu::ColorWrites::COLOR, + })], + }), + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleList, + strip_index_format: None, + front_face: wgpu::FrontFace::Ccw, + cull_mode: Some(wgpu::Face::Back), + polygon_mode: wgpu::PolygonMode::Fill, + conservative: false, + unclipped_depth: false, + }, + depth_stencil: Some(wgpu::DepthStencilState { + format: wgpu::TextureFormat::Depth32Float, + depth_write_enabled: true, + depth_compare: wgpu::CompareFunction::Less, + bias: wgpu::DepthBiasState::default(), + stencil: wgpu::StencilState::default(), + }), + multisample: wgpu::MultisampleState::default(), + multiview: None, + }) +} diff --git a/kubi/src/rendering/selection_box.rs b/kubi/src/rendering/selection_box.rs index d33b4c7..ae6a0ce 100644 --- a/kubi/src/rendering/selection_box.rs +++ b/kubi/src/rendering/selection_box.rs @@ -49,7 +49,7 @@ pub fn draw_selection_box( view: &depth.depth_view, depth_ops: Some(wgpu::Operations { load: wgpu::LoadOp::Load, - store: wgpu::StoreOp::Discard, + store: wgpu::StoreOp::Store, }), stencil_ops: None, }), diff --git a/kubi/src/rendering/world.rs b/kubi/src/rendering/world.rs index 5e57781..eb145c3 100644 --- a/kubi/src/rendering/world.rs +++ b/kubi/src/rendering/world.rs @@ -3,7 +3,7 @@ use shipyard::{AllStoragesView, IntoIter, NonSendSync, Unique, UniqueView, View} use kubi_shared::chunk::CHUNK_SIZE; use crate::{ camera::Camera, - prefabs::TexturePrefabs, + prefabs::GpuPrefabs, world::{ChunkMeshStorage, ChunkStorage}, }; use super::{camera_uniform::CameraUniformBuffer, depth::DepthTexture, RenderCtx}; @@ -30,7 +30,7 @@ pub fn draw_world( state: UniqueView, camera_ubo: UniqueView, depth: UniqueView, - textures: UniqueView, + textures: UniqueView, camera: View, chunks: UniqueView, meshes: NonSendSync>, diff --git a/kubi/src/rendering/world/pipeline.rs b/kubi/src/rendering/world/pipeline.rs index 9a63f65..799fd31 100644 --- a/kubi/src/rendering/world/pipeline.rs +++ b/kubi/src/rendering/world/pipeline.rs @@ -1,13 +1,13 @@ use shipyard::UniqueView; use crate::{ - prefabs::TexturePrefabs, + prefabs::GpuPrefabs, rendering::{camera_uniform::CameraUniformBuffer, depth::DepthTexture, world::ChunkVertex, Renderer} }; pub fn init_world_pipeline( ren: UniqueView, depth: UniqueView, - textures: UniqueView, + textures: UniqueView, camera_ubo: UniqueView, ) -> wgpu::RenderPipeline { let shader = ren.device().create_shader_module( From 438b79e8f0f9c5d2bd1fa194378e2e1fa62838cc Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Wed, 8 May 2024 13:35:03 +0200 Subject: [PATCH 45/51] uwu --- .gitignore | 3 +++ assets-src/playermodel1.blend | Bin 1127008 -> 1127504 bytes assets/playermodel1.obj | 26 ++++++++++++------------ kubi/src/rendering/entities/pipeline.rs | 2 +- 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index 0b9b7c9..4117f23 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,6 @@ _visualizer.json #but keep the dxcompiler.dll/dxil.dll !dxcompiler.dll !dxil.dll + +# blender backup files +*.blend1 diff --git a/assets-src/playermodel1.blend b/assets-src/playermodel1.blend index 4818ac7cce2c5b680c9cb895ea2109f6bda0f2f0..d9449fb3e5df560ed0a845c4ad4da0226b24210a 100644 GIT binary patch delta 101833 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 delta 106561 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 Date: Wed, 8 May 2024 15:02:16 +0200 Subject: [PATCH 46/51] players :3 --- assets-src/playermodel1.blend | Bin 1127504 -> 1127504 bytes assets/playermodel1.obj | 30 ++++----- kubi/shaders/entities.wgsl | 12 +++- kubi/src/rendering.rs | 1 + kubi/src/rendering/entities.rs | 24 ++++---- kubi/src/rendering/entities/instance.rs | 77 ++++++++++++++++++++++++ kubi/src/rendering/entities/pipeline.rs | 3 + 7 files changed, 118 insertions(+), 29 deletions(-) create mode 100644 kubi/src/rendering/entities/instance.rs diff --git a/assets-src/playermodel1.blend b/assets-src/playermodel1.blend index d9449fb3e5df560ed0a845c4ad4da0226b24210a..1f49949e72f90600ba3d76dea2a8cc03b4382120 100644 GIT binary patch delta 83766 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 delta 84334 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 U@S8@`GBB4{d0x zIcza&I|g3fA0hJfz-TLTGH!1diraciTsI z2ougMdi$`2y}XuzQ|kTo5IV4r`HS{de=X4;;)F~3m_KA7_t=%1!;Qbv1`QiCjGrK8 zV02J*xNUTZK;fDsI@Cs>=5WQMHHX{?sD;=FLQ)KfhtKvmK>o4p5bra$_9PO+Anxj9&2~YNq9iBhHCYevG z{x+_w_t!><0~qbA{(LKfIN_y%(Vr>OUi`f3Z^hbre;FbAi}vo%27~_+#0hV0>*L4u zc&j@c(owE=m;kbk$2x4iTf#Ff&CNw@j&Qm1aQ;f=7d5+a7Kpp0@Z|Q*?UUkO%lBTf z9ld-{mh>@q7NJ@e6(D-^p^+@J3eO*5+>xYxPa>;#%zI-BY-xRSneU zvvZ4gaqz~6YIM#jgfOeL#Lzxw37f#*JFo26tV?QLcD`5jw&LeCZ^*cW&^1Ht9D{Xk z&sOa?qF@74z3j9d(ch{LJ0ARkLqaQeZXU({o5LPxp&RJstvffrvCU=N-5c_d{b&E{ z#r-7?;y)kj%=f#H&~U%r$X_i^FdMgbf9}WQ`2IQi-L+TZqQ%W{-r;1k?)1yg_7+?m zS!lm7)kWEv2M!qCbYQOodnMa%mc~16zj+&l1+$k8EuliV|Cw~p@*4*<4lI-xjBb9Z ze-g9fJ-tr4XrJbj3ZK}Mn)1MXn=dbJU-?K0oSdP!DnnuFHrs`D6PwTOm%T55CHL+9 zD)FA@T0TU8{`NXwL$lp)axXoh>yct>5x&dU9nid8ajeIgWnIU}FZ)zuklcF3z20Bc z@$;209n@_9^|PO+?0@U04U89-G}~{tOdefmD56DS<$eQxmdsPzV&Bf$f51tFzm><& zZW>#}6Pi={wcYgwM>D&_$}oS@fUoqK@JHO}3inNH{&IM}xljLa|J=eM{d(S$Czk4E zckJbgYA^Y~rwMw|NibDL72m;KLObbpA=;Nppe`ygd3Mvz#qt;a|GV4h*^xboDK;>U zdiMr;hn9r@H*LTTgT3`{TSSamr5nAt_oxB0cjckgIn)WrKD)^=3(h` p{iKP0>{ zeL&Obh&w-tpWP4ndyBv9r~%2YPH=, @location(1) position: vec3, @location(2) normal: vec3, + @location(3) mat_row0: vec4, + @location(4) mat_row1: vec4, + @location(5) mat_row2: vec4, + @location(6) mat_row3: vec4, } struct VertexOutput { @@ -21,8 +25,14 @@ struct VertexOutput { fn vs_main( in: VertexInput, ) -> VertexOutput { + let inst_mat = mat4x4( + in.mat_row0, + in.mat_row1, + in.mat_row2, + in.mat_row3, + ); var out: VertexOutput; - out.clip_position = camera.view_proj * vec4(in.position, 1.0); + out.clip_position = camera.view_proj * (inst_mat * vec4(in.position, 1.0)); out.uv = in.uv; out.normal = in.normal; return out; diff --git a/kubi/src/rendering.rs b/kubi/src/rendering.rs index 4b8c2f9..7c5736e 100644 --- a/kubi/src/rendering.rs +++ b/kubi/src/rendering.rs @@ -54,6 +54,7 @@ pub fn update_rendering_late() -> Workload { ( camera_uniform::update_camera_uniform_buffer, selection_box::update_selection_box_render_state.run_if(is_ingame), + entities::update_entities_render_state.run_if(is_ingame), ).into_workload() } diff --git a/kubi/src/rendering/entities.rs b/kubi/src/rendering/entities.rs index a91e2bb..84865cf 100644 --- a/kubi/src/rendering/entities.rs +++ b/kubi/src/rendering/entities.rs @@ -6,19 +6,24 @@ use crate::{ use super::{camera_uniform::CameraUniformBuffer, depth::DepthTexture, RenderCtx}; +mod instance; mod pipeline; #[derive(Unique)] pub struct EntitiesRenderState { pub pipeline: wgpu::RenderPipeline, + pub instance_buffer: instance::InstanceBuffer, } pub fn init_entities_render_state(storages: AllStoragesView) { storages.add_unique(EntitiesRenderState { pipeline: storages.run(pipeline::init_entities_pipeline), + instance_buffer: storages.run(instance::create_instance_buffer), }); } +pub use instance::update_instance_buffer as update_entities_render_state; + // TODO: entity models pub fn render_entities( ctx: &mut RenderCtx, @@ -26,11 +31,11 @@ pub fn render_entities( depth: UniqueView, prefabs: UniqueView, camera_ubo: UniqueView, - camera: View, - settings: UniqueView, - entities: View, - transform: View, ) { + if state.instance_buffer.count == 0 { + return + } + let mut rpass = ctx.encoder.begin_render_pass(&wgpu::RenderPassDescriptor { label: Some("rpass_draw_entities"), color_attachments: &[Some(wgpu::RenderPassColorAttachment { @@ -56,14 +61,7 @@ pub fn render_entities( rpass.set_bind_group(0, &prefabs.player_model_diffuse_bind_group, &[]); rpass.set_bind_group(1, &camera_ubo.camera_bind_group, &[]); rpass.set_vertex_buffer(0, prefabs.player_model.vertex.slice(..)); + rpass.set_vertex_buffer(1, state.instance_buffer.buffer.slice(..)); rpass.set_index_buffer(prefabs.player_model.index.slice(..), wgpu::IndexFormat::Uint32); - rpass.draw_indexed(0..prefabs.player_model.index_len, 0, 0..1); - - // let (camera_id, _camera) = camera.iter().with_id().next().expect("No cameras in the scene"); - - // for (entity_id, (_, trans)) in (&entities, &transform).iter().with_id() { - // //skip rendering camera holder (as the entity would block the view) - // if entity_id == camera_id { continue } - - // } + rpass.draw_indexed(0..prefabs.player_model.index_len, 0, 0..state.instance_buffer.count); } diff --git a/kubi/src/rendering/entities/instance.rs b/kubi/src/rendering/entities/instance.rs new file mode 100644 index 0000000..271949a --- /dev/null +++ b/kubi/src/rendering/entities/instance.rs @@ -0,0 +1,77 @@ +use bytemuck::{Pod, Zeroable}; +use kubi_shared::{entity::Entity, transform::Transform}; +use renderer::Renderer; +use shipyard::{EntityId, IntoIter, IntoWithId, UniqueView, UniqueViewMut, View}; + +use crate::{camera::Camera, rendering::renderer}; + +use super::EntitiesRenderState; + +#[derive(Clone, Copy, Pod, Zeroable)] +#[repr(C, packed)] +pub struct InstanceData { + pub mat: [f32; 4 * 4], +} + +impl InstanceData { + pub const LAYOUT: wgpu::VertexBufferLayout<'static> = wgpu::VertexBufferLayout { + array_stride: std::mem::size_of::() as wgpu::BufferAddress, + step_mode: wgpu::VertexStepMode::Instance, + attributes: &wgpu::vertex_attr_array![ + 3 => Float32x4, + 4 => Float32x4, + 5 => Float32x4, + 6 => Float32x4, + ], + }; +} + +pub struct InstanceBuffer { + pub count: u32, + pub buffer: wgpu::Buffer, +} + +pub fn create_instance_buffer( + renderer: UniqueView, +) -> InstanceBuffer { + let buffer = renderer.device().create_buffer(&wgpu::BufferDescriptor { + label: Some("instance_buffer"), + size: 255 * std::mem::size_of::() as u64, + usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST, + mapped_at_creation: false, + }); + InstanceBuffer { count: 0, buffer } +} + +pub fn update_instance_buffer( + renderer: UniqueView, + mut state: UniqueViewMut, + entities: View, + transforms: View, + camera: View, +) { + //Get id of the camera entity (this assumes a single camera entity) + let cam_id = (&camera) + .iter().with_id().next() + .map(|(x, _)| x) + .unwrap_or(EntityId::dead()); + + // Create a list of instance data for all entities except ones that have camera attached + let mut instances = Vec::with_capacity(entities.len() - 1); + for (id, (_, trans)) in (&entities, &transforms).iter().with_id() { + if id == cam_id { continue } + instances.push(InstanceData { + mat: trans.0.to_cols_array(), + }); + } + + state.instance_buffer.count = instances.len() as u32; + + if !instances.is_empty() { + renderer.queue().write_buffer( + &state.instance_buffer.buffer, + 0, + bytemuck::cast_slice(&instances) + ); + } +} diff --git a/kubi/src/rendering/entities/pipeline.rs b/kubi/src/rendering/entities/pipeline.rs index 40f61a8..b7e8e42 100644 --- a/kubi/src/rendering/entities/pipeline.rs +++ b/kubi/src/rendering/entities/pipeline.rs @@ -2,6 +2,8 @@ use shipyard::UniqueView; use wgpu::include_wgsl; use crate::{prefabs::{GpuPrefabs, ModelVertex}, rendering::{camera_uniform::CameraUniformBuffer, Renderer}}; +use super::instance::InstanceData; + pub fn init_entities_pipeline( renderer: UniqueView, prefabs: UniqueView, @@ -27,6 +29,7 @@ pub fn init_entities_pipeline( entry_point: "vs_main", buffers: &[ ModelVertex::LAYOUT, + InstanceData::LAYOUT, ], }, fragment: Some(wgpu::FragmentState { From 1bf61500b3e2f25cb51a8cc4d200c7c9e1bdd5c9 Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Wed, 8 May 2024 20:13:19 +0200 Subject: [PATCH 47/51] trans chunks are visible again! --- kubi/shaders/world.wgsl | 5 ++ kubi/src/rendering.rs | 1 + kubi/src/rendering/world.rs | 87 ++++++++++++++++++++++++---- kubi/src/rendering/world/pipeline.rs | 49 +++++++++++++++- kubi/src/world/loading.rs | 4 +- kubi/src/world/mesh.rs | 2 +- 6 files changed, 131 insertions(+), 17 deletions(-) diff --git a/kubi/shaders/world.wgsl b/kubi/shaders/world.wgsl index 185b3bd..ed5d35d 100644 --- a/kubi/shaders/world.wgsl +++ b/kubi/shaders/world.wgsl @@ -45,3 +45,8 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4 { } return color; } + +@fragment +fn fs_main_trans(in: VertexOutput) -> @location(0) vec4 { + return textureSample(t_diffuse, s_diffuse, in.uv, in.tex_index); +} diff --git a/kubi/src/rendering.rs b/kubi/src/rendering.rs index 7c5736e..923e8ac 100644 --- a/kubi/src/rendering.rs +++ b/kubi/src/rendering.rs @@ -77,6 +77,7 @@ pub fn render_master(storages: AllStoragesViewMut) { storages.run_with_data(world::draw_world, &mut data); storages.run_with_data(selection_box::draw_selection_box, &mut data); storages.run_with_data(entities::render_entities, &mut data); + storages.run_with_data(world::rpass_submit_trans_bundle, &mut data); } storages.run_with_data(kubi_ui_draw, &mut data); diff --git a/kubi/src/rendering/world.rs b/kubi/src/rendering/world.rs index eb145c3..772e1bb 100644 --- a/kubi/src/rendering/world.rs +++ b/kubi/src/rendering/world.rs @@ -1,12 +1,12 @@ use glam::Vec3; -use shipyard::{AllStoragesView, IntoIter, NonSendSync, Unique, UniqueView, View}; +use shipyard::{AllStoragesView, IntoIter, NonSendSync, Unique, UniqueView, UniqueViewMut, View}; use kubi_shared::chunk::CHUNK_SIZE; use crate::{ camera::Camera, prefabs::GpuPrefabs, world::{ChunkMeshStorage, ChunkStorage}, }; -use super::{camera_uniform::CameraUniformBuffer, depth::DepthTexture, RenderCtx}; +use super::{camera_uniform::CameraUniformBuffer, depth::DepthTexture, RenderCtx, Renderer}; mod pipeline; mod vertex; @@ -15,19 +15,22 @@ pub use vertex::ChunkVertex; #[derive(Unique)] pub struct WorldRenderState { pub pipeline: wgpu::RenderPipeline, - //pub trans_chunk_queue: Vec, + pub pipeline_trans: wgpu::RenderPipeline, + pub trans_bundle: Option, } pub fn init_world_render_state(storages: AllStoragesView) { + let (pipeline, pipeline_trans) = storages.run(pipeline::init_world_pipeline); storages.add_unique(WorldRenderState { - pipeline: storages.run(pipeline::init_world_pipeline), - //trans_chunk_queue: Vec::with_capacity(512), + pipeline, pipeline_trans, + trans_bundle: None, }) } pub fn draw_world( ctx: &mut RenderCtx, - state: UniqueView, + mut state: UniqueViewMut, + renderer: UniqueView, camera_ubo: UniqueView, depth: UniqueView, textures: UniqueView, @@ -63,6 +66,23 @@ pub fn draw_world( render_pass.set_bind_group(0, &textures.block_diffuse_bind_group, &[]); render_pass.set_bind_group(1, &camera_ubo.camera_bind_group, &[]); + let mut trans_bundle_used = false; + let mut trans_bundle = renderer.device().create_render_bundle_encoder(&wgpu::RenderBundleEncoderDescriptor { + label: Some("trans_bundle_encoder"), + color_formats: &[Some(renderer.surface_config().format)], + depth_stencil: Some(wgpu::RenderBundleDepthStencil { + format: depth.depth_texture.format(), + depth_read_only: true, + stencil_read_only: true, + }), + sample_count: 1, + multiview: None, + }); + + trans_bundle.set_pipeline(&state.pipeline_trans); + trans_bundle.set_bind_group(0, &textures.block_diffuse_bind_group, &[]); + trans_bundle.set_bind_group(1, &camera_ubo.camera_bind_group, &[]); + for (&position, chunk) in &chunks.chunks { if let Some(key) = chunk.mesh_index { let mesh = meshes.get(key).expect("Mesh index pointing to nothing"); @@ -81,16 +101,61 @@ pub fn draw_world( } //Draw chunk mesh - if mesh.main.index.size() > 0 { + if mesh.main.index_len > 0 { render_pass.set_index_buffer(mesh.main.index.slice(..), wgpu::IndexFormat::Uint32); render_pass.set_vertex_buffer(0, mesh.main.vertex.slice(..)); render_pass.draw_indexed(0..mesh.main.index_len, 0, 0..1); } - //TODO trans chunks - // if mesh.trans_index_buffer.len() > 0 { - // trans_queue.0.push(position); - // } + //Draw transparent chunk mesh + if mesh.trans.index_len > 0 { + trans_bundle_used = true; + trans_bundle.set_index_buffer(mesh.trans.index.slice(..), wgpu::IndexFormat::Uint32); + trans_bundle.set_vertex_buffer(0, mesh.trans.vertex.slice(..)); + trans_bundle.draw_indexed(0..mesh.trans.index_len, 0, 0..1); + } } } + + drop(render_pass); + + if trans_bundle_used { + let bundle = trans_bundle.finish(&wgpu::RenderBundleDescriptor { + label: Some("trans_bundle"), + }); + state.trans_bundle = Some(bundle); + } else { + state.trans_bundle = None; + } +} + +pub fn rpass_submit_trans_bundle( + ctx: &mut RenderCtx, + state: UniqueView, + depth: UniqueView, +) { + let Some(bundle) = state.trans_bundle.as_ref() else { + return + }; + let mut rpass = ctx.encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + label: Some("rpass_submit_trans_bundle"), + color_attachments: &[Some(wgpu::RenderPassColorAttachment { + view: ctx.surface_view, + resolve_target: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Load, + store: wgpu::StoreOp::Store, + }, + })], + depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment { + view: &depth.depth_view, + depth_ops: Some(wgpu::Operations { + load: wgpu::LoadOp::Load, + store: wgpu::StoreOp::Store, + }), + stencil_ops: None, + }), + ..Default::default() + }); + rpass.execute_bundles(Some(bundle)); } diff --git a/kubi/src/rendering/world/pipeline.rs b/kubi/src/rendering/world/pipeline.rs index 799fd31..692cb7c 100644 --- a/kubi/src/rendering/world/pipeline.rs +++ b/kubi/src/rendering/world/pipeline.rs @@ -9,7 +9,7 @@ pub fn init_world_pipeline( depth: UniqueView, textures: UniqueView, camera_ubo: UniqueView, -) -> wgpu::RenderPipeline { +) -> (wgpu::RenderPipeline, wgpu::RenderPipeline) { let shader = ren.device().create_shader_module( wgpu::include_wgsl!("../../../shaders/world.wgsl") ); @@ -23,7 +23,7 @@ pub fn init_world_pipeline( push_constant_ranges: &[], }); - ren.device().create_render_pipeline(&wgpu::RenderPipelineDescriptor { + let pipeline_main = ren.device().create_render_pipeline(&wgpu::RenderPipelineDescriptor { label: Some("world_pipeline"), layout: Some(&world_pipeline_layout), fragment: Some(wgpu::FragmentState { @@ -62,5 +62,48 @@ pub fn init_world_pipeline( }), multisample: wgpu::MultisampleState::default(), multiview: None, - }) + }); + + let pipeline_trans = ren.device().create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("world_pipeline_trans"), + layout: Some(&world_pipeline_layout), + fragment: Some(wgpu::FragmentState { + module: &shader, + entry_point: "fs_main_trans", + compilation_options: wgpu::PipelineCompilationOptions::default(), + targets: &[Some(wgpu::ColorTargetState { + format: ren.surface_config().format, + blend: Some(wgpu::BlendState::ALPHA_BLENDING), + write_mask: wgpu::ColorWrites::COLOR, + })], + }), + vertex: wgpu::VertexState { + module: &shader, + entry_point: "vs_main", + compilation_options: wgpu::PipelineCompilationOptions::default(), + buffers: &[ + ChunkVertex::LAYOUT, + ], + }, + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleList, + strip_index_format: None, + cull_mode: None, + front_face: wgpu::FrontFace::Ccw, + unclipped_depth: false, + polygon_mode: wgpu::PolygonMode::Fill, + conservative: false, + }, + depth_stencil: Some(wgpu::DepthStencilState { + format: depth.depth_texture.format(), + depth_write_enabled: false, + depth_compare: wgpu::CompareFunction::Less, + stencil: wgpu::StencilState::default(), + bias: wgpu::DepthBiasState::default(), + }), + multisample: wgpu::MultisampleState::default(), + multiview: None, + }); + + (pipeline_main, pipeline_trans) } diff --git a/kubi/src/world/loading.rs b/kubi/src/world/loading.rs index 6037473..0033ec8 100644 --- a/kubi/src/world/loading.rs +++ b/kubi/src/world/loading.rs @@ -362,9 +362,9 @@ fn process_completed_tasks( let trans_buffer_pair = BufferPair { vertex: vtx_buffer_trans, - vertex_len: vertices.len() as u32, + vertex_len: trans_vertices.len() as u32, index: idx_buffer_trans, - index_len: indices.len() as u32, + index_len: trans_indices.len() as u32, }; let mesh = ChunkMesh { diff --git a/kubi/src/world/mesh.rs b/kubi/src/world/mesh.rs index 3b43116..98d1ec6 100644 --- a/kubi/src/world/mesh.rs +++ b/kubi/src/world/mesh.rs @@ -33,7 +33,7 @@ pub fn generate_mesh(position: IVec3, data: MeshGenData) -> ( }; let mut builder = MeshBuilder::new_with_offset((position * CHUNK_SIZE as i32).as_vec3()); - let mut trans_builder = MeshBuilder::new(); + let mut trans_builder = MeshBuilder::new_with_offset((position * CHUNK_SIZE as i32).as_vec3()); for x in 0..CHUNK_SIZE as i32 { for y in 0..CHUNK_SIZE as i32 { From 34a0c8c64807f79e21ace8c4bcbfdfdc6345e925 Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Mon, 13 May 2024 19:47:36 +0200 Subject: [PATCH 48/51] wip smoverlay --- kubi/shaders/c2d.wgsl | 1 + kubi/src/rendering/primitives.rs | 16 ++++++++++++++++ kubi/src/rendering/primitives/fstri.rs | 24 ++++++++++++++++++++++++ kubi/src/rendering/submerge/pipeline.rs | 14 ++++++++++++++ kubi/src/rendering/sumberge.rs | 2 ++ 5 files changed, 57 insertions(+) create mode 100644 kubi/shaders/c2d.wgsl create mode 100644 kubi/src/rendering/primitives/fstri.rs create mode 100644 kubi/src/rendering/submerge/pipeline.rs diff --git a/kubi/shaders/c2d.wgsl b/kubi/shaders/c2d.wgsl new file mode 100644 index 0000000..471ce88 --- /dev/null +++ b/kubi/shaders/c2d.wgsl @@ -0,0 +1 @@ +//TODO diff --git a/kubi/src/rendering/primitives.rs b/kubi/src/rendering/primitives.rs index c7e85f3..05ef112 100644 --- a/kubi/src/rendering/primitives.rs +++ b/kubi/src/rendering/primitives.rs @@ -2,7 +2,9 @@ use bytemuck::{Pod, Zeroable}; use shipyard::{IntoWorkload, Workload}; mod cube; +mod fstri; pub use cube::CubePrimitive; +pub use fstri::FstriPrimitive; pub fn init_primitives() -> Workload { ( @@ -23,3 +25,17 @@ impl PrimitiveVertex { attributes: &wgpu::vertex_attr_array![0 => Float32x3], }; } + +#[derive(Clone, Copy, Default, Pod, Zeroable)] +#[repr(C, packed)] +pub struct PrimitiveVertex2 { + pub position: [f32; 2], +} + +impl PrimitiveVertex2 { + pub const LAYOUT: wgpu::VertexBufferLayout<'static> = wgpu::VertexBufferLayout { + array_stride: std::mem::size_of::() as wgpu::BufferAddress, + step_mode: wgpu::VertexStepMode::Vertex, + attributes: &wgpu::vertex_attr_array![0 => Float32x2], + }; +} diff --git a/kubi/src/rendering/primitives/fstri.rs b/kubi/src/rendering/primitives/fstri.rs new file mode 100644 index 0000000..b6eb26d --- /dev/null +++ b/kubi/src/rendering/primitives/fstri.rs @@ -0,0 +1,24 @@ +use shipyard::{AllStoragesView, Unique, UniqueView}; +use wgpu::util::DeviceExt; +use crate::rendering::Renderer; +use super::PrimitiveVertex2; + +pub const FSTRI_VERTICES: &[PrimitiveVertex2] = &[ + PrimitiveVertex2 { position: [0.0, 0.0] }, + PrimitiveVertex2 { position: [1.0, 0.0] }, + PrimitiveVertex2 { position: [0.0, 1.0] }, + PrimitiveVertex2 { position: [1.0, 1.0] }, +]; + +#[derive(Unique)] +pub struct FstriPrimitive(wgpu::Buffer); + +pub fn init_fstri_primitive(storages: AllStoragesView) { + let renderer = storages.borrow::>().unwrap(); + let buffer = renderer.device().create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("fstri_vertex_buffer"), + contents: bytemuck::cast_slice(FSTRI_VERTICES), + usage: wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::VERTEX, + }); + storages.add_unique(FstriPrimitive(buffer)); +} diff --git a/kubi/src/rendering/submerge/pipeline.rs b/kubi/src/rendering/submerge/pipeline.rs new file mode 100644 index 0000000..0bcd41a --- /dev/null +++ b/kubi/src/rendering/submerge/pipeline.rs @@ -0,0 +1,14 @@ +pub fn create_render_pipeline( + ren: UniqueView, + stri_primitive: UniqueView, +) -> wgpu::RenderPipeline { + let shader = ren.device().create_shader_module( + wgpu::include_wgsl!("../../../shaders/c2d.wgsl") + ); + let pipeline_layout = ren.device().create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("smoverlay_pipeline_layout"), + bind_group_layouts: &[&ren.bind_group_layout], + push_constant_ranges: &[], + }); + //TODO +} diff --git a/kubi/src/rendering/sumberge.rs b/kubi/src/rendering/sumberge.rs index a44da40..89eebb0 100644 --- a/kubi/src/rendering/sumberge.rs +++ b/kubi/src/rendering/sumberge.rs @@ -1,3 +1,5 @@ +mod pipeline; + // use glium::{uniform, Blend, DrawParameters, Surface}; // use kubi_shared::transform::Transform; // use shipyard::{IntoIter, NonSendSync, UniqueView, UniqueViewMut, View}; From 1b096c07ed7a6b63a78cf402a974effa0d8e03ab Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Mon, 13 May 2024 23:43:39 +0200 Subject: [PATCH 49/51] add submerge overlay back --- kubi/shaders/c2d.wgsl | 15 +++- kubi/src/prefabs/loader.rs | 4 + kubi/src/rendering.rs | 12 ++- kubi/src/rendering/entities/instance.rs | 1 + kubi/src/rendering/entities/pipeline.rs | 2 + kubi/src/rendering/primitives.rs | 1 + kubi/src/rendering/primitives/cube.rs | 1 + kubi/src/rendering/primitives/fstri.rs | 10 +-- kubi/src/rendering/selection_box/pipeline.rs | 2 + kubi/src/rendering/selection_box/uniform.rs | 6 +- kubi/src/rendering/smoverlay.rs | 48 ++++++++++ kubi/src/rendering/smoverlay/pipeline.rs | 57 ++++++++++++ kubi/src/rendering/smoverlay/uniform.rs | 94 ++++++++++++++++++++ kubi/src/rendering/submerge/pipeline.rs | 14 --- kubi/src/rendering/sumberge.rs | 41 --------- kubi/src/rendering/world/pipeline.rs | 8 ++ kubi/src/settings.rs | 12 +-- 17 files changed, 257 insertions(+), 71 deletions(-) create mode 100644 kubi/src/rendering/smoverlay.rs create mode 100644 kubi/src/rendering/smoverlay/pipeline.rs create mode 100644 kubi/src/rendering/smoverlay/uniform.rs delete mode 100644 kubi/src/rendering/submerge/pipeline.rs delete mode 100644 kubi/src/rendering/sumberge.rs diff --git a/kubi/shaders/c2d.wgsl b/kubi/shaders/c2d.wgsl index 471ce88..c6fce2e 100644 --- a/kubi/shaders/c2d.wgsl +++ b/kubi/shaders/c2d.wgsl @@ -1 +1,14 @@ -//TODO +@group(0) @binding(0) +var color: vec4; + +@vertex +fn vs_main( + @location(0) position: vec2, +) -> @builtin(position) vec4 { + return vec4(position, 0.0, 1.0); +} + +@fragment +fn fs_main() -> @location(0) vec4 { + return color; +} diff --git a/kubi/src/prefabs/loader.rs b/kubi/src/prefabs/loader.rs index f32834b..ab11b32 100644 --- a/kubi/src/prefabs/loader.rs +++ b/kubi/src/prefabs/loader.rs @@ -80,6 +80,8 @@ pub fn load_texture2d_prefab( assman: &AssetManager, path: &Path, ) -> wgpu::Texture { + log::info!("loading texture2d: {path:?}"); + let image = image::load( BufReader::new(assman.open_asset(path).expect("Failed to open texture file")), image::ImageFormat::Png @@ -116,6 +118,8 @@ pub fn load_obj_prefab( assman: &AssetManager, path: &Path, ) -> BufferPair { + log::info!("loading obj prefab: {path:?}"); + let mut reader = BufReader::new( assman.open_asset(path).expect("Failed to open texture file") ); diff --git a/kubi/src/rendering.rs b/kubi/src/rendering.rs index 923e8ac..288627b 100644 --- a/kubi/src/rendering.rs +++ b/kubi/src/rendering.rs @@ -1,4 +1,4 @@ -use shipyard::{AllStoragesViewMut, IntoIter, IntoWorkload, SystemModificator, Unique, UniqueView, UniqueViewMut, View, Workload}; +use shipyard::{AllStoragesViewMut, IntoIter, IntoWorkload, SystemModificator, Unique, UniqueView, UniqueViewMut, View, Workload, WorkloadModificator}; use winit::dpi::PhysicalSize; use glam::Vec3; use crate::{events::WindowResizedEvent, hui_integration::kubi_ui_draw, state::is_ingame}; @@ -13,6 +13,7 @@ pub mod background; pub mod world; pub mod camera_uniform; pub mod depth; +pub mod smoverlay; pub struct BufferPair { pub index: wgpu::Buffer, @@ -40,6 +41,7 @@ pub fn init_rendering() -> Workload { world::init_world_render_state, //req: depth, camera entities::init_entities_render_state, //req: depth, camera selection_box::init_selection_box_render_state, //req: depth, camera, primitives + smoverlay::init_smoverlay_render_state, //req: primitives ).into_sequential_workload() } @@ -53,8 +55,11 @@ pub fn update_rendering_early() -> Workload { pub fn update_rendering_late() -> Workload { ( camera_uniform::update_camera_uniform_buffer, - selection_box::update_selection_box_render_state.run_if(is_ingame), - entities::update_entities_render_state.run_if(is_ingame), + ( + selection_box::update_selection_box_render_state, + entities::update_entities_render_state, + smoverlay::update_smoverlay_render_state, + ).into_workload().run_if(is_ingame), ).into_workload() } @@ -78,6 +83,7 @@ pub fn render_master(storages: AllStoragesViewMut) { storages.run_with_data(selection_box::draw_selection_box, &mut data); storages.run_with_data(entities::render_entities, &mut data); storages.run_with_data(world::rpass_submit_trans_bundle, &mut data); + storages.run_with_data(smoverlay::render_submerged_view, &mut data); } storages.run_with_data(kubi_ui_draw, &mut data); diff --git a/kubi/src/rendering/entities/instance.rs b/kubi/src/rendering/entities/instance.rs index 271949a..6ad7226 100644 --- a/kubi/src/rendering/entities/instance.rs +++ b/kubi/src/rendering/entities/instance.rs @@ -34,6 +34,7 @@ pub struct InstanceBuffer { pub fn create_instance_buffer( renderer: UniqueView, ) -> InstanceBuffer { + log::info!("entities: create_instance_buffer"); let buffer = renderer.device().create_buffer(&wgpu::BufferDescriptor { label: Some("instance_buffer"), size: 255 * std::mem::size_of::() as u64, diff --git a/kubi/src/rendering/entities/pipeline.rs b/kubi/src/rendering/entities/pipeline.rs index b7e8e42..bacc587 100644 --- a/kubi/src/rendering/entities/pipeline.rs +++ b/kubi/src/rendering/entities/pipeline.rs @@ -9,6 +9,8 @@ pub fn init_entities_pipeline( prefabs: UniqueView, camera_ubo: UniqueView, ) -> wgpu::RenderPipeline { + log::info!("init_entities_pipeline"); + let module = renderer.device().create_shader_module(include_wgsl!("../../../shaders/entities.wgsl")); let pipeline_layout = renderer.device().create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { diff --git a/kubi/src/rendering/primitives.rs b/kubi/src/rendering/primitives.rs index 05ef112..457bace 100644 --- a/kubi/src/rendering/primitives.rs +++ b/kubi/src/rendering/primitives.rs @@ -9,6 +9,7 @@ pub use fstri::FstriPrimitive; pub fn init_primitives() -> Workload { ( cube::init_cube_primitive, + fstri::init_fstri_primitive, ).into_workload() } diff --git a/kubi/src/rendering/primitives/cube.rs b/kubi/src/rendering/primitives/cube.rs index 3abd3e2..ff74e96 100644 --- a/kubi/src/rendering/primitives/cube.rs +++ b/kubi/src/rendering/primitives/cube.rs @@ -31,6 +31,7 @@ const CUBE_INDICES: &[u16] = &[ ]; pub fn init_cube_primitive(storages: AllStoragesView) { + log::info!("init_cube_primitive"); let renderer = storages.borrow::>().unwrap(); storages.add_unique(CubePrimitive(BufferPair { index: renderer.device().create_buffer_init(&wgpu::util::BufferInitDescriptor { diff --git a/kubi/src/rendering/primitives/fstri.rs b/kubi/src/rendering/primitives/fstri.rs index b6eb26d..7e22d5f 100644 --- a/kubi/src/rendering/primitives/fstri.rs +++ b/kubi/src/rendering/primitives/fstri.rs @@ -4,16 +4,16 @@ use crate::rendering::Renderer; use super::PrimitiveVertex2; pub const FSTRI_VERTICES: &[PrimitiveVertex2] = &[ - PrimitiveVertex2 { position: [0.0, 0.0] }, - PrimitiveVertex2 { position: [1.0, 0.0] }, - PrimitiveVertex2 { position: [0.0, 1.0] }, - PrimitiveVertex2 { position: [1.0, 1.0] }, + PrimitiveVertex2 { position: [-1.0, -1.0] }, + PrimitiveVertex2 { position: [ 3.0, -1.0] }, + PrimitiveVertex2 { position: [-1.0, 3.0] }, ]; #[derive(Unique)] -pub struct FstriPrimitive(wgpu::Buffer); +pub struct FstriPrimitive(pub wgpu::Buffer); pub fn init_fstri_primitive(storages: AllStoragesView) { + log::info!("init_fstri_primitive"); let renderer = storages.borrow::>().unwrap(); let buffer = renderer.device().create_buffer_init(&wgpu::util::BufferInitDescriptor { label: Some("fstri_vertex_buffer"), diff --git a/kubi/src/rendering/selection_box/pipeline.rs b/kubi/src/rendering/selection_box/pipeline.rs index 352ce83..ab15dcd 100644 --- a/kubi/src/rendering/selection_box/pipeline.rs +++ b/kubi/src/rendering/selection_box/pipeline.rs @@ -12,6 +12,8 @@ pub fn init_selection_box_pipeline( depth: UniqueView, camera_ubo: UniqueView, ) -> wgpu::RenderPipeline { + log::info!("init_selection_box_pipeline"); + let shader = ren.device().create_shader_module( wgpu::include_wgsl!("../../../shaders/selection_box.wgsl") ); diff --git a/kubi/src/rendering/selection_box/uniform.rs b/kubi/src/rendering/selection_box/uniform.rs index 8ee8f5e..cf551ad 100644 --- a/kubi/src/rendering/selection_box/uniform.rs +++ b/kubi/src/rendering/selection_box/uniform.rs @@ -21,7 +21,11 @@ pub struct SelectionBoxUniform { pub bind_group: wgpu::BindGroup, } -pub fn init_selection_box_uniform(renderer: UniqueView) -> SelectionBoxUniform { +pub fn init_selection_box_uniform( + renderer: UniqueView +) -> SelectionBoxUniform { + log::info!("init_selection_box_uniform"); + let buffer = renderer.device().create_buffer(&wgpu::BufferDescriptor { label: Some("selection_box_uniform"), size: std::mem::size_of::() as u64, diff --git a/kubi/src/rendering/smoverlay.rs b/kubi/src/rendering/smoverlay.rs new file mode 100644 index 0000000..e0e66fc --- /dev/null +++ b/kubi/src/rendering/smoverlay.rs @@ -0,0 +1,48 @@ +use shipyard::{AllStoragesView, Unique, UniqueView}; +use super::{primitives::FstriPrimitive, RenderCtx, Renderer}; + +mod uniform; +mod pipeline; +use uniform::SmUniform; + +#[derive(Unique)] +pub struct SmOverlayRenderState { + pub uniform: SmUniform, + pub pipeline: wgpu::RenderPipeline, +} + +pub fn init_smoverlay_render_state(storages: AllStoragesView) { + let uniform = storages.run(uniform::init_sm_uniform); + let pipeline = storages.run_with_data(pipeline::init_smoverlay_pipeline, &uniform); + storages.add_unique(SmOverlayRenderState { uniform, pipeline }); +} + +pub use uniform::update_sm_uniform as update_smoverlay_render_state; + +pub fn render_submerged_view( + ctx: &mut RenderCtx, + state: UniqueView, + buf: UniqueView, +) { + if state.uniform.stored_data.is_none() { return } + + let mut rpass = ctx.encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + label: Some("smoverlay_render_pass"), + color_attachments: &[Some(wgpu::RenderPassColorAttachment { + view: ctx.surface_view, + resolve_target: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Load, + store: wgpu::StoreOp::Store, + }, + })], + depth_stencil_attachment: None, + timestamp_writes: None, + occlusion_query_set: None, + }); + + rpass.set_pipeline(&state.pipeline); + rpass.set_bind_group(0, &state.uniform.bind_group, &[]); + rpass.set_vertex_buffer(0, buf.0.slice(..)); + rpass.draw(0..3, 0..1); +} diff --git a/kubi/src/rendering/smoverlay/pipeline.rs b/kubi/src/rendering/smoverlay/pipeline.rs new file mode 100644 index 0000000..df35e3e --- /dev/null +++ b/kubi/src/rendering/smoverlay/pipeline.rs @@ -0,0 +1,57 @@ +use shipyard::UniqueView; +use crate::rendering::{primitives::PrimitiveVertex2, Renderer}; +use super::uniform::SmUniform; + +pub fn init_smoverlay_pipeline( + uniform: &SmUniform, + renderer: UniqueView +) -> wgpu::RenderPipeline { + let module = renderer.device().create_shader_module( + wgpu::include_wgsl!("../../../shaders/c2d.wgsl") + ); + + let rp_layout = renderer.device().create_pipeline_layout( + &wgpu::PipelineLayoutDescriptor { + label: Some("smoverlay_pipeline_layout"), + bind_group_layouts: &[ + &uniform.bind_group_layout, + ], + push_constant_ranges: &[], + } + ); + + renderer.device().create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("smoverlay_pipeline"), + layout: Some(&rp_layout), + vertex: wgpu::VertexState { + module: &module, + compilation_options: wgpu::PipelineCompilationOptions::default(), + entry_point: "vs_main", + buffers: &[ + PrimitiveVertex2::LAYOUT, + ], + }, + fragment: Some(wgpu::FragmentState { + module: &module, + compilation_options: wgpu::PipelineCompilationOptions::default(), + entry_point: "fs_main", + targets: &[Some(wgpu::ColorTargetState { + format: renderer.surface_config().format, + blend: Some(wgpu::BlendState::ALPHA_BLENDING), + write_mask: wgpu::ColorWrites::ALL, + })], + }), + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleList, + strip_index_format: None, + front_face: wgpu::FrontFace::Ccw, + cull_mode: Some(wgpu::Face::Back), + polygon_mode: wgpu::PolygonMode::Fill, + conservative: false, + unclipped_depth: false, + }, + depth_stencil: None, + multisample: wgpu::MultisampleState::default(), + multiview: None, + }) +} diff --git a/kubi/src/rendering/smoverlay/uniform.rs b/kubi/src/rendering/smoverlay/uniform.rs new file mode 100644 index 0000000..c859739 --- /dev/null +++ b/kubi/src/rendering/smoverlay/uniform.rs @@ -0,0 +1,94 @@ +use bytemuck::{Pod, Zeroable}; +use kubi_shared::transform::Transform; +use shipyard::{IntoIter, UniqueView, UniqueViewMut, View}; +use crate::{player::MainPlayer, rendering::Renderer, world::ChunkStorage}; +use super::SmOverlayRenderState; + +#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)] +#[repr(C, packed)] +pub struct SmUniformData { + pub color: [f32; 4], +} + +pub struct SmUniform { + pub stored_data: Option, + pub buffer: wgpu::Buffer, + pub bind_group_layout: wgpu::BindGroupLayout, + pub bind_group: wgpu::BindGroup, +} + +pub fn init_sm_uniform( + renderer: UniqueView +) -> SmUniform { + log::info!("init_sm_uniform"); + + let buffer = renderer.device().create_buffer(&wgpu::BufferDescriptor { + label: Some("smoverlay_uniform"), + size: std::mem::size_of::() as u64, + usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, + mapped_at_creation: false, + }); + + let bind_group_layout = renderer.device().create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: Some("smoverlay_bind_group_layout"), + entries: &[wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStages::FRAGMENT, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, + min_binding_size: None, + }, + count: None, + }], + }); + + let bind_group = renderer.device().create_bind_group(&wgpu::BindGroupDescriptor { + label: Some("smoverlay_bind_group"), + layout: &bind_group_layout, + entries: &[wgpu::BindGroupEntry { + binding: 0, + resource: buffer.as_entire_binding(), + }], + }); + + SmUniform { + stored_data: None, + buffer, + bind_group_layout, + bind_group, + } +} + +pub fn update_sm_uniform( + mut state: UniqueViewMut, + renderer: UniqueView, + plr: View, + trans: View, + world: UniqueView, +) { + state.uniform.stored_data = None; + + let (_, plr_trans) = (&plr, &trans).iter().next().expect("Main player MIA"); + let plr_pos = plr_trans.0.to_scale_rotation_translation().2; + let block_at_pos = world.get_block(plr_pos.floor().as_ivec3()); + let Some(block_at_pos) = block_at_pos else { return }; + let Some(color) = block_at_pos.descriptor().submerge else { return }; + + let new_data = SmUniformData { + color: color.to_array() + }; + + if state.uniform.stored_data == Some(new_data) { + return + } + state.uniform.stored_data = Some(new_data); + + log::debug!("update_sm_uniform: {:?}", new_data); + + renderer.queue().write_buffer( + &state.uniform.buffer, + 0, + bytemuck::cast_slice(&[new_data]), + ); +} diff --git a/kubi/src/rendering/submerge/pipeline.rs b/kubi/src/rendering/submerge/pipeline.rs deleted file mode 100644 index 0bcd41a..0000000 --- a/kubi/src/rendering/submerge/pipeline.rs +++ /dev/null @@ -1,14 +0,0 @@ -pub fn create_render_pipeline( - ren: UniqueView, - stri_primitive: UniqueView, -) -> wgpu::RenderPipeline { - let shader = ren.device().create_shader_module( - wgpu::include_wgsl!("../../../shaders/c2d.wgsl") - ); - let pipeline_layout = ren.device().create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { - label: Some("smoverlay_pipeline_layout"), - bind_group_layouts: &[&ren.bind_group_layout], - push_constant_ranges: &[], - }); - //TODO -} diff --git a/kubi/src/rendering/sumberge.rs b/kubi/src/rendering/sumberge.rs deleted file mode 100644 index 89eebb0..0000000 --- a/kubi/src/rendering/sumberge.rs +++ /dev/null @@ -1,41 +0,0 @@ -mod pipeline; - -// use glium::{uniform, Blend, DrawParameters, Surface}; -// use kubi_shared::transform::Transform; -// use shipyard::{IntoIter, NonSendSync, UniqueView, UniqueViewMut, View}; -// use crate::{ -// player::MainPlayer, -// prefabs::Colored2ShaderPrefab, -// rendering::primitives::stri::STriPrimitive, -// world::ChunkStorage, -// }; -// use super::RenderTarget; - -// pub fn render_submerged_view( -// mut target: NonSendSync>, -// primitive: NonSendSync>, -// program: NonSendSync>, -// plr: View, -// trans: View, -// world: UniqueView, -// ) { -// let (_, plr_trans) = (&plr, &trans).iter().next().expect("Main player MIA"); -// let plr_pos = plr_trans.0.to_scale_rotation_translation().2; -// let block_at_pos = world.get_block(plr_pos.floor().as_ivec3()); -// let Some(block_at_pos) = block_at_pos else { return }; -// let Some(color) = block_at_pos.descriptor().submerge else { return }; - -// let draw_parameters = DrawParameters { -// blend: Blend::alpha_blending(), -// ..Default::default() -// }; -// target.0.draw( -// &primitive.0, -// &primitive.1, -// &program.0, -// &uniform! { -// color: color.to_array(), -// }, -// &draw_parameters, -// ).unwrap(); -// } diff --git a/kubi/src/rendering/world/pipeline.rs b/kubi/src/rendering/world/pipeline.rs index 692cb7c..6d960c6 100644 --- a/kubi/src/rendering/world/pipeline.rs +++ b/kubi/src/rendering/world/pipeline.rs @@ -10,10 +10,14 @@ pub fn init_world_pipeline( textures: UniqueView, camera_ubo: UniqueView, ) -> (wgpu::RenderPipeline, wgpu::RenderPipeline) { + log::info!("init_world_pipeline: creating shader module"); + let shader = ren.device().create_shader_module( wgpu::include_wgsl!("../../../shaders/world.wgsl") ); + log::info!("init_world_pipeline: creating pipeline layout"); + let world_pipeline_layout = ren.device().create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("world_pipeline_layout"), bind_group_layouts: &[ @@ -23,6 +27,8 @@ pub fn init_world_pipeline( push_constant_ranges: &[], }); + log::info!("init_world_pipeline: create main pipeline"); + let pipeline_main = ren.device().create_render_pipeline(&wgpu::RenderPipelineDescriptor { label: Some("world_pipeline"), layout: Some(&world_pipeline_layout), @@ -64,6 +70,8 @@ pub fn init_world_pipeline( multiview: None, }); + log::info!("init_world_pipeline: create trans pipeline"); + let pipeline_trans = ren.device().create_render_pipeline(&wgpu::RenderPipelineDescriptor { label: Some("world_pipeline_trans"), layout: Some(&world_pipeline_layout), diff --git a/kubi/src/settings.rs b/kubi/src/settings.rs index a0abbbe..9a83be3 100644 --- a/kubi/src/settings.rs +++ b/kubi/src/settings.rs @@ -11,10 +11,10 @@ pub struct FullscreenSettings { #[derive(Unique)] pub struct GameSettings { - pub vsync: bool, + // pub vsync: bool, pub fullscreen: Option, - pub msaa: Option, - pub max_anisotropy: Option, + // pub msaa: Option, + // pub max_anisotropy: Option, /// there's a 1 chunk border of loaded but invisible around this pub render_distance: u8, pub mouse_sensitivity: f32, @@ -24,10 +24,10 @@ pub struct GameSettings { impl Default for GameSettings { fn default() -> Self { Self { - vsync: false, + // vsync: false, fullscreen: None, - msaa: Some(4), - max_anisotropy: Some(16), + // msaa: Some(4), + // max_anisotropy: Some(16), render_distance: match true { cfg!(debug_assertions) => 5, cfg!(target_os = "android") => 6, From db05b0902d0c459bc8887e98efe6d8025a17ec74 Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Mon, 13 May 2024 23:44:48 +0200 Subject: [PATCH 50/51] Remove unneded use of nonsendsync --- kubi/src/cursor_lock.rs | 6 +++--- kubi/src/events.rs | 2 +- kubi/src/hui_integration.rs | 2 +- kubi/src/lib.rs | 2 +- kubi/src/prefabs.rs | 2 +- kubi/src/world/loading.rs | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/kubi/src/cursor_lock.rs b/kubi/src/cursor_lock.rs index 8e195d7..e8a1a43 100644 --- a/kubi/src/cursor_lock.rs +++ b/kubi/src/cursor_lock.rs @@ -1,4 +1,4 @@ -use shipyard::{AllStoragesView, IntoIter, NonSendSync, Unique, UniqueView, UniqueViewMut, View}; +use shipyard::{AllStoragesView, IntoIter, Unique, UniqueView, UniqueViewMut, View}; use crate::{events::InputDeviceEvent, rendering::Renderer}; use winit::{ dpi::PhysicalPosition, event::{DeviceEvent, ElementState, RawKeyEvent}, keyboard::{KeyCode, PhysicalKey}, window::CursorGrabMode @@ -9,7 +9,7 @@ pub struct CursorLock(pub bool); pub fn update_cursor_lock_state( lock: UniqueView, - display: NonSendSync> + display: UniqueView ) { if cfg!(target_os = "android") { return @@ -41,7 +41,7 @@ pub fn lock_cursor_now( pub fn debug_toggle_lock( mut lock: UniqueViewMut, device_events: View, - ren: NonSendSync>, + ren: UniqueView, ) { for evt in device_events.iter() { if let DeviceEvent::Key(RawKeyEvent { diff --git a/kubi/src/events.rs b/kubi/src/events.rs index 4bed070..0e8324f 100644 --- a/kubi/src/events.rs +++ b/kubi/src/events.rs @@ -90,7 +90,7 @@ pub fn process_winit_events(world: &mut World, event: &Event<()>) { // mut storages: AllStoragesViewMut, // ) { // let (w, h) = { -// let renderer = storages.borrow::>>().unwrap(); +// let renderer = storages.borrow::>().unwrap(); // (renderer.size().width, renderer.size().height) // }; // storages.add_entity(( diff --git a/kubi/src/hui_integration.rs b/kubi/src/hui_integration.rs index 78f0b02..90cdd30 100644 --- a/kubi/src/hui_integration.rs +++ b/kubi/src/hui_integration.rs @@ -13,7 +13,7 @@ pub struct UiState { pub fn kubi_ui_init( storages: AllStoragesView ) { - let renderer = storages.borrow::>>().unwrap(); + let renderer = storages.borrow::>().unwrap(); storages.add_unique_non_send_sync(UiState { hui: UiInstance::new(), renderer: WgpuUiRenderer::new(renderer.device(), renderer.surface_config().format), diff --git a/kubi/src/lib.rs b/kubi/src/lib.rs index 516c1cf..c5f1c15 100644 --- a/kubi/src/lib.rs +++ b/kubi/src/lib.rs @@ -310,7 +310,7 @@ pub fn kubi_main( //Start rendering (maybe use custom views for this?) // let target = { - // let renderer = world.borrow::>>().unwrap(); + // let renderer = world.borrow::>().unwrap(); // renderer.display.draw() // }; // world.add_unique_non_send_sync(RenderTarget(target)); diff --git a/kubi/src/prefabs.rs b/kubi/src/prefabs.rs index 2fb3514..49b0eac 100644 --- a/kubi/src/prefabs.rs +++ b/kubi/src/prefabs.rs @@ -76,7 +76,7 @@ pub struct UiFontPrefab(pub FontHandle); pub fn load_prefabs( storages: AllStoragesView, - renderer: NonSendSync>, + renderer: UniqueView, mut ui: NonSendSync>, assman: UniqueView ) { diff --git a/kubi/src/world/loading.rs b/kubi/src/world/loading.rs index 0033ec8..7ee4313 100644 --- a/kubi/src/world/loading.rs +++ b/kubi/src/world/loading.rs @@ -266,7 +266,7 @@ fn process_completed_tasks( task_manager: UniqueView, mut world: UniqueViewMut, mut meshes: NonSendSync>, - renderer: NonSendSync>, + renderer: UniqueView, state: UniqueView, mut queue: UniqueViewMut, ) { From e7d81ce7cc9efe59abf5c36abcf1b05eda4e57b7 Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Mon, 13 May 2024 23:56:31 +0200 Subject: [PATCH 51/51] add the old "lighting" thingy --- kubi/shaders/world.wgsl | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/kubi/shaders/world.wgsl b/kubi/shaders/world.wgsl index ed5d35d..96b54a7 100644 --- a/kubi/shaders/world.wgsl +++ b/kubi/shaders/world.wgsl @@ -39,10 +39,20 @@ var s_diffuse: sampler; @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4 { - let color: vec4 = textureSample(t_diffuse, s_diffuse, in.uv, in.tex_index); + // not actual lighting; makes it easier to distinguish unlit faces + let light: f32 = + abs(in.normal.x) + .85 * + abs(in.normal.y) + .65 * + abs(in.normal.z); + + let color: vec4 = + textureSample(t_diffuse, s_diffuse, in.uv, in.tex_index) + * vec4(light, light, light, 1.0); + if (color.a < 0.5) { discard; } + return color; }