Compare commits
971 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 23e722a9fb | |||
| 27fbd896f7 | |||
| 2b698ca8b0 | |||
| 3e945fbe34 | |||
| 6821e3c370 | |||
| d11a9d4d8f | |||
| 3ed55c89f0 | |||
| 9381d0f5f1 | |||
| a7a6dc7671 | |||
| 02856273ad | |||
| 8ba1affe9e | |||
| ba2b7939a3 | |||
| 7739078aad | |||
| 851c6d972c | |||
| 3410bd5380 | |||
| dc0f77ae2a | |||
| 3e73f40c0f | |||
| 28c0552e0a | |||
| 9857fb12c4 | |||
| 5b31a8222c | |||
| 1eacb36256 | |||
| eabab8301d | |||
| 20331bc858 | |||
| 6387e87a30 | |||
| 08d08133c1 | |||
| 0d422ec169 | |||
| c5dd3674c1 | |||
| cf0a16e875 | |||
| 841a336581 | |||
| b2729e35c2 | |||
| 698ce4c0ce | |||
| df07529f21 | |||
| bc7660fbf8 | |||
| 857b7e522f | |||
| af9962c30f | |||
| a7e29c5784 | |||
| 3a03fe5f7f | |||
| f1eebd3835 | |||
| 40ed499889 | |||
| 55155630ca | |||
| 3bfeb1db76 | |||
| b2d041c9b3 | |||
| e5ab536db4 | |||
| 0dafa2f562 | |||
| 5ab554f61c | |||
| 8a725ec243 | |||
| cd1f57b634 | |||
| c47db14c83 | |||
| 81305a10cf | |||
| a58645da0f | |||
| 27400cffe4 | |||
| 5b1c5824c8 | |||
| 3e080c44c6 | |||
| eff5d0899d | |||
| 9a17f2141b | |||
| d073a13f57 | |||
| 7e622a69a6 | |||
| 6001eb88fa | |||
| 1610af3f3f | |||
| 60e926a62f | |||
| ecc055d8b8 | |||
| 2622482b12 | |||
| ca6a075d8c | |||
| ca3d4a84ad | |||
| 6eec0b396d | |||
| e7edb9d38c | |||
| 2f42321551 | |||
| 98da5525f3 | |||
| 20f9bdc209 | |||
| 93f23af92e | |||
| d8a4814542 | |||
| 6c37673787 | |||
| 77f9716932 | |||
| ece77065ca | |||
| 15186cafe0 | |||
| b35795f1ff | |||
| d667084d11 | |||
| f8d6f8ffb5 | |||
| a3ca6b0dca | |||
| 2524d93f6b | |||
| 9581f7b10e | |||
| 2abb215034 | |||
| 12fd7274a9 | |||
| 7456bf38f7 | |||
| d85a020971 | |||
| 6f83330321 | |||
| 0a7f2fc043 | |||
| c32e869c56 | |||
| 23d38fc387 | |||
| 6d2092f9e8 | |||
| 0754434295 | |||
| 732f74e5c9 | |||
| 7de7c8806e | |||
| ebf2b0a2f3 | |||
| 97fd733c3e | |||
| c191815b82 | |||
| 7cf464aabb | |||
| 1a8456ea57 | |||
| 4847479dae | |||
| dbe5886ffe | |||
| 16a4b0dd8a | |||
| 0be815cddd | |||
| 9f79d0e3c4 | |||
| d3bdc3cf8b | |||
| 5c495b987b | |||
| 2b741cae58 | |||
| 44fc1f9d05 | |||
| 6982997a2b | |||
| de2db94b85 | |||
| 3f230415c4 | |||
| b79f090364 | |||
| 9db2feb674 | |||
| 624d24d209 | |||
| 3dbbcc3a8c | |||
| 2c0520cc9d | |||
| c0d0083cc2 | |||
| 934258aadb | |||
| 16f81cc184 | |||
| e8c9856665 | |||
| fad1e6fdfc | |||
| fcd86bccf5 | |||
| 319bee0838 | |||
| f92dd5d34a | |||
| d65ae8de96 | |||
| 39a6d0d292 | |||
| 78f8066d4d | |||
| b3e16a6b66 | |||
| cb96a87659 | |||
| 22812ad21e | |||
| a3eddd5b3b | |||
| e095b610fd | |||
| 851fd1a6d0 | |||
| 3bfb0e6cac | |||
| cec4db1531 | |||
| 1c140a5b0e | |||
| f413431667 | |||
| 160dfa5dc7 | |||
| 0d12ccef64 | |||
| 40a3fb96a2 | |||
| fac7c8aa6a | |||
| 7dd67b5ae3 | |||
| 59b975499f | |||
| 7010c52af3 | |||
| 29e06eb696 | |||
| 7ff5ebb45d | |||
| 54753a49ed | |||
| 4efd411045 | |||
| b5845d2e12 | |||
| f1b100841d | |||
| 8626350e5f | |||
| 4ae3fccfd9 | |||
| 255b2c85c8 | |||
| 8ef8b89fd5 | |||
| f70b116fcb | |||
| e0ae2984ae | |||
| 544a11562c | |||
| f688cd0c69 | |||
| f32ea92336 | |||
| 66c1b73635 | |||
| 759dc98737 | |||
| ac511cbadc | |||
| 7a12a6c280 | |||
| abe635ad9b | |||
| 960a122550 | |||
| 922201d1c0 | |||
| 5c171c8b58 | |||
| 6a6eb96793 | |||
| 968f536cdb | |||
| 8078b9543d | |||
| 00842e89cb | |||
| 8c021b0252 | |||
| 56b0d885a6 | |||
| 1f7a7a5488 | |||
| 845da14e6a | |||
| a21f6d1b9f | |||
| 42366ee66a | |||
| 1940707b06 | |||
| c8b57d417c | |||
| fb70368c8d | |||
| 5af3a22fd0 | |||
| df497bf684 | |||
| 675bb93fd5 | |||
| 960268f756 | |||
| 92cfcbff8c | |||
| 0c74e2ff9d | |||
| f194004ebf | |||
| 30615e842d | |||
| c4d457d7b7 | |||
| 518df5e62b | |||
| e6d3242670 | |||
| 2a2d9f54de | |||
| 0122bf68bf | |||
| aa1c200bf8 | |||
| 8fb27e6f83 | |||
| 4eeadf87fb | |||
| a479f1daf6 | |||
| 691df4cb80 | |||
| 878fee505f | |||
| 1262243af9 | |||
| b9ca496aff | |||
| 1567f8723d | |||
| 3e56cd2c70 | |||
| bb6bbe9793 | |||
| ec7d892412 | |||
| 5cad37fa50 | |||
| 1d0faddd2a | |||
| fb28cae2b4 | |||
| 97ab226d7e | |||
| 4dbc770d75 | |||
| b151ab497f | |||
| 85ab871d48 | |||
| afea02d92f | |||
| b2c824b77e | |||
| 76e056698b | |||
| 1d575f51b6 | |||
| 3abea4ec23 | |||
| 146dffa732 | |||
| 54c10dd78d | |||
| c3c28413d7 | |||
| 802893a214 | |||
| 97e44aee61 | |||
| 3c5bbe5075 | |||
| 9ed0138a17 | |||
| bdd8242a0f | |||
| 2a8dc0ddba | |||
| ecb788b28a | |||
| 82a0039926 | |||
| 722861b929 | |||
| 1d6240aca5 | |||
| 437f7e6f9c | |||
| c18e5f522a | |||
| 544a043c56 | |||
| a2be4bb74a | |||
| 4d85a5ac3d | |||
| 8db1a9b9ca | |||
| b4dcaef61a | |||
| b04321bdd2 | |||
| a1a9dfa6a2 | |||
| 6b614d5d57 | |||
| 1eafae8888 | |||
| 03f4e78158 | |||
| ba75cabdda | |||
| cc5849100b | |||
| 6813cb607e | |||
| 74280b7411 | |||
| ee33c97db6 | |||
| d672826808 | |||
| 0bf4ab9cb6 | |||
| 84265322d5 | |||
| 7fbb008ddd | |||
| d06433deed | |||
| 7b02a4b33b | |||
| b7814e119b | |||
| 0db1f5e965 | |||
| 33e88acf90 | |||
| fcc0ca1772 | |||
| 4502d29710 | |||
| 81f3a65a5f | |||
| 044234a55b | |||
| 2f7a84822a | |||
| aa28f9ef52 | |||
| c1b9dc4b2e | |||
| fc13351a2b | |||
| 5f7830d09e | |||
| 30b71b9d65 | |||
| f0e737fd4b | |||
| 5de2998774 | |||
| 85c29c3d2b | |||
| 0a59c61100 | |||
| d9a516206c | |||
| cbe97ef3f0 | |||
| 77b21de534 | |||
| 400cc97100 | |||
| 2b42e9256c | |||
| 862c02da6a | |||
| 4795ffdf3d | |||
| 406db6704f | |||
| 7cb0ac3603 | |||
| b8d03636dc | |||
| 2e687edd99 | |||
| a82c669504 | |||
| 8f4d88d607 | |||
| 28fea66282 | |||
| 268db124d9 | |||
| 180efe86e6 | |||
| dd1dd2ef8a | |||
| dbc88af339 | |||
| 89c966fee6 | |||
| 9f4c916016 | |||
| 86f3007887 | |||
| 758f260574 | |||
| 2e17a94216 | |||
| 96cd3e560c | |||
| 1dee615d6e | |||
| dfb502621d | |||
| 06f3d68716 | |||
| d7bf276deb | |||
| 117008babd | |||
| 68991d1222 | |||
| d09bd12e5b | |||
| 4593e4c669 | |||
| 3cba76277b | |||
| a7d0853519 | |||
| e04f482e52 | |||
| ae3ce49b92 | |||
| 512df5f673 | |||
| 69a3587f5d | |||
| 9f1c55edce | |||
| 8ccb4f5857 | |||
| 9c80354acf | |||
| 835cb93261 | |||
| 2193dfcbc1 | |||
| 1deadf84b1 | |||
| 8a9f86705b | |||
| 111eaf1cf9 | |||
| d6b566a3fe | |||
| e218cc417f | |||
| 99bc3289e8 | |||
| 31d1932d55 | |||
| 8f633523cd | |||
| 21d96c6baf | |||
| 489e8ddc42 | |||
| 113fe30d5a | |||
| 0ccffb7691 | |||
| 8750b61221 | |||
| db921bad10 | |||
| e0c6f7e8b2 | |||
| b4e09a9d55 | |||
| dbec1389e8 | |||
| a7bb25b7d5 | |||
| 90e385c3c3 | |||
| ce45070d63 | |||
| 1be5815df3 | |||
| 51e62c7e9d | |||
| b3fdc9eddd | |||
| 08a428416c | |||
| aaecb6f7fd | |||
| eb1a520986 | |||
| 7ec57f8ddb | |||
| 957b92eac7 | |||
| 19bf30558b | |||
| a0740c162a | |||
| 98a753267f | |||
| 657de4b62c | |||
| a293265058 | |||
| a1e7f4f689 | |||
| a1e8056070 | |||
| 86ce671c0d | |||
| 16056a00e0 | |||
| 89538cb5cd | |||
| 39e41d8528 | |||
| 0d82be3ac8 | |||
| f999f337b5 | |||
| af792ff677 | |||
| fbecd01435 | |||
| 8d40ab5883 | |||
| 4972092150 | |||
| 3472daf97d | |||
| f939eec924 | |||
| ab77e5ef31 | |||
| 20edcdc64b | |||
| 93541b6ed5 | |||
| ca3948ad69 | |||
| 88db7c2d5f | |||
| 8857a7a0ae | |||
| 1d5f98a730 | |||
| 84015f78fc | |||
| 6cea33caea | |||
| 233bffdf63 | |||
| 3bc664df37 | |||
| 05eac5aeb6 | |||
| 26244df222 | |||
| c3e3e70f96 | |||
| cdf66372e6 | |||
| bcf86d9d9f | |||
| 86c1823d4a | |||
| f3c608f2f3 | |||
| 09f8ad948a | |||
| 8b4a001641 | |||
| b402232a47 | |||
| 327fa6718e | |||
| e1497bcfe2 | |||
| 0a54b9e77e | |||
| ff70c16051 | |||
| a45b71617d | |||
| ebfa3822ef | |||
| 0334329c50 | |||
| e1387e92a3 | |||
| 13cc6eb7b9 | |||
| 70b0aa25b6 | |||
| 69162ad8d9 | |||
| 9ed0ace01e | |||
| fd802e54fb | |||
| 9265f23681 | |||
| e9adaa7c87 | |||
| 27d53b69dc | |||
| 4d73b271b8 | |||
| 26607c1d09 | |||
| 5d2fe5908b | |||
| 43d578deb2 | |||
| 529a82234b | |||
| 6f12dc8567 | |||
| b193a7abc4 | |||
| d41daee94c | |||
| bcc036f808 | |||
| 3da6f9186c | |||
| 1dbbbeced1 | |||
| d4b2171c19 | |||
| 5d7940f784 | |||
| 6f3e7bc253 | |||
| e66045029f | |||
| bc1b666b83 | |||
| 4cc7ec0461 | |||
| 706c4bd677 | |||
| 6ec58664e4 | |||
| 463251a7fa | |||
| f688f3ce20 | |||
| a21d1a91fc | |||
| c0f81a6f0a | |||
| 84ee882439 | |||
| 5a9ca6f130 | |||
| cf3ac7a26e | |||
| 747a9bcb98 | |||
| 63a6b704df | |||
| e160d719a9 | |||
| 87a290b45c | |||
| 3387da92ed | |||
| 12725ca4e1 | |||
| 6f40c66b31 | |||
| 3ddd64df2a | |||
| 24d31d024d | |||
| d01365d416 | |||
| 19c83e3b6e | |||
| 81fa876940 | |||
| 7fd542950f | |||
| e4794c5754 | |||
| 9d35068514 | |||
| a2f01ba638 | |||
| 07f7fee4a8 | |||
| f3216a9c96 | |||
| 0a9e9e6695 | |||
| 7f5903584e | |||
| 1ead4b1649 | |||
| 279d168b35 | |||
| 09651fa0fd | |||
| 3844aceba1 | |||
| 170d018f88 | |||
| 4c587ce870 | |||
| 89734760fa | |||
| 00b3760fbd | |||
| 2498d1d4f2 | |||
| 2a3003101e | |||
| 35b687bf3d | |||
| 6683cb299e | |||
| e79321241c | |||
| d018478255 | |||
| f2dc7346ad | |||
| 919bd4ee1b | |||
| 8b3fc9842d | |||
| a1d4e50e98 | |||
| 506ce69f53 | |||
| 67dd80e40d | |||
| 9752bfabee | |||
| cfb02692df | |||
| 3bc99c0949 | |||
| 12c503646d | |||
| 1b234fd32b | |||
| 5bdf4dc74e | |||
| 15028c60ba | |||
| 3c603d7f09 | |||
| 07f680eed2 | |||
| 68f6e0251c | |||
| 8e0493ee97 | |||
| 085186cfff | |||
| 9454f96e0b | |||
| 1745984d5a | |||
| e98380e0fa | |||
| 68b4fdb9c3 | |||
| a4409c729b | |||
| 597a9c537d | |||
| ae44ef0a79 | |||
| fec787b96b | |||
| 22b798928a | |||
| 1fb07a01d2 | |||
| d87f0df2a6 | |||
| 694b20148d | |||
| ee76440477 | |||
| 74d4bb8dc6 | |||
| 20ba37e223 | |||
| 92fafe877c | |||
| 52bc268ee7 | |||
| 49a0d66bfe | |||
| e2590b5f11 | |||
| 8fe656b88f | |||
| 05d5fd4fec | |||
| cd7642eeec | |||
| b133539c40 | |||
| c475e83aa3 | |||
| 78c5644de0 | |||
| db3552509a | |||
| 3da17918aa | |||
| 2f0c96abe2 | |||
| 5de034f073 | |||
| 161e9bd373 | |||
| e176ea749c | |||
| da24a474ea | |||
| 09be8994e9 | |||
| d866526dd8 | |||
| 6d7bd78816 | |||
| 3964fc7795 | |||
| 9f80b9853c | |||
| 2f12e67356 | |||
| ce9df56a97 | |||
| cc980fd70d | |||
| fe1d1b20f8 | |||
| c86508ef57 | |||
| c25abfda65 | |||
| cc0fe5bc28 | |||
| 115d6e46a8 | |||
| 5a03ef8e89 | |||
| 4aabb81c1f | |||
| bdfdb422fa | |||
| 81bb322fd2 | |||
| 915ac0122f | |||
| 7b0717094b | |||
| 64d7684551 | |||
| 431c21caa8 | |||
| d1f30a973d | |||
| 94381f356c | |||
| 0be22bf4b6 | |||
| 4ec2381716 | |||
| 4408e3bb3b | |||
| af0fb6c6fa | |||
| dc352edce7 | |||
| 74823a8bcf | |||
| 32c5a84576 | |||
| 161917977c | |||
| 9ee6104706 | |||
| 96846ea255 | |||
| f8290ea0c1 | |||
| 5507fea29d | |||
| 18095d5adc | |||
| f50022e88e | |||
| 0b54691f07 | |||
| 7ad64d0284 | |||
| 978ee84aea | |||
| 580e08b6ab | |||
| 88b575539a | |||
| c8a70ffda6 | |||
| 2609f9c21a | |||
| 622e608d76 | |||
| cd0a1a5fdd | |||
| ed04eece8a | |||
| cae0b5e91e | |||
| 1c1e9bb105 | |||
| d88335c51f | |||
| 62bfc94f24 | |||
| d896f4f699 | |||
| 57e4831a5f | |||
| d6546fb41c | |||
| 7cc5560adf | |||
| 25f61e931e | |||
| 654285e57f | |||
| bcc3b2bd59 | |||
| 6fd1580d67 | |||
| fc4dc8cb50 | |||
| 489672d346 | |||
| 1c5b779ae9 | |||
| bc229d0bb6 | |||
| c7894d7e54 | |||
| f4a587faf9 | |||
| 9144f6dcc9 | |||
| bc073b73cc | |||
| 588ad86f8e | |||
| 1530f91944 | |||
| d05204cb91 | |||
| c902e33d8a | |||
| 28a67f65b4 | |||
| f66b7ff785 | |||
| b742d0c326 | |||
| a98f867bd8 | |||
| 5f04f32097 | |||
| 3658611e0f | |||
| 537dde594d | |||
| 7221f7167f | |||
| fa332a3785 | |||
| 653e9609e4 | |||
| f11686a7b7 | |||
| 0841f5b479 | |||
| 81be73ad82 | |||
| 44afa732f1 | |||
| 26e3400a92 | |||
| a2e1346029 | |||
| bc6281ee63 | |||
| 134aec2d15 | |||
| b1f867f107 | |||
| 674e09e72b | |||
| 6987834b2d | |||
| 4e19b85e00 | |||
| 5714741a5d | |||
| cdd68c9a89 | |||
| 29f0834cc4 | |||
| 788907f3b1 | |||
| b6557cb15c | |||
| cd2a02a5c8 | |||
| c9ea812a24 | |||
| e42a6b0ccc | |||
| 312e4ad010 | |||
| 2357b60d0e | |||
| 3e608e6dec | |||
| 9cccdc1e89 | |||
| 025ae99901 | |||
| c68e3af566 | |||
| ff44622624 | |||
| da943f7604 | |||
| b4bf488e3c | |||
| f82ef8c065 | |||
| 865f2b871d | |||
| a947dc0cc3 | |||
| 17a738d2ce | |||
| a9ac758abd | |||
| 3bbda838a2 | |||
| 6bdc31df5a | |||
| ed1a3c2964 | |||
| a485622c2a | |||
| ac8c185056 | |||
| ccc60af4b6 | |||
| 311793dd7e | |||
| bd5897eaab | |||
| 55194edd2c | |||
| 8661091337 | |||
| 34b6cfebc3 | |||
| 74c1ac89c8 | |||
| 4dd8e19f79 | |||
| 9fd5e8928c | |||
| 17d0f40e1c | |||
| 0e78d13146 | |||
| 80e2aee92b | |||
| 5a23df6478 | |||
| 62acae10a5 | |||
| 04b650cbc3 | |||
| 4ba82047e0 | |||
| 49758fbfff | |||
| 8158c94d26 | |||
| 4c673bec9b | |||
| 2263b3db52 | |||
| 3a3c66b916 | |||
| 6c253ce892 | |||
| 29521b1b03 | |||
| 8bce445ab0 | |||
| 5cb2322270 | |||
| 81e41d51c8 | |||
| adbb467206 | |||
| 191694725a | |||
| 73efa35008 | |||
| b8420feed1 | |||
| cad7887957 | |||
| 01f2cc1dcc | |||
| 6906db499e | |||
| 8fe04d6db4 | |||
| 4ce6882fc0 | |||
| dc63d908b8 | |||
| 6673d70d0a | |||
| cb6b96dea6 | |||
| 042694f45e | |||
| d4f959b681 | |||
| 15c4b7df54 | |||
| 311dad7b82 | |||
| 2b962e4389 | |||
| 05a7b911f1 | |||
| e8dc48690e | |||
| be7024784e | |||
| b30ab38ef2 | |||
| dfe7963436 | |||
| 034890ee7c | |||
| 58350c87e2 | |||
| c9860f21ec | |||
| 85167b2d4b | |||
| 8e87c98644 | |||
| da784e98e5 | |||
| 20d9c7181f | |||
| 8f8f0266ce | |||
| c7feeb624d | |||
| 57f9e42486 | |||
| 103d630d80 | |||
| 2f34bfbeff | |||
| 57fab6a7f7 | |||
| 2325de3ddc | |||
| 96f1d9e820 | |||
| 04bb83fe31 | |||
| 5768eefe49 | |||
| 8c1f56b7db | |||
| 9f3be80f9c | |||
| 6ea897b0f5 | |||
| f9deb97229 | |||
| f5b48e03e9 | |||
| ca6afc0c2d | |||
| 08abc798cc | |||
| 0f4edbcc6f | |||
| 5529bd7bc0 | |||
| 0242e29873 | |||
| a246825b3d | |||
| 8d3f4aa9d9 | |||
| 6e5a13111a | |||
| 9ddb077e7c | |||
| 46b15551b4 | |||
| 522e1eb769 | |||
| 633357cc9b | |||
| 5cb0da3340 | |||
| 25f35b22be | |||
| f5d1ad5a9b | |||
| 5b32756536 | |||
| 8a567f0849 | |||
| d27edbf5a9 | |||
| 1e811324eb | |||
| 42393eb316 | |||
| 6b660c846b | |||
| 43692f514a | |||
| 78e4ba2f17 | |||
| 2fbfe61f2c | |||
| 0e57b32082 | |||
| 5a561b1278 | |||
| d8304a2178 | |||
| 300f948515 | |||
| 2da9ed4556 | |||
| 089f0dab3a | |||
| 01777a2c1b | |||
| 3661b19d6c | |||
| db55f5ea3f | |||
| ae785267c2 | |||
| 7868c6505d | |||
| b5847eb0d6 | |||
| 9e6243adcc | |||
| 2a3b6edf50 | |||
| 7e612d89cb | |||
| 21b311df17 | |||
| 880a8c9f58 | |||
| e3142e6408 | |||
| 4949ea4b3b | |||
| 9c348b284f | |||
| 85c219369d | |||
| 6ffa497c0a | |||
| ba0f07b57e | |||
| a572e581e5 | |||
| c3b36062ed | |||
| 8e4a0e9e97 | |||
| a560b19cbc | |||
| 28f53339e7 | |||
| 0c17ca82b7 | |||
| f048254d82 | |||
| fb74aef541 | |||
| 81cc8cf69c | |||
| 00fab5cfd6 | |||
| 85a6f485f1 | |||
| d2dba5680b | |||
| c00b32364a | |||
| 23652d1bc5 | |||
| 5d535fad6a | |||
| 1a11f1a231 | |||
| 107edfb958 | |||
| 2fe6129fcd | |||
| 7ddcf8507a | |||
| 1aab96676d | |||
| 1bd639c86d | |||
| 62f2ccb942 | |||
| e2cefc7407 | |||
| efea842486 | |||
| 1ae898918c | |||
| c3d9c52f1f | |||
| b22805f866 | |||
| d69b005792 | |||
| 69790f3576 | |||
| bab236c081 | |||
| bf80827bfd | |||
| 283714a39f | |||
| fecf7d7804 | |||
| 011b5f3e51 | |||
| 5c2d3cbe7b | |||
| f2ac6a970c | |||
| ed10c15069 | |||
| f77d0cc8fc | |||
| d059027a47 | |||
| 7fca8ae4bb | |||
| 28d16fd620 | |||
| bc6de6932b | |||
| e75ca148c0 | |||
| a5d6db6a18 | |||
| 33ce17c3fa | |||
| bd18286fbd | |||
| 7c85ac61b8 | |||
| 9cdbbf590a | |||
| bd93e46624 | |||
| f0c7fbb0cf | |||
| 560b6cf5da | |||
| c0e8b735ad | |||
| 5a402df3ff | |||
| 3dc6afef62 | |||
| 590fcebaec | |||
| 37e3a85080 | |||
| fd96957819 | |||
| d0c0259ee2 | |||
| 53601d8a85 | |||
| 1d19d38c38 | |||
| cd2ae08da0 | |||
| a876e56339 | |||
| c8b0773661 | |||
| 5f85e9ae96 | |||
| 09049990bd | |||
| 674d1fbcc5 | |||
| 254bdacc73 | |||
| 0c68cd8a10 | |||
| c20f0fa430 | |||
| 54b9eaa969 | |||
| aaac0aec96 | |||
| af1dfc0d08 | |||
| 15d24308e8 | |||
| 8ac0e7491a | |||
| 2bcbf23bca | |||
| 01a3a80103 | |||
| 2119075240 | |||
| 1df47bd8c5 | |||
| a51d47a4bb | |||
| 1b2dd0aff5 | |||
| ecb20afaa4 | |||
| 45ba154877 | |||
| 51a2c1e868 | |||
| 8180877269 | |||
| aa2eeb8243 | |||
| 937248794a | |||
| b674aae970 | |||
| dda5f26d89 | |||
| 023cdced0a | |||
| 029d9acaa2 | |||
| bbabd09983 | |||
| 67a8246077 | |||
| 330a588260 | |||
| 8e2a8c045c | |||
| a32658beea | |||
| c2af9164d6 | |||
| 27a62f4411 | |||
| 6dd699cbab | |||
| 206461e80e | |||
| 5bc1773dc5 | |||
| baa273f589 | |||
| dae366f04c | |||
| 075b049bb1 | |||
| fe78fa7575 | |||
| 6ef65734cd | |||
| ad621b824a | |||
| 6e193d4d0d | |||
| b4f791e0ca | |||
| 9b2c940896 | |||
| 3ab54bd7e1 | |||
| 9b300fe074 | |||
| 86b5fa9321 | |||
| 261aeb9245 | |||
| b3388d6fc7 | |||
| c9bab2c521 | |||
| 4a71fe6727 | |||
| 3250ca9fad | |||
| c9655eee8f | |||
| 54da2c8de0 | |||
| 3c1a69eb6f | |||
| a60e1ab8bb | |||
| c53fe681f5 | |||
| 125b4347da | |||
| aa97296123 | |||
| d76c167ad9 | |||
| 6cbeac6537 | |||
| cbbfb16628 | |||
| 4042d466d3 | |||
| c2f745397a | |||
| a4763f630e | |||
| 178f0b9e3a | |||
| d93a2803cc | |||
| 57d7508e25 | |||
| 9ae79b8307 | |||
| f8bf87e0b1 | |||
| ef240ce986 | |||
| e58332723a | |||
| 81daaf663b | |||
| a9e4d6d908 | |||
| 5f7f53304d | |||
| 3e0b753498 | |||
| 4bd76b70f2 | |||
| d19c31555b | |||
| e0f1f18998 | |||
| f80c33f381 | |||
| 2bfcc15f66 | |||
| fdc8e371c4 | |||
| ba050b9eaa | |||
| c1216a4318 | |||
| 2ae78b9afd | |||
| f33a2d8fe5 | |||
| 1943de62e9 | |||
| fcc4b371b9 | |||
| 837174582b | |||
| 6b0d34a21d | |||
| 01a30faa62 | |||
| 070faf12da | |||
| 65d3883f03 | |||
| 2c2c1af97f | |||
| d7949b5405 | |||
| f8624ae768 | |||
| 98d272a903 | |||
| 00c40e279c | |||
| 7835259a83 | |||
| 93aa265b20 | |||
| 8e44e6b23c | |||
| 437018e614 | |||
| 75c3388c00 | |||
| 31dd5b852e | |||
| 6649f0d4c2 | |||
| 604c583c36 | |||
| b2a2652b56 | |||
| af692605ab | |||
| d1a282e228 | |||
| 88bddfb141 | |||
| 29c3e2d54b | |||
| 27ed23c1b9 | |||
| 783b910700 | |||
| dba43c4e9f | |||
| eaba489ba2 | |||
| 40c7fe3f77 | |||
| a6d5fb318a | |||
| d20cbf434f | |||
| 45211fa61c | |||
| f8feccc27d | |||
| 0dc9d3a59a | |||
| 7bbf089e9f | |||
| 8d7d2431df | |||
| 09720ee758 | |||
| ee1b7bad56 | |||
| c7547b3a46 | |||
| d2888d0007 | |||
| efa5d05f5f | |||
| 153cfad507 | |||
| d7224670c5 | |||
| 31bab88a5b | |||
| 1e383fde5c | |||
| f5b9a95522 | |||
| 199683897a | |||
| be319c446d | |||
| cc8e78b505 | |||
| b38ccb0fbd | |||
| 953f8da84d | |||
| cd8a27ca26 | |||
| c5568c8eae | |||
| 8dc5b11f51 | |||
| e4936547e3 | |||
| 429b71b63f | |||
| 969367dc3e | |||
| e242dbf89f | |||
| ce6c360d29 | |||
| 07fb8e034f | |||
| 16cd75d179 | |||
| 4665e8fbdb | |||
| f25064fae8 | |||
| 5e77925492 | |||
| 7798a7f6d5 | |||
| 41b938b3cd | |||
| 4d2d801bf4 | |||
| cea1a67749 | |||
| aa7711dc31 | |||
| 585c752d72 | |||
| 3a314d97eb | |||
| 0e6ead938e | |||
| 93c35a19f5 | |||
| a36a54adcd | |||
| 4c0c7cc394 | |||
| 4a79df860d |
@@ -1,19 +0,0 @@
|
||||
name: Build Linux
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
|
||||
# Game
|
||||
game-linux:
|
||||
name: Game (Linux, Release x64)
|
||||
runs-on: "ubuntu-20.04"
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v2
|
||||
- name: Checkout LFS
|
||||
run: |
|
||||
git lfs version
|
||||
git lfs pull
|
||||
- name: Build
|
||||
run: |
|
||||
./Development/Scripts/Linux/CallBuildTool.sh -build -log -arch=x64 -platform=Linux -configuration=Release -buildtargets=FlaxGame
|
||||
@@ -0,0 +1,40 @@
|
||||
name: Build Linux
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
|
||||
# Editor
|
||||
editor-linux:
|
||||
name: Editor (Linux, Development x64)
|
||||
runs-on: "ubuntu-20.04"
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v2
|
||||
- name: Checkout LFS
|
||||
run: |
|
||||
git lfs version
|
||||
git lfs pull
|
||||
- name: Build
|
||||
run: |
|
||||
./Development/Scripts/Linux/CallBuildTool.sh -build -log -arch=x64 -platform=Linux -configuration=Development -buildtargets=FlaxEditor
|
||||
|
||||
# Game
|
||||
game-linux:
|
||||
name: Game (Linux, Release x64)
|
||||
runs-on: "ubuntu-20.04"
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v2
|
||||
- name: Checkout LFS
|
||||
run: |
|
||||
git lfs version
|
||||
git lfs pull
|
||||
- name: Build
|
||||
run: |
|
||||
./Development/Scripts/Linux/CallBuildTool.sh -build -log -arch=x64 -platform=Linux -configuration=Release -buildtargets=FlaxGame
|
||||
+3
-40
@@ -7,7 +7,9 @@ Cache/
|
||||
Binaries/
|
||||
Logs/
|
||||
Source/*.csproj
|
||||
/Package_*/
|
||||
!Source/Engine/Debug
|
||||
/Source/Platforms/Editor/Linux/Mono/etc/mono/registry
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
@@ -22,11 +24,6 @@ Source/*.csproj
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# NuGet Packages Directory
|
||||
packages/**/*
|
||||
!packages/repositories.config
|
||||
@@ -56,9 +53,6 @@ packages/**/*
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
@@ -72,12 +66,6 @@ ipch/
|
||||
*.vsp
|
||||
*.vspx
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
@@ -100,9 +88,6 @@ _NCrunch_*
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
@@ -149,32 +134,9 @@ ClientBin/
|
||||
*.publishsettings
|
||||
node_modules/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project files
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# LightSwitch generated files
|
||||
GeneratedArtifacts/
|
||||
_Pvt_Extensions/
|
||||
ModelManifest.xml
|
||||
|
||||
# IDE files
|
||||
*.VC.db
|
||||
enc_temp_folder/
|
||||
@@ -185,3 +147,4 @@ obj/
|
||||
*.vcxproj.filters
|
||||
.vscode/
|
||||
*.code-workspace
|
||||
|
||||
|
||||
@@ -32,3 +32,19 @@ Go check out our [Trello](https://trello.com/b/NQjLXRCP/flax-roadmap).
|
||||
|
||||
|
||||
Thank you for taking interest in contributing to Flax!
|
||||
|
||||
## **Common issues**
|
||||
|
||||
Below are some common issues that someone working with the FlaxEngine source code might run into. Hopefully some of those issues will get fixed in the future. If you know how, please contribute!
|
||||
|
||||
* Missing MSVC toolset
|
||||
* Install it through the Visual Studio Installer
|
||||
* Building or attaching fails
|
||||
* Run `GenerateProjectFiles.bat`
|
||||
* Rebuild `Flax.Build`
|
||||
* Make sure that there isn't a stray FlaxEngine process running in the background
|
||||
* First start Flax and then attach the C# debugger
|
||||
* Configure the C# FlaxEngine project by going into the project properties, then the debug tab and selecting "Start external program" `Flax\FlaxEngine\Binaries\Editor\Win64\Debug\FlaxEditor.exe`
|
||||
* Then you can also set command line arguments such as `-project "C:\Users\PROFILE\Documents\Flax Projects\FlaxSamples\BasicTemplate"`
|
||||
* Git LFS
|
||||
* Push with `git push --no-verify`
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -108,15 +108,14 @@ float4 GetVertexColor(MaterialInput input)
|
||||
return 1;
|
||||
}
|
||||
|
||||
@8
|
||||
|
||||
// Get material properties function (for pixel shader)
|
||||
Material GetMaterialPS(MaterialInput input)
|
||||
{
|
||||
@4
|
||||
}
|
||||
|
||||
// Fix line for errors/warnings for shader code from template
|
||||
#line 1000
|
||||
|
||||
// Input macro specified by the material: DECAL_BLEND_MODE
|
||||
|
||||
#define DECAL_BLEND_MODE_TRANSLUCENT 0
|
||||
@@ -211,3 +210,5 @@ void PS_Decal(
|
||||
#error "Invalid decal blending mode"
|
||||
#endif
|
||||
}
|
||||
|
||||
@9
|
||||
|
||||
@@ -0,0 +1,377 @@
|
||||
// File generated by Flax Materials Editor
|
||||
// Version: @0
|
||||
|
||||
#define MATERIAL 1
|
||||
@3
|
||||
#include "./Flax/Common.hlsl"
|
||||
#include "./Flax/MaterialCommon.hlsl"
|
||||
#include "./Flax/GBufferCommon.hlsl"
|
||||
@7
|
||||
// Primary constant buffer (with additional material parameters)
|
||||
META_CB_BEGIN(0, Data)
|
||||
float4x4 ViewProjectionMatrix;
|
||||
float4x4 WorldMatrix;
|
||||
float4x4 LocalMatrix;
|
||||
float4x4 ViewMatrix;
|
||||
float3 ViewPos;
|
||||
float ViewFar;
|
||||
float3 ViewDir;
|
||||
float TimeParam;
|
||||
float4 ViewInfo;
|
||||
float4 ScreenSize;
|
||||
float3 Dummy0;
|
||||
float WorldDeterminantSign;
|
||||
float MeshMinZ;
|
||||
float Segment;
|
||||
float ChunksPerSegment;
|
||||
float PerInstanceRandom;
|
||||
float4 TemporalAAJitter;
|
||||
float3 GeometrySize;
|
||||
float MeshMaxZ;
|
||||
@1META_CB_END
|
||||
|
||||
// Shader resources
|
||||
@2
|
||||
// The spline deformation buffer (stored as 4x3, 3 float4 behind each other)
|
||||
Buffer<float4> SplineDeformation : register(t0);
|
||||
|
||||
// Geometry data passed though the graphics rendering stages up to the pixel shader
|
||||
struct GeometryData
|
||||
{
|
||||
float3 WorldPosition : TEXCOORD0;
|
||||
float2 TexCoord : TEXCOORD1;
|
||||
#if USE_VERTEX_COLOR
|
||||
half4 VertexColor : COLOR;
|
||||
#endif
|
||||
float3 WorldNormal : TEXCOORD2;
|
||||
float4 WorldTangent : TEXCOORD3;
|
||||
};
|
||||
|
||||
// Interpolants passed from the vertex shader
|
||||
struct VertexOutput
|
||||
{
|
||||
float4 Position : SV_Position;
|
||||
GeometryData Geometry;
|
||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||
float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9;
|
||||
#endif
|
||||
#if USE_TESSELLATION
|
||||
float TessellationMultiplier : TESS;
|
||||
#endif
|
||||
};
|
||||
|
||||
// Interpolants passed to the pixel shader
|
||||
struct PixelInput
|
||||
{
|
||||
float4 Position : SV_Position;
|
||||
GeometryData Geometry;
|
||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||
float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9;
|
||||
#endif
|
||||
bool IsFrontFace : SV_IsFrontFace;
|
||||
};
|
||||
|
||||
// Material properties generation input
|
||||
struct MaterialInput
|
||||
{
|
||||
float3 WorldPosition;
|
||||
float TwoSidedSign;
|
||||
float2 TexCoord;
|
||||
#if USE_VERTEX_COLOR
|
||||
half4 VertexColor;
|
||||
#endif
|
||||
float3x3 TBN;
|
||||
float4 SvPosition;
|
||||
float3 PreSkinnedPosition;
|
||||
float3 PreSkinnedNormal;
|
||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||
float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT];
|
||||
#endif
|
||||
};
|
||||
|
||||
// Extracts geometry data to the material input
|
||||
MaterialInput GetGeometryMaterialInput(GeometryData geometry)
|
||||
{
|
||||
MaterialInput output = (MaterialInput)0;
|
||||
output.WorldPosition = geometry.WorldPosition;
|
||||
output.TexCoord = geometry.TexCoord;
|
||||
#if USE_VERTEX_COLOR
|
||||
output.VertexColor = geometry.VertexColor;
|
||||
#endif
|
||||
output.TBN = CalcTangentBasis(geometry.WorldNormal, geometry.WorldTangent);
|
||||
return output;
|
||||
}
|
||||
|
||||
#if USE_TESSELLATION
|
||||
|
||||
// Interpolates the geometry positions data only (used by the tessallation when generating vertices)
|
||||
#define InterpolateGeometryPositions(output, p0, w0, p1, w1, p2, w2, offset) output.WorldPosition = p0.WorldPosition * w0 + p1.WorldPosition * w1 + p2.WorldPosition * w2 + offset
|
||||
|
||||
// Offsets the geometry positions data only (used by the tessallation when generating vertices)
|
||||
#define OffsetGeometryPositions(geometry, offset) geometry.WorldPosition += offset
|
||||
|
||||
// Applies the Phong tessallation to the geometry positions (used by the tessallation when doing Phong tess)
|
||||
#define ApplyGeometryPositionsPhongTess(geometry, p0, p1, p2, U, V, W) \
|
||||
float3 posProjectedU = TessalationProjectOntoPlane(p0.WorldNormal, p0.WorldPosition, geometry.WorldPosition); \
|
||||
float3 posProjectedV = TessalationProjectOntoPlane(p1.WorldNormal, p1.WorldPosition, geometry.WorldPosition); \
|
||||
float3 posProjectedW = TessalationProjectOntoPlane(p2.WorldNormal, p2.WorldPosition, geometry.WorldPosition); \
|
||||
geometry.WorldPosition = U * posProjectedU + V * posProjectedV + W * posProjectedW
|
||||
|
||||
// Interpolates the geometry data except positions (used by the tessallation when generating vertices)
|
||||
GeometryData InterpolateGeometry(GeometryData p0, float w0, GeometryData p1, float w1, GeometryData p2, float w2)
|
||||
{
|
||||
GeometryData output = (GeometryData)0;
|
||||
output.TexCoord = p0.TexCoord * w0 + p1.TexCoord * w1 + p2.TexCoord * w2;
|
||||
#if USE_VERTEX_COLOR
|
||||
output.VertexColor = p0.VertexColor * w0 + p1.VertexColor * w1 + p2.VertexColor * w2;
|
||||
#endif
|
||||
output.WorldNormal = p0.WorldNormal * w0 + p1.WorldNormal * w1 + p2.WorldNormal * w2;
|
||||
output.WorldNormal = normalize(output.WorldNormal);
|
||||
output.WorldTangent = p0.WorldTangent * w0 + p1.WorldTangent * w1 + p2.WorldTangent * w2;
|
||||
output.WorldTangent.xyz = normalize(output.WorldTangent.xyz);
|
||||
return output;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
MaterialInput GetMaterialInput(PixelInput input)
|
||||
{
|
||||
MaterialInput output = GetGeometryMaterialInput(input.Geometry);
|
||||
output.TwoSidedSign = WorldDeterminantSign * (input.IsFrontFace ? 1.0 : -1.0);
|
||||
output.SvPosition = input.Position;
|
||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||
output.CustomVSToPS = input.CustomVSToPS;
|
||||
#endif
|
||||
return output;
|
||||
}
|
||||
|
||||
// Removes the scale vector from the local to world transformation matrix
|
||||
float3x3 RemoveScaleFromLocalToWorld(float3x3 localToWorld)
|
||||
{
|
||||
// Extract per axis scales from localToWorld transform
|
||||
float scaleX = length(localToWorld[0]);
|
||||
float scaleY = length(localToWorld[1]);
|
||||
float scaleZ = length(localToWorld[2]);
|
||||
float3 invScale = float3(
|
||||
scaleX > 0.00001f ? 1.0f / scaleX : 0.0f,
|
||||
scaleY > 0.00001f ? 1.0f / scaleY : 0.0f,
|
||||
scaleZ > 0.00001f ? 1.0f / scaleZ : 0.0f);
|
||||
localToWorld[0] *= invScale.x;
|
||||
localToWorld[1] *= invScale.y;
|
||||
localToWorld[2] *= invScale.z;
|
||||
return localToWorld;
|
||||
}
|
||||
|
||||
// Transforms a vector from tangent space to world space
|
||||
float3 TransformTangentVectorToWorld(MaterialInput input, float3 tangentVector)
|
||||
{
|
||||
return mul(tangentVector, input.TBN);
|
||||
}
|
||||
|
||||
// Transforms a vector from world space to tangent space
|
||||
float3 TransformWorldVectorToTangent(MaterialInput input, float3 worldVector)
|
||||
{
|
||||
return mul(input.TBN, worldVector);
|
||||
}
|
||||
|
||||
// Transforms a vector from world space to view space
|
||||
float3 TransformWorldVectorToView(MaterialInput input, float3 worldVector)
|
||||
{
|
||||
return mul(worldVector, (float3x3)ViewMatrix);
|
||||
}
|
||||
|
||||
// Transforms a vector from view space to world space
|
||||
float3 TransformViewVectorToWorld(MaterialInput input, float3 viewVector)
|
||||
{
|
||||
return mul((float3x3)ViewMatrix, viewVector);
|
||||
}
|
||||
|
||||
// Transforms a vector from local space to world space
|
||||
float3 TransformLocalVectorToWorld(MaterialInput input, float3 localVector)
|
||||
{
|
||||
float3x3 localToWorld = (float3x3)WorldMatrix;
|
||||
//localToWorld = RemoveScaleFromLocalToWorld(localToWorld);
|
||||
return mul(localVector, localToWorld);
|
||||
}
|
||||
|
||||
// Transforms a vector from local space to world space
|
||||
float3 TransformWorldVectorToLocal(MaterialInput input, float3 worldVector)
|
||||
{
|
||||
float3x3 localToWorld = (float3x3)WorldMatrix;
|
||||
//localToWorld = RemoveScaleFromLocalToWorld(localToWorld);
|
||||
return mul(localToWorld, worldVector);
|
||||
}
|
||||
|
||||
// Gets the current object position
|
||||
float3 GetObjectPosition(MaterialInput input)
|
||||
{
|
||||
return WorldMatrix[3].xyz;
|
||||
}
|
||||
|
||||
// Gets the current object size
|
||||
float3 GetObjectSize(MaterialInput input)
|
||||
{
|
||||
float4x4 world = WorldMatrix;
|
||||
return GeometrySize * float3(world._m00, world._m11, world._m22);
|
||||
}
|
||||
|
||||
// Get the current object random value
|
||||
float GetPerInstanceRandom(MaterialInput input)
|
||||
{
|
||||
return PerInstanceRandom;
|
||||
}
|
||||
|
||||
// Get the current object LOD transition dither factor
|
||||
float GetLODDitherFactor(MaterialInput input)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Gets the interpolated vertex color (in linear space)
|
||||
float4 GetVertexColor(MaterialInput input)
|
||||
{
|
||||
#if USE_VERTEX_COLOR
|
||||
return input.VertexColor;
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
float3 SampleLightmap(Material material, MaterialInput materialInput)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@8
|
||||
|
||||
// Get material properties function (for vertex shader)
|
||||
Material GetMaterialVS(MaterialInput input)
|
||||
{
|
||||
@5
|
||||
}
|
||||
|
||||
// Get material properties function (for domain shader)
|
||||
Material GetMaterialDS(MaterialInput input)
|
||||
{
|
||||
@6
|
||||
}
|
||||
|
||||
// Get material properties function (for pixel shader)
|
||||
Material GetMaterialPS(MaterialInput input)
|
||||
{
|
||||
@4
|
||||
}
|
||||
|
||||
// Calculates the transform matrix from mesh tangent space to local space
|
||||
float3x3 CalcTangentToLocal(ModelInput input)
|
||||
{
|
||||
float bitangentSign = input.Tangent.w ? -1.0f : +1.0f;
|
||||
float3 normal = input.Normal.xyz * 2.0 - 1.0;
|
||||
float3 tangent = input.Tangent.xyz * 2.0 - 1.0;
|
||||
float3 bitangent = cross(normal, tangent) * bitangentSign;
|
||||
return float3x3(tangent, bitangent, normal);
|
||||
}
|
||||
|
||||
// Vertex Shader function for GBuffer Pass and Depth Pass (with full vertex data)
|
||||
META_VS(true, FEATURE_LEVEL_ES2)
|
||||
META_VS_IN_ELEMENT(POSITION, 0, R32G32B32_FLOAT, 0, 0, PER_VERTEX, 0, true)
|
||||
META_VS_IN_ELEMENT(TEXCOORD, 0, R16G16_FLOAT, 1, 0, PER_VERTEX, 0, true)
|
||||
META_VS_IN_ELEMENT(NORMAL, 0, R10G10B10A2_UNORM, 1, ALIGN, PER_VERTEX, 0, true)
|
||||
META_VS_IN_ELEMENT(TANGENT, 0, R10G10B10A2_UNORM, 1, ALIGN, PER_VERTEX, 0, true)
|
||||
META_VS_IN_ELEMENT(TEXCOORD, 1, R16G16_FLOAT, 1, ALIGN, PER_VERTEX, 0, true)
|
||||
META_VS_IN_ELEMENT(COLOR, 0, R8G8B8A8_UNORM, 2, 0, PER_VERTEX, 0, USE_VERTEX_COLOR)
|
||||
VertexOutput VS_SplineModel(ModelInput input)
|
||||
{
|
||||
VertexOutput output;
|
||||
|
||||
// Apply local transformation of the geometry before deformation
|
||||
float3 position = mul(float4(input.Position, 1), LocalMatrix).xyz;
|
||||
float4x4 world = LocalMatrix;
|
||||
|
||||
// Apply spline curve deformation
|
||||
float splineAlpha = saturate((position.z - MeshMinZ) / (MeshMaxZ - MeshMinZ));
|
||||
int splineIndex = (int)((Segment + splineAlpha) * ChunksPerSegment);
|
||||
position.z = splineAlpha;
|
||||
float3x4 splineMatrix = float3x4(SplineDeformation[splineIndex * 3], SplineDeformation[splineIndex * 3 + 1], SplineDeformation[splineIndex * 3 + 2]);
|
||||
position = mul(splineMatrix, float4(position, 1));
|
||||
float4x3 splineMatrixT = transpose(splineMatrix);
|
||||
world = mul(world, float4x4(float4(splineMatrixT[0], 0), float4(splineMatrixT[1], 0), float4(splineMatrixT[2], 0), float4(splineMatrixT[3], 1)));
|
||||
|
||||
// Compute world space vertex position
|
||||
output.Geometry.WorldPosition = mul(float4(position, 1), WorldMatrix).xyz;
|
||||
world = mul(world, WorldMatrix);
|
||||
|
||||
// Compute clip space position
|
||||
output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
|
||||
|
||||
// Pass vertex attributes
|
||||
output.Geometry.TexCoord = input.TexCoord;
|
||||
#if USE_VERTEX_COLOR
|
||||
output.Geometry.VertexColor = input.Color;
|
||||
#endif
|
||||
|
||||
// Calculate tanget space to world space transformation matrix for unit vectors
|
||||
float3x3 tangentToLocal = CalcTangentToLocal(input);
|
||||
float3x3 localToWorld = RemoveScaleFromLocalToWorld((float3x3)world);
|
||||
float3x3 tangentToWorld = mul(tangentToLocal, localToWorld);
|
||||
output.Geometry.WorldNormal = tangentToWorld[2];
|
||||
output.Geometry.WorldTangent.xyz = tangentToWorld[0];
|
||||
output.Geometry.WorldTangent.w = input.Tangent.w ? -1.0f : +1.0f;
|
||||
|
||||
// Get material input params if need to evaluate any material property
|
||||
#if USE_POSITION_OFFSET || USE_TESSELLATION || USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||
MaterialInput materialInput = GetGeometryMaterialInput(output.Geometry);
|
||||
materialInput.TwoSidedSign = WorldDeterminantSign;
|
||||
materialInput.SvPosition = output.Position;
|
||||
materialInput.PreSkinnedPosition = input.Position.xyz;
|
||||
materialInput.PreSkinnedNormal = tangentToLocal[2].xyz;
|
||||
Material material = GetMaterialVS(materialInput);
|
||||
#endif
|
||||
|
||||
// Apply world position offset per-vertex
|
||||
#if USE_POSITION_OFFSET
|
||||
output.Geometry.WorldPosition += material.PositionOffset;
|
||||
output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
|
||||
#endif
|
||||
|
||||
// Get tessalation multiplier (per vertex)
|
||||
#if USE_TESSELLATION
|
||||
output.TessellationMultiplier = material.TessellationMultiplier;
|
||||
#endif
|
||||
|
||||
// Copy interpolants for other shader stages
|
||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||
output.CustomVSToPS = material.CustomVSToPS;
|
||||
#endif
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
#if USE_DITHERED_LOD_TRANSITION
|
||||
|
||||
void ClipLODTransition(PixelInput input)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Pixel Shader function for Depth Pass
|
||||
META_PS(true, FEATURE_LEVEL_ES2)
|
||||
void PS_Depth(PixelInput input)
|
||||
{
|
||||
#if MATERIAL_MASKED || MATERIAL_BLEND != MATERIAL_BLEND_OPAQUE
|
||||
// Get material parameters
|
||||
MaterialInput materialInput = GetMaterialInput(input);
|
||||
Material material = GetMaterialPS(materialInput);
|
||||
|
||||
// Perform per pixel clipping
|
||||
#if MATERIAL_MASKED
|
||||
clip(material.Mask - MATERIAL_MASK_THRESHOLD);
|
||||
#endif
|
||||
#if MATERIAL_BLEND != MATERIAL_BLEND_OPAQUE
|
||||
clip(material.Opacity - MATERIAL_OPACITY_THRESHOLD);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
@9
|
||||
@@ -0,0 +1,84 @@
|
||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||
|
||||
@0// Deferred Shading: Defines
|
||||
@1// Deferred Shading: Includes
|
||||
@2// Deferred Shading: Constants
|
||||
@3// Deferred Shading: Resources
|
||||
@4// Deferred Shading: Utilities
|
||||
@5// Deferred Shading: Shaders
|
||||
|
||||
// Pixel Shader function for GBuffer Pass
|
||||
META_PS(true, FEATURE_LEVEL_ES2)
|
||||
META_PERMUTATION_1(USE_LIGHTMAP=0)
|
||||
META_PERMUTATION_1(USE_LIGHTMAP=1)
|
||||
void PS_GBuffer(
|
||||
in PixelInput input
|
||||
,out float4 Light : SV_Target0
|
||||
#if MATERIAL_BLEND == MATERIAL_BLEND_OPAQUE
|
||||
// GBuffer
|
||||
,out float4 RT0 : SV_Target1
|
||||
,out float4 RT1 : SV_Target2
|
||||
,out float4 RT2 : SV_Target3
|
||||
#if USE_GBUFFER_CUSTOM_DATA
|
||||
,out float4 RT3 : SV_Target4
|
||||
#endif
|
||||
#endif
|
||||
)
|
||||
{
|
||||
Light = 0;
|
||||
|
||||
#if USE_DITHERED_LOD_TRANSITION
|
||||
// LOD masking
|
||||
ClipLODTransition(input);
|
||||
#endif
|
||||
|
||||
// Get material parameters
|
||||
MaterialInput materialInput = GetMaterialInput(input);
|
||||
Material material = GetMaterialPS(materialInput);
|
||||
|
||||
// Masking
|
||||
#if MATERIAL_MASKED
|
||||
clip(material.Mask - MATERIAL_MASK_THRESHOLD);
|
||||
#endif
|
||||
|
||||
#if USE_LIGHTMAP
|
||||
float3 diffuseColor = GetDiffuseColor(material.Color, material.Metalness);
|
||||
float3 specularColor = GetSpecularColor(material.Color, material.Specular, material.Metalness);
|
||||
|
||||
// Sample lightmap
|
||||
float3 diffuseIndirectLighting = SampleLightmap(material, materialInput);
|
||||
|
||||
// Apply static indirect light
|
||||
Light.rgb = diffuseColor * diffuseIndirectLighting * AOMultiBounce(material.AO, diffuseColor);
|
||||
#endif
|
||||
|
||||
#if MATERIAL_BLEND == MATERIAL_BLEND_OPAQUE
|
||||
|
||||
// Pack material properties to GBuffer
|
||||
RT0 = float4(material.Color, material.AO);
|
||||
RT1 = float4(material.WorldNormal * 0.5 + 0.5, MATERIAL_SHADING_MODEL * (1.0 / 3.0));
|
||||
RT2 = float4(material.Roughness, material.Metalness, material.Specular, 0);
|
||||
|
||||
// Custom data
|
||||
#if USE_GBUFFER_CUSTOM_DATA
|
||||
#if MATERIAL_SHADING_MODEL == SHADING_MODEL_SUBSURFACE
|
||||
RT3 = float4(material.SubsurfaceColor, material.Opacity);
|
||||
#elif MATERIAL_SHADING_MODEL == SHADING_MODEL_FOLIAGE
|
||||
RT3 = float4(material.SubsurfaceColor, material.Opacity);
|
||||
#else
|
||||
RT3 = float4(0, 0, 0, 0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Add light emission
|
||||
#if USE_EMISSIVE
|
||||
Light.rgb += material.Emissive;
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
// Handle blending as faked forward pass (use Light buffer and skip GBuffer modification)
|
||||
Light = float4(material.Emissive, material.Opacity);
|
||||
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||
|
||||
@0// Distortion: Defines
|
||||
@1// Distortion: Includes
|
||||
@2// Distortion: Constants
|
||||
@3// Distortion: Resources
|
||||
@4// Distortion: Utilities
|
||||
@5// Distortion: Shaders
|
||||
#if USE_DISTORTION
|
||||
|
||||
// Pixel Shader function for Distortion Pass
|
||||
META_PS(USE_DISTORTION, FEATURE_LEVEL_ES2)
|
||||
float4 PS_Distortion(PixelInput input) : SV_Target0
|
||||
{
|
||||
#if USE_DITHERED_LOD_TRANSITION
|
||||
// LOD masking
|
||||
ClipLODTransition(input);
|
||||
#endif
|
||||
|
||||
// Get material parameters
|
||||
MaterialInput materialInput = GetMaterialInput(input);
|
||||
Material material = GetMaterialPS(materialInput);
|
||||
|
||||
// Masking
|
||||
#if MATERIAL_MASKED
|
||||
clip(material.Mask - MATERIAL_MASK_THRESHOLD);
|
||||
#endif
|
||||
|
||||
float3 viewNormal = normalize(TransformWorldVectorToView(materialInput, material.WorldNormal));
|
||||
float airIOR = 1.0f;
|
||||
#if USE_PIXEL_NORMAL_OFFSET_REFRACTION
|
||||
float3 viewVertexNormal = TransformWorldVectorToView(materialInput, TransformTangentVectorToWorld(materialInput, float3(0, 0, 1)));
|
||||
float2 distortion = (viewVertexNormal.xy - viewNormal.xy) * (material.Refraction - airIOR);
|
||||
#else
|
||||
float2 distortion = viewNormal.xy * (material.Refraction - airIOR);
|
||||
#endif
|
||||
|
||||
// Clip if the distortion distance (squared) is too small to be noticed
|
||||
clip(dot(distortion, distortion) - 0.00001);
|
||||
|
||||
// Scale up for better precision in low/subtle refractions at the expense of artefacts at higher refraction
|
||||
distortion *= 4.0f;
|
||||
|
||||
// Use separate storage for positive and negative offsets
|
||||
float2 addOffset = max(distortion, 0);
|
||||
float2 subOffset = abs(min(distortion, 0));
|
||||
return float4(addOffset.x, addOffset.y, subOffset.x, subOffset.y);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,124 @@
|
||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||
|
||||
@0// Forward Shading: Defines
|
||||
#define MAX_LOCAL_LIGHTS 4
|
||||
@1// Forward Shading: Includes
|
||||
#include "./Flax/LightingCommon.hlsl"
|
||||
#if USE_REFLECTIONS
|
||||
#include "./Flax/ReflectionsCommon.hlsl"
|
||||
#endif
|
||||
#include "./Flax/Lighting.hlsl"
|
||||
#include "./Flax/ShadowsSampling.hlsl"
|
||||
#include "./Flax/ExponentialHeightFog.hlsl"
|
||||
@2// Forward Shading: Constants
|
||||
LightData DirectionalLight;
|
||||
LightShadowData DirectionalLightShadow;
|
||||
LightData SkyLight;
|
||||
ProbeData EnvironmentProbe;
|
||||
ExponentialHeightFogData ExponentialHeightFog;
|
||||
float3 Dummy2;
|
||||
uint LocalLightsCount;
|
||||
LightData LocalLights[MAX_LOCAL_LIGHTS];
|
||||
@3// Forward Shading: Resources
|
||||
TextureCube EnvProbe : register(t__SRV__);
|
||||
TextureCube SkyLightTexture : register(t__SRV__);
|
||||
Texture2DArray DirectionalLightShadowMap : register(t__SRV__);
|
||||
@4// Forward Shading: Utilities
|
||||
DECLARE_LIGHTSHADOWDATA_ACCESS(DirectionalLightShadow);
|
||||
@5// Forward Shading: Shaders
|
||||
|
||||
// Pixel Shader function for Forward Pass
|
||||
META_PS(USE_FORWARD, FEATURE_LEVEL_ES2)
|
||||
float4 PS_Forward(PixelInput input) : SV_Target0
|
||||
{
|
||||
float4 output = 0;
|
||||
|
||||
#if USE_DITHERED_LOD_TRANSITION
|
||||
// LOD masking
|
||||
ClipLODTransition(input);
|
||||
#endif
|
||||
|
||||
// Get material parameters
|
||||
MaterialInput materialInput = GetMaterialInput(input);
|
||||
Material material = GetMaterialPS(materialInput);
|
||||
|
||||
// Masking
|
||||
#if MATERIAL_MASKED
|
||||
clip(material.Mask - MATERIAL_MASK_THRESHOLD);
|
||||
#endif
|
||||
|
||||
// Add emissive light
|
||||
output = float4(material.Emissive, material.Opacity);
|
||||
|
||||
#if MATERIAL_SHADING_MODEL != SHADING_MODEL_UNLIT
|
||||
|
||||
// Setup GBuffer data as proxy for lighting
|
||||
GBufferSample gBuffer;
|
||||
gBuffer.Normal = material.WorldNormal;
|
||||
gBuffer.Roughness = material.Roughness;
|
||||
gBuffer.Metalness = material.Metalness;
|
||||
gBuffer.Color = material.Color;
|
||||
gBuffer.Specular = material.Specular;
|
||||
gBuffer.AO = material.AO;
|
||||
gBuffer.ViewPos = mul(float4(materialInput.WorldPosition, 1), ViewMatrix).xyz;
|
||||
#if MATERIAL_SHADING_MODEL == SHADING_MODEL_SUBSURFACE
|
||||
gBuffer.CustomData = float4(material.SubsurfaceColor, material.Opacity);
|
||||
#elif MATERIAL_SHADING_MODEL == SHADING_MODEL_FOLIAGE
|
||||
gBuffer.CustomData = float4(material.SubsurfaceColor, material.Opacity);
|
||||
#else
|
||||
gBuffer.CustomData = float4(0, 0, 0, 0);
|
||||
#endif
|
||||
gBuffer.WorldPos = materialInput.WorldPosition;
|
||||
gBuffer.ShadingModel = MATERIAL_SHADING_MODEL;
|
||||
|
||||
// Calculate lighting from a single directional light
|
||||
float4 shadowMask = 1.0f;
|
||||
if (DirectionalLight.CastShadows > 0)
|
||||
{
|
||||
LightShadowData directionalLightShadowData = GetDirectionalLightShadowData();
|
||||
shadowMask.r = SampleShadow(DirectionalLight, directionalLightShadowData, DirectionalLightShadowMap, gBuffer, shadowMask.g);
|
||||
}
|
||||
float4 light = GetLighting(ViewPos, DirectionalLight, gBuffer, shadowMask, false, false);
|
||||
|
||||
// Calculate lighting from sky light
|
||||
light += GetSkyLightLighting(SkyLight, gBuffer, SkyLightTexture);
|
||||
|
||||
// Calculate lighting from local lights
|
||||
LOOP
|
||||
for (uint localLightIndex = 0; localLightIndex < LocalLightsCount; localLightIndex++)
|
||||
{
|
||||
const LightData localLight = LocalLights[localLightIndex];
|
||||
bool isSpotLight = localLight.SpotAngles.x > -2.0f;
|
||||
shadowMask = 1.0f;
|
||||
light += GetLighting(ViewPos, localLight, gBuffer, shadowMask, true, isSpotLight);
|
||||
}
|
||||
|
||||
#if USE_REFLECTIONS
|
||||
// Calculate reflections
|
||||
light.rgb += GetEnvProbeLighting(ViewPos, EnvProbe, EnvironmentProbe, gBuffer) * light.a;
|
||||
#endif
|
||||
|
||||
// Add lighting (apply ambient occlusion)
|
||||
output.rgb += light.rgb * gBuffer.AO;
|
||||
|
||||
#if USE_FOG
|
||||
// Calculate exponential height fog
|
||||
float4 fog = GetExponentialHeightFog(ExponentialHeightFog, materialInput.WorldPosition, ViewPos, 0);
|
||||
|
||||
// Apply fog to the output color
|
||||
#if MATERIAL_BLEND == MATERIAL_BLEND_OPAQUE
|
||||
output = float4(output.rgb * fog.a + fog.rgb, output.a);
|
||||
#elif MATERIAL_BLEND == MATERIAL_BLEND_TRANSPARENT
|
||||
output = float4(output.rgb * fog.a + fog.rgb, output.a);
|
||||
#elif MATERIAL_BLEND == MATERIAL_BLEND_ADDITIVE
|
||||
output = float4(output.rgb * fog.a + fog.rgb, output.a * fog.a);
|
||||
#elif MATERIAL_BLEND == MATERIAL_BLEND_MULTIPLY
|
||||
output = float4(lerp(float3(1, 1, 1), output.rgb, fog.aaa * fog.aaa), output.a);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
return output;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||
|
||||
@0// Lightmap: Defines
|
||||
#define CAN_USE_LIGHTMAP 1
|
||||
@1// Lightmap: Includes
|
||||
@2// Lightmap: Constants
|
||||
float4 LightmapArea;
|
||||
@3// Lightmap: Resources
|
||||
#if USE_LIGHTMAP
|
||||
// Irradiance and directionality prebaked lightmaps
|
||||
Texture2D Lightmap0 : register(t__SRV__);
|
||||
Texture2D Lightmap1 : register(t__SRV__);
|
||||
Texture2D Lightmap2 : register(t__SRV__);
|
||||
#endif
|
||||
@4// Lightmap: Utilities
|
||||
#if USE_LIGHTMAP
|
||||
|
||||
// Evaluates the H-Basis coefficients in the tangent space normal direction
|
||||
float3 GetHBasisIrradiance(float3 n, float3 h0, float3 h1, float3 h2, float3 h3)
|
||||
{
|
||||
// Band 0
|
||||
float3 color = h0 * (1.0f / sqrt(2.0f * PI));
|
||||
|
||||
// Band 1
|
||||
color += h1 * -sqrt(1.5f / PI) * n.y;
|
||||
color += h2 * sqrt(1.5f / PI) * (2 * n.z - 1.0f);
|
||||
color += h3 * -sqrt(1.5f / PI) * n.x;
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
float3 SampleLightmap(Material material, MaterialInput materialInput)
|
||||
{
|
||||
// Sample lightmaps
|
||||
float4 lightmap0 = Lightmap0.Sample(SamplerLinearClamp, materialInput.LightmapUV);
|
||||
float4 lightmap1 = Lightmap1.Sample(SamplerLinearClamp, materialInput.LightmapUV);
|
||||
float4 lightmap2 = Lightmap2.Sample(SamplerLinearClamp, materialInput.LightmapUV);
|
||||
|
||||
// Unpack H-basis
|
||||
float3 h0 = float3(lightmap0.x, lightmap1.x, lightmap2.x);
|
||||
float3 h1 = float3(lightmap0.y, lightmap1.y, lightmap2.y);
|
||||
float3 h2 = float3(lightmap0.z, lightmap1.z, lightmap2.z);
|
||||
float3 h3 = float3(lightmap0.w, lightmap1.w, lightmap2.w);
|
||||
|
||||
// Sample baked diffuse irradiance from the H-basis coefficients
|
||||
float3 normal = material.TangentNormal;
|
||||
#if MATERIAL_SHADING_MODEL == SHADING_MODEL_FOLIAGE
|
||||
normal *= material.TangentNormal;
|
||||
#endif
|
||||
return GetHBasisIrradiance(normal, h0, h1, h2, h3) / PI;
|
||||
}
|
||||
|
||||
#endif
|
||||
@5// Lightmap: Shaders
|
||||
@@ -0,0 +1,44 @@
|
||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||
|
||||
@0// Motion Vectors: Defines
|
||||
@1// Motion Vectors: Includes
|
||||
@2// Motion Vectors: Constants
|
||||
@3// Motion Vectors: Resources
|
||||
@4// Motion Vectors: Utilities
|
||||
@5// Motion Vectors: Shaders
|
||||
|
||||
// Pixel Shader function for Motion Vectors Pass
|
||||
META_PS(true, FEATURE_LEVEL_ES2)
|
||||
float4 PS_MotionVectors(PixelInput input) : SV_Target0
|
||||
{
|
||||
#if USE_DITHERED_LOD_TRANSITION
|
||||
// LOD masking
|
||||
ClipLODTransition(input);
|
||||
#endif
|
||||
|
||||
#if MATERIAL_MASKED
|
||||
// Perform per pixel clipping if material requries it
|
||||
MaterialInput materialInput = GetMaterialInput(input);
|
||||
Material material = GetMaterialPS(materialInput);
|
||||
clip(material.Mask - MATERIAL_MASK_THRESHOLD);
|
||||
#endif
|
||||
|
||||
// Calculate this and previosu frame pixel locations in clip space
|
||||
float4 prevClipPos = mul(float4(input.Geometry.PrevWorldPosition, 1), PrevViewProjectionMatrix);
|
||||
float4 curClipPos = mul(float4(input.Geometry.WorldPosition, 1), ViewProjectionMatrix);
|
||||
float2 prevHPos = prevClipPos.xy / prevClipPos.w;
|
||||
float2 curHPos = curClipPos.xy / curClipPos.w;
|
||||
|
||||
// Revert temporal jitter offset
|
||||
prevHPos -= TemporalAAJitter.zw;
|
||||
curHPos -= TemporalAAJitter.xy;
|
||||
|
||||
// Clip Space -> UV Space
|
||||
float2 vPosPrev = prevHPos.xy * 0.5f + 0.5f;
|
||||
float2 vPosCur = curHPos.xy * 0.5f + 0.5f;
|
||||
vPosPrev.y = 1.0 - vPosPrev.y;
|
||||
vPosCur.y = 1.0 - vPosCur.y;
|
||||
|
||||
// Calculate per-pixel motion vector
|
||||
return float4(vPosCur - vPosPrev, 0, 1);
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||
|
||||
@0// Tessellation: Defines
|
||||
#define TessalationProjectOntoPlane(planeNormal, planePosition, pointToProject) pointToProject - dot(pointToProject - planePosition, planeNormal) * planeNormal
|
||||
@1// Tessellation: Includes
|
||||
@2// Tessellation: Constants
|
||||
@3// Tessellation: Resources
|
||||
@4// Tessellation: Utilities
|
||||
@5// Tessellation: Shaders
|
||||
#if USE_TESSELLATION
|
||||
|
||||
// Interpolants passed from the hull shader to the domain shader
|
||||
struct TessalationHSToDS
|
||||
{
|
||||
float4 Position : SV_Position;
|
||||
GeometryData Geometry;
|
||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||
float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9;
|
||||
#endif
|
||||
float TessellationMultiplier : TESS;
|
||||
};
|
||||
|
||||
// Interpolants passed from the domain shader and to the pixel shader
|
||||
struct TessalationDSToPS
|
||||
{
|
||||
float4 Position : SV_Position;
|
||||
GeometryData Geometry;
|
||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||
float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9;
|
||||
#endif
|
||||
};
|
||||
|
||||
MaterialInput GetMaterialInput(TessalationDSToPS input)
|
||||
{
|
||||
MaterialInput output = GetGeometryMaterialInput(input.Geometry);
|
||||
output.SvPosition = input.Position;
|
||||
output.TwoSidedSign = WorldDeterminantSign;
|
||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||
output.CustomVSToPS = input.CustomVSToPS;
|
||||
#endif
|
||||
return output;
|
||||
}
|
||||
|
||||
struct TessalationPatch
|
||||
{
|
||||
float EdgeTessFactor[3] : SV_TessFactor;
|
||||
float InsideTessFactor : SV_InsideTessFactor;
|
||||
#if MATERIAL_TESSELLATION == MATERIAL_TESSELLATION_PN
|
||||
float3 B210 : POSITION4;
|
||||
float3 B120 : POSITION5;
|
||||
float3 B021 : POSITION6;
|
||||
float3 B012 : POSITION7;
|
||||
float3 B102 : POSITION8;
|
||||
float3 B201 : POSITION9;
|
||||
float3 B111 : CENTER;
|
||||
#endif
|
||||
};
|
||||
|
||||
TessalationPatch HS_PatchConstant(InputPatch<VertexOutput, 3> input)
|
||||
{
|
||||
TessalationPatch output;
|
||||
|
||||
// Average tess factors along edges, and pick an edge tess factor for the interior tessellation
|
||||
float4 tessellationMultipliers;
|
||||
tessellationMultipliers.x = 0.5f * (input[1].TessellationMultiplier + input[2].TessellationMultiplier);
|
||||
tessellationMultipliers.y = 0.5f * (input[2].TessellationMultiplier + input[0].TessellationMultiplier);
|
||||
tessellationMultipliers.z = 0.5f * (input[0].TessellationMultiplier + input[1].TessellationMultiplier);
|
||||
tessellationMultipliers.w = 0.333f * (input[0].TessellationMultiplier + input[1].TessellationMultiplier + input[2].TessellationMultiplier);
|
||||
tessellationMultipliers = clamp(tessellationMultipliers, 1, MAX_TESSELLATION_FACTOR);
|
||||
|
||||
output.EdgeTessFactor[0] = tessellationMultipliers.x; // 1->2 edge
|
||||
output.EdgeTessFactor[1] = tessellationMultipliers.y; // 2->0 edge
|
||||
output.EdgeTessFactor[2] = tessellationMultipliers.z; // 0->1 edge
|
||||
output.InsideTessFactor = tessellationMultipliers.w;
|
||||
|
||||
#if MATERIAL_TESSELLATION == MATERIAL_TESSELLATION_PN
|
||||
// Calculate PN Triangle control points
|
||||
// Reference: [Vlachos 2001]
|
||||
float3 p1 = input[0].Geometry.WorldPosition;
|
||||
float3 p2 = input[1].Geometry.WorldPosition;
|
||||
float3 p3 = input[2].Geometry.WorldPosition;
|
||||
float3 n1 = input[0].Geometry.WorldNormal;
|
||||
float3 n2 = input[1].Geometry.WorldNormal;
|
||||
float3 n3 = input[2].Geometry.WorldNormal;
|
||||
output.B210 = (2.0f * p1 + p2 - dot((p2 - p1), n1) * n1) / 3.0f;
|
||||
output.B120 = (2.0f * p2 + p1 - dot((p1 - p2), n2) * n2) / 3.0f;
|
||||
output.B021 = (2.0f * p2 + p3 - dot((p3 - p2), n2) * n2) / 3.0f;
|
||||
output.B012 = (2.0f * p3 + p2 - dot((p2 - p3), n3) * n3) / 3.0f;
|
||||
output.B102 = (2.0f * p3 + p1 - dot((p1 - p3), n3) * n3) / 3.0f;
|
||||
output.B201 = (2.0f * p1 + p3 - dot((p3 - p1), n1) * n1) / 3.0f;
|
||||
float3 e = (output.B210 + output.B120 + output.B021 + output.B012 + output.B102 + output.B201) / 6.0f;
|
||||
float3 v = (p1 + p2 + p3) / 3.0f;
|
||||
output.B111 = e + ((e - v) / 2.0f);
|
||||
#endif
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
META_HS(USE_TESSELLATION, FEATURE_LEVEL_SM5)
|
||||
META_HS_PATCH(TESSELLATION_IN_CONTROL_POINTS)
|
||||
[domain("tri")]
|
||||
[partitioning("fractional_odd")]
|
||||
[outputtopology("triangle_cw")]
|
||||
[maxtessfactor(MAX_TESSELLATION_FACTOR)]
|
||||
[outputcontrolpoints(3)]
|
||||
[patchconstantfunc("HS_PatchConstant")]
|
||||
TessalationHSToDS HS(InputPatch<VertexOutput, TESSELLATION_IN_CONTROL_POINTS> input, uint ControlPointID : SV_OutputControlPointID)
|
||||
{
|
||||
TessalationHSToDS output;
|
||||
|
||||
// Pass through shader
|
||||
#define COPY(thing) output.thing = input[ControlPointID].thing;
|
||||
COPY(Position);
|
||||
COPY(Geometry);
|
||||
COPY(TessellationMultiplier);
|
||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||
COPY(CustomVSToPS);
|
||||
#endif
|
||||
#undef COPY
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
META_DS(USE_TESSELLATION, FEATURE_LEVEL_SM5)
|
||||
[domain("tri")]
|
||||
TessalationDSToPS DS(TessalationPatch constantData, float3 barycentricCoords : SV_DomainLocation, const OutputPatch<TessalationHSToDS, 3> input)
|
||||
{
|
||||
TessalationDSToPS output;
|
||||
|
||||
// Get the barycentric coords
|
||||
float U = barycentricCoords.x;
|
||||
float V = barycentricCoords.y;
|
||||
float W = barycentricCoords.z;
|
||||
|
||||
// Interpolate patch attributes to generated vertices
|
||||
output.Geometry = InterpolateGeometry(input[0].Geometry, U, input[1].Geometry, V, input[2].Geometry, W);
|
||||
#define INTERPOLATE(thing) output.thing = U * input[0].thing + V * input[1].thing + W * input[2].thing
|
||||
INTERPOLATE(Position);
|
||||
#if MATERIAL_TESSELLATION == MATERIAL_TESSELLATION_PN
|
||||
// Interpolate using barycentric coordinates and PN Triangle control points
|
||||
float UU = U * U;
|
||||
float VV = V * V;
|
||||
float WW = W * W;
|
||||
float UU3 = UU * 3.0f;
|
||||
float VV3 = VV * 3.0f;
|
||||
float WW3 = WW * 3.0f;
|
||||
float3 offset =
|
||||
constantData.B210 * UU3 * V +
|
||||
constantData.B120 * VV3 * U +
|
||||
constantData.B021 * VV3 * W +
|
||||
constantData.B012 * WW3 * V +
|
||||
constantData.B102 * WW3 * U +
|
||||
constantData.B201 * UU3 * W +
|
||||
constantData.B111 * 6.0f * W * U * V;
|
||||
InterpolateGeometryPositions(output.Geometry, input[0].Geometry, UU * U, input[1].Geometry, VV * V, input[2].Geometry, WW * W, offset);
|
||||
#else
|
||||
InterpolateGeometryPositions(output.Geometry, input[0].Geometry, U, input[1].Geometry, V, input[2].Geometry, W, float3(0, 0, 0));
|
||||
#endif
|
||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||
UNROLL
|
||||
for (int i = 0; i < CUSTOM_VERTEX_INTERPOLATORS_COUNT; i++)
|
||||
INTERPOLATE(CustomVSToPS[i]);
|
||||
#endif
|
||||
#undef INTERPOLATE
|
||||
|
||||
#if MATERIAL_TESSELLATION == MATERIAL_TESSELLATION_PHONG
|
||||
// Orthogonal projection in the tangent planes with interpolation
|
||||
ApplyGeometryPositionsPhongTess(output.Geometry, input[0].Geometry, input[1].Geometry, input[2].Geometry, U, V, W);
|
||||
#endif
|
||||
|
||||
// Perform displacement mapping
|
||||
#if USE_DISPLACEMENT
|
||||
MaterialInput materialInput = GetMaterialInput(output);
|
||||
Material material = GetMaterialDS(materialInput);
|
||||
OffsetGeometryPositions(output.Geometry, material.WorldDisplacement);
|
||||
#endif
|
||||
|
||||
// Recalculate the clip space position
|
||||
output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
#define MATERIAL 1
|
||||
@3
|
||||
|
||||
#include "./Flax/Common.hlsl"
|
||||
#include "./Flax/MaterialCommon.hlsl"
|
||||
#include "./Flax/GBufferCommon.hlsl"
|
||||
@@ -22,7 +21,7 @@ float4 ViewInfo;
|
||||
float4 ScreenSize;
|
||||
@1META_CB_END
|
||||
|
||||
// Material shader resources
|
||||
// Shader resources
|
||||
@2
|
||||
// Interpolants passed from the vertex shader
|
||||
struct VertexOutput
|
||||
@@ -185,6 +184,8 @@ float4 GetVertexColor(MaterialInput input)
|
||||
#endif
|
||||
}
|
||||
|
||||
@8
|
||||
|
||||
// Get material properties function (for vertex shader)
|
||||
Material GetMaterialVS(MaterialInput input)
|
||||
{
|
||||
@@ -197,9 +198,6 @@ Material GetMaterialPS(MaterialInput input)
|
||||
@4
|
||||
}
|
||||
|
||||
// Fix line for errors/warnings for shader code from template
|
||||
#line 1000
|
||||
|
||||
// Vertex Shader function for GUI materials rendering
|
||||
META_VS(true, FEATURE_LEVEL_ES2)
|
||||
META_VS_IN_ELEMENT(POSITION, 0, R32G32_FLOAT, 0, ALIGN, PER_VERTEX, 0, true)
|
||||
@@ -257,3 +255,5 @@ float4 PS_GUI(PixelInput input) : SV_Target0
|
||||
|
||||
return float4(material.Emissive, material.Opacity);
|
||||
}
|
||||
|
||||
@9
|
||||
|
||||
@@ -2,19 +2,13 @@
|
||||
// Version: @0
|
||||
|
||||
#define MATERIAL 1
|
||||
#define MAX_LOCAL_LIGHTS 4
|
||||
@3
|
||||
// Ribbons don't use sorted indices so overlap the segment distances buffer on the slot
|
||||
#define HAS_SORTED_INDICES (!defined(_VS_Ribbon))
|
||||
|
||||
#include "./Flax/Common.hlsl"
|
||||
#include "./Flax/MaterialCommon.hlsl"
|
||||
#include "./Flax/GBufferCommon.hlsl"
|
||||
#include "./Flax/LightingCommon.hlsl"
|
||||
#if USE_REFLECTIONS
|
||||
#include "./Flax/ReflectionsCommon.hlsl"
|
||||
#endif
|
||||
#include "./Flax/Lighting.hlsl"
|
||||
#include "./Flax/ShadowsSampling.hlsl"
|
||||
#include "./Flax/ExponentialHeightFog.hlsl"
|
||||
#include "./Flax/Matrix.hlsl"
|
||||
@7
|
||||
struct SpriteInput
|
||||
@@ -55,44 +49,19 @@ uint RibbonSegmentCount;
|
||||
float4x4 WorldMatrixInverseTransposed;
|
||||
@1META_CB_END
|
||||
|
||||
// Secondary constantant buffer (for lighting)
|
||||
META_CB_BEGIN(1, LightingData)
|
||||
LightData DirectionalLight;
|
||||
LightShadowData DirectionalLightShadow;
|
||||
LightData SkyLight;
|
||||
ProbeData EnvironmentProbe;
|
||||
ExponentialHeightFogData ExponentialHeightFog;
|
||||
float3 Dummy1;
|
||||
uint LocalLightsCount;
|
||||
LightData LocalLights[MAX_LOCAL_LIGHTS];
|
||||
META_CB_END
|
||||
|
||||
DECLARE_LIGHTSHADOWDATA_ACCESS(DirectionalLightShadow);
|
||||
|
||||
// Particles attributes buffer
|
||||
ByteAddressBuffer ParticlesData : register(t0);
|
||||
|
||||
// Ribbons don't use sorted indices so overlap the segment distances buffer on the slot
|
||||
#define HAS_SORTED_INDICES (!defined(_VS_Ribbon))
|
||||
|
||||
#if HAS_SORTED_INDICES
|
||||
|
||||
// Sorted particles indices
|
||||
Buffer<uint> SortedIndices : register(t1);
|
||||
|
||||
#else
|
||||
|
||||
// Ribbon particles segments distances buffer
|
||||
Buffer<float> SegmentDistances : register(t1);
|
||||
|
||||
#endif
|
||||
|
||||
// Shader resources
|
||||
TextureCube EnvProbe : register(t2);
|
||||
TextureCube SkyLightTexture : register(t3);
|
||||
Texture2DArray DirectionalLightShadowMap : register(t4);
|
||||
@2
|
||||
|
||||
// Interpolants passed from the vertex shader
|
||||
struct VertexOutput
|
||||
{
|
||||
@@ -172,14 +141,11 @@ MaterialInput GetMaterialInput(PixelInput input)
|
||||
}
|
||||
|
||||
// Gets the local to world transform matrix (supports instancing)
|
||||
float4x4 GetInstanceTransform(ModelInput input)
|
||||
{
|
||||
return WorldMatrix;
|
||||
}
|
||||
float4x4 GetInstanceTransform(MaterialInput input)
|
||||
{
|
||||
return WorldMatrix;
|
||||
}
|
||||
#if USE_INSTANCING
|
||||
#define GetInstanceTransform(input) float4x4(float4(input.InstanceTransform1.xyz, 0.0f), float4(input.InstanceTransform2.xyz, 0.0f), float4(input.InstanceTransform3.xyz, 0.0f), float4(input.InstanceOrigin.xyz, 1.0f))
|
||||
#else
|
||||
#define GetInstanceTransform(input) WorldMatrix;
|
||||
#endif
|
||||
|
||||
// Removes the scale vector from the local to world transformation matrix (supports instancing)
|
||||
float3x3 RemoveScaleFromLocalToWorld(float3x3 localToWorld)
|
||||
@@ -312,6 +278,8 @@ float3 TransformParticleVector(float3 input)
|
||||
return mul(float4(input, 0.0f), WorldMatrixInverseTransposed).xyz;
|
||||
}
|
||||
|
||||
@8
|
||||
|
||||
// Get material properties function (for vertex shader)
|
||||
Material GetMaterialVS(MaterialInput input)
|
||||
{
|
||||
@@ -330,9 +298,6 @@ Material GetMaterialPS(MaterialInput input)
|
||||
@4
|
||||
}
|
||||
|
||||
// Fix line for errors/warnings for shader code from template
|
||||
#line 1000
|
||||
|
||||
// Calculates the transform matrix from mesh tangent space to local space
|
||||
half3x3 CalcTangentToLocal(ModelInput input)
|
||||
{
|
||||
@@ -712,142 +677,9 @@ VertexOutput VS_Ribbon(uint vertexIndex : SV_VertexID)
|
||||
return output;
|
||||
}
|
||||
|
||||
// Pixel Shader function for Forward Pass
|
||||
META_PS(USE_FORWARD, FEATURE_LEVEL_ES2)
|
||||
float4 PS_Forward(PixelInput input) : SV_Target0
|
||||
{
|
||||
float4 output = 0;
|
||||
|
||||
// Get material parameters
|
||||
MaterialInput materialInput = GetMaterialInput(input);
|
||||
Material material = GetMaterialPS(materialInput);
|
||||
|
||||
// Masking
|
||||
#if MATERIAL_MASKED
|
||||
clip(material.Mask - MATERIAL_MASK_THRESHOLD);
|
||||
#endif
|
||||
|
||||
// Add emissive light
|
||||
output = float4(material.Emissive, material.Opacity);
|
||||
|
||||
#if MATERIAL_SHADING_MODEL != SHADING_MODEL_UNLIT
|
||||
|
||||
// Setup GBuffer data as proxy for lighting
|
||||
GBufferSample gBuffer;
|
||||
gBuffer.Normal = material.WorldNormal;
|
||||
gBuffer.Roughness = material.Roughness;
|
||||
gBuffer.Metalness = material.Metalness;
|
||||
gBuffer.Color = material.Color;
|
||||
gBuffer.Specular = material.Specular;
|
||||
gBuffer.AO = material.AO;
|
||||
gBuffer.ViewPos = mul(float4(materialInput.WorldPosition, 1), ViewMatrix).xyz;
|
||||
#if MATERIAL_SHADING_MODEL == SHADING_MODEL_SUBSURFACE
|
||||
gBuffer.CustomData = float4(material.SubsurfaceColor, material.Opacity);
|
||||
#elif MATERIAL_SHADING_MODEL == SHADING_MODEL_FOLIAGE
|
||||
gBuffer.CustomData = float4(material.SubsurfaceColor, material.Opacity);
|
||||
#else
|
||||
gBuffer.CustomData = float4(0, 0, 0, 0);
|
||||
#endif
|
||||
gBuffer.WorldPos = materialInput.WorldPosition;
|
||||
gBuffer.ShadingModel = MATERIAL_SHADING_MODEL;
|
||||
|
||||
// Calculate lighting from a single directional light
|
||||
float4 shadowMask = 1.0f;
|
||||
if (DirectionalLight.CastShadows > 0)
|
||||
{
|
||||
LightShadowData directionalLightShadowData = GetDirectionalLightShadowData();
|
||||
shadowMask.r = SampleShadow(DirectionalLight, directionalLightShadowData, DirectionalLightShadowMap, gBuffer, shadowMask.g);
|
||||
}
|
||||
float4 light = GetLighting(ViewPos, DirectionalLight, gBuffer, shadowMask, false, false);
|
||||
|
||||
// Calculate lighting from sky light
|
||||
light += GetSkyLightLighting(SkyLight, gBuffer, SkyLightTexture);
|
||||
|
||||
// Calculate lighting from local lights
|
||||
LOOP
|
||||
for (uint localLightIndex = 0; localLightIndex < LocalLightsCount; localLightIndex++)
|
||||
{
|
||||
const LightData localLight = LocalLights[localLightIndex];
|
||||
bool isSpotLight = localLight.SpotAngles.x > -2.0f;
|
||||
shadowMask = 1.0f;
|
||||
light += GetLighting(ViewPos, localLight, gBuffer, shadowMask, true, isSpotLight);
|
||||
}
|
||||
|
||||
#if USE_REFLECTIONS
|
||||
// Calculate reflections
|
||||
light.rgb += GetEnvProbeLighting(ViewPos, EnvProbe, EnvironmentProbe, gBuffer) * light.a;
|
||||
#endif
|
||||
|
||||
// Add lighting (apply ambient occlusion)
|
||||
output.rgb += light.rgb * gBuffer.AO;
|
||||
|
||||
#if USE_FOG
|
||||
// Calculate exponential height fog
|
||||
float4 fog = GetExponentialHeightFog(ExponentialHeightFog, materialInput.WorldPosition, ViewPos, 0);
|
||||
|
||||
// Apply fog to the output color
|
||||
#if MATERIAL_BLEND == MATERIAL_BLEND_OPAQUE
|
||||
output = float4(output.rgb * fog.a + fog.rgb, output.a);
|
||||
#elif MATERIAL_BLEND == MATERIAL_BLEND_TRANSPARENT
|
||||
output = float4(output.rgb * fog.a + fog.rgb, output.a);
|
||||
#elif MATERIAL_BLEND == MATERIAL_BLEND_ADDITIVE
|
||||
output = float4(output.rgb * fog.a + fog.rgb, output.a * fog.a);
|
||||
#elif MATERIAL_BLEND == MATERIAL_BLEND_MULTIPLY
|
||||
output = float4(lerp(float3(1, 1, 1), output.rgb, fog.aaa * fog.aaa), output.a);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
#if USE_DISTORTION
|
||||
|
||||
// Pixel Shader function for Distortion Pass
|
||||
META_PS(USE_DISTORTION, FEATURE_LEVEL_ES2)
|
||||
float4 PS_Distortion(PixelInput input) : SV_Target0
|
||||
{
|
||||
// Get material parameters
|
||||
MaterialInput materialInput = GetMaterialInput(input);
|
||||
Material material = GetMaterialPS(materialInput);
|
||||
|
||||
// Masking
|
||||
#if MATERIAL_MASKED
|
||||
clip(material.Mask - MATERIAL_MASK_THRESHOLD);
|
||||
#endif
|
||||
|
||||
float3 viewNormal = normalize(TransformWorldVectorToView(materialInput, material.WorldNormal));
|
||||
float airIOR = 1.0f;
|
||||
#if USE_PIXEL_NORMAL_OFFSET_REFRACTION
|
||||
float3 viewVertexNormal = TransformWorldVectorToView(materialInput, TransformTangentVectorToWorld(materialInput, float3(0, 0, 1)));
|
||||
float2 distortion = (viewVertexNormal.xy - viewNormal.xy) * (material.Refraction - airIOR);
|
||||
#else
|
||||
float2 distortion = viewNormal.xy * (material.Refraction - airIOR);
|
||||
#endif
|
||||
|
||||
// Clip if the distortion distance (squared) is too small to be noticed
|
||||
clip(dot(distortion, distortion) - 0.00001);
|
||||
|
||||
// Scale up for better precision in low/subtle refractions at the expense of artefacts at higher refraction
|
||||
distortion *= 4.0f;
|
||||
|
||||
// Use separate storage for positive and negative offsets
|
||||
float2 addOffset = max(distortion, 0);
|
||||
float2 subOffset = abs(min(distortion, 0));
|
||||
return float4(addOffset.x, addOffset.y, subOffset.x, subOffset.y);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Pixel Shader function for Depth Pass
|
||||
META_PS(true, FEATURE_LEVEL_ES2)
|
||||
void PS_Depth(PixelInput input
|
||||
#if GLSL
|
||||
, out float4 OutColor : SV_Target0
|
||||
#endif
|
||||
)
|
||||
void PS_Depth(PixelInput input)
|
||||
{
|
||||
// Get material parameters
|
||||
MaterialInput materialInput = GetMaterialInput(input);
|
||||
@@ -860,8 +692,6 @@ void PS_Depth(PixelInput input
|
||||
#if MATERIAL_BLEND == MATERIAL_BLEND_TRANSPARENT
|
||||
clip(material.Opacity - MATERIAL_OPACITY_THRESHOLD);
|
||||
#endif
|
||||
|
||||
#if GLSL
|
||||
OutColor = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
@9
|
||||
|
||||
@@ -20,7 +20,7 @@ float4 ScreenSize;
|
||||
float4 TemporalAAJitter;
|
||||
@1META_CB_END
|
||||
|
||||
// Material shader resources
|
||||
// Shader resources
|
||||
@2
|
||||
// Interpolants passed to the pixel shader
|
||||
struct PixelInput
|
||||
@@ -128,15 +128,14 @@ float4 GetVertexColor(MaterialInput input)
|
||||
return 1;
|
||||
}
|
||||
|
||||
@8
|
||||
|
||||
// Get material properties function (for pixel shader)
|
||||
Material GetMaterialPS(MaterialInput input)
|
||||
{
|
||||
@4
|
||||
}
|
||||
|
||||
// Fix line for errors/warnings for shader code from template
|
||||
#line 1000
|
||||
|
||||
// Pixel Shader function for PostFx materials rendering
|
||||
META_PS(true, FEATURE_LEVEL_ES2)
|
||||
float4 PS_PostFx(PixelInput input) : SV_Target0
|
||||
@@ -147,3 +146,5 @@ float4 PS_PostFx(PixelInput input) : SV_Target0
|
||||
|
||||
return float4(material.Emissive, material.Opacity);
|
||||
}
|
||||
|
||||
@9
|
||||
|
||||
@@ -0,0 +1,618 @@
|
||||
// File generated by Flax Materials Editor
|
||||
// Version: @0
|
||||
|
||||
#define MATERIAL 1
|
||||
@3
|
||||
#include "./Flax/Common.hlsl"
|
||||
#include "./Flax/MaterialCommon.hlsl"
|
||||
#include "./Flax/GBufferCommon.hlsl"
|
||||
@7
|
||||
// Primary constant buffer (with additional material parameters)
|
||||
META_CB_BEGIN(0, Data)
|
||||
float4x4 ViewProjectionMatrix;
|
||||
float4x4 WorldMatrix;
|
||||
float4x4 ViewMatrix;
|
||||
float4x4 PrevViewProjectionMatrix;
|
||||
float4x4 PrevWorldMatrix;
|
||||
float3 ViewPos;
|
||||
float ViewFar;
|
||||
float3 ViewDir;
|
||||
float TimeParam;
|
||||
float4 ViewInfo;
|
||||
float4 ScreenSize;
|
||||
float3 WorldInvScale;
|
||||
float WorldDeterminantSign;
|
||||
float2 Dummy0;
|
||||
float LODDitherFactor;
|
||||
float PerInstanceRandom;
|
||||
float4 TemporalAAJitter;
|
||||
float3 GeometrySize;
|
||||
float Dummy1;
|
||||
@1META_CB_END
|
||||
|
||||
// Shader resources
|
||||
@2
|
||||
// Geometry data passed though the graphics rendering stages up to the pixel shader
|
||||
struct GeometryData
|
||||
{
|
||||
float3 WorldPosition : TEXCOORD0;
|
||||
float2 TexCoord : TEXCOORD1;
|
||||
float2 LightmapUV : TEXCOORD2;
|
||||
#if USE_VERTEX_COLOR
|
||||
half4 VertexColor : COLOR;
|
||||
#endif
|
||||
float3 WorldNormal : TEXCOORD3;
|
||||
float4 WorldTangent : TEXCOORD4;
|
||||
float3 InstanceOrigin : TEXCOORD5;
|
||||
float2 InstanceParams : TEXCOORD6; // x-PerInstanceRandom, y-LODDitherFactor
|
||||
float3 PrevWorldPosition : TEXCOORD7;
|
||||
};
|
||||
|
||||
// Interpolants passed from the vertex shader
|
||||
struct VertexOutput
|
||||
{
|
||||
float4 Position : SV_Position;
|
||||
GeometryData Geometry;
|
||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||
float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9;
|
||||
#endif
|
||||
#if USE_TESSELLATION
|
||||
float TessellationMultiplier : TESS;
|
||||
#endif
|
||||
};
|
||||
|
||||
// Interpolants passed to the pixel shader
|
||||
struct PixelInput
|
||||
{
|
||||
float4 Position : SV_Position;
|
||||
GeometryData Geometry;
|
||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||
float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9;
|
||||
#endif
|
||||
bool IsFrontFace : SV_IsFrontFace;
|
||||
};
|
||||
|
||||
// Material properties generation input
|
||||
struct MaterialInput
|
||||
{
|
||||
float3 WorldPosition;
|
||||
float TwoSidedSign;
|
||||
float2 TexCoord;
|
||||
#if USE_LIGHTMAP
|
||||
float2 LightmapUV;
|
||||
#endif
|
||||
#if USE_VERTEX_COLOR
|
||||
half4 VertexColor;
|
||||
#endif
|
||||
float3x3 TBN;
|
||||
float4 SvPosition;
|
||||
float3 PreSkinnedPosition;
|
||||
float3 PreSkinnedNormal;
|
||||
float3 InstanceOrigin;
|
||||
float2 InstanceParams;
|
||||
#if USE_INSTANCING
|
||||
float3 InstanceTransform1;
|
||||
float3 InstanceTransform2;
|
||||
float3 InstanceTransform3;
|
||||
#endif
|
||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||
float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT];
|
||||
#endif
|
||||
};
|
||||
|
||||
// Extracts geometry data to the material input
|
||||
MaterialInput GetGeometryMaterialInput(GeometryData geometry)
|
||||
{
|
||||
MaterialInput output = (MaterialInput)0;
|
||||
output.WorldPosition = geometry.WorldPosition;
|
||||
output.TexCoord = geometry.TexCoord;
|
||||
#if USE_LIGHTMAP
|
||||
output.LightmapUV = geometry.LightmapUV;
|
||||
#endif
|
||||
#if USE_VERTEX_COLOR
|
||||
output.VertexColor = geometry.VertexColor;
|
||||
#endif
|
||||
output.TBN = CalcTangentBasis(geometry.WorldNormal, geometry.WorldTangent);
|
||||
output.InstanceOrigin = geometry.InstanceOrigin;
|
||||
output.InstanceParams = geometry.InstanceParams;
|
||||
return output;
|
||||
}
|
||||
|
||||
#if USE_TESSELLATION
|
||||
|
||||
// Interpolates the geometry positions data only (used by the tessallation when generating vertices)
|
||||
#define InterpolateGeometryPositions(output, p0, w0, p1, w1, p2, w2, offset) output.WorldPosition = p0.WorldPosition * w0 + p1.WorldPosition * w1 + p2.WorldPosition * w2 + offset; output.PrevWorldPosition = p0.PrevWorldPosition * w0 + p1.PrevWorldPosition * w1 + p2.PrevWorldPosition * w2 + offset
|
||||
|
||||
// Offsets the geometry positions data only (used by the tessallation when generating vertices)
|
||||
#define OffsetGeometryPositions(geometry, offset) geometry.WorldPosition += offset; geometry.PrevWorldPosition += offset
|
||||
|
||||
// Applies the Phong tessallation to the geometry positions (used by the tessallation when doing Phong tess)
|
||||
#define ApplyGeometryPositionsPhongTess(geometry, p0, p1, p2, U, V, W) \
|
||||
float3 posProjectedU = TessalationProjectOntoPlane(p0.WorldNormal, p0.WorldPosition, geometry.WorldPosition); \
|
||||
float3 posProjectedV = TessalationProjectOntoPlane(p1.WorldNormal, p1.WorldPosition, geometry.WorldPosition); \
|
||||
float3 posProjectedW = TessalationProjectOntoPlane(p2.WorldNormal, p2.WorldPosition, geometry.WorldPosition); \
|
||||
geometry.WorldPosition = U * posProjectedU + V * posProjectedV + W * posProjectedW; \
|
||||
posProjectedU = TessalationProjectOntoPlane(p0.WorldNormal, p0.PrevWorldPosition, geometry.PrevWorldPosition); \
|
||||
posProjectedV = TessalationProjectOntoPlane(p1.WorldNormal, p1.PrevWorldPosition, geometry.PrevWorldPosition); \
|
||||
posProjectedW = TessalationProjectOntoPlane(p2.WorldNormal, p2.PrevWorldPosition, geometry.PrevWorldPosition); \
|
||||
geometry.PrevWorldPosition = U * posProjectedU + V * posProjectedV + W * posProjectedW
|
||||
|
||||
// Interpolates the geometry data except positions (used by the tessallation when generating vertices)
|
||||
GeometryData InterpolateGeometry(GeometryData p0, float w0, GeometryData p1, float w1, GeometryData p2, float w2)
|
||||
{
|
||||
GeometryData output = (GeometryData)0;
|
||||
output.TexCoord = p0.TexCoord * w0 + p1.TexCoord * w1 + p2.TexCoord * w2;
|
||||
output.LightmapUV = p0.LightmapUV * w0 + p1.LightmapUV * w1 + p2.LightmapUV * w2;
|
||||
#if USE_VERTEX_COLOR
|
||||
output.VertexColor = p0.VertexColor * w0 + p1.VertexColor * w1 + p2.VertexColor * w2;
|
||||
#endif
|
||||
output.WorldNormal = p0.WorldNormal * w0 + p1.WorldNormal * w1 + p2.WorldNormal * w2;
|
||||
output.WorldNormal = normalize(output.WorldNormal);
|
||||
output.WorldTangent = p0.WorldTangent * w0 + p1.WorldTangent * w1 + p2.WorldTangent * w2;
|
||||
output.WorldTangent.xyz = normalize(output.WorldTangent.xyz);
|
||||
output.InstanceOrigin = p0.InstanceOrigin;
|
||||
output.InstanceParams = p0.InstanceParams;
|
||||
return output;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
MaterialInput GetMaterialInput(PixelInput input)
|
||||
{
|
||||
MaterialInput output = GetGeometryMaterialInput(input.Geometry);
|
||||
output.TwoSidedSign = WorldDeterminantSign * (input.IsFrontFace ? 1.0 : -1.0);
|
||||
output.SvPosition = input.Position;
|
||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||
output.CustomVSToPS = input.CustomVSToPS;
|
||||
#endif
|
||||
return output;
|
||||
}
|
||||
|
||||
// Gets the local to world transform matrix (supports instancing)
|
||||
#if USE_INSTANCING
|
||||
#define GetInstanceTransform(input) float4x4(float4(input.InstanceTransform1.xyz, 0.0f), float4(input.InstanceTransform2.xyz, 0.0f), float4(input.InstanceTransform3.xyz, 0.0f), float4(input.InstanceOrigin.xyz, 1.0f))
|
||||
#else
|
||||
#define GetInstanceTransform(input) WorldMatrix;
|
||||
#endif
|
||||
|
||||
// Removes the scale vector from the local to world transformation matrix (supports instancing)
|
||||
float3x3 RemoveScaleFromLocalToWorld(float3x3 localToWorld)
|
||||
{
|
||||
#if USE_INSTANCING
|
||||
// Extract per axis scales from localToWorld transform
|
||||
float scaleX = length(localToWorld[0]);
|
||||
float scaleY = length(localToWorld[1]);
|
||||
float scaleZ = length(localToWorld[2]);
|
||||
float3 invScale = float3(
|
||||
scaleX > 0.00001f ? 1.0f / scaleX : 0.0f,
|
||||
scaleY > 0.00001f ? 1.0f / scaleY : 0.0f,
|
||||
scaleZ > 0.00001f ? 1.0f / scaleZ : 0.0f);
|
||||
#else
|
||||
float3 invScale = WorldInvScale;
|
||||
#endif
|
||||
localToWorld[0] *= invScale.x;
|
||||
localToWorld[1] *= invScale.y;
|
||||
localToWorld[2] *= invScale.z;
|
||||
return localToWorld;
|
||||
}
|
||||
|
||||
// Transforms a vector from tangent space to world space
|
||||
float3 TransformTangentVectorToWorld(MaterialInput input, float3 tangentVector)
|
||||
{
|
||||
return mul(tangentVector, input.TBN);
|
||||
}
|
||||
|
||||
// Transforms a vector from world space to tangent space
|
||||
float3 TransformWorldVectorToTangent(MaterialInput input, float3 worldVector)
|
||||
{
|
||||
return mul(input.TBN, worldVector);
|
||||
}
|
||||
|
||||
// Transforms a vector from world space to view space
|
||||
float3 TransformWorldVectorToView(MaterialInput input, float3 worldVector)
|
||||
{
|
||||
return mul(worldVector, (float3x3)ViewMatrix);
|
||||
}
|
||||
|
||||
// Transforms a vector from view space to world space
|
||||
float3 TransformViewVectorToWorld(MaterialInput input, float3 viewVector)
|
||||
{
|
||||
return mul((float3x3)ViewMatrix, viewVector);
|
||||
}
|
||||
|
||||
// Transforms a vector from local space to world space
|
||||
float3 TransformLocalVectorToWorld(MaterialInput input, float3 localVector)
|
||||
{
|
||||
float3x3 localToWorld = (float3x3)GetInstanceTransform(input);
|
||||
//localToWorld = RemoveScaleFromLocalToWorld(localToWorld);
|
||||
return mul(localVector, localToWorld);
|
||||
}
|
||||
|
||||
// Transforms a vector from local space to world space
|
||||
float3 TransformWorldVectorToLocal(MaterialInput input, float3 worldVector)
|
||||
{
|
||||
float3x3 localToWorld = (float3x3)GetInstanceTransform(input);
|
||||
//localToWorld = RemoveScaleFromLocalToWorld(localToWorld);
|
||||
return mul(localToWorld, worldVector);
|
||||
}
|
||||
|
||||
// Gets the current object position (supports instancing)
|
||||
float3 GetObjectPosition(MaterialInput input)
|
||||
{
|
||||
return input.InstanceOrigin.xyz;
|
||||
}
|
||||
|
||||
// Gets the current object size (supports instancing)
|
||||
float3 GetObjectSize(MaterialInput input)
|
||||
{
|
||||
float4x4 world = GetInstanceTransform(input);
|
||||
return GeometrySize * float3(world._m00, world._m11, world._m22);
|
||||
}
|
||||
|
||||
// Get the current object random value (supports instancing)
|
||||
float GetPerInstanceRandom(MaterialInput input)
|
||||
{
|
||||
return input.InstanceParams.x;
|
||||
}
|
||||
|
||||
// Get the current object LOD transition dither factor (supports instancing)
|
||||
float GetLODDitherFactor(MaterialInput input)
|
||||
{
|
||||
#if USE_DITHERED_LOD_TRANSITION
|
||||
return input.InstanceParams.y;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Gets the interpolated vertex color (in linear space)
|
||||
float4 GetVertexColor(MaterialInput input)
|
||||
{
|
||||
#if USE_VERTEX_COLOR
|
||||
return input.VertexColor;
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
@8
|
||||
|
||||
// Get material properties function (for vertex shader)
|
||||
Material GetMaterialVS(MaterialInput input)
|
||||
{
|
||||
@5
|
||||
}
|
||||
|
||||
// Get material properties function (for domain shader)
|
||||
Material GetMaterialDS(MaterialInput input)
|
||||
{
|
||||
@6
|
||||
}
|
||||
|
||||
// Get material properties function (for pixel shader)
|
||||
Material GetMaterialPS(MaterialInput input)
|
||||
{
|
||||
@4
|
||||
}
|
||||
|
||||
// Calculates the transform matrix from mesh tangent space to local space
|
||||
float3x3 CalcTangentToLocal(ModelInput input)
|
||||
{
|
||||
float bitangentSign = input.Tangent.w ? -1.0f : +1.0f;
|
||||
float3 normal = input.Normal.xyz * 2.0 - 1.0;
|
||||
float3 tangent = input.Tangent.xyz * 2.0 - 1.0;
|
||||
float3 bitangent = cross(normal, tangent) * bitangentSign;
|
||||
return float3x3(tangent, bitangent, normal);
|
||||
}
|
||||
|
||||
float3x3 CalcTangentToWorld(float4x4 world, float3x3 tangentToLocal)
|
||||
{
|
||||
float3x3 localToWorld = RemoveScaleFromLocalToWorld((float3x3)world);
|
||||
return mul(tangentToLocal, localToWorld);
|
||||
}
|
||||
|
||||
// Vertex Shader function for GBuffer Pass and Depth Pass (with full vertex data)
|
||||
META_VS(true, FEATURE_LEVEL_ES2)
|
||||
META_PERMUTATION_1(USE_INSTANCING=0)
|
||||
META_PERMUTATION_1(USE_INSTANCING=1)
|
||||
META_VS_IN_ELEMENT(POSITION, 0, R32G32B32_FLOAT, 0, 0, PER_VERTEX, 0, true)
|
||||
META_VS_IN_ELEMENT(TEXCOORD, 0, R16G16_FLOAT, 1, 0, PER_VERTEX, 0, true)
|
||||
META_VS_IN_ELEMENT(NORMAL, 0, R10G10B10A2_UNORM, 1, ALIGN, PER_VERTEX, 0, true)
|
||||
META_VS_IN_ELEMENT(TANGENT, 0, R10G10B10A2_UNORM, 1, ALIGN, PER_VERTEX, 0, true)
|
||||
META_VS_IN_ELEMENT(TEXCOORD, 1, R16G16_FLOAT, 1, ALIGN, PER_VERTEX, 0, true)
|
||||
META_VS_IN_ELEMENT(COLOR, 0, R8G8B8A8_UNORM, 2, 0, PER_VERTEX, 0, USE_VERTEX_COLOR)
|
||||
META_VS_IN_ELEMENT(ATTRIBUTE,0, R32G32B32A32_FLOAT,3, 0, PER_INSTANCE, 1, USE_INSTANCING)
|
||||
META_VS_IN_ELEMENT(ATTRIBUTE,1, R32G32B32A32_FLOAT,3, ALIGN, PER_INSTANCE, 1, USE_INSTANCING)
|
||||
META_VS_IN_ELEMENT(ATTRIBUTE,2, R32G32B32_FLOAT, 3, ALIGN, PER_INSTANCE, 1, USE_INSTANCING)
|
||||
META_VS_IN_ELEMENT(ATTRIBUTE,3, R32G32B32_FLOAT, 3, ALIGN, PER_INSTANCE, 1, USE_INSTANCING)
|
||||
META_VS_IN_ELEMENT(ATTRIBUTE,4, R16G16B16A16_FLOAT,3, ALIGN, PER_INSTANCE, 1, USE_INSTANCING)
|
||||
VertexOutput VS(ModelInput input)
|
||||
{
|
||||
VertexOutput output;
|
||||
|
||||
// Compute world space vertex position
|
||||
float4x4 world = GetInstanceTransform(input);
|
||||
output.Geometry.WorldPosition = mul(float4(input.Position.xyz, 1), world).xyz;
|
||||
output.Geometry.PrevWorldPosition = mul(float4(input.Position.xyz, 1), PrevWorldMatrix).xyz;
|
||||
|
||||
// Compute clip space position
|
||||
output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
|
||||
|
||||
// Pass vertex attributes
|
||||
output.Geometry.TexCoord = input.TexCoord;
|
||||
#if USE_VERTEX_COLOR
|
||||
output.Geometry.VertexColor = input.Color;
|
||||
#endif
|
||||
output.Geometry.InstanceOrigin = world[3].xyz;
|
||||
#if USE_INSTANCING
|
||||
output.Geometry.LightmapUV = input.LightmapUV * input.InstanceLightmapArea.zw + input.InstanceLightmapArea.xy;
|
||||
output.Geometry.InstanceParams = float2(input.InstanceOrigin.w, input.InstanceTransform1.w);
|
||||
#else
|
||||
#if CAN_USE_LIGHTMAP
|
||||
output.Geometry.LightmapUV = input.LightmapUV * LightmapArea.zw + LightmapArea.xy;
|
||||
#else
|
||||
output.Geometry.LightmapUV = input.LightmapUV;
|
||||
#endif
|
||||
output.Geometry.InstanceParams = float2(PerInstanceRandom, LODDitherFactor);
|
||||
#endif
|
||||
|
||||
// Calculate tanget space to world space transformation matrix for unit vectors
|
||||
float3x3 tangentToLocal = CalcTangentToLocal(input);
|
||||
float3x3 tangentToWorld = CalcTangentToWorld(world, tangentToLocal);
|
||||
output.Geometry.WorldNormal = tangentToWorld[2];
|
||||
output.Geometry.WorldTangent.xyz = tangentToWorld[0];
|
||||
output.Geometry.WorldTangent.w = input.Tangent.w ? -1.0f : +1.0f;
|
||||
|
||||
// Get material input params if need to evaluate any material property
|
||||
#if USE_POSITION_OFFSET || USE_TESSELLATION || USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||
MaterialInput materialInput = GetGeometryMaterialInput(output.Geometry);
|
||||
materialInput.TwoSidedSign = WorldDeterminantSign;
|
||||
materialInput.SvPosition = output.Position;
|
||||
materialInput.PreSkinnedPosition = input.Position.xyz;
|
||||
materialInput.PreSkinnedNormal = tangentToLocal[2].xyz;
|
||||
#if USE_INSTANCING
|
||||
materialInput.InstanceTransform1 = input.InstanceTransform1.xyz;
|
||||
materialInput.InstanceTransform2 = input.InstanceTransform2.xyz;
|
||||
materialInput.InstanceTransform3 = input.InstanceTransform3.xyz;
|
||||
#endif
|
||||
Material material = GetMaterialVS(materialInput);
|
||||
#endif
|
||||
|
||||
// Apply world position offset per-vertex
|
||||
#if USE_POSITION_OFFSET
|
||||
output.Geometry.WorldPosition += material.PositionOffset;
|
||||
output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
|
||||
#endif
|
||||
|
||||
// Get tessalation multiplier (per vertex)
|
||||
#if USE_TESSELLATION
|
||||
output.TessellationMultiplier = material.TessellationMultiplier;
|
||||
#endif
|
||||
|
||||
// Copy interpolants for other shader stages
|
||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||
output.CustomVSToPS = material.CustomVSToPS;
|
||||
#endif
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
// Vertex Shader function for Depth Pass
|
||||
META_VS(true, FEATURE_LEVEL_ES2)
|
||||
META_PERMUTATION_1(USE_INSTANCING=0)
|
||||
META_PERMUTATION_1(USE_INSTANCING=1)
|
||||
META_VS_IN_ELEMENT(POSITION, 0, R32G32B32_FLOAT, 0, 0, PER_VERTEX, 0, true)
|
||||
META_VS_IN_ELEMENT(ATTRIBUTE,0, R32G32B32A32_FLOAT,3, 0, PER_INSTANCE, 1, USE_INSTANCING)
|
||||
META_VS_IN_ELEMENT(ATTRIBUTE,1, R32G32B32A32_FLOAT,3, ALIGN, PER_INSTANCE, 1, USE_INSTANCING)
|
||||
META_VS_IN_ELEMENT(ATTRIBUTE,2, R32G32B32_FLOAT, 3, ALIGN, PER_INSTANCE, 1, USE_INSTANCING)
|
||||
META_VS_IN_ELEMENT(ATTRIBUTE,3, R32G32B32_FLOAT, 3, ALIGN, PER_INSTANCE, 1, USE_INSTANCING)
|
||||
META_VS_IN_ELEMENT(ATTRIBUTE,4, R16G16B16A16_FLOAT,3, ALIGN, PER_INSTANCE, 1, USE_INSTANCING)
|
||||
float4 VS_Depth(ModelInput_PosOnly input) : SV_Position
|
||||
{
|
||||
float4x4 world = GetInstanceTransform(input);
|
||||
float3 worldPosition = mul(float4(input.Position.xyz, 1), world).xyz;
|
||||
float4 position = mul(float4(worldPosition, 1), ViewProjectionMatrix);
|
||||
return position;
|
||||
}
|
||||
|
||||
#if USE_SKINNING
|
||||
|
||||
// The skeletal bones matrix buffer (stored as 4x3, 3 float4 behind each other)
|
||||
Buffer<float4> BoneMatrices : register(t0);
|
||||
|
||||
#if PER_BONE_MOTION_BLUR
|
||||
|
||||
// The skeletal bones matrix buffer from the previous frame
|
||||
Buffer<float4> PrevBoneMatrices : register(t1);
|
||||
|
||||
float3x4 GetPrevBoneMatrix(int index)
|
||||
{
|
||||
float4 a = PrevBoneMatrices[index * 3];
|
||||
float4 b = PrevBoneMatrices[index * 3 + 1];
|
||||
float4 c = PrevBoneMatrices[index * 3 + 2];
|
||||
return float3x4(a, b, c);
|
||||
}
|
||||
|
||||
float3 SkinPrevPosition(ModelInput_Skinned input)
|
||||
{
|
||||
float4 position = float4(input.Position.xyz, 1);
|
||||
float3x4 boneMatrix = input.BlendWeights.x * GetPrevBoneMatrix(input.BlendIndices.x);
|
||||
boneMatrix += input.BlendWeights.y * GetPrevBoneMatrix(input.BlendIndices.y);
|
||||
boneMatrix += input.BlendWeights.z * GetPrevBoneMatrix(input.BlendIndices.z);
|
||||
boneMatrix += input.BlendWeights.w * GetPrevBoneMatrix(input.BlendIndices.w);
|
||||
return mul(boneMatrix, position);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Cached skinning data to avoid multiple calculation
|
||||
struct SkinningData
|
||||
{
|
||||
float3x4 BlendMatrix;
|
||||
};
|
||||
|
||||
// Calculates the transposed transform matrix for the given bone index
|
||||
float3x4 GetBoneMatrix(int index)
|
||||
{
|
||||
float4 a = BoneMatrices[index * 3];
|
||||
float4 b = BoneMatrices[index * 3 + 1];
|
||||
float4 c = BoneMatrices[index * 3 + 2];
|
||||
return float3x4(a, b, c);
|
||||
}
|
||||
|
||||
// Calculates the transposed transform matrix for the given vertex (uses blending)
|
||||
float3x4 GetBoneMatrix(ModelInput_Skinned input)
|
||||
{
|
||||
float3x4 boneMatrix = input.BlendWeights.x * GetBoneMatrix(input.BlendIndices.x);
|
||||
boneMatrix += input.BlendWeights.y * GetBoneMatrix(input.BlendIndices.y);
|
||||
boneMatrix += input.BlendWeights.z * GetBoneMatrix(input.BlendIndices.z);
|
||||
boneMatrix += input.BlendWeights.w * GetBoneMatrix(input.BlendIndices.w);
|
||||
return boneMatrix;
|
||||
}
|
||||
|
||||
// Transforms the vertex position by weighted sum of the skinning matrices
|
||||
float3 SkinPosition(ModelInput_Skinned input, SkinningData data)
|
||||
{
|
||||
return mul(data.BlendMatrix, float4(input.Position.xyz, 1));
|
||||
}
|
||||
|
||||
// Transforms the vertex position by weighted sum of the skinning matrices
|
||||
float3x3 SkinTangents(ModelInput_Skinned input, SkinningData data)
|
||||
{
|
||||
// Unpack vertex tangent frame
|
||||
float bitangentSign = input.Tangent.w ? -1.0f : +1.0f;
|
||||
float3 normal = input.Normal.xyz * 2.0 - 1.0;
|
||||
float3 tangent = input.Tangent.xyz * 2.0 - 1.0;
|
||||
|
||||
// Apply skinning
|
||||
tangent = mul(data.BlendMatrix, float4(tangent, 0));
|
||||
normal = mul(data.BlendMatrix, float4(normal, 0));
|
||||
|
||||
float3 bitangent = cross(normal, tangent) * bitangentSign;
|
||||
return float3x3(tangent, bitangent, normal);
|
||||
}
|
||||
|
||||
// Vertex Shader function for GBuffers/Depth Pass (skinned mesh rendering)
|
||||
META_VS(true, FEATURE_LEVEL_ES2)
|
||||
META_PERMUTATION_1(USE_SKINNING=1)
|
||||
META_PERMUTATION_2(USE_SKINNING=1, PER_BONE_MOTION_BLUR=1)
|
||||
META_VS_IN_ELEMENT(POSITION, 0, R32G32B32_FLOAT, 0, 0, PER_VERTEX, 0, true)
|
||||
META_VS_IN_ELEMENT(TEXCOORD, 0, R16G16_FLOAT, 0, ALIGN, PER_VERTEX, 0, true)
|
||||
META_VS_IN_ELEMENT(NORMAL, 0, R10G10B10A2_UNORM, 0, ALIGN, PER_VERTEX, 0, true)
|
||||
META_VS_IN_ELEMENT(TANGENT, 0, R10G10B10A2_UNORM, 0, ALIGN, PER_VERTEX, 0, true)
|
||||
META_VS_IN_ELEMENT(BLENDINDICES, 0, R8G8B8A8_UINT, 0, ALIGN, PER_VERTEX, 0, true)
|
||||
META_VS_IN_ELEMENT(BLENDWEIGHT, 0, R16G16B16A16_FLOAT,0, ALIGN, PER_VERTEX, 0, true)
|
||||
VertexOutput VS_Skinned(ModelInput_Skinned input)
|
||||
{
|
||||
VertexOutput output;
|
||||
|
||||
// Perform skinning
|
||||
SkinningData data;
|
||||
data.BlendMatrix = GetBoneMatrix(input);
|
||||
float3 position = SkinPosition(input, data);
|
||||
float3x3 tangentToLocal = SkinTangents(input, data);
|
||||
|
||||
// Compute world space vertex position
|
||||
float4x4 world = GetInstanceTransform(input);
|
||||
output.Geometry.WorldPosition = mul(float4(position, 1), world).xyz;
|
||||
#if PER_BONE_MOTION_BLUR
|
||||
float3 prevPosition = SkinPrevPosition(input);
|
||||
output.Geometry.PrevWorldPosition = mul(float4(prevPosition, 1), PrevWorldMatrix).xyz;
|
||||
#else
|
||||
output.Geometry.PrevWorldPosition = mul(float4(position, 1), PrevWorldMatrix).xyz;
|
||||
#endif
|
||||
|
||||
// Compute clip space position
|
||||
output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
|
||||
|
||||
// Pass vertex attributes
|
||||
output.Geometry.TexCoord = input.TexCoord;
|
||||
#if USE_VERTEX_COLOR
|
||||
output.Geometry.VertexColor = float4(0, 0, 0, 1);
|
||||
#endif
|
||||
output.Geometry.LightmapUV = float2(0, 0);
|
||||
output.Geometry.InstanceOrigin = world[3].xyz;
|
||||
#if USE_INSTANCING
|
||||
output.Geometry.InstanceParams = float2(input.InstanceOrigin.w, input.InstanceTransform1.w);
|
||||
#else
|
||||
output.Geometry.InstanceParams = float2(PerInstanceRandom, LODDitherFactor);
|
||||
#endif
|
||||
|
||||
// Calculate tanget space to world space transformation matrix for unit vectors
|
||||
float3x3 tangentToWorld = CalcTangentToWorld(world, tangentToLocal);
|
||||
output.Geometry.WorldNormal = tangentToWorld[2];
|
||||
output.Geometry.WorldTangent.xyz = tangentToWorld[0];
|
||||
output.Geometry.WorldTangent.w = input.Tangent.w ? -1.0f : +1.0f;
|
||||
|
||||
// Get material input params if need to evaluate any material property
|
||||
#if USE_POSITION_OFFSET || USE_TESSELLATION || USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||
MaterialInput materialInput = GetGeometryMaterialInput(output.Geometry);
|
||||
materialInput.TwoSidedSign = WorldDeterminantSign;
|
||||
materialInput.SvPosition = output.Position;
|
||||
materialInput.PreSkinnedPosition = input.Position.xyz;
|
||||
materialInput.PreSkinnedNormal = tangentToLocal[2].xyz;
|
||||
Material material = GetMaterialVS(materialInput);
|
||||
#endif
|
||||
|
||||
// Apply world position offset per-vertex
|
||||
#if USE_POSITION_OFFSET
|
||||
output.Geometry.WorldPosition += material.PositionOffset;
|
||||
output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
|
||||
#endif
|
||||
|
||||
// Get tessalation multiplier (per vertex)
|
||||
#if USE_TESSELLATION
|
||||
output.TessellationMultiplier = material.TessellationMultiplier;
|
||||
#endif
|
||||
|
||||
// Copy interpolants for other shader stages
|
||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||
output.CustomVSToPS = material.CustomVSToPS;
|
||||
#endif
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if USE_DITHERED_LOD_TRANSITION
|
||||
|
||||
void ClipLODTransition(PixelInput input)
|
||||
{
|
||||
float ditherFactor = input.Geometry.InstanceParams.y;
|
||||
if (abs(ditherFactor) > 0.001)
|
||||
{
|
||||
float randGrid = cos(dot(floor(input.Position.xy), float2(347.83452793, 3343.28371863)));
|
||||
float randGridFrac = frac(randGrid * 1000.0);
|
||||
half mask = (ditherFactor < 0.0) ? (ditherFactor + 1.0 > randGridFrac) : (ditherFactor < randGridFrac);
|
||||
clip(mask - 0.001);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Pixel Shader function for Depth Pass
|
||||
META_PS(true, FEATURE_LEVEL_ES2)
|
||||
void PS_Depth(PixelInput input)
|
||||
{
|
||||
#if USE_DITHERED_LOD_TRANSITION
|
||||
// LOD masking
|
||||
ClipLODTransition(input);
|
||||
#endif
|
||||
|
||||
#if MATERIAL_MASKED || MATERIAL_BLEND != MATERIAL_BLEND_OPAQUE
|
||||
// Get material parameters
|
||||
MaterialInput materialInput = GetMaterialInput(input);
|
||||
Material material = GetMaterialPS(materialInput);
|
||||
|
||||
// Perform per pixel clipping
|
||||
#if MATERIAL_MASKED
|
||||
clip(material.Mask - MATERIAL_MASK_THRESHOLD);
|
||||
#endif
|
||||
#if MATERIAL_BLEND != MATERIAL_BLEND_OPAQUE
|
||||
clip(material.Opacity - MATERIAL_OPACITY_THRESHOLD);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
@9
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,6 @@
|
||||
|
||||
#define MATERIAL 1
|
||||
@3
|
||||
|
||||
// Enables/disables smooth terrain chunks LOD transitions (with morphing higher LOD near edges to the lower LOD in the neighbour)
|
||||
#define USE_SMOOTH_LOD_TRANSITION 1
|
||||
|
||||
@@ -26,7 +25,6 @@ float3 ViewDir;
|
||||
float TimeParam;
|
||||
float4 ViewInfo;
|
||||
float4 ScreenSize;
|
||||
float4 LightmapArea;
|
||||
float3 WorldInvScale;
|
||||
float WorldDeterminantSign;
|
||||
float PerInstanceRandom;
|
||||
@@ -39,35 +37,31 @@ float2 OffsetUV;
|
||||
float2 Dummy0;
|
||||
@1META_CB_END
|
||||
|
||||
#if CAN_USE_LIGHTMAP
|
||||
|
||||
// Irradiance and directionality prebaked lightmaps
|
||||
Texture2D Lightmap0 : register(t0);
|
||||
Texture2D Lightmap1 : register(t1);
|
||||
Texture2D Lightmap2 : register(t2);
|
||||
|
||||
#endif
|
||||
|
||||
// Terrain data
|
||||
Texture2D Heightmap : register(t3);
|
||||
Texture2D Splatmap0 : register(t4);
|
||||
Texture2D Splatmap1 : register(t5);
|
||||
Texture2D Heightmap : register(t0);
|
||||
Texture2D Splatmap0 : register(t1);
|
||||
Texture2D Splatmap1 : register(t2);
|
||||
|
||||
// Material shader resources
|
||||
// Shader resources
|
||||
@2
|
||||
// Geometry data passed though the graphics rendering stages up to the pixel shader
|
||||
struct GeometryData
|
||||
{
|
||||
float3 WorldPosition : TEXCOORD0;
|
||||
float2 TexCoord : TEXCOORD1;
|
||||
float2 LightmapUV : TEXCOORD2;
|
||||
float3 WorldNormal : TEXCOORD3;
|
||||
float HolesMask : TEXCOORD4;
|
||||
#if USE_TERRAIN_LAYERS
|
||||
float4 Layers[TERRAIN_LAYERS_DATA_SIZE] : TEXCOORD5;
|
||||
#endif
|
||||
};
|
||||
|
||||
// Interpolants passed from the vertex shader
|
||||
struct VertexOutput
|
||||
{
|
||||
float4 Position : SV_Position;
|
||||
float3 WorldPosition : TEXCOORD0;
|
||||
float2 TexCoord : TEXCOORD1;
|
||||
float2 LightmapUV : TEXCOORD2;
|
||||
float3 WorldNormal : TEXCOORD3;
|
||||
float HolesMask : TEXCOORD4;
|
||||
#if USE_TERRAIN_LAYERS
|
||||
float4 Layers[TERRAIN_LAYERS_DATA_SIZE] : TEXCOORD5;
|
||||
#endif
|
||||
float4 Position : SV_Position;
|
||||
GeometryData Geometry;
|
||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||
float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9;
|
||||
#endif
|
||||
@@ -79,19 +73,12 @@ struct VertexOutput
|
||||
// Interpolants passed to the pixel shader
|
||||
struct PixelInput
|
||||
{
|
||||
float4 Position : SV_Position;
|
||||
float3 WorldPosition : TEXCOORD0;
|
||||
float2 TexCoord : TEXCOORD1;
|
||||
float2 LightmapUV : TEXCOORD2;
|
||||
float3 WorldNormal : TEXCOORD3;
|
||||
float HolesMask : TEXCOORD4;
|
||||
#if USE_TERRAIN_LAYERS
|
||||
float4 Layers[TERRAIN_LAYERS_DATA_SIZE] : TEXCOORD5;
|
||||
#endif
|
||||
float4 Position : SV_Position;
|
||||
GeometryData Geometry;
|
||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||
float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9;
|
||||
#endif
|
||||
bool IsFrontFace : SV_IsFrontFace;
|
||||
bool IsFrontFace : SV_IsFrontFace;
|
||||
};
|
||||
|
||||
// Material properties generation input
|
||||
@@ -116,25 +103,66 @@ struct MaterialInput
|
||||
#endif
|
||||
};
|
||||
|
||||
// Extracts geometry data to the material input
|
||||
MaterialInput GetGeometryMaterialInput(GeometryData geometry)
|
||||
{
|
||||
MaterialInput output = (MaterialInput)0;
|
||||
output.WorldPosition = geometry.WorldPosition;
|
||||
output.TexCoord = geometry.TexCoord;
|
||||
#if USE_LIGHTMAP
|
||||
output.LightmapUV = geometry.LightmapUV;
|
||||
#endif
|
||||
output.TBN = CalcTangentBasisFromWorldNormal(geometry.WorldNormal);
|
||||
output.HolesMask = geometry.HolesMask;
|
||||
#if USE_TERRAIN_LAYERS
|
||||
output.Layers = geometry.Layers;
|
||||
#endif
|
||||
return output;
|
||||
}
|
||||
|
||||
#if USE_TESSELLATION
|
||||
|
||||
// Interpolates the geometry positions data only (used by the tessallation when generating vertices)
|
||||
#define InterpolateGeometryPositions(output, p0, w0, p1, w1, p2, w2, offset) output.WorldPosition = p0.WorldPosition * w0 + p1.WorldPosition * w1 + p2.WorldPosition * w2 + offset
|
||||
|
||||
// Offsets the geometry positions data only (used by the tessallation when generating vertices)
|
||||
#define OffsetGeometryPositions(geometry, offset) geometry.WorldPosition += offset
|
||||
|
||||
// Applies the Phong tessallation to the geometry positions (used by the tessallation when doing Phong tess)
|
||||
#define ApplyGeometryPositionsPhongTess(geometry, p0, p1, p2, U, V, W) \
|
||||
float3 posProjectedU = TessalationProjectOntoPlane(p0.WorldNormal, p0.WorldPosition, geometry.WorldPosition); \
|
||||
float3 posProjectedV = TessalationProjectOntoPlane(p1.WorldNormal, p1.WorldPosition, geometry.WorldPosition); \
|
||||
float3 posProjectedW = TessalationProjectOntoPlane(p2.WorldNormal, p2.WorldPosition, geometry.WorldPosition); \
|
||||
geometry.WorldPosition = U * posProjectedU + V * posProjectedV + W * posProjectedW
|
||||
|
||||
// Interpolates the geometry data except positions (used by the tessallation when generating vertices)
|
||||
GeometryData InterpolateGeometry(GeometryData p0, float w0, GeometryData p1, float w1, GeometryData p2, float w2)
|
||||
{
|
||||
GeometryData output = (GeometryData)0;
|
||||
output.TexCoord = p0.TexCoord * w0 + p1.TexCoord * w1 + p2.TexCoord * w2;
|
||||
output.LightmapUV = p0.LightmapUV * w0 + p1.LightmapUV * w1 + p2.LightmapUV * w2;
|
||||
output.WorldNormal = p0.WorldNormal * w0 + p1.WorldNormal * w1 + p2.WorldNormal * w2;
|
||||
output.WorldNormal = normalize(output.WorldNormal);
|
||||
output.HolesMask = p0.HolesMask * w0 + p1.HolesMask * w1 + p2.HolesMask * w2;
|
||||
#if USE_TERRAIN_LAYERS
|
||||
UNROLL
|
||||
for (int i = 0; i < TERRAIN_LAYERS_DATA_SIZE; i++)
|
||||
output.Layers[i] = p0.Layers[i] * w0 + p1.Layers[i] * w1 + p2.Layers[i] * w2;
|
||||
#endif
|
||||
return output;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
MaterialInput GetMaterialInput(PixelInput input)
|
||||
{
|
||||
MaterialInput result = (MaterialInput)0;
|
||||
result.WorldPosition = input.WorldPosition;
|
||||
result.TexCoord = input.TexCoord;
|
||||
#if USE_LIGHTMAP
|
||||
result.LightmapUV = input.LightmapUV;
|
||||
#endif
|
||||
result.TBN = CalcTangentBasisFromWorldNormal(input.WorldNormal);
|
||||
result.TwoSidedSign = WorldDeterminantSign * (input.IsFrontFace ? 1.0 : -1.0);
|
||||
result.SvPosition = input.Position;
|
||||
result.HolesMask = input.HolesMask;
|
||||
#if USE_TERRAIN_LAYERS
|
||||
result.Layers = input.Layers;
|
||||
#endif
|
||||
MaterialInput output = GetGeometryMaterialInput(input.Geometry);
|
||||
output.TwoSidedSign = WorldDeterminantSign * (input.IsFrontFace ? 1.0 : -1.0);
|
||||
output.SvPosition = input.Position;
|
||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||
result.CustomVSToPS = input.CustomVSToPS;
|
||||
output.CustomVSToPS = input.CustomVSToPS;
|
||||
#endif
|
||||
return result;
|
||||
return output;
|
||||
}
|
||||
|
||||
// Removes the scale vector from the local to world transformation matrix
|
||||
@@ -216,6 +244,8 @@ float4 GetVertexColor(MaterialInput input)
|
||||
return 1;
|
||||
}
|
||||
|
||||
@8
|
||||
|
||||
// Get material properties function (for vertex shader)
|
||||
Material GetMaterialVS(MaterialInput input)
|
||||
{
|
||||
@@ -234,9 +264,6 @@ Material GetMaterialPS(MaterialInput input)
|
||||
@4
|
||||
}
|
||||
|
||||
// Fix line for errors/warnings for shader code from template
|
||||
#line 1000
|
||||
|
||||
// Calculates LOD value (with fractional part for blending)
|
||||
float CalcLOD(float2 xy, float4 morph)
|
||||
{
|
||||
@@ -285,7 +312,7 @@ float3x3 CalcTangentToWorld(float4x4 world, float3x3 tangentToLocal)
|
||||
struct TerrainVertexInput
|
||||
{
|
||||
float2 TexCoord : TEXCOORD0;
|
||||
float4 Morph : TEXCOORD1;
|
||||
float4 Morph : TEXCOORD1;
|
||||
};
|
||||
|
||||
// Vertex Shader function for terrain rendering
|
||||
@@ -336,7 +363,7 @@ VertexOutput VS(TerrainVertexInput input)
|
||||
float2 normalTemp = float2(heightmapValue.b, heightmapValue.a) * 2.0f - 1.0f;
|
||||
float3 normal = float3(normalTemp.x, sqrt(1.0 - saturate(dot(normalTemp, normalTemp))), normalTemp.y);
|
||||
normal = normalize(normal);
|
||||
output.HolesMask = isHole ? 0 : 1;
|
||||
output.Geometry.HolesMask = isHole ? 0 : 1;
|
||||
if (isHole)
|
||||
{
|
||||
normal = float3(0, 1, 0);
|
||||
@@ -353,10 +380,10 @@ VertexOutput VS(TerrainVertexInput input)
|
||||
float3 position = float3(positionXZ.x, height, positionXZ.y);
|
||||
|
||||
// Compute world space vertex position
|
||||
output.WorldPosition = mul(float4(position, 1), WorldMatrix).xyz;
|
||||
output.Geometry.WorldPosition = mul(float4(position, 1), WorldMatrix).xyz;
|
||||
|
||||
// Compute clip space position
|
||||
output.Position = mul(float4(output.WorldPosition.xyz, 1), ViewProjectionMatrix);
|
||||
output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
|
||||
|
||||
// Pass vertex attributes
|
||||
#if USE_SMOOTH_LOD_TRANSITION
|
||||
@@ -364,46 +391,46 @@ VertexOutput VS(TerrainVertexInput input)
|
||||
#else
|
||||
float2 texCoord = input.TexCoord;
|
||||
#endif
|
||||
output.TexCoord = positionXZ * (1.0f / TerrainChunkSizeLOD0) + OffsetUV;
|
||||
output.LightmapUV = texCoord * LightmapArea.zw + LightmapArea.xy;
|
||||
output.Geometry.TexCoord = positionXZ * (1.0f / TerrainChunkSizeLOD0) + OffsetUV;
|
||||
output.Geometry.LightmapUV = texCoord * LightmapArea.zw + LightmapArea.xy;
|
||||
|
||||
// Extract terrain layers weights from the splatmap
|
||||
#if USE_TERRAIN_LAYERS
|
||||
output.Layers[0] = splatmap0Value;
|
||||
output.Geometry.Layers[0] = splatmap0Value;
|
||||
#if TERRAIN_LAYERS_DATA_SIZE > 1
|
||||
output.Layers[1] = splatmap1Value;
|
||||
output.Geometry.Layers[1] = splatmap1Value;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Compute world space normal vector
|
||||
float3x3 tangentToLocal = CalcTangentBasisFromWorldNormal(normal);
|
||||
float3x3 tangentToWorld = CalcTangentToWorld(WorldMatrix, tangentToLocal);
|
||||
output.WorldNormal = tangentToWorld[2];
|
||||
output.Geometry.WorldNormal = tangentToWorld[2];
|
||||
|
||||
// Get material input params if need to evaluate any material property
|
||||
#if USE_POSITION_OFFSET || USE_TESSELLATION || USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||
MaterialInput materialInput = (MaterialInput)0;
|
||||
materialInput.WorldPosition = output.WorldPosition;
|
||||
materialInput.TexCoord = output.TexCoord;
|
||||
materialInput.WorldPosition = output.Geometry.WorldPosition;
|
||||
materialInput.TexCoord = output.Geometry.TexCoord;
|
||||
#if USE_LIGHTMAP
|
||||
materialInput.LightmapUV = output.LightmapUV;
|
||||
materialInput.LightmapUV = output.Geometry.LightmapUV;
|
||||
#endif
|
||||
materialInput.TBN = CalcTangentBasisFromWorldNormal(output.WorldNormal);
|
||||
materialInput.TBN = CalcTangentBasisFromWorldNormal(output.Geometry.WorldNormal);
|
||||
materialInput.TwoSidedSign = WorldDeterminantSign;
|
||||
materialInput.SvPosition = output.Position;
|
||||
materialInput.PreSkinnedPosition = position;
|
||||
materialInput.PreSkinnedNormal = normal;
|
||||
materialInput.HolesMask = output.HolesMask;
|
||||
materialInput.HolesMask = output.Geometry.HolesMask;
|
||||
#if USE_TERRAIN_LAYERS
|
||||
materialInput.Layers = output.Layers;
|
||||
materialInput.Layers = output.Geometry.Layers;
|
||||
#endif
|
||||
Material material = GetMaterialVS(materialInput);
|
||||
#endif
|
||||
|
||||
// Apply world position offset per-vertex
|
||||
#if USE_POSITION_OFFSET
|
||||
output.WorldPosition += material.PositionOffset;
|
||||
output.Position = mul(float4(output.WorldPosition.xyz, 1), ViewProjectionMatrix);
|
||||
output.Geometry.WorldPosition += material.PositionOffset;
|
||||
output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
|
||||
#endif
|
||||
|
||||
// Get tessalation multiplier (per vertex)
|
||||
@@ -419,356 +446,9 @@ VertexOutput VS(TerrainVertexInput input)
|
||||
return output;
|
||||
}
|
||||
|
||||
#if USE_TESSELLATION
|
||||
|
||||
// Interpolants passed from the hull shader to the domain shader
|
||||
struct TessalationHSToDS
|
||||
{
|
||||
float4 Position : SV_Position;
|
||||
float3 WorldPosition : TEXCOORD0;
|
||||
float2 TexCoord : TEXCOORD1;
|
||||
float2 LightmapUV : TEXCOORD2;
|
||||
float3 WorldNormal : TEXCOORD3;
|
||||
float HolesMask : TEXCOORD4;
|
||||
#if USE_TERRAIN_LAYERS
|
||||
float4 Layers[TERRAIN_LAYERS_DATA_SIZE] : TEXCOORD5;
|
||||
#endif
|
||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||
float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9;
|
||||
#endif
|
||||
float TessellationMultiplier : TESS;
|
||||
};
|
||||
|
||||
// Interpolants passed from the domain shader and to the pixel shader
|
||||
struct TessalationDSToPS
|
||||
{
|
||||
float4 Position : SV_Position;
|
||||
float3 WorldPosition : TEXCOORD0;
|
||||
float2 TexCoord : TEXCOORD1;
|
||||
float2 LightmapUV : TEXCOORD2;
|
||||
float3 WorldNormal : TEXCOORD3;
|
||||
float HolesMask : TEXCOORD4;
|
||||
#if USE_TERRAIN_LAYERS
|
||||
float4 Layers[TERRAIN_LAYERS_DATA_SIZE] : TEXCOORD5;
|
||||
#endif
|
||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||
float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9;
|
||||
#endif
|
||||
};
|
||||
|
||||
MaterialInput GetMaterialInput(TessalationDSToPS input)
|
||||
{
|
||||
MaterialInput result = (MaterialInput)0;
|
||||
result.WorldPosition = input.WorldPosition;
|
||||
result.TexCoord = input.TexCoord;
|
||||
#if USE_LIGHTMAP
|
||||
result.LightmapUV = input.LightmapUV;
|
||||
#endif
|
||||
result.TBN = CalcTangentBasisFromWorldNormal(input.WorldNormal);
|
||||
result.TwoSidedSign = WorldDeterminantSign;
|
||||
result.SvPosition = input.Position;
|
||||
result.HolesMask = input.HolesMask;
|
||||
#if USE_TERRAIN_LAYERS
|
||||
result.Layers = input.Layers;
|
||||
#endif
|
||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||
result.CustomVSToPS = input.CustomVSToPS;
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
struct TessalationPatch
|
||||
{
|
||||
float EdgeTessFactor[3] : SV_TessFactor;
|
||||
float InsideTessFactor : SV_InsideTessFactor;
|
||||
#if MATERIAL_TESSELLATION == MATERIAL_TESSELLATION_PN
|
||||
float3 B210 : POSITION4;
|
||||
float3 B120 : POSITION5;
|
||||
float3 B021 : POSITION6;
|
||||
float3 B012 : POSITION7;
|
||||
float3 B102 : POSITION8;
|
||||
float3 B201 : POSITION9;
|
||||
float3 B111 : CENTER;
|
||||
#endif
|
||||
};
|
||||
|
||||
TessalationPatch HS_PatchConstant(InputPatch<VertexOutput, 3> input)
|
||||
{
|
||||
TessalationPatch output;
|
||||
|
||||
// Average tess factors along edges, and pick an edge tess factor for the interior tessellation
|
||||
float4 TessellationMultipliers;
|
||||
TessellationMultipliers.x = 0.5f * (input[1].TessellationMultiplier + input[2].TessellationMultiplier);
|
||||
TessellationMultipliers.y = 0.5f * (input[2].TessellationMultiplier + input[0].TessellationMultiplier);
|
||||
TessellationMultipliers.z = 0.5f * (input[0].TessellationMultiplier + input[1].TessellationMultiplier);
|
||||
TessellationMultipliers.w = 0.333f * (input[0].TessellationMultiplier + input[1].TessellationMultiplier + input[2].TessellationMultiplier);
|
||||
|
||||
TessellationMultipliers = clamp(TessellationMultipliers, 1, MAX_TESSELLATION_FACTOR);
|
||||
|
||||
output.EdgeTessFactor[0] = TessellationMultipliers.x; // 1->2 edge
|
||||
output.EdgeTessFactor[1] = TessellationMultipliers.y; // 2->0 edge
|
||||
output.EdgeTessFactor[2] = TessellationMultipliers.z; // 0->1 edge
|
||||
output.InsideTessFactor = TessellationMultipliers.w;
|
||||
|
||||
#if MATERIAL_TESSELLATION == MATERIAL_TESSELLATION_PN
|
||||
// Calculate PN-Triangle coefficients
|
||||
// Refer to Vlachos 2001 for the original formula
|
||||
float3 p1 = input[0].WorldPosition;
|
||||
float3 p2 = input[1].WorldPosition;
|
||||
float3 p3 = input[2].WorldPosition;
|
||||
float3 n1 = input[0].WorldNormal;
|
||||
float3 n2 = input[1].WorldNormal;
|
||||
float3 n3 = input[2].WorldNormal;
|
||||
|
||||
// Calculate control points
|
||||
output.B210 = (2.0f * p1 + p2 - dot((p2 - p1), n1) * n1) / 3.0f;
|
||||
output.B120 = (2.0f * p2 + p1 - dot((p1 - p2), n2) * n2) / 3.0f;
|
||||
output.B021 = (2.0f * p2 + p3 - dot((p3 - p2), n2) * n2) / 3.0f;
|
||||
output.B012 = (2.0f * p3 + p2 - dot((p2 - p3), n3) * n3) / 3.0f;
|
||||
output.B102 = (2.0f * p3 + p1 - dot((p1 - p3), n3) * n3) / 3.0f;
|
||||
output.B201 = (2.0f * p1 + p3 - dot((p3 - p1), n1) * n1) / 3.0f;
|
||||
float3 e = (output.B210 + output.B120 + output.B021 +
|
||||
output.B012 + output.B102 + output.B201) / 6.0f;
|
||||
float3 v = (p1 + p2 + p3) / 3.0f;
|
||||
output.B111 = e + ((e - v) / 2.0f);
|
||||
#endif
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
META_HS(USE_TESSELLATION, FEATURE_LEVEL_SM5)
|
||||
META_HS_PATCH(TESSELLATION_IN_CONTROL_POINTS)
|
||||
[domain("tri")]
|
||||
[partitioning("fractional_odd")]
|
||||
[outputtopology("triangle_cw")]
|
||||
[maxtessfactor(MAX_TESSELLATION_FACTOR)]
|
||||
[outputcontrolpoints(3)]
|
||||
[patchconstantfunc("HS_PatchConstant")]
|
||||
TessalationHSToDS HS(InputPatch<VertexOutput, TESSELLATION_IN_CONTROL_POINTS> input, uint ControlPointID : SV_OutputControlPointID)
|
||||
{
|
||||
TessalationHSToDS output;
|
||||
|
||||
// Pass through shader
|
||||
#define COPY(thing) output.thing = input[ControlPointID].thing;
|
||||
COPY(Position);
|
||||
COPY(WorldPosition);
|
||||
COPY(TexCoord);
|
||||
COPY(LightmapUV);
|
||||
COPY(WorldNormal);
|
||||
COPY(HolesMask);
|
||||
COPY(TessellationMultiplier);
|
||||
#if USE_TERRAIN_LAYERS
|
||||
COPY(Layers);
|
||||
#endif
|
||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||
COPY(CustomVSToPS);
|
||||
#endif
|
||||
#undef COPY
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
#if MATERIAL_TESSELLATION == MATERIAL_TESSELLATION_PHONG
|
||||
|
||||
// Orthogonal projection on to plane
|
||||
float3 ProjectOntoPlane(float3 planeNormal, float3 planePoint, float3 pointToProject)
|
||||
{
|
||||
return pointToProject - dot(pointToProject-planePoint, planeNormal) * planeNormal;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
META_DS(USE_TESSELLATION, FEATURE_LEVEL_SM5)
|
||||
[domain("tri")]
|
||||
TessalationDSToPS DS(TessalationPatch constantData, float3 barycentricCoords : SV_DomainLocation, const OutputPatch<TessalationHSToDS, 3> input)
|
||||
{
|
||||
TessalationDSToPS output;
|
||||
|
||||
// Get the barycentric coords
|
||||
float U = barycentricCoords.x;
|
||||
float V = barycentricCoords.y;
|
||||
float W = barycentricCoords.z;
|
||||
|
||||
// Interpolate patch attributes to generated vertices
|
||||
#define INTERPOLATE(thing) output.thing = U * input[0].thing + V * input[1].thing + W * input[2].thing
|
||||
#define COPY(thing) output.thing = input[0].thing
|
||||
INTERPOLATE(Position);
|
||||
#if MATERIAL_TESSELLATION == MATERIAL_TESSELLATION_PN
|
||||
float UU = U * U;
|
||||
float VV = V * V;
|
||||
float WW = W * W;
|
||||
float UU3 = UU * 3.0f;
|
||||
float VV3 = VV * 3.0f;
|
||||
float WW3 = WW * 3.0f;
|
||||
|
||||
// Interpolate using barycentric coordinates and PN Triangle control points
|
||||
output.WorldPosition =
|
||||
input[0].WorldPosition * UU * U +
|
||||
input[1].WorldPosition * VV * V +
|
||||
input[2].WorldPosition * WW * W +
|
||||
constantData.B210 * UU3 * V +
|
||||
constantData.B120 * VV3 * U +
|
||||
constantData.B021 * VV3 * W +
|
||||
constantData.B012 * WW3 * V +
|
||||
constantData.B102 * WW3 * U +
|
||||
constantData.B201 * UU3 * W +
|
||||
constantData.B111 * 6.0f * W * U * V;
|
||||
#else
|
||||
INTERPOLATE(WorldPosition);
|
||||
#endif
|
||||
INTERPOLATE(TexCoord);
|
||||
INTERPOLATE(LightmapUV);
|
||||
INTERPOLATE(WorldNormal);
|
||||
INTERPOLATE(HolesMask);
|
||||
#if USE_TERRAIN_LAYERS
|
||||
UNROLL
|
||||
for (int i = 0; i < TERRAIN_LAYERS_DATA_SIZE; i++)
|
||||
{
|
||||
INTERPOLATE(Layers[i]);
|
||||
}
|
||||
#endif
|
||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||
UNROLL
|
||||
for (int i = 0; i < CUSTOM_VERTEX_INTERPOLATORS_COUNT; i++)
|
||||
{
|
||||
INTERPOLATE(CustomVSToPS[i]);
|
||||
}
|
||||
#endif
|
||||
#undef INTERPOLATE
|
||||
#undef COPY
|
||||
|
||||
// Interpolating normal can unnormalize it, so normalize it
|
||||
output.WorldNormal = normalize(output.WorldNormal);
|
||||
|
||||
#if MATERIAL_TESSELLATION == MATERIAL_TESSELLATION_PHONG
|
||||
// Orthogonal projection in the tangent planes
|
||||
float3 posProjectedU = ProjectOntoPlane(input[0].WorldNormal, input[0].WorldPosition, output.WorldPosition);
|
||||
float3 posProjectedV = ProjectOntoPlane(input[1].WorldNormal, input[1].WorldPosition, output.WorldPosition);
|
||||
float3 posProjectedW = ProjectOntoPlane(input[2].WorldNormal, input[2].WorldPosition, output.WorldPosition);
|
||||
|
||||
// Interpolate the projected points
|
||||
output.WorldPosition = U * posProjectedU + V * posProjectedV + W * posProjectedW;
|
||||
#endif
|
||||
|
||||
// Perform displacement mapping
|
||||
#if USE_DISPLACEMENT
|
||||
MaterialInput materialInput = GetMaterialInput(output);
|
||||
Material material = GetMaterialDS(materialInput);
|
||||
output.WorldPosition += material.WorldDisplacement;
|
||||
#endif
|
||||
|
||||
// Recalculate the clip space position
|
||||
output.Position = mul(float4(output.WorldPosition, 1), ViewProjectionMatrix);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if USE_LIGHTMAP
|
||||
|
||||
float3 SampleLightmap(Material material, MaterialInput materialInput)
|
||||
{
|
||||
// Sample lightmaps
|
||||
float4 lightmap0 = Lightmap0.Sample(SamplerLinearClamp, materialInput.LightmapUV);
|
||||
float4 lightmap1 = Lightmap1.Sample(SamplerLinearClamp, materialInput.LightmapUV);
|
||||
float4 lightmap2 = Lightmap2.Sample(SamplerLinearClamp, materialInput.LightmapUV);
|
||||
|
||||
// Unpack H-basis
|
||||
float3 h0 = float3(lightmap0.x, lightmap1.x, lightmap2.x);
|
||||
float3 h1 = float3(lightmap0.y, lightmap1.y, lightmap2.y);
|
||||
float3 h2 = float3(lightmap0.z, lightmap1.z, lightmap2.z);
|
||||
float3 h3 = float3(lightmap0.w, lightmap1.w, lightmap2.w);
|
||||
|
||||
// Sample baked diffuse irradiance from the H-basis coefficients
|
||||
float3 normal = material.TangentNormal;
|
||||
#if MATERIAL_SHADING_MODEL == SHADING_MODEL_FOLIAGE
|
||||
normal *= material.TangentNormal;
|
||||
#endif
|
||||
return GetHBasisIrradiance(normal, h0, h1, h2, h3) / PI;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Pixel Shader function for GBuffer Pass
|
||||
META_PS(true, FEATURE_LEVEL_ES2)
|
||||
META_PERMUTATION_1(USE_LIGHTMAP=0)
|
||||
META_PERMUTATION_1(USE_LIGHTMAP=1)
|
||||
void PS_GBuffer(
|
||||
in PixelInput input
|
||||
,out float4 Light : SV_Target0
|
||||
#if MATERIAL_BLEND == MATERIAL_BLEND_OPAQUE
|
||||
,out float4 RT0 : SV_Target1
|
||||
,out float4 RT1 : SV_Target2
|
||||
,out float4 RT2 : SV_Target3
|
||||
#if USE_GBUFFER_CUSTOM_DATA
|
||||
,out float4 RT3 : SV_Target4
|
||||
#endif
|
||||
#endif
|
||||
)
|
||||
{
|
||||
Light = 0;
|
||||
|
||||
// Get material parameters
|
||||
MaterialInput materialInput = GetMaterialInput(input);
|
||||
Material material = GetMaterialPS(materialInput);
|
||||
|
||||
// Masking
|
||||
#if MATERIAL_MASKED
|
||||
clip(material.Mask - MATERIAL_MASK_THRESHOLD);
|
||||
#endif
|
||||
|
||||
#if USE_LIGHTMAP
|
||||
|
||||
float3 diffuseColor = GetDiffuseColor(material.Color, material.Metalness);
|
||||
float3 specularColor = GetSpecularColor(material.Color, material.Specular, material.Metalness);
|
||||
|
||||
// Sample lightmap
|
||||
float3 diffuseIndirectLighting = SampleLightmap(material, materialInput);
|
||||
|
||||
// Apply static indirect light
|
||||
Light.rgb = diffuseColor * diffuseIndirectLighting * AOMultiBounce(material.AO, diffuseColor);
|
||||
|
||||
#endif
|
||||
|
||||
#if MATERIAL_BLEND == MATERIAL_BLEND_OPAQUE
|
||||
|
||||
// Pack material properties to GBuffer
|
||||
RT0 = float4(material.Color, material.AO);
|
||||
RT1 = float4(material.WorldNormal * 0.5 + 0.5, MATERIAL_SHADING_MODEL * (1.0 / 3.0));
|
||||
RT2 = float4(material.Roughness, material.Metalness, material.Specular, 0);
|
||||
|
||||
// Custom data
|
||||
#if USE_GBUFFER_CUSTOM_DATA
|
||||
#if MATERIAL_SHADING_MODEL == SHADING_MODEL_SUBSURFACE
|
||||
RT3 = float4(material.SubsurfaceColor, material.Opacity);
|
||||
#elif MATERIAL_SHADING_MODEL == SHADING_MODEL_FOLIAGE
|
||||
RT3 = float4(material.SubsurfaceColor, material.Opacity);
|
||||
#else
|
||||
RT3 = float4(0, 0, 0, 0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Add light emission
|
||||
#if USE_EMISSIVE
|
||||
Light.rgb += material.Emissive;
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
// Handle blending as faked forward pass (use Light buffer and skip GBuffer modification)
|
||||
Light = float4(material.Emissive, material.Opacity);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
// Pixel Shader function for Depth Pass
|
||||
META_PS(true, FEATURE_LEVEL_ES2)
|
||||
void PS_Depth(PixelInput input
|
||||
#if GLSL
|
||||
, out float4 OutColor : SV_Target0
|
||||
#endif
|
||||
)
|
||||
void PS_Depth(PixelInput input)
|
||||
{
|
||||
#if MATERIAL_MASKED
|
||||
// Perform per pixel clipping if material requries it
|
||||
@@ -776,8 +456,6 @@ void PS_Depth(PixelInput input
|
||||
Material material = GetMaterialPS(materialInput);
|
||||
clip(material.Mask - MATERIAL_MASK_THRESHOLD);
|
||||
#endif
|
||||
|
||||
#if GLSL
|
||||
OutColor = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
@9
|
||||
|
||||
@@ -0,0 +1,246 @@
|
||||
// File generated by Flax Materials Editor
|
||||
// Version: @0
|
||||
|
||||
#define MATERIAL 1
|
||||
@3
|
||||
|
||||
#include "./Flax/Common.hlsl"
|
||||
#include "./Flax/MaterialCommon.hlsl"
|
||||
#include "./Flax/GBufferCommon.hlsl"
|
||||
@7
|
||||
|
||||
// Primary constant buffer (with additional material parameters)
|
||||
META_CB_BEGIN(0, Data)
|
||||
float4x4 ViewProjectionMatrix;
|
||||
float4x4 InverseViewProjectionMatrix;
|
||||
float4x4 ViewMatrix;
|
||||
float4x4 WorldMatrix;
|
||||
float4x4 WorldMatrixInverseTransposed;
|
||||
float3 ViewPos;
|
||||
float ViewFar;
|
||||
float3 ViewDir;
|
||||
float TimeParam;
|
||||
float4 ViewInfo;
|
||||
float4 ScreenSize;
|
||||
float3 GridSize;
|
||||
float PerInstanceRandom;
|
||||
float Dummy0;
|
||||
float VolumetricFogMaxDistance;
|
||||
int ParticleStride;
|
||||
int ParticleIndex;
|
||||
@1META_CB_END
|
||||
|
||||
// Particles attributes buffer
|
||||
ByteAddressBuffer ParticlesData : register(t0);
|
||||
|
||||
// Shader resources
|
||||
@2
|
||||
// Material properties generation input
|
||||
struct MaterialInput
|
||||
{
|
||||
float3 WorldPosition;
|
||||
float TwoSidedSign;
|
||||
float2 TexCoord;
|
||||
uint ParticleIndex;
|
||||
#if USE_VERTEX_COLOR
|
||||
half4 VertexColor;
|
||||
#endif
|
||||
float3x3 TBN;
|
||||
float4 SvPosition;
|
||||
float3 PreSkinnedPosition;
|
||||
float3 PreSkinnedNormal;
|
||||
float3 InstanceOrigin;
|
||||
float InstanceParams;
|
||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||
float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT];
|
||||
#endif
|
||||
};
|
||||
|
||||
#define GetInstanceTransform(input) WorldMatrix;
|
||||
|
||||
// Removes the scale vector from the local to world transformation matrix (supports instancing)
|
||||
float3x3 RemoveScaleFromLocalToWorld(float3x3 localToWorld)
|
||||
{
|
||||
// Extract per axis scales from localToWorld transform
|
||||
float scaleX = length(localToWorld[0]);
|
||||
float scaleY = length(localToWorld[1]);
|
||||
float scaleZ = length(localToWorld[2]);
|
||||
float3 invScale = float3(
|
||||
scaleX > 0.00001f ? 1.0f / scaleX : 0.0f,
|
||||
scaleY > 0.00001f ? 1.0f / scaleY : 0.0f,
|
||||
scaleZ > 0.00001f ? 1.0f / scaleZ : 0.0f);
|
||||
localToWorld[0] *= invScale.x;
|
||||
localToWorld[1] *= invScale.y;
|
||||
localToWorld[2] *= invScale.z;
|
||||
return localToWorld;
|
||||
}
|
||||
|
||||
// Transforms a vector from tangent space to world space
|
||||
float3 TransformTangentVectorToWorld(MaterialInput input, float3 tangentVector)
|
||||
{
|
||||
return mul(tangentVector, input.TBN);
|
||||
}
|
||||
|
||||
// Transforms a vector from world space to tangent space
|
||||
float3 TransformWorldVectorToTangent(MaterialInput input, float3 worldVector)
|
||||
{
|
||||
return mul(input.TBN, worldVector);
|
||||
}
|
||||
|
||||
// Transforms a vector from world space to view space
|
||||
float3 TransformWorldVectorToView(MaterialInput input, float3 worldVector)
|
||||
{
|
||||
return mul(worldVector, (float3x3)ViewMatrix);
|
||||
}
|
||||
|
||||
// Transforms a vector from view space to world space
|
||||
float3 TransformViewVectorToWorld(MaterialInput input, float3 viewVector)
|
||||
{
|
||||
return mul((float3x3)ViewMatrix, viewVector);
|
||||
}
|
||||
|
||||
// Transforms a vector from local space to world space
|
||||
float3 TransformLocalVectorToWorld(MaterialInput input, float3 localVector)
|
||||
{
|
||||
float3x3 localToWorld = (float3x3)GetInstanceTransform(input);
|
||||
//localToWorld = RemoveScaleFromLocalToWorld(localToWorld);
|
||||
return mul(localVector, localToWorld);
|
||||
}
|
||||
|
||||
// Transforms a vector from local space to world space
|
||||
float3 TransformWorldVectorToLocal(MaterialInput input, float3 worldVector)
|
||||
{
|
||||
float3x3 localToWorld = (float3x3)GetInstanceTransform(input);
|
||||
//localToWorld = RemoveScaleFromLocalToWorld(localToWorld);
|
||||
return mul(localToWorld, worldVector);
|
||||
}
|
||||
|
||||
// Gets the current object position (supports instancing)
|
||||
float3 GetObjectPosition(MaterialInput input)
|
||||
{
|
||||
return input.InstanceOrigin.xyz;
|
||||
}
|
||||
|
||||
// Gets the current object size
|
||||
float3 GetObjectSize(MaterialInput input)
|
||||
{
|
||||
return float3(1, 1, 1);
|
||||
}
|
||||
|
||||
// Get the current object random value (supports instancing)
|
||||
float GetPerInstanceRandom(MaterialInput input)
|
||||
{
|
||||
return input.InstanceParams;
|
||||
}
|
||||
|
||||
// Get the current object LOD transition dither factor (supports instancing)
|
||||
float GetLODDitherFactor(MaterialInput input)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Gets the interpolated vertex color (in linear space)
|
||||
float4 GetVertexColor(MaterialInput input)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint GetParticleUint(uint particleIndex, int offset)
|
||||
{
|
||||
return ParticlesData.Load(particleIndex * ParticleStride + offset);
|
||||
}
|
||||
|
||||
int GetParticleInt(uint particleIndex, int offset)
|
||||
{
|
||||
return asint(ParticlesData.Load(particleIndex * ParticleStride + offset));
|
||||
}
|
||||
|
||||
float GetParticleFloat(uint particleIndex, int offset)
|
||||
{
|
||||
return asfloat(ParticlesData.Load(particleIndex * ParticleStride + offset));
|
||||
}
|
||||
|
||||
float2 GetParticleVec2(uint particleIndex, int offset)
|
||||
{
|
||||
return asfloat(ParticlesData.Load2(particleIndex * ParticleStride + offset));
|
||||
}
|
||||
|
||||
float3 GetParticleVec3(uint particleIndex, int offset)
|
||||
{
|
||||
return asfloat(ParticlesData.Load3(particleIndex * ParticleStride + offset));
|
||||
}
|
||||
|
||||
float4 GetParticleVec4(uint particleIndex, int offset)
|
||||
{
|
||||
return asfloat(ParticlesData.Load4(particleIndex * ParticleStride + offset));
|
||||
}
|
||||
|
||||
float3 TransformParticlePosition(float3 input)
|
||||
{
|
||||
return mul(float4(input, 1.0f), WorldMatrix).xyz;
|
||||
}
|
||||
|
||||
float3 TransformParticleVector(float3 input)
|
||||
{
|
||||
return mul(float4(input, 0.0f), WorldMatrixInverseTransposed).xyz;
|
||||
}
|
||||
|
||||
@8
|
||||
|
||||
// Get material properties function (for vertex shader)
|
||||
Material GetMaterialVS(MaterialInput input)
|
||||
{
|
||||
@5
|
||||
}
|
||||
|
||||
// Get material properties function (for domain shader)
|
||||
Material GetMaterialDS(MaterialInput input)
|
||||
{
|
||||
@6
|
||||
}
|
||||
|
||||
// Get material properties function (for pixel shader)
|
||||
Material GetMaterialPS(MaterialInput input)
|
||||
{
|
||||
@4
|
||||
}
|
||||
|
||||
// Pixel Shader function for Volumetric Fog material injection (local fog)
|
||||
META_PS(true, FEATURE_LEVEL_SM5)
|
||||
void PS_VolumetricFog(Quad_GS2PS input, out float4 VBufferA : SV_Target0, out float4 VBufferB : SV_Target1)
|
||||
{
|
||||
uint3 gridCoordinate = uint3(input.Vertex.Position.xy, input.LayerIndex);
|
||||
float3 cellOffset = 0.5f;
|
||||
float2 volumeUV = (gridCoordinate.xy + cellOffset.xy) / GridSize.xy;
|
||||
float zSlice = gridCoordinate.z + cellOffset.z;
|
||||
float sceneDepth = (zSlice / GridSize.z) * VolumetricFogMaxDistance / ViewFar;
|
||||
float deviceDepth = (ViewInfo.w / sceneDepth) + ViewInfo.z;
|
||||
float4 clipPos = float4(volumeUV * float2(2.0, -2.0) + float2(-1.0, 1.0), deviceDepth, 1.0);
|
||||
float4 wsPos = mul(clipPos, InverseViewProjectionMatrix);
|
||||
float3 positionWS = wsPos.xyz / wsPos.w;
|
||||
|
||||
// Get material parameters
|
||||
MaterialInput materialInput = (MaterialInput)0;
|
||||
materialInput.WorldPosition = positionWS;
|
||||
materialInput.TexCoord = input.Vertex.TexCoord;
|
||||
materialInput.ParticleIndex = ParticleIndex;
|
||||
materialInput.TBN = float3x3(float3(1, 0, 0), float3(0, 1, 0), float3(0, 0, 1));
|
||||
materialInput.TwoSidedSign = 1.0f;
|
||||
materialInput.InstanceOrigin = WorldMatrix[3].xyz;
|
||||
materialInput.InstanceParams = PerInstanceRandom;
|
||||
materialInput.SvPosition = clipPos;
|
||||
Material material = GetMaterialPS(materialInput);
|
||||
|
||||
// Compute fog properties
|
||||
float3 albedo = material.Color;
|
||||
float extinction = material.Opacity * material.Mask * 0.001f;
|
||||
float3 emission = material.Emissive;
|
||||
float3 scattering = albedo * extinction;
|
||||
float absorption = max(0.0f, extinction - Luminance(scattering));
|
||||
|
||||
// Write fog properties
|
||||
VBufferA = float4(scattering, absorption);
|
||||
VBufferB = float4(emission, 0);
|
||||
}
|
||||
|
||||
@9
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -5,6 +5,7 @@
|
||||
|
||||
API_CLASS() class %module%%class% : public Script
|
||||
{
|
||||
API_AUTO_SERIALIZATION();
|
||||
DECLARE_SCRIPTING_TYPE(%class%);
|
||||
|
||||
// [Script]
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,14 @@
|
||||
## Mono
|
||||
|
||||
Custom fork: [https://github.com/FlaxEngine/mono](https://github.com/FlaxEngine/mono) with custom features for C# assemblies hot-reloading at runtime without domain unload (more: [https://flaxengine.com/blog/flax-facts-16-scripts-hot-reload/](https://flaxengine.com/blog/flax-facts-16-scripts-hot-reload/)).
|
||||
|
||||
### Notes
|
||||
|
||||
Some useful notes and tips for devs:
|
||||
* When working with mono fork set `localRepoPath` to local repo location in `Source\Tools\Flax.Build\Deps\Dependencies\mono.cs`
|
||||
* To update mono deps when developing/updating use `.\Development\Scripts\Windows\CallBuildTool.bat -log -ReBuildDeps -verbose -depsToBuild=mono -platform=Windows`, then build engine and run it
|
||||
* `MONO_GC_DEBUG=check-remset-consistency` - it will do additional checks at each collection to see if there are any missing write barriers
|
||||
* `MONO_GC_DEBUG=nursery-canaries` - it might catch some buffer overflows in case of problems in code.
|
||||
* `MONO_GC_DEBUG=<log-level>:<log-file>` - will print GC debug to the log file (eg. `4:sgen-gc`).
|
||||
* Methods `mono_custom_attrs_from_property` and `mono_custom_attrs_get_attr` are internally cached
|
||||
* If C++ mono call a method in c# that will throw an error, error will be handled but, not completly. Calling relase domain will return random `Access memory violation`. First search for error in c# code. No workaround yet.
|
||||
+2
-2
@@ -2,8 +2,8 @@
|
||||
"Name": "Flax",
|
||||
"Version": {
|
||||
"Major": 1,
|
||||
"Minor": 0,
|
||||
"Build": 6216
|
||||
"Minor": 1,
|
||||
"Build": 6218
|
||||
},
|
||||
"Company": "Flax",
|
||||
"Copyright": "Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.",
|
||||
|
||||
Executable
+12
@@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
# Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
|
||||
|
||||
set -e
|
||||
|
||||
echo Building and packaging Flax Editor...
|
||||
|
||||
# Change the path to the script root
|
||||
cd "`dirname "$0"`"
|
||||
|
||||
# Run Flax.Build (also pass the arguments)
|
||||
bash ./Development/Scripts/Linux/CallBuildTool.sh --deploy --deployEditor --verbose --log --logFile="Cache/Intermediate/PackageLog.txt" "$@"
|
||||
+1
-1
@@ -8,5 +8,5 @@ echo Building and packaging platforms data...
|
||||
# Change the path to the script root
|
||||
cd "`dirname "$0"`"
|
||||
|
||||
# Run Flax.Build to generate project files (also pass the arguments)
|
||||
# Run Flax.Build (also pass the arguments)
|
||||
bash ./Development/Scripts/Linux/CallBuildTool.sh --deploy --deployPlatforms --verbose --log --logFile="Cache/Intermediate/PackageLog.txt" "$@"
|
||||
|
||||
@@ -34,11 +34,11 @@ Flax Visual Studio extension provides better programming workflow, C# scripts de
|
||||
|
||||
* Install Visual Studio 2015 or newer
|
||||
* Install Windows 8.1 SDK or newer
|
||||
* Install Microsoft Visual C++ 2015.3 v140 toolset for desktop (x86, x64)
|
||||
* Install Microsoft Visual C++ 2015 v140 toolset or newer
|
||||
* Clone repo (with LFS)
|
||||
* Run **GenerateProjectFiles.bat**
|
||||
* Open `Flax.sln` and set solution configuration to **Editor.Development** and solution platform to **Win64**
|
||||
* Set Flax or FlaxEngine as startup project
|
||||
* Set Flax (C++) or FlaxEngine (C#) as startup project
|
||||
* Compile Flax project (hit F7 or CTRL+Shift+B)
|
||||
* Run Flax (hit F5 key)
|
||||
|
||||
@@ -47,12 +47,12 @@ Flax Visual Studio extension provides better programming workflow, C# scripts de
|
||||
* Install Visual Studio Code
|
||||
* Install Mono ([https://www.mono-project.com/download/stable](https://www.mono-project.com/download/stable))
|
||||
* Install Git with LFS
|
||||
* Install requried packages: `sudo apt-get install nuget autoconf libtool libogg-dev automake build-essential gettext cmake python curl libtool-bin libx11-dev libpulse-dev libasound2-dev libjack-dev portaudio19-dev`
|
||||
* Install compiler `sudo apt-get install clang-7 lldb-7 lld-7`
|
||||
* Install requried packages: `sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev nuget autoconf libogg-dev automake build-essential gettext cmake python libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev`
|
||||
* Install compiler `sudo apt-get install clang lldb lld` (Clang 6 or newer)
|
||||
* Clone repo (with LFS)
|
||||
* Run `sudo bash GenerateProjectFiles.sh`
|
||||
* Run `./GenerateProjectFiles.sh`
|
||||
* Open workspace with Visual Code
|
||||
* Build and run
|
||||
* Build and run (configuration and task named `Flax|Editor.Linux.Development|x64`)
|
||||
|
||||
## Workspace directory
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "Engine/Core/Math/Vector2.h"
|
||||
#include "Engine/Core/Types/DateTime.h"
|
||||
#include "Editor/Editor.h"
|
||||
#include "Editor/ProjectInfo.h"
|
||||
#include "Engine/Engine/EngineService.h"
|
||||
#include "Engine/Graphics/GPUDevice.h"
|
||||
#include "Engine/Utilities/StringConverter.h"
|
||||
@@ -103,6 +104,8 @@ void EditorAnalytics::StartSession()
|
||||
{ UA_DOCUMENT_TITLE, 0, "Flax Editor" },
|
||||
#if PLATFORM_WINDOWS
|
||||
{ UA_USER_AGENT, 0, "Windows " FLAXENGINE_VERSION_TEXT },
|
||||
#elif PLATFORM_LINUX
|
||||
{ UA_USER_AGENT, 0, "Linux " FLAXENGINE_VERSION_TEXT },
|
||||
#else
|
||||
#error "Unknown platform"
|
||||
#endif
|
||||
|
||||
@@ -26,8 +26,7 @@ namespace FlaxEditor.Content
|
||||
{
|
||||
if (reader.TokenType == JsonToken.String)
|
||||
{
|
||||
Guid id;
|
||||
FlaxEngine.Json.JsonSerializer.ParseID((string)reader.Value, out id);
|
||||
FlaxEngine.Json.JsonSerializer.ParseID((string)reader.Value, out Guid id);
|
||||
return Editor.Instance.ContentDatabase.Find(id);
|
||||
}
|
||||
|
||||
|
||||
@@ -113,8 +113,7 @@ namespace FlaxEditor.Content.Import
|
||||
extension = extension.ToLower();
|
||||
|
||||
// Check if use overriden type
|
||||
ImportFileEntryHandler createDelegate;
|
||||
if (FileTypes.TryGetValue(extension, out createDelegate))
|
||||
if (FileTypes.TryGetValue(extension, out ImportFileEntryHandler createDelegate))
|
||||
return createDelegate(ref request);
|
||||
|
||||
// Use default type
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace FlaxEditor.Content.Import
|
||||
var result = 0;
|
||||
for (int i = 0; i < _rootNode.ChildrenCount; i++)
|
||||
{
|
||||
if (_rootNode.Children[i].Tag is ImportFileEntry fileEntry)
|
||||
if (_rootNode.Children[i].Tag is ImportFileEntry)
|
||||
result++;
|
||||
}
|
||||
return result;
|
||||
@@ -215,8 +215,7 @@ namespace FlaxEditor.Content.Import
|
||||
var entries = new List<ImportFileEntry>(_rootNode.ChildrenCount);
|
||||
for (int i = 0; i < _rootNode.ChildrenCount; i++)
|
||||
{
|
||||
var fileEntry = _rootNode.Children[i].Tag as ImportFileEntry;
|
||||
if (fileEntry != null)
|
||||
if (_rootNode.Children[i].Tag is ImportFileEntry fileEntry)
|
||||
entries.Add(fileEntry);
|
||||
}
|
||||
Editor.Instance.ContentImporting.LetThemBeImportedxD(entries);
|
||||
|
||||
@@ -599,7 +599,7 @@ namespace FlaxEditor.Content
|
||||
public override bool OnShowTooltip(out string text, out Vector2 location, out Rectangle area)
|
||||
{
|
||||
UpdateTooltipText();
|
||||
var result = base.OnShowTooltip(out text, out location, out area);
|
||||
var result = base.OnShowTooltip(out text, out _, out area);
|
||||
location = Size * new Vector2(0.9f, 0.5f);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -50,6 +50,9 @@ namespace FlaxEditor.Content
|
||||
/// <inheritdoc />
|
||||
public bool IsMethod => false;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsEvent => false;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool HasGet => true;
|
||||
|
||||
@@ -72,6 +75,8 @@ namespace FlaxEditor.Content
|
||||
}
|
||||
}
|
||||
|
||||
public int MetadataToken => 0;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool HasAttribute(Type attributeType, bool inherit)
|
||||
{
|
||||
@@ -174,6 +179,9 @@ namespace FlaxEditor.Content
|
||||
/// <inheritdoc />
|
||||
public bool IsMethod => true;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsEvent => false;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool HasGet => false;
|
||||
|
||||
@@ -189,6 +197,8 @@ namespace FlaxEditor.Content
|
||||
/// <inheritdoc />
|
||||
public ScriptType ValueType => _returnType;
|
||||
|
||||
public int MetadataToken => 0;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool HasAttribute(Type attributeType, bool inherit)
|
||||
{
|
||||
|
||||
@@ -46,24 +46,47 @@ namespace FlaxEditor.Content
|
||||
/// Create collision data from model.
|
||||
/// </summary>
|
||||
/// <param name="model">The associated model.</param>
|
||||
public void CreateCollisionDataFromModel(Model model)
|
||||
/// <param name="created">The action to call once the collision data gets created (or reused from existing).</param>
|
||||
public void CreateCollisionDataFromModel(Model model, Action<CollisionData> created = null)
|
||||
{
|
||||
Action<ContentItem> created = contentItem =>
|
||||
// Check if there already is collision data for that model to reuse
|
||||
var modelItem = (AssetItem)Editor.Instance.ContentDatabase.Find(model.ID);
|
||||
if (modelItem?.ParentFolder != null)
|
||||
{
|
||||
var ai = (AssetItem)contentItem;
|
||||
var cd = FlaxEngine.Content.LoadAsync<CollisionData>(ai.ID);
|
||||
if (cd == null || cd.WaitForLoaded())
|
||||
foreach (var child in modelItem.ParentFolder.Children)
|
||||
{
|
||||
if (child is BinaryAssetItem b && b.IsOfType<CollisionData>())
|
||||
{
|
||||
var collisionData = FlaxEngine.Content.Load<CollisionData>(b.ID);
|
||||
if (collisionData && collisionData.Options.Model == model.ID)
|
||||
{
|
||||
Editor.Instance.Windows.ContentWin.Select(b);
|
||||
if (created != null)
|
||||
FlaxEngine.Scripting.InvokeOnUpdate(() => created(collisionData));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create new item so user can name it and then generate collision for it in async
|
||||
Action<ContentItem> create = contentItem =>
|
||||
{
|
||||
var assetItem = (AssetItem)contentItem;
|
||||
var collisionData = FlaxEngine.Content.LoadAsync<CollisionData>(assetItem.ID);
|
||||
if (collisionData == null || collisionData.WaitForLoaded())
|
||||
{
|
||||
Editor.LogError("Failed to load created collision data.");
|
||||
return;
|
||||
}
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
Editor.CookMeshCollision(ai.Path, CollisionDataType.TriangleMesh, model);
|
||||
});
|
||||
Editor.CookMeshCollision(assetItem.Path, CollisionDataType.TriangleMesh, model);
|
||||
if (created != null)
|
||||
FlaxEngine.Scripting.InvokeOnUpdate(() => created(collisionData));
|
||||
});
|
||||
};
|
||||
Editor.Instance.Windows.ContentWin.NewItem(this, null, created);
|
||||
Editor.Instance.Windows.ContentWin.NewItem(this, null, create);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ namespace FlaxEditor.Content
|
||||
_preview = new CubeTexturePreview(false)
|
||||
{
|
||||
RenderOnlyWithWindow = false,
|
||||
UseAutomaticTaskManagement = false,
|
||||
AnchorPreset = AnchorPresets.StretchAll,
|
||||
Offsets = Margin.Zero,
|
||||
};
|
||||
|
||||
@@ -54,6 +54,7 @@ namespace FlaxEditor.Content
|
||||
_preview = new MaterialPreview(false)
|
||||
{
|
||||
RenderOnlyWithWindow = false,
|
||||
UseAutomaticTaskManagement = false,
|
||||
AnchorPreset = AnchorPresets.StretchAll,
|
||||
Offsets = Margin.Zero,
|
||||
};
|
||||
|
||||
@@ -100,6 +100,7 @@ namespace FlaxEditor.Content
|
||||
_preview = new MaterialPreview(false)
|
||||
{
|
||||
RenderOnlyWithWindow = false,
|
||||
UseAutomaticTaskManagement = false,
|
||||
AnchorPreset = AnchorPresets.StretchAll,
|
||||
Offsets = Margin.Zero,
|
||||
};
|
||||
|
||||
@@ -45,11 +45,11 @@ namespace FlaxEditor.Content
|
||||
{
|
||||
base.OnContentWindowContextMenu(menu, item);
|
||||
|
||||
menu.AddButton("Generate collision data", () =>
|
||||
menu.AddButton("Create collision data", () =>
|
||||
{
|
||||
var model = FlaxEngine.Content.LoadAsync<Model>(((ModelAssetItem)item).ID);
|
||||
var cdProxy = (CollisionDataProxy)Editor.Instance.ContentDatabase.GetProxy<CollisionData>();
|
||||
cdProxy.CreateCollisionDataFromModel(model);
|
||||
var collisionDataProxy = (CollisionDataProxy)Editor.Instance.ContentDatabase.GetProxy<CollisionData>();
|
||||
collisionDataProxy.CreateCollisionDataFromModel(model);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -61,6 +61,7 @@ namespace FlaxEditor.Content
|
||||
_preview = new ModelPreview(false)
|
||||
{
|
||||
RenderOnlyWithWindow = false,
|
||||
UseAutomaticTaskManagement = false,
|
||||
AnchorPreset = AnchorPresets.StretchAll,
|
||||
Offsets = Margin.Zero,
|
||||
};
|
||||
|
||||
@@ -55,6 +55,7 @@ namespace FlaxEditor.Content
|
||||
_preview = new ParticleEmitterPreview(false)
|
||||
{
|
||||
RenderOnlyWithWindow = false,
|
||||
UseAutomaticTaskManagement = false,
|
||||
AnchorPreset = AnchorPresets.StretchAll,
|
||||
Offsets = Margin.Zero,
|
||||
};
|
||||
|
||||
@@ -55,6 +55,7 @@ namespace FlaxEditor.Content
|
||||
_preview = new ParticleEmitterPreview(false)
|
||||
{
|
||||
RenderOnlyWithWindow = false,
|
||||
UseAutomaticTaskManagement = false,
|
||||
AnchorPreset = AnchorPresets.StretchAll,
|
||||
Offsets = Margin.Zero,
|
||||
};
|
||||
|
||||
@@ -74,12 +74,13 @@ namespace FlaxEditor.Content
|
||||
/// <inheritdoc />
|
||||
public override void Create(string outputPath, object arg)
|
||||
{
|
||||
var actor = arg as Actor;
|
||||
if (actor == null)
|
||||
if (!(arg is Actor actor))
|
||||
{
|
||||
// Create default prefab root object
|
||||
actor = new EmptyActor();
|
||||
actor.Name = "Root";
|
||||
actor = new EmptyActor
|
||||
{
|
||||
Name = "Root"
|
||||
};
|
||||
|
||||
// Cleanup it after usage
|
||||
Object.Destroy(actor, 20.0f);
|
||||
@@ -96,6 +97,7 @@ namespace FlaxEditor.Content
|
||||
_preview = new PrefabPreview(false)
|
||||
{
|
||||
RenderOnlyWithWindow = false,
|
||||
UseAutomaticTaskManagement = false,
|
||||
AnchorPreset = AnchorPresets.StretchAll,
|
||||
Offsets = Margin.Zero,
|
||||
};
|
||||
@@ -162,8 +164,7 @@ namespace FlaxEditor.Content
|
||||
|
||||
// Auto fit actor to camera
|
||||
float targetSize = 30.0f;
|
||||
BoundingBox bounds;
|
||||
Editor.GetActorEditorBox(_preview.Instance, out bounds);
|
||||
Editor.GetActorEditorBox(_preview.Instance, out var bounds);
|
||||
float maxSize = Mathf.Max(0.001f, bounds.Size.MaxValue);
|
||||
_preview.Instance.Scale = new Vector3(targetSize / maxSize);
|
||||
_preview.Instance.Position = Vector3.Zero;
|
||||
@@ -175,6 +176,7 @@ namespace FlaxEditor.Content
|
||||
/// <inheritdoc />
|
||||
public override void OnThumbnailDrawEnd(ThumbnailRequest request, ContainerControl guiRoot)
|
||||
{
|
||||
_preview.RemoveChildren();
|
||||
_preview.Prefab = null;
|
||||
_preview.Parent = null;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace FlaxEditor.Content
|
||||
if (asset)
|
||||
{
|
||||
var source = Editor.GetShaderSourceCode(asset);
|
||||
Utilities.Utils.ShowSourceCodeWindow(source, "Shader Source");
|
||||
Utilities.Utils.ShowSourceCodeWindow(source, "Shader Source", item.RootWindow.Window);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ namespace FlaxEditor.Content
|
||||
_preview = new AnimatedModelPreview(false)
|
||||
{
|
||||
RenderOnlyWithWindow = false,
|
||||
UseAutomaticTaskManagement = false,
|
||||
AnchorPreset = AnchorPresets.StretchAll,
|
||||
Offsets = Margin.Zero,
|
||||
};
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||
|
||||
using FlaxEngine;
|
||||
|
||||
namespace FlaxEditor.Content.Settings
|
||||
{
|
||||
/// <summary>
|
||||
/// The Android platform settings asset archetype. Allows to edit asset via editor.
|
||||
/// </summary>
|
||||
public class AndroidPlatformSettings : SettingsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// The application package name (eg. com.company.product). Custom tokens: ${PROJECT_NAME}, ${COMPANY_NAME}.
|
||||
/// </summary>
|
||||
[EditorOrder(0), EditorDisplay("General"), Tooltip("The application package name (eg. com.company.product). Custom tokens: ${PROJECT_NAME}, ${COMPANY_NAME}.")]
|
||||
public string PackageName = "com.${COMPANY_NAME}.${PROJECT_NAME}";
|
||||
|
||||
/// <summary>
|
||||
/// The application permissions list (eg. android.media.action.IMAGE_CAPTURE). Added to the generated manifest file.
|
||||
/// </summary>
|
||||
[EditorOrder(100), EditorDisplay("General"), Tooltip("The application permissions list (eg. android.media.action.IMAGE_CAPTURE). Added to the generated manifest file.")]
|
||||
public string[] Permissions;
|
||||
|
||||
/// <summary>
|
||||
/// Custom icon texture to use for the application (overrides the default one).
|
||||
/// </summary>
|
||||
[EditorOrder(1030), EditorDisplay("Other"), Tooltip("Custom icon texture to use for the application (overrides the default one).")]
|
||||
public Texture OverrideIcon;
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System.ComponentModel;
|
||||
using FlaxEngine;
|
||||
|
||||
namespace FlaxEditor.Content.Settings
|
||||
{
|
||||
/// <summary>
|
||||
/// The audio payback engine settings container. Allows to edit asset via editor.
|
||||
/// </summary>
|
||||
public sealed class AudioSettings : SettingsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// If checked, audio playback will be disabled in build game. Can be used if game uses custom audio playback engine.
|
||||
/// </summary>
|
||||
[DefaultValue(false)]
|
||||
[EditorOrder(0), EditorDisplay("General"), Tooltip("If checked, audio playback will be disabled in build game. Can be used if game uses custom audio playback engine.")]
|
||||
public bool DisableAudio;
|
||||
|
||||
/// <summary>
|
||||
/// The doppler doppler effect factor. Scale for source and listener velocities. Default is 1.
|
||||
/// </summary>
|
||||
[DefaultValue(1.0f)]
|
||||
[EditorOrder(100), EditorDisplay("General"), Limit(0, 10.0f, 0.01f), Tooltip("The doppler doppler effect factor. Scale for source and listener velocities. Default is 1.")]
|
||||
public float DopplerFactor = 1.0f;
|
||||
|
||||
/// <summary>
|
||||
/// True if mute all audio playback when game has no use focus.
|
||||
/// </summary>
|
||||
[DefaultValue(true)]
|
||||
[EditorOrder(200), EditorDisplay("General", "Mute On Focus Loss"), Tooltip("If checked, engine will mute all audio playback when game has no use focus.")]
|
||||
public bool MuteOnFocusLoss = true;
|
||||
}
|
||||
}
|
||||
@@ -1,143 +0,0 @@
|
||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using FlaxEngine;
|
||||
|
||||
namespace FlaxEditor.Content.Settings
|
||||
{
|
||||
/// <summary>
|
||||
/// The game building settings container. Allows to edit asset via editor.
|
||||
/// </summary>
|
||||
public sealed class BuildSettings : SettingsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// The maximum amount of assets to include into a single assets package. Assets will be split into several packages if need to.
|
||||
/// </summary>
|
||||
[DefaultValue(4096)]
|
||||
[EditorOrder(10), Limit(32, short.MaxValue), EditorDisplay("General", "Max assets per package"), Tooltip("The maximum amount of assets to include into a single assets package. Assets will be split into several packages if need to.")]
|
||||
public int MaxAssetsPerPackage = 4096;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum size of the single assets package (in megabytes). Assets will be split into several packages if need to.
|
||||
/// </summary>
|
||||
[DefaultValue(1024)]
|
||||
[EditorOrder(20), Limit(16, short.MaxValue), EditorDisplay("General", "Max package size (in MB)"), Tooltip("The maximum size of the single assets package (in megabytes). Assets will be split into several packages if need to.")]
|
||||
public int MaxPackageSizeMB = 1024;
|
||||
|
||||
/// <summary>
|
||||
/// The game content cooking Keys. Use the same value for a game and DLC packages to support loading them by the build game. Use 0 to randomize it during building.
|
||||
/// </summary>
|
||||
[DefaultValue(0)]
|
||||
[EditorOrder(30), EditorDisplay("General"), Tooltip("The game content cooking Keys. Use the same value for a game and DLC packages to support loading them by the build game. Use 0 to randomize it during building.")]
|
||||
public int ContentKey = 0;
|
||||
|
||||
/// <summary>
|
||||
/// If checked, the builds produced by the Game Cooker will be treated as for final game distribution (eg. for game store upload). Builds done this way cannot be tested on console devkits (eg. Xbox One, Xbox Scarlett).
|
||||
/// </summary>
|
||||
[DefaultValue(false)]
|
||||
[EditorOrder(40), EditorDisplay("General"), Tooltip("If checked, the builds produced by the Game Cooker will be treated as for final game distribution (eg. for game store upload). Builds done this way cannot be tested on console devkits (eg. Xbox One, Xbox Scarlett).")]
|
||||
public bool ForDistribution;
|
||||
|
||||
/// <summary>
|
||||
/// If checked, the output build files won't be packaged for the destination platform. Useful when debugging build from local PC.
|
||||
/// </summary>
|
||||
[DefaultValue(false)]
|
||||
[EditorOrder(50), EditorDisplay("General"), Tooltip("If checked, the output build files won't be packaged for the destination platform. Useful when debugging build from local PC.")]
|
||||
public bool SkipPackaging;
|
||||
|
||||
/// <summary>
|
||||
/// The additional assets to include into build (into root assets set).
|
||||
/// </summary>
|
||||
[EditorOrder(1000), EditorDisplay("Additional Data"), Tooltip("The additional assets to include into build (into root assets set).")]
|
||||
public Asset[] AdditionalAssets;
|
||||
|
||||
/// <summary>
|
||||
/// The additional folders with assets to include into build (into root assets set). List of paths relative to the project directory (or absolute).
|
||||
/// </summary>
|
||||
[EditorOrder(1010), EditorDisplay("Additional Data"), Tooltip("The additional folders with assets to include into build (to root assets set). List of paths relative to the project directory (or absolute).")]
|
||||
public string[] AdditionalAssetFolders;
|
||||
|
||||
/// <summary>
|
||||
/// Disables shaders compiler optimizations in cooked game. Can be used to debug shaders on a target platform or to speed up the shaders compilation time.
|
||||
/// </summary>
|
||||
[DefaultValue(false)]
|
||||
[EditorOrder(2000), EditorDisplay("Content", "Shaders No Optimize"), Tooltip("Disables shaders compiler optimizations in cooked game. Can be used to debug shaders on a target platform or to speed up the shaders compilation time.")]
|
||||
public bool ShadersNoOptimize;
|
||||
|
||||
/// <summary>
|
||||
/// Enables shader debug data generation for shaders in cooked game (depends on the target platform rendering backend).
|
||||
/// </summary>
|
||||
[DefaultValue(false)]
|
||||
[EditorOrder(2010), EditorDisplay("Content"), Tooltip("Enables shader debug data generation for shaders in cooked game (depends on the target platform rendering backend).")]
|
||||
public bool ShadersGenerateDebugData;
|
||||
|
||||
/// <summary>
|
||||
/// The build presets.
|
||||
/// </summary>
|
||||
[EditorOrder(5000), EditorDisplay("Presets", EditorDisplayAttribute.InlineStyle), Tooltip("Build presets configuration")]
|
||||
public BuildPreset[] Presets =
|
||||
{
|
||||
new BuildPreset
|
||||
{
|
||||
Name = "Development",
|
||||
Targets = new[]
|
||||
{
|
||||
new BuildTarget
|
||||
{
|
||||
Name = "Windows 64bit",
|
||||
Output = "Output\\Win64",
|
||||
Platform = BuildPlatform.Windows64,
|
||||
Mode = BuildConfiguration.Development,
|
||||
},
|
||||
new BuildTarget
|
||||
{
|
||||
Name = "Windows 32bit",
|
||||
Output = "Output\\Win32",
|
||||
Platform = BuildPlatform.Windows32,
|
||||
Mode = BuildConfiguration.Development,
|
||||
},
|
||||
}
|
||||
},
|
||||
new BuildPreset
|
||||
{
|
||||
Name = "Release",
|
||||
Targets = new[]
|
||||
{
|
||||
new BuildTarget
|
||||
{
|
||||
Name = "Windows 64bit",
|
||||
Output = "Output\\Win64",
|
||||
Platform = BuildPlatform.Windows64,
|
||||
Mode = BuildConfiguration.Development,
|
||||
},
|
||||
new BuildTarget
|
||||
{
|
||||
Name = "Windows 32bit",
|
||||
Output = "Output\\Win32",
|
||||
Platform = BuildPlatform.Windows32,
|
||||
Mode = BuildConfiguration.Development,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Gets the preset of the given name (ignore case search) or returns null if cannot find it.
|
||||
/// </summary>
|
||||
/// <param name="name">The preset name.</param>
|
||||
/// <returns>Found preset or null if is missing.</returns>
|
||||
public BuildPreset GetPreset(string name)
|
||||
{
|
||||
if (Presets != null)
|
||||
{
|
||||
for (int i = 0; i < Presets.Length; i++)
|
||||
{
|
||||
if (string.Equals(Presets[i].Name, name, StringComparison.OrdinalIgnoreCase))
|
||||
return Presets[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,12 @@ namespace FlaxEditor.Content.Settings
|
||||
[EditorOrder(30), Tooltip("Configuration build mode")]
|
||||
public BuildConfiguration Mode;
|
||||
|
||||
/// <summary>
|
||||
/// The list of custom defines passed to the build tool when compiling project scripts. Can be used in build scripts for configuration (Configuration.CustomDefines).
|
||||
/// </summary>
|
||||
[EditorOrder(90), Tooltip("The list of custom defines passed to the build tool when compiling project scripts. Can be used in build scripts for configuration (Configuration.CustomDefines).")]
|
||||
public string[] CustomDefines;
|
||||
|
||||
/// <summary>
|
||||
/// The pre-build action command line.
|
||||
/// </summary>
|
||||
@@ -46,11 +52,5 @@ namespace FlaxEditor.Content.Settings
|
||||
/// </summary>
|
||||
[EditorOrder(110)]
|
||||
public string PostBuildAction;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the build options computed from the target configuration.
|
||||
/// </summary>
|
||||
[HideInEditor, NoSerialize]
|
||||
public virtual BuildOptions Options => BuildOptions.None;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||
|
||||
using FlaxEngine;
|
||||
|
||||
namespace FlaxEditor.Content.Settings
|
||||
{
|
||||
/// <summary>
|
||||
/// The graphics rendering settings container. Allows to edit asset via editor. To modify those settings at runtime use <see cref="GraphicsSettings"/>.
|
||||
/// </summary>
|
||||
/// <seealso cref="FlaxEngine.Graphics"/>
|
||||
public sealed class GraphicsSettings : SettingsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Enables rendering synchronization with the refresh rate of the display device to avoid "tearing" artifacts.
|
||||
/// </summary>
|
||||
[EditorOrder(20), EditorDisplay("General", "Use V-Sync"), Tooltip("Enables rendering synchronization with the refresh rate of the display device to avoid \"tearing\" artifacts.")]
|
||||
public bool UseVSync = false;
|
||||
|
||||
/// <summary>
|
||||
/// Anti Aliasing quality setting.
|
||||
/// </summary>
|
||||
[EditorOrder(1000), EditorDisplay("Quality", "AA Quality"), Tooltip("Anti Aliasing quality.")]
|
||||
public Quality AAQuality = Quality.Medium;
|
||||
|
||||
/// <summary>
|
||||
/// Screen Space Reflections quality.
|
||||
/// </summary>
|
||||
[EditorOrder(1100), EditorDisplay("Quality", "SSR Quality"), Tooltip("Screen Space Reflections quality.")]
|
||||
public Quality SSRQuality = Quality.Medium;
|
||||
|
||||
/// <summary>
|
||||
/// Screen Space Ambient Occlusion quality setting.
|
||||
/// </summary>
|
||||
[EditorOrder(1200), EditorDisplay("Quality", "SSAO Quality"), Tooltip("Screen Space Ambient Occlusion quality setting.")]
|
||||
public Quality SSAOQuality = Quality.Medium;
|
||||
|
||||
/// <summary>
|
||||
/// Volumetric Fog quality setting.
|
||||
/// </summary>
|
||||
[EditorOrder(1250), EditorDisplay("Quality", "Volumetric Fog Quality"), Tooltip("Volumetric Fog quality setting.")]
|
||||
public Quality VolumetricFogQuality = Quality.High;
|
||||
|
||||
/// <summary>
|
||||
/// The shadows quality.
|
||||
/// </summary>
|
||||
[EditorOrder(1300), EditorDisplay("Quality", "Shadows Quality"), Tooltip("The shadows quality.")]
|
||||
public Quality ShadowsQuality = Quality.Medium;
|
||||
|
||||
/// <summary>
|
||||
/// The shadow maps quality (textures resolution).
|
||||
/// </summary>
|
||||
[EditorOrder(1310), EditorDisplay("Quality", "Shadow Maps Quality"), Tooltip("The shadow maps quality (textures resolution).")]
|
||||
public Quality ShadowMapsQuality = Quality.Medium;
|
||||
|
||||
/// <summary>
|
||||
/// Enables cascades splits blending for directional light shadows.
|
||||
/// </summary>
|
||||
[EditorOrder(1320), EditorDisplay("Quality", "Allow CSM Blending"), Tooltip("Enables cascades splits blending for directional light shadows.")]
|
||||
public bool AllowCSMBlending = false;
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||
|
||||
using FlaxEngine;
|
||||
|
||||
namespace FlaxEditor.Content.Settings
|
||||
{
|
||||
/// <summary>
|
||||
/// The Linux platform settings asset archetype. Allows to edit asset via editor.
|
||||
/// </summary>
|
||||
public class LinuxPlatformSettings : SettingsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// The default game window mode.
|
||||
/// </summary>
|
||||
[EditorOrder(10), EditorDisplay("Window"), Tooltip("The default game window mode.")]
|
||||
public GameWindowMode WindowMode = GameWindowMode.Windowed;
|
||||
|
||||
/// <summary>
|
||||
/// The default game window width (in pixels).
|
||||
/// </summary>
|
||||
[EditorOrder(20), EditorDisplay("Window"), Tooltip("The default game window width (in pixels).")]
|
||||
public int ScreenWidth = 1280;
|
||||
|
||||
/// <summary>
|
||||
/// The default game window height (in pixels).
|
||||
/// </summary>
|
||||
[EditorOrder(30), EditorDisplay("Window"), Tooltip("The default game window height (in pixels).")]
|
||||
public int ScreenHeight = 720;
|
||||
|
||||
/// <summary>
|
||||
/// Enables resizing the game window by the user.
|
||||
/// </summary>
|
||||
[EditorOrder(40), EditorDisplay("Window"), Tooltip("Enables resizing the game window by the user.")]
|
||||
public bool ResizableWindow = false;
|
||||
|
||||
/// <summary>
|
||||
/// Enables game running when application window loses focus.
|
||||
/// </summary>
|
||||
[EditorOrder(1010), EditorDisplay("Other", "Run In Background"), Tooltip("Enables game running when application window loses focus.")]
|
||||
public bool RunInBackground = false;
|
||||
|
||||
/// <summary>
|
||||
/// Limits maximum amount of concurrent game instances running to one, otherwise user may launch application more than once.
|
||||
/// </summary>
|
||||
[EditorOrder(1020), EditorDisplay("Other"), Tooltip("Limits maximum amount of concurrent game instances running to one, otherwise user may launch application more than once.")]
|
||||
public bool ForceSingleInstance = false;
|
||||
|
||||
/// <summary>
|
||||
/// Custom icon texture to use for the application (overrides the default one).
|
||||
/// </summary>
|
||||
[EditorOrder(1030), EditorDisplay("Other"), Tooltip("Custom icon texture to use for the application (overrides the default one).")]
|
||||
public Texture OverrideIcon;
|
||||
|
||||
/// <summary>
|
||||
/// Enables support for Vulkan. Disabling it reduces compiled shaders count.
|
||||
/// </summary>
|
||||
[EditorOrder(2020), EditorDisplay("Graphics", "Support Vulkan"), Tooltip("Enables support for Vulkan. Disabling it reduces compiled shaders count.")]
|
||||
public bool SupportVulkan = true;
|
||||
}
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System.ComponentModel;
|
||||
using FlaxEngine;
|
||||
|
||||
namespace FlaxEditor.Content.Settings
|
||||
{
|
||||
/// <summary>
|
||||
/// The navigation system settings container.
|
||||
/// </summary>
|
||||
public sealed class NavigationSettings : SettingsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// The height of a grid cell in the navigation mesh building steps using heightfields.
|
||||
/// A lower number means higher precision on the vertical axis but longer build times.
|
||||
/// </summary>
|
||||
[DefaultValue(10.0f), Limit(1, 400)]
|
||||
[EditorOrder(10), EditorDisplay("Nav Mesh Options"), Tooltip("The height of a grid cell in the navigation mesh building steps using heightfields. A lower number means higher precision on the vertical axis but longer build times.")]
|
||||
public float CellHeight = 10.0f;
|
||||
|
||||
/// <summary>
|
||||
/// The width/height of a grid cell in the navigation mesh building steps using heightfields.
|
||||
/// A lower number means higher precision on the horizontal axes but longer build times.
|
||||
/// </summary>
|
||||
[DefaultValue(30.0f), Limit(1, 400)]
|
||||
[EditorOrder(20), EditorDisplay("Nav Mesh Options"), Tooltip("The width/height of a grid cell in the navigation mesh building steps using heightfields. A lower number means higher precision on the vertical axis but longer build times.")]
|
||||
public float CellSize = 30.0f;
|
||||
|
||||
/// <summary>
|
||||
/// Tile size used for Navigation mesh tiles, the final size of a tile is CellSize*TileSize.
|
||||
/// </summary>
|
||||
[DefaultValue(64), Limit(8, 4096)]
|
||||
[EditorOrder(30), EditorDisplay("Nav Mesh Options"), Tooltip("Tile size used for Navigation mesh tiles, the final size of a tile is CellSize*TileSize.")]
|
||||
public int TileSize = 64;
|
||||
|
||||
/// <summary>
|
||||
/// The minimum number of cells allowed to form isolated island areas.
|
||||
/// </summary>
|
||||
[DefaultValue(0), Limit(0, 100)]
|
||||
[EditorOrder(40), EditorDisplay("Nav Mesh Options"), Tooltip("The minimum number of cells allowed to form isolated island areas.")]
|
||||
public int MinRegionArea = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Any regions with a span count smaller than this value will, if possible, be merged with larger regions.
|
||||
/// </summary>
|
||||
[DefaultValue(20), Limit(0, 100)]
|
||||
[EditorOrder(50), EditorDisplay("Nav Mesh Options"), Tooltip("Any regions with a span count smaller than this value will, if possible, be merged with larger regions.")]
|
||||
public int MergeRegionArea = 20;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum allowed length for contour edges along the border of the mesh.
|
||||
/// </summary>
|
||||
[DefaultValue(1200.0f), Limit(100)]
|
||||
[EditorOrder(60), EditorDisplay("Nav Mesh Options", "Max Edge Length"), Tooltip("The maximum allowed length for contour edges along the border of the mesh.")]
|
||||
public float MaxEdgeLen = 1200.0f;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum distance a simplified contour's border edges should deviate from the original raw contour.
|
||||
/// </summary>
|
||||
[DefaultValue(1.3f), Limit(0.1f, 4)]
|
||||
[EditorOrder(70), EditorDisplay("Nav Mesh Options"), Tooltip("The maximum distance a simplified contour's border edges should deviate from the original raw contour.")]
|
||||
public float MaxEdgeError = 1.3f;
|
||||
|
||||
/// <summary>
|
||||
/// The sampling distance to use when generating the detail mesh. For height detail only.
|
||||
/// </summary>
|
||||
[DefaultValue(600.0f), Limit(1)]
|
||||
[EditorOrder(80), EditorDisplay("Nav Mesh Options", "Detail Sampling Distance"), Tooltip("The sampling distance to use when generating the detail mesh.")]
|
||||
public float DetailSamplingDist = 600.0f;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum distance the detail mesh surface should deviate from heightfield data. For height detail only.
|
||||
/// </summary>
|
||||
[DefaultValue(1.0f), Limit(0, 3)]
|
||||
[EditorOrder(90), EditorDisplay("Nav Mesh Options"), Tooltip("The maximum distance the detail mesh surface should deviate from heightfield data.")]
|
||||
public float MaxDetailSamplingError = 1.0f;
|
||||
|
||||
/// <summary>
|
||||
/// The radius of the smallest objects to traverse this nav mesh. Objects can't pass through gaps of less than twice the radius.
|
||||
/// </summary>
|
||||
[DefaultValue(34.0f), Limit(0)]
|
||||
[EditorOrder(1000), EditorDisplay("Agent Options"), Tooltip("The radius of the smallest objects to traverse this nav mesh. Objects can't pass through gaps of less than twice the radius.")]
|
||||
public float WalkableRadius = 34.0f;
|
||||
|
||||
/// <summary>
|
||||
/// The height of the smallest objects to traverse this nav mesh. Objects can't enter areas with ceilings lower than this value.
|
||||
/// </summary>
|
||||
[DefaultValue(144.0f), Limit(0)]
|
||||
[EditorOrder(1010), EditorDisplay("Agent Options"), Tooltip("The height of the smallest objects to traverse this nav mesh. Objects can't enter areas with ceilings lower than this value.")]
|
||||
public float WalkableHeight = 144.0f;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum ledge height that is considered to still be traversable.
|
||||
/// </summary>
|
||||
[DefaultValue(35.0f), Limit(0)]
|
||||
[EditorOrder(1020), EditorDisplay("Agent Options"), Tooltip("The maximum ledge height that is considered to still be traversable.")]
|
||||
public float WalkableMaxClimb = 35.0f;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum slope that is considered walkable (in degrees). Objects can't go up or down slopes higher than this value.
|
||||
/// </summary>
|
||||
[DefaultValue(60.0f), Limit(0, 89.0f)]
|
||||
[EditorOrder(1030), EditorDisplay("Agent Options"), Tooltip("The maximum slope that is considered walkable (in degrees). Objects can't go up or down slopes higher than this value.")]
|
||||
public float WalkableMaxSlopeAngle = 60.0f;
|
||||
}
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System.ComponentModel;
|
||||
using FlaxEngine;
|
||||
|
||||
namespace FlaxEditor.Content.Settings
|
||||
{
|
||||
/// <summary>
|
||||
/// The physics simulation settings container. Allows to edit asset via editor.
|
||||
/// </summary>
|
||||
public sealed class PhysicsSettings : SettingsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// The default gravity force value (in cm^2/s).
|
||||
/// </summary>
|
||||
[DefaultValue(typeof(Vector3), "0,-981.0,0")]
|
||||
[EditorOrder(0), EditorDisplay("Simulation"), Tooltip("The default gravity force value (in cm^2/s).")]
|
||||
public Vector3 DefaultGravity = new Vector3(0, -981.0f, 0);
|
||||
|
||||
/// <summary>
|
||||
/// If enabled, any Raycast or other scene query that intersects with a Collider marked as a Trigger will returns with a hit. Individual raycasts can override this behavior.
|
||||
/// </summary>
|
||||
[DefaultValue(true)]
|
||||
[EditorOrder(10), EditorDisplay("Simulation"), Tooltip("If enabled, any Raycast or other scene query that intersects with a Collider marked as a Trigger will returns with a hit. Individual raycasts can override this behavior.")]
|
||||
public bool QueriesHitTriggers = true;
|
||||
|
||||
/// <summary>
|
||||
/// Triangles from triangle meshes (CSG) with an area less than or equal to this value will be removed from physics collision data. Set to less than or equal 0 to disable.
|
||||
/// </summary>
|
||||
[DefaultValue(5.0f)]
|
||||
[EditorOrder(20), EditorDisplay("Simulation"), Limit(-1, 10), Tooltip("Triangles from triangle meshes (CSG) with an area less than or equal to this value will be removed from physics collision data. Set to less than or equal 0 to disable.")]
|
||||
public float TriangleMeshTriangleMinAreaThreshold = 5.0f;
|
||||
|
||||
/// <summary>
|
||||
/// Minimum relative velocity required for an object to bounce. A typical value for simulation stability is about 0.2 * gravity
|
||||
/// </summary>
|
||||
[DefaultValue(200.0f)]
|
||||
[EditorOrder(30), EditorDisplay("Simulation"), Limit(0), Tooltip("Minimum relative velocity required for an object to bounce. A typical value for simulation stability is about 0.2 * gravity")]
|
||||
public float BounceThresholdVelocity = 200.0f;
|
||||
|
||||
/// <summary>
|
||||
/// Default friction combine mode, controls how friction is computed for multiple materials.
|
||||
/// </summary>
|
||||
[DefaultValue(PhysicsCombineMode.Average)]
|
||||
[EditorOrder(40), EditorDisplay("Simulation"), Tooltip("Default friction combine mode, controls how friction is computed for multiple materials.")]
|
||||
public PhysicsCombineMode FrictionCombineMode = PhysicsCombineMode.Average;
|
||||
|
||||
/// <summary>
|
||||
/// Default restitution combine mode, controls how restitution is computed for multiple materials.
|
||||
/// </summary>
|
||||
[DefaultValue(PhysicsCombineMode.Average)]
|
||||
[EditorOrder(50), EditorDisplay("Simulation"), Tooltip("Default restitution combine mode, controls how restitution is computed for multiple materials.")]
|
||||
public PhysicsCombineMode RestitutionCombineMode = PhysicsCombineMode.Average;
|
||||
|
||||
/// <summary>
|
||||
/// If true CCD will be ignored. This is an optimization when CCD is never used which removes the need for PhysX to check it internally.
|
||||
/// </summary>
|
||||
[DefaultValue(false)]
|
||||
[EditorOrder(70), EditorDisplay("Simulation", "Disable CCD"), Tooltip("If true CCD will be ignored. This is an optimization when CCD is never used which removes the need for PhysX to check it internally.")]
|
||||
public bool DisableCCD;
|
||||
|
||||
/// <summary>
|
||||
/// Enables adaptive forces to accelerate convergence of the solver. Can improve physics simulation performance but lead to artifacts.
|
||||
/// </summary>
|
||||
[DefaultValue(false)]
|
||||
[EditorOrder(80), EditorDisplay("Simulation"), Tooltip("Enables adaptive forces to accelerate convergence of the solver. Can improve physics simulation performance but lead to artifacts.")]
|
||||
public bool EnableAdaptiveForce;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum allowed delta time (in seconds) for the physics simulation step.
|
||||
/// </summary>
|
||||
[DefaultValue(1.0f / 10.0f)]
|
||||
[EditorOrder(1000), EditorDisplay("Framerate"), Limit(0.0013f, 2.0f), Tooltip("The maximum allowed delta time (in seconds) for the physics simulation step.")]
|
||||
public float MaxDeltaTime = 1.0f / 10.0f;
|
||||
|
||||
/// <summary>
|
||||
/// Whether to substep the physics simulation.
|
||||
/// </summary>
|
||||
[DefaultValue(false)]
|
||||
[EditorOrder(1005), EditorDisplay("Framerate"), Tooltip("Whether to substep the physics simulation.")]
|
||||
public bool EnableSubstepping;
|
||||
|
||||
/// <summary>
|
||||
/// Delta time (in seconds) for an individual simulation substep.
|
||||
/// </summary>
|
||||
[DefaultValue(1.0f / 120.0f)]
|
||||
[EditorOrder(1010), EditorDisplay("Framerate"), Limit(0.0013f, 1.0f), Tooltip("Delta time (in seconds) for an individual simulation substep.")]
|
||||
public float SubstepDeltaTime = 1.0f / 120.0f;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum number of substeps for physics simulation.
|
||||
/// </summary>
|
||||
[DefaultValue(5)]
|
||||
[EditorOrder(1020), EditorDisplay("Framerate"), Limit(1, 16), Tooltip("The maximum number of substeps for physics simulation.")]
|
||||
public int MaxSubsteps = 5;
|
||||
|
||||
/// <summary>
|
||||
/// The collision layers masks. Used to define layer-based collision detection.
|
||||
/// </summary>
|
||||
[EditorOrder(1040), EditorDisplay("Layers Matrix"), CustomEditor(typeof(FlaxEditor.CustomEditors.Dedicated.LayersMatrixEditor))]
|
||||
public uint[] LayerMasks = new uint[32];
|
||||
|
||||
/// <summary>
|
||||
/// Enables support for cooking physical collision shapes geometry at runtime. Use it to enable generating runtime terrain collision or convex mesh colliders.
|
||||
/// </summary>
|
||||
[DefaultValue(false)]
|
||||
[EditorOrder(1100), EditorDisplay("Other", "Support Cooking At Runtime"), Tooltip("Enables support for cooking physical collision shapes geometry at runtime. Use it to enable generating runtime terrain collision or convex mesh colliders.")]
|
||||
public bool SupportCookingAtRuntime;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PhysicsSettings"/> class.
|
||||
/// </summary>
|
||||
public PhysicsSettings()
|
||||
{
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
LayerMasks[i] = uint.MaxValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System.ComponentModel;
|
||||
using FlaxEngine;
|
||||
|
||||
namespace FlaxEditor.Content.Settings
|
||||
{
|
||||
/// <summary>
|
||||
/// The time settings asset archetype. Allows to edit asset via editor.
|
||||
/// </summary>
|
||||
public sealed class TimeSettings : SettingsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// The target amount of the game logic updates per second (script updates frequency). Use 0 for infinity.
|
||||
/// </summary>
|
||||
[DefaultValue(30.0f)]
|
||||
[EditorOrder(1), Limit(0, 1000), EditorDisplay(null, "Update FPS"), Tooltip("Target amount of the game logic updates per second (script updates frequency). Use 0 for infinity.")]
|
||||
public float UpdateFPS = 30.0f;
|
||||
|
||||
/// <summary>
|
||||
/// The target amount of the physics simulation updates per second (also fixed updates frequency). Use 0 for infinity.
|
||||
/// </summary>
|
||||
[DefaultValue(60.0f)]
|
||||
[EditorOrder(2), Limit(0, 1000), EditorDisplay(null, "Physics FPS"), Tooltip("Target amount of the physics simulation updates per second (also fixed updates frequency). Use 0 for infinity.")]
|
||||
public float PhysicsFPS = 60.0f;
|
||||
|
||||
/// <summary>
|
||||
/// The target amount of the frames rendered per second (actual game FPS). Use 0 for infinity.
|
||||
/// </summary>
|
||||
[DefaultValue(60.0f)]
|
||||
[EditorOrder(3), Limit(0, 1000), EditorDisplay(null, "Draw FPS"), Tooltip("Target amount of the frames rendered per second (actual game FPS). Use 0 for infinity.")]
|
||||
public float DrawFPS = 60.0f;
|
||||
|
||||
/// <summary>
|
||||
/// The game time scale factor. Default is 1.
|
||||
/// </summary>
|
||||
[DefaultValue(1.0f)]
|
||||
[EditorOrder(10), Limit(0, 1000.0f, 0.1f), Tooltip("Game time scaling factor. Default is 1 for real-time simulation.")]
|
||||
public float TimeScale = 1.0f;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum allowed delta time (in seconds) for the game logic update step.
|
||||
/// </summary>
|
||||
[DefaultValue(1.0f / 10.0f)]
|
||||
[EditorOrder(20), Limit(0.1f, 1000.0f, 0.01f), Tooltip("The maximum allowed delta time (in seconds) for the game logic update step.")]
|
||||
public float MaxUpdateDeltaTime = 1.0f / 10.0f;
|
||||
}
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using FlaxEngine;
|
||||
|
||||
namespace FlaxEditor.Content.Settings
|
||||
{
|
||||
/// <summary>
|
||||
/// The Universal Windows Platform (UWP) platform settings asset archetype. Allows to edit asset via editor.
|
||||
/// </summary>
|
||||
public class UWPPlatformSettings : SettingsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// The preferred launch windowing mode.
|
||||
/// </summary>
|
||||
public enum WindowMode
|
||||
{
|
||||
/// <summary>
|
||||
/// The full screen mode
|
||||
/// </summary>
|
||||
FullScreen = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The view size.
|
||||
/// </summary>
|
||||
ViewSize = 1,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The display orientation modes. Can be combined as flags.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum DisplayOrientations
|
||||
{
|
||||
/// <summary>
|
||||
/// The none.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The landscape.
|
||||
/// </summary>
|
||||
Landscape = 1,
|
||||
|
||||
/// <summary>
|
||||
/// The landscape flipped.
|
||||
/// </summary>
|
||||
LandscapeFlipped = 2,
|
||||
|
||||
/// <summary>
|
||||
/// The portrait.
|
||||
/// </summary>
|
||||
Portrait = 4,
|
||||
|
||||
/// <summary>
|
||||
/// The portrait flipped.
|
||||
/// </summary>
|
||||
PortraitFlipped = 8,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The preferred launch windowing mode. Always fullscreen on Xbox.
|
||||
/// </summary>
|
||||
[DefaultValue(WindowMode.FullScreen)]
|
||||
[EditorOrder(10), EditorDisplay("Window"), Tooltip("The preferred launch windowing mode. Always fullscreen on Xbox.")]
|
||||
public WindowMode PreferredLaunchWindowingMode = WindowMode.FullScreen;
|
||||
|
||||
/// <summary>
|
||||
/// The display orientation modes. Can be combined as flags.
|
||||
/// </summary>
|
||||
[DefaultValue(DisplayOrientations.Landscape | DisplayOrientations.LandscapeFlipped | DisplayOrientations.Portrait | DisplayOrientations.PortraitFlipped)]
|
||||
[EditorOrder(20), EditorDisplay("Window"), Tooltip("The display orientation modes. Can be combined as flags.")]
|
||||
public DisplayOrientations AutoRotationPreferences = DisplayOrientations.Landscape | DisplayOrientations.LandscapeFlipped | DisplayOrientations.Portrait | DisplayOrientations.PortraitFlipped;
|
||||
|
||||
/// <summary>
|
||||
/// The location of the package certificate (relative to the project).
|
||||
/// </summary>
|
||||
[DefaultValue("")]
|
||||
[EditorOrder(1010), EditorDisplay("Other"), Tooltip("The location of the package certificate (relative to the project).")]
|
||||
public string CertificateLocation = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Enables support for DirectX 11. Disabling it reduces compiled shaders count.
|
||||
/// </summary>
|
||||
[DefaultValue(true)]
|
||||
[EditorOrder(2000), EditorDisplay("Graphics", "Support DirectX 11"), Tooltip("Enables support for DirectX 11. Disabling it reduces compiled shaders count.")]
|
||||
public bool SupportDX11 = true;
|
||||
|
||||
/// <summary>
|
||||
/// Enables support for DirectX 10 and DirectX 10.1. Disabling it reduces compiled shaders count.
|
||||
/// </summary>
|
||||
[DefaultValue(false)]
|
||||
[EditorOrder(2010), EditorDisplay("Graphics", "Support DirectX 10"), Tooltip("Enables support for DirectX 10 and DirectX 10.1. Disabling it reduces compiled shaders count.")]
|
||||
public bool SupportDX10 = false;
|
||||
}
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System.ComponentModel;
|
||||
using FlaxEngine;
|
||||
|
||||
namespace FlaxEditor.Content.Settings
|
||||
{
|
||||
/// <summary>
|
||||
/// The Windows platform settings asset archetype. Allows to edit asset via editor.
|
||||
/// </summary>
|
||||
public class WindowsPlatformSettings : SettingsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// The default game window mode.
|
||||
/// </summary>
|
||||
[DefaultValue(GameWindowMode.Windowed)]
|
||||
[EditorOrder(10), EditorDisplay("Window"), Tooltip("The default game window mode.")]
|
||||
public GameWindowMode WindowMode = GameWindowMode.Windowed;
|
||||
|
||||
/// <summary>
|
||||
/// The default game window width (in pixels).
|
||||
/// </summary>
|
||||
[DefaultValue(1280)]
|
||||
[EditorOrder(20), EditorDisplay("Window"), Tooltip("The default game window width (in pixels).")]
|
||||
public int ScreenWidth = 1280;
|
||||
|
||||
/// <summary>
|
||||
/// The default game window height (in pixels).
|
||||
/// </summary>
|
||||
[DefaultValue(720)]
|
||||
[EditorOrder(30), EditorDisplay("Window"), Tooltip("The default game window height (in pixels).")]
|
||||
public int ScreenHeight = 720;
|
||||
|
||||
/// <summary>
|
||||
/// Enables resizing the game window by the user.
|
||||
/// </summary>
|
||||
[DefaultValue(false)]
|
||||
[EditorOrder(40), EditorDisplay("Window"), Tooltip("Enables resizing the game window by the user.")]
|
||||
public bool ResizableWindow = false;
|
||||
|
||||
/// <summary>
|
||||
/// Enables game running when application window loses focus.
|
||||
/// </summary>
|
||||
[DefaultValue(false)]
|
||||
[EditorOrder(1010), EditorDisplay("Other", "Run In Background"), Tooltip("Enables game running when application window loses focus.")]
|
||||
public bool RunInBackground = false;
|
||||
|
||||
/// <summary>
|
||||
/// Limits maximum amount of concurrent game instances running to one, otherwise user may launch application more than once.
|
||||
/// </summary>
|
||||
[DefaultValue(false)]
|
||||
[EditorOrder(1020), EditorDisplay("Other"), Tooltip("Limits maximum amount of concurrent game instances running to one, otherwise user may launch application more than once.")]
|
||||
public bool ForceSingleInstance = false;
|
||||
|
||||
/// <summary>
|
||||
/// Custom icon texture to use for the application (overrides the default one).
|
||||
/// </summary>
|
||||
[DefaultValue(null)]
|
||||
[EditorOrder(1030), EditorDisplay("Other"), Tooltip("Custom icon texture to use for the application (overrides the default one).")]
|
||||
public Texture OverrideIcon;
|
||||
|
||||
/// <summary>
|
||||
/// Enables support for DirectX 12. Disabling it reduces compiled shaders count.
|
||||
/// </summary>
|
||||
[DefaultValue(false)]
|
||||
[EditorOrder(2000), EditorDisplay("Graphics", "Support DirectX 12"), Tooltip("Enables support for DirectX 12. Disabling it reduces compiled shaders count.")]
|
||||
public bool SupportDX12 = false;
|
||||
|
||||
/// <summary>
|
||||
/// Enables support for DirectX 11. Disabling it reduces compiled shaders count.
|
||||
/// </summary>
|
||||
[DefaultValue(true)]
|
||||
[EditorOrder(2010), EditorDisplay("Graphics", "Support DirectX 11"), Tooltip("Enables support for DirectX 11. Disabling it reduces compiled shaders count.")]
|
||||
public bool SupportDX11 = true;
|
||||
|
||||
/// <summary>
|
||||
/// Enables support for DirectX 10 and DirectX 10.1. Disabling it reduces compiled shaders count.
|
||||
/// </summary>
|
||||
[DefaultValue(false)]
|
||||
[EditorOrder(2020), EditorDisplay("Graphics", "Support DirectX 10"), Tooltip("Enables support for DirectX 10 and DirectX 10.1. Disabling it reduces compiled shaders count.")]
|
||||
public bool SupportDX10 = false;
|
||||
|
||||
/// <summary>
|
||||
/// Enables support for Vulkan. Disabling it reduces compiled shaders count.
|
||||
/// </summary>
|
||||
[DefaultValue(false)]
|
||||
[EditorOrder(2030), EditorDisplay("Graphics", "Support Vulkan"), Tooltip("Enables support for Vulkan. Disabling it reduces compiled shaders count.")]
|
||||
public bool SupportVulkan = false;
|
||||
}
|
||||
}
|
||||
@@ -120,9 +120,8 @@ namespace FlaxEditor.Content
|
||||
}
|
||||
else
|
||||
{
|
||||
QueryFilterHelper.Range[] ranges;
|
||||
var text = Text;
|
||||
if (QueryFilterHelper.Match(filterText, text, out ranges))
|
||||
if (QueryFilterHelper.Match(filterText, text, out QueryFilterHelper.Range[] ranges))
|
||||
{
|
||||
// Update highlights
|
||||
if (_highlights == null)
|
||||
@@ -295,7 +294,8 @@ namespace FlaxEditor.Content
|
||||
StartRenaming();
|
||||
return true;
|
||||
case KeyboardKeys.Delete:
|
||||
Editor.Instance.Windows.ContentWin.Delete(Folder);
|
||||
if (Folder.Exists)
|
||||
Editor.Instance.Windows.ContentWin.Delete(Folder);
|
||||
return true;
|
||||
}
|
||||
if (RootWindow.GetKey(KeyboardKeys.Control))
|
||||
@@ -303,7 +303,8 @@ namespace FlaxEditor.Content
|
||||
switch (key)
|
||||
{
|
||||
case KeyboardKeys.D:
|
||||
Editor.Instance.Windows.ContentWin.Duplicate(Folder);
|
||||
if (Folder.Exists)
|
||||
Editor.Instance.Windows.ContentWin.Duplicate(Folder);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,6 +174,11 @@ struct FLAXENGINE_API CookingData
|
||||
/// </summary>
|
||||
BuildOptions Options;
|
||||
|
||||
/// <summary>
|
||||
/// The list of custom defines passed to the build tool when compiling project scripts. Can be used in build scripts for configuration (Configuration.CustomDefines).
|
||||
/// </summary>
|
||||
Array<String> CustomDefines;
|
||||
|
||||
/// <summary>
|
||||
/// The original output path (actual OutputPath could be modified by the Platform Tools or a plugin for additional layout customizations or packaging). This path is preserved.
|
||||
/// </summary>
|
||||
|
||||
@@ -43,53 +43,11 @@
|
||||
#endif
|
||||
#if PLATFORM_TOOLS_XBOX_SCARLETT
|
||||
#include "Platforms/XboxScarlett/Editor/PlatformTools/XboxScarlettPlatformTools.h"
|
||||
#include "Platforms/XboxScarlett/Engine/Platform/XboxScarlettPlatformSettings.h"
|
||||
#endif
|
||||
#if PLATFORM_TOOLS_ANDROID
|
||||
#include "Platform/Android/AndroidPlatformTools.h"
|
||||
#include "Engine/Platform/Android/AndroidPlatformSettings.h"
|
||||
#endif
|
||||
|
||||
void LoadPlatformSettingsEditor(ISerializable::DeserializeStream& data)
|
||||
{
|
||||
#define LOAD_SETTINGS(nodeName, settingsType) \
|
||||
{ \
|
||||
Guid id = JsonTools::GetGuid(data, nodeName); \
|
||||
if (id.IsValid()) \
|
||||
{ \
|
||||
AssetReference<JsonAsset> subAsset = Content::LoadAsync<JsonAsset>(id); \
|
||||
if (subAsset) \
|
||||
{ \
|
||||
if (!subAsset->WaitForLoaded()) \
|
||||
{ \
|
||||
settingsType::Instance()->Deserialize(*subAsset->Data, nullptr); \
|
||||
settingsType::Instance()->Apply(); \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
{ LOG(Warning, "Cannot load " nodeName " settings"); } \
|
||||
} \
|
||||
}
|
||||
#if PLATFORM_TOOLS_WINDOWS
|
||||
LOAD_SETTINGS("WindowsPlatform", WindowsPlatformSettings);
|
||||
#endif
|
||||
#if PLATFORM_TOOLS_UWP || PLATFORM_TOOLS_XBOX_ONE
|
||||
LOAD_SETTINGS("UWPPlatform", UWPPlatformSettings);
|
||||
#endif
|
||||
#if PLATFORM_TOOLS_LINUX
|
||||
LOAD_SETTINGS("LinuxPlatform", LinuxPlatformSettings);
|
||||
#endif
|
||||
#if PLATFORM_TOOLS_PS4
|
||||
LOAD_SETTINGS("PS4Platform", PS4PlatformSettings);
|
||||
#endif
|
||||
#if PLATFORM_TOOLS_XBOX_SCARLETT
|
||||
LOAD_SETTINGS("XboxScarlettPlatform", XboxScarlettPlatformSettings);
|
||||
#endif
|
||||
#if PLATFORM_TOOLS_ANDROID
|
||||
LOAD_SETTINGS("AndroidPlatform", AndroidPlatformSettings);
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace GameCookerImpl
|
||||
{
|
||||
MMethod* Internal_OnEvent = nullptr;
|
||||
@@ -299,7 +257,7 @@ PlatformTools* GameCooker::GetTools(BuildPlatform platform)
|
||||
return result;
|
||||
}
|
||||
|
||||
void GameCooker::Build(BuildPlatform platform, BuildConfiguration configuration, const StringView& outputPath, BuildOptions options)
|
||||
void GameCooker::Build(BuildPlatform platform, BuildConfiguration configuration, const StringView& outputPath, BuildOptions options, const Array<String>& customDefines)
|
||||
{
|
||||
if (IsRunning())
|
||||
{
|
||||
@@ -323,6 +281,7 @@ void GameCooker::Build(BuildPlatform platform, BuildConfiguration configuration,
|
||||
data.Platform = platform;
|
||||
data.Configuration = configuration;
|
||||
data.Options = options;
|
||||
data.CustomDefines = customDefines;
|
||||
data.OutputPath = outputPath;
|
||||
FileSystem::NormalizePath(data.OutputPath);
|
||||
data.OutputPath = data.OriginalOutputPath = FileSystem::ConvertRelativePathToAbsolute(Globals::ProjectFolder, data.OutputPath);
|
||||
@@ -497,7 +456,7 @@ int32 GameCookerImpl::ThreadFunction()
|
||||
|
||||
bool GameCookerService::Init()
|
||||
{
|
||||
auto editorAssembly = GetBinaryModuleFlaxEngine()->Assembly;
|
||||
auto editorAssembly = ((NativeBinaryModule*)GetBinaryModuleFlaxEngine())->Assembly;
|
||||
editorAssembly->Unloading.Bind(OnEditorAssemblyUnloading);
|
||||
|
||||
return false;
|
||||
|
||||
@@ -84,7 +84,8 @@ public:
|
||||
/// <param name="configuration">The build configuration.</param>
|
||||
/// <param name="outputPath">The output path (output directory).</param>
|
||||
/// <param name="options">The build options.</param>
|
||||
API_FUNCTION() static void Build(BuildPlatform platform, BuildConfiguration configuration, const StringView& outputPath, BuildOptions options);
|
||||
/// <param name="customDefines">The list of custom defines passed to the build tool when compiling project scripts. Can be used in build scripts for configuration (Configuration.CustomDefines).</param>
|
||||
API_FUNCTION() static void Build(BuildPlatform platform, BuildConfiguration configuration, const StringView& outputPath, BuildOptions options, const Array<String>& customDefines);
|
||||
|
||||
/// <summary>
|
||||
/// Sends a cancel event to the game building service.
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "AndroidPlatformTools.h"
|
||||
#include "Editor/Editor.h"
|
||||
#include "Editor/ProjectInfo.h"
|
||||
#include "Engine/Platform/File.h"
|
||||
#include "Engine/Platform/FileSystem.h"
|
||||
#include "Engine/Platform/Android/AndroidPlatformSettings.h"
|
||||
@@ -12,6 +13,10 @@
|
||||
#include "Engine/Core/Config/GameSettings.h"
|
||||
#include "Engine/Core/Config/BuildSettings.h"
|
||||
#include "Editor/Utilities/EditorUtilities.h"
|
||||
#include "Engine/Content/Content.h"
|
||||
#include "Engine/Content/JsonAsset.h"
|
||||
|
||||
IMPLEMENT_SETTINGS_GETTER(AndroidPlatformSettings, AndroidPlatform);
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -106,7 +111,8 @@ void AndroidPlatformTools::OnBuildStarted(CookingData& data)
|
||||
|
||||
bool AndroidPlatformTools::OnPostProcess(CookingData& data)
|
||||
{
|
||||
const auto platformSettings = AndroidPlatformSettings::Instance();
|
||||
const auto gameSettings = GameSettings::Get();
|
||||
const auto platformSettings = AndroidPlatformSettings::Get();
|
||||
const auto platformDataPath = data.GetPlatformBinariesRoot();
|
||||
const auto assetsPath = data.OutputPath;
|
||||
const auto jniLibsPath = data.OriginalOutputPath / TEXT("app/jniLibs");
|
||||
@@ -125,11 +131,11 @@ bool AndroidPlatformTools::OnPostProcess(CookingData& data)
|
||||
// Setup package name (eg. com.company.project)
|
||||
String packageName = platformSettings->PackageName;
|
||||
{
|
||||
String productName = GameSettings::ProductName;
|
||||
String productName = gameSettings->ProductName;
|
||||
productName.Replace(TEXT(" "), TEXT(""));
|
||||
productName.Replace(TEXT("."), TEXT(""));
|
||||
productName.Replace(TEXT("-"), TEXT(""));
|
||||
String companyName = GameSettings::CompanyName;
|
||||
String companyName = gameSettings->CompanyName;
|
||||
companyName.Replace(TEXT(" "), TEXT(""));
|
||||
companyName.Replace(TEXT("."), TEXT(""));
|
||||
companyName.Replace(TEXT("-"), TEXT(""));
|
||||
@@ -235,7 +241,7 @@ bool AndroidPlatformTools::OnPostProcess(CookingData& data)
|
||||
EditorUtilities::ReplaceInFile(manifestPath, TEXT("${AndroidPermissions}"), permissions);
|
||||
EditorUtilities::ReplaceInFile(manifestPath, TEXT("${AndroidAttributes}"), attributes);
|
||||
const String stringsPath = data.OriginalOutputPath / TEXT("app/src/main/res/values/strings.xml");
|
||||
EditorUtilities::ReplaceInFile(stringsPath, TEXT("${ProjectName}"), GameSettings::ProductName);
|
||||
EditorUtilities::ReplaceInFile(stringsPath, TEXT("${ProjectName}"), gameSettings->ProductName);
|
||||
|
||||
// Deploy native binaries to the output location (per-ABI)
|
||||
const String abiBinariesPath = jniLibsPath / abi;
|
||||
@@ -256,7 +262,8 @@ bool AndroidPlatformTools::OnPostProcess(CookingData& data)
|
||||
|
||||
// TODO: expose event to inject custom gradle and manifest options or custom binaries into app
|
||||
|
||||
if (BuildSettings::Instance()->SkipPackaging)
|
||||
const auto buildSettings = BuildSettings::Get();
|
||||
if (buildSettings->SkipPackaging)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -286,7 +293,7 @@ bool AndroidPlatformTools::OnPostProcess(CookingData& data)
|
||||
#else
|
||||
const Char* gradlew = TEXT("gradlew");
|
||||
#endif
|
||||
const bool distributionPackage = BuildSettings::Instance()->ForDistribution;
|
||||
const bool distributionPackage = buildSettings->ForDistribution;
|
||||
const String gradleCommand = String::Format(TEXT("\"{0}\" {1}"), data.OriginalOutputPath / gradlew, distributionPackage ? TEXT("assemble") : TEXT("assembleDebug"));
|
||||
const int32 result = Platform::RunProcess(gradleCommand, data.OriginalOutputPath, envVars, true);
|
||||
if (result != 0)
|
||||
@@ -297,7 +304,7 @@ bool AndroidPlatformTools::OnPostProcess(CookingData& data)
|
||||
|
||||
// Copy result package
|
||||
const String apk = data.OriginalOutputPath / (distributionPackage ? TEXT("app/build/outputs/apk/release/app-release-unsigned.apk") : TEXT("app/build/outputs/apk/debug/app-debug.apk"));
|
||||
const String outputApk = data.OriginalOutputPath / GameSettings::ProductName + TEXT(".apk");
|
||||
const String outputApk = data.OriginalOutputPath / gameSettings->ProductName + TEXT(".apk");
|
||||
if (FileSystem::CopyFile(outputApk, apk))
|
||||
{
|
||||
LOG(Error, "Failed to copy package from {0} to {1}", apk, outputApk);
|
||||
|
||||
@@ -9,6 +9,10 @@
|
||||
#include "Editor/Utilities/EditorUtilities.h"
|
||||
#include "Engine/Tools/TextureTool/TextureTool.h"
|
||||
#include "Engine/Graphics/Textures/TextureData.h"
|
||||
#include "Engine/Content/Content.h"
|
||||
#include "Engine/Content/JsonAsset.h"
|
||||
|
||||
IMPLEMENT_SETTINGS_GETTER(LinuxPlatformSettings, LinuxPlatform);
|
||||
|
||||
const Char* LinuxPlatformTools::GetDisplayName() const
|
||||
{
|
||||
@@ -32,7 +36,8 @@ ArchitectureType LinuxPlatformTools::GetArchitecture() const
|
||||
|
||||
bool LinuxPlatformTools::OnDeployBinaries(CookingData& data)
|
||||
{
|
||||
const auto platformSettings = LinuxPlatformSettings::Instance();
|
||||
const auto gameSettings = GameSettings::Get();
|
||||
const auto platformSettings = LinuxPlatformSettings::Get();
|
||||
const auto outputPath = data.OutputPath;
|
||||
|
||||
// Copy binaries
|
||||
@@ -60,7 +65,7 @@ bool LinuxPlatformTools::OnDeployBinaries(CookingData& data)
|
||||
// Apply game executable file name
|
||||
#if !BUILD_DEBUG
|
||||
const String outputExePath = outputPath / TEXT("FlaxGame");
|
||||
const String gameExePath = outputPath / GameSettings::ProductName;
|
||||
const String gameExePath = outputPath / gameSettings->ProductName;
|
||||
if (FileSystem::FileExists(outputExePath) && gameExePath.Compare(outputExePath, StringSearchCase::IgnoreCase) == 0)
|
||||
{
|
||||
if (FileSystem::MoveFile(gameExePath, outputExePath, true))
|
||||
@@ -74,6 +79,11 @@ bool LinuxPlatformTools::OnDeployBinaries(CookingData& data)
|
||||
const String gameExePath = outputPath / TEXT("FlaxGame");
|
||||
#endif
|
||||
|
||||
// Ensure the output binary can be executed
|
||||
#if PLATFORM_LINUX
|
||||
system(*StringAnsi(String::Format(TEXT("chmod +x \"{0}\""), gameExePath)));
|
||||
#endif
|
||||
|
||||
// Apply game icon
|
||||
TextureData iconData;
|
||||
if (!EditorUtilities::GetApplicationImage(platformSettings->OverrideIcon, iconData))
|
||||
|
||||
@@ -11,6 +11,10 @@
|
||||
#include "Engine/Serialization/FileWriteStream.h"
|
||||
#include "Editor/Utilities/EditorUtilities.h"
|
||||
#include "Engine/Engine/Globals.h"
|
||||
#include "Engine/Content/Content.h"
|
||||
#include "Engine/Content/JsonAsset.h"
|
||||
|
||||
IMPLEMENT_SETTINGS_GETTER(UWPPlatformSettings, UWPPlatform);
|
||||
|
||||
bool UWPPlatformTools::UseAOT() const
|
||||
{
|
||||
@@ -37,8 +41,9 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
||||
bool isXboxOne = data.Platform == BuildPlatform::XboxOne;
|
||||
const auto platformDataPath = Globals::StartupFolder / TEXT("Source/Platforms");
|
||||
const auto uwpDataPath = platformDataPath / (isXboxOne ? TEXT("XboxOne") : TEXT("UWP")) / TEXT("Binaries");
|
||||
const auto platformSettings = UWPPlatformSettings::Instance();
|
||||
Array<byte> fileTemplate;
|
||||
const auto gameSettings = GameSettings::Get();
|
||||
const auto platformSettings = UWPPlatformSettings::Get();
|
||||
StringAnsi fileTemplate;
|
||||
|
||||
// Copy binaries
|
||||
const auto binPath = data.GetGameBinariesPath();
|
||||
@@ -66,7 +71,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
||||
}
|
||||
}
|
||||
|
||||
const auto projectName = GameSettings::ProductName;
|
||||
const auto projectName = gameSettings->ProductName;
|
||||
auto defaultNamespace = projectName;
|
||||
ScriptsBuilder::FilterNamespaceText(defaultNamespace);
|
||||
const StringAnsi projectGuid = "{3A9A2246-71DD-4567-9ABF-3E040310E30E}";
|
||||
@@ -102,7 +107,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
||||
// Generate new temp cert if missing
|
||||
if (!FileSystem::FileExists(dstCertificatePath))
|
||||
{
|
||||
if (EditorUtilities::GenerateCertificate(GameSettings::CompanyName, dstCertificatePath))
|
||||
if (EditorUtilities::GenerateCertificate(gameSettings->CompanyName, dstCertificatePath))
|
||||
{
|
||||
LOG(Warning, "Failed to create certificate.");
|
||||
}
|
||||
@@ -144,12 +149,11 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
||||
if (!FileSystem::FileExists(dstAssemblyInfoPath))
|
||||
{
|
||||
// Get template
|
||||
if (File::ReadAllBytes(srcAssemblyInfoPath, fileTemplate))
|
||||
if (File::ReadAllText(srcAssemblyInfoPath, fileTemplate))
|
||||
{
|
||||
data.Error(TEXT("Failed to load AssemblyInfo.cs template."));
|
||||
return true;
|
||||
}
|
||||
fileTemplate[fileTemplate.Count() - 1] = 0;
|
||||
|
||||
// Write data to file
|
||||
auto file = FileWriteStream::Open(dstAssemblyInfoPath);
|
||||
@@ -158,9 +162,9 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
||||
{
|
||||
auto now = DateTime::Now();
|
||||
file->WriteTextFormatted(
|
||||
(char*)fileTemplate.Get()
|
||||
, GameSettings::ProductName.ToStringAnsi()
|
||||
, GameSettings::CompanyName.ToStringAnsi()
|
||||
fileTemplate.Get()
|
||||
, gameSettings->ProductName.ToStringAnsi()
|
||||
, gameSettings->CompanyName.ToStringAnsi()
|
||||
, now.GetYear()
|
||||
);
|
||||
hasError = file->HasError();
|
||||
@@ -177,12 +181,11 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
||||
if (!FileSystem::FileExists(dstAppPath))
|
||||
{
|
||||
// Get template
|
||||
if (File::ReadAllBytes(srcAppPath, fileTemplate))
|
||||
if (File::ReadAllText(srcAppPath, fileTemplate))
|
||||
{
|
||||
data.Error(TEXT("Failed to load App.cs template."));
|
||||
return true;
|
||||
}
|
||||
fileTemplate[fileTemplate.Count() - 1] = 0;
|
||||
|
||||
// Write data to file
|
||||
auto file = FileWriteStream::Open(dstAppPath);
|
||||
@@ -190,7 +193,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
||||
if (file)
|
||||
{
|
||||
file->WriteTextFormatted(
|
||||
(char*)fileTemplate.Get()
|
||||
fileTemplate.Get()
|
||||
, defaultNamespace.ToStringAnsi() // {0} Default Namespace
|
||||
);
|
||||
hasError = file->HasError();
|
||||
@@ -206,12 +209,11 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
||||
const auto srcFlaxGeneratedPath = uwpDataPath / TEXT("FlaxGenerated.cs");
|
||||
{
|
||||
// Get template
|
||||
if (File::ReadAllBytes(srcFlaxGeneratedPath, fileTemplate))
|
||||
if (File::ReadAllText(srcFlaxGeneratedPath, fileTemplate))
|
||||
{
|
||||
data.Error(TEXT("Failed to load FlaxGenerated.cs template."));
|
||||
return true;
|
||||
}
|
||||
fileTemplate[fileTemplate.Count() - 1] = 0;
|
||||
|
||||
// Prepare
|
||||
StringAnsi autoRotationPreferences;
|
||||
@@ -247,7 +249,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
||||
if (file)
|
||||
{
|
||||
file->WriteTextFormatted(
|
||||
(char*)fileTemplate.Get()
|
||||
fileTemplate.Get()
|
||||
, autoRotationPreferences.Get()
|
||||
, preferredLaunchWindowingMode.Get()
|
||||
);
|
||||
@@ -267,12 +269,11 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
||||
if (!FileSystem::FileExists(dstSolutionPath))
|
||||
{
|
||||
// Get template
|
||||
if (File::ReadAllBytes(srcSolutionPath, fileTemplate))
|
||||
if (File::ReadAllText(srcSolutionPath, fileTemplate))
|
||||
{
|
||||
data.Error(TEXT("Failed to load Solution.sln template."));
|
||||
return true;
|
||||
}
|
||||
fileTemplate[fileTemplate.Count() - 1] = 0;
|
||||
|
||||
// Write data to file
|
||||
auto file = FileWriteStream::Open(dstSolutionPath);
|
||||
@@ -280,7 +281,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
||||
if (file)
|
||||
{
|
||||
file->WriteTextFormatted(
|
||||
(char*)fileTemplate.Get()
|
||||
fileTemplate.Get()
|
||||
, projectName.ToStringAnsi() // {0} Project Name
|
||||
, mode // {1} Platform Mode
|
||||
, projectGuid.ToStringAnsi() // {2} Project ID
|
||||
@@ -300,12 +301,11 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
||||
const auto srcProjectPath = uwpDataPath / TEXT("Project.csproj");
|
||||
{
|
||||
// Get template
|
||||
if (File::ReadAllBytes(srcProjectPath, fileTemplate))
|
||||
if (File::ReadAllText(srcProjectPath, fileTemplate))
|
||||
{
|
||||
data.Error(TEXT("Failed to load Project.csproj template."));
|
||||
return true;
|
||||
}
|
||||
fileTemplate[fileTemplate.Count() - 1] = 0;
|
||||
|
||||
// Build included files data
|
||||
StringBuilder filesInclude(2048);
|
||||
@@ -329,7 +329,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
||||
if (file)
|
||||
{
|
||||
file->WriteTextFormatted(
|
||||
(char*)fileTemplate.Get()
|
||||
fileTemplate.Get()
|
||||
, projectName.ToStringAnsi() // {0} Project Name
|
||||
, mode // {1} Platform Mode
|
||||
, projectGuid.Get() // {2} Project ID
|
||||
@@ -352,12 +352,11 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
||||
if (!FileSystem::FileExists(dstManifestPath))
|
||||
{
|
||||
// Get template
|
||||
if (File::ReadAllBytes(srcManifestPath, fileTemplate))
|
||||
if (File::ReadAllText(srcManifestPath, fileTemplate))
|
||||
{
|
||||
data.Error(TEXT("Failed to load Package.appxmanifest template."));
|
||||
return true;
|
||||
}
|
||||
fileTemplate[fileTemplate.Count() - 1] = 0;
|
||||
|
||||
// Build included files data
|
||||
StringBuilder filesInclude(2048);
|
||||
@@ -380,9 +379,9 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
||||
if (file)
|
||||
{
|
||||
file->WriteTextFormatted(
|
||||
(char*)fileTemplate.Get()
|
||||
fileTemplate.Get()
|
||||
, projectName.ToStringAnsi() // {0} Display Name
|
||||
, GameSettings::CompanyName.ToStringAnsi() // {1} Company Name
|
||||
, gameSettings->CompanyName.ToStringAnsi() // {1} Company Name
|
||||
, productId.ToStringAnsi() // {2} Product ID
|
||||
, defaultNamespace.ToStringAnsi() // {3} Default Namespace
|
||||
);
|
||||
|
||||
@@ -8,6 +8,10 @@
|
||||
#include "Engine/Core/Config/GameSettings.h"
|
||||
#include "Editor/Utilities/EditorUtilities.h"
|
||||
#include "Engine/Graphics/Textures/TextureData.h"
|
||||
#include "Engine/Content/Content.h"
|
||||
#include "Engine/Content/JsonAsset.h"
|
||||
|
||||
IMPLEMENT_SETTINGS_GETTER(WindowsPlatformSettings, WindowsPlatform);
|
||||
|
||||
const Char* WindowsPlatformTools::GetDisplayName() const
|
||||
{
|
||||
@@ -31,7 +35,7 @@ ArchitectureType WindowsPlatformTools::GetArchitecture() const
|
||||
|
||||
bool WindowsPlatformTools::OnDeployBinaries(CookingData& data)
|
||||
{
|
||||
const auto platformSettings = WindowsPlatformSettings::Instance();
|
||||
const auto platformSettings = WindowsPlatformSettings::Get();
|
||||
const auto& outputPath = data.OutputPath;
|
||||
|
||||
// Apply executable icon
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "Engine/Serialization/JsonWriters.h"
|
||||
#include "Editor/Cooker/PlatformTools.h"
|
||||
#include "Editor/Editor.h"
|
||||
#include "Editor/ProjectInfo.h"
|
||||
|
||||
bool CompileScriptsStep::DeployBinaries(CookingData& data, const String& path, const String& projectFolderPath)
|
||||
{
|
||||
@@ -100,7 +101,7 @@ bool CompileScriptsStep::DeployBinaries(CookingData& data, const String& path, c
|
||||
// Deploy files
|
||||
Array<String> files(16);
|
||||
const String outputPath = StringUtils::GetDirectoryName(path);
|
||||
FileSystem::DirectoryGetFiles(files, outputPath, TEXT("*.*"), DirectorySearchOption::TopDirectoryOnly);
|
||||
FileSystem::DirectoryGetFiles(files, outputPath, TEXT("*"), DirectorySearchOption::TopDirectoryOnly);
|
||||
for (int32 i = files.Count() - 1; i >= 0; i--)
|
||||
{
|
||||
bool skip = false;
|
||||
@@ -217,6 +218,11 @@ bool CompileScriptsStep::Perform(CookingData& data)
|
||||
args += TEXT(" -SkipTargets=FlaxGame");
|
||||
}
|
||||
#endif
|
||||
for (auto& define : data.CustomDefines)
|
||||
{
|
||||
args += TEXT(" -D");
|
||||
args += define;
|
||||
}
|
||||
if (ScriptsBuilder::RunBuildTool(args))
|
||||
{
|
||||
data.Error(TEXT("Failed to compile game scripts."));
|
||||
|
||||
@@ -160,8 +160,9 @@ void CookAssetsStep::CacheData::Load(CookingData& data)
|
||||
|
||||
// Invalidate shaders and assets with shaders if need to rebuild them
|
||||
bool invalidateShaders = false;
|
||||
const bool shadersNoOptimize = BuildSettings::Instance()->ShadersNoOptimize;
|
||||
const bool shadersGenerateDebugData = BuildSettings::Instance()->ShadersGenerateDebugData;
|
||||
const auto buildSettings = BuildSettings::Get();
|
||||
const bool shadersNoOptimize = buildSettings->ShadersNoOptimize;
|
||||
const bool shadersGenerateDebugData = buildSettings->ShadersGenerateDebugData;
|
||||
if (shadersNoOptimize != Settings.Global.ShadersNoOptimize)
|
||||
{
|
||||
LOG(Info, "ShadersNoOptimize option has been modified.");
|
||||
@@ -175,7 +176,7 @@ void CookAssetsStep::CacheData::Load(CookingData& data)
|
||||
#if PLATFORM_TOOLS_WINDOWS
|
||||
if (data.Platform == BuildPlatform::Windows32 || data.Platform == BuildPlatform::Windows64)
|
||||
{
|
||||
const auto settings = WindowsPlatformSettings::Instance();
|
||||
const auto settings = WindowsPlatformSettings::Get();
|
||||
const bool modified =
|
||||
Settings.Windows.SupportDX11 != settings->SupportDX11 ||
|
||||
Settings.Windows.SupportDX10 != settings->SupportDX10 ||
|
||||
@@ -190,7 +191,7 @@ void CookAssetsStep::CacheData::Load(CookingData& data)
|
||||
#if PLATFORM_TOOLS_UWP
|
||||
if (data.Platform == BuildPlatform::UWPx86 || data.Platform == BuildPlatform::UWPx64)
|
||||
{
|
||||
const auto settings = UWPPlatformSettings::Instance();
|
||||
const auto settings = UWPPlatformSettings::Get();
|
||||
const bool modified =
|
||||
Settings.UWP.SupportDX11 != settings->SupportDX11 ||
|
||||
Settings.UWP.SupportDX10 != settings->SupportDX10;
|
||||
@@ -204,7 +205,7 @@ void CookAssetsStep::CacheData::Load(CookingData& data)
|
||||
#if PLATFORM_TOOLS_LINUX
|
||||
if (data.Platform == BuildPlatform::LinuxX64)
|
||||
{
|
||||
const auto settings = LinuxPlatformSettings::Instance();
|
||||
const auto settings = LinuxPlatformSettings::Get();
|
||||
const bool modified =
|
||||
Settings.Linux.SupportVulkan != settings->SupportVulkan;
|
||||
if (modified)
|
||||
@@ -322,6 +323,8 @@ bool ProcessShaderBase(CookAssetsStep::AssetCookData& data, ShaderAssetBase* ass
|
||||
auto sourceLength = sourceChunk->Size();
|
||||
Encryption::DecryptBytes((byte*)source, sourceLength);
|
||||
source[sourceLength - 1] = 0;
|
||||
while (sourceLength > 2 && source[sourceLength - 1] == 0)
|
||||
sourceLength--;
|
||||
|
||||
// Init shader cache output stream
|
||||
// TODO: reuse MemoryWriteStream per cooking process to reduce dynamic memory allocations
|
||||
@@ -365,11 +368,12 @@ bool ProcessShaderBase(CookAssetsStep::AssetCookData& data, ShaderAssetBase* ass
|
||||
// Compile for a target platform
|
||||
switch (data.Data.Platform)
|
||||
{
|
||||
#if PLATFORM_TOOLS_WINDOWS
|
||||
case BuildPlatform::Windows32:
|
||||
case BuildPlatform::Windows64:
|
||||
{
|
||||
const char* platformDefineName = "PLATFORM_WINDOWS";
|
||||
const auto settings = WindowsPlatformSettings::Instance();
|
||||
const auto settings = WindowsPlatformSettings::Get();
|
||||
if (settings->SupportDX12)
|
||||
{
|
||||
COMPILE_PROFILE(DirectX_SM6, SHADER_FILE_CHUNK_INTERNAL_D3D_SM6_CACHE);
|
||||
@@ -388,12 +392,13 @@ bool ProcessShaderBase(CookAssetsStep::AssetCookData& data, ShaderAssetBase* ass
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if PLATFORM_TOOLS_UWP
|
||||
case BuildPlatform::UWPx86:
|
||||
case BuildPlatform::UWPx64:
|
||||
{
|
||||
const char* platformDefineName = "PLATFORM_UWP";
|
||||
const auto settings = UWPPlatformSettings::Instance();
|
||||
const auto settings = UWPPlatformSettings::Get();
|
||||
if (settings->SupportDX11)
|
||||
{
|
||||
COMPILE_PROFILE(DirectX_SM5, SHADER_FILE_CHUNK_INTERNAL_D3D_SM5_CACHE);
|
||||
@@ -405,17 +410,19 @@ bool ProcessShaderBase(CookAssetsStep::AssetCookData& data, ShaderAssetBase* ass
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if PLATFORM_TOOLS_UWP
|
||||
case BuildPlatform::XboxOne:
|
||||
{
|
||||
const char* platformDefineName = "PLATFORM_XBOX_ONE";
|
||||
COMPILE_PROFILE(DirectX_SM4, SHADER_FILE_CHUNK_INTERNAL_D3D_SM4_CACHE);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if PLATFORM_TOOLS_LINUX
|
||||
case BuildPlatform::LinuxX64:
|
||||
{
|
||||
const char* platformDefineName = "PLATFORM_LINUX";
|
||||
const auto settings = LinuxPlatformSettings::Instance();
|
||||
const auto settings = LinuxPlatformSettings::Get();
|
||||
if (settings->SupportVulkan)
|
||||
{
|
||||
COMPILE_PROFILE(Vulkan_SM5, SHADER_FILE_CHUNK_INTERNAL_VULKAN_SM5_CACHE);
|
||||
@@ -423,24 +430,30 @@ bool ProcessShaderBase(CookAssetsStep::AssetCookData& data, ShaderAssetBase* ass
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if PLATFORM_TOOLS_PS4
|
||||
case BuildPlatform::PS4:
|
||||
{
|
||||
const char* platformDefineName = "PLATFORM_PS4";
|
||||
COMPILE_PROFILE(PS4, SHADER_FILE_CHUNK_INTERNAL_GENERIC_CACHE);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if PLATFORM_TOOLS_XBOX_SCARLETT
|
||||
case BuildPlatform::XboxScarlett:
|
||||
{
|
||||
const char* platformDefineName = "PLATFORM_XBOX_SCARLETT";
|
||||
COMPILE_PROFILE(DirectX_SM6, SHADER_FILE_CHUNK_INTERNAL_D3D_SM6_CACHE);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if PLATFORM_TOOLS_ANDROID
|
||||
case BuildPlatform::AndroidARM64:
|
||||
{
|
||||
const char* platformDefineName = "PLATFORM_ANDROID";
|
||||
COMPILE_PROFILE(Vulkan_SM5, SHADER_FILE_CHUNK_INTERNAL_VULKAN_SM5_CACHE);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
{
|
||||
LOG(Warning, "Not implemented platform or shaders not supported.");
|
||||
@@ -881,7 +894,8 @@ bool CookAssetsStep::Perform(CookingData& data)
|
||||
data.StepProgress(TEXT("Loading build cache"), 0);
|
||||
|
||||
// Prepare
|
||||
const auto buildSettings = BuildSettings::Instance();
|
||||
const auto gameSettings = GameSettings::Get();
|
||||
const auto buildSettings = BuildSettings::Get();
|
||||
const int32 contentKey = buildSettings->ContentKey == 0 ? rand() : buildSettings->ContentKey;
|
||||
AssetsRegistry.Clear();
|
||||
AssetPathsMapping.Clear();
|
||||
@@ -891,23 +905,28 @@ bool CookAssetsStep::Perform(CookingData& data)
|
||||
cache.Load(data);
|
||||
|
||||
// Update build settings
|
||||
#if PLATFORM_TOOLS_WINDOWS
|
||||
{
|
||||
const auto settings = WindowsPlatformSettings::Instance();
|
||||
const auto settings = WindowsPlatformSettings::Get();
|
||||
cache.Settings.Windows.SupportDX11 = settings->SupportDX11;
|
||||
cache.Settings.Windows.SupportDX10 = settings->SupportDX10;
|
||||
cache.Settings.Windows.SupportVulkan = settings->SupportVulkan;
|
||||
}
|
||||
#endif
|
||||
#if PLATFORM_TOOLS_UWP
|
||||
{
|
||||
const auto settings = UWPPlatformSettings::Instance();
|
||||
const auto settings = UWPPlatformSettings::Get();
|
||||
cache.Settings.UWP.SupportDX11 = settings->SupportDX11;
|
||||
cache.Settings.UWP.SupportDX10 = settings->SupportDX10;
|
||||
}
|
||||
#endif
|
||||
#if PLATFORM_TOOLS_LINUX
|
||||
{
|
||||
const auto settings = LinuxPlatformSettings::Instance();
|
||||
const auto settings = LinuxPlatformSettings::Get();
|
||||
cache.Settings.Linux.SupportVulkan = settings->SupportVulkan;
|
||||
}
|
||||
#endif
|
||||
{
|
||||
const auto buildSettings = BuildSettings::Instance();
|
||||
cache.Settings.Global.ShadersNoOptimize = buildSettings->ShadersNoOptimize;
|
||||
cache.Settings.Global.ShadersGenerateDebugData = buildSettings->ShadersGenerateDebugData;
|
||||
}
|
||||
@@ -1004,7 +1023,7 @@ bool CookAssetsStep::Perform(CookingData& data)
|
||||
// Create build game header
|
||||
{
|
||||
GameHeaderFlags gameFlags = GameHeaderFlags::None;
|
||||
if (!GameSettings::NoSplashScreen)
|
||||
if (!gameSettings->NoSplashScreen)
|
||||
gameFlags |= GameHeaderFlags::ShowSplashScreen;
|
||||
|
||||
// Open file
|
||||
@@ -1022,17 +1041,17 @@ bool CookAssetsStep::Perform(CookingData& data)
|
||||
Array<byte> bytes;
|
||||
bytes.Resize(808 + sizeof(Guid));
|
||||
Platform::MemoryClear(bytes.Get(), bytes.Count());
|
||||
int32 length = sizeof(Char) * GameSettings::ProductName.Length();
|
||||
Platform::MemoryCopy(bytes.Get() + 0, GameSettings::ProductName.Get(), length);
|
||||
int32 length = sizeof(Char) * gameSettings->ProductName.Length();
|
||||
Platform::MemoryCopy(bytes.Get() + 0, gameSettings->ProductName.Get(), length);
|
||||
bytes[length] = 0;
|
||||
bytes[length + 1] = 0;
|
||||
length = sizeof(Char) * GameSettings::CompanyName.Length();
|
||||
Platform::MemoryCopy(bytes.Get() + 400, GameSettings::CompanyName.Get(), length);
|
||||
length = sizeof(Char) * gameSettings->CompanyName.Length();
|
||||
Platform::MemoryCopy(bytes.Get() + 400, gameSettings->CompanyName.Get(), length);
|
||||
bytes[length + 400] = 0;
|
||||
bytes[length + 401] = 0;
|
||||
*(int32*)(bytes.Get() + 800) = (int32)gameFlags;
|
||||
*(int32*)(bytes.Get() + 804) = contentKey;
|
||||
*(Guid*)(bytes.Get() + 808) = GameSettings::SplashScreen;
|
||||
*(Guid*)(bytes.Get() + 808) = gameSettings->SplashScreen;
|
||||
Encryption::EncryptBytes(bytes.Get(), bytes.Count());
|
||||
stream->WriteArray(bytes);
|
||||
|
||||
@@ -1078,12 +1097,12 @@ bool CookAssetsStep::Perform(CookingData& data)
|
||||
|
||||
data.StepProgress(TEXT("Creating assets cache"), Step2ProgressEnd);
|
||||
|
||||
// Create asset paths mapping for the root assets.
|
||||
// Create asset paths mapping for the assets.
|
||||
// Assets mapping is use to convert paths used in Content::Load(path) into the asset id.
|
||||
// It fixes the issues when in build game all assets are in the packages while engine parts are requesting in-build assets by name.
|
||||
// It fixes the issues when in build game all assets are in the packages and are requested by path.
|
||||
// E.g. game settings are loaded from `Content/GameSettings.json` file which is packages in one of the packages.
|
||||
// Additionally it improves the in-build assets loading performance.
|
||||
for (auto i = data.RootAssets.Begin(); i.IsNotEnd(); ++i)
|
||||
// Additionally it improves the in-build assets loading performance (no more registry linear lookup for path by dictionary access).
|
||||
for (auto i = data.Assets.Begin(); i.IsNotEnd(); ++i)
|
||||
{
|
||||
if (Content::GetAssetInfo(i->Item, assetInfo))
|
||||
{
|
||||
|
||||
@@ -12,6 +12,7 @@ bool DeployDataStep::Perform(CookingData& data)
|
||||
{
|
||||
data.StepProgress(TEXT("Deploying engine data"), 0);
|
||||
const String depsRoot = data.GetPlatformBinariesRoot();
|
||||
const auto gameSettings = GameSettings::Get();
|
||||
|
||||
// Setup output folders and copy required data
|
||||
const auto contentDir = data.OutputPath / TEXT("Content");
|
||||
@@ -73,8 +74,9 @@ bool DeployDataStep::Perform(CookingData& data)
|
||||
data.AddRootEngineAsset(TEXT("Shaders/SSR"));
|
||||
data.AddRootEngineAsset(TEXT("Shaders/VolumetricFog"));
|
||||
data.AddRootEngineAsset(TEXT("Engine/DefaultMaterial"));
|
||||
data.AddRootEngineAsset(TEXT("Engine/DefaultDeformableMaterial"));
|
||||
data.AddRootEngineAsset(TEXT("Engine/DefaultTerrainMaterial"));
|
||||
if (!GameSettings::NoSplashScreen && !GameSettings::SplashScreen.IsValid())
|
||||
if (!gameSettings->NoSplashScreen && !gameSettings->SplashScreen.IsValid())
|
||||
data.AddRootEngineAsset(TEXT("Engine/Textures/Logo"));
|
||||
data.AddRootEngineAsset(TEXT("Engine/Textures/NormalTexture"));
|
||||
data.AddRootEngineAsset(TEXT("Engine/Textures/BlackTexture"));
|
||||
@@ -95,10 +97,12 @@ bool DeployDataStep::Perform(CookingData& data)
|
||||
data.AddRootEngineAsset(PRE_INTEGRATED_GF_ASSET_NAME);
|
||||
data.AddRootEngineAsset(SMAA_AREA_TEX);
|
||||
data.AddRootEngineAsset(SMAA_SEARCH_TEX);
|
||||
if (data.Configuration != BuildConfiguration::Release)
|
||||
data.AddRootEngineAsset(TEXT("Editor/Fonts/Roboto-Regular"));
|
||||
|
||||
// Register game assets
|
||||
data.StepProgress(TEXT("Deploying game data"), 50);
|
||||
auto& buildSettings = *BuildSettings::Instance();
|
||||
auto& buildSettings = *BuildSettings::Get();
|
||||
for (auto& e : buildSettings.AdditionalAssets)
|
||||
data.AddRootAsset(e.GetID());
|
||||
Array<String> files;
|
||||
|
||||
@@ -38,18 +38,23 @@ bool ValidateStep::Perform(CookingData& data)
|
||||
#endif
|
||||
|
||||
// Load game settings (may be modified via editor)
|
||||
GameSettings::Load();
|
||||
if (GameSettings::Load())
|
||||
{
|
||||
data.Error(TEXT("Failed to load game settings."));
|
||||
return true;
|
||||
}
|
||||
data.AddRootAsset(Globals::ProjectContentFolder / TEXT("GameSettings.json"));
|
||||
|
||||
// Validate game settings
|
||||
auto gameSettings = GameSettings::Get();
|
||||
{
|
||||
if (GameSettings::ProductName.IsEmpty())
|
||||
if (gameSettings->ProductName.IsEmpty())
|
||||
{
|
||||
data.Error(TEXT("Missing product name."));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (GameSettings::CompanyName.IsEmpty())
|
||||
if (gameSettings->CompanyName.IsEmpty())
|
||||
{
|
||||
data.Error(TEXT("Missing company name."));
|
||||
return true;
|
||||
@@ -58,7 +63,7 @@ bool ValidateStep::Perform(CookingData& data)
|
||||
// TODO: validate version
|
||||
|
||||
AssetInfo info;
|
||||
if (!Content::GetAssetInfo(GameSettings::FirstScene, info))
|
||||
if (!Content::GetAssetInfo(gameSettings->FirstScene, info))
|
||||
{
|
||||
data.Error(TEXT("Missing first scene. Set it in the game settings."));
|
||||
return true;
|
||||
|
||||
@@ -520,15 +520,46 @@ namespace FlaxEditor.CustomEditors
|
||||
try
|
||||
{
|
||||
string text;
|
||||
if (new ScriptType(typeof(FlaxEngine.Object)).IsAssignableFrom(Values.Type))
|
||||
if (ParentEditor is Dedicated.ScriptsEditor)
|
||||
{
|
||||
// Script
|
||||
text = JsonSerializer.Serialize(Values[0]);
|
||||
|
||||
// Remove properties that should be ignored when copy/pasting data
|
||||
if (text == null)
|
||||
text = string.Empty;
|
||||
int idx = text.IndexOf("\"Actor\":");
|
||||
if (idx != -1)
|
||||
{
|
||||
int endIdx = text.IndexOf("\n", idx);
|
||||
if (endIdx != -1)
|
||||
text = text.Remove(idx, endIdx - idx);
|
||||
}
|
||||
idx = text.IndexOf("\"Parent\":");
|
||||
if (idx != -1)
|
||||
{
|
||||
int endIdx = text.IndexOf("\n", idx);
|
||||
if (endIdx != -1)
|
||||
text = text.Remove(idx, endIdx - idx);
|
||||
}
|
||||
idx = text.IndexOf("\"OrderInParent\":");
|
||||
if (idx != -1)
|
||||
{
|
||||
int endIdx = text.IndexOf("\n", idx);
|
||||
if (endIdx != -1)
|
||||
text = text.Remove(idx, endIdx - idx);
|
||||
}
|
||||
}
|
||||
else if (new ScriptType(typeof(FlaxEngine.Object)).IsAssignableFrom(Values.Type))
|
||||
{
|
||||
// Object reference
|
||||
text = JsonSerializer.GetStringID(Values[0] as FlaxEngine.Object);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Default
|
||||
text = JsonSerializer.Serialize(Values[0]);
|
||||
}
|
||||
|
||||
Clipboard.Text = text;
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -538,7 +569,7 @@ namespace FlaxEditor.CustomEditors
|
||||
}
|
||||
}
|
||||
|
||||
private bool GetClipboardObject(out object result)
|
||||
private bool GetClipboardObject(out object result, bool deserialize)
|
||||
{
|
||||
result = null;
|
||||
var text = Clipboard.Text;
|
||||
@@ -546,8 +577,32 @@ namespace FlaxEditor.CustomEditors
|
||||
return false;
|
||||
|
||||
object obj;
|
||||
if (new ScriptType(typeof(FlaxEngine.Object)).IsAssignableFrom(Values.Type))
|
||||
if (ParentEditor is Dedicated.ScriptsEditor)
|
||||
{
|
||||
// Script
|
||||
obj = Values[0];
|
||||
if (deserialize)
|
||||
{
|
||||
if (Presenter.Undo != null && Presenter.Undo.Enabled)
|
||||
{
|
||||
using (new UndoBlock(Presenter.Undo, obj, "Paste values"))
|
||||
JsonSerializer.Deserialize(obj, text);
|
||||
}
|
||||
else
|
||||
{
|
||||
JsonSerializer.Deserialize(obj, text);
|
||||
}
|
||||
}
|
||||
#pragma warning disable 618
|
||||
else if (Newtonsoft.Json.Schema.JsonSchema.Parse(text) == null)
|
||||
#pragma warning restore 618
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (new ScriptType(typeof(FlaxEngine.Object)).IsAssignableFrom(Values.Type))
|
||||
{
|
||||
// Object reference
|
||||
if (text.Length != 32)
|
||||
return false;
|
||||
JsonSerializer.ParseID(text, out var id);
|
||||
@@ -555,6 +610,7 @@ namespace FlaxEditor.CustomEditors
|
||||
}
|
||||
else
|
||||
{
|
||||
// Default
|
||||
obj = JsonConvert.DeserializeObject(text, TypeUtils.GetType(Values.Type), JsonSerializer.Settings);
|
||||
}
|
||||
|
||||
@@ -576,7 +632,7 @@ namespace FlaxEditor.CustomEditors
|
||||
{
|
||||
try
|
||||
{
|
||||
return GetClipboardObject(out _);
|
||||
return GetClipboardObject(out _, false);
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -594,7 +650,7 @@ namespace FlaxEditor.CustomEditors
|
||||
|
||||
try
|
||||
{
|
||||
if (GetClipboardObject(out var obj))
|
||||
if (GetClipboardObject(out var obj, true))
|
||||
{
|
||||
SetValue(obj);
|
||||
}
|
||||
@@ -624,7 +680,7 @@ namespace FlaxEditor.CustomEditors
|
||||
return FindPrefabRoot(actor.Parent);
|
||||
}
|
||||
|
||||
private ISceneObject FindObjectWithPrefabObjectId(Actor actor, ref Guid prefabObjectId)
|
||||
private SceneObject FindObjectWithPrefabObjectId(Actor actor, ref Guid prefabObjectId)
|
||||
{
|
||||
if (actor.PrefabObjectID == prefabObjectId)
|
||||
return actor;
|
||||
@@ -667,7 +723,7 @@ namespace FlaxEditor.CustomEditors
|
||||
{
|
||||
// Special case for object references
|
||||
// If prefab object has reference to other object in prefab needs to revert to matching prefab instance object not the reference prefab object value
|
||||
if (Values.ReferenceValue is ISceneObject referenceSceneObject && referenceSceneObject.HasPrefabLink)
|
||||
if (Values.ReferenceValue is SceneObject referenceSceneObject && referenceSceneObject.HasPrefabLink)
|
||||
{
|
||||
if (Values.Count > 1)
|
||||
{
|
||||
|
||||
@@ -250,6 +250,7 @@ namespace FlaxEditor.CustomEditors
|
||||
|
||||
Selection.Clear();
|
||||
Selection.Add(obj);
|
||||
Selection.SetType(new ScriptType(obj.GetType()));
|
||||
|
||||
OnSelectionChanged();
|
||||
}
|
||||
@@ -271,6 +272,7 @@ namespace FlaxEditor.CustomEditors
|
||||
|
||||
Selection.Clear();
|
||||
Selection.AddRange(objectsArray);
|
||||
Selection.SetType(new ScriptType(objectsArray.GetType()));
|
||||
|
||||
OnSelectionChanged();
|
||||
}
|
||||
@@ -284,6 +286,7 @@ namespace FlaxEditor.CustomEditors
|
||||
return;
|
||||
|
||||
Selection.Clear();
|
||||
Selection.SetType(ScriptType.Null);
|
||||
|
||||
OnSelectionChanged();
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ MonoReflectionType* CustomEditorsUtil::GetCustomEditor(MonoReflectionType* refTy
|
||||
|
||||
bool CustomEditorsUtilService::Init()
|
||||
{
|
||||
TRACK_ASSEMBLY(GetBinaryModuleFlaxEngine()->Assembly);
|
||||
TRACK_ASSEMBLY(((NativeBinaryModule*)GetBinaryModuleFlaxEngine())->Assembly);
|
||||
Scripting::BinaryModuleLoaded.Bind(&OnBinaryModuleLoaded);
|
||||
|
||||
return false;
|
||||
@@ -84,7 +84,7 @@ void OnAssemblyLoaded(MAssembly* assembly)
|
||||
const auto startTime = DateTime::NowUTC();
|
||||
|
||||
// Prepare FlaxEngine
|
||||
auto engineAssembly = GetBinaryModuleFlaxEngine()->Assembly;
|
||||
auto engineAssembly = ((NativeBinaryModule*)GetBinaryModuleFlaxEngine())->Assembly;
|
||||
if (!engineAssembly->IsLoaded())
|
||||
{
|
||||
LOG(Warning, "Cannot load custom editors meta for assembly {0} because FlaxEngine is not loaded.", assembly->ToString());
|
||||
@@ -173,7 +173,7 @@ void OnAssemblyLoaded(MAssembly* assembly)
|
||||
void OnAssemblyUnloading(MAssembly* assembly)
|
||||
{
|
||||
// Fast clear for editor unloading
|
||||
if (assembly == GetBinaryModuleFlaxEngine()->Assembly)
|
||||
if (assembly == ((NativeBinaryModule*)GetBinaryModuleFlaxEngine())->Assembly)
|
||||
{
|
||||
Cache.Clear();
|
||||
return;
|
||||
|
||||
@@ -71,7 +71,7 @@ namespace FlaxEditor.CustomEditors
|
||||
// Space before word starting with uppercase letter
|
||||
if (char.IsUpper(c) && i > 0)
|
||||
{
|
||||
if (i + 2 < length && !char.IsUpper(name[i + 1]) && !char.IsUpper(name[i + 2]))
|
||||
if (i + 1 < length && !char.IsUpper(name[i + 1]))
|
||||
sb.Append(' ');
|
||||
}
|
||||
// Space instead of underscore
|
||||
|
||||
@@ -24,43 +24,6 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
||||
{
|
||||
private Guid _linkedPrefabId;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void SpawnProperty(LayoutElementsContainer itemLayout, ValueContainer itemValues, ItemInfo item)
|
||||
{
|
||||
// Note: we cannot specify actor properties editor types directly because we want to keep editor classes in FlaxEditor assembly
|
||||
int order = item.Order?.Order ?? int.MinValue;
|
||||
switch (order)
|
||||
{
|
||||
// Override static flags editor
|
||||
case -80:
|
||||
item.CustomEditor = new CustomEditorAttribute(typeof(ActorStaticFlagsEditor));
|
||||
break;
|
||||
|
||||
// Override layer editor
|
||||
case -69:
|
||||
item.CustomEditor = new CustomEditorAttribute(typeof(ActorLayerEditor));
|
||||
break;
|
||||
|
||||
// Override tag editor
|
||||
case -68:
|
||||
item.CustomEditor = new CustomEditorAttribute(typeof(ActorTagEditor));
|
||||
break;
|
||||
|
||||
// Override position/scale editor
|
||||
case -30:
|
||||
case -10:
|
||||
item.CustomEditor = new CustomEditorAttribute(typeof(ActorTransformEditor.PositionScaleEditor));
|
||||
break;
|
||||
|
||||
// Override orientation editor
|
||||
case -20:
|
||||
item.CustomEditor = new CustomEditorAttribute(typeof(ActorTransformEditor.OrientationEditor));
|
||||
break;
|
||||
}
|
||||
|
||||
base.SpawnProperty(itemLayout, itemValues, item);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override List<ItemInfo> GetItemsForType(ScriptType type)
|
||||
{
|
||||
@@ -70,8 +33,10 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
||||
var scriptsMember = type.GetProperty("Scripts");
|
||||
if (scriptsMember != ScriptMemberInfo.Null)
|
||||
{
|
||||
var item = new ItemInfo(scriptsMember);
|
||||
item.CustomEditor = new CustomEditorAttribute(typeof(ScriptsEditor));
|
||||
var item = new ItemInfo(scriptsMember)
|
||||
{
|
||||
CustomEditor = new CustomEditorAttribute(typeof(ScriptsEditor))
|
||||
};
|
||||
items.Add(item);
|
||||
}
|
||||
|
||||
@@ -232,9 +197,10 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
||||
|
||||
private TreeNode CreateDiffNode(CustomEditor editor)
|
||||
{
|
||||
var node = new TreeNode(false);
|
||||
|
||||
node.Tag = editor;
|
||||
var node = new TreeNode(false)
|
||||
{
|
||||
Tag = editor
|
||||
};
|
||||
|
||||
// Removed Script
|
||||
if (editor is RemovedScriptDummy removed)
|
||||
@@ -243,7 +209,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
||||
node.Text = CustomEditorsUtil.GetPropertyNameUI(removed.PrefabObject.GetType().Name);
|
||||
}
|
||||
// Actor or Script
|
||||
else if (editor.Values[0] is ISceneObject sceneObject)
|
||||
else if (editor.Values[0] is SceneObject sceneObject)
|
||||
{
|
||||
node.TextColor = sceneObject.HasPrefabLink ? FlaxEngine.GUI.Style.Current.ProgressNormal : FlaxEngine.GUI.Style.Current.BackgroundSelected;
|
||||
node.Text = CustomEditorsUtil.GetPropertyNameUI(sceneObject.GetType().Name);
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||
|
||||
using FlaxEditor.Content.Settings;
|
||||
using FlaxEngine;
|
||||
using FlaxEngine.GUI;
|
||||
|
||||
namespace FlaxEditor.CustomEditors.Dedicated
|
||||
{
|
||||
/// <summary>
|
||||
/// Custom editor for <see cref="LayersMask"/>.
|
||||
/// </summary>
|
||||
[CustomEditor(typeof(LayersMask)), DefaultEditor]
|
||||
internal class LayersMaskEditor : CustomEditor
|
||||
{
|
||||
private CheckBox[] _checkBoxes;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Initialize(LayoutElementsContainer layout)
|
||||
{
|
||||
var layers = LayersAndTagsSettings.GetCurrentLayers();
|
||||
if (layers == null || layers.Length == 0)
|
||||
{
|
||||
layout.Label("Missing layers and tags settings");
|
||||
return;
|
||||
}
|
||||
|
||||
_checkBoxes = new CheckBox[layers.Length];
|
||||
for (int i = 0; i < layers.Length; i++)
|
||||
{
|
||||
var layer = layers[i];
|
||||
var property = layout.AddPropertyItem(layer);
|
||||
var checkbox = property.Checkbox().CheckBox;
|
||||
UpdateCheckbox(checkbox, i);
|
||||
checkbox.Tag = i;
|
||||
checkbox.StateChanged += OnCheckboxStateChanged;
|
||||
_checkBoxes[i] = checkbox;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Deinitialize()
|
||||
{
|
||||
_checkBoxes = null;
|
||||
|
||||
base.Deinitialize();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Refresh()
|
||||
{
|
||||
if (_checkBoxes != null)
|
||||
{
|
||||
for (int i = 0; i < _checkBoxes.Length; i++)
|
||||
{
|
||||
UpdateCheckbox(_checkBoxes[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
base.Refresh();
|
||||
}
|
||||
|
||||
private void OnCheckboxStateChanged(CheckBox checkBox)
|
||||
{
|
||||
var i = (int)checkBox.Tag;
|
||||
var value = (LayersMask)Values[0];
|
||||
var mask = 1u << i;
|
||||
value.Mask &= ~mask;
|
||||
value.Mask |= checkBox.Checked ? mask : 0;
|
||||
SetValue(value);
|
||||
}
|
||||
|
||||
private void UpdateCheckbox(CheckBox checkbox, int i)
|
||||
{
|
||||
for (var j = 0; j < Values.Count; j++)
|
||||
{
|
||||
var value = (((LayersMask)Values[j]).Mask & (1 << i)) != 0;
|
||||
if (j == 0)
|
||||
{
|
||||
checkbox.Checked = value;
|
||||
}
|
||||
else if (checkbox.State != CheckBoxState.Intermediate)
|
||||
{
|
||||
if (checkbox.Checked != value)
|
||||
checkbox.State = CheckBoxState.Intermediate;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user