diff --git a/Cargo.lock b/Cargo.lock index 50da994..f102553 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,11 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "ab_glyph_rasterizer" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9fe5e32de01730eb1f6b7f5b51c17e03e2325bf40a74f754f04f130043affff" + [[package]] name = "addr2line" version = "0.14.0" @@ -36,6 +42,25 @@ dependencies = [ "memchr", ] +[[package]] +name = "andrew" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c4afb09dd642feec8408e33f92f3ffc4052946f6b20f32fb99c1f58cd4fa7cf" +dependencies = [ + "bitflags", + "rusttype", + "walkdir", + "xdg", + "xml-rs 0.8.3", +] + +[[package]] +name = "android_glue" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "000444226fcff248f2bc4c7625be32c63caccfecc2723a2b9f78a7487a49c407" + [[package]] name = "approx" version = "0.4.0" @@ -71,12 +96,28 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + [[package]] name = "byteorder" version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" +[[package]] +name = "calloop" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b036167e76041694579972c28cf4877b4f92da222560ddb49008937b6a6727c" +dependencies = [ + "log", + "nix", +] + [[package]] name = "cc" version = "1.0.65" @@ -95,6 +136,15 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cgl" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ced0551234e87afee12411d535648dd89d2e7f34c78b753395567aff3d447ff" +dependencies = [ + "libc", +] + [[package]] name = "cloudabi" version = "0.1.0" @@ -113,6 +163,37 @@ dependencies = [ "cc", ] +[[package]] +name = "cocoa" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c54201c07dcf3a5ca33fececb8042aed767ee4bfd5a0235a8ceabcda956044b2" +dependencies = [ + "bitflags", + "block", + "cocoa-foundation", + "core-foundation 0.9.1", + "core-graphics 0.22.1", + "foreign-types", + "libc", + "objc", +] + +[[package]] +name = "cocoa-foundation" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ade49b65d560ca58c403a479bb396592b155c0185eada742ee323d1d68d6318" +dependencies = [ + "bitflags", + "block", + "core-foundation 0.9.1", + "core-graphics-types", + "foreign-types", + "libc", + "objc", +] + [[package]] name = "color_quant" version = "1.1.0" @@ -125,6 +206,88 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c478836e029dcef17fb47c89023448c64f781a046e0300e257ad8225ae59afab" +[[package]] +name = "core-foundation" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" +dependencies = [ + "core-foundation-sys 0.7.0", + "libc", +] + +[[package]] +name = "core-foundation" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a89e2ae426ea83155dccf10c0fa6b1463ef6d5fcb44cee0b224a408fa640a62" +dependencies = [ + "core-foundation-sys 0.8.2", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" + +[[package]] +name = "core-foundation-sys" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b" + +[[package]] +name = "core-graphics" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3889374e6ea6ab25dba90bb5d96202f61108058361f6dc72e8b03e6f8bbe923" +dependencies = [ + "bitflags", + "core-foundation 0.7.0", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc239bba52bab96649441699533a68de294a101533b0270b2d65aa402b29a7f9" +dependencies = [ + "bitflags", + "core-foundation 0.9.1", + "core-graphics-types", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b" +dependencies = [ + "bitflags", + "core-foundation 0.9.1", + "foreign-types", + "libc", +] + +[[package]] +name = "core-video-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34ecad23610ad9757664d644e369246edde1803fcb43ed72876565098a5d3828" +dependencies = [ + "cfg-if 0.1.10", + "core-foundation-sys 0.7.0", + "core-graphics 0.19.2", + "libc", + "objc", +] + [[package]] name = "crc32fast" version = "1.2.1" @@ -181,6 +344,41 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "darling" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2 1.0.24", + "quote 1.0.7", + "strsim", + "syn 1.0.51", +] + +[[package]] +name = "darling_macro" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" +dependencies = [ + "darling_core", + "quote 1.0.7", + "syn 1.0.51", +] + [[package]] name = "deflate" version = "0.7.20" @@ -191,6 +389,32 @@ dependencies = [ "byteorder", ] +[[package]] +name = "derivative" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb582b60359da160a9477ee80f15c8d784c477e69c217ef2cdd4169c24ea380f" +dependencies = [ + "proc-macro2 1.0.24", + "quote 1.0.7", + "syn 1.0.51", +] + +[[package]] +name = "dispatch" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" + +[[package]] +name = "dlib" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b11f15d1e3268f140f68d390637d5e76d849782d971ae7063e0da69fe9709a76" +dependencies = [ + "libloading", +] + [[package]] name = "dlv-list" version = "0.2.2" @@ -252,7 +476,7 @@ dependencies = [ "cfg-if 1.0.0", "libc", "redox_syscall", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -273,6 +497,43 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "fuchsia-zircon" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +dependencies = [ + "bitflags", + "fuchsia-zircon-sys", +] + +[[package]] +name = "fuchsia-zircon-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" + [[package]] name = "generic-array" version = "0.14.4" @@ -314,7 +575,7 @@ checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce" name = "gl" version = "0.1.0" dependencies = [ - "gl_generator", + "gl_generator 0.9.0", ] [[package]] @@ -323,9 +584,92 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a795170cbd85b5a7baa58d6d7525cae6a03e486859860c220f7ebbbdd379d0a" dependencies = [ - "khronos_api", + "khronos_api 2.2.0", + "log", + "xml-rs 0.7.0", +] + +[[package]] +name = "gl_generator" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d" +dependencies = [ + "khronos_api 3.1.0", + "log", + "xml-rs 0.8.3", +] + +[[package]] +name = "glutin" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8bae26a39a728b003e9fad473ea89527de0de050143b4df866f18bb154bc86e" +dependencies = [ + "android_glue", + "cgl", + "cocoa", + "core-foundation 0.9.1", + "glutin_egl_sys", + "glutin_emscripten_sys", + "glutin_gles2_sys", + "glutin_glx_sys", + "glutin_wgl_sys", + "lazy_static", + "libloading", "log", - "xml-rs", + "objc", + "osmesa-sys", + "parking_lot", + "wayland-client", + "wayland-egl", + "winapi 0.3.9", + "winit", +] + +[[package]] +name = "glutin_egl_sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2abb6aa55523480c4adc5a56bbaa249992e2dddb2fc63dc96e04a3355364c211" +dependencies = [ + "gl_generator 0.14.0", + "winapi 0.3.9", +] + +[[package]] +name = "glutin_emscripten_sys" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80de4146df76e8a6c32b03007bc764ff3249dcaeb4f675d68a06caf1bac363f1" + +[[package]] +name = "glutin_gles2_sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8094e708b730a7c8a1954f4f8a31880af00eb8a1c5b5bf85d28a0a3c6d69103" +dependencies = [ + "gl_generator 0.14.0", + "objc", +] + +[[package]] +name = "glutin_glx_sys" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e393c8fc02b807459410429150e9c4faffdb312d59b8c038566173c81991351" +dependencies = [ + "gl_generator 0.14.0", + "x11-dl", +] + +[[package]] +name = "glutin_wgl_sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3da5951a1569dbab865c6f2a863efafff193a93caf05538d193e9e3816d21696" +dependencies = [ + "gl_generator 0.14.0", ] [[package]] @@ -346,6 +690,12 @@ dependencies = [ "libc", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "image" version = "0.20.1" @@ -382,7 +732,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91712c94f8ff36ad1add686def2223eb27fbdf4962205de94630992a493abaaa" dependencies = [ - "gl_generator", + "gl_generator 0.9.0", "imgui", ] @@ -433,6 +783,21 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "iovec" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +dependencies = [ + "libc", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + [[package]] name = "jpeg-decoder" version = "0.1.20" @@ -443,24 +808,56 @@ dependencies = [ "rayon", ] +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + [[package]] name = "khronos_api" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "037ab472c33f67b5fbd3e9163a2645319e5356fcd355efa6d4eb7fff4bbcb554" +[[package]] +name = "khronos_api" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" + [[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "libc" version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614" +[[package]] +name = "libloading" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1090080fe06ec2648d0da3881d9453d97e71a45f00eb179af7fdd7e3f686fdb0" +dependencies = [ + "cfg-if 1.0.0", + "winapi 0.3.9", +] + [[package]] name = "libm" version = "0.1.4" @@ -497,6 +894,15 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d947cbb889ed21c2a84be6ffbaebf5b4e0f4340638cba0444907e38b56be084" +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + [[package]] name = "matrixmultiply" version = "0.2.3" @@ -506,29 +912,88 @@ dependencies = [ "rawpointer", ] +[[package]] +name = "maybe-uninit" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" + [[package]] name = "memchr" version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" +[[package]] +name = "memmap" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" +dependencies = [ + "libc", + "winapi 0.3.9", +] + [[package]] name = "memoffset" version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" +checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" +dependencies = [ + "autocfg", +] + +[[package]] +name = "miniz_oxide" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d" +dependencies = [ + "adler", + "autocfg", +] + +[[package]] +name = "mio" +version = "0.6.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430" +dependencies = [ + "cfg-if 0.1.10", + "fuchsia-zircon", + "fuchsia-zircon-sys", + "iovec", + "kernel32-sys", + "libc", + "log", + "miow", + "net2", + "slab", + "winapi 0.2.8", +] + +[[package]] +name = "mio-extras" +version = "2.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" dependencies = [ - "autocfg", + "lazycell", + "log", + "mio", + "slab", ] [[package]] -name = "miniz_oxide" -version = "0.4.3" +name = "miow" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d" +checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" dependencies = [ - "adler", - "autocfg", + "kernel32-sys", + "net2", + "winapi 0.2.8", + "ws2_32-sys", ] [[package]] @@ -569,7 +1034,7 @@ dependencies = [ "bitflags", "lazy_static", "stretch", - "winapi", + "winapi 0.3.9", "winapi-build", ] @@ -592,6 +1057,84 @@ dependencies = [ "smallvec", ] +[[package]] +name = "ndk" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eb167c1febed0a496639034d0c76b3b74263636045db5489eee52143c246e73" +dependencies = [ + "jni-sys", + "ndk-sys", + "num_enum", + "thiserror", +] + +[[package]] +name = "ndk-glue" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdf399b8b7a39c6fb153c4ec32c72fd5fe789df24a647f229c239aa7adb15241" +dependencies = [ + "lazy_static", + "libc", + "log", + "ndk", + "ndk-macro", + "ndk-sys", +] + +[[package]] +name = "ndk-macro" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05d1c6307dc424d0f65b9b06e94f88248e6305726b14729fd67a5e47b2dc481d" +dependencies = [ + "darling", + "proc-macro-crate", + "proc-macro2 1.0.24", + "quote 1.0.7", + "syn 1.0.51", +] + +[[package]] +name = "ndk-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c44922cb3dbb1c70b5e5f443d63b64363a898564d739ba5198e3a9138442868d" + +[[package]] +name = "net2" +version = "0.2.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7cf75f38f16cb05ea017784dc6dbfd354f76c223dba37701734c4f5a9337d02" +dependencies = [ + "cfg-if 0.1.10", + "libc", + "winapi 0.3.9", +] + +[[package]] +name = "nix" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83450fe6a6142ddd95fb064b746083fc4ef1705fe81f64a64e1d4b39f54a1055" +dependencies = [ + "bitflags", + "cc", + "cfg-if 0.1.10", + "libc", +] + +[[package]] +name = "nom" +version = "6.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88034cfd6b4a0d54dd14f4a507eceee36c0b70e5a02236c4e4df571102be17f0" +dependencies = [ + "memchr", + "version_check", +] + [[package]] name = "num-complex" version = "0.3.1" @@ -675,12 +1218,49 @@ dependencies = [ "libc", ] +[[package]] +name = "num_enum" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca565a7df06f3d4b485494f25ba05da1435950f4dc263440eda7a6fa9b8e36e4" +dependencies = [ + "derivative", + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffa5a33ddddfee04c0283a7653987d634e880347e96b5b2ed64de07efb59db9d" +dependencies = [ + "proc-macro-crate", + "proc-macro2 1.0.24", + "quote 1.0.7", + "syn 1.0.51", +] + +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + [[package]] name = "object" version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397" +[[package]] +name = "once_cell" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0" + [[package]] name = "ordered-multimap" version = "0.3.1" @@ -691,6 +1271,24 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "osmesa-sys" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88cfece6e95d2e717e0872a7f53a8684712ad13822a7979bc760b9c77ec0013b" +dependencies = [ + "shared_library", +] + +[[package]] +name = "owned_ttf_parser" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f923fb806c46266c02ab4a5b239735c144bdeda724a50ed058e5226f594cde3" +dependencies = [ + "ttf-parser", +] + [[package]] name = "parking_lot" version = "0.11.1" @@ -714,7 +1312,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -723,6 +1321,12 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7151b083b0664ed58ed669fcdd92f01c3d2fdbf10af4931a301474950b52bfa9" +[[package]] +name = "percent-encoding" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" + [[package]] name = "petgraph" version = "0.5.1" @@ -733,6 +1337,12 @@ dependencies = [ "indexmap", ] +[[package]] +name = "pkg-config" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" + [[package]] name = "png" version = "0.12.0" @@ -751,6 +1361,15 @@ version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" +[[package]] +name = "proc-macro-crate" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" +dependencies = [ + "toml", +] + [[package]] name = "proc-macro2" version = "0.4.30" @@ -799,6 +1418,7 @@ version = "0.1.0" dependencies = [ "failure", "gl", + "glutin", "image", "imgui", "imgui-opengl-renderer", @@ -875,6 +1495,15 @@ dependencies = [ "rand_core", ] +[[package]] +name = "raw-window-handle" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a441a7a6c80ad6473bd4b74ec1c9a4c951794285bf941c2126f607c72e48211" +dependencies = [ + "libc", +] + [[package]] name = "rawpointer" version = "0.2.1" @@ -954,6 +1583,16 @@ version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e3bad0ee36814ca07d7968269dd4b7ec89ec2da10c4bb613928d3077083c232" +[[package]] +name = "rusttype" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc7c727aded0be18c5b80c1640eae0ac8e396abf6fa8477d96cb37d18ee5ec59" +dependencies = [ + "ab_glyph_rasterizer", + "owned_ttf_parser", +] + [[package]] name = "same-file" version = "1.0.6" @@ -963,6 +1602,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scoped-tls" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" + [[package]] name = "scoped_threadpool" version = "0.1.9" @@ -1002,6 +1647,22 @@ dependencies = [ "version-compare", ] +[[package]] +name = "serde" +version = "1.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b88fa983de7720629c9387e9f517353ed404164b1e482c970a90c1a4aaf7dc1a" + +[[package]] +name = "shared_library" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a9e7e0f2bfae24d8a5b5a66c5b257a83c7412304311512a0c054cd5e619da11" +dependencies = [ + "lazy_static", + "libc", +] + [[package]] name = "simba" version = "0.3.1" @@ -1032,6 +1693,26 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7acad6f34eb9e8a259d3283d1e8c1d34d7415943d4895f65cc73813c7396fc85" +[[package]] +name = "smithay-client-toolkit" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ec5c077def8af49f9b5aeeb5fcf8079c638c6615c3a8f9305e2dea601de57f7" +dependencies = [ + "andrew", + "bitflags", + "byteorder", + "calloop", + "dlib", + "lazy_static", + "log", + "memmap", + "nix", + "wayland-client", + "wayland-cursor", + "wayland-protocols", +] + [[package]] name = "stretch" version = "0.3.2" @@ -1042,6 +1723,12 @@ dependencies = [ "libm 0.1.4", ] +[[package]] +name = "strsim" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" + [[package]] name = "syn" version = "0.11.11" @@ -1108,6 +1795,26 @@ dependencies = [ "xattr", ] +[[package]] +name = "thiserror" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e9ae34b84616eedaaf1e9dd6026dbe00dcafa92aa0c8077cb69df1fcfe5e53e" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ba20f23e85b10754cd195504aebf6a27e2e6cbe28c17778a0c930724628dd56" +dependencies = [ + "proc-macro2 1.0.24", + "quote 1.0.7", + "syn 1.0.51", +] + [[package]] name = "thread_local" version = "1.0.1" @@ -1129,6 +1836,21 @@ dependencies = [ "num-traits", ] +[[package]] +name = "toml" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75cf45bb0bef80604d001caaec0d09da99611b3c0fd39d3080468875cdb65645" +dependencies = [ + "serde", +] + +[[package]] +name = "ttf-parser" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e5d7cd7ab3e47dda6e56542f4bbf3824c15234958c6e1bd6aaa347e93499fdc" + [[package]] name = "typenum" version = "1.12.0" @@ -1183,7 +1905,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d" dependencies = [ "same-file", - "winapi", + "winapi 0.3.9", "winapi-util", ] @@ -1193,6 +1915,95 @@ version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" +[[package]] +name = "wayland-client" +version = "0.28.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "222b227f47871e47d657c1c5e5360b4af9a877aa9c892716787be1c192c78c42" +dependencies = [ + "bitflags", + "downcast-rs", + "libc", + "nix", + "scoped-tls", + "wayland-commons", + "wayland-scanner", + "wayland-sys", +] + +[[package]] +name = "wayland-commons" +version = "0.28.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "230b3ffeda101f877ff8ecb8573f5d26e7beb345b197807c4df34ec06879a3e6" +dependencies = [ + "nix", + "once_cell", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-cursor" +version = "0.28.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aad1b4301cdccfb5f64056a4736e8155a5f4734bac41fdbca80b1fdbe1ab3e1" +dependencies = [ + "nix", + "wayland-client", + "xcursor", +] + +[[package]] +name = "wayland-egl" +version = "0.28.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308f3ec651a099d1aa4e60625c81f67b4264d72d1b524bc7fb1a7675f7c050b4" +dependencies = [ + "wayland-client", + "wayland-sys", +] + +[[package]] +name = "wayland-protocols" +version = "0.28.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc16a9db803cae58b45f9a84a6cf364434cc49a95c8b1ef98ffeb467d228bdc9" +dependencies = [ + "bitflags", + "wayland-client", + "wayland-commons", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.28.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee5bd43a1d746efc486515fec561e47205f328b74802b959f10f5500f7e56cc" +dependencies = [ + "proc-macro2 1.0.24", + "quote 1.0.7", + "xml-rs 0.7.0", +] + +[[package]] +name = "wayland-sys" +version = "0.28.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0814adbecc7ea97869971e1d1c1b657e31863dda6fd768f119ad3dc408a01e58" +dependencies = [ + "dlib", + "lazy_static", + "pkg-config", +] + +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" + [[package]] name = "winapi" version = "0.3.9" @@ -1221,7 +2032,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" dependencies = [ - "winapi", + "winapi 0.3.9", ] [[package]] @@ -1230,6 +2041,59 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "winit" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5bc559da567d8aa671bbcd08304d49e982c7bf2cb91e10288b9188931c1b772" +dependencies = [ + "bitflags", + "cocoa", + "core-foundation 0.9.1", + "core-graphics 0.22.1", + "core-video-sys", + "dispatch", + "instant", + "lazy_static", + "libc", + "log", + "mio", + "mio-extras", + "ndk", + "ndk-glue", + "ndk-sys", + "objc", + "parking_lot", + "percent-encoding", + "raw-window-handle", + "smithay-client-toolkit", + "wayland-client", + "winapi 0.3.9", + "x11-dl", +] + +[[package]] +name = "ws2_32-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + +[[package]] +name = "x11-dl" +version = "2.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf981e3a5b3301209754218f962052d4d9ee97e478f4d26d4a6eced34c1fef8" +dependencies = [ + "lazy_static", + "libc", + "maybe-uninit", + "pkg-config", +] + [[package]] name = "xattr" version = "0.2.2" @@ -1239,6 +2103,21 @@ dependencies = [ "libc", ] +[[package]] +name = "xcursor" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a9a231574ae78801646617cefd13bfe94be907c0e4fa979cfd8b770aa3c5d08" +dependencies = [ + "nom", +] + +[[package]] +name = "xdg" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d089681aa106a86fade1b0128fb5daf07d5867a509ab036d99988dec80429a57" + [[package]] name = "xml-rs" version = "0.7.0" @@ -1247,3 +2126,9 @@ checksum = "3c1cb601d29fe2c2ac60a2b2e5e293994d87a1f6fa9687a31a15270f909be9c2" dependencies = [ "bitflags", ] + +[[package]] +name = "xml-rs" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b07db065a5cf61a7e4ba64f29e67db906fb1787316516c4e6e5ff0fea1efcd8a" diff --git a/Cargo.toml b/Cargo.toml index a94b494..3f2515c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,7 @@ imgui-opengl-renderer = { version = "0.9.0", optional = true } native-windows-gui = "1.0.7" native-windows-derive = "1.0.2" rust-ini = "0.16.0" +glutin = "0.25.1" [build-dependencies] walkdir = "2.3.1" diff --git a/src/main.rs b/src/main.rs index 54954cb..8f40801 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,6 @@ #![windows_subsystem = "windows"] extern crate gl; -extern crate sdl2; #[macro_use] extern crate failure; #[macro_use] @@ -19,6 +18,7 @@ mod debug_ui; mod droplet; mod droplets; mod quad; +mod rain; pub mod render_gl; pub mod resources; mod vertex; @@ -30,9 +30,7 @@ use crate::debug::failure_to_string; use crate::debug_ui::DebugUi; use crate::droplets::Droplets; use crate::quad::Quad; -use crate::render_gl::{ - ColorBuffer, Error, FrameBuffer, Program, Shader, Texture, TextureLoadOptions, Viewport, -}; + use failure::err_msg; use image::GenericImageView; use nalgebra as na; @@ -42,7 +40,7 @@ use ncollide2d::pipeline::{ }; use ncollide2d::query::Proximity; use ncollide2d::shape::{Ball, ShapeHandle}; -use rand::prelude::*; + use render_gl::buffer::*; use resources::Resources; use std::env; @@ -52,23 +50,6 @@ use std::time::{Duration, Instant}; const MAX_DROPLET_COUNT: usize = 10_000; -const DROPLETS_PER_SECOND: usize = 50; - -const VIEW_DISTANCE: f32 = 10.0; - -const DROPLET_SIZE_GRAVITY_THRESHOLD: f32 = 5.0; -const PRIVATE_GRAVITY_FORCE_FACTOR_Y: f32 = 0.25; -const PRIVATE_GRAVITY_FORCE_FACTOR_X: f32 = 0.0; - -const DROP_VERT: &str = include_str!("../assets/shaders/drop.vert"); -const DROP_FRAG: &str = include_str!("../assets/shaders/drop.frag"); -const DROP_WIPE_VERT: &str = include_str!("../assets/shaders/drop_wipe.vert"); -const DROP_WIPE_FRAG: &str = include_str!("../assets/shaders/drop_wipe.frag"); -const COLORED_QUAD_VERT: &str = include_str!("../assets/shaders/colored_quad.vert"); -const COLORED_QUAD_FRAG: &str = include_str!("../assets/shaders/colored_quad.frag"); -const QUAD_VERT: &str = include_str!("../assets/shaders/quad.vert"); -const FINAL_FRAG: &str = include_str!("../assets/shaders/final.frag"); - fn main() { let args: Vec = env::args().skip(1).collect(); @@ -91,659 +72,108 @@ fn main() { } fn run() -> Result<(), failure::Error> { - let res = Resources::from_relative_exe_path(Path::new("assets")).unwrap(); - - let sdl = sdl2::init().map_err(err_msg)?; - - let video_subsystem = sdl.video().map_err(err_msg)?; - - let gl_attr = video_subsystem.gl_attr(); - - gl_attr.set_context_profile(sdl2::video::GLProfile::Core); - gl_attr.set_context_version(4, 5); - - let window = video_subsystem - .window("Rain", 1920, 1080) - .position_centered() - .fullscreen_desktop() - .opengl() - .resizable() - .allow_highdpi() - .build()?; - - let _gl_context = window.gl_create_context().map_err(err_msg)?; - - let gl = gl::Gl::load_with(|s| { - video_subsystem.gl_get_proc_address(s) as *const std::os::raw::c_void - }); - - let window_size = window.size(); - - let mut viewport = Viewport::for_window(window_size.0 as i32, window_size.1 as i32); - - let view: na::Matrix4 = (na::Translation3::::from(na::Point3::origin().coords) - * na::Translation3::::from(na::Vector3::z() * VIEW_DISTANCE)) - .inverse() - .to_homogeneous(); - - let mut projection = na::Orthographic3::new( - 0.0, - window_size.0 as f32, - 0.0, - window_size.1 as f32, - 0.01, - 1000.0, - ); - - let matrix = projection.into_inner() * view; - - let config = Config::default(); - - let background_texture = match config.background() { - Some(path) => { - let mut options = TextureLoadOptions::from_res_rgb(&path); - options.gen_mipmaps = true; - - let mut image = image::open(&path)?; - - let texture_dimensions = image.dimensions(); - let (screen_width, screen_height) = window_size; - - let screen_ratio = screen_width as f32 / screen_height as f32; - let texture_ratio = texture_dimensions.0 as f32 / texture_dimensions.1 as f32; + use glutin::event::{Event, WindowEvent}; + use glutin::event_loop::{ControlFlow, EventLoop}; + use glutin::window::WindowBuilder; + use glutin::ContextBuilder; - let target_dimensions = if screen_ratio < texture_ratio { - let ratio = screen_ratio / texture_ratio; - ( - texture_dimensions.0 as f32 * ratio, - texture_dimensions.1 as f32, - ) - } else { - let ratio = texture_ratio / screen_ratio; - ( - texture_dimensions.0 as f32, - texture_dimensions.1 as f32 * ratio, - ) - }; + let res = Resources::from_relative_exe_path(Path::new("assets")).unwrap(); - let offsets = ( - (texture_dimensions.0 as f32 - target_dimensions.0) * 0.5, - (texture_dimensions.1 as f32 - target_dimensions.1) * 0.5, - ); + let el = EventLoop::new(); + let mut wb = WindowBuilder::new().with_title("Rain"); - let x = offsets.0; - let y = offsets.1; - let width = texture_dimensions.0 as f32 - offsets.0; - let height = texture_dimensions.1 as f32 - offsets.1; + let window = wb.build(&el)?; - let image = image.crop(x as u32, y as u32, (width - x) as u32, (height - y) as u32); + let raw_context = unsafe { + use glutin::platform::windows::{RawContextExt, WindowExtWindows}; - Texture::from_image(options, &gl, &image)? - } - None => Texture::from_res_rgb("textures/background.jpg") - .with_gen_mipmaps() - .load(&gl, &res)?, + let hwnd = window.hwnd(); + ContextBuilder::new().build_raw_context(hwnd)? }; - let texture_rc = Rc::::new(background_texture); - - let frame_buffer = FrameBuffer::new(&gl); - - let background = - background::Background::new(&gl, texture_rc.clone(), window_size.0, window_size.1, 1.0)?; - - let quad = Quad::default(&gl); - - viewport.set_used(&gl); - - let mut event_pump = sdl.event_pump().map_err(err_msg)?; + let raw_context = unsafe { raw_context.make_current().unwrap() }; - let mut rng = rand::thread_rng(); + let gl = gl::Gl::load_with(|s| raw_context.get_proc_address(s) as *const _); - let mut droplets: Droplets = Droplets::with_capacity(MAX_DROPLET_COUNT); + let window_size = window.inner_size(); - let mut world = CollisionWorld::new(2.0); - - let collision_group = CollisionGroups::new(); - let contacts_query = GeometricQueryType::Proximity(0.0); - - #[cfg(feature = "debug")] - let mut debug_ui = DebugUi::new(&window); + // #[cfg(feature = "debug")] + // let mut debug_ui = DebugUi::new(&window); unsafe { gl.Enable(gl::BLEND); gl.BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA); } - let drop_program = render_gl::Program::from_shaders( - &gl, - &[ - Shader::from_vert_source_str(&gl, DROP_VERT)?, - Shader::from_frag_source_str(&gl, DROP_FRAG)?, - ], - ) - .map_err(|msg| Error::LinkError { - message: msg, - name: "drop".to_string(), - })?; - - let drop_wipe_program = Program::from_shaders( - &gl, - &[ - Shader::from_vert_source_str(&gl, DROP_WIPE_VERT)?, - Shader::from_frag_source_str(&gl, DROP_WIPE_FRAG)?, - ], - ) - .map_err(|msg| Error::LinkError { - message: msg, - name: "drop_wipe".to_string(), - })?; + let mut raw_context = Option::from(raw_context); - let colored_quad_program = Program::from_shaders( + let mut rain = rain::Rain::new( &gl, - &[ - Shader::from_vert_source_str(&gl, COLORED_QUAD_VERT)?, - Shader::from_frag_source_str(&gl, COLORED_QUAD_FRAG)?, - ], - ) - .map_err(|msg| Error::LinkError { - message: msg, - name: "colored_quad".to_string(), - })?; - - let final_program = Program::from_shaders( - &gl, - &[ - Shader::from_vert_source_str(&gl, QUAD_VERT)?, - Shader::from_frag_source_str(&gl, FINAL_FRAG)?, - ], - ) - .map_err(|msg| Error::LinkError { - message: msg, - name: "final".to_string(), - })?; - - let mut updates = Vec::<(CollisionObjectSlabHandle, CollisionObjectSlabHandle)>::new(); - - let mut time_accumulator: f64 = 0.; - let mut droplets_accumulator: usize = DROPLETS_PER_SECOND; - - let background_mask = Texture::new(&gl, window_size.0 as u32, window_size.1 as u32)?; - - let background_tex = Texture::new(&gl, window_size.0, window_size.1)?; - - let fullscreen_quad = - Quad::new_with_size(&gl, 0.0, 0.0, window_size.1 as f32, window_size.0 as f32); - - let black = ColorBuffer::from_rgba(0.0, 0.0, 0.0, 1.0); - - { - frame_buffer.bind(); - frame_buffer.attach_texture(&background_mask); - - black.set_used(&gl); - black.clear(&gl); - - frame_buffer.unbind(); - } - - let mut resolution: Vector2 = Vector2::new(viewport.w as f32, viewport.h as f32); + MAX_DROPLET_COUNT, + (window_size.width, window_size.height), + &Config::default(), + )?; let mut instant = Instant::now(); - 'main: loop { - let now = Instant::now(); - let delta = now.duration_since(instant); - instant = now; - - time_accumulator += delta.as_secs_f64(); - - if time_accumulator > 1.0 { - time_accumulator -= 1.0; - - droplets_accumulator += DROPLETS_PER_SECOND; - } - - for event in event_pump.poll_iter() { - #[cfg(feature = "debug")] - { - debug_ui.handle_event(&event); - - if debug_ui.ignore_event(&event) { - continue; - } - } - - match event { - sdl2::event::Event::Quit { .. } => break 'main, - sdl2::event::Event::KeyUp { .. } => break 'main, - sdl2::event::Event::Window { - win_event: sdl2::event::WindowEvent::Resized(w, h), - .. - } => { - viewport.update_size(w, h); - viewport.set_used(&gl); - - projection.set_left_and_right(0.0, w as f32); - projection.set_bottom_and_top(0.0, h as f32); - - resolution = Vector2::new(viewport.w as f32, viewport.h as f32); - } - _ => {} - } - } - - // Updates - { - gravity_non_linear(&mut droplets, &mut world, &mut rng, &delta); - - trail( - &mut droplets, - &mut world, - &mut rng, - &collision_group, - &contacts_query, - &delta, - ); - - updates.clear(); - - // We get an "allowance" of DROPLETS_PER_SECOND every second. - // This part of the loop will attempt to spend them at random times, and is more likely to - // spend them the more time has past. - // TODO: Any better way to spend these more evenly? - // TODO: What happens when budget > fps? - if droplets_accumulator > 0 && rng.gen_bool(time_accumulator.max(0.0).min(1.0)) { - if let Some((i, d)) = droplets.checkout() { - d.pos = na::Vector2::new( - rng.gen_range(0.0, viewport.w as f32), - rng.gen_range(0.0, viewport.h as f32), - ); - d.size = rng.gen_range(3.0, 8.0); - - let shape_handle = ShapeHandle::new(Ball::new(d.size * 0.5)); - - let handle = world - .add( - Isometry2::new(d.pos.clone_owned(), na::zero()), - shape_handle, - collision_group, - contacts_query, - i, - ) - .0; - - d.collision_handle = handle; - - droplets_accumulator -= 1; - } - } - - for ev in world.proximity_events().iter().collect::>() { - if ev.new_status == Proximity::Intersecting { - if let (Some(obj1), Some(obj2)) = ( - world.collision_object(ev.collider1), - world.collision_object(ev.collider2), - ) { - let sphere1 = obj1.shape().local_bounding_sphere(); - let sphere2 = obj2.shape().local_bounding_sphere(); - - let rad1 = sphere1.radius(); - let rad2 = sphere2.radius(); - - let pair = if rad1 > rad2 { - (ev.collider1, ev.collider2) - } else if rad1 < rad2 { - (ev.collider2, ev.collider1) - } else if sphere1.center().y > sphere2.center().y { - (ev.collider1, ev.collider2) - } else { - (ev.collider2, ev.collider1) - }; - - updates.push(pair); - } - } - } - - for (keep_handle, delete_handle) in updates.iter() { - if let (Some(keep), Some(delete)) = - world.collision_object_pair_mut(*keep_handle, *delete_handle) - { - let keep_droplet_index = *keep.data(); - let delete_droplet_index = *delete.data(); - - let delete_droplet_size = droplets[delete_droplet_index].size; - - let keep_droplet = &mut droplets[keep_droplet_index]; - - // TODO: How much does a droplet grow when is absorbs another? - keep_droplet.size = ((keep_droplet.size * 0.5).powf(3.0) - + (delete_droplet_size * 0.5).powf(3.0)) - .cbrt() - * 2.0; - - keep.set_shape(ShapeHandle::new(Ball::new(keep_droplet.size * 0.5))); - } - } - - for (_, delete_handle) in updates.iter() { - if let Some(delete) = world.collision_object(*delete_handle) { - droplets.free(*delete.data()); - world.remove(&[*delete_handle]); + let mut delta = Duration::default(); + + el.run(move |event, _, control_flow| { + *control_flow = ControlFlow::Poll; + + // #[cfg(feature = "debug")] + // { + // debug_ui.handle_event(&event); + // + // if debug_ui.ignore_event(&event) { + // continue; + // } + // } + + match event { + Event::NewEvents(_) => { + let now = Instant::now(); + + delta = now.duration_since(instant); + + instant = now; + } + Event::MainEventsCleared => { + rain.update(&delta); + } + Event::LoopDestroyed => { + raw_context.take(); // Make sure it drops first + return; + } + Event::WindowEvent { event, .. } => match event { + WindowEvent::Resized(physical_size) => { + // viewport.update_size(w, h); + // viewport.set_used(&gl); + // + // projection.set_left_and_right(0.0, w as f32); + // projection.set_bottom_and_top(0.0, h as f32); + // + // raw_context.resize(physical_size); } - } - } - - // Background pass - { - background.prepass(&gl, &view, &matrix, &resolution); - - frame_buffer.bind(); - frame_buffer.attach_texture(&background_tex); - - background.render(&gl, &view, &matrix, &resolution); - - frame_buffer.unbind(); + WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit, + _ => (), + }, + Event::RedrawRequested(_) => { + // rain.render(&delta); + + // #[cfg(feature = "debug")] + // debug_ui.render( + // &window, + // &event_pump.mouse_state(), + // &delta, + // droplets.used_count(), + // droplets_accumulator, + // ); + + raw_context.as_ref().unwrap().swap_buffers().unwrap(); + } + _ => (), } - - // Mask pass - { - frame_buffer.bind(); - frame_buffer.attach_texture(&background_mask); - - unsafe { - gl.BlendFuncSeparate(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA, gl::ZERO, gl::ONE); - } - - { - colored_quad_program.set_used(); - - if let Some(loc) = colored_quad_program.get_uniform_location("MVP") { - colored_quad_program.set_uniform_matrix_4fv(loc, &matrix); - } - - if let Some(loc) = colored_quad_program.get_uniform_location("Color") { - colored_quad_program.set_uniform_4f( - loc, - &na::Vector4::new(0.0, 0.0, 0.0, 0.25 * delta.as_secs_f32()), - ); - } - - fullscreen_quad.render(&gl); - } - - { - let program_matrix_location = drop_wipe_program.get_uniform_location("MVP"); - let resolution_location = drop_wipe_program.get_uniform_location("Resolution"); - - drop_wipe_program.set_used(); - - if let Some(loc) = resolution_location { - drop_wipe_program.set_uniform_2f(loc, &resolution); - } - - if let Some(loc) = program_matrix_location { - drop_wipe_program.set_uniform_matrix_4fv(loc, &matrix); - } - - render_droplets(&gl, &quad, &droplets); - } - - unsafe { - gl.BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA); - } - - frame_buffer.unbind(); - } - - // Merge pass - { - final_program.set_used(); - - black.set_used(&gl); - black.clear(&gl); - - if let Some(loc) = final_program.get_uniform_location("MVP") { - final_program.set_uniform_matrix_4fv(loc, &matrix); - } - - if let Some(loc) = final_program.get_uniform_location("Texture0") { - background_tex.bind_at(0); - final_program.set_uniform_1i(loc, 0); - } - if let Some(loc) = final_program.get_uniform_location("Texture1") { - texture_rc.bind_at(1); - final_program.set_uniform_1i(loc, 1); - } - if let Some(loc) = final_program.get_uniform_location("Mask") { - background_mask.bind_at(2); - final_program.set_uniform_1i(loc, 2); - } - - fullscreen_quad.render(&gl); - } - - { - drop_program.set_used(); - - if let Some(loc) = drop_program.get_uniform_location("Resolution") { - drop_program.set_uniform_2f(loc, &resolution); - } - - if let Some(loc) = drop_program.get_uniform_location("MVP") { - drop_program.set_uniform_matrix_4fv(loc, &matrix); - } - - if let Some(loc) = drop_program.get_uniform_location("Texture") { - texture_rc.bind_at(0); - drop_program.set_uniform_1i(loc, 0); - } - - render_droplets(&gl, &quad, &droplets); - } - - #[cfg(feature = "debug")] - debug_ui.render( - &window, - &event_pump.mouse_state(), - &delta, - droplets.used_count(), - droplets_accumulator, - ); - - window.gl_swap_window(); - } + }); Ok(()) } - -fn render_droplets(gl: &gl::Gl, quad: &Quad, droplets: &Droplets) { - quad.vao.bind(); - - let instance_vbo: ArrayBuffer = ArrayBuffer::new(&gl); - instance_vbo.bind(); - - let offsets: Vec> = droplets - .into_iter() - .filter(|d| !d.deleted) - .map(|d| na::Vector3::new(d.pos.x, d.pos.y, d.size)) - .collect(); - - instance_vbo.static_draw_data(&offsets); - - unsafe { - gl.EnableVertexAttribArray(3); - gl.VertexAttribPointer( - 3, - 3, // the number of components per generic vertex attribute - gl::FLOAT, // data type - gl::FALSE, - std::mem::size_of::>() as gl::types::GLint, - 0 as *const gl::types::GLvoid, - ); - } - instance_vbo.unbind(); - - unsafe { - gl.VertexAttribDivisor(3, 1); - } - - unsafe { - gl.DrawElementsInstanced( - gl::TRIANGLES, - 6, - gl::UNSIGNED_BYTE, - ::std::ptr::null(), - offsets.len() as i32, - ); - } - quad.vao.unbind(); -} - -fn gravity_non_linear( - droplets: &mut Droplets, - world: &mut CollisionWorld, - rng: &mut ThreadRng, - dt: &Duration, -) { - let fps = 1.0 / dt.as_secs_f32(); - let gravity_y = PRIVATE_GRAVITY_FORCE_FACTOR_Y * dt.as_secs_f32(); - - for i in 0..droplets.len() { - let mut delete_index: Option = None; - - { - let droplet = &mut droplets[i]; - - if droplet.deleted || droplet.size < DROPLET_SIZE_GRAVITY_THRESHOLD { - continue; - } - - if droplet.size < DROPLET_SIZE_GRAVITY_THRESHOLD && droplet.seed > 0 { - droplet.slowing = true; - } - - let movement_probability = 0.01 * dt.as_secs_f64(); - - if droplet.seed <= 0 { - droplet.seed = (droplet.size * 0.5 * rng.gen_range(0.0, 1.0) * fps).floor() as i32; - droplet.skipping = droplet.skipping == false; - droplet.slowing = true; - } - - droplet.seed -= 1; - - assert!(droplet.size >= 1.0); - - if droplet.speed.y > 0.0 { - if droplet.slowing { - droplet.speed *= 0.9; - if droplet.speed.y < gravity_y { - droplet.slowing = false; - } - } else if droplet.skipping { - droplet.speed.y = gravity_y; - droplet.speed.x = PRIVATE_GRAVITY_FORCE_FACTOR_X; - } else { - droplet.speed.y += gravity_y * droplet.size; - droplet.speed.x += PRIVATE_GRAVITY_FORCE_FACTOR_X * droplet.size; - } - } else if rng.gen_bool((1.0 - 1.0 / droplet.size as f64) * movement_probability) { - droplet.speed.y = gravity_y; - droplet.speed.x = PRIVATE_GRAVITY_FORCE_FACTOR_X; - } - - // if this.options.gravityAngleVariance != 0 { - // droplet.x_speed += - // (rnd.gen() * 2 - 1) * droplet.y_speed * this.options.gravityAngleVariance - // } - - droplet.pos.y -= droplet.speed.y; - droplet.pos.x += droplet.speed.x; - - if droplet.pos.y + droplet.size * 0.5 < 0.0 { - delete_index = Some(i); - - world.remove(&[droplet.collision_handle]); - } else if droplet.speed.x != 0.0 || droplet.speed.y != 0.0 { - let handle = droplet.collision_handle; - - let object = world.get_mut(handle).unwrap(); - - object.set_position(Isometry2::new(droplet.pos.clone_owned(), na::zero())); - } - } - - if let Some(delete_index) = delete_index { - droplets.free(delete_index); - } - } - - world.update(); -} - -fn trail( - droplets: &mut Droplets, - world: &mut CollisionWorld, - rng: &mut ThreadRng, - collision_group: &CollisionGroups, - contacts_query: &GeometricQueryType, - dt: &Duration, -) { - let gravity_y = PRIVATE_GRAVITY_FORCE_FACTOR_Y * dt.as_secs_f32(); - - for i in 0..droplets.len() { - let pos; - let size; - - { - let droplet = &mut droplets[i]; - - if droplet.speed.y <= gravity_y { - continue; - } - - if droplet.size >= 6.0 - && (droplet.last_trail_y.is_none() - || (droplet.last_trail_y.unwrap_or(0.0) - droplet.pos.y) - >= rng.gen_range(0.1, 1.0) * 200.0) - { - droplet.last_trail_y = Some(droplet.pos.y); - - size = rng.gen_range(0.9, 1.1) * droplet.size * 0.25; - pos = Vector2::new( - droplet.pos.x + rng.gen_range(-1.0, 1.0), - droplet.pos.y + droplet.size * 0.5 + droplet.speed.y + size * 0.5, - ); - - droplet.size = - ((droplet.size * 0.5).powf(3.0) - (size * 0.5).powf(3.0)).cbrt() * 2.0; - - if let Some(droplet_collision) = world.get_mut(droplet.collision_handle) { - droplet_collision.set_shape(ShapeHandle::new(Ball::new(droplet.size * 0.5))) - } - } else { - continue; - } - } - - if let Some((i, d)) = droplets.checkout() { - d.pos = pos; - d.size = size; - - let shape_handle = ShapeHandle::new(Ball::new(d.size * 0.5)); - - let handle = world - .add( - Isometry2::new(d.pos.clone_owned(), na::zero()), - shape_handle, - *collision_group, - *contacts_query, - i, - ) - .0; - - d.collision_handle = handle; - } - } -} diff --git a/src/rain.rs b/src/rain.rs new file mode 100644 index 0000000..b3d7d98 --- /dev/null +++ b/src/rain.rs @@ -0,0 +1,696 @@ +use crate::background::Background; +use crate::config::Config; +use crate::droplets::Droplets; +use crate::quad::Quad; +use crate::render_gl; +use crate::render_gl::buffer::ArrayBuffer; +use crate::render_gl::{ + ColorBuffer, Error, FrameBuffer, Program, Shader, Texture, TextureLoadOptions, Viewport, +}; +use image::GenericImageView; +use nalgebra as na; +use nalgebra::{Matrix4, Orthographic3, Point3, Translation3, Vector2, Vector3, Vector4}; +use ncollide2d::na::Isometry2; +use ncollide2d::pipeline::{CollisionGroups, CollisionObjectSlabHandle, GeometricQueryType}; +use ncollide2d::query::Proximity; +use ncollide2d::shape::{Ball, ShapeHandle}; +use ncollide2d::world::CollisionWorld; +use rand::prelude::*; +use std::rc::Rc; +use std::time::Duration; + +const VIEW_DISTANCE: f32 = 10.0; + +const DROPLETS_PER_SECOND: usize = 50; + +const DROPLET_SIZE_GRAVITY_THRESHOLD: f32 = 5.0; +const PRIVATE_GRAVITY_FORCE_FACTOR_Y: f32 = 0.25; +const PRIVATE_GRAVITY_FORCE_FACTOR_X: f32 = 0.0; + +const DROP_VERT: &str = include_str!("../assets/shaders/drop.vert"); +const DROP_FRAG: &str = include_str!("../assets/shaders/drop.frag"); +const DROP_WIPE_VERT: &str = include_str!("../assets/shaders/drop_wipe.vert"); +const DROP_WIPE_FRAG: &str = include_str!("../assets/shaders/drop_wipe.frag"); +const COLORED_QUAD_VERT: &str = include_str!("../assets/shaders/colored_quad.vert"); +const COLORED_QUAD_FRAG: &str = include_str!("../assets/shaders/colored_quad.frag"); +const QUAD_VERT: &str = include_str!("../assets/shaders/quad.vert"); +const FINAL_FRAG: &str = include_str!("../assets/shaders/final.frag"); + +fn load_shader(gl: &gl::Gl, vert_source: &str, frag_source: &str, debug_name: &str) -> Program { + Program::from_shaders( + &gl, + &[ + Shader::from_vert_source_str(&gl, vert_source).unwrap(), + Shader::from_frag_source_str(&gl, frag_source).unwrap(), + ], + ) + .map_err(|msg| Error::LinkError { + message: msg, + name: debug_name.to_string(), + }) + .unwrap() +} + +pub struct Rain { + gl: gl::Gl, + + max_droplet_count: usize, + + updates: Vec<(CollisionObjectSlabHandle, CollisionObjectSlabHandle)>, + + world: CollisionWorld, + + collision_group: CollisionGroups, + contacts_query: GeometricQueryType, + + viewport: Viewport, + + view_matrix: Matrix4, + projection_matrix: Matrix4, + + time_accumulator: f64, + droplets_accumulator: usize, + + droplets: Droplets, + + black_color_buffer: ColorBuffer, + + background_texture: Rc, + background_mask: Texture, + background_buffer: Texture, + + background: Background, + drop_quad: Quad, + fullscreen_quad: Quad, + + drop_program: Program, + drop_wipe_program: Program, + colored_quad_program: Program, + final_program: Program, + + frame_buffer: FrameBuffer, +} + +impl Rain { + pub fn new( + gl: &gl::Gl, + max_droplet_count: usize, + window_size: (u32, u32), + config: &Config, + ) -> Result { + let mut droplets: Droplets = Droplets::with_capacity(max_droplet_count); + + let world = CollisionWorld::new(2.0); + + let collision_group = CollisionGroups::new(); + let contacts_query = GeometricQueryType::Proximity(0.0); + + let mut viewport = Viewport::for_window(window_size.0 as i32, window_size.1 as i32); + + viewport.set_used(&gl); + + let view_matrix: Matrix4 = (Translation3::::from(Point3::origin().coords) + * Translation3::::from(Vector3::z() * VIEW_DISTANCE)) + .inverse() + .to_homogeneous(); + + let mut projection_matrix: Matrix4 = Orthographic3::new( + 0.0, + window_size.0 as f32, + 0.0, + window_size.1 as f32, + 0.01, + 1000.0, + ) + .into_inner(); + + let background_texture = { + let path = match config.background() { + Some(path) => path, + None => { + let current_exe = std::env::current_exe().unwrap(); + let mut dir = current_exe.parent().unwrap(); + + dir.join("assets/background.jpg") + .to_str() + .unwrap() + .to_string() + } + }; + + let mut options = TextureLoadOptions::from_res_rgb(&path); + options.gen_mipmaps = true; + + let mut image = image::open(&path).unwrap(); + + let texture_dimensions = image.dimensions(); + let (screen_width, screen_height) = window_size; + + let screen_ratio = screen_width as f32 / screen_height as f32; + let texture_ratio = texture_dimensions.0 as f32 / texture_dimensions.1 as f32; + + let target_dimensions = if screen_ratio < texture_ratio { + let ratio = screen_ratio / texture_ratio; + ( + texture_dimensions.0 as f32 * ratio, + texture_dimensions.1 as f32, + ) + } else { + let ratio = texture_ratio / screen_ratio; + ( + texture_dimensions.0 as f32, + texture_dimensions.1 as f32 * ratio, + ) + }; + + let offsets = ( + (texture_dimensions.0 as f32 - target_dimensions.0) * 0.5, + (texture_dimensions.1 as f32 - target_dimensions.1) * 0.5, + ); + + let x = offsets.0; + let y = offsets.1; + let width = texture_dimensions.0 as f32 - offsets.0; + let height = texture_dimensions.1 as f32 - offsets.1; + + let image = image.crop(x as u32, y as u32, (width - x) as u32, (height - y) as u32); + + Texture::from_image(options, &gl, &image).unwrap() + }; + + let texture_rc = Rc::::new(background_texture); + + let drop_quad = Quad::default(&gl); + + let background = + Background::new(&gl, texture_rc.clone(), window_size.0, window_size.1, 1.0)?; + + let drop_program = load_shader(&gl, DROP_VERT, DROP_FRAG, "drop"); + + let drop_wipe_program = load_shader(&gl, DROP_WIPE_VERT, DROP_WIPE_FRAG, "drop_wipe"); + + let colored_quad_program = + load_shader(&gl, COLORED_QUAD_VERT, COLORED_QUAD_FRAG, "colored_quad"); + + let final_program = load_shader(&gl, QUAD_VERT, FINAL_FRAG, "final"); + + let background_mask = Texture::new(&gl, window_size.0 as u32, window_size.1 as u32)?; + + let background_buffer = Texture::new(&gl, window_size.0, window_size.1)?; + + let fullscreen_quad = + Quad::new_with_size(&gl, 0.0, 0.0, window_size.1 as f32, window_size.0 as f32); + + let black_color_buffer = ColorBuffer::from_rgba(0.0, 0.0, 0.0, 1.0); + + let frame_buffer = FrameBuffer::new(&gl); + + { + frame_buffer.bind(); + frame_buffer.attach_texture(&background_mask); + + black_color_buffer.set_used(&gl); + black_color_buffer.clear(&gl); + + frame_buffer.unbind(); + } + + Ok(Rain { + gl: gl.clone(), + + max_droplet_count, + + updates: Vec::<(CollisionObjectSlabHandle, CollisionObjectSlabHandle)>::new(), + + viewport, + + time_accumulator: 0.0, + droplets_accumulator: DROPLETS_PER_SECOND, + + droplets, + + world, + collision_group, + contacts_query, + + view_matrix, + projection_matrix, + + black_color_buffer, + + background_texture: texture_rc, + background_mask, + background_buffer, + + background, + drop_quad, + fullscreen_quad, + + drop_program, + drop_wipe_program, + colored_quad_program, + final_program, + + frame_buffer, + }) + } + + pub fn update_resolution() {} + + pub fn update(&mut self, delta: &Duration) { + let mut rng = rand::thread_rng(); + + self.time_accumulator += delta.as_secs_f64(); + + if self.time_accumulator > 1.0 { + self.time_accumulator -= 1.0; + + self.droplets_accumulator += DROPLETS_PER_SECOND; + } + + // Updates + { + Self::gravity_non_linear(&mut self.droplets, &mut self.world, &mut rng, delta); + + Self::trail( + &mut self.droplets, + &mut self.world, + &mut rng, + &self.collision_group, + &self.contacts_query, + &delta, + ); + + self.updates.clear(); + + // We get an "allowance" of DROPLETS_PER_SECOND every second. + // This part of the loop will attempt to spend them at random times, and is more likely to + // spend them the more time has past. + // TODO: Any better way to spend these more evenly? + // TODO: What happens when budget > fps? + if self.droplets_accumulator > 0 + && rng.gen_bool(self.time_accumulator.max(0.0).min(1.0)) + { + if let Some((i, d)) = self.droplets.checkout() { + d.pos = Vector2::new( + rng.gen_range(0.0, self.viewport.w as f32), + rng.gen_range(0.0, self.viewport.h as f32), + ); + d.size = rng.gen_range(3.0, 8.0); + + let shape_handle = ShapeHandle::new(Ball::new(d.size * 0.5)); + + let handle = self + .world + .add( + Isometry2::new(d.pos.clone_owned(), na::zero()), + shape_handle, + self.collision_group, + self.contacts_query, + i, + ) + .0; + + d.collision_handle = handle; + + self.droplets_accumulator -= 1; + } + } + + for ev in self.world.proximity_events().iter().collect::>() { + if ev.new_status == Proximity::Intersecting { + if let (Some(obj1), Some(obj2)) = ( + self.world.collision_object(ev.collider1), + self.world.collision_object(ev.collider2), + ) { + let sphere1 = obj1.shape().local_bounding_sphere(); + let sphere2 = obj2.shape().local_bounding_sphere(); + + let rad1 = sphere1.radius(); + let rad2 = sphere2.radius(); + + let pair = if rad1 > rad2 { + (ev.collider1, ev.collider2) + } else if rad1 < rad2 { + (ev.collider2, ev.collider1) + } else if sphere1.center().y > sphere2.center().y { + (ev.collider1, ev.collider2) + } else { + (ev.collider2, ev.collider1) + }; + + self.updates.push(pair); + } + } + } + + for (keep_handle, delete_handle) in self.updates.iter() { + if let (Some(keep), Some(delete)) = self + .world + .collision_object_pair_mut(*keep_handle, *delete_handle) + { + let keep_droplet_index = *keep.data(); + let delete_droplet_index = *delete.data(); + + let delete_droplet_size = self.droplets[delete_droplet_index].size; + + let keep_droplet = &mut self.droplets[keep_droplet_index]; + + // TODO: How much does a droplet grow when is absorbs another? + keep_droplet.size = ((keep_droplet.size * 0.5).powf(3.0) + + (delete_droplet_size * 0.5).powf(3.0)) + .cbrt() + * 2.0; + + keep.set_shape(ShapeHandle::new(Ball::new(keep_droplet.size * 0.5))); + } + } + + for (_, delete_handle) in self.updates.iter() { + if let Some(delete) = self.world.collision_object(*delete_handle) { + self.droplets.free(*delete.data()); + self.world.remove(&[*delete_handle]); + } + } + } + } + + pub fn render(&self, delta: &Duration) { + let matrix = &self.projection_matrix * &self.view_matrix; + + let resolution = Vector2::new(self.viewport.w as f32, self.viewport.h as f32); + + // Background pass + { + self.background.prepass( + &self.gl, + &self.view_matrix, + &self.projection_matrix, + &resolution, + ); + + self.frame_buffer.bind(); + self.frame_buffer.attach_texture(&self.background_buffer); + + self.background.render( + &self.gl, + &self.view_matrix, + &self.projection_matrix, + &resolution, + ); + + self.frame_buffer.unbind(); + } + + // Mask pass + { + self.frame_buffer.bind(); + self.frame_buffer.attach_texture(&self.background_mask); + + unsafe { + self.gl.BlendFuncSeparate( + gl::SRC_ALPHA, + gl::ONE_MINUS_SRC_ALPHA, + gl::ZERO, + gl::ONE, + ); + } + + { + self.colored_quad_program.set_used(); + + if let Some(loc) = self.colored_quad_program.get_uniform_location("MVP") { + self.colored_quad_program + .set_uniform_matrix_4fv(loc, &matrix); + } + + if let Some(loc) = self.colored_quad_program.get_uniform_location("Color") { + self.colored_quad_program.set_uniform_4f( + loc, + &Vector4::new(0.0, 0.0, 0.0, 0.25 * delta.as_secs_f32()), + ); + } + + self.fullscreen_quad.render(&self.gl); + } + + { + self.drop_wipe_program.set_used(); + + if let Some(loc) = self.drop_wipe_program.get_uniform_location("Resolution") { + self.drop_wipe_program.set_uniform_2f(loc, &resolution); + } + + if let Some(loc) = self.drop_wipe_program.get_uniform_location("MVP") { + self.drop_wipe_program.set_uniform_matrix_4fv(loc, &matrix); + } + + self.render_droplets(&self.gl, &self.drop_quad, &self.droplets); + } + + unsafe { + self.gl.BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA); + } + + self.frame_buffer.unbind(); + } + + // Merge pass + { + self.final_program.set_used(); + + self.black_color_buffer.set_used(&self.gl); + self.black_color_buffer.clear(&self.gl); + + if let Some(loc) = self.final_program.get_uniform_location("MVP") { + self.final_program.set_uniform_matrix_4fv(loc, &matrix); + } + + if let Some(loc) = self.final_program.get_uniform_location("Texture0") { + self.background_buffer.bind_at(0); + self.final_program.set_uniform_1i(loc, 0); + } + if let Some(loc) = self.final_program.get_uniform_location("Texture1") { + self.background_texture.bind_at(1); + self.final_program.set_uniform_1i(loc, 1); + } + if let Some(loc) = self.final_program.get_uniform_location("Mask") { + self.background_mask.bind_at(2); + self.final_program.set_uniform_1i(loc, 2); + } + + self.fullscreen_quad.render(&self.gl); + } + + { + self.drop_program.set_used(); + + if let Some(loc) = self.drop_program.get_uniform_location("Resolution") { + self.drop_program.set_uniform_2f(loc, &resolution); + } + + if let Some(loc) = self.drop_program.get_uniform_location("MVP") { + self.drop_program.set_uniform_matrix_4fv(loc, &matrix); + } + + if let Some(loc) = self.drop_program.get_uniform_location("Texture") { + self.background_texture.bind_at(0); + self.drop_program.set_uniform_1i(loc, 0); + } + + self.render_droplets(&self.gl, &self.drop_quad, &self.droplets); + } + } + + fn render_droplets(&self, gl: &gl::Gl, quad: &Quad, droplets: &Droplets) { + quad.vao.bind(); + + let instance_vbo: ArrayBuffer = ArrayBuffer::new(&gl); + instance_vbo.bind(); + + let offsets: Vec> = droplets + .into_iter() + .filter(|d| !d.deleted) + .map(|d| na::Vector3::new(d.pos.x, d.pos.y, d.size)) + .collect(); + + instance_vbo.static_draw_data(&offsets); + + unsafe { + gl.EnableVertexAttribArray(3); + gl.VertexAttribPointer( + 3, + 3, // the number of components per generic vertex attribute + gl::FLOAT, // data type + gl::FALSE, + std::mem::size_of::>() as gl::types::GLint, + 0 as *const gl::types::GLvoid, + ); + } + instance_vbo.unbind(); + + unsafe { + gl.VertexAttribDivisor(3, 1); + } + + unsafe { + gl.DrawElementsInstanced( + gl::TRIANGLES, + 6, + gl::UNSIGNED_BYTE, + ::std::ptr::null(), + offsets.len() as i32, + ); + } + quad.vao.unbind(); + } + + fn gravity_non_linear( + droplets: &mut Droplets, + world: &mut CollisionWorld, + rng: &mut ThreadRng, + dt: &Duration, + ) { + let fps = 1.0 / dt.as_secs_f32(); + let gravity_y = PRIVATE_GRAVITY_FORCE_FACTOR_Y * dt.as_secs_f32(); + + for i in 0..droplets.len() { + let mut delete_index: Option = None; + + { + let droplet = &mut droplets[i]; + + if droplet.deleted || droplet.size < DROPLET_SIZE_GRAVITY_THRESHOLD { + continue; + } + + if droplet.size < DROPLET_SIZE_GRAVITY_THRESHOLD && droplet.seed > 0 { + droplet.slowing = true; + } + + let movement_probability = 0.01 * dt.as_secs_f64(); + + if droplet.seed <= 0 { + droplet.seed = + (droplet.size * 0.5 * rng.gen_range(0.0, 1.0) * fps).floor() as i32; + droplet.skipping = droplet.skipping == false; + droplet.slowing = true; + } + + droplet.seed -= 1; + + assert!(droplet.size >= 1.0); + + if droplet.speed.y > 0.0 { + if droplet.slowing { + droplet.speed *= 0.9; + if droplet.speed.y < gravity_y { + droplet.slowing = false; + } + } else if droplet.skipping { + droplet.speed.y = gravity_y; + droplet.speed.x = PRIVATE_GRAVITY_FORCE_FACTOR_X; + } else { + droplet.speed.y += gravity_y * droplet.size; + droplet.speed.x += PRIVATE_GRAVITY_FORCE_FACTOR_X * droplet.size; + } + } else if rng.gen_bool((1.0 - 1.0 / droplet.size as f64) * movement_probability) { + droplet.speed.y = gravity_y; + droplet.speed.x = PRIVATE_GRAVITY_FORCE_FACTOR_X; + } + + // if this.options.gravityAngleVariance != 0 { + // droplet.x_speed += + // (rnd.gen() * 2 - 1) * droplet.y_speed * this.options.gravityAngleVariance + // } + + droplet.pos.y -= droplet.speed.y; + droplet.pos.x += droplet.speed.x; + + if droplet.pos.y + droplet.size * 0.5 < 0.0 { + delete_index = Some(i); + + world.remove(&[droplet.collision_handle]); + } else if droplet.speed.x != 0.0 || droplet.speed.y != 0.0 { + let handle = droplet.collision_handle; + + let object = world.get_mut(handle).unwrap(); + + object.set_position(Isometry2::new(droplet.pos.clone_owned(), na::zero())); + } + } + + if let Some(delete_index) = delete_index { + droplets.free(delete_index); + } + } + + world.update(); + } + + fn trail( + droplets: &mut Droplets, + world: &mut CollisionWorld, + rng: &mut ThreadRng, + collision_group: &CollisionGroups, + contacts_query: &GeometricQueryType, + dt: &Duration, + ) { + let gravity_y = PRIVATE_GRAVITY_FORCE_FACTOR_Y * dt.as_secs_f32(); + + for i in 0..droplets.len() { + let pos; + let size; + + { + let droplet = &mut droplets[i]; + + if droplet.speed.y <= gravity_y { + continue; + } + + if droplet.size >= 6.0 + && (droplet.last_trail_y.is_none() + || (droplet.last_trail_y.unwrap_or(0.0) - droplet.pos.y) + >= rng.gen_range(0.1, 1.0) * 200.0) + { + droplet.last_trail_y = Some(droplet.pos.y); + + size = rng.gen_range(0.9, 1.1) * droplet.size * 0.25; + pos = Vector2::new( + droplet.pos.x + rng.gen_range(-1.0, 1.0), + droplet.pos.y + droplet.size * 0.5 + droplet.speed.y + size * 0.5, + ); + + droplet.size = + ((droplet.size * 0.5).powf(3.0) - (size * 0.5).powf(3.0)).cbrt() * 2.0; + + if let Some(droplet_collision) = world.get_mut(droplet.collision_handle) { + droplet_collision.set_shape(ShapeHandle::new(Ball::new(droplet.size * 0.5))) + } + } else { + continue; + } + } + + if let Some((i, d)) = droplets.checkout() { + d.pos = pos; + d.size = size; + + let shape_handle = ShapeHandle::new(Ball::new(d.size * 0.5)); + + let handle = world + .add( + Isometry2::new(d.pos.clone_owned(), na::zero()), + shape_handle, + *collision_group, + *contacts_query, + i, + ) + .0; + + d.collision_handle = handle; + } + } + } +}