From 4106f4a4029322f8005f1a9f9e902ce4cd23cbb5 Mon Sep 17 00:00:00 2001 From: prushton2 Date: Mon, 6 Apr 2026 12:24:18 -0400 Subject: [PATCH 1/4] Working on textures --- Cargo.lock | 705 ++++++++++++++++++++++++++++- Cargo.toml | 1 + src/main.rs | 10 + src/material/material_interface.rs | 2 +- src/shaders/intersection.wgsl | 2 +- src/shaders/main.wgsl | 2 +- src/shaders/material.wgsl | 4 +- src/shaders/types.wgsl | 5 +- src/wgpu_handler.rs | 54 ++- textures/dirt.png | Bin 0 -> 750 bytes textures/grass_side.png | Bin 0 -> 804 bytes textures/grass_top.png | Bin 0 -> 506 bytes 12 files changed, 773 insertions(+), 12 deletions(-) create mode 100644 textures/dirt.png create mode 100644 textures/grass_side.png create mode 100644 textures/grass_top.png diff --git a/Cargo.lock b/Cargo.lock index 32c5555..8094400 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10,8 +10,9 @@ dependencies = [ "bytemuck", "downcast-rs 2.0.2", "env_logger", + "image", "pollster", - "rand", + "rand 0.10.0", "softbuffer", "wgpu", "winit", @@ -33,6 +34,12 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618" +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + [[package]] name = "ahash" version = "0.8.12" @@ -55,6 +62,24 @@ dependencies = [ "memchr", ] +[[package]] +name = "aligned" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee4508988c62edf04abd8d92897fca0c2995d907ce1dfeaf369dac3716a40685" +dependencies = [ + "as-slice", +] + +[[package]] +name = "aligned-vec" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b" +dependencies = [ + "equator", +] + [[package]] name = "android-activity" version = "0.6.0" @@ -147,6 +172,23 @@ version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" +[[package]] +name = "arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" + +[[package]] +name = "arg_enum_proc_macro" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "arrayref" version = "0.3.9" @@ -165,6 +207,15 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b" +[[package]] +name = "as-slice" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516" +dependencies = [ + "stable_deref_trait", +] + [[package]] name = "ash" version = "0.38.0+1.3.281" @@ -192,6 +243,49 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +[[package]] +name = "av-scenechange" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f321d77c20e19b92c39e7471cf986812cbb46659d2af674adc4331ef3f18394" +dependencies = [ + "aligned", + "anyhow", + "arg_enum_proc_macro", + "arrayvec", + "log", + "num-rational", + "num-traits", + "pastey", + "rayon", + "thiserror 2.0.18", + "v_frame", + "y4m", +] + +[[package]] +name = "av1-grain" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cfddb07216410377231960af4fcab838eaa12e013417781b78bd95ee22077f8" +dependencies = [ + "anyhow", + "arrayvec", + "log", + "nom", + "num-rational", + "v_frame", +] + +[[package]] +name = "avif-serialize" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "375082f007bd67184fb9c0374614b29f9aaa604ec301635f72338bb65386a53d" +dependencies = [ + "arrayvec", +] + [[package]] name = "bit-set" version = "0.8.0" @@ -207,6 +301,12 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" +[[package]] +name = "bit_field" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6" + [[package]] name = "bitflags" version = "1.3.2" @@ -222,6 +322,15 @@ dependencies = [ "serde_core", ] +[[package]] +name = "bitstream-io" +version = "4.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60d4bd9d1db2c6bdf285e223a7fa369d5ce98ec767dec949c6ca62863ce61757" +dependencies = [ + "core2", +] + [[package]] name = "block" version = "0.1.6" @@ -237,6 +346,12 @@ dependencies = [ "objc2 0.5.2", ] +[[package]] +name = "built" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4ad8f11f288f48ca24471bbd51ac257aaeaaa07adae295591266b792902ae64" + [[package]] name = "bumpalo" version = "3.20.2" @@ -263,6 +378,12 @@ dependencies = [ "syn", ] +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + [[package]] name = "bytes" version = "1.11.1" @@ -333,7 +454,7 @@ checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" dependencies = [ "cfg-if", "cpufeatures", - "rand_core", + "rand_core 0.10.0", ] [[package]] @@ -346,6 +467,12 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + [[package]] name = "colorchoice" version = "1.0.5" @@ -411,6 +538,15 @@ dependencies = [ "libc", ] +[[package]] +name = "core2" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" +dependencies = [ + "memchr", +] + [[package]] name = "cpufeatures" version = "0.3.0" @@ -420,12 +556,46 @@ dependencies = [ "libc", ] +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + [[package]] name = "ctor-lite" version = "0.1.2" @@ -531,6 +701,12 @@ dependencies = [ "linux-raw-sys 0.9.4", ] +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + [[package]] name = "env_filter" version = "1.0.0" @@ -554,6 +730,26 @@ dependencies = [ "log", ] +[[package]] +name = "equator" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" +dependencies = [ + "equator-macro", +] + +[[package]] +name = "equator-macro" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "equivalent" version = "1.0.2" @@ -570,18 +766,72 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "exr" +version = "1.74.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4300e043a56aa2cb633c01af81ca8f699a321879a7854d3896a0ba89056363be" +dependencies = [ + "bit_field", + "half", + "lebe", + "miniz_oxide", + "rayon-core", + "smallvec", + "zune-inflate", +] + [[package]] name = "fastrand" version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +[[package]] +name = "fax" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f05de7d48f37cd6730705cbca900770cab77a89f413d23e100ad7fad7795a0ab" +dependencies = [ + "fax_derive", +] + +[[package]] +name = "fax_derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0aca10fb742cb43f9e7bb8467c91aa9bcb8e3ffbc6a6f7389bb93ffc920577d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +dependencies = [ + "simd-adler32", +] + [[package]] name = "find-msvc-tools" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" +[[package]] +name = "flate2" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + [[package]] name = "foldhash" version = "0.1.5" @@ -670,11 +920,21 @@ dependencies = [ "cfg-if", "libc", "r-efi 6.0.0", - "rand_core", + "rand_core 0.10.0", "wasip2", "wasip3", ] +[[package]] +name = "gif" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5df2ba84018d80c213569363bdcd0c64e6933c67fe4c1d60ecf822971a3c35e" +dependencies = [ + "color_quant", + "weezl", +] + [[package]] name = "gl_generator" version = "0.14.0" @@ -758,6 +1018,17 @@ dependencies = [ "bitflags 2.11.0", ] +[[package]] +name = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "cfg-if", + "crunchy", + "zerocopy", +] + [[package]] name = "hashbrown" version = "0.15.5" @@ -797,6 +1068,46 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" +[[package]] +name = "image" +version = "0.25.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104" +dependencies = [ + "bytemuck", + "byteorder-lite", + "color_quant", + "exr", + "gif", + "image-webp", + "moxcms", + "num-traits", + "png", + "qoi", + "ravif", + "rayon", + "rgb", + "tiff", + "zune-core", + "zune-jpeg", +] + +[[package]] +name = "image-webp" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525e9ff3e1a4be2fbea1fdf0e98686a6d98b4d8f937e1bf7402245af1909e8c3" +dependencies = [ + "byteorder-lite", + "quick-error", +] + +[[package]] +name = "imgref" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c5cedc30da3a610cac6b4ba17597bdf7152cf974e8aab3afb3d54455e371c8" + [[package]] name = "indexmap" version = "2.13.0" @@ -809,12 +1120,32 @@ dependencies = [ "serde_core", ] +[[package]] +name = "interpolate_name" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "is_terminal_polyfill" version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.17" @@ -910,12 +1241,28 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" +[[package]] +name = "lebe" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8" + [[package]] name = "libc" version = "0.2.183" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" +[[package]] +name = "libfuzzer-sys" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f12a681b7dd8ce12bff52488013ba614b869148d54dd79836ab85aafdd53f08d" +dependencies = [ + "arbitrary", + "cc", +] + [[package]] name = "libloading" version = "0.8.9" @@ -977,6 +1324,15 @@ version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +[[package]] +name = "loop9" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" +dependencies = [ + "imgref", +] + [[package]] name = "malloc_buf" version = "0.0.6" @@ -986,6 +1342,16 @@ dependencies = [ "libc", ] +[[package]] +name = "maybe-rayon" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" +dependencies = [ + "cfg-if", + "rayon", +] + [[package]] name = "memchr" version = "2.8.0" @@ -1016,6 +1382,26 @@ dependencies = [ "paste", ] +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "moxcms" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b" +dependencies = [ + "num-traits", + "pxfm", +] + [[package]] name = "naga" version = "24.0.0" @@ -1077,6 +1463,68 @@ dependencies = [ "jni-sys", ] +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + +[[package]] +name = "noop_proc_macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -1456,6 +1904,12 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "pastey" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35fb2e5f958ec131621fdd531e9fc186ed768cbe395337403ae56c17a74c68ec" + [[package]] name = "percent-encoding" version = "2.3.2" @@ -1500,6 +1954,19 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" +[[package]] +name = "png" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" +dependencies = [ + "bitflags 2.11.0", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + [[package]] name = "polling" version = "3.11.0" @@ -1535,6 +2002,15 @@ dependencies = [ "portable-atomic", ] +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + [[package]] name = "presser" version = "0.3.1" @@ -1574,6 +2050,40 @@ name = "profiling" version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773" +dependencies = [ + "profiling-procmacros", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52717f9a02b6965224f95ca2a81e2e0c5c43baacd28ca057577988930b6c3d5b" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "pxfm" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5a041e753da8b807c9255f28de81879c78c876392ff2469cde94799b2896b9d" + +[[package]] +name = "qoi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" [[package]] name = "quick-xml" @@ -1605,6 +2115,16 @@ version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha", + "rand_core 0.9.5", +] + [[package]] name = "rand" version = "0.10.0" @@ -1613,7 +2133,26 @@ checksum = "bc266eb313df6c5c09c1c7b1fbe2510961e5bcd3add930c1e31f7ed9da0feff8" dependencies = [ "chacha20", "getrandom 0.4.2", - "rand_core", + "rand_core 0.10.0", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", ] [[package]] @@ -1628,12 +2167,82 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca45419789ae5a7899559e9512e58ca889e41f04f1f2445e9f4b290ceccd1d08" +[[package]] +name = "rav1e" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43b6dd56e85d9483277cde964fd1bdb0428de4fec5ebba7540995639a21cb32b" +dependencies = [ + "aligned-vec", + "arbitrary", + "arg_enum_proc_macro", + "arrayvec", + "av-scenechange", + "av1-grain", + "bitstream-io", + "built", + "cfg-if", + "interpolate_name", + "itertools", + "libc", + "libfuzzer-sys", + "log", + "maybe-rayon", + "new_debug_unreachable", + "noop_proc_macro", + "num-derive", + "num-traits", + "paste", + "profiling", + "rand 0.9.2", + "rand_chacha", + "simd_helpers", + "thiserror 2.0.18", + "v_frame", + "wasm-bindgen", +] + +[[package]] +name = "ravif" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e52310197d971b0f5be7fe6b57530dcd27beb35c1b013f29d66c1ad73fbbcc45" +dependencies = [ + "avif-serialize", + "imgref", + "loop9", + "quick-error", + "rav1e", + "rayon", + "rgb", +] + [[package]] name = "raw-window-handle" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" +[[package]] +name = "rayon" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "redox_syscall" version = "0.4.1" @@ -1696,6 +2305,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" +[[package]] +name = "rgb" +version = "0.8.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b34b781b31e5d73e9fbc8689c70551fd1ade9a19e3e28cfec8580a79290cc4" + [[package]] name = "rustc-hash" version = "1.1.0" @@ -1822,6 +2437,21 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "simd-adler32" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" + +[[package]] +name = "simd_helpers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" +dependencies = [ + "quote", +] + [[package]] name = "slab" version = "0.4.12" @@ -1918,6 +2548,12 @@ dependencies = [ "bitflags 2.11.0", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + [[package]] name = "static_assertions" version = "1.1.0" @@ -2012,6 +2648,20 @@ dependencies = [ "syn", ] +[[package]] +name = "tiff" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b63feaf3343d35b6ca4d50483f94843803b0f51634937cc2ec519fc32232bc52" +dependencies = [ + "fax", + "flate2", + "half", + "quick-error", + "weezl", + "zune-jpeg", +] + [[package]] name = "tiny-skia" version = "0.11.4" @@ -2132,6 +2782,17 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "v_frame" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "666b7727c8875d6ab5db9533418d7c764233ac9c0cff1d469aec8fa127597be2" +dependencies = [ + "aligned-vec", + "num-traits", + "wasm-bindgen", +] + [[package]] name = "version_check" version = "0.9.5" @@ -2388,6 +3049,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "weezl" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88" + [[package]] name = "wgpu" version = "24.0.5" @@ -2945,6 +3612,12 @@ version = "0.8.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" +[[package]] +name = "y4m" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5a4b21e1a62b67a2970e6831bc091d7b87e119e7f9791aef9702e3bef04448" + [[package]] name = "zerocopy" version = "0.8.42" @@ -2970,3 +3643,27 @@ name = "zmij" version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" + +[[package]] +name = "zune-core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb8a0807f7c01457d0379ba880ba6322660448ddebc890ce29bb64da71fb40f9" + +[[package]] +name = "zune-inflate" +version = "0.2.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "zune-jpeg" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296" +dependencies = [ + "zune-core", +] diff --git a/Cargo.toml b/Cargo.toml index d618754..220486b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ auto_ops = "0.3.0" bytemuck = "1.25.0" downcast-rs = "2.0.2" env_logger = "0.11.9" +image = "0.25.10" pollster = "0.4.0" rand = "0.10.0" softbuffer = "0.4.8" diff --git a/src/main.rs b/src/main.rs index 805a9b4..bc104c2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -366,6 +366,16 @@ fn main() { // mirror sphere Box::new(object::Sphere::new(&ds::Vector3::new(4.0, 0.0, 3.0), 2.0, GpuMaterial::new(0x00AAAAAA, 90, 0))), Box::new(object::Sphere::new(&ds::Vector3::new(4.0, 0.3, 3.0), 0.25, GpuMaterial::new(0x000000FF, 0, 0))), + + // grass block + Box::new(object::Quad::new(&ds::Vector3::new(1.0, 0.0, 5.0), &ds::Vector3::new(0.0, 0.0, 1.0), &ds::Vector3::new(0.0, 1.0, 0.0), GpuMaterial::new(0x00888888, 0, 0))), + Box::new(object::Quad::new(&ds::Vector3::new(1.0, 0.0, 6.0), &ds::Vector3::new(1.0, 0.0, 0.0), &ds::Vector3::new(0.0, 1.0, 0.0), GpuMaterial::new(0x00888888, 0, 0))), + Box::new(object::Quad::new(&ds::Vector3::new(2.0, 0.0, 6.0), &ds::Vector3::new(0.0, 0.0,-1.0), &ds::Vector3::new(0.0, 1.0, 0.0), GpuMaterial::new(0x00888888, 0, 0))), + Box::new(object::Quad::new(&ds::Vector3::new(2.0, 0.0, 5.0), &ds::Vector3::new(-1.0,0.0, 0.0), &ds::Vector3::new(0.0, 1.0, 0.0), GpuMaterial::new(0x00888888, 0, 0))), + + Box::new(object::Quad::new(&ds::Vector3::new(1.0, 1.0, 5.0), &ds::Vector3::new(1.0, 0.0, 0.0), &ds::Vector3::new(0.0, 0.0, 1.0), GpuMaterial::new(0x00888888, 0, 0))), + Box::new(object::Quad::new(&ds::Vector3::new(1.0, 0.0, 5.0), &ds::Vector3::new(1.0, 0.0, 0.0), &ds::Vector3::new(0.0, 0.0, 1.0), GpuMaterial::new(0x00888888, 0, 0))), + ]; let event_loop = EventLoop::new().expect("Failed to create event loop"); diff --git a/src/material/material_interface.rs b/src/material/material_interface.rs index 957a83a..2414104 100644 --- a/src/material/material_interface.rs +++ b/src/material/material_interface.rs @@ -1,7 +1,7 @@ #[repr(C)] #[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] pub struct GpuMaterial { - color: [f32; 3], + color: [f32; 3], reflective: u32, translucent: u32, _pad0: u32, diff --git a/src/shaders/intersection.wgsl b/src/shaders/intersection.wgsl index bf4a182..873515a 100644 --- a/src/shaders/intersection.wgsl +++ b/src/shaders/intersection.wgsl @@ -75,4 +75,4 @@ fn closest_hit(origin: vec3, dir: vec3) -> HitRecord { } return rec; -} \ No newline at end of file +} diff --git a/src/shaders/main.wgsl b/src/shaders/main.wgsl index 24511dd..faec53e 100644 --- a/src/shaders/main.wgsl +++ b/src/shaders/main.wgsl @@ -46,4 +46,4 @@ fn vs_main(@builtin(vertex_index) idx: u32) -> @builtin(position) vec4 { vec2(-1.0, 3.0), ); return vec4(positions[idx], 0.0, 1.0); -} \ No newline at end of file +} diff --git a/src/shaders/material.wgsl b/src/shaders/material.wgsl index 48506ec..efcdae2 100644 --- a/src/shaders/material.wgsl +++ b/src/shaders/material.wgsl @@ -93,7 +93,7 @@ fn ray_color(ray_pos: vec3, ray_dir: vec3, tid: u32) -> u32 { pushed_to_stack = true; } - var lit_color = material.color; + var lit_color = textureLoad(textures, vec2u(0, 0), 0).rgb; if material.reflect + material.translucent < 100 { let light = max(dot(record.normal, light_dir), 0.0); @@ -120,4 +120,4 @@ fn ray_color(ray_pos: vec3, ray_dir: vec3, tid: u32) -> u32 { } return 0x00BADBEDu; -} \ No newline at end of file +} diff --git a/src/shaders/types.wgsl b/src/shaders/types.wgsl index 3049606..306c52b 100644 --- a/src/shaders/types.wgsl +++ b/src/shaders/types.wgsl @@ -46,8 +46,9 @@ struct Material { @group(0) @binding(1) var output: array; @group(0) @binding(2) var spheres: array; @group(0) @binding(3) var quads: array; - +@group(0) @binding(4) var textures: texture_2d; +@group(0) @binding(5) var texture_sampler: sampler; fn ray_at(ray_pos: vec3, ray_dir: vec3, t: f32) -> vec3 { return ray_pos + t * ray_dir; -} \ No newline at end of file +} diff --git a/src/wgpu_handler.rs b/src/wgpu_handler.rs index c3a003d..5ecf583 100644 --- a/src/wgpu_handler.rs +++ b/src/wgpu_handler.rs @@ -1,5 +1,7 @@ use std::sync::Arc; +use std::io::Cursor; +use image::ImageReader; use winit::window::{Window}; use crate::object; @@ -161,6 +163,44 @@ impl GpuHandler { surface.configure(&device, &surface_config); + // --- textures --- + let texture_size = wgpu::Extent3d { + width: 16, + height: 16, + depth_or_array_layers: 1, + }; + + let texture = device.create_texture(&wgpu::TextureDescriptor { + label: Some("Dirt"), + size: texture_size, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::Rgba8UnormSrgb, + usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST, + view_formats: &[], + }); + + let rgba_data = ImageReader::open("textures/dirt.png").expect("No image").decode().expect("Bad decode").to_rgba8().into_raw(); + + queue.write_texture( + wgpu::TexelCopyTextureInfo { + texture: &texture, + mip_level: 0, + origin: wgpu::Origin3d::ZERO, + aspect: wgpu::TextureAspect::All, + }, + &rgba_data, // Your pixel bytes + wgpu::TexelCopyBufferLayout { + offset: 0, + bytes_per_row: Some(4 * 16), // 4 bytes per pixel * width + rows_per_image: Some(16), + }, + texture_size, + ); + + let view = texture.create_view(&wgpu::TextureViewDescriptor::default()); + // --- buffers --- let uniform_buf = device.create_buffer(&wgpu::BufferDescriptor { @@ -254,6 +294,17 @@ impl GpuHandler { }, count: None, }, + // textures + wgpu::BindGroupLayoutEntry { + binding: 4, + visibility: wgpu::ShaderStages::FRAGMENT | wgpu::ShaderStages::COMPUTE, // Usually read in fragment shaders + ty: wgpu::BindingType::Texture { + multisampled: false, + view_dimension: wgpu::TextureViewDimension::D2, + sample_type: wgpu::TextureSampleType::Float { filterable: false }, + }, + count: None, + } ], }); @@ -265,6 +316,7 @@ impl GpuHandler { wgpu::BindGroupEntry { binding: 1, resource: output_buf.as_entire_binding() }, wgpu::BindGroupEntry { binding: 2, resource: spheres_buf.as_entire_binding() }, wgpu::BindGroupEntry { binding: 3, resource: quads_buf.as_entire_binding() }, + wgpu::BindGroupEntry { binding: 4, resource: wgpu::BindingResource::TextureView(&view)}, ], }); @@ -343,4 +395,4 @@ impl Default for GpuHandler { output_buf_size: None, } } -} \ No newline at end of file +} diff --git a/textures/dirt.png b/textures/dirt.png new file mode 100644 index 0000000000000000000000000000000000000000..adda077bd136193522c5613648143efc06c753cc GIT binary patch literal 750 zcmVO6chZ`viEdDGTOve!n8J=A(2;4%Q9`8G$KMoD%Wiz;8C|(}>n1mWX zW(5WGaAy+X?5aXUCiy79uj>-`^AXgWgB@p#qCGurRLG-%U>-&7K+}d%E(t8sd2AH> z9>wgjLYotxBYc1T)XmEp=Zgjv1rs*%vE-$Lt#zC)D_qgqS{%{uk&aF;F+pzg8C?hAJ4El@EyDV-^J&ImLeht#9R6~~danFhQ|fYTR`oCp-s z32KOY6sKe&6+uhJSTR(iKy>ISqQ||1&#a6n=yWB7`uu9&{hrs@n6Mi)82Nx^4g_Gr z$o`zwL!rzsV+eReD`VQ55?H-I+;bhjRFCs)mL`4x41wq6@P)MN`_F4$~0~8CvTCfm7 z1UoCS5CT>{LlUEj`@DDWb38LEep}4knQzYd&iTF-J6|7_U^F9JEf}kW_}1}JbyIXR z6KhJ5{#LQ~YlxZ6mfkmGN3Y_<(c=HCt*@s8uvG*bFo(ukiOx<6=yGtXu{Hl$6=lkciZ$cAXeA~gB<2KSo8yjB! zgm`dfk5pH-(NFli#=@4L5}sutmlDrU+Bo$h!Q(3>TzwMZ(_$OjhpYIw(CkZia$&zz zhbmTAO8_02Z$%iXmSGxzWtjM~)W)#7(;>0Y?CIV5dKu#W>D@A-dA=_uEOvWn#Tk~vR2yw8V;CcBeThbk>xaf=oGOKM z-ZbIbrZ%cVkmWFe#j2XU48wyi*c2q0x-+5Pj0QCE+QD&|v3#Ef_7aJ}XZtufQIe~M zAk7Pu3F;8sAbB^=K};C@ZCpWsn^W6lnoD$hg}$iy)JT?;of+~?bSOn>R_wL1sliS5 zY<1N^%y;6(PqGwKVI40YGR*pP=tFF~W5QG$)%EdO^q ig+=y&ED3W1&%$3TLq#&6x_uY`0000FPfgO>0>pbv|mwPpV8HDBj3EzekpH>--hz`7=V-0VWmH?ze#gRx*jPQ z?c4!)8tXqUkZpV9-9FEqRQ-#NAO+Apu;JkSxiREI<6Z@ji0cDj@#L%mGvEXU{H?Sl z4(7ciwTfsP%wPcqu`&=1nEo=>p2L!|;`$6iy7%>U)xKGSO$pNIFLKf*47V+h&3f zlCUBliZM;|0}INFlhsfW0A6Qqj9~d;rV$aw z*arYoa|r;?a)-xfC%(*GI#7EyI9xUeLS+GEgV}WC+wOsSL;y}S08mykZSA#fXZ~)$ w>?_xssRi;DfLu@9x=vM_keZ8i(RNJCe{IYqkMq6na{vGU07*qoM6N<$g8Lxk8vp Date: Mon, 6 Apr 2026 13:22:52 -0400 Subject: [PATCH 2/4] Texture plumbing works --- src/main.rs | 2 ++ src/shaders/material.wgsl | 2 +- src/shaders/types.wgsl | 3 +-- src/wgpu_handler.rs | 28 ++++++++++++++++++++-------- 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/main.rs b/src/main.rs index bc104c2..c9236c1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -213,6 +213,8 @@ impl ApplicationHandler for App { // wgpu init is async but resumed() isn't — use pollster to block pollster::block_on(self.gpu.init(window.clone(), WIDTH as u32, HEIGHT as u32)); + std::thread::sleep(std::time::Duration::from_millis(1000)); + self.window = Some(window); } diff --git a/src/shaders/material.wgsl b/src/shaders/material.wgsl index efcdae2..ff5f764 100644 --- a/src/shaders/material.wgsl +++ b/src/shaders/material.wgsl @@ -93,7 +93,7 @@ fn ray_color(ray_pos: vec3, ray_dir: vec3, tid: u32) -> u32 { pushed_to_stack = true; } - var lit_color = textureLoad(textures, vec2u(0, 0), 0).rgb; + var lit_color = textureLoad(textures, vec2u(0, 0), 0).rgb * 255.0; if material.reflect + material.translucent < 100 { let light = max(dot(record.normal, light_dir), 0.0); diff --git a/src/shaders/types.wgsl b/src/shaders/types.wgsl index 306c52b..ee498fe 100644 --- a/src/shaders/types.wgsl +++ b/src/shaders/types.wgsl @@ -46,8 +46,7 @@ struct Material { @group(0) @binding(1) var output: array; @group(0) @binding(2) var spheres: array; @group(0) @binding(3) var quads: array; -@group(0) @binding(4) var textures: texture_2d; -@group(0) @binding(5) var texture_sampler: sampler; +@group(0) @binding(4) var textures: texture_2d; fn ray_at(ray_pos: vec3, ray_dir: vec3, t: f32) -> vec3 { return ray_pos + t * ray_dir; diff --git a/src/wgpu_handler.rs b/src/wgpu_handler.rs index 5ecf583..7781a1f 100644 --- a/src/wgpu_handler.rs +++ b/src/wgpu_handler.rs @@ -1,7 +1,7 @@ use std::sync::Arc; -use std::io::Cursor; use image::ImageReader; +use wgpu::{Texture, TextureView}; use winit::window::{Window}; use crate::object; @@ -19,6 +19,9 @@ pub struct GpuHandler { pub spheres_buf: Option, pub quads_buf: Option, pub output_buf_size: Option, + + texture: Option, + view: Option } #[allow(unused)] @@ -51,6 +54,7 @@ pub struct GpuStateMut<'a> { // makes my life infinitely easier pub spheres_buf: &'a mut wgpu::Buffer, pub quads_buf: &'a mut wgpu::Buffer, pub output_buf_size: &'a mut u64, + pub view: &'a mut TextureView, } impl GpuHandler { @@ -71,6 +75,7 @@ impl GpuHandler { spheres_buf: self.spheres_buf.as_mut()?, quads_buf: self.quads_buf.as_mut()?, output_buf_size: self.output_buf_size.as_mut()?, + view: self.view.as_mut()?, } ) } @@ -122,6 +127,7 @@ impl GpuHandler { wgpu::BindGroupEntry { binding: 1, resource: gpu.output_buf.as_entire_binding() }, wgpu::BindGroupEntry { binding: 2, resource: gpu.spheres_buf.as_entire_binding() }, wgpu::BindGroupEntry { binding: 3, resource: gpu.quads_buf.as_entire_binding() }, + wgpu::BindGroupEntry { binding: 4, resource: wgpu::BindingResource::TextureView(gpu.view)}, ], }); @@ -152,7 +158,7 @@ impl GpuHandler { let surface_config = wgpu::SurfaceConfiguration { usage: wgpu::TextureUsages::RENDER_ATTACHMENT, - format: wgpu::TextureFormat::Bgra8Unorm, + format: wgpu::TextureFormat::Rgba8Unorm, width: width, height: height, present_mode: wgpu::PresentMode::Mailbox, @@ -170,22 +176,24 @@ impl GpuHandler { depth_or_array_layers: 1, }; - let texture = device.create_texture(&wgpu::TextureDescriptor { + self.texture = Some(device.create_texture(&wgpu::TextureDescriptor { label: Some("Dirt"), size: texture_size, mip_level_count: 1, sample_count: 1, dimension: wgpu::TextureDimension::D2, - format: wgpu::TextureFormat::Rgba8UnormSrgb, + format: wgpu::TextureFormat::Rgba8Unorm, usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST, view_formats: &[], - }); + })); let rgba_data = ImageReader::open("textures/dirt.png").expect("No image").decode().expect("Bad decode").to_rgba8().into_raw(); + // println!("First 4 bytes of image: {:?}", &rgba_data[0..4]); + queue.write_texture( wgpu::TexelCopyTextureInfo { - texture: &texture, + texture: self.texture.as_ref().expect(""), mip_level: 0, origin: wgpu::Origin3d::ZERO, aspect: wgpu::TextureAspect::All, @@ -199,7 +207,7 @@ impl GpuHandler { texture_size, ); - let view = texture.create_view(&wgpu::TextureViewDescriptor::default()); + self.view = Some(self.texture.as_ref().expect("").create_view(&wgpu::TextureViewDescriptor::default())); // --- buffers --- @@ -316,7 +324,7 @@ impl GpuHandler { wgpu::BindGroupEntry { binding: 1, resource: output_buf.as_entire_binding() }, wgpu::BindGroupEntry { binding: 2, resource: spheres_buf.as_entire_binding() }, wgpu::BindGroupEntry { binding: 3, resource: quads_buf.as_entire_binding() }, - wgpu::BindGroupEntry { binding: 4, resource: wgpu::BindingResource::TextureView(&view)}, + wgpu::BindGroupEntry { binding: 4, resource: wgpu::BindingResource::TextureView(self.view.as_ref().expect(""))}, ], }); @@ -362,6 +370,8 @@ impl GpuHandler { cache: None, }); + queue.submit([]); + // i opted to set them all at the end so im not wrapping everything in Some() and .unwrap() self.device = Some(device); self.queue = Some(queue); @@ -393,6 +403,8 @@ impl Default for GpuHandler { spheres_buf: None, quads_buf: None, output_buf_size: None, + texture: None, + view: None } } } From ae0214fbd812fcbbbd91fabf2a8790281f1639d1 Mon Sep 17 00:00:00 2001 From: prushton2 Date: Mon, 6 Apr 2026 13:58:09 -0400 Subject: [PATCH 3/4] materials can now have a texture that loads --- src/main.rs | 20 +++++++++++++------- src/material/material_interface.rs | 15 +++++++++++++-- src/shaders/material.wgsl | 12 ++++++++++-- src/shaders/types.wgsl | 1 + src/wgpu_handler.rs | 19 ++++++++++++------- 5 files changed, 49 insertions(+), 18 deletions(-) diff --git a/src/main.rs b/src/main.rs index c9236c1..126610b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -211,7 +211,13 @@ impl ApplicationHandler for App { window.set_cursor_visible(false); // wgpu init is async but resumed() isn't — use pollster to block - pollster::block_on(self.gpu.init(window.clone(), WIDTH as u32, HEIGHT as u32)); + pollster::block_on( + self.gpu.init( + window.clone(), + WIDTH as u32, + HEIGHT as u32, + vec!["textures/dirt.png", "textures/grass_side.png", "textures/grass_top.png"]) + ); std::thread::sleep(std::time::Duration::from_millis(1000)); @@ -370,13 +376,13 @@ fn main() { Box::new(object::Sphere::new(&ds::Vector3::new(4.0, 0.3, 3.0), 0.25, GpuMaterial::new(0x000000FF, 0, 0))), // grass block - Box::new(object::Quad::new(&ds::Vector3::new(1.0, 0.0, 5.0), &ds::Vector3::new(0.0, 0.0, 1.0), &ds::Vector3::new(0.0, 1.0, 0.0), GpuMaterial::new(0x00888888, 0, 0))), - Box::new(object::Quad::new(&ds::Vector3::new(1.0, 0.0, 6.0), &ds::Vector3::new(1.0, 0.0, 0.0), &ds::Vector3::new(0.0, 1.0, 0.0), GpuMaterial::new(0x00888888, 0, 0))), - Box::new(object::Quad::new(&ds::Vector3::new(2.0, 0.0, 6.0), &ds::Vector3::new(0.0, 0.0,-1.0), &ds::Vector3::new(0.0, 1.0, 0.0), GpuMaterial::new(0x00888888, 0, 0))), - Box::new(object::Quad::new(&ds::Vector3::new(2.0, 0.0, 5.0), &ds::Vector3::new(-1.0,0.0, 0.0), &ds::Vector3::new(0.0, 1.0, 0.0), GpuMaterial::new(0x00888888, 0, 0))), + Box::new(object::Quad::new(&ds::Vector3::new(1.0, 0.0, 5.0), &ds::Vector3::new(0.0, 0.0, 1.0), &ds::Vector3::new(0.0, 1.0, 0.0), GpuMaterial::texture(1, 0, 0))), + Box::new(object::Quad::new(&ds::Vector3::new(1.0, 0.0, 6.0), &ds::Vector3::new(1.0, 0.0, 0.0), &ds::Vector3::new(0.0, 1.0, 0.0), GpuMaterial::texture(1, 0, 0))), + Box::new(object::Quad::new(&ds::Vector3::new(2.0, 0.0, 6.0), &ds::Vector3::new(0.0, 0.0,-1.0), &ds::Vector3::new(0.0, 1.0, 0.0), GpuMaterial::texture(1, 0, 0))), + Box::new(object::Quad::new(&ds::Vector3::new(2.0, 0.0, 5.0), &ds::Vector3::new(-1.0,0.0, 0.0), &ds::Vector3::new(0.0, 1.0, 0.0), GpuMaterial::texture(1, 0, 0))), - Box::new(object::Quad::new(&ds::Vector3::new(1.0, 1.0, 5.0), &ds::Vector3::new(1.0, 0.0, 0.0), &ds::Vector3::new(0.0, 0.0, 1.0), GpuMaterial::new(0x00888888, 0, 0))), - Box::new(object::Quad::new(&ds::Vector3::new(1.0, 0.0, 5.0), &ds::Vector3::new(1.0, 0.0, 0.0), &ds::Vector3::new(0.0, 0.0, 1.0), GpuMaterial::new(0x00888888, 0, 0))), + Box::new(object::Quad::new(&ds::Vector3::new(1.0, 1.0, 5.0), &ds::Vector3::new(1.0, 0.0, 0.0), &ds::Vector3::new(0.0, 0.0, 1.0), GpuMaterial::texture(2, 0, 0))), + Box::new(object::Quad::new(&ds::Vector3::new(1.0, 0.0, 5.0), &ds::Vector3::new(1.0, 0.0, 0.0), &ds::Vector3::new(0.0, 0.0, 1.0), GpuMaterial::texture(0, 0, 0))), ]; diff --git a/src/material/material_interface.rs b/src/material/material_interface.rs index 2414104..219811e 100644 --- a/src/material/material_interface.rs +++ b/src/material/material_interface.rs @@ -4,7 +4,7 @@ pub struct GpuMaterial { color: [f32; 3], reflective: u32, translucent: u32, - _pad0: u32, + texture_id: i32, _pad1: u32, _pad2: u32, } @@ -20,7 +20,18 @@ impl GpuMaterial { ], reflective: reflective_pct, translucent: translucent_pct, - _pad0: 0, + texture_id: -1, + _pad1: 0, + _pad2: 0, + } + } + pub fn texture(texture_id: i32, reflective_pct: u32, translucent_pct: u32) -> Self { + assert!(reflective_pct + translucent_pct <= 100); + Self { + color: [0.0, 0.0, 0.0], + reflective: reflective_pct, + translucent: translucent_pct, + texture_id: texture_id, _pad1: 0, _pad2: 0, } diff --git a/src/shaders/material.wgsl b/src/shaders/material.wgsl index ff5f764..28cb99b 100644 --- a/src/shaders/material.wgsl +++ b/src/shaders/material.wgsl @@ -93,7 +93,12 @@ fn ray_color(ray_pos: vec3, ray_dir: vec3, tid: u32) -> u32 { pushed_to_stack = true; } - var lit_color = textureLoad(textures, vec2u(0, 0), 0).rgb * 255.0; + var lit_color = vec3(0.0, 0.0, 0.0); + if material.texture_id != -1 { + lit_color = textureLoad(textures, vec2u(0, 16 * u32(material.texture_id)), 0).rgb * 255.0; + } else { + lit_color = material.color; + } if material.reflect + material.translucent < 100 { let light = max(dot(record.normal, light_dir), 0.0); @@ -106,7 +111,10 @@ fn ray_color(ray_pos: vec3, ray_dir: vec3, tid: u32) -> u32 { if !pushed_to_stack { call = callstack[tid][index]; - var color = f32(material.translucent) * call.outputs[0] + f32(material.reflect) * call.outputs[1] + f32(100 - material.translucent - material.reflect) * lit_color; + var color = f32(material.translucent) * call.outputs[0] + + f32(material.reflect) * call.outputs[1] + + f32(100 - material.translucent - material.reflect) * lit_color; + color = color / 100.0; if call.caller != -1 { diff --git a/src/shaders/types.wgsl b/src/shaders/types.wgsl index ee498fe..13150dd 100644 --- a/src/shaders/types.wgsl +++ b/src/shaders/types.wgsl @@ -40,6 +40,7 @@ struct Material { color: vec3, reflect: u32, translucent: u32, + texture_id: i32, } @group(0) @binding(0) var uniforms: Uniform; diff --git a/src/wgpu_handler.rs b/src/wgpu_handler.rs index 7781a1f..d55f5f5 100644 --- a/src/wgpu_handler.rs +++ b/src/wgpu_handler.rs @@ -136,7 +136,7 @@ impl GpuHandler { } // vibecoded but man thats a lot - pub async fn init(&mut self, window: Arc, width: u32, height: u32) { + pub async fn init(&mut self, window: Arc, width: u32, height: u32, texture_paths: Vec<&str>) { // --- get a handle to the graphics card --- let instance = wgpu::Instance::default(); let surface = instance.create_surface(window).unwrap(); @@ -170,9 +170,18 @@ impl GpuHandler { surface.configure(&device, &surface_config); // --- textures --- + + let mut rgba_data: Vec = vec![]; + + for path in &texture_paths { + rgba_data.extend_from_slice( + &ImageReader::open(path).expect("No image").decode().expect("Bad decode").to_rgba8().into_raw() + ); + } + let texture_size = wgpu::Extent3d { width: 16, - height: 16, + height: 16*texture_paths.len() as u32, depth_or_array_layers: 1, }; @@ -187,10 +196,6 @@ impl GpuHandler { view_formats: &[], })); - let rgba_data = ImageReader::open("textures/dirt.png").expect("No image").decode().expect("Bad decode").to_rgba8().into_raw(); - - // println!("First 4 bytes of image: {:?}", &rgba_data[0..4]); - queue.write_texture( wgpu::TexelCopyTextureInfo { texture: self.texture.as_ref().expect(""), @@ -202,7 +207,7 @@ impl GpuHandler { wgpu::TexelCopyBufferLayout { offset: 0, bytes_per_row: Some(4 * 16), // 4 bytes per pixel * width - rows_per_image: Some(16), + rows_per_image: Some(16 * texture_paths.len() as u32), }, texture_size, ); From 7ca5623c492599af387b1d8de18ab88d5f4313cb Mon Sep 17 00:00:00 2001 From: prushton2 Date: Mon, 6 Apr 2026 15:23:58 -0400 Subject: [PATCH 4/4] Added textures --- src/main.rs | 4 ++-- src/shaders/material.wgsl | 25 +++++++++++++++++++++++-- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index 126610b..6eb66a9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -367,8 +367,8 @@ fn main() { // Box::new(object::Sphere::new(&ds::Vector3::new(-3.25, -0.8, 6.0), 0.5, GpuMaterial::new(0x0000FF00, 0, 0))), Box::new(object::Sphere::new(&ds::Vector3::new(-4.75, -0.8, 6.0), 0.5, GpuMaterial::new(0x000000FF, 0, 0))), - Box::new(object::Sphere::new(&ds::Vector3::new(-4.0, 0.0, 6.0), 0.5, GpuMaterial::new(0x00FF0000, 50, 0))), - Box::new(object::Sphere::new(&ds::Vector3::new(-4.0, 1.0, 6.0), 0.49, GpuMaterial::new(0x00000000, 0, 50))), + Box::new(object::Sphere::new(&ds::Vector3::new(-4.0, 0.0, 6.0), 0.5, GpuMaterial::new(0x00FF69B4, 50, 0))), + Box::new(object::Sphere::new(&ds::Vector3::new(-4.0, 1.0, 6.0), 0.49, GpuMaterial::new(0x00FF69B4, 0, 50))), Box::new(object::Sphere::new(&ds::Vector3::new(-4.0, 2.0, 6.0), 0.49, GpuMaterial::new(0x00FF0000, 0, 0))), // mirror sphere diff --git a/src/shaders/material.wgsl b/src/shaders/material.wgsl index 28cb99b..71124a9 100644 --- a/src/shaders/material.wgsl +++ b/src/shaders/material.wgsl @@ -95,7 +95,7 @@ fn ray_color(ray_pos: vec3, ray_dir: vec3, tid: u32) -> u32 { var lit_color = vec3(0.0, 0.0, 0.0); if material.texture_id != -1 { - lit_color = textureLoad(textures, vec2u(0, 16 * u32(material.texture_id)), 0).rgb * 255.0; + lit_color = get_texture_color(record); } else { lit_color = material.color; } @@ -124,8 +124,29 @@ fn ray_color(ray_pos: vec3, ray_dir: vec3, tid: u32) -> u32 { return (u32(color.x) << 16) | (u32(color.y) << 8) | (u32(color.z)); } } - } return 0x00BADBEDu; } + +fn get_texture_color(record: HitRecord) -> vec3 { + var material: Material; + var quad: Quad; + + switch record.obj_type { + case 0u: { + material = spheres[record.obj_index].material; + return material.color; // only works on quads for now + } + case 1u: { + material = quads[record.obj_index].material; + quad = quads[record.obj_index]; + } + default: {} + } + + let pct_across = u32(abs((dot(cross(quad.v, record.normal), record.position - quad.q))*16 / length(quad.v))); + let pct_up = u32(abs((dot(cross(quad.u, record.normal), record.position - quad.q))*16 / length(quad.u))); + + return textureLoad(textures, vec2u(pct_across, (15-pct_up) + 16 * u32(material.texture_id)), 0).rgb * 255.0; +} \ No newline at end of file