Compare commits

...

10 Commits

Author SHA1 Message Date
e4ccf95a2f Document new Mesh system 2022-11-01 19:09:04 +01:00
c1e8fea84a Rework Mesh system
The mesh is now direclty handled by its corresponding sprite to
simplify things
2022-11-01 18:53:21 +01:00
2e326306d9 Clean up frame implementation
Sprites no longer need to handle the frame creation as it is fully
handled by the renderer itself. The fields order in the renderer have
also been swapped to drop things in the right order
2022-10-22 22:26:11 +02:00
c2e884f68c Clean up Sprite's file hierarchy 2022-10-22 20:47:27 +02:00
d5d36cfadc Perform major code refactor
The rendering is moved from the renderer to the sprites. As a result,
WgpuRenderer is now more of a rendering context while the renderer in
itself is the context + the sprites
2022-10-22 00:21:41 +02:00
f025bef6c9 Updated Cargo.toml
bytemuck support for cgmath hasn't been released yet, so using the
master branch from github instead. Won't be adding it as submodule yet
as it is only temporary
2022-08-21 21:14:28 +02:00
be968adb89 Removed warnings 2022-08-21 21:09:19 +02:00
d3bc7ecc7f Moved from push constants to uniforms
This move also fixed display issues on Vulkan since the matrix's data
alignement was not properly handled
2022-08-21 20:35:02 +02:00
2591b60a5d Added proper texture scaling 2022-08-20 19:51:21 +02:00
7a46eff82c Moved surface size handling to renderer
Canvas is no longer resizeable by the interface as that would shift all
sprites on the screen. The user can still do it through the API
2022-08-20 17:04:15 +02:00
19 changed files with 1386 additions and 1046 deletions

434
Cargo.lock generated
View File

@ -8,12 +8,6 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "adler32"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
[[package]]
name = "ahash"
version = "0.7.6"
@ -27,18 +21,18 @@ dependencies = [
[[package]]
name = "android_system_properties"
version = "0.1.2"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a20ae67ce26261f218e2b3f2f0d01887a9818283ca6fb260fa7c67e253d61c92"
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
dependencies = [
"libc",
]
[[package]]
name = "approx"
version = "0.4.0"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f2a05fd1bd10b2527e20a2cd32d8873d115b8b39fe219ee25f42a8aca6ba278"
checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6"
dependencies = [
"num-traits",
]
@ -77,9 +71,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bit-set"
version = "0.5.2"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e11e16035ea35e4e5997b393eacbf6f63983188f7a2ad25bfb13465f5ad59de"
checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1"
dependencies = [
"bit-vec",
]
@ -104,24 +98,24 @@ checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
[[package]]
name = "bumpalo"
version = "3.10.0"
version = "3.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3"
checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
[[package]]
name = "bytemuck"
version = "1.10.0"
version = "1.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c53dfa917ec274df8ed3c572698f381a24eef2efba9492d797301b72b6db408a"
checksum = "5aec14f5d4e6e3f927cd0c81f72e5710d95ee9019fbeb4b3021193867491bfd8"
dependencies = [
"bytemuck_derive",
]
[[package]]
name = "bytemuck_derive"
version = "1.1.0"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "562e382481975bc61d11275ac5e62a19abd00b0547d99516a415336f183dcd0e"
checksum = "1b9e1f5fa78f69496407a27ae9ed989e3c3b072310286f5ef385525e4cbc24a9"
dependencies = [
"proc-macro2",
"quote",
@ -141,7 +135,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf2eec61efe56aa1e813f5126959296933cf0700030e4314786c48779a66ab82"
dependencies = [
"log",
"nix",
"nix 0.22.3",
]
[[package]]
@ -158,6 +152,7 @@ dependencies = [
"pollster",
"raw-window-handle",
"wgpu",
"wgpu-core",
"wgpu-hal",
"wgpu-types",
"winit",
@ -165,9 +160,9 @@ dependencies = [
[[package]]
name = "cc"
version = "1.0.73"
version = "1.0.74"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
checksum = "581f5dba903aac52ea3feb5ec4810848460ee833876f1f9b0fdeab1f19091574"
[[package]]
name = "cfg-if"
@ -190,31 +185,32 @@ checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
[[package]]
name = "cgmath"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a98d30140e3296250832bbaaff83b27dcd6fa3cc70fb6f1f3e5c9c0023b5317"
dependencies = [
"approx",
"bytemuck",
"num-traits",
]
[[package]]
name = "chrono"
version = "0.4.19"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1"
dependencies = [
"libc",
"iana-time-zone",
"js-sys",
"num-integer",
"num-traits",
"time",
"wasm-bindgen",
"winapi",
]
[[package]]
name = "cocoa"
version = "0.24.0"
version = "0.24.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f63902e9223530efb4e26ccd0cf55ec30d592d3b42e21a28defc42a9586e832"
checksum = "f425db7937052c684daec3bd6375c8abe2d146dca4b8b143d6db777c39138f3a"
dependencies = [
"bitflags",
"block",
@ -371,6 +367,50 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35"
[[package]]
name = "cxx"
version = "1.0.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b7d4e43b25d3c994662706a1d4fcfc32aaa6afd287502c111b237093bb23f3a"
dependencies = [
"cc",
"cxxbridge-flags",
"cxxbridge-macro",
"link-cplusplus",
]
[[package]]
name = "cxx-build"
version = "1.0.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84f8829ddc213e2c1368e51a2564c552b65a8cb6a28f31e576270ac81d5e5827"
dependencies = [
"cc",
"codespan-reporting",
"once_cell",
"proc-macro2",
"quote",
"scratch",
"syn",
]
[[package]]
name = "cxxbridge-flags"
version = "1.0.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e72537424b474af1460806647c41d4b6d35d09ef7fe031c5c2fa5766047cc56a"
[[package]]
name = "cxxbridge-macro"
version = "1.0.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "309e4fb93eed90e1e14bea0da16b209f81813ba9fc7830c20ed151dd7bc0a4d7"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "d3d12"
version = "0.5.0"
@ -417,15 +457,6 @@ dependencies = [
"syn",
]
[[package]]
name = "deflate"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c86f7e25f518f4b81808a2cf1c50996a61f5c2eb394b2393bd87f2a4780a432f"
dependencies = [
"adler32",
]
[[package]]
name = "dispatch"
version = "0.2.0"
@ -457,6 +488,16 @@ dependencies = [
"log",
]
[[package]]
name = "flate2"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6"
dependencies = [
"crc32fast",
"miniz_oxide 0.5.4",
]
[[package]]
name = "fnv"
version = "1.0.7"
@ -489,9 +530,9 @@ dependencies = [
[[package]]
name = "getrandom"
version = "0.2.7"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
dependencies = [
"cfg-if 1.0.0",
"libc",
@ -531,13 +572,13 @@ dependencies = [
[[package]]
name = "gpu-descriptor"
version = "0.2.2"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a538f217be4d405ff4719a283ca68323cc2384003eca5baaa87501e821c81dda"
checksum = "0b0c02e1ba0bdb14e965058ca34e09c020f8e507a760df1121728e0aef68d57a"
dependencies = [
"bitflags",
"gpu-descriptor-types",
"hashbrown 0.11.2",
"hashbrown",
]
[[package]]
@ -551,19 +592,13 @@ dependencies = [
[[package]]
name = "hashbrown"
version = "0.11.2"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
dependencies = [
"ahash",
]
[[package]]
name = "hashbrown"
version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "607c8a29735385251a339424dd462993c0fed8fa09d378f259377df08c126022"
[[package]]
name = "hermit-abi"
version = "0.1.19"
@ -579,6 +614,30 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df"
[[package]]
name = "iana-time-zone"
version = "0.1.53"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765"
dependencies = [
"android_system_properties",
"core-foundation-sys 0.8.3",
"iana-time-zone-haiku",
"js-sys",
"wasm-bindgen",
"winapi",
]
[[package]]
name = "iana-time-zone-haiku"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca"
dependencies = [
"cxx",
"cxx-build",
]
[[package]]
name = "ident_case"
version = "1.0.1"
@ -587,15 +646,14 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "image"
version = "0.24.2"
version = "0.24.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28edd9d7bc256be2502e325ac0628bde30b7001b9b52e0abe31a1a9dc2701212"
checksum = "bd8e4fb07cf672b1642304e731ef8a6a4c7891d67bb4fd4f5ce58cd6ed86803c"
dependencies = [
"bytemuck",
"byteorder",
"color_quant",
"jpeg-decoder",
"num-iter",
"num-rational",
"num-traits",
"png",
@ -608,14 +666,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
dependencies = [
"autocfg",
"hashbrown 0.12.2",
"hashbrown",
]
[[package]]
name = "inplace_it"
version = "0.3.3"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90953f308a79fe6d62a4643e51f848fbfddcd05975a38e69fdf4ab86a7baf7ca"
checksum = "e567468c50f3d4bc7397702e09b380139f9b9288b4e909b070571007f8b5bf78"
[[package]]
name = "instant"
@ -643,9 +701,9 @@ checksum = "9478aa10f73e7528198d75109c8be5cd7d15fb530238040148d5f9a22d4c5b3b"
[[package]]
name = "js-sys"
version = "0.3.58"
version = "0.3.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3fac17f7123a73ca62df411b1bf727ccc805daa070338fda671c86dac1bdc27"
checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47"
dependencies = [
"wasm-bindgen",
]
@ -669,9 +727,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.126"
version = "0.2.137"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
[[package]]
name = "libloading"
@ -684,10 +742,19 @@ dependencies = [
]
[[package]]
name = "lock_api"
version = "0.4.7"
name = "link-cplusplus"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53"
checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369"
dependencies = [
"cc",
]
[[package]]
name = "lock_api"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
dependencies = [
"autocfg",
"scopeguard",
@ -757,18 +824,27 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "miniz_oxide"
version = "0.5.3"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc"
checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34"
dependencies = [
"adler",
]
[[package]]
name = "miniz_oxide"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
dependencies = [
"adler",
]
[[package]]
name = "mio"
version = "0.8.4"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf"
checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de"
dependencies = [
"libc",
"log",
@ -862,6 +938,18 @@ dependencies = [
"memoffset",
]
[[package]]
name = "nix"
version = "0.24.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "195cdbc1741b8134346d515b3a56a1c94b0912758009cfd53f99ea0f57b065fc"
dependencies = [
"bitflags",
"cfg-if 1.0.0",
"libc",
"memoffset",
]
[[package]]
name = "nom"
version = "7.1.1"
@ -882,17 +970,6 @@ dependencies = [
"num-traits",
]
[[package]]
name = "num-iter"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-rational"
version = "0.4.1"
@ -955,9 +1032,9 @@ dependencies = [
[[package]]
name = "once_cell"
version = "1.13.0"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1"
checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
[[package]]
name = "parking_lot"
@ -977,7 +1054,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
dependencies = [
"lock_api",
"parking_lot_core 0.9.3",
"parking_lot_core 0.9.4",
]
[[package]]
@ -996,9 +1073,9 @@ dependencies = [
[[package]]
name = "parking_lot_core"
version = "0.9.3"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929"
checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0"
dependencies = [
"cfg-if 1.0.0",
"libc",
@ -1009,26 +1086,26 @@ dependencies = [
[[package]]
name = "percent-encoding"
version = "2.1.0"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
[[package]]
name = "pkg-config"
version = "0.3.25"
version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
[[package]]
name = "png"
version = "0.17.5"
version = "0.17.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc38c0ad57efb786dd57b9864e5b18bae478c00c824dc55a38bbc9da95dde3ba"
checksum = "5d708eaf860a19b19ce538740d2b4bdeeb8337fa53f7738455e706623ad5c638"
dependencies = [
"bitflags",
"crc32fast",
"deflate",
"miniz_oxide",
"flate2",
"miniz_oxide 0.6.2",
]
[[package]]
@ -1039,34 +1116,35 @@ checksum = "5da3b0203fd7ee5720aa0b5e790b591aa5d3f41c3ed2c34a3a393382198af2f7"
[[package]]
name = "proc-macro-crate"
version = "1.1.3"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a"
checksum = "eda0fc3b0fb7c975631757e14d9049da17374063edb6ebbcbc54d880d4fe94e9"
dependencies = [
"once_cell",
"thiserror",
"toml",
]
[[package]]
name = "proc-macro2"
version = "1.0.40"
version = "1.0.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7"
checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
dependencies = [
"unicode-ident",
]
[[package]]
name = "profiling"
version = "1.0.6"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f61dcf0b917cd75d4521d7343d1ffff3d1583054133c9b5cbea3375c703c40d"
checksum = "74605f360ce573babfe43964cbe520294dcb081afbf8c108fc6e23036b4da2df"
[[package]]
name = "quote"
version = "1.0.20"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804"
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
dependencies = [
"proc-macro2",
]
@ -1088,9 +1166,9 @@ dependencies = [
[[package]]
name = "redox_syscall"
version = "0.2.13"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42"
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
dependencies = [
"bitflags",
]
@ -1109,9 +1187,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "scoped-tls"
version = "1.0.0"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
[[package]]
name = "scopeguard"
@ -1120,10 +1198,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "serde"
version = "1.0.139"
name = "scratch"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0171ebb889e45aa68b44aee0859b3eede84c6f5f5c228e6f140c0b2a0a46cad6"
checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898"
[[package]]
name = "serde"
version = "1.0.147"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965"
[[package]]
name = "slotmap"
@ -1136,9 +1220,9 @@ dependencies = [
[[package]]
name = "smallvec"
version = "1.9.0"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1"
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
[[package]]
name = "smithay-client-toolkit"
@ -1152,7 +1236,7 @@ dependencies = [
"lazy_static",
"log",
"memmap2",
"nix",
"nix 0.22.3",
"pkg-config",
"wayland-client",
"wayland-cursor",
@ -1177,9 +1261,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "1.0.98"
version = "1.0.103"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd"
checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d"
dependencies = [
"proc-macro2",
"quote",
@ -1197,18 +1281,18 @@ dependencies = [
[[package]]
name = "thiserror"
version = "1.0.31"
version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a"
checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.31"
version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a"
checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb"
dependencies = [
"proc-macro2",
"quote",
@ -1237,21 +1321,21 @@ dependencies = [
[[package]]
name = "unicode-ident"
version = "1.0.1"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c"
checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
[[package]]
name = "unicode-width"
version = "0.1.9"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
[[package]]
name = "unicode-xid"
version = "0.2.3"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]]
name = "version_check"
@ -1273,9 +1357,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.81"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994"
checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268"
dependencies = [
"cfg-if 1.0.0",
"wasm-bindgen-macro",
@ -1283,13 +1367,13 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.81"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5491a68ab4500fa6b4d726bd67408630c3dbe9c4fe7bda16d5c82a1fd8c7340a"
checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142"
dependencies = [
"bumpalo",
"lazy_static",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn",
@ -1298,9 +1382,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.31"
version = "0.4.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de9a9cec1733468a8c657e57fa2413d2ae2c0129b95e87c5b72b8ace4d13f31f"
checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d"
dependencies = [
"cfg-if 1.0.0",
"js-sys",
@ -1310,9 +1394,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.81"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa"
checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@ -1320,9 +1404,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.81"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048"
checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
dependencies = [
"proc-macro2",
"quote",
@ -1333,20 +1417,20 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.81"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be"
checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
[[package]]
name = "wayland-client"
version = "0.29.4"
version = "0.29.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91223460e73257f697d9e23d401279123d36039a3f7a449e983f123292d4458f"
checksum = "3f3b068c05a039c9f755f881dc50f01732214f5685e379829759088967c46715"
dependencies = [
"bitflags",
"downcast-rs",
"libc",
"nix",
"nix 0.24.2",
"scoped-tls",
"wayland-commons",
"wayland-scanner",
@ -1355,11 +1439,11 @@ dependencies = [
[[package]]
name = "wayland-commons"
version = "0.29.4"
version = "0.29.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94f6e5e340d7c13490eca867898c4cec5af56c27a5ffe5c80c6fc4708e22d33e"
checksum = "8691f134d584a33a6606d9d717b95c4fa20065605f798a3f350d78dced02a902"
dependencies = [
"nix",
"nix 0.24.2",
"once_cell",
"smallvec",
"wayland-sys",
@ -1367,20 +1451,20 @@ dependencies = [
[[package]]
name = "wayland-cursor"
version = "0.29.4"
version = "0.29.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c52758f13d5e7861fc83d942d3d99bf270c83269575e52ac29e5b73cb956a6bd"
checksum = "6865c6b66f13d6257bef1cd40cbfe8ef2f150fb8ebbdb1e8e873455931377661"
dependencies = [
"nix",
"nix 0.24.2",
"wayland-client",
"xcursor",
]
[[package]]
name = "wayland-protocols"
version = "0.29.4"
version = "0.29.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60147ae23303402e41fe034f74fb2c35ad0780ee88a1c40ac09a3be1e7465741"
checksum = "b950621f9354b322ee817a23474e479b34be96c2e909c14f7bc0100e9a970bc6"
dependencies = [
"bitflags",
"wayland-client",
@ -1390,9 +1474,9 @@ dependencies = [
[[package]]
name = "wayland-scanner"
version = "0.29.4"
version = "0.29.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39a1ed3143f7a143187156a2ab52742e89dac33245ba505c17224df48939f9e0"
checksum = "8f4303d8fa22ab852f789e75a967f0a2cdc430a607751c0499bada3e451cbd53"
dependencies = [
"proc-macro2",
"quote",
@ -1401,9 +1485,9 @@ dependencies = [
[[package]]
name = "wayland-sys"
version = "0.29.4"
version = "0.29.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9341df79a8975679188e37dab3889bfa57c44ac2cb6da166f519a81cbe452d4"
checksum = "be12ce1a3c39ec7dba25594b97b42cb3195d54953ddb9d3d95a7c3902bc6e9d4"
dependencies = [
"dlib",
"lazy_static",
@ -1412,9 +1496,9 @@ dependencies = [
[[package]]
name = "web-sys"
version = "0.3.58"
version = "0.3.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fed94beee57daf8dd7d51f2b15dc2bcde92d7a72304cdf662a4371008b71b90"
checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f"
dependencies = [
"js-sys",
"wasm-bindgen",
@ -1443,9 +1527,9 @@ dependencies = [
[[package]]
name = "wgpu-core"
version = "0.13.1"
version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "266ca6be6004fd1b2a768023b1cb0afbf7af0cbffaba19af25c5792d44e74784"
checksum = "89b92788dec9d0c1bed849a1b83f01b2ee12819bf04a79c90f68e4173f7b5ba2"
dependencies = [
"arrayvec",
"bit-vec",
@ -1547,46 +1631,60 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.36.1"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_msvc"
version = "0.36.1"
name = "windows_aarch64_gnullvm"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
[[package]]
name = "windows_i686_gnu"
version = "0.36.1"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
[[package]]
name = "windows_i686_msvc"
version = "0.36.1"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
[[package]]
name = "windows_x86_64_gnu"
version = "0.36.1"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
[[package]]
name = "windows_x86_64_msvc"
version = "0.36.1"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
[[package]]
name = "winit"
@ -1623,9 +1721,9 @@ dependencies = [
[[package]]
name = "x11-dl"
version = "2.19.1"
version = "2.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea26926b4ce81a6f5d9d0f3a0bc401e5a37c6ae14a1bfaa8ff6099ca80038c59"
checksum = "0c83627bc137605acc00bb399c7b908ef460b621fc37c953db2b09f88c449ea6"
dependencies = [
"lazy_static",
"libc",

View File

@ -19,9 +19,10 @@ winit = "^0.26.1"
raw-window-handle = "^0.4.3"
# gpu API
wgpu = "0.13.0"
wgpu = "0.13.1"
wgpu-hal = "0.13.2"
wgpu-types = "0.13.2"
wgpu-core = "0.13.2"
bytemuck = { version = "1.4", features = ["derive"] }
[dependencies.image]
@ -29,3 +30,6 @@ version = "^0.24.2"
default-features = false
features = ["png", "jpeg"]
[patch.crates-io]
cgmath = { path = "cgmath" }

View File

@ -6,9 +6,9 @@ use raw_window_handle::HasRawWindowHandle;
use crate::{
io::{Key, Scroll},
sprite::{Sprite, TextureSprite, TextSprite, ShapeSprite},
texture::Texture,
texture::TextureHandle,
utils::{Size, Pixel, Position, Color},
renderer::WgpuRenderer,
renderer::{WgpuRenderer, Texture},
};
use std::{
@ -16,6 +16,7 @@ use std::{
cell::RefCell,
};
//--Application trait-------------------------------------------------------------------------------
pub trait Application<S> {
@ -26,9 +27,10 @@ pub trait Application<S> {
//--Canvas struct-----------------------------------------------------------------------------------
pub struct Canvas {
renderer: WgpuRenderer,
default_texture: TextureHandle,
clear_color: Pixel,
default_texture: Texture,
renderer: WgpuRenderer,
}
impl Canvas {
@ -58,7 +60,8 @@ impl Canvas {
}
};
Texture::create(renderer.create_gpu_texture(&rgba, img_size))
let texture = Texture::create(&renderer, &rgba, img_size);
TextureHandle::from_texture(texture)
};
Ok(Self {
@ -70,10 +73,10 @@ impl Canvas {
//--Create functions--
pub fn create_texture_sprite(&mut self, size: Size) -> TextureSprite {
TextureSprite::create(
TextureSprite::new(
self.default_texture.clone(),
size,
self.renderer.create_texture_mesh(),
&self.renderer,
)
}
@ -96,7 +99,7 @@ impl Canvas {
_offset: Option<Position>,
_size: Option<Size>,
_background: Option<Pixel>)
-> Result<Texture, &'static str>
-> Result<TextureHandle, &'static str>
{
use image::{
io::Reader,
@ -116,7 +119,8 @@ impl Canvas {
}
};
Ok(Texture::create(self.renderer.create_gpu_texture(&rgba, img_size)))
let texture = Texture::create(&self.renderer, &rgba, img_size);
Ok(TextureHandle::from_texture(texture))
}
pub fn create_texture_from_bytes(&mut self,
@ -136,7 +140,7 @@ impl Canvas {
pub fn draw<S: Sprite>(&mut self, sprite: &mut S) {
//update texture
self.renderer.render(sprite);
sprite.render(&mut self.renderer);
}
pub fn set_clear_color(&mut self, color: Pixel) {

View File

@ -12,6 +12,7 @@ bitflags! {
}
//--Scroll struct-----------------------------------------------------------------------------------
#[allow(dead_code)]
pub struct Scroll {
x: f32,
y: f32,

View File

@ -15,9 +15,10 @@ mod renderer;
use utils::Size;
pub fn run_canvas<S: 'static + Sized, A: 'static + Application<S>>(title: &'static str,
size: Size, mut app: A)
-> !
pub fn run_canvas<S, A>(title: &'static str, size: Size, _: A) -> !
where
S: 'static + Sized,
A: 'static + Application<S>,
{
use winit::{
event_loop::EventLoop,
@ -27,7 +28,7 @@ pub fn run_canvas<S: 'static + Sized, A: 'static + Application<S>>(title: &'stat
let event_loop = EventLoop::new();
let window = WindowBuilder::new()
.with_inner_size(size)
//.with_resizable(false)
.with_resizable(false)
.with_title(title)
.with_visible(false) //keep window invisible until we are ready to write to it
.build(&event_loop)
@ -61,9 +62,10 @@ pub fn run_canvas<S: 'static + Sized, A: 'static + Application<S>>(title: &'stat
WindowEvent::Resized (size) => {
canvas.set_size(size.into());
},
WindowEvent::ScaleFactorChanged {new_inner_size, ..} => {
WindowEvent::ScaleFactorChanged {/*new_inner_size, */..} => {
// new_inner_size is &&mut so we have to dereference it twice
canvas.set_size((*new_inner_size).into());
// canvas does not support resize, do nothing
//canvas.set_size((*new_inner_size).into());
},
_ => (),
},

View File

@ -4,16 +4,12 @@ use log::{debug, error, info, trace, warn};
use canvas::{
Application,
Canvas,
texture::Texture,
texture::TextureHandle,
sprite::TextureSprite,
utils::Position,
};
use std::{
rc::Rc,
cell::RefCell,
time::Instant,
};
use std::time::Instant;
fn setup_logger() -> Result<(), fern::InitError> {
use fern::colors::{Color, ColoredLevelConfig};
@ -37,17 +33,17 @@ fn setup_logger() -> Result<(), fern::InitError> {
.level(log::LevelFilter::Debug)
.chain(std::io::stdout())
.chain(fern::log_file("output.log")?)
.apply()?;
Ok(())
.apply()?; Ok(())
}
struct ExampleState {
pub texture: Texture,
pub texture: TextureHandle,
pub tex_sprite: TextureSprite,
pub sub_sprite: TextureSprite,
pub last_instant: Instant,
pub last_offset: u32,
pub last_pos: Position,
pub last_rot: f32,
}
struct ExampleApp {}
@ -55,18 +51,16 @@ struct ExampleApp {}
impl Application<ExampleState> for ExampleApp {
fn init(canvas: &mut Canvas) -> Result<ExampleState, &'static str> {
use canvas::{
utils::{Position, Size},
};
use canvas::utils::Size;
//// 20 x 20 sprite of a picture
let texture = canvas.create_texture_from_file("assets/camel.jpg", None, None, None)
.unwrap();
let mut tex_sprite = canvas.create_texture_sprite(Size {w: 200, h: 200});
tex_sprite.set_texture(texture.clone(), Some(Position {x: 0, y: 0}));
let mut tex_sprite = canvas.create_texture_sprite(Size {w: 1280, h: 720});
tex_sprite.set_texture(texture.clone(), Some(Position {x: 0, y: 0}), 1.0);
let mut sub_sprite = canvas.create_texture_sprite(Size {w: 350, h: 427});
sub_sprite.set_texture(texture.clone(), Some(Position {x: 350, y: 0}));
let mut sub_sprite = canvas.create_texture_sprite(Size {w: 200, h: 200});
sub_sprite.set_texture(texture.clone(), Some(Position {x: 350, y: 0}), 1.0);
canvas.clear();
canvas.update();
@ -80,16 +74,12 @@ impl Application<ExampleState> for ExampleApp {
last_instant,
last_offset: 0,
last_pos: Position::origin(),
last_rot: 0.0,
})
}
fn tick(state: &mut ExampleState, canvas: &mut Canvas) -> Result<(), &'static str> {
use canvas::{
io::Key,
sprite::Sprite,
utils::{Position, Size, Color, Pixel},
shape::{Shape, Rectangle},
};
use canvas::sprite::Sprite;
let now = Instant::now();
let elapsed = now.duration_since(state.last_instant).as_millis();
@ -99,10 +89,15 @@ impl Application<ExampleState> for ExampleApp {
//state.sub_sprite.for_each(|pix| unsafe {pix.flat = pix.flat.wrapping_add(1);});
state.last_offset += 1;
state.last_pos.x += 1;
state.last_pos.y += 1;
state.last_rot += 1.0;
state.tex_sprite.set_texture(state.texture.clone(), None, state.last_rot/100.0);
state.sub_sprite.set_texture(state.texture.clone(),
Some(Position {x: state.last_offset, y: 0}));
Some(Position {x: state.last_offset, y: 0}), 1.0);
state.sub_sprite.set_position(state.last_pos);
state.sub_sprite.set_rotation(state.last_rot);
//state.sub_sprite.set_scale(state.last_rot/1000.0);
// inputs
//if canvas.key_pressed(Key::A) {

View File

@ -3,36 +3,33 @@ use log::{debug, error, info, trace, warn};
use raw_window_handle::HasRawWindowHandle;
use wgpu;
use wgpu_hal;
use cgmath::Matrix3;
use crate::{
sprite::{Sprite, ModelMatrix},
texture::{GpuTexture},
utils::{Pixel, Size},
};
use crate::utils::{Pixel, Size};
use std::{
rc::Rc,
cell::RefCell,
};
pub mod utils;
mod texture;
pub use texture::Texture as Texture;
mod uniform;
pub use uniform::Uniform as Uniform;
mod matrix;
pub use matrix::ModelMatrix as ModelMatrix;
//--Renderer struct---------------------------------------------------------------------------------
pub struct WgpuRenderer {
pub texture_layout: wgpu::BindGroupLayout,
pub matrix_layout: wgpu::BindGroupLayout,
frame: Option<wgpu::SurfaceTexture>,
surface: wgpu::Surface,
device: wgpu::Device,
queue: wgpu::Queue,
config: wgpu::SurfaceConfiguration,
surface_size: Size,
aspect_matrix: Matrix3<f32>,
output: Option<wgpu::SurfaceTexture>,
texture_bind_group_layout: wgpu::BindGroupLayout,
texture_render_pipeline: wgpu::RenderPipeline,
shape_render_pipeline: wgpu::RenderPipeline,
quad_mesh: GpuMesh<ColorVertex, 4, 6>, //TODO temporary, to be moved to shapes.rs
pub config: wgpu::SurfaceConfiguration,
pub queue: wgpu::Queue,
pub device: wgpu::Device,
}
impl WgpuRenderer {
@ -57,14 +54,11 @@ impl WgpuRenderer {
},
).await.unwrap();
let mut limits = wgpu::Limits::downlevel_defaults();
limits.max_push_constant_size = 36;
let (device, queue) = adapter.request_device(
&wgpu::DeviceDescriptor {
//using minimum requirements possible since 2D isn't very demanding anyway
features: wgpu::Features::PUSH_CONSTANTS,
limits,
limits: wgpu::Limits::downlevel_webgl2_defaults(),
label: None,
},
None, // Trace path
@ -82,268 +76,29 @@ impl WgpuRenderer {
surface.configure(&device, &config);
let surface_size = size;
let aspect_matrix = Matrix3::from_nonuniform_scale(size.h as f32 / size.w as f32, 1.0);
let output = Some(surface.get_current_texture()
.map_err(|_| "Failed to create SurfaceTexture")?);
let frame = Some(surface.get_current_texture()
.map_err(|_| "Failed to create frame")?);
let texture_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[
wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Texture {
multisampled: false,
view_dimension: wgpu::TextureViewDimension::D2,
sample_type: wgpu::TextureSampleType::Float { filterable: true },
},
count: None,
},
wgpu::BindGroupLayoutEntry {
binding: 1,
visibility: wgpu::ShaderStages::FRAGMENT,
// This should match the filterable field of the
// corresponding Texture entry above.
ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
count: None,
},
],
label: Some("texture_bind_group_layout"),
});
let mvp_push_constant = wgpu::PushConstantRange {
stages: wgpu::ShaderStages::VERTEX,
range: 0..36,
};
let texture_render_pipeline = {
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: Some("texture shader"),
source: wgpu::ShaderSource::Wgsl(include_str!("shaders/texture.wgsl").into()),
});
let render_pipeline_layout =
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("texture render pipeline layout"),
bind_group_layouts: &[&texture_bind_group_layout],
push_constant_ranges: &[mvp_push_constant],
});
device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: Some("texture render pipeline"),
layout: Some(&render_pipeline_layout),
vertex: wgpu::VertexState {
module: &shader,
entry_point: "vs_main",
buffers: &[
TextureVertex::desc(),
],
},
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: "fs_main",
targets: &[Some(wgpu::ColorTargetState {
format: config.format,
blend: Some(wgpu::BlendState::REPLACE),
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),
// Setting this to anything other than Fill requires
// Features::NON_FILL_POLYGON_MODE
polygon_mode: wgpu::PolygonMode::Fill,
// Requires Features::DEPTH_CLIP_CONTROL
unclipped_depth: false,
// Requires Features::CONSERVATIVE_RASTERIZATION
conservative: false,
},
depth_stencil: None,
// multisampling, we don't need it
multisample: wgpu::MultisampleState {
count: 1,
mask: !0,
alpha_to_coverage_enabled: false,
},
multiview: None,
})
};
let shape_render_pipeline = {
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: Some("shape shader"),
source: wgpu::ShaderSource::Wgsl(include_str!("shaders/shape.wgsl").into()),
});
let render_pipeline_layout =
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("shape render pipeline layout"),
bind_group_layouts: &[],
push_constant_ranges: &[],
});
device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: Some("shape render pipeline"),
layout: Some(&render_pipeline_layout),
vertex: wgpu::VertexState {
module: &shader,
entry_point: "vs_main",
buffers: &[
ColorVertex::desc(),
],
},
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: "fs_main",
targets: &[Some(wgpu::ColorTargetState {
format: config.format,
blend: Some(wgpu::BlendState::REPLACE),
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),
// Setting this to anything other than Fill requires
// Features::NON_FILL_POLYGON_MODE
polygon_mode: wgpu::PolygonMode::Fill,
// Requires Features::DEPTH_CLIP_CONTROL
unclipped_depth: false,
// Requires Features::CONSERVATIVE_RASTERIZATION
conservative: false,
},
depth_stencil: None,
// multisampling, we don't need it
multisample: wgpu::MultisampleState {
count: 1,
mask: !0,
alpha_to_coverage_enabled: false,
},
multiview: None,
})
};
let quad_mesh = {
let mesh = Mesh {
vertices: [
ColorVertex { position: [0.0, 0.0], color: [1.0, 0.0, 0.0] },
ColorVertex { position: [1.0, 0.0], color: [0.0, 1.0, 0.0] },
ColorVertex { position: [1.0, 1.0], color: [0.0, 0.0, 1.0] },
ColorVertex { position: [0.0, 1.0], color: [0.5, 0.5, 0.5] },
],
indices: [
0, 1, 2,
0, 2, 3,
],
};
GpuMesh::create(&device, mesh)
};
let matrix_layout = utils::new_matrix_layout(&device);
let texture_layout = utils::new_texture_layout(&device);
Ok(Self {
texture_layout,
matrix_layout,
frame,
surface,
device,
queue,
config,
surface_size,
aspect_matrix,
output,
texture_bind_group_layout,
texture_render_pipeline,
shape_render_pipeline,
quad_mesh,
config,
queue,
device,
})
}
pub fn create_gpu_texture(&mut self, buf: &[u8], size: Size)
-> GpuTexture
{
GpuTexture::create(&self.device, &self.texture_bind_group_layout, buf, size)
}
pub fn create_texture_mesh(&self) -> GpuMesh<TextureVertex, 4, 6>
{
GpuMesh::create(&self.device, TEXTURE_QUAD)
}
pub fn render<S: Sprite>(&mut self, sprite: &mut S) {
let output = match &self.output {
Some(out) => out,
None => {
self.create_output();
&self.output.as_ref().unwrap()
},
};
//TODO move that to output struct ?
let view = output.texture.create_view(&wgpu::TextureViewDescriptor::default());
match sprite.render_data() {
RenderData::Texture ((matrix, gpu_mesh, texture)) => {
let mut texture = texture.borrow_mut();
if texture.is_synced == false {
texture.update(&mut self.queue);
}
if gpu_mesh.is_synced() == false {
gpu_mesh.update(&mut self.queue);
}
let mut encoder = self.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor {
label: Some("Render Encoder"),
});
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("Render Pass"),
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
view: &view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Load, store: true, },
})],
depth_stencil_attachment: None,
});
render_pass.set_pipeline(&self.texture_render_pipeline);
render_pass.set_vertex_buffer(0, gpu_mesh.vertex_buffer.slice(..));
render_pass.set_index_buffer(gpu_mesh.index_buffer.slice(..),
wgpu::IndexFormat::Uint16);
render_pass.set_bind_group(0, &texture.bind_group, &[]);
debug!("mat: {:#?}", matrix.get_matrix());
render_pass.set_push_constants(
wgpu::ShaderStages::VERTEX,
0,
bytemuck::bytes_of(&(self.aspect_matrix * matrix.get_matrix()))
);
render_pass.draw_indexed(0..gpu_mesh.index_number, 0, 0..1);
drop(render_pass);
self.queue.submit(std::iter::once(encoder.finish()));
},
_ => (),
}
}
pub fn clear(&mut self, color: Pixel) {
let output = match &self.output {
Some(out) => out,
None => {
self.create_output();
&self.output.as_ref().unwrap()
},
};
let view = output.texture.create_view(&wgpu::TextureViewDescriptor::default());
let view = self.create_texture_view();
let mut encoder = self.device.create_command_encoder(&wgpu::CommandEncoderDescriptor {
label: Some("Clear Encoder"),
});
@ -366,29 +121,86 @@ impl WgpuRenderer {
self.queue.submit(std::iter::once(encoder.finish()));
}
/// Resizes the render area to fit the given size.
///
/// The current frame is dropped, clearing any of the rendering done. The underlying surface is
/// then reconfigured to the right size before a new frame can be created.
///
/// # Panics
///
/// The function will panic is the given size has any of its values equal to 0 or if the
/// renderer fails to create a new frame
pub fn resize(&mut self, size: Size) {
trace!("resizing render area...");
// check for valid size
if size.w == 0 || size.h == 0 {
panic!("window has zero as at least one of its dimensions");
}
self.surface_size = size;
self.aspect_matrix = Matrix3::from_nonuniform_scale(size.h as f32 / size.w as f32, 1.0);
//destroy current frame
match self.frame.take() {
Some(out) => drop(out),
None => {}//nothing to do
}
//reconfigure surface
self.config.width = size.w;
self.config.height = size.h;
self.surface.configure(&self.device, &self.config);
//generate new frame from new surface
let frame = self.create_frame();
let _ = self.frame.insert(frame);
debug!("render area resized !");
}
/// Presents the current frame to the screen.
///
/// The current frame is presented and a new one is created for the future renders
///
/// # Panics
///
/// The function will panic if the renderer fails to create a new frame
pub fn present(&mut self) {
match self.output.take() {
trace!("presenting frame...");
match self.frame.take() {
Some(out) => out.present(),
None => {
}//nothing to do
None => {}//nothing to do
}
debug!("frame presented !");
//generate next frame
let frame = self.create_frame();
let _ = self.frame.insert(frame);
}
fn create_output(&mut self) {
self.output = Some(
pub fn create_texture_view(&self) -> wgpu::TextureView {
self.frame
.as_ref()
.unwrap()
.texture
.create_view(&wgpu::TextureViewDescriptor::default())
}
/// Creates a new frame to be rendered on.
///
/// In case of a lost surface, will try to reconfigure it before creating the frame.
///
/// #Panics
///
/// The underlying backend will panic if a new frame is created while the previous one is still
/// alive. Only call this function after the previous frame was either dropped or presented.
///
/// The function will panic if the frame can't be created.
fn create_frame(&mut self) -> wgpu::SurfaceTexture {
trace!("creating new frame...");
let surface_texture = {
self.surface.get_current_texture()
.map_err(|err| match err {
wgpu::SurfaceError::Lost => {
@ -397,161 +209,17 @@ impl WgpuRenderer {
self.surface.get_current_texture()
},
_ => Err(err)
}).unwrap()
);
})
.map_err(|_| "Failed to acquire to SurfaceTexture, giving up")
.unwrap()
};
debug!("frame created !");
surface_texture
}
}
pub struct GpuMesh<V, const V_NB: usize, const I_NB: usize>
where
V: Copy + Clone + bytemuck::Pod + bytemuck::Zeroable,
{
vertex_buffer: wgpu::Buffer,
index_buffer: wgpu::Buffer,
index_number: u32,
mesh: Mesh<V, V_NB, I_NB>,
is_synced: bool,
}
impl<V, const V_NB: usize, const I_NB: usize> GpuMesh<V, V_NB, I_NB>
where
V: Copy + Clone + bytemuck::Pod + bytemuck::Zeroable,
{
pub fn create(device: &wgpu::Device, mesh: Mesh<V, V_NB, I_NB>) -> Self {
use std::mem::size_of;
use wgpu_types::BufferUsages as Usages;
let vertex_buffer = device.create_buffer(
&wgpu_types::BufferDescriptor {
label: Some("Vertex Buffer"),
size: (V_NB * size_of::<V>()) as u64,
usage: Usages::VERTEX.union(Usages::COPY_DST),
mapped_at_creation: false,
}
);
let index_buffer = device.create_buffer( &wgpu_types::BufferDescriptor {
label: Some("Index Buffer"),
size: (I_NB * size_of::<u16>()) as u64,
usage: Usages::INDEX.union(Usages::COPY_DST),
mapped_at_creation: false,
}
);
Self {
vertex_buffer,
index_buffer,
index_number: mesh.indices.len() as u32,
mesh,
is_synced: true,
}
}
pub fn set_mesh(&mut self, mesh: Mesh<V, V_NB, I_NB>) {
self.mesh = mesh;
self.is_synced = false;
}
pub fn is_synced(&self) -> bool {
self.is_synced
}
pub fn update(&mut self, queue: &wgpu::Queue) {
queue.write_buffer(&self.vertex_buffer, 0, bytemuck::cast_slice(&self.mesh.vertices));
queue.write_buffer(&self.index_buffer, 0, bytemuck::cast_slice(&self.mesh.indices));
self.is_synced = true;
}
}
pub enum RenderData<'a> {
Texture ((
&'a mut ModelMatrix,
&'a mut GpuMesh<TextureVertex, 4, 6>,
&'a Rc<RefCell<GpuTexture>>,
)),
Shape (&'a GpuMesh<ColorVertex, 4, 6>),
}
//--Renderer struct utils---------------------------------------------------------------------------
#[repr(C)]
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
pub struct TextureVertex {
pub position: [f32; 2],
pub tex_coords: [f32; 2],
}
impl TextureVertex {
const ATTRIBS: [wgpu::VertexAttribute; 2] =
wgpu::vertex_attr_array![0 => Float32x2, 1 => Float32x2];
fn desc<'a>() -> wgpu::VertexBufferLayout<'a> {
wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<TextureVertex>() as wgpu::BufferAddress,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &Self::ATTRIBS,
}
}
}
#[repr(C)]
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
pub struct ColorVertex {
pub position: [f32; 2],
pub color: [f32; 3],
}
impl ColorVertex {
const ATTRIBS: [wgpu::VertexAttribute; 2] =
wgpu::vertex_attr_array![0 => Float32x2, 1 => Float32x3];
fn desc<'a>() -> wgpu::VertexBufferLayout<'a> {
wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<ColorVertex>() as wgpu::BufferAddress,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &Self::ATTRIBS,
}
}
}
pub struct Mesh<V, const V_NB: usize, const I_NB: usize>
where
V: Copy + Clone + bytemuck::Pod + bytemuck::Zeroable,
{
pub vertices: [V; V_NB],
pub indices: [u16; I_NB],
}
pub const TEXTURE_QUAD: Mesh<TextureVertex, 4, 6> = Mesh {
vertices: [
TextureVertex { position: [0.0, 0.0], tex_coords: [0.0, 1.0] },
TextureVertex { position: [1.0, 0.0], tex_coords: [1.0, 1.0] },
TextureVertex { position: [1.0, 1.0], tex_coords: [1.0, 0.0] },
TextureVertex { position: [0.0, 1.0], tex_coords: [0.0, 0.0] },
],
indices: [
0, 1, 2,
0, 2, 3,
],
};
//
//const QUAD: Mesh<ColorVertex> = Mesh {
// vertices: [
// ColorVertex { position: [0.0, 0.0], color: [1.0, 0.0, 0.0] },
// ColorVertex { position: [1.0, 0.0], color: [0.0, 1.0, 0.0] },
// ColorVertex { position: [1.0, 1.0], color: [0.0, 0.0, 1.0] },
// ColorVertex { position: [0.0, 1.0], color: [0.5, 0.5, 0.5] },
// ],
// indices: [
// 0, 1, 2,
// 0, 2, 3,
// ],
//};
impl From<Pixel> for wgpu::Color {

97
src/renderer/matrix.rs Normal file
View File

@ -0,0 +1,97 @@
#[allow(unused_imports)]
use log::{debug, error, info, trace, warn};
use crate:: utils::Position;
use super::{Uniform, WgpuRenderer};
use cgmath::{
Deg,
Vector2,
Matrix3,
};
pub const MATRIX_SIZE: usize = 48;//std::mem::size_of::<Matrix3<f32>>();
//--ModelMatrix struct------------------------------------------------------------------------------
pub struct ModelMatrix {
position: Position,
rotation: Deg<f32>,
scale: f32,
uniform: Uniform<MATRIX_SIZE>,
is_synced: bool,
}
impl ModelMatrix {
pub fn new(renderer: &WgpuRenderer,
pos: Position,
rot: f32,
scale: f32)
-> Self
{
Self {
position: pos,
rotation: Deg (rot),
scale,
uniform: Uniform::create(renderer, &renderer.matrix_layout),
is_synced: false,
}
}
pub fn default(renderer: &WgpuRenderer) -> Self {
Self::new(renderer, Position::origin(), 0.0, 1.0)
}
pub fn set_position(&mut self, pos: Position) {
self.position = pos;
self.is_synced = false;
}
pub fn set_rotation(&mut self, rot: f32) {
self.rotation = Deg (rot);
self.is_synced = false;
}
pub fn set_scale(&mut self, scale: f32) {
self.scale = scale;
self.is_synced = false;
}
pub fn get_uniform(&mut self) -> &mut Uniform<MATRIX_SIZE> {
use cgmath::{Basis3, Rotation3};
if self.is_synced == false {
let pos_vec = Vector2 {
x: self.position.x as f32,
y: self.position.y as f32,
};
let rotation_mat = Matrix3::from(Basis3::from_angle_z(self.rotation));
let scale_mat = Matrix3::from_scale(self.scale);
let translation_mat = Matrix3::from_translation(pos_vec);
let aspect_mat = Matrix3::from_nonuniform_scale(1.0/1280.0, 1.0/720.0);
let matrix = aspect_mat * translation_mat * rotation_mat * scale_mat;
let mat_bytes: [u8; 36] = bytemuck::bytes_of(&matrix).try_into().unwrap();
let mut bytes = [0; 48];
for i in 0..12 {
bytes[i] = mat_bytes[i];
}
for i in 0..12 {
bytes[i+16] = mat_bytes[i+12];
}
for i in 0..12 {
bytes[i+32] = mat_bytes[i+24];
}
self.uniform.update(bytes);
self.is_synced = true;
}
&mut self.uniform
}
}

98
src/renderer/texture.rs Normal file
View File

@ -0,0 +1,98 @@
#[allow(unused_imports)]
use log::{debug, error, info, trace, warn};
use crate::{
utils::{Pixel, Size},
renderer::WgpuRenderer,
};
pub struct Texture {
pub texture: wgpu::Texture,
pub bind_group: wgpu::BindGroup,
pub buffer: Vec<Pixel>,
pub size: Size,
pub is_synced: bool,
}
impl Texture {
pub fn create(renderer: &WgpuRenderer,
buffer: &[u8],
size: Size)
-> Self
{
let texture = renderer.device.create_texture(
&wgpu::TextureDescriptor {
label: None,
size: size.into(),
mip_level_count: 1,
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Rgba8UnormSrgb,
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
}
);
let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
let sampler = renderer.device.create_sampler(
&wgpu::SamplerDescriptor {
address_mode_u: wgpu::AddressMode::Repeat,
address_mode_v: wgpu::AddressMode::Repeat,
address_mode_w: wgpu::AddressMode::Repeat,
mag_filter: wgpu::FilterMode::Linear,
min_filter: wgpu::FilterMode::Nearest,
mipmap_filter: wgpu::FilterMode::Nearest,
..Default::default()
}
);
let bind_group = renderer.device.create_bind_group(
&wgpu::BindGroupDescriptor {
layout: &renderer.texture_layout,
entries: &[
wgpu::BindGroupEntry {
binding: 0,
resource: wgpu::BindingResource::TextureView(&view),
},
wgpu::BindGroupEntry {
binding: 1,
resource: wgpu::BindingResource::Sampler(&sampler),
}
],
label: Some("texture_bind_group"),
}
);
Self {
texture,
bind_group,
buffer: Vec::from(bytemuck::cast_slice(buffer)),
size,
is_synced: false,
}
}
pub fn update(&mut self, queue: &wgpu::Queue) {
queue.write_texture(
wgpu::ImageCopyTexture {
aspect: wgpu::TextureAspect::All,
texture: &self.texture,
mip_level: 0,
origin: wgpu::Origin3d::ZERO,
},
bytemuck::cast_slice(&self.buffer),
wgpu::ImageDataLayout {
offset: 0,
bytes_per_row: std::num::NonZeroU32::new(4 * self.size.w),
rows_per_image: std::num::NonZeroU32::new(self.size.h),
},
self.size.into(),
);
self.is_synced = true;
}
}

62
src/renderer/uniform.rs Normal file
View File

@ -0,0 +1,62 @@
#[allow(unused_imports)]
use log::{debug, error, info, trace, warn};
use super::WgpuRenderer;
//--Uniform struct----------------------------------------------------------------------------------
pub struct Uniform<const S: usize> {
buffer: wgpu::Buffer,
bind_group: wgpu::BindGroup,
data: [u8; S],
is_synced: bool,
}
impl<const S: usize> Uniform<S> {
pub fn create(renderer: &WgpuRenderer, layout: &wgpu::BindGroupLayout) -> Self {
let buffer = renderer.device.create_buffer(
&wgpu_types::BufferDescriptor {
label: Some("Uniform Buffer"),
size: S as u64,
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: false,
}
);
let bind_group = renderer.device.create_bind_group(&wgpu::BindGroupDescriptor {
layout,
entries: &[
wgpu::BindGroupEntry {
binding: 0,
resource: buffer.as_entire_binding(),
}
],
label: Some("uniform_bind_group"),
});
Self {
buffer,
bind_group,
data: [0; S],
is_synced: false,
}
}
pub fn update(&mut self, data: [u8; S]) {
self.data = data;
self.is_synced = false;
}
pub fn get_bind_group(&mut self, queue: &wgpu::Queue) -> &wgpu::BindGroup {
if self.is_synced == false {
queue.write_buffer(&self.buffer, 0, &self.data);
self.is_synced = true;
}
&self.bind_group
}
}

166
src/renderer/utils.rs Normal file
View File

@ -0,0 +1,166 @@
#[allow(unused_imports)]
use log::{debug, error, info, trace, warn};
//--Internal imports--------------------------------------------------------------------------------
//--External imports--------------------------------------------------------------------------------
use std::marker::PhantomData;
use super::WgpuRenderer;
//--Bind group layouts------------------------------------------------------------------------------
/// Creates the layout bind_group used by all matrixes of the renderer
pub fn new_matrix_layout(device: &wgpu::Device) -> wgpu::BindGroupLayout {
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
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,
}
],
label: Some("matrix_bind_group_layout"),
})
}
/// Crates the layout bind group used by all textures of the renderer
pub fn new_texture_layout(device: &wgpu::Device) -> wgpu::BindGroupLayout {
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[
wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Texture {
multisampled: false,
view_dimension: wgpu::TextureViewDimension::D2,
sample_type: wgpu::TextureSampleType::Float { filterable: true },
},
count: None,
},
wgpu::BindGroupLayoutEntry {
binding: 1,
visibility: wgpu::ShaderStages::FRAGMENT,
// This should match the filterable field of the
// corresponding Texture entry above.
ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
count: None,
},
],
label: Some("texture_bind_group_layout"),
})
}
//--TextureVertex struct----------------------------------------------------------------------------
#[repr(C)]
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
pub struct ColorVertex {
pub position: [f32; 2],
pub color: [f32; 3],
}
impl ColorVertex {
const ATTRIBS: [wgpu::VertexAttribute; 2] =
wgpu::vertex_attr_array![0 => Float32x2, 1 => Float32x3];
pub fn desc<'a>() -> wgpu::VertexBufferLayout<'a> {
wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<ColorVertex>() as wgpu::BufferAddress,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &Self::ATTRIBS,
}
}
}
//--Mesh struct-------------------------------------------------------------------------------------
/// Handles the buffers to be used to draw a Mesh
///
/// The mesh consist of an array of vertices, and its ccorresponding indices.
///
/// A vertex can be any type that can be converted to a byte array using the bytemuck crate.
/// Generaly, adding `#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]` to a struct
/// is enough for that.
///
/// An index is a standard u16
///
/// A mesh can be used with, and only with, the renderer for wich it was created
pub struct Mesh<V, const V_NB: usize, const I_NB: usize>
where
V: Copy + Clone + bytemuck::Pod + bytemuck::Zeroable,
{
vertex_buffer: wgpu::Buffer,
index_buffer: wgpu::Buffer,
vertex_type: PhantomData<V>,
}
impl <V, const V_NB: usize, const I_NB: usize> Mesh<V, V_NB, I_NB>
where
V: Copy + Clone + bytemuck::Pod + bytemuck::Zeroable + std::fmt::Debug
{
/// Creates a new mesh using the [Device] from the renderer to be used
pub fn new(device: &wgpu::Device) -> Self {
use std::mem::size_of;
use wgpu_types::BufferUsages as Usages;
let vertex_buffer = device.create_buffer(
&wgpu_types::BufferDescriptor {
label: Some("Vertex Buffer"),
size: (V_NB * size_of::<V>()) as u64,
usage: Usages::VERTEX | Usages::COPY_DST,
mapped_at_creation: false,
}
);
let index_buffer = device.create_buffer( &wgpu_types::BufferDescriptor {
label: Some("Index Buffer"),
size: (I_NB * size_of::<u16>()) as u64,
usage: Usages::INDEX | Usages::COPY_DST,
mapped_at_creation: false,
}
);
Self {
vertex_buffer,
index_buffer,
vertex_type: PhantomData::default(),
}
}
/// Updates the vertices of the [Mesh]. The modification will be applied before the next
/// rendering of the [Mesh]. The function will fail if the given slice has more elements than
/// specified at the [Mesh] creation
pub fn set_vertices(&mut self, renderer: &WgpuRenderer, vertices: &[V]) {
renderer.queue.write_buffer(&self.vertex_buffer, 0, bytemuck::cast_slice(vertices));
}
/// Updates the indices of the [Mesh]. The modification will be applied before the next
/// rendering of the [Mesh]. The function will fail if the given slice has more elements than
/// specified at the [Mesh] creation
pub fn set_indices(&mut self, renderer: &WgpuRenderer, indices: &[u16]) {
renderer.queue.write_buffer(&self.index_buffer, 0, bytemuck::cast_slice(indices));
}
/// Returns a [BufferSlice] containing the vertices, to be used in a render pass
pub fn get_vertex_buffer_slice(&self) -> wgpu::BufferSlice {
self.vertex_buffer.slice(..)
}
/// Returns a [BufferSlice] containing the indices, to be used in a render pass
pub fn get_index_buffer_slice(&self) -> wgpu::BufferSlice {
self.index_buffer.slice(..)
}
}

View File

@ -1,276 +1,45 @@
#[allow(unused_imports)]
use log::{debug, error, info, trace, warn};
//--Internal imports--------------------------------------------------------------------------------
mod texture_sprite;
pub use texture_sprite::TextureSprite;
mod text_sprite;
pub use text_sprite::TextSprite;
mod shape_sprite;
pub use shape_sprite::ShapeSprite;
use crate::{
renderer::{Mesh, GpuMesh, RenderData, TextureVertex},
shape::Shape,
texture::Texture,
utils::{Pixel, Position, Size},
utils::Position,
renderer::WgpuRenderer,
};
use cgmath::{
Deg,
Vector2,
Matrix3,
Matrix4,
};
use std::{
rc::Rc,
cell::RefCell,
slice::{Iter, IterMut},
};
//--External imports--------------------------------------------------------------------------------
//--Sprite trait------------------------------------------------------------------------------------
/// The interface for everything that can be rendered by the engine.
///
/// This trait provides a few generic functions to have basic controls over the rendered object as
/// well as the unique function necessary for it to be rendered
pub trait Sprite {
/// Set the position of the [Sprite] on the screen
fn set_position(&mut self, pos: Position);
/// Set the rotation of the [Sprite] on the screen
fn set_rotation(&mut self, rot: f32);
/// Set the alpha of the [Sprite] on the screen
fn set_alpha(&mut self, alpha: u8);
/// Set the scale of the [Sprite] on the screen
fn set_scale(&mut self, scale: f32);
fn render_data(&mut self) -> RenderData;
}
//--ModelMatrix struct------------------------------------------------------------------------------
pub struct ModelMatrix {
position: Vector2<f32>,
rotation: Deg<f32>,
scale: f32,
matrix: Matrix3<f32>,
is_synced: bool,
}
impl ModelMatrix {
pub fn new(pos: Vector2<f32>, rot: f32, scale: f32) -> Self {
use cgmath::SquareMatrix;
Self {
position: pos,
rotation: Deg (rot),
scale,
matrix: Matrix3::identity(),
is_synced: false,
}
}
pub fn default() -> Self {
Self::new(Vector2 {x: 0.1, y: 0.1}, 0.0, 1.0)
}
pub fn set_position(&mut self, pos: Vector2<f32>) {
self.position = pos;
self.is_synced = false;
}
pub fn set_rotation(&mut self, rot: f32) {
self.rotation = Deg (rot);
self.is_synced = false;
}
pub fn set_scale(&mut self, scale: f32) {
self.scale = scale;
self.is_synced = false;
}
pub fn get_matrix(&mut self) -> Matrix3<f32> {
use cgmath::{Basis3, Rotation3, SquareMatrix};
if self.is_synced == false {
let rot_mat = Matrix3::from(Basis3::from_angle_z(self.rotation));
debug!("rot_mat : {:#?}", rot_mat);
let scale_mat = Matrix3::from_scale(self.scale);
debug!("scale_mat : {:#?}", scale_mat);
let pos_mat = Matrix3::from_translation(self.position);
debug!("pos_mat : {:#?}", pos_mat);
self.matrix = pos_mat * rot_mat * scale_mat;
self.is_synced = true;
}
self.matrix
}
}
//--TextureSprite struct----------------------------------------------------------------------------
pub struct TextureSprite {
matrix: ModelMatrix,
gpu_mesh: GpuMesh<TextureVertex, 4, 6>,
texture: Texture,
texture_offset: Position,
texture_size: Size,
}
impl TextureSprite {
pub fn create(texture: Texture, size: Size, gpu_mesh: GpuMesh<TextureVertex, 4, 6>) -> Self {
Self {
matrix: ModelMatrix::default(),
gpu_mesh,
texture,
texture_offset: Position::origin(),
texture_size: size,
}
}
pub fn set_texture(&mut self, texture: Texture, offset: Option<Position>) {
// update texture
self.texture = texture;
let size = self.texture.get_size();
// compute normalized coordinates
self.texture_offset = offset.unwrap_or(Position::origin());
let x_size = self.texture_size.w as f32 / size.w as f32;
let y_size = self.texture_size.h as f32 / size.h as f32;
let x_offset = self.texture_offset.x as f32 / size.w as f32;
let y_offset = self.texture_offset.y as f32 / size.h as f32;
// generate new sprite mesh
let mesh = Mesh {
vertices: [
TextureVertex {
position: [0.0, 0.0],
tex_coords: [x_offset , y_offset + y_size],
},
TextureVertex {
position: [1.0, 0.0],
tex_coords: [x_offset + x_size, y_offset + y_size],
},
TextureVertex {
position: [1.0, 1.0],
tex_coords: [x_offset + x_size, y_offset ],
},
TextureVertex {
position: [0.0, 1.0],
tex_coords: [x_offset , y_offset ],
},
],
indices: [
0, 1, 2,
0, 2, 3,
],
};
self.gpu_mesh.set_mesh(mesh);
}
pub fn set_pixel(&mut self, pos: Position, pix: Pixel) {
//TODO check pos ?
self.texture.set_pixel(self.texture_offset + pos, pix);
}
pub fn for_each<F: FnMut(&mut Pixel)>(&mut self, func: F) {
//TODO check pos ?
self.texture.for_each_in_area(func, self.texture_offset, self.texture_size);
}
}
impl Sprite for TextureSprite {
fn set_position(&mut self, pos: Position) {
let normalized_pos = Vector2 { x: pos.x as f32 / 720.0, y: pos.y as f32 / 1280.0 };
self.matrix.set_position(normalized_pos);
}
fn set_rotation(&mut self, rot: f32) {
self.matrix.set_rotation(rot);
}
fn set_alpha(&mut self, _alpha: u8) {
unimplemented!();
}
fn set_scale(&mut self, scale: f32) {
self.matrix.set_scale(scale);
}
fn render_data(&mut self) -> RenderData {
RenderData::Texture ((&mut self.matrix, &mut self.gpu_mesh, &self.texture.gpu_texture()))
}
}
//--TextSprite struct-------------------------------------------------------------------------------
pub struct TextSprite {
matrix: Matrix4<f32>,
size: Size,
text: &'static str, //TODO: temporary
}
impl TextSprite {
pub fn set_text(&mut self, _text: &'static str) {
unimplemented!();
}
pub fn set_color(&mut self, _color: Pixel) {
unimplemented!();
}
}
impl Sprite for TextSprite {
fn set_position(&mut self, _pos: Position) {
unimplemented!();
}
fn set_rotation(&mut self, _rot: f32) {
unimplemented!();
}
fn set_alpha(&mut self, _alpha: u8) {
unimplemented!();
}
fn set_scale(&mut self, _scale: f32) {
unimplemented!();
}
fn render_data(&mut self) -> RenderData {
todo!();
}
}
//--ShapeSprite struct-------------------------------------------------------------------------------
pub struct ShapeSprite {
matrix: Matrix4<f32>,
size: Size,
shape: Shape,
}
impl ShapeSprite {
pub fn set_shape(&mut self, _shape: Shape) {
unimplemented!();
}
pub fn set_color(&mut self, _color: Pixel) {
unimplemented!();
}
}
impl Sprite for ShapeSprite {
fn set_position(&mut self, _pos: Position) {
unimplemented!();
}
fn set_rotation(&mut self, _rot: f32) {
unimplemented!();
}
fn set_alpha(&mut self, _alpha: u8) {
unimplemented!();
}
fn set_scale(&mut self, _scale: f32) {
unimplemented!();
}
fn render_data(&mut self) -> RenderData {
todo!();
}
/// Renders the [Sprite] using the given rendering context
fn render(&mut self, renderer: &mut WgpuRenderer);
}

View File

@ -1,7 +1,5 @@
// Vertex shader
var<push_constant> model_matrix: mat3x3<f32>;
struct VertexInput {
@location(0) position: vec2<f32>,
@location(1) tex_coords: vec2<f32>,
@ -12,6 +10,9 @@ struct VertexOutput {
@location(0) tex_coords: vec2<f32>,
}
@group(0)@binding(0)
var<uniform> model_matrix: mat3x3<f32>;
@vertex
fn vs_main(model: VertexInput) -> VertexOutput {
@ -24,9 +25,9 @@ fn vs_main(model: VertexInput) -> VertexOutput {
// Fragment shader
@group(0) @binding(0)
@group(1)@binding(0)
var t_diffuse: texture_2d<f32>;
@group(0)@binding(1)
@group(1)@binding(1)
var s_diffuse: sampler;
@fragment

118
src/sprite/shape_sprite.rs Normal file
View File

@ -0,0 +1,118 @@
#[allow(unused_imports)]
use log::{debug, error, info, trace, warn};
//--Internal imports--------------------------------------------------------------------------------
use crate::{
renderer::WgpuRenderer,
sprite::Sprite,
shape::Shape,
utils::{Pixel, Position, Size},
};
//--External imports--------------------------------------------------------------------------------
use cgmath::Matrix4;
//--ShapeSprite struct-------------------------------------------------------------------------------
#[allow(dead_code)]
pub struct ShapeSprite {
matrix: Matrix4<f32>,
size: Size,
shape: Shape,
}
impl ShapeSprite {
pub fn set_shape(&mut self, _shape: Shape) {
todo!();
}
pub fn set_color(&mut self, _color: Pixel) {
todo!();
}
}
impl Sprite for ShapeSprite {
fn set_position(&mut self, _pos: Position) {
todo!();
}
fn set_rotation(&mut self, _rot: f32) {
todo!();
}
fn set_alpha(&mut self, _alpha: u8) {
todo!();
}
fn set_scale(&mut self, _scale: f32) {
todo!();
}
fn render(&mut self, _renderer: &mut WgpuRenderer) {
todo!();
}
}
#[allow(dead_code)]
fn initialize_pipeline(renderer: &WgpuRenderer) -> wgpu::RenderPipeline {
use crate::renderer::utils::ColorVertex;
let shader = renderer.device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: Some("shape shader"),
source: wgpu::ShaderSource::Wgsl(include_str!("shaders/shape.wgsl").into()),
});
let render_pipeline_layout =
renderer.device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("shape render pipeline layout"),
bind_group_layouts: &[
&renderer.matrix_layout,
],
push_constant_ranges: &[],
});
renderer.device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: Some("shape render pipeline"),
layout: Some(&render_pipeline_layout),
vertex: wgpu::VertexState {
module: &shader,
entry_point: "vs_main",
buffers: &[
ColorVertex::desc(),
],
},
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: "fs_main",
targets: &[Some(wgpu::ColorTargetState {
format: renderer.config.format,
blend: Some(wgpu::BlendState::REPLACE),
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),
// Setting this to anything other than Fill requires
// Features::NON_FILL_POLYGON_MODE
polygon_mode: wgpu::PolygonMode::Fill,
// Requires Features::DEPTH_CLIP_CONTROL
unclipped_depth: false,
// Requires Features::CONSERVATIVE_RASTERIZATION
conservative: false,
},
depth_stencil: None,
// multisampling, we don't need it
multisample: wgpu::MultisampleState {
count: 1,
mask: !0,
alpha_to_coverage_enabled: false,
},
multiview: None,
})
}

57
src/sprite/text_sprite.rs Normal file
View File

@ -0,0 +1,57 @@
#[allow(unused_imports)]
use log::{debug, error, info, trace, warn};
//--Internal imports--------------------------------------------------------------------------------
use crate::{
renderer::WgpuRenderer,
sprite::Sprite,
utils::{Pixel, Position, Size},
};
//--External imports--------------------------------------------------------------------------------
use cgmath::Matrix4;
//--TextSprite struct-------------------------------------------------------------------------------
#[allow(dead_code)]
pub struct TextSprite {
matrix: Matrix4<f32>,
size: Size,
text: &'static str, //TODO: temporary
}
impl TextSprite {
pub fn set_text(&mut self, _text: &'static str) {
todo!();
}
pub fn set_color(&mut self, _color: Pixel) {
todo!();
}
}
impl Sprite for TextSprite {
fn set_position(&mut self, _pos: Position) {
todo!();
}
fn set_rotation(&mut self, _rot: f32) {
todo!();
}
fn set_alpha(&mut self, _alpha: u8) {
todo!();
}
fn set_scale(&mut self, _scale: f32) {
todo!();
}
fn render(&mut self, _renderer: &mut WgpuRenderer) {
todo!();
}
}

View File

@ -0,0 +1,288 @@
#[allow(unused_imports)]
use log::{debug, error, info, trace, warn};
//--Internal imports--------------------------------------------------------------------------------
use super::Sprite;
use crate::{
texture::TextureHandle,
renderer::{
utils::Mesh,
WgpuRenderer, ModelMatrix,
},
utils::{Size, Position, Pixel},
};
//--External imports--------------------------------------------------------------------------------
use wgpu;
use std::cell::RefCell;
thread_local!(static PIPELINE : RefCell<Option<wgpu::RenderPipeline>> = RefCell::new(None));
//--TextureSprite struct----------------------------------------------------------------------------
pub struct TextureSprite {
matrix: ModelMatrix,
texture: TextureHandle,
inner_size: Size, //TODO move to f32
mesh: Mesh<TextureVertex, 4, 6>,
offset: Position,
scale: f32,
vertice_update_needed: bool,
}
impl TextureSprite {
const INDICES: [u16; 6] = [
0, 1, 2,
0, 2, 3,
];
pub fn new(texture: TextureHandle,
size: Size,
renderer: &WgpuRenderer)
-> Self
{
// initialize pipeline if needed
PIPELINE.with(|cell| {
if cell.borrow().is_none() {
cell.replace(Some(initialize_pipeline(renderer)));
}
});
let mut sprite = Self {
matrix: ModelMatrix::default(renderer),
texture,
inner_size: size,
mesh: Mesh::new(&renderer.device),
offset: Position::origin(),
scale: 1.0,
vertice_update_needed: false,
};
sprite.mesh.set_indices(renderer, &TextureSprite::INDICES);
sprite.update_vertices(renderer);
sprite
}
pub fn set_texture(&mut self, texture: TextureHandle, offset: Option<Position>, scale: f32) {
self.texture = texture;
self.offset = offset.unwrap_or(Position::origin());
self.scale = scale;
self.vertice_update_needed = true;
}
pub fn set_pixel(&mut self, pos: Position, pix: Pixel) {
//TODO check pos ?
self.texture.set_pixel(self.offset + pos, pix);
}
pub fn for_each<F: FnMut(&mut Pixel)>(&mut self, func: F) {
//TODO check pos ?
//TODO take scale into account
self.texture.for_each_in_area(func, self.offset, self.inner_size);
}
fn update_vertices(&mut self, renderer: &WgpuRenderer) {
debug!("Updating vertices...");
let size = self.texture.get_size();
// compute normalized coordinates
let x_size = self.inner_size.w as f32 / size.w as f32 * self.scale;
let y_size = self.inner_size.h as f32 / size.h as f32 * self.scale;
let x_offset = self.offset.x as f32 / size.w as f32;
let y_offset = self.offset.y as f32 / size.h as f32;
// compute mesh size
let w = self.inner_size.w as f32;
let h = self.inner_size.h as f32;
let mesh = [
TextureVertex {
position: [-w, -h],
tex_coords: [x_offset , y_offset + y_size],
},
TextureVertex {
position: [ w, -h],
tex_coords: [x_offset + x_size, y_offset + y_size],
},
TextureVertex {
position: [ w, h],
tex_coords: [x_offset + x_size, y_offset ],
},
TextureVertex {
position: [-w, h],
tex_coords: [x_offset , y_offset ],
},
];
self.mesh.set_vertices(renderer, &mesh);
self.vertice_update_needed = false;
info!("Vertices updated!");
}
}
impl Sprite for TextureSprite {
fn set_position(&mut self, pos: Position) {
self.matrix.set_position(pos);
}
fn set_rotation(&mut self, rot: f32) {
self.matrix.set_rotation(rot);
}
fn set_alpha(&mut self, _alpha: u8) {
todo!();
}
fn set_scale(&mut self, scale: f32) {
self.matrix.set_scale(scale);
}
fn render(&mut self, renderer: &mut WgpuRenderer) {
// update mesh if necessary
if self.vertice_update_needed == true {
self.update_vertices(renderer);
}
// update texture if necessary
let texture = self.texture.texture();
if texture.borrow().is_synced == false {
texture.borrow_mut().update(&mut renderer.queue);
}
// create command encoder
let mut encoder = renderer.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor {
label: Some("Render Encoder"),
});
// write render pass
PIPELINE.with(|pipeline| {
let pipeline = pipeline.borrow();
let texture_bind_group = &texture.borrow().bind_group;
let view = renderer.create_texture_view();
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("Render Pass"),
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
view: &view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Load, store: true, },
})],
depth_stencil_attachment: None,
});
render_pass.set_pipeline(pipeline.as_ref().unwrap());
render_pass.set_vertex_buffer(0, self.mesh.get_vertex_buffer_slice());
render_pass.set_index_buffer(self.mesh.get_index_buffer_slice(),
wgpu::IndexFormat::Uint16);
render_pass.set_bind_group(0,
self.matrix.get_uniform().get_bind_group(&renderer.queue),
&[]);
render_pass.set_bind_group(1, texture_bind_group, &[]);
render_pass.draw_indexed(0..6, 0, 0..1);
drop(render_pass);
});
renderer.queue.submit(std::iter::once(encoder.finish()));
}
}
//--Pipeline initialization-------------------------------------------------------------------------
fn initialize_pipeline(renderer: &WgpuRenderer) -> wgpu::RenderPipeline {
let shader = renderer.device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: Some("texture shader"),
source: wgpu::ShaderSource::Wgsl(include_str!("shaders/texture.wgsl").into()),
});
let render_pipeline_layout =
renderer.device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("texture render pipeline layout"),
bind_group_layouts: &[
&renderer.matrix_layout,
&renderer.texture_layout,
],
push_constant_ranges: &[],
});
renderer.device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: Some("texture render pipeline"),
layout: Some(&render_pipeline_layout),
vertex: wgpu::VertexState {
module: &shader,
entry_point: "vs_main",
buffers: &[
TextureVertex::layout(),
],
},
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: "fs_main",
targets: &[Some(wgpu::ColorTargetState {
format: renderer.config.format,
blend: Some(wgpu::BlendState::REPLACE),
write_mask: wgpu::ColorWrites::ALL,
})],
}),
primitive: wgpu::PrimitiveState {
topology: wgpu::PrimitiveTopology::TriangleList,
strip_index_format: None,
front_face: wgpu::FrontFace::Ccw,
cull_mode: None,//Some(wgpu::Face::Back),
// Setting this to anything other than Fill requires
// Features::NON_FILL_POLYGON_MODE
polygon_mode: wgpu::PolygonMode::Fill,
// Requires Features::DEPTH_CLIP_CONTROL
unclipped_depth: false,
// Requires Features::CONSERVATIVE_RASTERIZATION
conservative: false,
},
depth_stencil: None,
// multisampling, we don't need it
multisample: wgpu::MultisampleState {
count: 1,
mask: !0,
alpha_to_coverage_enabled: false,
},
multiview: None,
})
}
//--TextureVertex struct----------------------------------------------------------------------------
#[repr(C)]
#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
pub struct TextureVertex {
pub position: [f32; 2],
pub tex_coords: [f32; 2],
}
impl TextureVertex {
const ATTRIBS: [wgpu::VertexAttribute; 2] =
wgpu::vertex_attr_array![0 => Float32x2, 1 => Float32x2];
pub fn layout<'a>() -> wgpu::VertexBufferLayout<'a> {
wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<TextureVertex>() as wgpu::BufferAddress,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &Self::ATTRIBS,
}
}
}

View File

@ -1,136 +1,47 @@
#[allow(unused_imports)]
use log::{debug, error, info, trace, warn};
use crate::utils::{Pixel, Position, Size};
use crate::{
utils::{Pixel, Position, Size},
renderer::Texture,
};
use std::{
slice::{Iter, IterMut},
rc::Rc,
cell::RefCell,
};
//--GpuTexture struct-------------------------------------------------------------------------------
pub struct GpuTexture {
pub texture: wgpu::Texture,
pub bind_group: wgpu::BindGroup,
pub buffer: Vec<Pixel>,
pub size: Size,
pub is_synced: bool,
}
impl GpuTexture {
pub fn create(device: &wgpu::Device,
layout: &wgpu::BindGroupLayout,
buffer: &[u8],
size: Size)
-> Self
{
let texture = device.create_texture(
&wgpu::TextureDescriptor {
label: None,
size: size.into(),
mip_level_count: 1,
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Rgba8UnormSrgb,
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
}
);
let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
let sampler = device.create_sampler(
&wgpu::SamplerDescriptor {
address_mode_u: wgpu::AddressMode::Repeat,
address_mode_v: wgpu::AddressMode::Repeat,
address_mode_w: wgpu::AddressMode::Repeat,
mag_filter: wgpu::FilterMode::Linear,
min_filter: wgpu::FilterMode::Nearest,
mipmap_filter: wgpu::FilterMode::Nearest,
..Default::default()
}
);
let bind_group = device.create_bind_group(
&wgpu::BindGroupDescriptor {
layout,
entries: &[
wgpu::BindGroupEntry {
binding: 0,
resource: wgpu::BindingResource::TextureView(&view),
},
wgpu::BindGroupEntry {
binding: 1,
resource: wgpu::BindingResource::Sampler(&sampler),
}
],
label: Some("texture_bind_group"),
}
);
Self {
texture,
bind_group,
buffer: Vec::from(bytemuck::cast_slice(buffer)),
size,
is_synced: false,
}
}
pub fn update(&mut self, queue: &wgpu::Queue) {
queue.write_texture(
wgpu::ImageCopyTexture {
aspect: wgpu::TextureAspect::All,
texture: &self.texture,
mip_level: 0,
origin: wgpu::Origin3d::ZERO,
},
bytemuck::cast_slice(&self.buffer),
wgpu::ImageDataLayout {
offset: 0,
bytes_per_row: std::num::NonZeroU32::new(4 * self.size.w),
rows_per_image: std::num::NonZeroU32::new(self.size.h),
},
self.size.into(),
);
self.is_synced = true;
}
}
//--Texture struct----------------------------------------------------------------------------------
//--TextureHandle struct----------------------------------------------------------------------------
#[derive(Clone)]
pub struct Texture {
gpu_texture: Rc<RefCell<GpuTexture>>,
pub struct TextureHandle {
texture: Rc<RefCell<Texture>>,
}
impl Texture {
impl TextureHandle {
pub fn create(gpu_texture: GpuTexture) -> Self {
pub fn from_texture(texture: Texture) -> Self {
Self {
gpu_texture: Rc::new(RefCell::new(gpu_texture)),
texture: Rc::new(RefCell::new(texture)),
}
}
pub fn set_pixel(&mut self, pos: Position, pix: Pixel) {
//TODO check pos ?
let mut gpu_texture = self.gpu_texture.borrow_mut();
let width = gpu_texture.size.w;
gpu_texture.buffer[(pos.x + pos.y*width) as usize] = pix;
gpu_texture.is_synced = false;
let mut texture = self.texture.borrow_mut();
let width = texture.size.w;
texture.buffer[(pos.x + pos.y*width) as usize] = pix;
texture.is_synced = false;
}
pub fn for_each<F: FnMut(&mut Pixel)>(&mut self, mut func: F) {
let mut gpu_texture = self.gpu_texture.borrow_mut();
for pix in &mut gpu_texture.buffer {
let mut texture = self.texture.borrow_mut();
for pix in &mut texture.buffer {
func(pix);
}
gpu_texture.is_synced = false;
texture.is_synced = false;
}
pub fn for_each_in_area<F: FnMut(&mut Pixel)>(&mut self,
@ -139,23 +50,24 @@ impl Texture {
size: Size)
{
//TODO check offset and pos ?
let mut gpu_texture = self.gpu_texture.borrow_mut();
let width = gpu_texture.size.w;
let mut texture = self.texture.borrow_mut();
let width = texture.size.w;
for x in offset.x..(offset.x + size.w) {
for y in offset.y..(offset.y + size.h) {
func(&mut gpu_texture.buffer[(x + y*width) as usize]);
func(&mut texture.buffer[(x + y*width) as usize]);
}
}
gpu_texture.is_synced = false;
texture.is_synced = false;
}
pub fn gpu_texture(&self) -> &Rc<RefCell<GpuTexture>> {
pub fn texture(&self) -> &Rc<RefCell<Texture>> {
//TODO improve that
&self.gpu_texture
&self.texture
}
pub fn get_size(&self) -> Size {
self.gpu_texture.borrow().size
self.texture.borrow().size
}
}