mirror of
https://github.com/maplibre/maplibre-rs.git
synced 2025-12-08 19:05:57 +00:00
Add first test for lyon tesselation
This commit is contained in:
parent
3838725c4f
commit
742d510ed4
378
Cargo.lock
generated
378
Cargo.lock
generated
@ -41,6 +41,15 @@ dependencies = [
|
||||
"xml-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "approx"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f2a05fd1bd10b2527e20a2cd32d8873d115b8b39fe219ee25f42a8aca6ba278"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.5.2"
|
||||
@ -53,6 +62,18 @@ version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
|
||||
|
||||
[[package]]
|
||||
name = "as-slice"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45403b49e3954a4b8428a0ac21a4b7afadccf92bfd96273f1a58cd4812496ae0"
|
||||
dependencies = [
|
||||
"generic-array 0.12.4",
|
||||
"generic-array 0.13.3",
|
||||
"generic-array 0.14.4",
|
||||
"stable_deref_trait",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ash"
|
||||
version = "0.33.3+1.2.191"
|
||||
@ -124,6 +145,12 @@ version = "3.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c"
|
||||
|
||||
[[package]]
|
||||
name = "bytemuck"
|
||||
version = "1.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72957246c41db82b8ef88a5486143830adeb8227ef9837740bdec67724cf2c5b"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.3"
|
||||
@ -584,6 +611,30 @@ dependencies = [
|
||||
"termcolor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "euclid"
|
||||
version = "0.22.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da96828553a086d7b18dcebfc579bd9628b016f86590d7453c115e490fa74b80"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "float-cmp"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75224bec9bfe1a65e2d34132933f2de7fe79900c96a0174307554244ece8150e"
|
||||
|
||||
[[package]]
|
||||
name = "float_next_after"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fc612c5837986b7104a87a0df74a5460931f1c5274be12f8d0f40aa2f30d632"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
@ -605,6 +656,95 @@ version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
||||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.3.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8cd0210d8c325c245ff06fd95a3b13689a1a276ac8cfa8e8720cb840bfb84b9e"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-executor",
|
||||
"futures-io",
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
"futures-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fc8cd39e3dbf865f7340dce6a2d401d24fd37c6fe6c4f0ee0de8bfca2252d27"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-core"
|
||||
version = "0.3.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "629316e42fe7c2a0b9a65b47d159ceaa5453ab14e8f0a3c5eedbb8cd55b4a445"
|
||||
|
||||
[[package]]
|
||||
name = "futures-executor"
|
||||
version = "0.3.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b808bf53348a36cab739d7e04755909b9fcaaa69b7d7e588b37b6ec62704c97"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-task",
|
||||
"futures-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-io"
|
||||
version = "0.3.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e481354db6b5c353246ccf6a728b0c5511d752c08da7260546fc0933869daa11"
|
||||
|
||||
[[package]]
|
||||
name = "futures-macro"
|
||||
version = "0.3.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a89f17b21645bc4ed773c69af9c9a0effd4a3f1a3876eadd453469f8854e7fdd"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-sink"
|
||||
version = "0.3.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "996c6442437b62d21a32cd9906f9c41e7dc1e19a9579843fad948696769305af"
|
||||
|
||||
[[package]]
|
||||
name = "futures-task"
|
||||
version = "0.3.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dabf1872aaab32c886832f2276d2f5399887e2bd613698a02359e4ea83f8de12"
|
||||
|
||||
[[package]]
|
||||
name = "futures-util"
|
||||
version = "0.3.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41d22213122356472061ac0f1ab2cee28d2bac8491410fd68c2af53d1cedb83e"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
"futures-macro",
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
"memchr",
|
||||
"pin-project-lite",
|
||||
"pin-utils",
|
||||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fxhash"
|
||||
version = "0.2.1"
|
||||
@ -614,6 +754,68 @@ dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.12.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.13.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f797e67af32588215eaaab8327027ee8e71b9dd0b2b26996aedf20c030fce309"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "geo"
|
||||
version = "0.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02bf7fb342abefefb0abbb8d033f37233e6f857a1a970805d15f96560834d699"
|
||||
dependencies = [
|
||||
"geo-types",
|
||||
"geographiclib-rs",
|
||||
"log",
|
||||
"num-traits",
|
||||
"robust",
|
||||
"rstar",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "geo-types"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8bd2e95dd9f5c8ff74159ed9205ad7fd239a9569173a550863976421b45d2bb"
|
||||
dependencies = [
|
||||
"approx",
|
||||
"num-traits",
|
||||
"rstar",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "geographiclib-rs"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b78e20d5d868fa2c4182a8170cb4df261e781a605810e3c1500269c1907da461"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.3"
|
||||
@ -682,6 +884,15 @@ version = "1.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7"
|
||||
|
||||
[[package]]
|
||||
name = "hash32"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4041af86e63ac4298ce40e5cca669066e75b6f1aa3390fe2561ffa5e1d9f4cc"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.11.2"
|
||||
@ -691,6 +902,18 @@ dependencies = [
|
||||
"ahash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heapless"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "634bd4d29cbf24424d0a4bfcbf80c6960129dc24424752a7d1d1390607023422"
|
||||
dependencies = [
|
||||
"as-slice",
|
||||
"generic-array 0.14.4",
|
||||
"hash32",
|
||||
"stable_deref_trait",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.19"
|
||||
@ -852,6 +1075,77 @@ dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lyon"
|
||||
version = "0.17.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf0510ed5e3e2fb80f3db2061ef5ca92d87bfda1a624bb1eacf3bd50226e4cbb"
|
||||
dependencies = [
|
||||
"lyon_algorithms",
|
||||
"lyon_extra",
|
||||
"lyon_tessellation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lyon_algorithms"
|
||||
version = "0.17.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8037f716541ba0d84d3de05c0069f8068baf73990d55980558b84d944c8a244a"
|
||||
dependencies = [
|
||||
"lyon_path",
|
||||
"sid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lyon_extra"
|
||||
version = "0.17.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a0729bc681ea3d88df18cbe65cf6495790424c78d361bf8c517898a11081c882"
|
||||
dependencies = [
|
||||
"lyon_path",
|
||||
"lyon_svg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lyon_geom"
|
||||
version = "0.17.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce99ce77c22bfd8f39a95b9c749dffbfc3e2491ea30c874764c801a8b1485489"
|
||||
dependencies = [
|
||||
"arrayvec 0.5.2",
|
||||
"euclid",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lyon_path"
|
||||
version = "0.17.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b0a59fdf767ca0d887aa61d1b48d4bbf6a124c1a45503593f7d38ab945bfbc0"
|
||||
dependencies = [
|
||||
"lyon_geom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lyon_svg"
|
||||
version = "0.17.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d48d6de2455c678fc9f41c14d05555b0585ee4a12aca0447ce73fbe1334363a"
|
||||
dependencies = [
|
||||
"lyon_path",
|
||||
"svgtypes",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lyon_tessellation"
|
||||
version = "0.17.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7230e08dd0638048e46f387f255dbe7a7344a3e6705beab53242b5af25635760"
|
||||
dependencies = [
|
||||
"float_next_after",
|
||||
"lyon_path",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "malloc_buf"
|
||||
version = "0.0.6"
|
||||
@ -865,11 +1159,16 @@ dependencies = [
|
||||
name = "mapr"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"criterion",
|
||||
"env_logger 0.8.4",
|
||||
"env_logger 0.9.0",
|
||||
"futures",
|
||||
"geo",
|
||||
"geo-types",
|
||||
"hexdump",
|
||||
"log",
|
||||
"lyon",
|
||||
"mvt",
|
||||
"pollster",
|
||||
"serde",
|
||||
@ -1182,12 +1481,30 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pdqselect"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ec91767ecc0a0bbe558ce8c9da33c068066c57ecc8bb8477ef8c1ad3ef77c27"
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443"
|
||||
|
||||
[[package]]
|
||||
name = "pin-utils"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.22"
|
||||
@ -1403,6 +1720,24 @@ version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1382d1f0a252c4bf97dc20d979a2fdd05b024acd7c2ed0f7595d7817666a157"
|
||||
|
||||
[[package]]
|
||||
name = "robust"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5864e7ef1a6b7bcf1d6ca3f655e65e724ed3b52546a0d0a663c991522f552ea"
|
||||
|
||||
[[package]]
|
||||
name = "rstar"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a45c0e8804d37e4d97e55c6f258bc9ad9c5ee7b07437009dd152d764949a27c"
|
||||
dependencies = [
|
||||
"heapless",
|
||||
"num-traits",
|
||||
"pdqselect",
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.4.0"
|
||||
@ -1496,6 +1831,27 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sid"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd5ac56c121948b4879bba9e519852c211bcdd8f014efff766441deff0b91bdb"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac"
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5"
|
||||
|
||||
[[package]]
|
||||
name = "slotmap"
|
||||
version = "1.0.6"
|
||||
@ -1540,12 +1896,28 @@ dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stable_deref_trait"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c"
|
||||
|
||||
[[package]]
|
||||
name = "svgtypes"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c536faaff1a10837cfe373142583f6e27d81e96beba339147e77b67c9f260ff"
|
||||
dependencies = [
|
||||
"float-cmp",
|
||||
"siphasher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.82"
|
||||
@ -1631,6 +2003,12 @@ version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3e5d7cd7ab3e47dda6e56542f4bbf3824c15234958c6e1bd6aaa347e93499fdc"
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.9"
|
||||
|
||||
14
Cargo.toml
14
Cargo.toml
@ -9,14 +9,21 @@ resolver = "2"
|
||||
|
||||
[dependencies]
|
||||
|
||||
# Wanted by lyon experiment
|
||||
futures = "0.3.5"
|
||||
bytemuck = "1.2.0"
|
||||
|
||||
# Vector riles
|
||||
mvt = { path = "libs/mvt" }
|
||||
vector-tile = { path = "libs/vector_tile" }
|
||||
geo = "0.18.0"
|
||||
geo-types = "0.7"
|
||||
|
||||
# Rendering
|
||||
winit = "0.25"
|
||||
wgpu = "0.11"
|
||||
pollster = "0.2"
|
||||
lyon = { version = "0.17", features = ["extra"] }
|
||||
# https://docs.rs/euclid/0.22.6/euclid/index.html
|
||||
|
||||
# Logging
|
||||
@ -39,4 +46,9 @@ env_logger = "0.8" # Used for test-env-log
|
||||
|
||||
[[bin]]
|
||||
name = "mapr"
|
||||
path = "src/main.rs"
|
||||
path = "src/main.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "lyon_test"
|
||||
path = "src/lyon_test/main.rs"
|
||||
|
||||
489
src/lyon_test/main.rs
Normal file
489
src/lyon_test/main.rs
Normal file
@ -0,0 +1,489 @@
|
||||
use std::ops::Rem;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use futures::executor::block_on;
|
||||
use lyon::extra::rust_logo::build_logo_path;
|
||||
use lyon::math::*;
|
||||
use lyon::path::Path;
|
||||
use lyon::tessellation;
|
||||
use lyon::tessellation::geometry_builder::*;
|
||||
use lyon::tessellation::{FillOptions, FillTessellator};
|
||||
use lyon::tessellation::{StrokeOptions, StrokeTessellator};
|
||||
use wgpu::util::DeviceExt;
|
||||
use winit::event_loop::EventLoop;
|
||||
use winit::window::Window;
|
||||
|
||||
use crate::piplines::create_map_render_pipeline_description;
|
||||
use crate::scene::SceneParams;
|
||||
use crate::shader::{
|
||||
create_fragment_module_descriptor, create_map_fragment_state, create_map_vertex_state,
|
||||
create_vertex_module_descriptor,
|
||||
};
|
||||
use crate::shader_ffi::*;
|
||||
|
||||
mod piplines;
|
||||
mod scene;
|
||||
mod shader;
|
||||
mod shader_ffi;
|
||||
|
||||
const PRIM_BUFFER_LEN: usize = 256;
|
||||
|
||||
const DEFAULT_WINDOW_WIDTH: f32 = 800.0;
|
||||
const DEFAULT_WINDOW_HEIGHT: f32 = 800.0;
|
||||
|
||||
/// Creates a texture that uses MSAA and fits a given swap chain
|
||||
fn create_multisampled_framebuffer(
|
||||
device: &wgpu::Device,
|
||||
desc: &wgpu::SurfaceConfiguration,
|
||||
sample_count: u32,
|
||||
) -> wgpu::TextureView {
|
||||
let multisampled_frame_descriptor = &wgpu::TextureDescriptor {
|
||||
label: Some("Multisampled frame descriptor"),
|
||||
size: wgpu::Extent3d {
|
||||
width: desc.width,
|
||||
height: desc.height,
|
||||
depth_or_array_layers: 1,
|
||||
},
|
||||
mip_level_count: 1,
|
||||
sample_count,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: desc.format,
|
||||
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
|
||||
};
|
||||
|
||||
device
|
||||
.create_texture(multisampled_frame_descriptor)
|
||||
.create_view(&wgpu::TextureViewDescriptor::default())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
env_logger::init();
|
||||
println!("== wgpu example ==");
|
||||
println!("Controls:");
|
||||
println!(" Arrow keys: scrolling");
|
||||
println!(" PgUp/PgDown: zoom in/out");
|
||||
println!(" a/z: increase/decrease the stroke width");
|
||||
|
||||
// Number of samples for anti-aliasing
|
||||
// Set to 1 to disable
|
||||
let sample_count = 4;
|
||||
|
||||
let num_instances: u32 = 1;
|
||||
let tolerance = 0.02;
|
||||
|
||||
let stroke_prim_id = 0;
|
||||
let fill_prim_id = 1;
|
||||
let arrows_prim_id = num_instances + 1;
|
||||
|
||||
let mut geometry: VertexBuffers<GpuVertex, u16> = VertexBuffers::new();
|
||||
|
||||
let mut fill_tess = FillTessellator::new();
|
||||
let mut stroke_tess = StrokeTessellator::new();
|
||||
|
||||
// Build a Path for the rust logo.
|
||||
let mut builder = Path::builder().with_svg();
|
||||
build_logo_path(&mut builder);
|
||||
let path = builder.build();
|
||||
|
||||
// Build a Path for the arrow.
|
||||
let mut builder = Path::builder();
|
||||
builder.begin(point(-1.0, -0.3));
|
||||
builder.line_to(point(0.0, -0.3));
|
||||
builder.line_to(point(0.0, -1.0));
|
||||
builder.line_to(point(1.5, 0.0));
|
||||
builder.line_to(point(0.0, 1.0));
|
||||
builder.line_to(point(0.0, 0.3));
|
||||
builder.line_to(point(-1.0, 0.3));
|
||||
builder.close();
|
||||
let arrow_path = builder.build();
|
||||
|
||||
fill_tess
|
||||
.tessellate_path(
|
||||
&path,
|
||||
&FillOptions::tolerance(tolerance).with_fill_rule(tessellation::FillRule::NonZero),
|
||||
&mut BuffersBuilder::new(&mut geometry, WithId(fill_prim_id as u32)),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let fill_range = 0..(geometry.indices.len() as u32);
|
||||
|
||||
stroke_tess
|
||||
.tessellate_path(
|
||||
&path,
|
||||
&StrokeOptions::tolerance(tolerance),
|
||||
&mut BuffersBuilder::new(&mut geometry, WithId(stroke_prim_id as u32)),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let stroke_range = fill_range.end..(geometry.indices.len() as u32);
|
||||
|
||||
fill_tess
|
||||
.tessellate_path(
|
||||
&arrow_path,
|
||||
&FillOptions::tolerance(tolerance),
|
||||
&mut BuffersBuilder::new(&mut geometry, WithId(arrows_prim_id as u32)),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut cpu_primitives = Vec::with_capacity(PRIM_BUFFER_LEN);
|
||||
for _ in 0..PRIM_BUFFER_LEN {
|
||||
cpu_primitives.push(Primitive {
|
||||
color: [1.0, 0.0, 0.0, 1.0],
|
||||
z_index: 0,
|
||||
width: 0.0,
|
||||
translate: [0.0, 0.0],
|
||||
angle: 0.0,
|
||||
..Primitive::DEFAULT
|
||||
});
|
||||
}
|
||||
|
||||
// Stroke primitive
|
||||
cpu_primitives[stroke_prim_id] = Primitive {
|
||||
color: [0.0, 0.0, 0.0, 1.0],
|
||||
z_index: num_instances as i32 + 2,
|
||||
width: 1.0,
|
||||
..Primitive::DEFAULT
|
||||
};
|
||||
// Main fill primitive
|
||||
cpu_primitives[fill_prim_id] = Primitive {
|
||||
color: [1.0, 1.0, 1.0, 1.0],
|
||||
z_index: num_instances as i32 + 1,
|
||||
..Primitive::DEFAULT
|
||||
};
|
||||
// Instance primitives
|
||||
for (idx, cpu_prim) in cpu_primitives
|
||||
.iter_mut()
|
||||
.enumerate()
|
||||
.skip(fill_prim_id + 1)
|
||||
.take(num_instances as usize - 1)
|
||||
{
|
||||
cpu_prim.z_index = (idx as u32 + 1) as i32;
|
||||
cpu_prim.color = [
|
||||
(0.1 * idx as f32).rem(1.0),
|
||||
(0.5 * idx as f32).rem(1.0),
|
||||
(0.9 * idx as f32).rem(1.0),
|
||||
1.0,
|
||||
];
|
||||
}
|
||||
|
||||
let mut scene = SceneParams::DEFAULT;
|
||||
|
||||
let event_loop = EventLoop::new();
|
||||
let window = Window::new(&event_loop).unwrap();
|
||||
|
||||
// create an instance
|
||||
let instance = wgpu::Instance::new(wgpu::Backends::all());
|
||||
|
||||
// create an surface
|
||||
let surface = unsafe { instance.create_surface(&window) };
|
||||
|
||||
// create an adapter
|
||||
let adapter = block_on(instance.request_adapter(&wgpu::RequestAdapterOptions {
|
||||
power_preference: wgpu::PowerPreference::LowPower,
|
||||
compatible_surface: Some(&surface),
|
||||
force_fallback_adapter: false,
|
||||
}))
|
||||
.unwrap();
|
||||
// create a device and a queue
|
||||
let (device, queue) = block_on(adapter.request_device(
|
||||
&wgpu::DeviceDescriptor {
|
||||
label: None,
|
||||
features: wgpu::Features::default(),
|
||||
limits: wgpu::Limits::default(),
|
||||
},
|
||||
None,
|
||||
))
|
||||
.unwrap();
|
||||
|
||||
let vbo = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
label: None,
|
||||
contents: bytemuck::cast_slice(&geometry.vertices),
|
||||
usage: wgpu::BufferUsages::VERTEX,
|
||||
});
|
||||
|
||||
let ibo = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
label: None,
|
||||
contents: bytemuck::cast_slice(&geometry.indices),
|
||||
usage: wgpu::BufferUsages::INDEX,
|
||||
});
|
||||
|
||||
let prim_buffer_byte_size = (PRIM_BUFFER_LEN * std::mem::size_of::<Primitive>()) as u64;
|
||||
let globals_buffer_byte_size = std::mem::size_of::<Globals>() as u64;
|
||||
|
||||
let prims_ubo = device.create_buffer(&wgpu::BufferDescriptor {
|
||||
label: Some("Prims ubo"),
|
||||
size: prim_buffer_byte_size,
|
||||
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
|
||||
mapped_at_creation: false,
|
||||
});
|
||||
|
||||
let globals_ubo = device.create_buffer(&wgpu::BufferDescriptor {
|
||||
label: Some("Globals ubo"),
|
||||
size: globals_buffer_byte_size,
|
||||
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
|
||||
mapped_at_creation: false,
|
||||
});
|
||||
|
||||
let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
label: Some("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: wgpu::BufferSize::new(globals_buffer_byte_size),
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
visibility: wgpu::ShaderStages::VERTEX,
|
||||
ty: wgpu::BindingType::Buffer {
|
||||
ty: wgpu::BufferBindingType::Uniform,
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: wgpu::BufferSize::new(prim_buffer_byte_size),
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
],
|
||||
});
|
||||
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
label: Some("Bind group"),
|
||||
layout: &bind_group_layout,
|
||||
entries: &[
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 0,
|
||||
resource: wgpu::BindingResource::Buffer(globals_ubo.as_entire_buffer_binding()),
|
||||
},
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 1,
|
||||
resource: wgpu::BindingResource::Buffer(prims_ubo.as_entire_buffer_binding()),
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
bind_group_layouts: &[&bind_group_layout],
|
||||
push_constant_ranges: &[],
|
||||
label: None,
|
||||
});
|
||||
|
||||
let vertex_module = device.create_shader_module(&create_vertex_module_descriptor());
|
||||
let fragment_module = device.create_shader_module(&create_fragment_module_descriptor());
|
||||
let mut render_pipeline_descriptor = create_map_render_pipeline_description(
|
||||
&pipeline_layout,
|
||||
create_map_vertex_state(&vertex_module),
|
||||
create_map_fragment_state(&fragment_module),
|
||||
sample_count,
|
||||
);
|
||||
let render_pipeline = device.create_render_pipeline(&render_pipeline_descriptor);
|
||||
|
||||
// TODO: this isn't what we want: we'd need the equivalent of VK_POLYGON_MODE_LINE,
|
||||
// but it doesn't seem to be exposed by wgpu?
|
||||
render_pipeline_descriptor.primitive.topology = wgpu::PrimitiveTopology::LineList;
|
||||
|
||||
let size = window.inner_size();
|
||||
|
||||
let mut surface_desc = wgpu::SurfaceConfiguration {
|
||||
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
|
||||
format: wgpu::TextureFormat::Bgra8UnormSrgb,
|
||||
width: size.width,
|
||||
height: size.height,
|
||||
present_mode: wgpu::PresentMode::Mailbox,
|
||||
};
|
||||
|
||||
let mut multisampled_render_target = None;
|
||||
|
||||
surface.configure(&device, &surface_desc);
|
||||
|
||||
let mut depth_texture_view = None;
|
||||
|
||||
let start = Instant::now();
|
||||
let mut next_report = start + Duration::from_secs(1);
|
||||
let mut frame_count: u32 = 0;
|
||||
let mut time_secs: f32 = 0.0;
|
||||
|
||||
window.request_redraw();
|
||||
|
||||
event_loop.run(move |event, _, control_flow| {
|
||||
if !scene.update_inputs(event, &window, control_flow) {
|
||||
// keep polling inputs.
|
||||
return;
|
||||
}
|
||||
|
||||
if scene.size_changed {
|
||||
scene.size_changed = false;
|
||||
let physical = scene.window_size;
|
||||
surface_desc.width = physical.width;
|
||||
surface_desc.height = physical.height;
|
||||
surface.configure(&device, &surface_desc);
|
||||
|
||||
let depth_texture = device.create_texture(&wgpu::TextureDescriptor {
|
||||
label: Some("Depth texture"),
|
||||
size: wgpu::Extent3d {
|
||||
width: surface_desc.width,
|
||||
height: surface_desc.height,
|
||||
depth_or_array_layers: 1,
|
||||
},
|
||||
mip_level_count: 1,
|
||||
sample_count,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: wgpu::TextureFormat::Depth32Float,
|
||||
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
|
||||
});
|
||||
|
||||
depth_texture_view =
|
||||
Some(depth_texture.create_view(&wgpu::TextureViewDescriptor::default()));
|
||||
|
||||
multisampled_render_target = if sample_count > 1 {
|
||||
Some(create_multisampled_framebuffer(
|
||||
&device,
|
||||
&surface_desc,
|
||||
sample_count,
|
||||
))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
}
|
||||
|
||||
// TODO: Without this we are not able to close the window
|
||||
if !scene.render {
|
||||
return;
|
||||
}
|
||||
|
||||
scene.render = false;
|
||||
|
||||
let frame = match surface.get_current_texture() {
|
||||
Ok(texture) => texture,
|
||||
Err(e) => {
|
||||
println!("Swap-chain error: {:?}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let frame_view = frame
|
||||
.texture
|
||||
.create_view(&wgpu::TextureViewDescriptor::default());
|
||||
|
||||
let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor {
|
||||
label: Some("Encoder"),
|
||||
});
|
||||
|
||||
cpu_primitives[stroke_prim_id as usize].width = scene.stroke_width;
|
||||
cpu_primitives[stroke_prim_id as usize].color = [
|
||||
(time_secs * 0.8 - 1.6).sin() * 0.1 + 0.1,
|
||||
(time_secs * 0.5 - 1.6).sin() * 0.1 + 0.1,
|
||||
(time_secs - 1.6).sin() * 0.1 + 0.1,
|
||||
1.0,
|
||||
];
|
||||
|
||||
for idx in 2..(num_instances + 1) {
|
||||
cpu_primitives[idx as usize].translate = [
|
||||
(time_secs * 0.05 * idx as f32).sin() * (100.0 + idx as f32 * 10.0),
|
||||
(time_secs * 0.1 * idx as f32).sin() * (100.0 + idx as f32 * 10.0),
|
||||
];
|
||||
}
|
||||
|
||||
queue.write_buffer(
|
||||
&globals_ubo,
|
||||
0,
|
||||
bytemuck::cast_slice(&[Globals {
|
||||
resolution: [
|
||||
scene.window_size.width as f32,
|
||||
scene.window_size.height as f32,
|
||||
],
|
||||
zoom: scene.zoom,
|
||||
scroll_offset: scene.scroll.to_array(),
|
||||
_pad: 0.0,
|
||||
}]),
|
||||
);
|
||||
|
||||
queue.write_buffer(&prims_ubo, 0, bytemuck::cast_slice(&cpu_primitives));
|
||||
|
||||
{
|
||||
// A resolve target is only supported if the attachment actually uses anti-aliasing
|
||||
// So if sample_count == 1 then we must render directly to the surface's buffer
|
||||
let color_attachment = if let Some(msaa_target) = &multisampled_render_target {
|
||||
wgpu::RenderPassColorAttachment {
|
||||
view: msaa_target,
|
||||
ops: wgpu::Operations {
|
||||
load: wgpu::LoadOp::Clear(wgpu::Color::WHITE),
|
||||
store: true,
|
||||
},
|
||||
resolve_target: Some(&frame_view),
|
||||
}
|
||||
} else {
|
||||
wgpu::RenderPassColorAttachment {
|
||||
view: &frame_view,
|
||||
ops: wgpu::Operations {
|
||||
load: wgpu::LoadOp::Clear(wgpu::Color::WHITE),
|
||||
store: true,
|
||||
},
|
||||
resolve_target: None,
|
||||
}
|
||||
};
|
||||
|
||||
let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||
label: None,
|
||||
color_attachments: &[color_attachment],
|
||||
depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
|
||||
view: depth_texture_view.as_ref().unwrap(),
|
||||
depth_ops: Some(wgpu::Operations {
|
||||
load: wgpu::LoadOp::Clear(0.0),
|
||||
store: true,
|
||||
}),
|
||||
stencil_ops: Some(wgpu::Operations {
|
||||
load: wgpu::LoadOp::Clear(0),
|
||||
store: true,
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
pass.set_pipeline(&render_pipeline);
|
||||
pass.set_bind_group(0, &bind_group, &[]);
|
||||
pass.set_index_buffer(ibo.slice(..), wgpu::IndexFormat::Uint16);
|
||||
pass.set_vertex_buffer(0, vbo.slice(..));
|
||||
|
||||
pass.draw_indexed(fill_range.clone(), 0, 0..(num_instances as u32));
|
||||
pass.draw_indexed(stroke_range.clone(), 0, 0..1);
|
||||
}
|
||||
|
||||
queue.submit(Some(encoder.finish()));
|
||||
frame.present();
|
||||
|
||||
frame_count += 1;
|
||||
let now = Instant::now();
|
||||
time_secs = (now - start).as_secs_f32();
|
||||
if now >= next_report {
|
||||
println!("{} FPS", frame_count);
|
||||
frame_count = 0;
|
||||
next_report = now + Duration::from_secs(1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// This vertex constructor forwards the positions and normals provided by the
|
||||
/// tessellators and add a shape id.
|
||||
pub struct WithId(pub u32);
|
||||
|
||||
impl FillVertexConstructor<GpuVertex> for WithId {
|
||||
fn new_vertex(&mut self, vertex: tessellation::FillVertex) -> GpuVertex {
|
||||
GpuVertex {
|
||||
position: vertex.position().to_array(),
|
||||
normal: [0.0, 0.0],
|
||||
prim_id: self.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl StrokeVertexConstructor<GpuVertex> for WithId {
|
||||
fn new_vertex(&mut self, vertex: tessellation::StrokeVertex) -> GpuVertex {
|
||||
GpuVertex {
|
||||
position: vertex.position_on_path().to_array(),
|
||||
normal: vertex.normal().to_array(),
|
||||
prim_id: self.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
44
src/lyon_test/piplines.rs
Normal file
44
src/lyon_test/piplines.rs
Normal file
@ -0,0 +1,44 @@
|
||||
use wgpu::{FragmentState, PipelineLayout, RenderPipelineDescriptor, VertexState};
|
||||
|
||||
pub fn create_map_render_pipeline_description<'a>(
|
||||
pipeline_layout: &'a PipelineLayout,
|
||||
vertex_state: VertexState<'a>,
|
||||
fragment_state: FragmentState<'a>,
|
||||
sample_count: u32,
|
||||
) -> RenderPipelineDescriptor<'a> {
|
||||
let depth_stencil_state = wgpu::DepthStencilState {
|
||||
format: wgpu::TextureFormat::Depth32Float,
|
||||
depth_write_enabled: true,
|
||||
depth_compare: wgpu::CompareFunction::Greater,
|
||||
stencil: wgpu::StencilState {
|
||||
front: wgpu::StencilFaceState::IGNORE,
|
||||
back: wgpu::StencilFaceState::IGNORE,
|
||||
read_mask: 0,
|
||||
write_mask: 0,
|
||||
},
|
||||
bias: wgpu::DepthBiasState::default(),
|
||||
};
|
||||
|
||||
let descriptor = wgpu::RenderPipelineDescriptor {
|
||||
label: None,
|
||||
layout: Some(&pipeline_layout),
|
||||
vertex: vertex_state,
|
||||
fragment: Some(fragment_state),
|
||||
primitive: wgpu::PrimitiveState {
|
||||
topology: wgpu::PrimitiveTopology::TriangleList,
|
||||
polygon_mode: wgpu::PolygonMode::Fill,
|
||||
front_face: wgpu::FrontFace::Ccw,
|
||||
strip_index_format: None,
|
||||
cull_mode: Some(wgpu::Face::Back),
|
||||
clamp_depth: false,
|
||||
conservative: false,
|
||||
},
|
||||
depth_stencil: Some(depth_stencil_state),
|
||||
multisample: wgpu::MultisampleState {
|
||||
count: sample_count,
|
||||
mask: !0,
|
||||
alpha_to_coverage_enabled: false,
|
||||
},
|
||||
};
|
||||
descriptor
|
||||
}
|
||||
128
src/lyon_test/scene.rs
Normal file
128
src/lyon_test/scene.rs
Normal file
@ -0,0 +1,128 @@
|
||||
use lyon::math::Vector;
|
||||
use winit::dpi::PhysicalSize;
|
||||
use winit::event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent};
|
||||
use winit::event_loop::ControlFlow;
|
||||
use winit::window::Window;
|
||||
|
||||
use crate::{DEFAULT_WINDOW_HEIGHT, DEFAULT_WINDOW_WIDTH};
|
||||
|
||||
pub struct SceneParams {
|
||||
pub target_zoom: f32,
|
||||
pub zoom: f32,
|
||||
pub target_scroll: Vector,
|
||||
pub scroll: Vector,
|
||||
pub show_points: bool,
|
||||
pub stroke_width: f32,
|
||||
pub target_stroke_width: f32,
|
||||
pub window_size: PhysicalSize<u32>,
|
||||
pub size_changed: bool,
|
||||
pub render: bool,
|
||||
}
|
||||
|
||||
impl SceneParams {
|
||||
pub const DEFAULT: SceneParams = SceneParams {
|
||||
target_zoom: 5.0,
|
||||
zoom: 5.0,
|
||||
target_scroll: Vector::new(70.0, 70.0),
|
||||
scroll: Vector::new(70.0, 70.0),
|
||||
show_points: false,
|
||||
stroke_width: 1.0,
|
||||
target_stroke_width: 1.0,
|
||||
window_size: PhysicalSize::new(DEFAULT_WINDOW_WIDTH as u32, DEFAULT_WINDOW_HEIGHT as u32),
|
||||
size_changed: true,
|
||||
render: false,
|
||||
};
|
||||
|
||||
pub fn update_inputs(
|
||||
self: &mut SceneParams,
|
||||
event: Event<()>,
|
||||
window: &Window,
|
||||
control_flow: &mut ControlFlow,
|
||||
) -> bool {
|
||||
match event {
|
||||
Event::RedrawRequested(_) => {
|
||||
self.render = true;
|
||||
}
|
||||
Event::RedrawEventsCleared => {
|
||||
window.request_redraw();
|
||||
}
|
||||
Event::WindowEvent {
|
||||
event: WindowEvent::Destroyed,
|
||||
..
|
||||
}
|
||||
| Event::WindowEvent {
|
||||
event: WindowEvent::CloseRequested,
|
||||
..
|
||||
} => {
|
||||
*control_flow = ControlFlow::Exit;
|
||||
return false;
|
||||
}
|
||||
Event::WindowEvent {
|
||||
event: WindowEvent::Resized(size),
|
||||
..
|
||||
} => {
|
||||
self.window_size = size;
|
||||
self.size_changed = true
|
||||
}
|
||||
Event::WindowEvent {
|
||||
event:
|
||||
WindowEvent::KeyboardInput {
|
||||
input:
|
||||
KeyboardInput {
|
||||
state: ElementState::Pressed,
|
||||
virtual_keycode: Some(key),
|
||||
..
|
||||
},
|
||||
..
|
||||
},
|
||||
..
|
||||
} => match key {
|
||||
VirtualKeyCode::Escape => {
|
||||
*control_flow = ControlFlow::Exit;
|
||||
return false;
|
||||
}
|
||||
VirtualKeyCode::PageDown => {
|
||||
self.target_zoom *= 0.8;
|
||||
}
|
||||
VirtualKeyCode::PageUp => {
|
||||
self.target_zoom *= 1.25;
|
||||
}
|
||||
VirtualKeyCode::Left => {
|
||||
self.target_scroll.x -= 50.0 / self.target_zoom;
|
||||
}
|
||||
VirtualKeyCode::Right => {
|
||||
self.target_scroll.x += 50.0 / self.target_zoom;
|
||||
}
|
||||
VirtualKeyCode::Up => {
|
||||
self.target_scroll.y -= 50.0 / self.target_zoom;
|
||||
}
|
||||
VirtualKeyCode::Down => {
|
||||
self.target_scroll.y += 50.0 / self.target_zoom;
|
||||
}
|
||||
VirtualKeyCode::P => {
|
||||
self.show_points = !self.show_points;
|
||||
}
|
||||
VirtualKeyCode::A => {
|
||||
self.target_stroke_width /= 0.8;
|
||||
}
|
||||
VirtualKeyCode::Z => {
|
||||
self.target_stroke_width *= 0.8;
|
||||
}
|
||||
_key => {}
|
||||
},
|
||||
_evt => {
|
||||
//println!("{:?}", _evt);
|
||||
}
|
||||
}
|
||||
//println!(" -- zoom: {}, scroll: {:?}", self.target_zoom, self.target_scroll);
|
||||
|
||||
self.zoom += (self.target_zoom - self.zoom) / 3.0;
|
||||
self.scroll = self.scroll + (self.target_scroll - self.scroll) / 3.0;
|
||||
self.stroke_width =
|
||||
self.stroke_width + (self.target_stroke_width - self.stroke_width) / 5.0;
|
||||
|
||||
*control_flow = ControlFlow::Poll;
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
63
src/lyon_test/shader.rs
Normal file
63
src/lyon_test/shader.rs
Normal file
@ -0,0 +1,63 @@
|
||||
use wgpu::{ColorTargetState, FragmentState, ShaderModule, ShaderModuleDescriptor, VertexAttribute, VertexBufferLayout, VertexState};
|
||||
|
||||
use crate::GpuVertex;
|
||||
|
||||
const MAP_VERTEX_SHADER_ARGUMENTS: [VertexAttribute; 3] = [
|
||||
wgpu::VertexAttribute {
|
||||
offset: 0,
|
||||
format: wgpu::VertexFormat::Float32x2,
|
||||
shader_location: 0,
|
||||
},
|
||||
wgpu::VertexAttribute {
|
||||
offset: wgpu::VertexFormat::Float32x2.size(),
|
||||
format: wgpu::VertexFormat::Float32x2,
|
||||
shader_location: 1,
|
||||
},
|
||||
wgpu::VertexAttribute {
|
||||
offset: 2 * wgpu::VertexFormat::Float32x2.size(),
|
||||
format: wgpu::VertexFormat::Uint32,
|
||||
shader_location: 2,
|
||||
},
|
||||
];
|
||||
|
||||
const MAP_VERTEX_SHADER_BUFFERS: [VertexBufferLayout; 1] = [wgpu::VertexBufferLayout {
|
||||
array_stride: std::mem::size_of::<GpuVertex>() as u64,
|
||||
step_mode: wgpu::VertexStepMode::Vertex,
|
||||
attributes: &MAP_VERTEX_SHADER_ARGUMENTS,
|
||||
}];
|
||||
|
||||
const MAP_VERTEX_COLOR_TARGETS: [ColorTargetState; 1] = [wgpu::ColorTargetState {
|
||||
format: wgpu::TextureFormat::Bgra8UnormSrgb,
|
||||
blend: None,
|
||||
write_mask: wgpu::ColorWrites::ALL,
|
||||
}];
|
||||
|
||||
pub fn create_vertex_module_descriptor<'a>() -> ShaderModuleDescriptor<'a> {
|
||||
wgpu::ShaderModuleDescriptor {
|
||||
label: Some("Geometry vs"),
|
||||
source: wgpu::ShaderSource::Wgsl(include_str!("shaders/vertex.wgsl").into()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_fragment_module_descriptor<'a>() -> ShaderModuleDescriptor<'a> {
|
||||
wgpu::ShaderModuleDescriptor {
|
||||
label: Some("Geometry fs"),
|
||||
source: wgpu::ShaderSource::Wgsl(include_str!("shaders/fragment.wgsl").into()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_map_vertex_state(vertex_shader_module: &ShaderModule) -> VertexState {
|
||||
wgpu::VertexState {
|
||||
module: vertex_shader_module,
|
||||
entry_point: "main",
|
||||
buffers: &MAP_VERTEX_SHADER_BUFFERS,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_map_fragment_state(fragment_shader_module: &ShaderModule) -> FragmentState {
|
||||
wgpu::FragmentState {
|
||||
module: fragment_shader_module,
|
||||
entry_point: "main",
|
||||
targets: &MAP_VERTEX_COLOR_TARGETS,
|
||||
}
|
||||
}
|
||||
58
src/lyon_test/shader_ffi.rs
Normal file
58
src/lyon_test/shader_ffi.rs
Normal file
@ -0,0 +1,58 @@
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Globals {
|
||||
pub resolution: [f32; 2],
|
||||
pub scroll_offset: [f32; 2],
|
||||
pub zoom: f32,
|
||||
pub _pad: f32,
|
||||
}
|
||||
|
||||
unsafe impl bytemuck::Pod for Globals {}
|
||||
unsafe impl bytemuck::Zeroable for Globals {}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct GpuVertex {
|
||||
pub position: [f32; 2],
|
||||
pub normal: [f32; 2],
|
||||
pub prim_id: u32,
|
||||
}
|
||||
unsafe impl bytemuck::Pod for GpuVertex {}
|
||||
unsafe impl bytemuck::Zeroable for GpuVertex {}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Primitive {
|
||||
pub color: [f32; 4],
|
||||
pub translate: [f32; 2],
|
||||
pub z_index: i32,
|
||||
pub width: f32,
|
||||
pub angle: f32,
|
||||
pub scale: f32,
|
||||
pub _pad1: i32,
|
||||
pub _pad2: i32,
|
||||
}
|
||||
|
||||
impl Primitive {
|
||||
pub const DEFAULT: Self = Primitive {
|
||||
color: [0.0; 4],
|
||||
translate: [0.0; 2],
|
||||
z_index: 0,
|
||||
width: 0.0,
|
||||
angle: 0.0,
|
||||
scale: 1.0,
|
||||
_pad1: 0,
|
||||
_pad2: 0,
|
||||
};
|
||||
}
|
||||
|
||||
unsafe impl bytemuck::Pod for Primitive {}
|
||||
unsafe impl bytemuck::Zeroable for Primitive {}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct BgPoint {
|
||||
pub point: [f32; 2],
|
||||
}
|
||||
unsafe impl bytemuck::Pod for BgPoint {}
|
||||
unsafe impl bytemuck::Zeroable for BgPoint {}
|
||||
8
src/lyon_test/shaders/fragment.wgsl
Normal file
8
src/lyon_test/shaders/fragment.wgsl
Normal file
@ -0,0 +1,8 @@
|
||||
struct Output {
|
||||
[[location(0)]] out_color: vec4<f32>;
|
||||
};
|
||||
|
||||
[[stage(fragment)]]
|
||||
fn main([[location(0)]] v_color: vec4<f32>) -> Output {
|
||||
return Output(v_color);
|
||||
}
|
||||
56
src/lyon_test/shaders/vertex.wgsl
Normal file
56
src/lyon_test/shaders/vertex.wgsl
Normal file
@ -0,0 +1,56 @@
|
||||
[[block]]
|
||||
struct Globals {
|
||||
resolution: vec2<f32>;
|
||||
scroll_offset: vec2<f32>;
|
||||
zoom: f32;
|
||||
};
|
||||
|
||||
struct Primitive {
|
||||
color: vec4<f32>;
|
||||
translate: vec2<f32>;
|
||||
z_index: i32;
|
||||
width: f32;
|
||||
angle: f32;
|
||||
scale: f32;
|
||||
pad1: i32;
|
||||
pad2: i32;
|
||||
};
|
||||
|
||||
[[block]]
|
||||
struct Primitives {
|
||||
primitives: [[stride(48)]] array<Primitive, 256>;
|
||||
};
|
||||
|
||||
[[group(0), binding(0)]] var<uniform> globals: Globals;
|
||||
[[group(0), binding(1)]] var<uniform> u_primitives: Primitives;
|
||||
|
||||
struct VertexOutput {
|
||||
[[location(0)]] v_color: vec4<f32>;
|
||||
[[builtin(position)]] position: vec4<f32>;
|
||||
};
|
||||
|
||||
[[stage(vertex)]]
|
||||
fn main(
|
||||
[[location(0)]] a_position: vec2<f32>,
|
||||
[[location(1)]] a_normal: vec2<f32>,
|
||||
[[location(2)]] a_prim_id: u32,
|
||||
[[builtin(instance_index)]] instance_idx: u32
|
||||
) -> VertexOutput {
|
||||
var prim: Primitive = u_primitives.primitives[a_prim_id + instance_idx];
|
||||
|
||||
var invert_y = vec2<f32>(1.0, -1.0);
|
||||
|
||||
var rotation = mat2x2<f32>(
|
||||
vec2<f32>(cos(prim.angle), -sin(prim.angle)),
|
||||
vec2<f32>(sin(prim.angle), cos(prim.angle))
|
||||
);
|
||||
|
||||
var local_pos = (a_position * prim.scale + a_normal * prim.width) * rotation;
|
||||
var world_pos = local_pos - globals.scroll_offset + prim.translate;
|
||||
var transformed_pos = world_pos * globals.zoom / (0.5 * globals.resolution) * invert_y;
|
||||
|
||||
var z = f32(prim.z_index) / 4096.0;
|
||||
var position = vec4<f32>(transformed_pos.x, transformed_pos.y, z, 1.0);
|
||||
|
||||
return VertexOutput(prim.color, position);
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user