WebGPU Voxel Game

Tutorial 5: Textures and bind groups

j0.lol 458b6ad1 d7c92bf3

+297 -23
Cargo.lock
··· 19 19 checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046" 20 20 21 21 [[package]] 22 + name = "addr2line" 23 + version = "0.24.2" 24 + source = "registry+https://github.com/rust-lang/crates.io-index" 25 + checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" 26 + dependencies = [ 27 + "gimli", 28 + ] 29 + 30 + [[package]] 31 + name = "adler2" 32 + version = "2.0.0" 33 + source = "registry+https://github.com/rust-lang/crates.io-index" 34 + checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" 35 + 36 + [[package]] 22 37 name = "ahash" 23 38 version = "0.8.11" 24 39 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 64 79 "ndk-context", 65 80 "ndk-sys", 66 81 "num_enum", 67 - "thiserror", 82 + "thiserror 1.0.64", 68 83 ] 69 84 70 85 [[package]] ··· 122 137 checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" 123 138 124 139 [[package]] 140 + name = "backtrace" 141 + version = "0.3.74" 142 + source = "registry+https://github.com/rust-lang/crates.io-index" 143 + checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" 144 + dependencies = [ 145 + "addr2line", 146 + "cfg-if", 147 + "libc", 148 + "miniz_oxide", 149 + "object", 150 + "rustc-demangle", 151 + "windows-targets 0.52.6", 152 + ] 153 + 154 + [[package]] 155 + name = "backtrace-ext" 156 + version = "0.2.1" 157 + source = "registry+https://github.com/rust-lang/crates.io-index" 158 + checksum = "537beee3be4a18fb023b570f80e3ae28003db9167a751266b259926e25539d50" 159 + dependencies = [ 160 + "backtrace", 161 + ] 162 + 163 + [[package]] 125 164 name = "bit-set" 126 165 version = "0.6.0" 127 166 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 157 196 "console_error_panic_hook", 158 197 "console_log", 159 198 "env_logger", 199 + "image", 160 200 "log", 201 + "miette", 161 202 "pollster", 203 + "thiserror 2.0.11", 162 204 "wasm-bindgen", 163 205 "wasm-bindgen-futures", 164 206 "web-sys", ··· 214 256 dependencies = [ 215 257 "proc-macro2", 216 258 "quote", 217 - "syn 2.0.77", 259 + "syn 2.0.96", 218 260 ] 219 261 220 262 [[package]] 263 + name = "byteorder-lite" 264 + version = "0.1.0" 265 + source = "registry+https://github.com/rust-lang/crates.io-index" 266 + checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" 267 + 268 + [[package]] 221 269 name = "bytes" 222 270 version = "1.7.2" 223 271 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 234 282 "polling", 235 283 "rustix", 236 284 "slab", 237 - "thiserror", 285 + "thiserror 1.0.64", 238 286 ] 239 287 240 288 [[package]] ··· 399 447 ] 400 448 401 449 [[package]] 450 + name = "crc32fast" 451 + version = "1.4.2" 452 + source = "registry+https://github.com/rust-lang/crates.io-index" 453 + checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" 454 + dependencies = [ 455 + "cfg-if", 456 + ] 457 + 458 + [[package]] 402 459 name = "crossbeam-utils" 403 460 version = "0.8.20" 404 461 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 481 538 ] 482 539 483 540 [[package]] 541 + name = "fdeflate" 542 + version = "0.3.7" 543 + source = "registry+https://github.com/rust-lang/crates.io-index" 544 + checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" 545 + dependencies = [ 546 + "simd-adler32", 547 + ] 548 + 549 + [[package]] 550 + name = "flate2" 551 + version = "1.0.35" 552 + source = "registry+https://github.com/rust-lang/crates.io-index" 553 + checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" 554 + dependencies = [ 555 + "crc32fast", 556 + "miniz_oxide", 557 + ] 558 + 559 + [[package]] 484 560 name = "foreign-types" 485 561 version = "0.5.0" 486 562 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 498 574 dependencies = [ 499 575 "proc-macro2", 500 576 "quote", 501 - "syn 2.0.77", 577 + "syn 2.0.96", 502 578 ] 503 579 504 580 [[package]] ··· 527 603 "libc", 528 604 "wasi", 529 605 ] 606 + 607 + [[package]] 608 + name = "gimli" 609 + version = "0.31.1" 610 + source = "registry+https://github.com/rust-lang/crates.io-index" 611 + checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" 530 612 531 613 [[package]] 532 614 name = "gl_generator" ··· 587 669 dependencies = [ 588 670 "log", 589 671 "presser", 590 - "thiserror", 672 + "thiserror 1.0.64", 591 673 "winapi", 592 674 "windows", 593 675 ] ··· 632 714 "com", 633 715 "libc", 634 716 "libloading", 635 - "thiserror", 717 + "thiserror 1.0.64", 636 718 "widestring", 637 719 "winapi", 638 720 ] ··· 667 749 ] 668 750 669 751 [[package]] 752 + name = "image" 753 + version = "0.25.5" 754 + source = "registry+https://github.com/rust-lang/crates.io-index" 755 + checksum = "cd6f44aed642f18953a158afeb30206f4d50da59fbc66ecb53c66488de73563b" 756 + dependencies = [ 757 + "bytemuck", 758 + "byteorder-lite", 759 + "num-traits", 760 + "png", 761 + "zune-core", 762 + "zune-jpeg", 763 + ] 764 + 765 + [[package]] 670 766 name = "indexmap" 671 767 version = "2.5.0" 672 768 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 688 784 ] 689 785 690 786 [[package]] 787 + name = "is_ci" 788 + version = "1.2.0" 789 + source = "registry+https://github.com/rust-lang/crates.io-index" 790 + checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45" 791 + 792 + [[package]] 691 793 name = "jni" 692 794 version = "0.21.1" 693 795 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 698 800 "combine", 699 801 "jni-sys", 700 802 "log", 701 - "thiserror", 803 + "thiserror 1.0.64", 702 804 "walkdir", 703 805 "windows-sys 0.45.0", 704 806 ] ··· 839 941 ] 840 942 841 943 [[package]] 944 + name = "miette" 945 + version = "7.4.0" 946 + source = "registry+https://github.com/rust-lang/crates.io-index" 947 + checksum = "317f146e2eb7021892722af37cf1b971f0a70c8406f487e24952667616192c64" 948 + dependencies = [ 949 + "backtrace", 950 + "backtrace-ext", 951 + "cfg-if", 952 + "miette-derive", 953 + "owo-colors", 954 + "supports-color", 955 + "supports-hyperlinks", 956 + "supports-unicode", 957 + "terminal_size", 958 + "textwrap", 959 + "thiserror 1.0.64", 960 + "unicode-width", 961 + ] 962 + 963 + [[package]] 964 + name = "miette-derive" 965 + version = "7.4.0" 966 + source = "registry+https://github.com/rust-lang/crates.io-index" 967 + checksum = "23c9b935fbe1d6cbd1dac857b54a688145e2d93f48db36010514d0f612d0ad67" 968 + dependencies = [ 969 + "proc-macro2", 970 + "quote", 971 + "syn 2.0.96", 972 + ] 973 + 974 + [[package]] 975 + name = "miniz_oxide" 976 + version = "0.8.3" 977 + source = "registry+https://github.com/rust-lang/crates.io-index" 978 + checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924" 979 + dependencies = [ 980 + "adler2", 981 + "simd-adler32", 982 + ] 983 + 984 + [[package]] 842 985 name = "naga" 843 986 version = "22.1.0" 844 987 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 855 998 "rustc-hash", 856 999 "spirv", 857 1000 "termcolor", 858 - "thiserror", 1001 + "thiserror 1.0.64", 859 1002 "unicode-xid", 860 1003 ] 861 1004 ··· 872 1015 "num_enum", 873 1016 "raw-window-handle 0.5.2", 874 1017 "raw-window-handle 0.6.2", 875 - "thiserror", 1018 + "thiserror 1.0.64", 876 1019 ] 877 1020 878 1021 [[package]] ··· 888 1031 checksum = "8c196769dd60fd4f363e11d948139556a344e79d451aeb2fa2fd040738ef7691" 889 1032 dependencies = [ 890 1033 "jni-sys", 1034 + ] 1035 + 1036 + [[package]] 1037 + name = "num-traits" 1038 + version = "0.2.19" 1039 + source = "registry+https://github.com/rust-lang/crates.io-index" 1040 + checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" 1041 + dependencies = [ 1042 + "autocfg", 891 1043 ] 892 1044 893 1045 [[package]] ··· 908 1060 "proc-macro-crate", 909 1061 "proc-macro2", 910 1062 "quote", 911 - "syn 2.0.77", 1063 + "syn 2.0.96", 912 1064 ] 913 1065 914 1066 [[package]] ··· 943 1095 checksum = "d079845b37af429bfe5dfa76e6d087d788031045b25cfc6fd898486fd9847666" 944 1096 945 1097 [[package]] 1098 + name = "object" 1099 + version = "0.36.5" 1100 + source = "registry+https://github.com/rust-lang/crates.io-index" 1101 + checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" 1102 + dependencies = [ 1103 + "memchr", 1104 + ] 1105 + 1106 + [[package]] 946 1107 name = "once_cell" 947 1108 version = "1.19.0" 948 1109 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 965 1126 dependencies = [ 966 1127 "ttf-parser", 967 1128 ] 1129 + 1130 + [[package]] 1131 + name = "owo-colors" 1132 + version = "4.1.0" 1133 + source = "registry+https://github.com/rust-lang/crates.io-index" 1134 + checksum = "fb37767f6569cd834a413442455e0f066d0d522de8630436e2a1761d9726ba56" 968 1135 969 1136 [[package]] 970 1137 name = "parking_lot" ··· 1012 1179 version = "0.3.31" 1013 1180 source = "registry+https://github.com/rust-lang/crates.io-index" 1014 1181 checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" 1182 + 1183 + [[package]] 1184 + name = "png" 1185 + version = "0.17.16" 1186 + source = "registry+https://github.com/rust-lang/crates.io-index" 1187 + checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" 1188 + dependencies = [ 1189 + "bitflags 1.3.2", 1190 + "crc32fast", 1191 + "fdeflate", 1192 + "flate2", 1193 + "miniz_oxide", 1194 + ] 1015 1195 1016 1196 [[package]] 1017 1197 name = "polling" ··· 1051 1231 1052 1232 [[package]] 1053 1233 name = "proc-macro2" 1054 - version = "1.0.86" 1234 + version = "1.0.93" 1055 1235 source = "registry+https://github.com/rust-lang/crates.io-index" 1056 - checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" 1236 + checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" 1057 1237 dependencies = [ 1058 1238 "unicode-ident", 1059 1239 ] ··· 1161 1341 version = "1.1.0" 1162 1342 source = "registry+https://github.com/rust-lang/crates.io-index" 1163 1343 checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" 1344 + 1345 + [[package]] 1346 + name = "rustc-demangle" 1347 + version = "0.1.24" 1348 + source = "registry+https://github.com/rust-lang/crates.io-index" 1349 + checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" 1164 1350 1165 1351 [[package]] 1166 1352 name = "rustc-hash" ··· 1232 1418 dependencies = [ 1233 1419 "proc-macro2", 1234 1420 "quote", 1235 - "syn 2.0.77", 1421 + "syn 2.0.96", 1236 1422 ] 1237 1423 1238 1424 [[package]] ··· 1240 1426 version = "1.3.0" 1241 1427 source = "registry+https://github.com/rust-lang/crates.io-index" 1242 1428 checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 1429 + 1430 + [[package]] 1431 + name = "simd-adler32" 1432 + version = "0.3.7" 1433 + source = "registry+https://github.com/rust-lang/crates.io-index" 1434 + checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" 1243 1435 1244 1436 [[package]] 1245 1437 name = "slab" ··· 1279 1471 "log", 1280 1472 "memmap2", 1281 1473 "rustix", 1282 - "thiserror", 1474 + "thiserror 1.0.64", 1283 1475 "wayland-backend", 1284 1476 "wayland-client", 1285 1477 "wayland-csd-frame", ··· 1321 1513 checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" 1322 1514 1323 1515 [[package]] 1516 + name = "supports-color" 1517 + version = "3.0.1" 1518 + source = "registry+https://github.com/rust-lang/crates.io-index" 1519 + checksum = "8775305acf21c96926c900ad056abeef436701108518cf890020387236ac5a77" 1520 + dependencies = [ 1521 + "is_ci", 1522 + ] 1523 + 1524 + [[package]] 1525 + name = "supports-hyperlinks" 1526 + version = "3.0.0" 1527 + source = "registry+https://github.com/rust-lang/crates.io-index" 1528 + checksum = "2c0a1e5168041f5f3ff68ff7d95dcb9c8749df29f6e7e89ada40dd4c9de404ee" 1529 + 1530 + [[package]] 1531 + name = "supports-unicode" 1532 + version = "3.0.0" 1533 + source = "registry+https://github.com/rust-lang/crates.io-index" 1534 + checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2" 1535 + 1536 + [[package]] 1324 1537 name = "syn" 1325 1538 version = "1.0.109" 1326 1539 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1333 1546 1334 1547 [[package]] 1335 1548 name = "syn" 1336 - version = "2.0.77" 1549 + version = "2.0.96" 1337 1550 source = "registry+https://github.com/rust-lang/crates.io-index" 1338 - checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" 1551 + checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" 1339 1552 dependencies = [ 1340 1553 "proc-macro2", 1341 1554 "quote", ··· 1352 1565 ] 1353 1566 1354 1567 [[package]] 1568 + name = "terminal_size" 1569 + version = "0.4.0" 1570 + source = "registry+https://github.com/rust-lang/crates.io-index" 1571 + checksum = "4f599bd7ca042cfdf8f4512b277c02ba102247820f9d9d4a9f521f496751a6ef" 1572 + dependencies = [ 1573 + "rustix", 1574 + "windows-sys 0.59.0", 1575 + ] 1576 + 1577 + [[package]] 1578 + name = "textwrap" 1579 + version = "0.16.1" 1580 + source = "registry+https://github.com/rust-lang/crates.io-index" 1581 + checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" 1582 + dependencies = [ 1583 + "unicode-linebreak", 1584 + "unicode-width", 1585 + ] 1586 + 1587 + [[package]] 1355 1588 name = "thiserror" 1356 1589 version = "1.0.64" 1357 1590 source = "registry+https://github.com/rust-lang/crates.io-index" 1358 1591 checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" 1359 1592 dependencies = [ 1360 - "thiserror-impl", 1593 + "thiserror-impl 1.0.64", 1594 + ] 1595 + 1596 + [[package]] 1597 + name = "thiserror" 1598 + version = "2.0.11" 1599 + source = "registry+https://github.com/rust-lang/crates.io-index" 1600 + checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" 1601 + dependencies = [ 1602 + "thiserror-impl 2.0.11", 1361 1603 ] 1362 1604 1363 1605 [[package]] ··· 1368 1610 dependencies = [ 1369 1611 "proc-macro2", 1370 1612 "quote", 1371 - "syn 2.0.77", 1613 + "syn 2.0.96", 1614 + ] 1615 + 1616 + [[package]] 1617 + name = "thiserror-impl" 1618 + version = "2.0.11" 1619 + source = "registry+https://github.com/rust-lang/crates.io-index" 1620 + checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" 1621 + dependencies = [ 1622 + "proc-macro2", 1623 + "quote", 1624 + "syn 2.0.96", 1372 1625 ] 1373 1626 1374 1627 [[package]] ··· 1442 1695 checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" 1443 1696 1444 1697 [[package]] 1698 + name = "unicode-linebreak" 1699 + version = "0.1.5" 1700 + source = "registry+https://github.com/rust-lang/crates.io-index" 1701 + checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" 1702 + 1703 + [[package]] 1445 1704 name = "unicode-segmentation" 1446 1705 version = "1.12.0" 1447 1706 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1503 1762 "once_cell", 1504 1763 "proc-macro2", 1505 1764 "quote", 1506 - "syn 2.0.77", 1765 + "syn 2.0.96", 1507 1766 "wasm-bindgen-shared", 1508 1767 ] 1509 1768 ··· 1537 1796 dependencies = [ 1538 1797 "proc-macro2", 1539 1798 "quote", 1540 - "syn 2.0.77", 1799 + "syn 2.0.96", 1541 1800 "wasm-bindgen-backend", 1542 1801 "wasm-bindgen-shared", 1543 1802 ] ··· 1722 1981 "raw-window-handle 0.6.2", 1723 1982 "rustc-hash", 1724 1983 "smallvec", 1725 - "thiserror", 1984 + "thiserror 1.0.64", 1726 1985 "wgpu-hal", 1727 1986 "wgpu-types", 1728 1987 ] ··· 1765 2024 "renderdoc-sys", 1766 2025 "rustc-hash", 1767 2026 "smallvec", 1768 - "thiserror", 2027 + "thiserror 1.0.64", 1769 2028 "wasm-bindgen", 1770 2029 "web-sys", 1771 2030 "wgpu-types", ··· 2191 2450 dependencies = [ 2192 2451 "proc-macro2", 2193 2452 "quote", 2194 - "syn 2.0.77", 2453 + "syn 2.0.96", 2454 + ] 2455 + 2456 + [[package]] 2457 + name = "zune-core" 2458 + version = "0.4.12" 2459 + source = "registry+https://github.com/rust-lang/crates.io-index" 2460 + checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" 2461 + 2462 + [[package]] 2463 + name = "zune-jpeg" 2464 + version = "0.4.14" 2465 + source = "registry+https://github.com/rust-lang/crates.io-index" 2466 + checksum = "99a5bab8d7dedf81405c4bb1f2b83ea057643d9cb28778cea9eecddeedd2e028" 2467 + dependencies = [ 2468 + "zune-core", 2195 2469 ]
+3 -1
Cargo.toml
··· 13 13 web-sys = "0.3.70" 14 14 pollster = "0.3.0" 15 15 bytemuck = { version = "1.18.0", features = ["derive"] } 16 - 16 + image = { version = "0.25.5", default-features = false, features = ["png", "jpeg"] } 17 + miette = { version = "7.4.0", features = ["fancy"] } 18 + thiserror = "2.0.11" 17 19 18 20 [lib] 19 21 crate-type = ["cdylib", "rlib"]
src/happy-tree.png

This is a binary file and will not be displayed.

+65 -24
src/lib.rs
··· 1 + mod texture; 2 + 1 3 use wgpu::util::DeviceExt; 2 4 use winit::{ 3 5 event::*, ··· 13 15 #[derive(Clone, Copy, Debug, bytemuck::Pod, bytemuck::Zeroable)] 14 16 struct Vertex { 15 17 position: [f32; 3], 16 - color: [f32; 3], 18 + tex_coords: [f32; 2], 17 19 } 18 20 19 21 impl Vertex { ··· 30 32 wgpu::VertexAttribute { 31 33 offset: std::mem::size_of::<[f32; 3]>() as wgpu::BufferAddress, 32 34 shader_location: 1, 33 - format: wgpu::VertexFormat::Float32x3, 35 + format: wgpu::VertexFormat::Float32x2, 34 36 }, 35 37 ], 36 38 } 37 39 } 38 40 } 39 41 40 - const TRI_VERTICES: &[Vertex] = &[ 41 - // CCW order 42 - Vertex { 43 - position: [0.0, 0.5, 0.0], 44 - color: [1.0, 0.0, 0.0], 45 - }, 46 - Vertex { 47 - position: [-0.5, -0.5, 0.0], 48 - color: [0.0, 1.0, 0.0], 49 - }, 50 - Vertex { 51 - position: [0.5, -0.5, 0.0], 52 - color: [0.0, 0.0, 1.0], 53 - }, 54 - ]; 55 - 56 42 const VERTICES: &[Vertex] = &[ 57 - Vertex { position: [-0.0868241, 0.49240386, 0.0], color: [0.5, 0.0, 0.5] }, // A 58 - Vertex { position: [-0.49513406, 0.06958647, 0.0], color: [0.5, 0.0, 0.5] }, // B 59 - Vertex { position: [-0.21918549, -0.44939706, 0.0], color: [0.5, 0.0, 0.5] }, // C 60 - Vertex { position: [0.35966998, -0.3473291, 0.0], color: [0.5, 0.0, 0.5] }, // D 61 - Vertex { position: [0.44147372, 0.2347359, 0.0], color: [0.5, 0.0, 0.5] }, // E 43 + Vertex { position: [-0.0868241, 0.49240386, 0.0], tex_coords: [0.4131759, 0.00759614], }, // A 44 + Vertex { position: [-0.49513406, 0.06958647, 0.0], tex_coords: [0.0048659444, 0.43041354], }, // B 45 + Vertex { position: [-0.21918549, -0.44939706, 0.0], tex_coords: [0.28081453, 0.949397], }, // C 46 + Vertex { position: [0.35966998, -0.3473291, 0.0], tex_coords: [0.85967, 0.84732914], }, // D 47 + Vertex { position: [0.44147372, 0.2347359, 0.0], tex_coords: [0.9414737, 0.2652641], }, // E 62 48 ]; 63 49 64 50 const INDICES: &[u16] = &[ ··· 77 63 vertex_buffer: wgpu::Buffer, 78 64 index_buffer: wgpu::Buffer, 79 65 num_indices: u32, 66 + diffuse_bind_group: wgpu::BindGroup, 67 + diffuse_texture: texture::Texture, 80 68 81 69 // Window must be declared after surface 82 70 // so it gets dropped after it ··· 160 148 desired_maximum_frame_latency: 2, 161 149 }; 162 150 151 + surface.configure(&device, &config); 152 + 153 + let diffuse_bytes = include_bytes!("happy-tree.png"); 154 + let diffuse_texture = texture::Texture::from_bytes(&device, &queue, diffuse_bytes, "happy_tree.png").unwrap(); 155 + 156 + let texture_bind_group_layout = device.create_bind_group_layout( 157 + &wgpu::BindGroupLayoutDescriptor { 158 + entries: &[ 159 + wgpu::BindGroupLayoutEntry { 160 + binding: 0, 161 + visibility: wgpu::ShaderStages::FRAGMENT, 162 + ty: wgpu::BindingType::Texture { 163 + multisampled: false, 164 + view_dimension: wgpu::TextureViewDimension::D2, 165 + sample_type: wgpu::TextureSampleType::Float { 166 + filterable: true 167 + }, 168 + }, 169 + count: None, 170 + }, 171 + wgpu::BindGroupLayoutEntry { 172 + binding: 1, 173 + visibility: wgpu::ShaderStages::FRAGMENT, 174 + ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), 175 + count: None, 176 + } 177 + ], 178 + label: Some("texture_bind_group_layout") 179 + } 180 + ); 181 + 182 + let diffuse_bind_group = device.create_bind_group( 183 + &wgpu::BindGroupDescriptor { 184 + layout: &texture_bind_group_layout, 185 + entries: &[ 186 + wgpu::BindGroupEntry { 187 + binding: 0, 188 + resource: wgpu::BindingResource::TextureView(&diffuse_texture.view), 189 + }, 190 + wgpu::BindGroupEntry { 191 + binding: 1, 192 + resource: wgpu::BindingResource::Sampler(&diffuse_texture.sampler), 193 + } 194 + ], 195 + label: Some("diffuse_bind_group"), 196 + } 197 + ); 198 + 199 + 163 200 let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor { 164 201 label: Some("Shader"), 165 202 source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()), ··· 168 205 let render_pipeline_layout = 169 206 device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { 170 207 label: Some("Render Pipeline Layout"), 171 - bind_group_layouts: &[], 208 + bind_group_layouts: &[&texture_bind_group_layout], 172 209 push_constant_ranges: &[], 173 210 }); 174 211 ··· 237 274 vertex_buffer, 238 275 index_buffer, 239 276 num_indices, 277 + diffuse_bind_group, 278 + diffuse_texture, 240 279 clear_color: wgpu::Color { 241 280 r: 0.1, 242 281 g: 0.2, ··· 313 352 }); 314 353 315 354 render_pass.set_pipeline(&self.render_pipeline); 355 + render_pass.set_bind_group(0, &self.diffuse_bind_group, &[]); 316 356 render_pass.set_vertex_buffer(0, self.vertex_buffer.slice(..)); 317 357 render_pass.set_index_buffer(self.index_buffer.slice(..), wgpu::IndexFormat::Uint16); 358 + 318 359 render_pass.draw_indexed(0..self.num_indices, 0, 0..1); 319 360 320 361 // drop render pass before we submit to drop the mut borrow on encoder
+10 -5
src/shader.wgsl
··· 2 2 3 3 struct VertexInput { 4 4 @location(0) position: vec3<f32>, 5 - @location(1) color: vec3<f32>, 5 + @location(1) tex_coords: vec2<f32>, 6 6 } 7 7 8 8 struct VertexOutput { 9 9 @builtin(position) clip_position: vec4<f32>, 10 - @location(0) color: vec3<f32>, 10 + @location(0) tex_coords: vec2<f32>, 11 11 }; 12 12 13 13 @vertex ··· 15 15 model: VertexInput, 16 16 ) -> VertexOutput { 17 17 var out: VertexOutput; 18 - out.color = model.color; 18 + out.tex_coords = model.tex_coords; 19 19 out.clip_position = vec4<f32>(model.position, 1.0); 20 20 return out; 21 21 } ··· 23 23 24 24 // Fragment shader 25 25 26 + @group(0) @binding(0) 27 + var t_diffuse: texture_2d<f32>; 28 + @group(0) @binding(1) 29 + var s_diffuse: sampler; 30 + 26 31 @fragment 27 32 fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> { 28 - return vec4<f32>(in.color, 1.0); 29 - } 33 + return textureSample(t_diffuse, s_diffuse, in.tex_coords); 34 + }
+81
src/texture.rs
··· 1 + use image::GenericImageView; 2 + use miette::{IntoDiagnostic, Report, Result}; 3 + 4 + pub struct Texture { 5 + #[allow(unused)] 6 + pub texture: wgpu::Texture, 7 + pub view: wgpu::TextureView, 8 + pub sampler: wgpu::Sampler, 9 + } 10 + 11 + impl Texture { 12 + pub fn from_bytes( 13 + device: &wgpu::Device, 14 + queue: &wgpu::Queue, 15 + bytes: &[u8], 16 + label: &str, 17 + ) -> Result<Self> { 18 + let img = image::load_from_memory(bytes).into_diagnostic()?; 19 + Self::from_image(device, queue, &img, Some(label)) 20 + } 21 + 22 + fn from_image( 23 + device: &wgpu::Device, 24 + queue: &wgpu::Queue, 25 + img: &image::DynamicImage, 26 + label: Option<&str>, 27 + ) -> Result<Self> { 28 + let rgba = img.to_rgba8(); 29 + let dimensions = img.dimensions(); 30 + 31 + let size = wgpu::Extent3d { 32 + width: dimensions.0, 33 + height: dimensions.1, 34 + depth_or_array_layers: 1, 35 + }; 36 + 37 + let texture = device.create_texture( 38 + &wgpu::TextureDescriptor { 39 + label, 40 + size, 41 + mip_level_count: 1, 42 + sample_count: 1, 43 + dimension: wgpu::TextureDimension::D2, 44 + format: wgpu::TextureFormat::Rgba8UnormSrgb, 45 + usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST, 46 + view_formats: &[], 47 + } 48 + ); 49 + 50 + queue.write_texture( 51 + wgpu::ImageCopyTexture { 52 + aspect: wgpu::TextureAspect::All, 53 + texture: &texture, 54 + mip_level: 0, 55 + origin: wgpu::Origin3d::ZERO, 56 + }, 57 + &rgba, 58 + wgpu::ImageDataLayout { 59 + offset: 0, 60 + bytes_per_row: Some(4 * dimensions.0), 61 + rows_per_image: Some(dimensions.1), 62 + }, 63 + size, 64 + ); 65 + 66 + let view = texture.create_view(&wgpu::TextureViewDescriptor::default()); 67 + let sampler = device.create_sampler( 68 + &wgpu::SamplerDescriptor { 69 + address_mode_u: wgpu::AddressMode::ClampToEdge, 70 + address_mode_v: wgpu::AddressMode::ClampToEdge, 71 + address_mode_w: wgpu::AddressMode::ClampToEdge, 72 + mag_filter: wgpu::FilterMode::Linear, 73 + min_filter: wgpu::FilterMode::Nearest, 74 + mipmap_filter: wgpu::FilterMode::Nearest, 75 + ..Default::default() 76 + } 77 + ); 78 + 79 + Ok(Self { texture, view, sampler }) 80 + } 81 + }