├── assets ├── models │ ├── suzanne.obj │ ├── Crate │ │ ├── Crate1.3ds │ │ ├── Crate1.mtl │ │ ├── Crate1.obj │ │ ├── crate_1.jpg │ │ ├── Crate1.blend │ │ ├── CrateImage1.JPG │ │ └── CrateImage2.JPG │ ├── floor │ │ ├── floor.mtl │ │ ├── floor.obj │ │ └── floor.blend │ ├── sphere │ │ ├── sphere.mtl │ │ ├── sphere.obj │ │ └── untitled.blend │ ├── sponza │ │ ├── README.md │ │ └── glTF │ │ │ ├── Sponza.bin │ │ │ └── Sponza.gltf │ └── viking_room.obj ├── textures │ ├── 154s.png │ ├── 165s.png │ ├── 191s.png │ ├── 196.png │ ├── 196_s.png │ ├── white.png │ ├── 196_norm.png │ ├── viking_room.png │ ├── 10381718147657362067.jpg │ ├── 10388182081421875623.jpg │ ├── 11490520546946913238.jpg │ ├── 11872827283454512094.jpg │ ├── 11968150294050148237.jpg │ ├── 1219024358953944284.jpg │ ├── 12501374198249454378.jpg │ ├── 13196865903111448057.jpg │ ├── 13824894030729245199.jpg │ ├── 13982482287905699490.jpg │ ├── 14170708867020035030.jpg │ ├── 14267839433702832875.jpg │ ├── 14650633544276105767.jpg │ ├── 15295713303328085182.jpg │ ├── 15722799267630235092.jpg │ ├── 16299174074766089871.jpg │ ├── 16885566240357350108.jpg │ ├── 17556969131407844942.jpg │ ├── 2051777328469649772.jpg │ ├── 2185409758123873465.jpg │ ├── 2299742237651021498.jpg │ ├── 2374361008830720677.jpg │ ├── 2411100444841994089.jpg │ ├── 2775690330959970771.jpg │ ├── 2969916736137545357.jpg │ ├── 332936164838540657.jpg │ ├── 3371964815757888145.jpg │ ├── 3455394979645218238.jpg │ ├── 3628158980083700836.jpg │ ├── 3827035219084910048.jpg │ ├── 4477655471536070370.jpg │ ├── 4601176305987539675.jpg │ ├── 466164707995436622.jpg │ ├── 4675343432951571524.jpg │ ├── 4871783166746854860.jpg │ ├── 4910669866631290573.jpg │ ├── 4975155472559461469.jpg │ ├── 5061699253647017043.png │ ├── 5792855332885324923.jpg │ ├── 5823059166183034438.jpg │ ├── 6047387724914829168.jpg │ ├── 6151467286084645207.jpg │ ├── 6593109234861095314.jpg │ ├── 6667038893015345571.jpg │ ├── 6772804448157695701.jpg │ ├── 7056944414013900257.jpg │ ├── 715093869573992647.jpg │ ├── 7268504077753552595.jpg │ ├── 7441062115984513793.jpg │ ├── 755318871556304029.jpg │ ├── 759203620573749278.jpg │ ├── 7645212358685992005.jpg │ ├── 7815564343179553343.jpg │ ├── 8006627369776289000.png │ ├── 8051790464816141987.jpg │ ├── 8114461559286000061.jpg │ ├── 8481240838833932244.jpg │ ├── 8503262930880235456.jpg │ ├── 8747919177698443163.jpg │ ├── 8750083169368950601.jpg │ ├── 8773302468495022225.jpg │ ├── 8783994986360286082.jpg │ ├── 9288698199695299068.jpg │ ├── 9916269861720640319.jpg │ ├── metal_hammered_norm.jpg │ ├── metal_hammered_rough.jpg │ ├── skybox │ │ ├── default_back.jpg │ │ ├── default_front.jpg │ │ ├── default_left.jpg │ │ ├── default_right.jpg │ │ ├── default_top.jpg │ │ └── default_bottom.jpg │ ├── 11474523244911310074.jpg │ ├── 14118779221266351425.jpg │ ├── 16275776544635328252.png │ ├── 17876391417123941155.jpg │ └── metal_hammered_diffuse.jpg ├── fonts │ └── Roboto-Medium.ttf └── shaders │ └── default │ ├── mrt.frag │ ├── mrt.vert │ ├── ui.frag │ ├── ui.vert │ ├── deferred.frag │ ├── deferred.vert │ ├── mrt.frag.spv │ ├── mrt.vert.spv │ ├── shadow.vert │ ├── skybox.frag │ ├── skybox.frag.spv │ ├── skybox.vert │ ├── ui.frag.spv │ ├── ui.vert.spv │ ├── deferred.frag.spv │ ├── deferred.vert.spv │ ├── shadow.vert.spv │ └── skybox.vert.spv ├── src ├── time │ ├── utils.hpp │ ├── utils.cpp │ ├── scoped_timer.cpp │ ├── scoped_timer.hpp │ ├── timer.hpp │ └── timer.cpp ├── utils │ ├── assert.hpp │ ├── assert.cpp │ ├── file_manager.hpp │ └── file_manager.cpp ├── app │ ├── main.cpp │ ├── input │ │ ├── input_listener.hpp │ │ ├── input_manager.hpp │ │ ├── event.hpp │ │ └── input_manager.cpp │ ├── shady.hpp │ ├── window.hpp │ ├── gui │ │ └── gui.hpp │ ├── window.cpp │ └── shady.cpp ├── render │ ├── command.hpp │ ├── types.hpp │ ├── shader.hpp │ ├── command.cpp │ ├── common.cpp │ ├── buffer.hpp │ ├── shader.cpp │ ├── vertex.hpp │ ├── texture.hpp │ ├── deferred_pipeline.hpp │ ├── renderer.hpp │ ├── common.hpp │ ├── framebuffer.hpp │ ├── buffer.cpp │ └── framebuffer.cpp ├── scene │ ├── orthographic_camera.cpp │ ├── orthographic_camera.hpp │ ├── scene.hpp │ ├── perspective_camera.hpp │ ├── mesh.hpp │ ├── model.hpp │ ├── light.hpp │ ├── mesh.cpp │ ├── scene.cpp │ ├── skybox.hpp │ ├── camera.hpp │ ├── perspective_camera.cpp │ ├── camera.cpp │ ├── light.cpp │ ├── model.cpp │ └── skybox.cpp └── trace │ ├── logger.cpp │ ├── logger.impl.hpp │ ├── logger.hpp │ └── formatter_types.hpp ├── conanfile.txt ├── cmake ├── compile_shaders.cmake ├── util_functions.cmake └── compile_warnings.cmake ├── .clang-tidy ├── LICENSE ├── .github └── workflows │ ├── code_quality.yml │ ├── windows.yml │ └── ubuntu.yml ├── README.md ├── .clang-format ├── CMakeLists.txt └── .gitignore /assets/models/suzanne.obj: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:e4ebe818a8edda1e8547c9655f312e7aee287e97dcf9dd474e941786fbe684fc 3 | size 81334 4 | -------------------------------------------------------------------------------- /assets/textures/154s.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:99d2db68ac53c158e28d84d1f52758cf50bcf57b63b480e4d90ce5a6eec24308 3 | size 882371 4 | -------------------------------------------------------------------------------- /assets/textures/165s.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:3adbb3859f25797c52395836a60d5e07805b33558056cfea0c1fb86eda666feb 3 | size 683624 4 | -------------------------------------------------------------------------------- /assets/textures/191s.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:765de76f8c921aec0aa3d4b7b6ab558354199ec0313bb2bf83c8f77e990332e6 3 | size 1062911 4 | -------------------------------------------------------------------------------- /assets/textures/196.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a66e08ef87608f5ebacd608609eb29a0de1fc8a779b240939d0f91a9277e6523 3 | size 1892415 4 | -------------------------------------------------------------------------------- /assets/textures/196_s.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:61412ea2dc79904d5d43616392cfa8fea190bbc174f2625e5fad9f454f62109b 3 | size 910616 4 | -------------------------------------------------------------------------------- /assets/textures/white.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a7f6ba46f50b075f96194a24b39aa10b8896a0fd0358d127d947204e4eb22f40 3 | size 5478 4 | -------------------------------------------------------------------------------- /assets/fonts/Roboto-Medium.ttf: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:8559132c89ad51d8a2ba5b171887a44a7ba93776e205f553573de228e64b45f8 3 | size 162588 4 | -------------------------------------------------------------------------------- /assets/models/Crate/Crate1.3ds: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:347f328b0364d233f4ea87c4554da1e9a3228ff975342eebe6980866f4e5bfb5 3 | size 800 4 | -------------------------------------------------------------------------------- /assets/models/Crate/Crate1.mtl: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:173e0367723b5dd0c5ef1dd500812444098c635ff28a36319fa4a39b5d8b8fa7 3 | size 227 4 | -------------------------------------------------------------------------------- /assets/models/Crate/Crate1.obj: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:17b38c88b7433cef957a8cfaf4bd4e112120a938a33fa466ce731ce5a72d62fb 3 | size 563 4 | -------------------------------------------------------------------------------- /assets/models/Crate/crate_1.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:73b038c304eefda02ee4a7159326b02111a4112c3bf0b6a9f2385dab79d91734 3 | size 29819 4 | -------------------------------------------------------------------------------- /assets/models/floor/floor.mtl: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:e807e3dfc3c5cbff841d9061e9b0905e183b1e6642979b7b6b82babdaccdc836 3 | size 131 4 | -------------------------------------------------------------------------------- /assets/models/floor/floor.obj: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:046897e7c37aebd6f96d87cc611049dfe79c21d21fe3f19118bfa5cb55b166df 3 | size 8062 4 | -------------------------------------------------------------------------------- /assets/models/sphere/sphere.mtl: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:68bf9fa354f039fbaa7593067de878ac0e6fdd63d6bb77166b96d27152bf2c81 3 | size 134 4 | -------------------------------------------------------------------------------- /assets/models/sphere/sphere.obj: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:dba0d83bcaa6d979dd215a60bb244826ff9cd76cc2a7958bf7b20a9eb87f5e4f 3 | size 63152 4 | -------------------------------------------------------------------------------- /assets/models/sponza/README.md: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:4fd2da96d2dda40fb2e7520c0362e36b7e26d2a1afd1d9387623611c66f448f7 3 | size 2814 4 | -------------------------------------------------------------------------------- /assets/models/viking_room.obj: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:0af27cd99ce43f48c89d9c73cff47cbdfc3d29c3754b29bd0ccfe7e3fe7de869 3 | size 479536 4 | -------------------------------------------------------------------------------- /assets/shaders/default/mrt.frag: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a2a39627a46774229f4f5d7b2d5f1b4364bab3c5276a0535467cb7aa42f50751 3 | size 1155 4 | -------------------------------------------------------------------------------- /assets/shaders/default/mrt.vert: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:463884bcdc868265fea8c7aeb764e82b0dfff1383dea5298bf0c0c3e470eeb06 3 | size 1472 4 | -------------------------------------------------------------------------------- /assets/shaders/default/ui.frag: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:8aafaae01012f85103545a2158ba0dfef9319e5f600f207d67b6a09272527dac 3 | size 264 4 | -------------------------------------------------------------------------------- /assets/shaders/default/ui.vert: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:9ba2c8dc0f6640178b6859e47ea046062deabe6ef60f7ea2f4d862fe9fea099d 3 | size 507 4 | -------------------------------------------------------------------------------- /assets/textures/196_norm.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ef08d4bcc19f65ec9aa8f11b5d9c71fba332b7a50bc8882cb1a2d7433e8bacef 3 | size 1899409 4 | -------------------------------------------------------------------------------- /assets/models/Crate/Crate1.blend: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a0d91ce30743a9ede4eb06c8afe01b84183fa10fec802b8fa51bacb9ab2d24ba 3 | size 483892 4 | -------------------------------------------------------------------------------- /assets/models/Crate/CrateImage1.JPG: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:30bcae3cc055a956c4886655f3108f1bac3b537b7c40bd8ef0935a1afc44db61 3 | size 25129 4 | -------------------------------------------------------------------------------- /assets/models/Crate/CrateImage2.JPG: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:1f915e2409b64c1233cbb562e9ebc6a0bf34814d708b18182567d7ff69e69ade 3 | size 20837 4 | -------------------------------------------------------------------------------- /assets/models/floor/floor.blend: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:7a64d610886f0864a3e96353dab4e29cac3bdfbd784f1609f8f99cc7799b3f97 3 | size 861356 4 | -------------------------------------------------------------------------------- /assets/models/sphere/untitled.blend: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:3f94337f916f0126c514ae5bbcd05d2f971bb9aff42393fec54029f544b6ed77 3 | size 818820 4 | -------------------------------------------------------------------------------- /assets/shaders/default/deferred.frag: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f803daf68bffe22da471d0e9a3d714ed8e60547a6e85a308736b21657fa8af2c 3 | size 4045 4 | -------------------------------------------------------------------------------- /assets/shaders/default/deferred.vert: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:feff00e837cc2b0d98ba59a038d3231ce3259ae9d1e0e86875b7fa7a0997ed73 3 | size 198 4 | -------------------------------------------------------------------------------- /assets/shaders/default/mrt.frag.spv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:9eff695f323aec5610b6a17eca3270ce6b8eceb9f1fda45ff11ca83a62ca0c8e 3 | size 3292 4 | -------------------------------------------------------------------------------- /assets/shaders/default/mrt.vert.spv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:5f4b69653c5fb8406d266f6d2c67e7507dea29952d4253e2b76b274b4d03a3e2 3 | size 4140 4 | -------------------------------------------------------------------------------- /assets/shaders/default/shadow.vert: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:24a2f97ac67fc7adcac39f9be8030ae38f7fffb3d7f14d8b7a35feb8eef2b08b 3 | size 499 4 | -------------------------------------------------------------------------------- /assets/shaders/default/skybox.frag: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:e2a0537dedf0e4e578b80f6889abdfee8e0bb3eaa259fd9d9bc73b4660497a31 3 | size 360 4 | -------------------------------------------------------------------------------- /assets/shaders/default/skybox.frag.spv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:78cbc78ce01ffda47a4eb365c530d4ab5a088330e8fab4465cc073734944b7b4 3 | size 748 4 | -------------------------------------------------------------------------------- /assets/shaders/default/skybox.vert: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:9b775e237fec0324a38d978faafc654e335ac6e6c99648e094985c4f711b2e9c 3 | size 266 4 | -------------------------------------------------------------------------------- /assets/shaders/default/ui.frag.spv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:eb026c4dcad029d958b15b539f2b196ec15a220f1149bcdea3782944f02791a4 3 | size 736 4 | -------------------------------------------------------------------------------- /assets/shaders/default/ui.vert.spv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f8cc855fd001e2503dd02f8b74a055aa06fd172cc060c7bf0c6111d3bc92fddd 3 | size 1324 4 | -------------------------------------------------------------------------------- /assets/textures/viking_room.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:facb693858cafcb70b7eed264e34107f06bbf3f41805e7b8084e5b42bd914a66 3 | size 962052 4 | -------------------------------------------------------------------------------- /assets/models/sponza/glTF/Sponza.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:10024b38b5df7f3c6fcdd8e7928649c96627649cfed6aebab081875270acb44c 3 | size 9529440 4 | -------------------------------------------------------------------------------- /assets/models/sponza/glTF/Sponza.gltf: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:e17c14edbc06b757dafcfed99f8815af9c5f5d9f9de3f0bc7740c37e68e0d829 3 | size 212504 4 | -------------------------------------------------------------------------------- /assets/shaders/default/deferred.frag.spv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:b84ed3e6861ed50c53315400881a7d3a7bb4bc1d3a0478171e6acda57499a320 3 | size 9984 4 | -------------------------------------------------------------------------------- /assets/shaders/default/deferred.vert.spv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a4d5580f2bf7da7c686cc22198d34166cad64c42b661f288aeab78160b80ab08 3 | size 1232 4 | -------------------------------------------------------------------------------- /assets/shaders/default/shadow.vert.spv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:40ba12367fff412198ef1be98f7106c32fdb37d1a132289a10c3b59850942007 3 | size 2204 4 | -------------------------------------------------------------------------------- /assets/shaders/default/skybox.vert.spv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:33131ae7e63586c119ee0e3dabb473b844d989098a9d2c970e7dc0ceaf568841 3 | size 1276 4 | -------------------------------------------------------------------------------- /assets/textures/10381718147657362067.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:728dd0fe3b570103e51dbfcc1eac64ad09916a7a31603c62a4090a2f2afaa6f8 3 | size 876227 4 | -------------------------------------------------------------------------------- /assets/textures/10388182081421875623.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:e309f1e6310dc0bb85df0a5f3b139207876f067378796a7aa666b0bb169587ae 3 | size 919134 4 | -------------------------------------------------------------------------------- /assets/textures/11490520546946913238.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:98e4c4a091fea684cd693f3ae7ebe83e491969b501b4cd6e1fdd6a3cc1fa5cab 3 | size 321375 4 | -------------------------------------------------------------------------------- /assets/textures/11872827283454512094.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:da2a0b308b4d6d57ffbcf4bb7509d4afe91156d5d86d0396e83d7cac883a4857 3 | size 668962 4 | -------------------------------------------------------------------------------- /assets/textures/11968150294050148237.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:bee42826d56d3ff719c4908c11ef65584fbe19e08273862fde7ec1408e44ba25 3 | size 530384 4 | -------------------------------------------------------------------------------- /assets/textures/1219024358953944284.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:9cbd61fcb8047f1c21450eff05207b29d71824edd75483267b5fbc2f7b21378c 3 | size 329124 4 | -------------------------------------------------------------------------------- /assets/textures/12501374198249454378.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:81ede4ce51045540817c1efb83dbb65a9a9701f1abd78fa130def51d227162fc 3 | size 421442 4 | -------------------------------------------------------------------------------- /assets/textures/13196865903111448057.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:8c26ae9523cfae7a062fd074f74e0ddbb61630772f9a2130489e1d6e4724c38b 3 | size 281980 4 | -------------------------------------------------------------------------------- /assets/textures/13824894030729245199.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:9158388312a76ba25a40d3b57978e1ace224882e53198a766494d98f9118aeba 3 | size 313460 4 | -------------------------------------------------------------------------------- /assets/textures/13982482287905699490.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:70d85bff3bc017177124942ae187db117ba2588e490746f440f2cef085852956 3 | size 357112 4 | -------------------------------------------------------------------------------- /assets/textures/14170708867020035030.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:763740af8d22f0bfc6a43bd46050ef24bb661833bcace92f1f3326b9d5d7dc16 3 | size 137384 4 | -------------------------------------------------------------------------------- /assets/textures/14267839433702832875.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:3a2c2aeb87a490a9bd37a8aa912a00e5f5c13974879fcb4f4f0ef39b17c52a7a 3 | size 718904 4 | -------------------------------------------------------------------------------- /assets/textures/14650633544276105767.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:e8b68080eb4c5709536dfb7858d595d51d4bb725003e11b0f383acf76a7e05a3 3 | size 521947 4 | -------------------------------------------------------------------------------- /assets/textures/15295713303328085182.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:5bbd0cbf2da7416d5620514ebb0c4837b0ccc841b649cf4070281aa333ff8520 3 | size 520162 4 | -------------------------------------------------------------------------------- /assets/textures/15722799267630235092.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d54c520da7e60e2a62630e9cf946faf139648a7ab831c4531272238e4ade8fa8 3 | size 557865 4 | -------------------------------------------------------------------------------- /assets/textures/16299174074766089871.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:0821ec8dc8226fd5ac70f068e134d014a9952276a7100cc7f0660853471b39f6 3 | size 339486 4 | -------------------------------------------------------------------------------- /assets/textures/16885566240357350108.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:5562f0e76ca213d72295e48b8a14a59ee1971f58a47f95e5c022a4e78371c5aa 3 | size 12575 4 | -------------------------------------------------------------------------------- /assets/textures/17556969131407844942.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:cb09708202859d08764601acc9c9ea3b5254b2c4fd39dcc6b6055768c77aee9b 3 | size 370061 4 | -------------------------------------------------------------------------------- /assets/textures/2051777328469649772.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:86defcb4c007b80b9d23bcc9fdccd994f6a68f710eb75f11396d92faa2fbe368 3 | size 206244 4 | -------------------------------------------------------------------------------- /assets/textures/2185409758123873465.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:88861c8c7f10517c1d7942f316aae3b74dc5b8ae2faa2021d9dfe9d2c09fb24f 3 | size 780166 4 | -------------------------------------------------------------------------------- /assets/textures/2299742237651021498.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:62a52f200082c02a0fbfa25c0bc40ea7d105a21f10d5aa0ec9408c4f45523794 3 | size 772201 4 | -------------------------------------------------------------------------------- /assets/textures/2374361008830720677.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:231d919288db7c977fda3091549195c1bd5197e9e63c039e972da8764f5435c1 3 | size 844768 4 | -------------------------------------------------------------------------------- /assets/textures/2411100444841994089.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:12e1f2ea3c2714a6ec455fa8e623a702e33ef95765ebd09f7874a68fa55fd104 3 | size 399963 4 | -------------------------------------------------------------------------------- /assets/textures/2775690330959970771.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:751606c94a5fe5bda3bf6709e7f6a74363bd7902bf2353d54e55ef3b50007487 3 | size 785678 4 | -------------------------------------------------------------------------------- /assets/textures/2969916736137545357.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:dfa17f2dee2cd2d850585673d19d5cda477a63e21659b346d8730e80edd3b347 3 | size 822373 4 | -------------------------------------------------------------------------------- /assets/textures/332936164838540657.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:231d919288db7c977fda3091549195c1bd5197e9e63c039e972da8764f5435c1 3 | size 844768 4 | -------------------------------------------------------------------------------- /assets/textures/3371964815757888145.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d939d2e8bf11c2cf375154129f861b982c786b83db79cb9fde1a2b94b46caf62 3 | size 682743 4 | -------------------------------------------------------------------------------- /assets/textures/3455394979645218238.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:967005ccfbf4d38f674df41aebb3e58ac1fdcd91f554ead7acfcc132372f8ec6 3 | size 551432 4 | -------------------------------------------------------------------------------- /assets/textures/3628158980083700836.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:9552937c9fa0481a07dc66768958b4be382544add46d1d66a687af54c51ab6da 3 | size 547553 4 | -------------------------------------------------------------------------------- /assets/textures/3827035219084910048.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:8af8fb0810bf3493242491da44f7ae14f7c0bfa6cbacea4be01f6f4261db4559 3 | size 618837 4 | -------------------------------------------------------------------------------- /assets/textures/4477655471536070370.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:b93291121303b5a24a488a3e29e0645a24bb471413cfd25c0917d306dff1d038 3 | size 208352 4 | -------------------------------------------------------------------------------- /assets/textures/4601176305987539675.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:3af8848a1a952ad8cc83199bbda0c095f9ed136be839659aa668f72afac91508 3 | size 1034060 4 | -------------------------------------------------------------------------------- /assets/textures/466164707995436622.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:21bb124f5b5d4d5e9c8d9773cd31dedfc41b30eb302af36e7257cf930152908e 3 | size 486634 4 | -------------------------------------------------------------------------------- /assets/textures/4675343432951571524.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:9d5fd79619a52db0232edb2287f5f05c0124c304355e3b035a4e48c0871090bf 3 | size 764529 4 | -------------------------------------------------------------------------------- /assets/textures/4871783166746854860.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:259b6659cb2681e06ef04becd49298d379f2f25b2cc468acf0c2ade4d190637c 3 | size 570081 4 | -------------------------------------------------------------------------------- /assets/textures/4910669866631290573.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:3af8848a1a952ad8cc83199bbda0c095f9ed136be839659aa668f72afac91508 3 | size 1034060 4 | -------------------------------------------------------------------------------- /assets/textures/4975155472559461469.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:fbdb7bcced57a005b84b4c3bbf744bae6309804cca51dabd9237e03a72fbc505 3 | size 399027 4 | -------------------------------------------------------------------------------- /assets/textures/5061699253647017043.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:6fbdbf67d3501831ad3a4e2adbf3d27e4c3d13ba1d655e5861c3f39b5f899f65 3 | size 2427921 4 | -------------------------------------------------------------------------------- /assets/textures/5792855332885324923.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:9330cf1d51c8f6924b6c9ce09f2dedb21a82e1c7406c37d49ce95beca40bb3be 3 | size 564801 4 | -------------------------------------------------------------------------------- /assets/textures/5823059166183034438.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:34b464edddbd2295b0ee23fa7a7a440a19456888c586acdc47032f841b302abd 3 | size 573157 4 | -------------------------------------------------------------------------------- /assets/textures/6047387724914829168.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:c39c9f304c2605be791b4c0a58cd0f8eb20de2dd6a4a4af893c4eb112d158353 3 | size 518310 4 | -------------------------------------------------------------------------------- /assets/textures/6151467286084645207.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:170f6c637ebd71a101244eb4d80c3dcf7063caf89e42053d3114d8aeca755cdf 3 | size 643517 4 | -------------------------------------------------------------------------------- /assets/textures/6593109234861095314.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:3af8848a1a952ad8cc83199bbda0c095f9ed136be839659aa668f72afac91508 3 | size 1034060 4 | -------------------------------------------------------------------------------- /assets/textures/6667038893015345571.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:58942b73c8f209ab9cc6ea174375adfde9c1875cbfe093f993086a0ab6570724 3 | size 698410 4 | -------------------------------------------------------------------------------- /assets/textures/6772804448157695701.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:1ea4f9bc86354d363ea8153df9b7593c3bd3da153c53b9624c1fd8a960cb3ebc 3 | size 599959 4 | -------------------------------------------------------------------------------- /assets/textures/7056944414013900257.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:231d919288db7c977fda3091549195c1bd5197e9e63c039e972da8764f5435c1 3 | size 844768 4 | -------------------------------------------------------------------------------- /assets/textures/715093869573992647.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d81efcb42b3a044595ca984cb46d941b159064bddae9a43ed8d9582db68d6b47 3 | size 280745 4 | -------------------------------------------------------------------------------- /assets/textures/7268504077753552595.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:430758549ba2189d94f06abeaae092bfc0a1d8c22afc56f5caf3f99c5ee7407c 3 | size 572245 4 | -------------------------------------------------------------------------------- /assets/textures/7441062115984513793.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:9edc7c1c73661658cd8ed7733728002d45fecd17cb37a962fb654ff1d8c1933d 3 | size 665796 4 | -------------------------------------------------------------------------------- /assets/textures/755318871556304029.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:9f849f0510ca0df66ba1cba2380a6a1b481444d9e64b68da6b2ce202b54d9cec 3 | size 302363 4 | -------------------------------------------------------------------------------- /assets/textures/759203620573749278.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f296e43c0d4c92953d4899ea0c38e8af992ba471acc87feb10f08e29a94aaef6 3 | size 512035 4 | -------------------------------------------------------------------------------- /assets/textures/7645212358685992005.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:46ffc9123ee3ad94b2595843b4446fd67dbf5a2f79dc1e3b4e637f5ea4578630 3 | size 652476 4 | -------------------------------------------------------------------------------- /assets/textures/7815564343179553343.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:8ad0e8a9ca6de602225a527361bc718881de8741bc48927e27259a8803e7fed7 3 | size 623144 4 | -------------------------------------------------------------------------------- /assets/textures/8006627369776289000.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:75328d1aac87f8539be2456e6a5392cef7c6d08476d75585eafcd334dbeee0c5 3 | size 1225157 4 | -------------------------------------------------------------------------------- /assets/textures/8051790464816141987.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:4f06c93f8e9f90be44a2e78847e57acec82bd793f58f7be7f86b088150730b88 3 | size 260119 4 | -------------------------------------------------------------------------------- /assets/textures/8114461559286000061.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:06c6480e207ce64f9e7c08df3f7f21638da7da43f77682657f4c823acd8c81a5 3 | size 193077 4 | -------------------------------------------------------------------------------- /assets/textures/8481240838833932244.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:1da7664b7b88ae58386a6e6b5eca2829537818061d704f002356d8fc483c1a28 3 | size 531156 4 | -------------------------------------------------------------------------------- /assets/textures/8503262930880235456.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:c288a37ed8373d1132644873624b096a72ba81d03cda601e050a5de24ba13c39 3 | size 104626 4 | -------------------------------------------------------------------------------- /assets/textures/8747919177698443163.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:8e90e94cadf80528a3df3496035d3c77900eba24d88b1c1d31c9dce77990fc44 3 | size 872255 4 | -------------------------------------------------------------------------------- /assets/textures/8750083169368950601.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:73a94a12fb0a9ab4c75e40996c9a2d49ac45ac18a8c8ae81d5ceb1c8ae52d6dc 3 | size 362437 4 | -------------------------------------------------------------------------------- /assets/textures/8773302468495022225.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:dc5bf5f3091b548f1dfe40410b1aa1e2e55d82e2d77ba57dbd1f92955a0d8ff8 3 | size 413837 4 | -------------------------------------------------------------------------------- /assets/textures/8783994986360286082.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:93d495e33d754c5723c910e322ac94108fc753b65af082a19be5252905aa741b 3 | size 388462 4 | -------------------------------------------------------------------------------- /assets/textures/9288698199695299068.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:7f55814430f289e89c7d675c3db925eee904fbc566ff83f4b49904de53138e98 3 | size 1044330 4 | -------------------------------------------------------------------------------- /assets/textures/9916269861720640319.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:81b21b9352f1fb9ccfeaf237f8547b985ddbf0cfd7ade7a4a8670b73a72b2cb5 3 | size 608687 4 | -------------------------------------------------------------------------------- /assets/textures/metal_hammered_norm.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f486dc74656960631d29b029bdd2e153f25759aaea27400ad0b02f6d5d372193 3 | size 116132 4 | -------------------------------------------------------------------------------- /assets/textures/metal_hammered_rough.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:91054b356a6885697768ecb18df4e6209c7397ed9fbbf2568eb399e4744e62cd 3 | size 79877 4 | -------------------------------------------------------------------------------- /assets/textures/skybox/default_back.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:da4938039f6a536c7db3fba35ffdd905861ce36608ceadf4412479c5fcacd138 3 | size 740068 4 | -------------------------------------------------------------------------------- /assets/textures/skybox/default_front.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:dd6f9d8bb04466c06387e8dc736eb453bcb92a09750be520b8d5e00e8bd484fe 3 | size 473329 4 | -------------------------------------------------------------------------------- /assets/textures/skybox/default_left.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:087df0cdc2d28b7e9f5f6b2d82795aa6b10684ce51d3104e8dd3c128b485a960 3 | size 601885 4 | -------------------------------------------------------------------------------- /assets/textures/skybox/default_right.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d4a1b6fd9daffdfb6c42d0dc169cffba7129a8d7da3fab52531e4df4a203191d 3 | size 538038 4 | -------------------------------------------------------------------------------- /assets/textures/skybox/default_top.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ff0aa54d15b7c69fc6fae738f943854950a67afd7b1a4e297809668b2380e055 3 | size 346139 4 | -------------------------------------------------------------------------------- /assets/textures/11474523244911310074.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:23c32277c33d8eac091cd73daf81561ebe3640eede49b037546ed5c244a01347 3 | size 1079152 4 | -------------------------------------------------------------------------------- /assets/textures/14118779221266351425.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:e5166a5fba339e44a9d197dedc168683971f8acb2156034248a80674cbba0dd5 3 | size 1607263 4 | -------------------------------------------------------------------------------- /assets/textures/16275776544635328252.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d6df943a0dcf535d9dfb009c2833e0c7dc21939cfe3a2c10316c552b3dc3441b 3 | size 1077432 4 | -------------------------------------------------------------------------------- /assets/textures/17876391417123941155.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:005b774a968c1f6af00e4bf97afd668a6a045126a94f524df722ba19edc77d61 3 | size 1151448 4 | -------------------------------------------------------------------------------- /assets/textures/metal_hammered_diffuse.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:df2bea7196666688caad79a2ee88066c66d342a49d644cdf59c78bbe5dede0b4 3 | size 80807 4 | -------------------------------------------------------------------------------- /assets/textures/skybox/default_bottom.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:088f074272f731abdc9da601cf925aeb80060d048ef33d2a60dd1b215d41feec 3 | size 280589 4 | -------------------------------------------------------------------------------- /src/time/utils.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace shady::time { 6 | 7 | std::string 8 | GetTime(); 9 | 10 | } // namespace shady::time 11 | -------------------------------------------------------------------------------- /src/utils/assert.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace shady::utils { 6 | 7 | void 8 | Assert(bool assertion, std::string_view logMsg); 9 | 10 | } // namespace shady::utils -------------------------------------------------------------------------------- /src/app/main.cpp: -------------------------------------------------------------------------------- 1 | #include "app/shady.hpp" 2 | 3 | int 4 | main(int /*argc*/, char** /*argv*/) 5 | { 6 | shady::app::Shady shady; 7 | 8 | shady.Init(); 9 | shady.MainLoop(); 10 | 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /src/utils/assert.cpp: -------------------------------------------------------------------------------- 1 | #include "assert.hpp" 2 | #include "trace/logger.hpp" 3 | 4 | namespace shady::utils { 5 | 6 | void 7 | Assert(bool assertion, std::string_view logMsg) 8 | { 9 | if (!assertion) 10 | { 11 | trace::Logger::Fatal("{}", logMsg); 12 | std::terminate(); 13 | } 14 | } 15 | } // namespace shady::utils -------------------------------------------------------------------------------- /src/time/utils.cpp: -------------------------------------------------------------------------------- 1 | #include "utils.hpp" 2 | 3 | #include 4 | 5 | namespace shady::time { 6 | 7 | std::string 8 | GetTime() 9 | { 10 | auto time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); 11 | return fmt::format("{:%H:%M:%S}", fmt::localtime(time)); 12 | } 13 | 14 | } // namespace shady::time 15 | -------------------------------------------------------------------------------- /conanfile.txt: -------------------------------------------------------------------------------- 1 | # Docs at https://docs.conan.io/en/latest/reference/conanfile_txt.html 2 | 3 | [requires] 4 | fmt/10.1.0 5 | glfw/3.3.8 6 | assimp/5.3.1 7 | imgui/1.89.9 8 | stb/cci.20230920 9 | glm/0.9.9.8 10 | 11 | [options] 12 | glfw/*:shared=False 13 | assimp/*:with_gltf=True 14 | assimp/*:shared=False 15 | 16 | [generators] 17 | CMakeToolchain 18 | CMakeDeps 19 | -------------------------------------------------------------------------------- /src/render/command.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace shady::render { 6 | 7 | class Command 8 | { 9 | public: 10 | static VkCommandBuffer 11 | BeginSingleTimeCommands(); 12 | 13 | static void 14 | EndSingleTimeCommands(VkCommandBuffer commandBuffer); 15 | }; 16 | 17 | } // namespace shady::render 18 | -------------------------------------------------------------------------------- /src/time/scoped_timer.cpp: -------------------------------------------------------------------------------- 1 | #include "scoped_timer.hpp" 2 | #include "trace/logger.hpp" 3 | 4 | namespace shady::time { 5 | 6 | ScopedTimer::ScopedTimer(std::string&& logMsg) : m_logMsg(std::move(logMsg)) 7 | { 8 | static_cast(m_timer.ToggleTimer()); 9 | } 10 | 11 | //NOLINTNEXTLINE 12 | ScopedTimer::~ScopedTimer() 13 | { 14 | trace::Logger::Debug("{} took {}", m_logMsg, m_timer.ToggleTimer().ToString()); 15 | } 16 | 17 | } // namespace shady::time -------------------------------------------------------------------------------- /src/scene/orthographic_camera.cpp: -------------------------------------------------------------------------------- 1 | #include "scene/orthographic_camera.hpp" 2 | 3 | #include 4 | 5 | namespace shady::scene { 6 | 7 | OrthographicCamera::OrthographicCamera(const glm::mat4& projection, const glm::vec3& position) 8 | : Camera(projection, position) 9 | { 10 | } 11 | 12 | OrthographicCamera::OrthographicCamera(float left, float right, float top, float bottom, 13 | const glm::vec3& position) 14 | //NOLINTNEXTLINE 15 | : Camera(glm::ortho(left, right, top, bottom, -1.0f, 10.0f), position) 16 | { 17 | } 18 | 19 | } // namespace shady::scene -------------------------------------------------------------------------------- /cmake/compile_shaders.cmake: -------------------------------------------------------------------------------- 1 | function(compile_shader) 2 | set(options "") 3 | set(oneValueArgs SOURCE_FILE OUTPUT_FILE_NAME) 4 | set(multiValueArgs DEFINES) 5 | cmake_parse_arguments(params "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) 6 | 7 | if (NOT params_SOURCE_FILE) 8 | message(FATAL_ERROR "compile_shader: SOURCE_FILE argument missing") 9 | endif() 10 | 11 | if (NOT params_OUTPUT_FILE_NAME) 12 | message(FATAL_ERROR "compile_shader: OUTPUT_FILE_NAME argument missing") 13 | endif() 14 | 15 | execute_process(COMMAND ${Vulkan_GLSLC_EXECUTABLE} "${params_SOURCE_FILE}" -o "${params_OUTPUT_FILE_NAME}") 16 | 17 | endfunction() 18 | -------------------------------------------------------------------------------- /src/time/scoped_timer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "timer.hpp" 4 | 5 | #include 6 | 7 | namespace shady::time { 8 | 9 | class ScopedTimer 10 | { 11 | public: 12 | ScopedTimer(const ScopedTimer&) = delete; 13 | ScopedTimer(ScopedTimer&&) = delete; 14 | ScopedTimer& operator=(const ScopedTimer&) = delete; 15 | ScopedTimer& operator=(ScopedTimer&&) = delete; 16 | 17 | explicit ScopedTimer(std::string&& logMsg); 18 | ~ScopedTimer(); 19 | 20 | private: 21 | std::string m_logMsg; 22 | Timer m_timer; 23 | }; 24 | 25 | //NOLINTNEXTLINE 26 | #define SCOPED_TIMER(str) shady::time::ScopedTimer t(std::move(str)); 27 | 28 | } // namespace shady::time 29 | -------------------------------------------------------------------------------- /src/scene/orthographic_camera.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "scene/camera.hpp" 4 | 5 | namespace shady::scene { 6 | 7 | class OrthographicCamera : public Camera 8 | { 9 | public: 10 | OrthographicCamera() = delete; 11 | OrthographicCamera(const OrthographicCamera&) = delete; 12 | OrthographicCamera(OrthographicCamera&&) = delete; 13 | OrthographicCamera& 14 | operator=(const OrthographicCamera&) = delete; 15 | OrthographicCamera& 16 | operator=(OrthographicCamera&&) = delete; 17 | 18 | 19 | OrthographicCamera(const glm::mat4& projection, const glm::vec3& position); 20 | OrthographicCamera(float left, float right, float top, float bottom, const glm::vec3& position); 21 | 22 | ~OrthographicCamera() override = default; 23 | }; 24 | 25 | } // namespace shady::scene 26 | -------------------------------------------------------------------------------- /src/scene/scene.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "scene/camera.hpp" 4 | #include "scene/light.hpp" 5 | #include "scene/model.hpp" 6 | #include "scene/skybox.hpp" 7 | 8 | #include 9 | #include 10 | 11 | namespace shady::scene { 12 | 13 | class Scene 14 | { 15 | public: 16 | scene::Camera& 17 | GetCamera(); 18 | 19 | void 20 | AddModel(const std::string& fileName, LoadFlags additionalFlags = LoadFlags::None); 21 | 22 | Light& 23 | GetLight(); 24 | 25 | void 26 | Render(int32_t windowWidth, int32_t windowHeight); 27 | 28 | void 29 | LoadDefault(); 30 | 31 | private: 32 | // Skybox m_skybox; 33 | std::unique_ptr< Camera > m_camera; 34 | std::vector< std::unique_ptr< Model > > m_models; 35 | std::unique_ptr< Light > m_light; 36 | }; 37 | 38 | } // namespace shady::scene 39 | -------------------------------------------------------------------------------- /src/time/timer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace shady::time { 7 | 8 | using timeStamp = std::chrono::time_point< std::chrono::steady_clock >; 9 | using milliseconds = std::chrono::milliseconds; 10 | using seconds = std::chrono::seconds; 11 | 12 | struct TimeStep 13 | { 14 | explicit TimeStep(milliseconds time); 15 | 16 | [[nodiscard]] std::string 17 | ToString() const; 18 | 19 | [[nodiscard]] seconds 20 | GetSeconds() const; 21 | 22 | [[nodiscard]] milliseconds 23 | GetMilliseconds() const; 24 | 25 | private: 26 | milliseconds time_; 27 | }; 28 | 29 | 30 | class Timer 31 | { 32 | public: 33 | Timer(); 34 | 35 | [[nodiscard]] TimeStep 36 | ToggleTimer(); 37 | 38 | private: 39 | timeStamp lastTimeStamp_; 40 | }; 41 | 42 | } // namespace shady::time -------------------------------------------------------------------------------- /src/render/types.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace shady::render { 8 | 9 | enum class TextureType 10 | { 11 | DIFFUSE_MAP = 0, 12 | SPECULAR_MAP = 1, 13 | NORMAL_MAP = 2, 14 | CUBE_MAP = 3 15 | }; 16 | 17 | struct UniformBufferObject 18 | { 19 | glm::mat4 proj = {}; 20 | glm::mat4 view = {}; 21 | glm::mat4 lightView = {}; 22 | }; 23 | 24 | struct DebugData 25 | { 26 | uint32_t displayDebugTarget = 0; 27 | int32_t pcfShadow = 1; 28 | float ambientLight = 0.1f; 29 | float shadowFactor = 0.1f; 30 | }; 31 | 32 | struct PerInstanceBuffer 33 | { 34 | glm::mat4 model = {}; 35 | glm::vec4 textures = {}; 36 | }; 37 | 38 | // DIFFUSE_MAP SPECULAR_MAP NORMAL_MAP 39 | using TextureMaps = std::array< std::string, 3 >; 40 | 41 | } // namespace shady::render 42 | -------------------------------------------------------------------------------- /src/trace/logger.cpp: -------------------------------------------------------------------------------- 1 | #include "logger.hpp" 2 | 3 | namespace shady::trace { 4 | 5 | void 6 | Logger::SetType(TYPE newType) 7 | { 8 | s_currentLogType = newType; 9 | } 10 | 11 | std::string 12 | Logger::ToString(TYPE type) 13 | { 14 | std::string returnValue; 15 | 16 | if (type == TYPE::TRACE) 17 | { 18 | returnValue = " [TRACE] "; 19 | } 20 | else if (type == TYPE::DEBUG) 21 | { 22 | returnValue = " [DEBUG] "; 23 | } 24 | else if (type == TYPE::INFO) 25 | { 26 | returnValue = " [INFO] "; 27 | } 28 | else if (type == TYPE::WARNING) 29 | { 30 | returnValue = " [WARNING] "; 31 | } 32 | else if (type == TYPE::FATAL) 33 | { 34 | returnValue = " [FATAL] "; 35 | } 36 | else 37 | { 38 | returnValue = " [UNKNOWN] "; 39 | } 40 | 41 | return returnValue; 42 | } 43 | 44 | } // namespace shady::trace -------------------------------------------------------------------------------- /src/app/input/input_listener.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "event.hpp" 4 | 5 | namespace shady::app::input { 6 | 7 | class InputListener 8 | { 9 | public: 10 | InputListener() = default; 11 | InputListener(const InputListener&) = default; 12 | InputListener(InputListener&&) = default; 13 | InputListener& operator=(const InputListener&) = default; 14 | InputListener& operator=(InputListener&&) = default; 15 | virtual ~InputListener() = default; 16 | 17 | virtual void 18 | KeyCallback(const KeyEvent& /*event*/) 19 | { 20 | } 21 | 22 | virtual void 23 | MouseButtonCallback(const MouseButtonEvent& /*event*/) 24 | { 25 | } 26 | 27 | virtual void 28 | CursorPositionCallback(const CursorPositionEvent& /*event*/) 29 | { 30 | } 31 | 32 | virtual void 33 | MouseScrollCallback(const MouseScrollEvent& /*event*/) 34 | { 35 | } 36 | }; 37 | 38 | } // namespace shady::app::input 39 | -------------------------------------------------------------------------------- /src/time/timer.cpp: -------------------------------------------------------------------------------- 1 | #include "timer.hpp" 2 | 3 | #include 4 | 5 | namespace shady::time { 6 | 7 | TimeStep::TimeStep(milliseconds time) : time_(time) 8 | { 9 | } 10 | 11 | std::string 12 | TimeStep::ToString() const 13 | { 14 | return fmt::format("{}ms", time_.count()); 15 | } 16 | 17 | seconds 18 | TimeStep::GetSeconds() const 19 | { 20 | return std::chrono::duration_cast< seconds >(time_); 21 | } 22 | 23 | milliseconds 24 | TimeStep::GetMilliseconds() const 25 | { 26 | return time_; 27 | } 28 | 29 | 30 | Timer::Timer() : lastTimeStamp_(std::chrono::steady_clock::now()) 31 | { 32 | } 33 | 34 | TimeStep 35 | Timer::ToggleTimer() 36 | { 37 | const auto timeNow = std::chrono::steady_clock::now(); 38 | const auto step = std::chrono::duration_cast< milliseconds >(timeNow - lastTimeStamp_); 39 | 40 | lastTimeStamp_ = timeNow; 41 | 42 | return TimeStep{step}; 43 | } 44 | 45 | } // namespace shady::time 46 | -------------------------------------------------------------------------------- /src/render/shader.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace shady::render { 8 | 9 | struct ShaderInfoWrapper 10 | { 11 | /* 12 | * This should be called after the pipeline is created 13 | */ 14 | void 15 | Destroy() const 16 | { 17 | vkDestroyShaderModule(device, shaderInfo.module, nullptr); 18 | } 19 | 20 | VkDevice device; 21 | VkPipelineShaderStageCreateInfo shaderInfo; 22 | }; 23 | 24 | using VertexShaderInfo = ShaderInfoWrapper; 25 | using GeometryShaderInfo = ShaderInfoWrapper; 26 | using FragmentShaderInfo = ShaderInfoWrapper; 27 | 28 | class Shader 29 | { 30 | public: 31 | static ShaderInfoWrapper 32 | LoadShader(std::string_view shader, VkShaderStageFlagBits stage); 33 | 34 | static std::pair< VertexShaderInfo, FragmentShaderInfo > 35 | CreateShader(VkDevice device, std::string_view vertex, std::string_view fragment); 36 | }; 37 | 38 | } // namespace shady::render::vulkan 39 | -------------------------------------------------------------------------------- /cmake/util_functions.cmake: -------------------------------------------------------------------------------- 1 | function(target_link_libraries_system target) 2 | set(options PRIVATE PUBLIC INTERFACE) 3 | cmake_parse_arguments(TLLS "${options}" "" "" ${ARGN}) 4 | foreach(op ${options}) 5 | if(TLLS_${op}) 6 | set(scope ${op}) 7 | endif() 8 | endforeach(op) 9 | set(libs ${TLLS_UNPARSED_ARGUMENTS}) 10 | 11 | foreach(lib ${libs}) 12 | get_target_property(lib_include_dirs ${lib} INTERFACE_INCLUDE_DIRECTORIES) 13 | if(lib_include_dirs) 14 | if(scope) 15 | target_include_directories(${target} SYSTEM ${scope} ${lib_include_dirs}) 16 | else() 17 | target_include_directories(${target} SYSTEM PRIVATE ${lib_include_dirs}) 18 | endif() 19 | else() 20 | message("Warning: ${lib} doesn't set INTERFACE_INCLUDE_DIRECTORIES. No include_directories set.") 21 | endif() 22 | if(scope) 23 | target_link_libraries(${target} ${scope} ${lib}) 24 | else() 25 | target_link_libraries(${target} ${lib}) 26 | endif() 27 | endforeach() 28 | endfunction(target_link_libraries_system) 29 | -------------------------------------------------------------------------------- /.clang-tidy: -------------------------------------------------------------------------------- 1 | --- 2 | Checks: '*,-fuchsia-*,-google-*,-zircon-*,-abseil-*,-modernize-use-trailing-return-type,-llvm*,\ 3 | -hicpp-uppercase-literal-suffix, -readability-uppercase-literal-suffix, -readability-implicit-bool-conversion,\ 4 | -cppcoreguidelines-avoid-magic-numbers, -readability-magic-numbers, -cppcoreguidelines-pro-type-union-access,\ 5 | -cppcoreguidelines-pro-bounds-pointer-arithmetic, -cppcoreguidelines-pro-type-reinterpret-cast,\ 6 | -cppcoreguidelines-pro-type-vararg, -altera-unroll-loops, -hicpp-vararg, -avoid-non-const-global-variables,\ 7 | -cppcoreguidelines-avoid-non-const-global-variables, -altera-id-dependent-backward-branch, -hicpp-signed-bitwise,\ 8 | -readability-identifier-length, -readability-redundant-access-specifiers, -bugprone-easily-swappable-parameters,\ 9 | -misc-non-private-member-variables-in-classes, -altera-struct-pack-align, -cppcoreguidelines-non-private-member-variables-in-classes,\ 10 | -misc-no-recursion, -cppcoreguidelines-pro-bounds-constant-array-index' 11 | WarningsAsErrors: '*' 12 | HeaderFilterRegex: '' 13 | FormatStyle: none -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2021 GitHub, Inc. and contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/scene/perspective_camera.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "scene/camera.hpp" 4 | 5 | namespace shady::scene { 6 | 7 | class PerspectiveCamera : public Camera 8 | { 9 | public: 10 | PerspectiveCamera() = delete; 11 | PerspectiveCamera(const PerspectiveCamera&) = delete; 12 | PerspectiveCamera(PerspectiveCamera&&) = delete; 13 | PerspectiveCamera& 14 | operator=(const PerspectiveCamera&) = delete; 15 | PerspectiveCamera& 16 | operator=(PerspectiveCamera&&) = delete; 17 | 18 | PerspectiveCamera(const glm::mat4& projection, const glm::vec3& position); 19 | PerspectiveCamera(float fieldOfView, float aspectRatio, float nearClip, float farClip, 20 | const glm::vec3& position); 21 | 22 | ~PerspectiveCamera() override = default; 23 | 24 | void 25 | MouseMovement(const glm::vec2& mouseMovement) override; 26 | 27 | void 28 | MoveCamera(const glm::vec2& leftRightVec) override; 29 | 30 | void 31 | RotateCamera(float angle, const glm::vec3& axis) override; 32 | 33 | private: 34 | float yaw_ = 0.0f; 35 | float pitch_ = 0.0f; 36 | bool constrainPitch_ = true; 37 | }; 38 | 39 | } // namespace shady::scene 40 | -------------------------------------------------------------------------------- /src/app/shady.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "app/window.hpp" 4 | #include "input/input_listener.hpp" 5 | #include "scene/scene.hpp" 6 | 7 | #include 8 | 9 | namespace shady::app { 10 | 11 | class Shady : public input::InputListener 12 | { 13 | public: 14 | Shady() = default; 15 | Shady(const Shady&) = delete; 16 | Shady(Shady&&) = delete; 17 | Shady& operator=(const Shady&) = delete; 18 | Shady& operator=(Shady&&) = delete; 19 | ~Shady() override = default; 20 | 21 | void 22 | Init(); 23 | 24 | void 25 | MainLoop(); 26 | 27 | // InputListener overrides 28 | public: 29 | void 30 | KeyCallback(const input::KeyEvent& event) override; 31 | 32 | void 33 | MouseButtonCallback(const input::MouseButtonEvent& event) override; 34 | 35 | void 36 | CursorPositionCallback(const input::CursorPositionEvent& event) override; 37 | 38 | void 39 | MouseScrollCallback(const input::MouseScrollEvent& event) override; 40 | 41 | private: 42 | void 43 | OnUpdate(); 44 | 45 | private: 46 | // Application settings 47 | Window m_window; 48 | int32_t m_windowWidth = 1920; 49 | int32_t m_windowHeight = 1080; 50 | 51 | scene::Scene m_currentScene; 52 | 53 | bool m_active = true; 54 | }; 55 | 56 | } // namespace shady::app 57 | -------------------------------------------------------------------------------- /src/scene/mesh.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.hpp" 4 | #include "vertex.hpp" 5 | 6 | #include 7 | #include 8 | 9 | namespace shady::scene { 10 | 11 | class Mesh 12 | { 13 | public: 14 | Mesh(const std::string& name, std::vector< render::Vertex >&& vertices, 15 | std::vector< uint32_t >&& indices, render::TextureMaps&& textures); 16 | 17 | /*void 18 | AddTexture(const render::TexturePtr& texture);*/ 19 | 20 | void 21 | Submit(); 22 | 23 | void 24 | Draw(const std::string& modelName, const glm::mat4& modelMat, const glm::vec4& tintColor); 25 | 26 | void 27 | Scale(const glm::vec3& scale); 28 | 29 | void 30 | Rotate(float roateVal, const glm::vec3& axis); 31 | 32 | void 33 | Translate(const glm::vec3& translateVal); 34 | 35 | private: 36 | void 37 | RebuildModelMat(); 38 | 39 | private: 40 | glm::mat4 modelMat_ = glm::mat4(1.0f); 41 | 42 | glm::mat4 translateMat_ = glm::mat4(1.0f); 43 | glm::mat4 rotateMat_ = glm::mat4(1.0f); 44 | glm::mat4 scaleMat_ = glm::mat4(1.0f); 45 | 46 | std::vector< render::Vertex > vertices_ = {}; 47 | std::vector< uint32_t > indices_ = {}; 48 | // render::TexturePtrVec m_textures = {}; 49 | render::TextureMaps textures_; 50 | std::string name_ = "dummyMeshName"; 51 | }; 52 | 53 | } // namespace shady::scene 54 | -------------------------------------------------------------------------------- /src/render/command.cpp: -------------------------------------------------------------------------------- 1 | #include "command.hpp" 2 | #include "common.hpp" 3 | 4 | namespace shady::render { 5 | 6 | VkCommandBuffer 7 | Command::BeginSingleTimeCommands() 8 | { 9 | VkCommandBufferAllocateInfo allocInfo{}; 10 | allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; 11 | allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; 12 | allocInfo.commandPool = Data::vk_commandPool; 13 | allocInfo.commandBufferCount = 1; 14 | 15 | VkCommandBuffer commandBuffer{}; 16 | vkAllocateCommandBuffers(Data::vk_device, &allocInfo, &commandBuffer); 17 | 18 | VkCommandBufferBeginInfo beginInfo{}; 19 | beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; 20 | beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; 21 | 22 | vkBeginCommandBuffer(commandBuffer, &beginInfo); 23 | 24 | return commandBuffer; 25 | } 26 | 27 | void 28 | Command::EndSingleTimeCommands(VkCommandBuffer commandBuffer) 29 | { 30 | vkEndCommandBuffer(commandBuffer); 31 | 32 | VkSubmitInfo submitInfo{}; 33 | submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 34 | submitInfo.commandBufferCount = 1; 35 | submitInfo.pCommandBuffers = &commandBuffer; 36 | 37 | vkQueueSubmit(Data::vk_graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE); 38 | vkQueueWaitIdle(Data::vk_graphicsQueue); 39 | 40 | vkFreeCommandBuffers(Data::vk_device, Data::vk_commandPool, 1, &commandBuffer); 41 | } 42 | 43 | } // namespace shady::render 44 | -------------------------------------------------------------------------------- /src/scene/model.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "mesh.hpp" 4 | #include "render/types.hpp" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | struct aiNode; 16 | struct aiMesh; 17 | struct aiScene; 18 | 19 | namespace shady::scene { 20 | 21 | enum class LoadFlags 22 | { 23 | None = 0, 24 | FlipUV = aiProcess_FlipUVs 25 | }; 26 | 27 | class Model 28 | { 29 | public: 30 | Model() = default; 31 | explicit Model(const std::string& path, LoadFlags additionalAssimpFlags = LoadFlags::None); 32 | 33 | void 34 | ScaleModel(const glm::vec3& scale); 35 | 36 | void 37 | TranslateModel(const glm::vec3& translate); 38 | 39 | void 40 | RotateModel(const glm::vec3& rotate, float angle); 41 | 42 | void 43 | Submit(); 44 | 45 | void 46 | Draw(); 47 | 48 | [[nodiscard]] std::vector< Mesh >& 49 | GetMeshes(); 50 | 51 | [[nodiscard]] static std::unique_ptr< Model > 52 | CreatePlane(); 53 | 54 | // void 55 | // ReloadModel(); 56 | 57 | private: 58 | void 59 | ProcessNode(aiNode* node, const aiScene* scene); 60 | 61 | [[nodiscard]] Mesh 62 | ProcessMesh(aiMesh* mesh, const aiScene* scene); 63 | 64 | private: 65 | std::vector< Mesh > meshes_ = {}; 66 | uint32_t numVertices_ = 0; 67 | uint32_t numIndices_ = 0; 68 | 69 | std::string name_ = "DefaultName"; 70 | }; 71 | 72 | } // namespace shady::scene 73 | -------------------------------------------------------------------------------- /.github/workflows/code_quality.yml: -------------------------------------------------------------------------------- 1 | name: Code quality check 2 | 3 | on: [pull_request] 4 | 5 | jobs: 6 | code-quality: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - uses: actions/checkout@v3 11 | 12 | - name: setup init_script 13 | shell: bash 14 | run: | 15 | echo "#!/bin/bash 16 | 17 | root_dir=\${1} 18 | build_dir=\${2} 19 | 20 | pip install conan --break-system-packages 21 | conan profile detect 22 | conan install \$root_dir --output-folder=build --build=missing --settings=build_type=Release -c tools.system.package_manager:mode=install 23 | 24 | wget https://sdk.lunarg.com/sdk/download/1.3.216.0/linux/vulkansdk-linux-x86_64-1.3.216.0.tar.gz 25 | mkdir vulkan 26 | tar xf vulkansdk-linux-x86_64-1.3.216.0.tar.gz -C \$root_dir/vulkan 27 | source \$root_dir/vulkan/1.3.216.0/setup-env.sh" > init_script.sh 28 | 29 | - name: Run static analysis 30 | uses: JacobDomagala/StaticAnalysis@master 31 | with: 32 | exclude_dir: lib 33 | init_script: init_script.sh 34 | apt_pckgs: xorg-dev python3-pip 35 | report_pr_changes_only: false 36 | cmake_args: -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release 37 | verbose: true 38 | clang_tidy_args: | 39 | -extra-arg=-std=c++20 40 | cppcheck_args: | 41 | --enable=all --suppress=missingIncludeSystem --suppress=functionStatic --suppress=unusedFunction --inline-suppr --inconclusive --check-level=exhaustive 42 | -------------------------------------------------------------------------------- /src/scene/light.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace shady::scene { 6 | 7 | enum class LightType 8 | { 9 | DIRECTIONAL_LIGHT, 10 | POINT_LIGHT, 11 | SPOTLIGHT 12 | }; 13 | 14 | class Light 15 | { 16 | public: 17 | Light(const glm::vec3& position, const glm::vec3& color, LightType type); 18 | 19 | [[nodiscard]] const glm::mat4& 20 | GetLightSpaceMat() const; 21 | 22 | [[nodiscard]] const glm::mat4& 23 | GetViewMat() const; 24 | 25 | [[nodiscard]] glm::vec3 26 | GetPosition() const; 27 | 28 | [[nodiscard]] glm::vec3 29 | GetLookAt() const; 30 | 31 | [[nodiscard]] glm::vec3 32 | GetColor() const; 33 | 34 | void 35 | SetColor(const glm::vec3& new_color); 36 | 37 | [[nodiscard]] glm::tvec2< uint32_t > 38 | GetLightmapSize() const; 39 | 40 | void 41 | MoveBy(const glm::vec3& moveBy); 42 | 43 | private: 44 | void 45 | UpdateViewProjection(); 46 | 47 | private: 48 | uint32_t shadowTextureWidth_ = 4096; 49 | uint32_t shadowTextureHeight_ = 4096; 50 | // std::shared_ptr< render::FrameBuffer > m_shadowBuffer; 51 | 52 | glm::vec3 position_ = glm::vec3(0.0f); 53 | glm::vec3 lookAt_ = glm::vec3(0.0f); 54 | glm::vec3 upVec_ = glm::vec3(0.0f); 55 | glm::vec3 color_ = glm::vec3(1.0f); 56 | 57 | glm::mat4 projectionMatrix_ = glm::mat4(); 58 | glm::mat4 viewMatrix_ = glm::mat4(); 59 | glm::mat4 lightSpaceMatrix_ = glm::mat4(); 60 | glm::mat4 biasMatrix_ = glm::mat4(); 61 | glm::mat4 shadowMatrix_ = glm::mat4(); 62 | }; 63 | 64 | } // namespace shady::scene 65 | -------------------------------------------------------------------------------- /src/scene/mesh.cpp: -------------------------------------------------------------------------------- 1 | #include "mesh.hpp" 2 | 3 | #include "renderer.hpp" 4 | 5 | namespace shady::scene { 6 | 7 | //NOLINTNEXTLINE 8 | Mesh::Mesh(const std::string& name, std::vector< render::Vertex >&& vertices, 9 | std::vector< uint32_t >&& indices, render::TextureMaps&& textures) 10 | : vertices_(std::move(vertices)), 11 | indices_(std::move(indices)), 12 | textures_(std::move(textures)), 13 | name_(name) 14 | { 15 | } 16 | 17 | // void 18 | // Mesh::AddTexture(const render::TexturePtr& texture) 19 | //{ 20 | // //textures_.push_back(texture); 21 | //} 22 | 23 | void 24 | Mesh::Submit() 25 | { 26 | render::Renderer::MeshLoaded(vertices_, indices_, textures_, modelMat_); 27 | } 28 | 29 | void 30 | Mesh::Draw(const std::string& /*modelName*/, const glm::mat4& /*modelMat*/, 31 | const glm::vec4& /*tintColor*/) 32 | { 33 | // render::Renderer3D::DrawMesh(name_, modelMat, textures_, tintColor); 34 | render::Renderer::MeshLoaded(vertices_, indices_, textures_, modelMat_); 35 | } 36 | 37 | void 38 | Mesh::Scale(const glm::vec3& scale) 39 | { 40 | scaleMat_ = glm::scale(glm::mat4(1.0f), scale); 41 | RebuildModelMat(); 42 | } 43 | 44 | void 45 | Mesh::Rotate(float roateVal, const glm::vec3& axis) 46 | { 47 | rotateMat_ = glm::rotate(glm::mat4(1.0f), roateVal, axis); 48 | RebuildModelMat(); 49 | } 50 | 51 | void 52 | Mesh::Translate(const glm::vec3& translateVal) 53 | { 54 | translateMat_ = glm::translate(glm::mat4(1.0f), translateVal); 55 | RebuildModelMat(); 56 | } 57 | 58 | void 59 | Mesh::RebuildModelMat() 60 | { 61 | modelMat_ = translateMat_ * scaleMat_ * rotateMat_; 62 | } 63 | 64 | } // namespace shady::scene 65 | -------------------------------------------------------------------------------- /src/scene/scene.cpp: -------------------------------------------------------------------------------- 1 | #include "scene/scene.hpp" 2 | #include "render/renderer.hpp" 3 | #include "scene/perspective_camera.hpp" 4 | #include "time/scoped_timer.hpp" 5 | #include "utils/file_manager.hpp" 6 | 7 | #include 8 | 9 | 10 | namespace shady::scene { 11 | 12 | scene::Camera& 13 | Scene::GetCamera() 14 | { 15 | return *m_camera; 16 | } 17 | 18 | void 19 | Scene::AddModel(const std::string& fileName, LoadFlags additionalFlags) 20 | { 21 | auto model = std::make_unique< Model >(fileName, additionalFlags); 22 | m_models.push_back(std::move(model)); 23 | } 24 | 25 | Light& 26 | Scene::GetLight() 27 | { 28 | return *m_light; 29 | } 30 | 31 | void Scene::Render(int32_t /*windowWidth*/, int32_t /*windowHeight*/) 32 | { 33 | render::Renderer::UpdateUniformBuffer(m_camera.get(), m_light.get()); 34 | render::Renderer::Draw(); 35 | } 36 | 37 | void 38 | Scene::LoadDefault() 39 | { 40 | const time::ScopedTimer loadScope("Scene::LoadDefault"); 41 | 42 | AddModel((utils::FileManager::MODELS_DIR / "sponza" / "glTF" / "Sponza.gltf").string(), 43 | scene::LoadFlags::FlipUV); 44 | 45 | m_models.back()->ScaleModel(glm::vec3(0.1f, 0.1f, 0.1f)); 46 | m_models.back()->Submit(); 47 | 48 | m_light = 49 | std::make_unique< scene::Light >(glm::vec3(0.0f, 450.0f, 0.0f), glm::vec3(1.0f, 0.8f, 0.7f), 50 | scene::LightType::DIRECTIONAL_LIGHT); 51 | 52 | m_camera = std::make_unique< scene::PerspectiveCamera >(70.0f, 16.0f / 9.0f, 0.1f, 500.0f, 53 | glm::vec3(0.0f, 20.0f, 0.0f)); 54 | } 55 | 56 | } // namespace shady::scene 57 | -------------------------------------------------------------------------------- /src/utils/file_manager.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace shady::render { 10 | 11 | //NOLINTNEXTLINE 12 | using ImageHandleType = std::unique_ptr< uint8_t[], std::function< void(uint8_t*) > >; 13 | 14 | struct ImageData 15 | { 16 | ImageHandleType m_bytes = {}; 17 | glm::uvec2 m_size = {}; 18 | int32_t m_channels = {}; 19 | }; 20 | 21 | } // namespace shady::render 22 | 23 | namespace shady::utils { 24 | 25 | class FileManager 26 | { 27 | public: 28 | //NOLINTBEGIN 29 | static inline const std::filesystem::path ROOT_DIR = 30 | std::filesystem::path(std::string(CMAKE_ROOT_DIR)); 31 | static inline const std::filesystem::path ASSETS_DIR = ROOT_DIR / "assets"; 32 | static inline const std::filesystem::path TEXTURES_DIR = ASSETS_DIR / "textures"; 33 | static inline const std::filesystem::path SHADERS_DIR = ASSETS_DIR / "shaders"; 34 | static inline const std::filesystem::path MODELS_DIR = ASSETS_DIR / "models"; 35 | static inline const std::filesystem::path FONTS_DIR = ASSETS_DIR / "fonts"; 36 | //NOLINTEND 37 | 38 | public: 39 | static std::string 40 | ReadTextFile(const std::filesystem::path& path); 41 | 42 | static std::string 43 | ReadTextFile(std::string_view fileName); 44 | 45 | static std::vector< char > 46 | ReadBinaryFile(const std::filesystem::path& path); 47 | 48 | static std::vector< char > 49 | ReadBinaryFile(std::string_view fileName); 50 | 51 | static void 52 | WriteToFile(std::string_view fileName, std::string_view content); 53 | 54 | static render::ImageData 55 | ReadTexture(std::string_view fileName, bool flipVertical = false); 56 | }; 57 | 58 | } // namespace shady::utils 59 | -------------------------------------------------------------------------------- /src/app/window.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | struct GLFWwindow; 9 | 10 | namespace shady::app { 11 | 12 | class Window 13 | { 14 | public: 15 | Window() = default; 16 | Window(const Window&) = delete; 17 | Window(Window&&) = delete; 18 | Window& operator=(const Window&) = delete; 19 | Window& operator=(Window&&) = delete; 20 | 21 | Window(int32_t width, int32_t height, const std::string& title); 22 | ~Window(); 23 | 24 | void 25 | Create(int32_t width, int32_t height, const std::string& title); 26 | 27 | void 28 | ShutDown(); 29 | 30 | [[nodiscard]] 31 | glm::ivec2 32 | GetSize() const; 33 | 34 | void 35 | Resize(int32_t newWidth, int32_t newHeight); 36 | 37 | void 38 | SetIcon(const std::string& file); 39 | 40 | void 41 | Clear(); 42 | 43 | void 44 | SwapBuffers(); 45 | 46 | // true -> mouse visible and not wrapped 47 | // false -> mouse is disabled (hidden and wrapped) 48 | void 49 | ShowCursor(bool choice); 50 | 51 | // update and get cursor position <-1, 1> 52 | // with positive 'y' is up 53 | [[nodiscard]] 54 | glm::vec2 55 | GetCursorScreenPosition(const glm::mat4& projectionMatrix); 56 | 57 | // update and get cursor position <-1, 1> 58 | // with positive 'y' is down 59 | [[nodiscard]] 60 | glm::vec2 61 | GetCursorNormalized(); 62 | 63 | // return current cursor position on window 64 | [[nodiscard]] 65 | glm::vec2 66 | GetCursor(); 67 | 68 | [[nodiscard]] 69 | GLFWwindow* 70 | GetWindowHandle(); 71 | 72 | private: 73 | bool m_created = false; 74 | int32_t m_width = 0; 75 | int32_t m_height = 0; 76 | std::string m_title = "Default Title"; 77 | 78 | GLFWwindow* m_pWindow = nullptr; 79 | }; 80 | 81 | } // namespace shady::app 82 | -------------------------------------------------------------------------------- /src/scene/skybox.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "render/buffer.hpp" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | namespace shady::scene { 10 | class Camera; 11 | } 12 | 13 | namespace shady::scene { 14 | 15 | struct SkyboxUBO 16 | { 17 | // camera's viewProjection (minus the translation) 18 | glm::mat4 viewProjection; 19 | }; 20 | 21 | class Skybox 22 | { 23 | public: 24 | /* 25 | * Load Cubemap from 6 face files. Each face file should be suffixed with face orientation. 26 | * 27 | * Example: 28 | * sky_front.jpg, sky_back.jpg, sky_left.jpg, sky_right.jpg, sky_top.jpg, sky_bottom.jpg 29 | * 30 | * param[in]: skyboxName prefix for each face file 31 | */ 32 | void 33 | LoadCubeMap(std::string_view skyboxName); 34 | 35 | /* 36 | * Draw commands for 'commandBuffer' 37 | */ 38 | void 39 | Draw(VkCommandBuffer commandBuffer); 40 | 41 | /* 42 | * Update uniform buffer (SkyboxUBO) 43 | */ 44 | void 45 | UpdateBuffers(const scene::Camera* camera); 46 | 47 | private: 48 | void 49 | CreatePipeline(); 50 | 51 | void 52 | CreateDescriptorSet(); 53 | 54 | void 55 | CreateBuffers(); 56 | 57 | void 58 | CreateImageAndSampler(std::string_view skyboxName); 59 | 60 | private: 61 | VkPipeline m_pipeline = {}; 62 | VkPipelineLayout m_pipelineLayout = {}; 63 | VkDescriptorSetLayout m_descriptorSetLayout = {}; 64 | VkDescriptorSet m_descriptorSet = {}; 65 | VkDescriptorPool m_descriptorPool = {}; 66 | 67 | VkImage m_image = {}; 68 | VkDeviceMemory m_imageMemory = {}; 69 | VkImageView m_imageView = {}; 70 | VkSampler m_sampler = {}; 71 | 72 | render::Buffer m_vertexBuffer = {}; 73 | render::Buffer m_indexBuffer = {}; 74 | render::Buffer m_uniformBuffer = {}; 75 | }; 76 | 77 | } // namespace shady::scene 78 | -------------------------------------------------------------------------------- /src/app/gui/gui.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "buffer.hpp" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | namespace shady::scene { 13 | class Scene; 14 | } 15 | 16 | namespace shady::app::gui { 17 | 18 | struct PushConstBlock 19 | { 20 | glm::vec2 scale; 21 | glm::vec2 translate; 22 | }; 23 | 24 | class Gui 25 | { 26 | public: 27 | static void 28 | Init(const glm::ivec2& windowSize); 29 | 30 | static void 31 | Shutdown(); 32 | 33 | static bool 34 | UpdateUI(const glm::ivec2& windowSize, scene::Scene& scene); 35 | 36 | static bool 37 | UpdateBuffers(); 38 | 39 | static void 40 | Render(VkCommandBuffer commandBuffer); 41 | 42 | private: 43 | static void 44 | PrepareResources(); 45 | 46 | static void 47 | PreparePipeline(VkPipelineCache pipelineCache, VkRenderPass renderPass); 48 | 49 | private: 50 | inline static VkImage m_fontImage = {}; 51 | inline static VkDeviceMemory m_fontMemory = {}; 52 | inline static VkImageView m_fontView = {}; 53 | inline static VkSampler m_sampler = {}; 54 | inline static VkDescriptorPool m_descriptorPool = {}; 55 | inline static VkDescriptorSetLayout m_descriptorSetLayout = {}; 56 | inline static VkDescriptorSet m_descriptorSet = {}; 57 | 58 | inline static VkPipeline m_pipeline = {}; 59 | inline static VkPipelineLayout m_pipelineLayout = {}; 60 | inline static uint32_t m_subpass = 0; 61 | 62 | inline static PushConstBlock m_pushConstant = {}; 63 | inline static render::Buffer m_vertexBuffer = {}; 64 | inline static render::Buffer m_indexBuffer = {}; 65 | inline static int32_t m_vertexCount = 0; 66 | inline static int32_t m_indexCount = 0; 67 | }; 68 | 69 | } // namespace shady::app::gui 70 | -------------------------------------------------------------------------------- /src/render/common.cpp: -------------------------------------------------------------------------------- 1 | #include "common.hpp" 2 | #include "utils/assert.hpp" 3 | 4 | namespace shady::render { 5 | 6 | uint32_t 7 | FindMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties) 8 | { 9 | VkPhysicalDeviceMemoryProperties memProperties; 10 | vkGetPhysicalDeviceMemoryProperties(Data::vk_physicalDevice, &memProperties); 11 | 12 | for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) 13 | { 14 | if ((typeFilter & (1 << i)) 15 | && (memProperties.memoryTypes[i].propertyFlags & properties) == properties) 16 | { 17 | return i; 18 | } 19 | } 20 | 21 | utils::Assert(false, "failed to find suitable memory type!"); 22 | return {}; 23 | } 24 | 25 | VkFormat 26 | FindSupportedFormat(const std::vector< VkFormat >& candidates, VkImageTiling tiling, 27 | VkFormatFeatureFlags features) 28 | { 29 | for (const VkFormat format : candidates) 30 | { 31 | VkFormatProperties props; 32 | vkGetPhysicalDeviceFormatProperties(Data::vk_physicalDevice, format, &props); 33 | 34 | if (tiling == VK_IMAGE_TILING_LINEAR && (props.linearTilingFeatures & features) == features) 35 | { 36 | return format; 37 | } 38 | 39 | if (tiling == VK_IMAGE_TILING_OPTIMAL && (props.optimalTilingFeatures & features) == features) 40 | { 41 | return format; 42 | } 43 | } 44 | 45 | utils::Assert(false, "failed to find supported format!"); 46 | return {}; 47 | } 48 | 49 | VkFormat 50 | FindDepthFormat() 51 | { 52 | return FindSupportedFormat( 53 | {VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D32_SFLOAT, VK_FORMAT_D24_UNORM_S8_UINT, 54 | VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_D16_UNORM}, 55 | VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT); 56 | } 57 | 58 | } // namespace shady::render 59 | -------------------------------------------------------------------------------- /src/render/buffer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | 7 | namespace shady::render { 8 | 9 | class Buffer 10 | { 11 | public: 12 | static void 13 | AllocateImageMemory(VkImage image, VkDeviceMemory& bufferMemory, 14 | VkMemoryPropertyFlags properties); 15 | 16 | static void 17 | AllocateBufferMemory(VkBuffer buffer, VkDeviceMemory& bufferMemory, 18 | VkMemoryPropertyFlags properties); 19 | 20 | static Buffer 21 | CreateBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties); 22 | 23 | static void 24 | CreateBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, 25 | VkBuffer& buffer, VkDeviceMemory& bufferMemory); 26 | 27 | static void 28 | CopyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size); 29 | 30 | void 31 | Map(VkDeviceSize size = VK_WHOLE_SIZE); 32 | 33 | void 34 | Unmap(); 35 | 36 | void 37 | CopyData(const void* data) const; 38 | 39 | void 40 | CopyDataWithStaging(void* data, size_t dataSize); 41 | 42 | static void 43 | CopyDataToImageWithStaging(VkImage image, void* data, size_t dataSize, 44 | const std::vector< VkBufferImageCopy >& copyRegions); 45 | 46 | void 47 | Flush(VkDeviceSize size = VK_WHOLE_SIZE, VkDeviceSize offset = 0) const; 48 | 49 | void 50 | SetupDescriptor(VkDeviceSize size = VK_WHOLE_SIZE, VkDeviceSize offset = 0); 51 | 52 | void 53 | Destroy(); 54 | 55 | [[nodiscard]] VkBuffer& 56 | GetBuffer(); 57 | 58 | [[nodiscard]] void* 59 | GetMappedMemory(); 60 | 61 | [[nodiscard]] VkDescriptorBufferInfo& 62 | GetDescriptor(); 63 | 64 | private: 65 | void* mappedMemory_ = nullptr; 66 | bool mapped_ = false; 67 | VkBuffer buffer_ = {}; 68 | VkDeviceMemory bufferMemory_ = {}; 69 | VkDeviceSize bufferSize_ = {}; 70 | VkDescriptorBufferInfo descriptor_ = {}; 71 | }; 72 | 73 | 74 | } // namespace shady::render 75 | -------------------------------------------------------------------------------- /src/trace/logger.impl.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "logger.hpp" 4 | 5 | namespace shady::trace { 6 | 7 | 8 | template < typename... Args > 9 | constexpr void 10 | Logger::Trace(fmt::format_string buffer, Args&&... args) 11 | { 12 | Log< TYPE::TRACE >(buffer, std::forward< Args >(args)...); 13 | } 14 | 15 | template < typename... Args > 16 | constexpr void 17 | Logger::Debug(fmt::format_string buffer, Args&&... args) 18 | { 19 | Log< TYPE::DEBUG >(buffer, std::forward< Args >(args)...); 20 | } 21 | 22 | template < typename... Args > 23 | constexpr void 24 | Logger::Info(fmt::format_string buffer, Args&&... args) 25 | { 26 | Log< TYPE::INFO >(buffer, std::forward< Args >(args)...); 27 | } 28 | 29 | template < typename... Args > 30 | constexpr void 31 | Logger::Warn(fmt::format_string buffer, Args&&... args) 32 | { 33 | Log< TYPE::WARNING >(buffer, std::forward< Args >(args)...); 34 | } 35 | 36 | template < typename... Args > 37 | constexpr void 38 | Logger::Fatal(fmt::format_string buffer, Args&&... args) 39 | { 40 | Log< TYPE::FATAL >(buffer, std::forward< Args >(args)...); 41 | } 42 | 43 | template < TYPE LogLevel, typename... Args > 44 | constexpr void 45 | Logger::Log(fmt::format_string buffer, Args&&... args) 46 | { 47 | if (LogLevel >= s_currentLogType) 48 | { 49 | #if defined(_WIN32) 50 | auto hConsole = GetStdHandle(STD_OUTPUT_HANDLE); 51 | SetConsoleTextAttribute(hConsole, s_typeStyles.at(LogLevel)); 52 | 53 | fmt::print("[{}]{} {}\n", time::GetTime(), ToString(LogLevel), 54 | fmt::format(buffer, std::forward< Args >(args)...)); 55 | 56 | // Set the color to white 57 | SetConsoleTextAttribute(hConsole, FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED); 58 | #else 59 | fmt::print(fmt::fg(s_typeStyles.at(LogLevel)), "[{}]{} {}\n", time::GetTime(), 60 | ToString(LogLevel), 61 | fmt::format(buffer, std::forward< Args >(args)...)); 62 | #endif 63 | } 64 | } 65 | 66 | } // namespace shady::trace 67 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Shady 2 | [![Windows](https://github.com/JacobDomagala/Shady/actions/workflows/windows.yml/badge.svg?branch=master)](https://github.com/JacobDomagala/Shady/actions/workflows/windows.yml?query=branch%3Amaster) 3 | [![Ubuntu](https://github.com/JacobDomagala/Shady/actions/workflows/ubuntu.yml/badge.svg?branch=master)](https://github.com/JacobDomagala/Shady/actions/workflows/ubuntu.yml?query=branch%3Amaster) 4 | 5 | ------------------------------------------------------------ 6 | 7 | Shady is a 3D rendering engine written in modern C++ and Vulkan. It's not meant to be a fully fledged rendering/game engine, it's just a fun project I'm doing in my free time.
8 | 9 | This project is in an early stage so it's still missing many basic features. For current roadmap/planned features see [Github Project](https://github.com/users/JacobDomagala/projects/3/views/1)
10 | 11 | Below you can see famous [Sponza](https://en.wikipedia.org/wiki/Sponza_Palace) scene rendered using Shady (click to see YouTube video):
12 | [![Sponza](https://github.com/JacobDomagala/Shady/wiki/Youtube.png)](https://www.youtube.com/watch?v=LZlHqkR0CQ0) 13 | 14 | ------------------------------------------------------------ 15 | ## Building 16 | 17 | Shady is CMake/Conan based project working both on Linux (Ubuntu) and Windows. To build it, you will need at least C++20 compiler and CMake version 3.22.
18 | While most of the dependencies will be handled by Conan, it's required that you have Vulkan installed on your machine. 19 | 20 | Typical build process would look like this: 21 | ```bash 22 | # Create build directory 23 | mkdir build && cd build 24 | 25 | conan profile detect 26 | conan install .. -of=build --build=missing -s compiler.cppstd=20 27 | 28 | # Generate build system for Windows/Linux 29 | cmake -G "Ninja" -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake .. 30 | 31 | # Build 32 | cmake --build . 33 | ``` 34 | 35 | ## Youtube 36 | For past and future video logs, please visit my [Youtube](https://www.youtube.com/@Jacob.Domagala) channel.
37 | [![Playlist](https://img.youtube.com/vi/LZlHqkR0CQ0/0.jpg)](https://www.youtube.com/watch?v=LZlHqkR0CQ0&list=PLRLVUsGGaSH8GcSjxOiAQBRWuFpVtWVOp "YouTube Playlist") 38 | -------------------------------------------------------------------------------- /src/scene/camera.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace shady::scene { 6 | 7 | enum class CameraType 8 | { 9 | orthographic, 10 | perspective 11 | }; 12 | 13 | class Camera 14 | { 15 | public: 16 | Camera() = delete; 17 | Camera(const Camera&) = delete; 18 | Camera(Camera&&) = delete; 19 | Camera& 20 | operator=(const Camera&) = delete; 21 | Camera& 22 | operator=(Camera&&) = delete; 23 | 24 | Camera(const glm::mat4& projection, const glm::vec3& position); 25 | virtual ~Camera() = default; 26 | 27 | void 28 | SetProjection(const glm::mat4&); 29 | 30 | [[nodiscard]] const glm::mat4& 31 | GetProjection() const; 32 | 33 | void 34 | SetView(const glm::mat4&); 35 | 36 | [[nodiscard]] const glm::mat4& 37 | GetView() const; 38 | 39 | void 40 | SetViewProjection(const glm::mat4&); 41 | 42 | [[nodiscard]] const glm::mat4& 43 | GetViewProjection() const; 44 | 45 | void 46 | SetPosition(const glm::vec3&); 47 | 48 | [[nodiscard]] const glm::vec3& 49 | GetPosition() const; 50 | 51 | [[nodiscard]] const glm::vec3& 52 | GetLookAtVec() const; 53 | 54 | [[nodiscard]] const glm::vec3& 55 | GetUpVec() const; 56 | 57 | [[nodiscard]] const glm::vec3& 58 | GetRightVec() const; 59 | 60 | virtual void 61 | MouseMovement(const glm::vec2& mouseMovement) = 0; 62 | 63 | virtual void 64 | MoveCamera(const glm::vec2& leftRightVec) = 0; 65 | 66 | virtual void 67 | RotateCamera(float angle, const glm::vec3& axis) = 0; 68 | 69 | protected: 70 | void 71 | UpdateViewMatrix(); 72 | 73 | void 74 | UpdateViewProjection(); 75 | 76 | protected: 77 | glm::mat4 projectionMat_ = glm::mat4(1.0f); 78 | glm::mat4 viewMat_ = glm::mat4(1.0f); 79 | glm::mat4 viewProjectionMat_ = glm::mat4(1.0f); 80 | 81 | glm::vec3 position_ = glm::vec3(0.0f); 82 | const glm::vec3 worldUp_ = glm::vec3(0.0f, -1.0f, 0.0f); 83 | glm::vec3 upVector_ = worldUp_; 84 | glm::vec3 rightVector_ = glm::vec3(0.0f, 0.0f, -1.0f); 85 | glm::vec3 lookAtDirection_ = glm::vec3(1.0f, 0.0f, 0.0f); 86 | }; 87 | } // namespace shady::scene -------------------------------------------------------------------------------- /src/scene/perspective_camera.cpp: -------------------------------------------------------------------------------- 1 | #include "scene/perspective_camera.hpp" 2 | #include "trace/logger.hpp" 3 | 4 | #include 5 | 6 | namespace shady::scene { 7 | 8 | PerspectiveCamera::PerspectiveCamera(const glm::mat4& projection, const glm::vec3& position) 9 | : Camera(projection, position) 10 | { 11 | } 12 | 13 | PerspectiveCamera::PerspectiveCamera(float fieldOfView, float aspectRatio, float nearClip, 14 | float farClip, const glm::vec3& position) 15 | : Camera(glm::perspective(fieldOfView, aspectRatio, nearClip, farClip), position) 16 | { 17 | } 18 | 19 | void 20 | PerspectiveCamera::MouseMovement(const glm::vec2& mouseMovement) 21 | { 22 | yaw_ += mouseMovement.x; 23 | pitch_ += mouseMovement.y; 24 | 25 | if (constrainPitch_) 26 | { 27 | pitch_ = glm::clamp(pitch_, -89.0f, 89.0f); 28 | } 29 | 30 | lookAtDirection_.x = -glm::cos(glm::radians(yaw_)) * glm::cos(glm::radians(pitch_)); 31 | lookAtDirection_.y = glm::sin(glm::radians(pitch_)); 32 | lookAtDirection_.z = -glm::sin(glm::radians(yaw_)) * glm::cos(glm::radians(pitch_)); 33 | lookAtDirection_ = glm::normalize(lookAtDirection_); 34 | 35 | rightVector_ = glm::normalize(glm::cross(lookAtDirection_, worldUp_)); 36 | upVector_ = glm::normalize(glm::cross(rightVector_, lookAtDirection_)); 37 | 38 | UpdateViewMatrix(); 39 | } 40 | 41 | void 42 | PerspectiveCamera::MoveCamera(const glm::vec2& leftRightVec) 43 | { 44 | constexpr auto cameraSpeed = 0.5f; 45 | 46 | trace::Logger::Trace("Camera Pos:{} LookAtDir:{} RightVec:{}", position_, lookAtDirection_, 47 | rightVector_); 48 | position_ += cameraSpeed * (leftRightVec.y * lookAtDirection_); 49 | position_ += cameraSpeed * (leftRightVec.x * rightVector_); 50 | 51 | UpdateViewMatrix(); 52 | } 53 | 54 | void 55 | PerspectiveCamera::RotateCamera(float /*angle*/, const glm::vec3& /*axis*/) 56 | { 57 | lookAtDirection_ = glm::normalize(lookAtDirection_); 58 | 59 | rightVector_ = glm::normalize(glm::cross(lookAtDirection_, worldUp_)); 60 | upVector_ = glm::normalize(glm::cross(rightVector_, lookAtDirection_)); 61 | UpdateViewMatrix(); 62 | } 63 | 64 | } // namespace shady::scene 65 | -------------------------------------------------------------------------------- /src/scene/camera.cpp: -------------------------------------------------------------------------------- 1 | #include "scene/camera.hpp" 2 | #include "trace/logger.hpp" 3 | 4 | #include 5 | 6 | namespace shady::scene { 7 | 8 | Camera::Camera(const glm::mat4& projection, const glm::vec3& position) 9 | : projectionMat_(projection), position_(position) 10 | { 11 | UpdateViewMatrix(); 12 | } 13 | 14 | void 15 | Camera::SetProjection(const glm::mat4& projection) 16 | { 17 | projectionMat_ = projection; 18 | } 19 | 20 | const glm::mat4& 21 | Camera::GetProjection() const 22 | { 23 | return projectionMat_; 24 | } 25 | 26 | void 27 | Camera::SetView(const glm::mat4& view) 28 | { 29 | const auto inversed = glm::inverse(view); 30 | 31 | rightVector_ = glm::normalize(inversed[0]); 32 | position_ = inversed[3]; 33 | lookAtDirection_ = glm::vec3(inversed[1]) - position_; 34 | upVector_ = glm::normalize(glm::cross(rightVector_, glm::normalize(lookAtDirection_))); 35 | 36 | viewMat_ = view; 37 | 38 | UpdateViewProjection(); 39 | } 40 | 41 | const glm::mat4& 42 | Camera::GetView() const 43 | { 44 | return viewMat_; 45 | } 46 | 47 | void 48 | Camera::SetViewProjection(const glm::mat4& viewProjection) 49 | { 50 | viewProjectionMat_ = viewProjection; 51 | } 52 | 53 | const glm::mat4& 54 | Camera::GetViewProjection() const 55 | { 56 | return viewProjectionMat_; 57 | } 58 | 59 | void 60 | Camera::SetPosition(const glm::vec3& position) 61 | { 62 | position_ = position; 63 | UpdateViewMatrix(); 64 | } 65 | 66 | const glm::vec3& 67 | Camera::GetPosition() const 68 | { 69 | return position_; 70 | } 71 | 72 | const glm::vec3& 73 | Camera::GetLookAtVec() const 74 | { 75 | return lookAtDirection_; 76 | } 77 | 78 | const glm::vec3& 79 | Camera::GetUpVec() const 80 | { 81 | return upVector_; 82 | } 83 | 84 | const glm::vec3& 85 | Camera::GetRightVec() const 86 | { 87 | return rightVector_; 88 | } 89 | 90 | void 91 | Camera::UpdateViewMatrix() 92 | { 93 | viewMat_ = glm::lookAt(position_, position_ + lookAtDirection_, upVector_); 94 | UpdateViewProjection(); 95 | } 96 | 97 | void 98 | Camera::UpdateViewProjection() 99 | { 100 | viewProjectionMat_ = projectionMat_ * viewMat_; 101 | } 102 | 103 | } // namespace shady::scene -------------------------------------------------------------------------------- /src/scene/light.cpp: -------------------------------------------------------------------------------- 1 | #include "scene/light.hpp" 2 | #include "trace/logger.hpp" 3 | 4 | #include 5 | 6 | namespace shady::scene { 7 | 8 | Light::Light(const glm::vec3& position, const glm::vec3& color, LightType type) 9 | : position_(position), color_(color) 10 | { 11 | // auto buffer_type = render::FrameBufferType::SINGLE; 12 | switch (type) 13 | { 14 | case LightType::DIRECTIONAL_LIGHT: { 15 | projectionMatrix_ = glm::ortho(-200.0f, 200.0f, -200.0f, 200.0f, 1.0f, 500.0f); 16 | // projectionMatrix_ = glm::perspective(70.0f, 16.0f / 9.0f, 0.1f, 500.0f); 17 | } 18 | break; 19 | 20 | case LightType::POINT_LIGHT: 21 | case LightType::SPOTLIGHT: { 22 | projectionMatrix_ = glm::perspective(60.0f, 1.0f, 0.1f, 100.0f); 23 | // buffer_type = render::FrameBufferType::CUBE; 24 | } 25 | break; 26 | } 27 | 28 | // m_shadowBuffer = render::FrameBuffer::Create({shadowTextureWidth_, shadowTextureHeight_}, 29 | // buffer_type); 30 | biasMatrix_ = glm::translate(glm::mat4(1.0f), glm::vec3(0.5f)) 31 | * glm::scale(glm::mat4(1.0f), glm::vec3(0.5f)); 32 | lookAt_ = glm::vec3(0.0f, -1.0f, 0.0f); 33 | upVec_ = glm::vec3(0.0f, 0.0f, 0.5f); 34 | // m_shadowBuffer->MakeTextureResident(); 35 | 36 | UpdateViewProjection(); 37 | } 38 | 39 | const glm::mat4& 40 | Light::GetLightSpaceMat() const 41 | { 42 | return lightSpaceMatrix_; 43 | } 44 | 45 | const glm::mat4& 46 | Light::GetViewMat() const 47 | { 48 | return viewMatrix_; 49 | } 50 | 51 | glm::vec3 52 | Light::GetPosition() const 53 | { 54 | return position_; 55 | } 56 | 57 | glm::vec3 58 | Light::GetLookAt() const 59 | { 60 | return lookAt_; 61 | } 62 | 63 | glm::vec3 64 | Light::GetColor() const 65 | { 66 | return color_; 67 | } 68 | 69 | void 70 | Light::SetColor(const glm::vec3& new_color) 71 | { 72 | color_ = new_color; 73 | } 74 | 75 | glm::tvec2< uint32_t > 76 | Light::GetLightmapSize() const 77 | { 78 | return {shadowTextureWidth_, shadowTextureHeight_}; 79 | } 80 | 81 | void 82 | Light::MoveBy(const glm::vec3& moveBy) 83 | { 84 | position_ += moveBy; 85 | 86 | UpdateViewProjection(); 87 | // trace::Logger::Info("Light position {}", position_); 88 | } 89 | 90 | void 91 | Light::UpdateViewProjection() 92 | { 93 | viewMatrix_ = glm::lookAt(position_, lookAt_, upVec_); 94 | lightSpaceMatrix_ = projectionMatrix_ * viewMatrix_; 95 | shadowMatrix_ = biasMatrix_ * lightSpaceMatrix_; 96 | } 97 | 98 | } // namespace shady::scene 99 | -------------------------------------------------------------------------------- /src/trace/logger.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "time/utils.hpp" 4 | #include "trace/formatter_types.hpp" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #if defined(_WIN32) 11 | #include 12 | #endif // WIN 13 | 14 | namespace shady::trace { 15 | 16 | enum class TYPE 17 | { 18 | TRACE, 19 | DEBUG, 20 | INFO, 21 | WARNING, 22 | FATAL 23 | }; 24 | 25 | struct LoggerTypeHash 26 | { 27 | std::size_t 28 | operator()(TYPE t) const 29 | { 30 | return static_cast< std::size_t >(t); 31 | } 32 | }; 33 | 34 | class Logger 35 | { 36 | public: 37 | template < typename... Args > 38 | static constexpr void 39 | Trace(fmt::format_string buffer, Args&&... args); 40 | 41 | template < typename... Args > 42 | static constexpr void 43 | Debug(fmt::format_string buffer, Args&&... args); 44 | 45 | template < typename... Args > 46 | static constexpr void 47 | Info(fmt::format_string buffer, Args&&... args); 48 | 49 | template < typename... Args > 50 | static constexpr void 51 | Warn(fmt::format_string buffer, Args&&... args); 52 | 53 | template < typename... Args > 54 | static constexpr void 55 | Fatal(fmt::format_string buffer, Args&&... args); 56 | 57 | template < TYPE LogLevel, typename... Args > 58 | static constexpr void 59 | Log(fmt::format_string buffer, Args&&... args); 60 | 61 | static void 62 | SetType(TYPE newType); 63 | 64 | private: 65 | static std::string 66 | ToString(TYPE type); 67 | 68 | private: 69 | static inline TYPE s_currentLogType = TYPE::DEBUG; 70 | 71 | #if defined(_WIN32) 72 | static const inline std::unordered_map< TYPE, WORD, LoggerTypeHash > s_typeStyles = { 73 | {TYPE::TRACE, FOREGROUND_BLUE}, 74 | {TYPE::DEBUG, FOREGROUND_GREEN | FOREGROUND_BLUE}, 75 | {TYPE::INFO, FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED}, 76 | {TYPE::WARNING, FOREGROUND_GREEN | FOREGROUND_RED}, 77 | {TYPE::FATAL, FOREGROUND_RED}}; 78 | #else 79 | //NOLINTNEXTLINE 80 | static const inline std::unordered_map< TYPE, fmt::color, LoggerTypeHash > s_typeStyles = { 81 | {TYPE::TRACE, fmt::color::azure}, 82 | {TYPE::DEBUG, fmt::color::blanched_almond}, 83 | {TYPE::INFO, fmt::color::floral_white}, 84 | {TYPE::WARNING, fmt::color::yellow}, 85 | {TYPE::FATAL, fmt::color::crimson}}; 86 | #endif 87 | }; 88 | 89 | } // namespace shady::trace 90 | 91 | #include "logger.impl.hpp" 92 | -------------------------------------------------------------------------------- /src/render/shader.cpp: -------------------------------------------------------------------------------- 1 | #include "shader.hpp" 2 | #include "common.hpp" 3 | #include "trace/logger.hpp" 4 | #include "utils/assert.hpp" 5 | #include "utils/file_manager.hpp" 6 | 7 | namespace shady::render { 8 | 9 | static VkShaderModule 10 | CreateShaderModule(VkDevice device, std::vector< char >&& shaderByteCode) 11 | { 12 | VkShaderModuleCreateInfo createInfo{}; 13 | createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; 14 | createInfo.codeSize = shaderByteCode.size(); 15 | createInfo.pCode = reinterpret_cast< const uint32_t* >(shaderByteCode.data()); 16 | 17 | VkShaderModule shaderModule = {}; 18 | VK_CHECK(vkCreateShaderModule(device, &createInfo, nullptr, &shaderModule), 19 | "Failed to create shader module!"); 20 | 21 | return shaderModule; 22 | } 23 | 24 | 25 | ShaderInfoWrapper 26 | Shader::LoadShader(std::string_view shader, VkShaderStageFlagBits stage) 27 | { 28 | VkShaderModule shaderModule = CreateShaderModule( 29 | Data::vk_device, 30 | utils::FileManager::ReadBinaryFile(utils::FileManager::SHADERS_DIR / shader)); 31 | 32 | VkPipelineShaderStageCreateInfo shaderStageInfo{}; 33 | shaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 34 | shaderStageInfo.stage = stage; 35 | shaderStageInfo.module = shaderModule; 36 | shaderStageInfo.pName = "main"; 37 | 38 | return {Data::vk_device, shaderStageInfo}; 39 | } 40 | 41 | std::pair< VertexShaderInfo, FragmentShaderInfo > 42 | Shader::CreateShader(VkDevice device, std::string_view vertex, std::string_view fragment) 43 | { 44 | VkShaderModule vertShaderModule = CreateShaderModule( 45 | device, utils::FileManager::ReadBinaryFile(utils::FileManager::SHADERS_DIR / vertex)); 46 | VkShaderModule fragShaderModule = CreateShaderModule( 47 | device, utils::FileManager::ReadBinaryFile(utils::FileManager::SHADERS_DIR / fragment)); 48 | 49 | VkPipelineShaderStageCreateInfo vertShaderStageInfo{}; 50 | vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 51 | vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT; 52 | vertShaderStageInfo.module = vertShaderModule; 53 | vertShaderStageInfo.pName = "main"; 54 | 55 | VkPipelineShaderStageCreateInfo fragShaderStageInfo{}; 56 | fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 57 | fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT; 58 | fragShaderStageInfo.module = fragShaderModule; 59 | fragShaderStageInfo.pName = "main"; 60 | 61 | return {{device, vertShaderStageInfo}, {device, fragShaderStageInfo}}; 62 | } 63 | 64 | } // namespace shady::render 65 | -------------------------------------------------------------------------------- /.github/workflows/windows.yml: -------------------------------------------------------------------------------- 1 | name: Windows 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | - develop 8 | pull_request: 9 | 10 | env: 11 | VULKAN_DIR: C:\VulkanSDK 12 | SDK_VERSION: 1.3.268.0 13 | BUILD_TYPE: Release 14 | 15 | jobs: 16 | build: 17 | runs-on: windows-latest 18 | 19 | steps: 20 | - uses: actions/checkout@v3 21 | 22 | - name: Cache Vulkan SDK 23 | id: cache-vulkan-sdk 24 | uses: actions/cache@v3 25 | with: 26 | path: ${{env.VULKAN_DIR}}\${{env.SDK_VERSION}} 27 | key: vulkan-sdk-${{ runner.os }}-${{env.SDK_VERSION}} 28 | 29 | - name: Download and install Vulkan SDK 30 | if: steps.cache-vulkan-sdk.outputs.cache-hit != 'true' 31 | run: | 32 | Invoke-WebRequest -Uri "https://sdk.lunarg.com/sdk/download/$env:SDK_VERSION/windows/VulkanSDK-$env:SDK_VERSION-Installer.exe" -OutFile VulkanSDK.exe; 33 | $installer = Start-Process -FilePath VulkanSDK.exe -Wait -PassThru -ArgumentList @("--accept-licenses --default-answer --confirm-command install"); 34 | $installer.WaitForExit(); 35 | 36 | - name: Install Conan 37 | id: conan 38 | uses: turtlebrowser/get-conan@main 39 | 40 | - name: Cache Conan packages 41 | id: cache-conan 42 | uses: actions/cache@v3 43 | with: 44 | path: ~/.conan/data 45 | key: conan-cache-${{ hashFiles('**/conanfile.txt') }} 46 | 47 | - name: Create Build Environment 48 | run: | 49 | cmake -E make_directory ${{runner.workspace}}/build 50 | 51 | - name: Install dependencies with Conan 52 | working-directory: ${{runner.workspace}}/build 53 | run: | 54 | conan profile detect 55 | conan install $env:GITHUB_WORKSPACE --output-folder=build --build=missing --settings=build_type=$env:BUILD_TYPE -s compiler.cppstd=20 56 | 57 | - name: Configure CMake and build 58 | working-directory: ${{runner.workspace}}/build 59 | run: | 60 | $env:VULKAN_SDK="$env:VULKAN_DIR\$env:SDK_VERSION" 61 | 62 | cmake $env:GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$env:BUILD_TYPE -DCMAKE_TOOLCHAIN_FILE=${{runner.workspace}}\build\build\conan_toolchain.cmake 63 | cmake --build . --config $env:BUILD_TYPE > output.txt 64 | cat output.txt 65 | 66 | - name: Post PR comment for warnings/errors 67 | if: always() && github.ref != 'refs/heads/develop' && github.ref != 'refs/heads/master' 68 | uses: JacobDomagala/CompileResultAction@master 69 | with: 70 | comment_title: WINDOWS COMPILE RESULT 71 | compile_result_file: ${{runner.workspace}}/build/output.txt 72 | compiler: MSVC 73 | exclude_dir: ${{github.workspace}}/lib 74 | debug_output: true 75 | -------------------------------------------------------------------------------- /src/render/vertex.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace shady::render { 8 | 9 | struct SkyboxVertex 10 | { 11 | glm::vec3 m_position; 12 | 13 | static auto 14 | getBindingDescription() 15 | { 16 | VkVertexInputBindingDescription bindingDescription{}; 17 | bindingDescription.binding = 0; 18 | bindingDescription.stride = sizeof(SkyboxVertex); 19 | bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; 20 | 21 | return bindingDescription; 22 | } 23 | 24 | static auto 25 | getAttributeDescriptions() 26 | { 27 | std::array< VkVertexInputAttributeDescription, 1 > attributeDescriptions{}; 28 | 29 | attributeDescriptions[0].binding = 0; 30 | attributeDescriptions[0].location = 0; 31 | attributeDescriptions[0].format = VK_FORMAT_R32G32B32_SFLOAT; 32 | attributeDescriptions[0].offset = offsetof(SkyboxVertex, m_position); 33 | 34 | return attributeDescriptions; 35 | } 36 | }; 37 | 38 | struct Vertex 39 | { 40 | glm::vec3 m_position; 41 | glm::vec3 m_normal; 42 | glm::vec2 m_texCoords; 43 | glm::vec3 m_tangent; 44 | 45 | static auto 46 | getBindingDescription() 47 | { 48 | VkVertexInputBindingDescription bindingDescription{}; 49 | bindingDescription.binding = 0; 50 | bindingDescription.stride = sizeof(Vertex); 51 | bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; 52 | 53 | return bindingDescription; 54 | } 55 | 56 | static auto 57 | getAttributeDescriptions() 58 | { 59 | std::array< VkVertexInputAttributeDescription, 4 > attributeDescriptions{}; 60 | 61 | attributeDescriptions[0].binding = 0; 62 | attributeDescriptions[0].location = 0; 63 | attributeDescriptions[0].format = VK_FORMAT_R32G32B32_SFLOAT; 64 | attributeDescriptions[0].offset = offsetof(Vertex, m_position); 65 | 66 | attributeDescriptions[1].binding = 0; 67 | attributeDescriptions[1].location = 1; 68 | attributeDescriptions[1].format = VK_FORMAT_R32G32B32_SFLOAT; 69 | attributeDescriptions[1].offset = offsetof(Vertex, m_normal); 70 | 71 | attributeDescriptions[2].binding = 0; 72 | attributeDescriptions[2].location = 2; 73 | attributeDescriptions[2].format = VK_FORMAT_R32G32_SFLOAT; 74 | attributeDescriptions[2].offset = offsetof(Vertex, m_texCoords); 75 | 76 | attributeDescriptions[3].binding = 0; 77 | attributeDescriptions[3].location = 3; 78 | attributeDescriptions[3].format = VK_FORMAT_R32G32B32_SFLOAT; 79 | attributeDescriptions[3].offset = offsetof(Vertex, m_tangent); 80 | 81 | return attributeDescriptions; 82 | } 83 | }; 84 | 85 | } // namespace shady::render 86 | -------------------------------------------------------------------------------- /.github/workflows/ubuntu.yml: -------------------------------------------------------------------------------- 1 | name: Ubuntu 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | - develop 8 | pull_request: 9 | 10 | env: 11 | BUILD_TYPE: Release 12 | SDK_VERSION: 1.3.268.0 13 | CXX: clang++-15 14 | CC: clang-15 15 | 16 | jobs: 17 | build: 18 | runs-on: ubuntu-22.04 19 | 20 | steps: 21 | - uses: actions/checkout@v3 22 | 23 | - name: Install dependencies 24 | run: | 25 | sudo apt-get update 26 | sudo apt-get install -y xorg-dev clang++-15 llvm-dev python3-pip libgl-dev libgl1-mesa-dev \ 27 | libx11-xcb-dev libxcb-render-util0-dev libxcb-xkb-dev libxcb-icccm4-dev \ 28 | libxcb-image0-dev libxcb-keysyms1-dev libxcb-randr0-dev libxcb-shape0-dev \ 29 | libxcb-sync-dev libxcb-xfixes0-dev libxcb-xinerama0-dev libxcb-dri3-dev \ 30 | libx11-xcb-dev libxcb-render-util0-dev libxcb-xkb-dev libxcb-icccm4-dev \ 31 | libxcb-image0-dev libxcb-keysyms1-dev libxcb-randr0-dev libxcb-shape0-dev \ 32 | libxcb-sync-dev libxcb-xfixes0-dev libxcb-xinerama0-dev libxcb-dri3-dev \ 33 | libxcb-util-dev libxcb-util0-dev \ 34 | libx11-dev libfontenc-dev libice-dev libsm-dev libxau-dev \ 35 | libxaw7-dev libxcb-glx0-dev libxcb-cursor-dev libxcb-dri2-0-dev libxcb-present-dev \ 36 | libxcb-composite0-dev libxcb-ewmh-dev libxcb-res0-dev 37 | 38 | pip install conan 39 | 40 | wget https://sdk.lunarg.com/sdk/download/$SDK_VERSION/linux/vulkansdk-linux-x86_64-$SDK_VERSION.tar.xz 41 | tar xf vulkansdk-linux-x86_64-$SDK_VERSION.tar.xz 42 | 43 | cmake -E make_directory ${{runner.workspace}}/build 44 | 45 | - name: Cache Conan packages 46 | id: cache-conan 47 | uses: actions/cache@v3 48 | with: 49 | path: ~/.conan/data 50 | key: conan-cache-${{ hashFiles('**/conanfile.txt') }} 51 | 52 | - name: Install dependencies with Conan 53 | working-directory: ${{runner.workspace}}/build 54 | run: | 55 | conan profile detect 56 | conan install $GITHUB_WORKSPACE --output-folder=build --build=missing --settings=build_type=$BUILD_TYPE -s compiler.cppstd=gnu20 57 | 58 | - name: Configure CMake and build 59 | shell: bash 60 | working-directory: ${{runner.workspace}}/build 61 | run: | 62 | source ${{runner.workspace}}/Shady/$SDK_VERSION/setup-env.sh 63 | 64 | cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DWARNINGS_AS_ERRORS=ON \ 65 | -DENABLE_INCLUDE_WHAT_YOU_USE=OFF -DUNITY_BUILD=ON -DCMAKE_TOOLCHAIN_FILE=build/conan_toolchain.cmake 66 | 67 | cmake --build . --config $BUILD_TYPE 2> >(tee "output.txt") 68 | 69 | - name: Post PR comment for warnings/errors 70 | if: always() && github.ref != 'refs/heads/develop' && github.ref != 'refs/heads/master' 71 | uses: JacobDomagala/CompileResultAction@master 72 | with: 73 | comment_title: UBUNTU COMPILE RESULT 74 | compile_result_file: ${{runner.workspace}}/build/output.txt 75 | -------------------------------------------------------------------------------- /src/trace/formatter_types.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | template < typename T > 8 | struct fmt::formatter< glm::tmat4x4< T > > 9 | { 10 | constexpr auto 11 | parse(format_parse_context& ctx) 12 | { 13 | return ctx.begin(); 14 | } 15 | 16 | template < typename FormatContext > 17 | auto 18 | format(const glm::tmat4x4< T >& mat, FormatContext& ctx) const 19 | { 20 | return fmt::format_to( 21 | ctx.out(), 22 | std::is_same< T, float >::value 23 | ? "\n[{:.1f}, {:.1f}, {:.1f}, {:.1f}]\n[{:.1f}, {:.1f}, {:.1f}, {:.1f}]\n[{:.1f}, " 24 | "{:.1f}, {:.1f}, {:.1f}]\n[{:.1f}, {:.1f}, {:.1f}, {:.1f}]" 25 | : "\n[{0:d}, {0:d}, {0:d}, {0:d}]\n[{0:d}, {0:d}, {0:d}, {0:d}]\n[{0:d}, {0:d}, {0:d}, " 26 | "{0:d}]\n[{0:d}, {0:d}, {0:d}, {0:d}]", 27 | mat[0][0], mat[0][1], mat[0][2], mat[0][3], mat[1][0], mat[1][1], mat[1][2], mat[1][3], 28 | mat[2][0], mat[2][1], mat[2][2], mat[2][3], mat[3][0], mat[3][1], mat[3][2], mat[3][3]); 29 | } 30 | }; 31 | 32 | template < typename T > 33 | struct fmt::formatter< glm::tvec4< T > > 34 | { 35 | constexpr auto 36 | parse(format_parse_context& ctx) 37 | { 38 | return ctx.begin(); 39 | } 40 | 41 | template < typename FormatContext > 42 | auto 43 | format(const glm::tvec4< T >& vec, FormatContext& ctx) const 44 | { 45 | return fmt::format_to(ctx.out(), 46 | std::is_same< T, float >::value ? "({:.1f}, {:.1f}, {:.1f}, {:.1f})" 47 | : "({0:d}, {0:d}, {0:d}, {0:d})", 48 | vec.x, vec.y, vec.z, vec.y); 49 | } 50 | }; 51 | 52 | template < typename T > 53 | struct fmt::formatter< glm::tvec3< T > > 54 | { 55 | constexpr auto 56 | parse(format_parse_context& ctx) 57 | { 58 | return ctx.begin(); 59 | } 60 | 61 | template < typename FormatContext > 62 | auto 63 | format(const glm::tvec3< T >& vec, FormatContext& ctx) const 64 | { 65 | return fmt::format_to(ctx.out(), 66 | std::is_same< T, float >::value ? "({:.1f}, {:.1f}, {:.1f})" 67 | : "({0:d}, {0:d}, {0:d})", 68 | vec.x, vec.y, vec.z); 69 | } 70 | }; 71 | 72 | template < typename T > 73 | struct fmt::formatter< glm::tvec2< T > > 74 | { 75 | constexpr auto 76 | parse(format_parse_context& ctx) 77 | { 78 | return ctx.begin(); 79 | } 80 | 81 | template < typename FormatContext > 82 | auto 83 | format(const glm::tvec2< T >& vec, FormatContext& ctx) const 84 | { 85 | return fmt::format_to(ctx.out(), 86 | std::is_same< T, float >::value ? "({:.1f}, {:.1f})" : "({0:d}, {0:d})", 87 | vec.x, vec.y); 88 | } 89 | }; 90 | -------------------------------------------------------------------------------- /src/app/input/input_manager.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "input_listener.hpp" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | struct GLFWwindow; 10 | 11 | namespace shady::app::input { 12 | 13 | struct Event; 14 | 15 | class InputManager 16 | { 17 | public: 18 | // Functions used by InputListener to register for input callbacks 19 | static void 20 | RegisterForKeyInput(InputListener* listener); 21 | 22 | static void 23 | RegisterForMouseButtonInput(InputListener* listener); 24 | 25 | static void 26 | RegisterForMouseMovementInput(InputListener* listener); 27 | 28 | static void 29 | RegisterForMouseScrollInput(InputListener* listener); 30 | 31 | // @brief Polling function to check if key is currenty pressed 32 | // @param keyKode Key in which user is interested 33 | // @return True if key is pressed, False otherwise 34 | static bool 35 | CheckKeyPressed(int32_t keyKode); 36 | 37 | // @brief Polling function to check if mouse button is currenty pressed 38 | // @param button is this button pressed 39 | // @return True if button is pressed, False otherwise 40 | static bool 41 | CheckButtonPressed(int32_t button); 42 | 43 | // @brief Polling function to get current mouse position 44 | // @return Mouse position relative to window 45 | static glm::vec2 46 | GetMousePos(); 47 | 48 | static void 49 | SetMousePos(const glm::vec2& position); 50 | 51 | // @brief Called each frame to update the input 52 | static void 53 | PollEvents(); 54 | 55 | // @brief Initialize function which should be called once at the start of the program 56 | // @param mainWindow GLFW window handle for which input will be handled 57 | static void 58 | Init(GLFWwindow* mainWindow); 59 | 60 | // callbacks for GLFW input 61 | static void 62 | InternalKeyCallback(GLFWwindow* window, int32_t key, int32_t scancode, int32_t action, 63 | int32_t mods); 64 | static void 65 | InternalMouseButtonCallback(GLFWwindow* window, int32_t button, int32_t action, int32_t mods); 66 | static void 67 | InternalCursorPositionCallback(GLFWwindow* window, double xpos, double ypos); 68 | static void 69 | InternalMouseScrollCallback(GLFWwindow* window, double xoffset, double yoffset); 70 | 71 | private: 72 | static void 73 | BroadcastEvent(const Event& event); 74 | 75 | private: 76 | static inline std::vector< InputListener* > s_keyListeners = {}; 77 | static inline std::vector< InputListener* > s_mouseButtonListeners = {}; 78 | static inline std::vector< InputListener* > s_mouseMovementListeners = {}; 79 | static inline std::vector< InputListener* > s_mouseScrollListeners = {}; 80 | 81 | // in future handle input from multiple windows? 82 | static inline GLFWwindow* s_windowHandle = nullptr; 83 | 84 | static inline glm::dvec2 s_mousePosition = {}; 85 | static inline std::unordered_map< int32_t, bool > s_mouseButtonMap = {}; 86 | static inline std::unordered_map< int32_t, bool > s_keyMap = {}; 87 | }; 88 | 89 | } // namespace shady::app::input 90 | -------------------------------------------------------------------------------- /src/utils/file_manager.cpp: -------------------------------------------------------------------------------- 1 | #include "file_manager.hpp" 2 | #include "trace/logger.hpp" 3 | #include "utils/assert.hpp" 4 | 5 | #define STB_IMAGE_STATIC 6 | #define STB_IMAGE_IMPLEMENTATION 7 | #include 8 | #include 9 | #include 10 | 11 | namespace shady::utils { 12 | 13 | auto static CreatePath(const std::filesystem::path& rootPath, std::string_view assetPath) 14 | { 15 | auto new_path = rootPath / ""; 16 | new_path += std::filesystem::path(assetPath); 17 | return new_path.string(); 18 | } 19 | 20 | std::string 21 | FileManager::ReadTextFile(const std::filesystem::path& path) 22 | { 23 | return ReadTextFile(std::string_view{path.string()}); 24 | } 25 | 26 | std::string 27 | FileManager::ReadTextFile(std::string_view fileName) 28 | { 29 | std::ifstream fileHandle(fileName.data()); 30 | 31 | utils::Assert(fileHandle.is_open(), 32 | fmt::format("FileManager::ReadTextFile -> {} can't be opened!", fileName)); 33 | 34 | std::string returnVal((std::istreambuf_iterator< char >(fileHandle)), 35 | std::istreambuf_iterator< char >()); 36 | fileHandle.close(); 37 | 38 | utils::Assert(!returnVal.empty(), 39 | fmt::format("FileManager::ReadTextFile -> {} is empty!", fileName)); 40 | 41 | return returnVal; 42 | } 43 | 44 | std::vector< char > 45 | FileManager::ReadBinaryFile(const std::filesystem::path& path) 46 | { 47 | return ReadBinaryFile(std::string_view{path.string()}); 48 | } 49 | 50 | std::vector< char > 51 | FileManager::ReadBinaryFile(std::string_view fileName) 52 | { 53 | std::ifstream fileHandle(fileName.data(), std::ios::binary); 54 | 55 | utils::Assert(fileHandle.is_open(), 56 | fmt::format("FileManager::ReadBinaryFile -> {} can't be opened!", fileName)); 57 | 58 | const auto size = std::filesystem::file_size(fileName); 59 | 60 | utils::Assert(size, fmt::format("FileManager::ReadBinaryFile -> {} is empty!", fileName)); 61 | 62 | std::vector< char > buffer(size); 63 | 64 | fileHandle.read(buffer.data(), static_cast< std::streamsize >(size)); 65 | 66 | return buffer; 67 | } 68 | 69 | void 70 | FileManager::WriteToFile(std::string_view fileName, std::string_view content) 71 | { 72 | std::ofstream fileHandle; 73 | fileHandle.open(fileName.data()); 74 | fileHandle << content; 75 | } 76 | 77 | render::ImageData 78 | FileManager::ReadTexture(std::string_view fileName, bool flipVertical) 79 | { 80 | const auto pathToImage = CreatePath(TEXTURES_DIR, fileName); 81 | const int force_channels = STBI_rgb_alpha; 82 | int w{}; 83 | int h{}; 84 | int n{}; 85 | 86 | stbi_set_flip_vertically_on_load(flipVertical); 87 | 88 | render::ImageHandleType textureData(stbi_load(pathToImage.c_str(), &w, &h, &n, force_channels), 89 | stbi_image_free); 90 | 91 | utils::Assert(textureData != nullptr, 92 | fmt::format("FileManager::LoadImage -> {} can't be opened!", pathToImage)); 93 | 94 | 95 | return {std::move(textureData), {w, h}, n}; 96 | } 97 | 98 | } // namespace shady::utils 99 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | Standard: Cpp11 4 | UseTab: Never 5 | ColumnLimit: 100 6 | IndentWidth: 3 7 | ContinuationIndentWidth: 3 8 | TabWidth: 3 9 | AccessModifierOffset: -2 10 | MaxEmptyLinesToKeep: 2 11 | DisableFormat: false 12 | 13 | AlignAfterOpenBracket: Align 14 | AlignConsecutiveDeclarations: false 15 | AlignConsecutiveAssignments: false 16 | AlignEscapedNewlinesLeft: true 17 | AlignOperands: true 18 | AlignTrailingComments: true 19 | 20 | BinPackArguments: true 21 | BinPackParameters: true 22 | AllowAllParametersOfDeclarationOnNextLine: false 23 | 24 | AlwaysBreakAfterDefinitionReturnType: None 25 | AlwaysBreakAfterReturnType: All 26 | 27 | BreakBeforeBraces: Custom 28 | BraceWrapping: 29 | AfterClass: true 30 | AfterControlStatement: true 31 | AfterEnum: true 32 | AfterFunction: true 33 | AfterNamespace: false 34 | AfterObjCDeclaration: true 35 | AfterStruct: true 36 | AfterUnion: true 37 | BeforeCatch: true 38 | BeforeElse: true 39 | IndentBraces: false 40 | 41 | AllowShortBlocksOnASingleLine: false 42 | AllowShortCaseLabelsOnASingleLine: false 43 | AllowShortFunctionsOnASingleLine: None 44 | AllowShortIfStatementsOnASingleLine: false 45 | AllowShortLoopsOnASingleLine: false 46 | KeepEmptyLinesAtTheStartOfBlocks: false 47 | 48 | BreakBeforeBinaryOperators: NonAssignment 49 | BreakBeforeTernaryOperators: true 50 | BreakConstructorInitializersBeforeComma: false 51 | BreakStringLiterals: true 52 | 53 | ConstructorInitializerAllOnOneLineOrOnePerLine: true 54 | ConstructorInitializerIndentWidth: 3 55 | 56 | Cpp11BracedListStyle: true 57 | 58 | IndentCaseLabels: true 59 | IndentWrappedFunctionNames: false 60 | NamespaceIndentation: None 61 | 62 | DerivePointerAlignment: false 63 | PointerAlignment: Left 64 | 65 | SpaceBeforeAssignmentOperators: true 66 | SpaceBeforeParens: ControlStatements 67 | SpaceInEmptyParentheses: false 68 | SpacesInParentheses: false 69 | SpacesInSquareBrackets: false 70 | SpacesInAngles: true 71 | 72 | SpacesBeforeTrailingComments: 1 73 | SpacesInContainerLiterals: true 74 | SpacesInCStyleCastParentheses: false 75 | 76 | ReflowComments: true 77 | 78 | AlwaysBreakBeforeMultilineStrings: false 79 | AlwaysBreakTemplateDeclarations: false 80 | 81 | SpaceAfterCStyleCast: false 82 | ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] 83 | ExperimentalAutoDetectBinPacking: false 84 | 85 | CommentPragmas: '^ IWYU pragma:' 86 | 87 | PenaltyBreakBeforeFirstCallParameter: 19 88 | PenaltyBreakComment: 300 89 | PenaltyBreakFirstLessLess: 120 90 | PenaltyBreakString: 1000 91 | PenaltyExcessCharacter: 1000000 92 | PenaltyReturnTypeOnItsOwnLine: 0 93 | 94 | ObjCBlockIndentWidth: 2 95 | ObjCSpaceAfterProperty: false 96 | ObjCSpaceBeforeProtocolList: true 97 | BreakAfterJavaFieldAnnotations: false 98 | 99 | MacroBlockBegin: '' 100 | MacroBlockEnd: '' -------------------------------------------------------------------------------- /src/render/texture.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "texture.hpp" 4 | #include "types.hpp" 5 | 6 | #include 7 | #include 8 | 9 | namespace shady::render { 10 | 11 | class Texture 12 | { 13 | public: 14 | Texture(TextureType type, std::string_view textureName); 15 | 16 | Texture() = default; 17 | 18 | void 19 | Destroy(); 20 | 21 | void 22 | CreateTextureImage(TextureType type, std::string_view textureName); 23 | 24 | static std::pair< VkImage, VkDeviceMemory > 25 | CreateImage(uint32_t width, uint32_t height, uint32_t mipLevels, 26 | VkSampleCountFlagBits numSamples, VkFormat format, VkImageTiling tiling, 27 | VkImageUsageFlags usage, VkMemoryPropertyFlags properties, bool cubemap = false); 28 | 29 | static void 30 | GenerateMipmaps(VkImage image, VkFormat imageFormat, int32_t texWidth, int32_t texHeight, 31 | uint32_t mipLevels); 32 | 33 | static VkImageView 34 | CreateImageView(VkImage image, VkFormat format, VkImageAspectFlags aspectFlags, 35 | uint32_t mipLevels, bool cubemap = false); 36 | 37 | static VkSampler 38 | CreateSampler(uint32_t mipLevels = 1); 39 | 40 | static void 41 | TransitionImageLayout(VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout, 42 | uint32_t mipLevels, bool cubemap = false); 43 | 44 | static void 45 | CopyBufferToImage(VkImage image, uint32_t texWidth, uint32_t texHeight, uint8_t* data); 46 | 47 | static void 48 | CopyBufferToCubemapImage(VkImage image, uint32_t texWidth, uint32_t texHeight, uint8_t* data); 49 | 50 | [[nodiscard]] std::pair< VkImageView, VkSampler > 51 | GetImageViewAndSampler() const; 52 | 53 | void 54 | CreateTextureSampler(); 55 | 56 | [[nodiscard]] TextureType 57 | GetType() const; 58 | 59 | private: 60 | void 61 | TransitionImageLayout(VkImageLayout oldLayout, VkImageLayout newLayout, uint32_t mipLevels); 62 | 63 | void 64 | CopyBufferToImage(uint8_t* data); 65 | 66 | private: 67 | TextureType m_type = {}; 68 | VkImage m_textureImage = {}; 69 | VkDeviceMemory m_textureImageMemory = {}; 70 | VkImageView m_textureImageView = {}; 71 | VkSampler m_textureSampler = {}; 72 | VkFormat m_format = {}; 73 | // int32_t m_channels = {}; 74 | uint32_t m_mips = {}; 75 | uint32_t m_width = {}; 76 | uint32_t m_height = {}; 77 | std::string m_name = "default_texture_name"; 78 | }; 79 | 80 | class TextureLibrary 81 | { 82 | public: 83 | static const Texture& 84 | GetTexture(TextureType type, const std::string& textureName); 85 | 86 | static const Texture& 87 | GetTexture(const std::string& textureName); 88 | 89 | static void 90 | CreateTexture(TextureType type, const std::string& textureName); 91 | 92 | static void 93 | Clear(); 94 | 95 | private: 96 | static void 97 | LoadTexture(TextureType type, std::string_view textureName); 98 | 99 | private: 100 | static inline std::unordered_map< std::string, Texture > s_loadedTextures = {}; 101 | }; 102 | 103 | } // namespace shady::render 104 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.22) 2 | 3 | set(PROJECT_NAME Shady) 4 | project(${PROJECT_NAME} VERSION 0.0.2) 5 | 6 | set(OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/build) 7 | 8 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${OUTPUT_PATH}) 9 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${OUTPUT_PATH}) 10 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${OUTPUT_PATH}) 11 | 12 | set(ASSETS_PATH ${CMAKE_CURRENT_SOURCE_DIR}/assets) 13 | set(SHADERS_PATH ${ASSETS_PATH}/shaders) 14 | 15 | 16 | add_definitions( -DCMAKE_ROOT_DIR="${CMAKE_CURRENT_SOURCE_DIR}" ) 17 | 18 | # Link this 'library' to use the warnings specified in CompilerWarnings.cmake 19 | add_library(project_warnings INTERFACE) 20 | 21 | include(cmake/compile_warnings.cmake) 22 | include(cmake/util_functions.cmake) 23 | set_target_warnings(project_warnings) 24 | 25 | add_executable(${PROJECT_NAME} 26 | # app 27 | src/app/window.hpp src/app/window.cpp src/app/main.cpp src/app/shady.hpp src/app/shady.cpp 28 | 29 | # app/input 30 | src/app/input/event.hpp src/app/input/input_manager.hpp src/app/input/input_manager.cpp src/app/input/input_listener.hpp 31 | 32 | # app/gui 33 | src/app/gui/gui.hpp src/app/gui/gui.cpp 34 | 35 | # trace 36 | src/trace/logger.hpp src/trace/logger.impl.hpp src/trace/logger.cpp src/trace/formatter_types.hpp 37 | 38 | # time 39 | src/time/timer.hpp src/time/timer.cpp src/time/scoped_timer.hpp src/time/scoped_timer.cpp src/time/utils.hpp src/time/utils.cpp 40 | 41 | # render/vulkan 42 | "src/render/renderer.hpp" "src/render/renderer.cpp" "src/render/shader.hpp" "src/render/shader.cpp" 43 | "src/render/buffer.hpp" "src/render/buffer.cpp" "src/render/texture.hpp" "src/render/texture.cpp" 44 | "src/render/command.hpp" "src/render/command.cpp" "src/render/common.hpp" "src/render/common.cpp" 45 | "src/render/vertex.hpp" "src/render/types.hpp" "src/render/framebuffer.hpp" "src/render/framebuffer.cpp" 46 | "src/render/deferred_pipeline.hpp" "src/render/deferred_pipeline.cpp" 47 | 48 | # scene 49 | src/scene/mesh.hpp src/scene/mesh.cpp src/scene/model.hpp src/scene/model.cpp src/scene/light.hpp src/scene/light.cpp 50 | src/scene/skybox.hpp src/scene/skybox.cpp src/scene/scene.hpp src/scene/scene.cpp 51 | src/scene/camera.hpp src/scene/camera.cpp src/scene/orthographic_camera.hpp src/scene/orthographic_camera.cpp 52 | src/scene/perspective_camera.hpp src/scene/perspective_camera.cpp 53 | 54 | # utils 55 | src/utils/file_manager.hpp src/utils/file_manager.cpp src/utils/assert.hpp src/utils/assert.cpp 56 | ) 57 | 58 | find_package(Vulkan REQUIRED) 59 | find_package(stb REQUIRED) 60 | find_package(fmt REQUIRED) 61 | find_package(glfw3 REQUIRED) 62 | find_package(imgui REQUIRED) 63 | find_package(glm REQUIRED) 64 | find_package(assimp REQUIRED) 65 | 66 | target_include_directories(${PROJECT_NAME} 67 | PRIVATE src src/app src/app/input src/trace src/render src/utils src/scene src/time) 68 | target_link_libraries_system (${PROJECT_NAME} PRIVATE stb::stb fmt::fmt glfw imgui::imgui glm::glm assimp::assimp Vulkan::Vulkan) 69 | target_link_libraries(${PROJECT_NAME} PRIVATE project_warnings) 70 | target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_20) 71 | 72 | # include(cmake/compile_shaders.cmake) 73 | # compile_shader(SOURCE_FILE "${SHADERS_PATH}/default/default.vert" OUTPUT_FILE_NAME "${SHADERS_PATH}/default/vert.spv") 74 | # compile_shader(SOURCE_FILE "${SHADERS_PATH}/default/default.frag" OUTPUT_FILE_NAME "${SHADERS_PATH}/default/frag.spv") 75 | 76 | -------------------------------------------------------------------------------- /src/render/deferred_pipeline.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "buffer.hpp" 4 | #include "framebuffer.hpp" 5 | #include "scene/skybox.hpp" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace shady::scene { 13 | class Light; 14 | class Camera; 15 | } // namespace shady::scene 16 | 17 | namespace shady::render { 18 | 19 | class DeferredPipeline 20 | { 21 | public: 22 | static void 23 | Initialize(VkRenderPass mainRenderPass, const std::vector< VkImageView >& swapChainImageViews, 24 | VkPipelineCache pipelineCache); 25 | 26 | static VkDescriptorSet& 27 | GetDescriptorSet(); 28 | 29 | static VkPipelineLayout 30 | GetPipelineLayout(); 31 | 32 | static VkPipeline 33 | GetCompositionPipeline(); 34 | 35 | static VkCommandBuffer& 36 | GetOffscreenCmdBuffer(); 37 | 38 | static VkSemaphore& 39 | GetOffscreenSemaphore(); 40 | 41 | static void 42 | UpdateDeferred(const scene::Camera* camera, const scene::Light* light); 43 | 44 | private: 45 | static void 46 | ShadowSetup(); 47 | 48 | // Prepare a new framebuffer and attachments for offscreen rendering (G-Buffer) 49 | static void 50 | PrepareOffscreenFramebuffer(); 51 | 52 | static void 53 | PrepareUniformBuffers(); 54 | 55 | static void 56 | SetupDescriptorSetLayout(); 57 | 58 | static void 59 | PreparePipelines(); 60 | 61 | static void 62 | SetupDescriptorPool(); 63 | 64 | static void 65 | SetupDescriptorSet(); 66 | 67 | static void 68 | BuildDeferredCommandBuffer(const std::vector< VkImageView >& swapChainImageViews); 69 | 70 | static void 71 | UpdateUniformBufferComposition(const scene::Camera* camera, const scene::Light* light); 72 | 73 | static void 74 | UpdateUniformBufferOffscreen(const scene::Camera* camera); 75 | 76 | inline static VkRenderPass m_mainRenderPass = {}; 77 | inline static VkPipeline m_graphicsPipeline = {}; 78 | 79 | inline static Framebuffer m_shadowMap = {}; 80 | inline static Framebuffer m_offscreenFrameBuffer = {}; 81 | inline static Framebuffer m_compositionFrameBuffer = {}; 82 | 83 | inline static VkPipelineCache m_pipelineCache = {}; 84 | inline static VkPipeline m_shadowMapPipeline = {}; 85 | inline static VkPipeline m_offscreenPipeline = {}; 86 | inline static VkPipeline m_compositionPipeline = {}; 87 | 88 | inline static VkPipelineLayout m_pipelineLayout = {}; 89 | inline static std::vector< VkDescriptorSet > m_descriptorSets = {}; 90 | inline static VkDescriptorSet m_descriptorSet = {}; 91 | inline static VkDescriptorSetLayout m_descriptorSetLayout = {}; 92 | inline static VkDescriptorPool m_descriptorPool = {}; 93 | 94 | inline static Buffer m_offscreenBuffer = {}; 95 | inline static Buffer m_compositionBuffer = {}; 96 | inline static VkDescriptorSet m_shadowMapDescriptor = {}; 97 | inline static int32_t m_debugDisplayTarget = 0; 98 | 99 | inline static VkSampler m_colorSampler = {}; 100 | 101 | inline static std::vector< VkCommandBuffer > m_commandBuffers = {}; 102 | inline static VkCommandBuffer m_offscreenCommandBuffer = {}; 103 | inline static VkSemaphore m_offscreenSemaphore = {}; 104 | 105 | inline static VkViewport m_viewport = {}; 106 | inline static scene::Skybox m_skybox = {}; 107 | }; 108 | 109 | } // namespace shady::render 110 | -------------------------------------------------------------------------------- /src/render/renderer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "deferred_pipeline.hpp" 4 | #include "vertex.hpp" 5 | #include "types.hpp" 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | struct GLFWwindow; 12 | 13 | namespace shady::render { 14 | 15 | class Renderer 16 | { 17 | public: 18 | static void 19 | Initialize(GLFWwindow* windowHandle); 20 | 21 | static void 22 | CreateRenderPipeline(); 23 | 24 | static void 25 | Draw(); 26 | 27 | static void 28 | MeshLoaded(const std::vector< Vertex >& vertices, 29 | const std::vector< uint32_t >& indicies, const TextureMaps& textures, 30 | const glm::mat4& modelMat); 31 | 32 | static void 33 | CreateCommandBufferForDeferred(); 34 | 35 | static void 36 | UpdateUniformBuffer(const scene::Camera* camera, const scene::Light* light); 37 | 38 | private: 39 | static void 40 | SetupData(); 41 | 42 | static void 43 | CreateInstance(); 44 | 45 | static void 46 | CreateDevice(); 47 | 48 | static void 49 | CreateSwapchain(GLFWwindow* windowHandle); 50 | 51 | static void 52 | CreateImageViews(); 53 | 54 | static void 55 | CreateRenderPass(); 56 | 57 | static void 58 | CreateCommandPool(); 59 | 60 | static void 61 | CreateFramebuffers(); 62 | 63 | static void 64 | CreateSyncObjects(); 65 | 66 | static void 67 | CreatePipelineCache(); 68 | 69 | static void 70 | CreateVertexBuffer(); 71 | 72 | static void 73 | CreateIndexBuffer(); 74 | 75 | static void 76 | CreateUniformBuffers(); 77 | 78 | static void 79 | CreateDepthResources(); 80 | 81 | static void 82 | CreateColorResources(); 83 | 84 | private: 85 | inline static VkDebugUtilsMessengerCreateInfoEXT m_debugCreateInfo = {}; 86 | inline static VkDebugUtilsMessengerEXT m_debugMessenger = {}; 87 | 88 | inline static VkSwapchainKHR m_swapChain = {}; 89 | inline static std::vector< VkImage > m_swapChainImages = {}; 90 | inline static std::vector< VkImageView > m_swapChainImageViews = {}; 91 | inline static std::vector< VkFramebuffer > m_swapChainFramebuffers = {}; 92 | inline static VkFormat m_swapChainImageFormat = {}; 93 | 94 | inline static VkDescriptorSetLayout m_descriptorSetLayout = {}; 95 | inline static VkDescriptorPool m_descriptorPool = {}; 96 | inline static std::vector< VkDescriptorSet > m_descriptorSets = {}; 97 | 98 | inline static VkPipelineLayout m_pipelineLayout = {}; 99 | 100 | inline static std::vector< VkCommandBuffer > m_commandBuffers = {}; 101 | 102 | inline static std::vector< VkSemaphore > m_imageAvailableSemaphores = {}; 103 | inline static std::vector< VkSemaphore > m_renderFinishedSemaphores = {}; 104 | inline static std::vector< VkFence > m_inFlightFences = {}; 105 | inline static std::vector< VkFence > m_imagesInFlight = {}; 106 | 107 | inline static VkImage m_depthImage = {}; 108 | inline static VkDeviceMemory m_depthImageMemory = {}; 109 | inline static VkImageView m_depthImageView = {}; 110 | 111 | inline static VkImage m_colorImage = {}; 112 | inline static VkDeviceMemory m_colorImageMemory = {}; 113 | inline static VkImageView m_colorImageView = {}; 114 | 115 | inline static DeferredPipeline m_deferredPipeline = {}; 116 | inline static uint32_t m_imageIndex = {}; 117 | }; 118 | 119 | } // namespace shady::render::vulkan 120 | -------------------------------------------------------------------------------- /src/app/window.cpp: -------------------------------------------------------------------------------- 1 | #include "window.hpp" 2 | #include "trace/logger.hpp" 3 | #include "utils/assert.hpp" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | 11 | namespace shady::app { 12 | 13 | Window::Window(int32_t width, int32_t height, const std::string& title) 14 | { 15 | Create(width, height, title); 16 | } 17 | 18 | Window::~Window() 19 | { 20 | glfwTerminate(); 21 | } 22 | 23 | void 24 | Window::Create(int32_t width, int32_t height, const std::string& title) 25 | { 26 | m_width = width; 27 | m_height = height; 28 | m_title = title; 29 | 30 | glfwSetErrorCallback([](int error, const char* description) { 31 | trace::Logger::Fatal("GLFW Error={}: {}", error, description); 32 | }); 33 | 34 | utils::Assert(glfwInit(), "GLFW Init failed!"); 35 | 36 | glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); 37 | glfwWindowHint(GLFW_VISIBLE, GL_TRUE); 38 | glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); 39 | 40 | m_pWindow = glfwCreateWindow(m_width, m_height, title.c_str(), nullptr, nullptr); 41 | 42 | utils::Assert(m_pWindow, "Failed to create GLFW window!"); 43 | 44 | trace::Logger::Info("GLFW Window created! Name:{} Width:{} Height:{}", m_title, m_width, 45 | m_height); 46 | 47 | m_created = true; 48 | } 49 | 50 | void 51 | Window::ShutDown() 52 | { 53 | glfwDestroyWindow(m_pWindow); 54 | } 55 | 56 | void 57 | Window::SetIcon(const std::string& /*file*/) 58 | { 59 | GLFWimage image; 60 | image.width = 16; 61 | image.height = 16; 62 | // image.pixels = TextureLibrary::GetTexture(file)->GetData(); 63 | 64 | auto* cursor = glfwCreateCursor(&image, 0, 0); 65 | glfwSetCursor(m_pWindow, cursor); 66 | } 67 | 68 | void 69 | Window::Resize(int32_t newWidth, int32_t newHeight) 70 | { 71 | glfwSetWindowSize(m_pWindow, newWidth, newHeight); 72 | 73 | m_height = newHeight; 74 | m_width = newWidth; 75 | } 76 | 77 | void 78 | Window::Clear() 79 | { 80 | // glfwMakeContextCurrent(m_pWindow); 81 | 82 | // render::RenderCommand::Clear(); 83 | } 84 | 85 | void 86 | Window::SwapBuffers() 87 | { 88 | // m_context->SwapBuffers(); 89 | } 90 | 91 | void 92 | Window::ShowCursor(bool choice) 93 | { 94 | const int mode = choice ? GLFW_CURSOR_NORMAL : GLFW_CURSOR_DISABLED; 95 | glfwSetInputMode(m_pWindow, GLFW_CURSOR, mode); 96 | } 97 | 98 | glm::vec2 99 | Window::GetCursorScreenPosition(const glm::mat4& /*projectionMatrix*/) 100 | { 101 | auto cursorPos = GetCursor(); 102 | 103 | cursorPos -= 104 | glm::vec2((static_cast< float >(m_width) / 2.0f), (static_cast< float >(m_height) / 2.0f)); 105 | // glm::vec2 tmpCursor = projectionMatrix * glm::vec4(cursorPos, 0.0f, 1.0f); 106 | 107 | return cursorPos; 108 | } 109 | 110 | glm::vec2 111 | Window::GetCursorNormalized() 112 | { 113 | auto cursorPos = GetCursor(); 114 | 115 | const glm::vec2 centerOfScreen(static_cast< float >(m_width) / 2.0f, 116 | static_cast< float >(m_height) / 2.0f); 117 | 118 | cursorPos -= centerOfScreen; 119 | cursorPos /= centerOfScreen; 120 | 121 | return cursorPos; 122 | } 123 | 124 | glm::vec2 125 | Window::GetCursor() 126 | { 127 | glm::dvec2 cursorPos; 128 | glfwGetCursorPos(m_pWindow, &cursorPos.x, &cursorPos.y); 129 | 130 | return cursorPos; 131 | } 132 | 133 | glm::ivec2 134 | Window::GetSize() const 135 | { 136 | return {m_width, m_height}; 137 | } 138 | 139 | GLFWwindow* 140 | Window::GetWindowHandle() 141 | { 142 | return m_pWindow; 143 | } 144 | 145 | } // namespace shady::app 146 | -------------------------------------------------------------------------------- /src/app/input/event.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace shady::app::input { 6 | 7 | struct Event 8 | { 9 | Event(const Event&) = default; 10 | Event(Event&&) = default; 11 | Event& operator=(const Event&) = default; 12 | Event& operator=(Event&&) = default; 13 | virtual ~Event() = default; 14 | 15 | enum class EventType 16 | { 17 | KEY, 18 | MOUSE_BUTTON, 19 | MOUSE_CURSOR, 20 | MOUSE_SCROLL 21 | }; 22 | 23 | explicit Event(EventType t) : type_(t) 24 | { 25 | } 26 | 27 | [[nodiscard]] EventType 28 | GetType() const 29 | { 30 | return type_; 31 | } 32 | 33 | [[nodiscard]] bool 34 | IsHandled() const 35 | { 36 | return handled_; 37 | } 38 | 39 | private: 40 | EventType type_; 41 | bool handled_ = false; 42 | }; 43 | 44 | struct KeyEvent : public Event 45 | { 46 | KeyEvent(int32_t key, int32_t scanCode, int32_t action, int32_t mods) 47 | : Event(EventType::KEY), key_(key), scanCode_(scanCode), action_(action), mods_(mods) 48 | { 49 | } 50 | 51 | [[nodiscard]] int32_t 52 | GetKey() const 53 | { 54 | return key_; 55 | } 56 | 57 | [[nodiscard]] int32_t 58 | GetScanCode() const 59 | { 60 | return scanCode_; 61 | } 62 | 63 | [[nodiscard]] int32_t 64 | GetAction() const 65 | { 66 | return action_; 67 | } 68 | 69 | [[nodiscard]] int32_t 70 | GetMods() const 71 | { 72 | return mods_; 73 | } 74 | 75 | private: 76 | int32_t key_; 77 | int32_t scanCode_; 78 | int32_t action_; 79 | int32_t mods_; 80 | }; 81 | 82 | struct MouseButtonEvent : public Event 83 | { 84 | MouseButtonEvent(int32_t button, int32_t action, int32_t mods) 85 | : Event(EventType::MOUSE_BUTTON), buttton_(button), action_(action), mods_(mods) 86 | { 87 | } 88 | 89 | [[nodiscard]] int32_t 90 | GetButton() const 91 | { 92 | return buttton_; 93 | } 94 | 95 | [[nodiscard]] int32_t 96 | GetAction() const 97 | { 98 | return action_; 99 | } 100 | 101 | [[nodiscard]] int32_t 102 | GetMods() const 103 | { 104 | return mods_; 105 | } 106 | 107 | private: 108 | int32_t buttton_; 109 | int32_t action_; 110 | int32_t mods_; 111 | }; 112 | 113 | struct CursorPositionEvent : public Event 114 | { 115 | CursorPositionEvent(double x, double y, double xDelta, double yDelta) 116 | : Event(EventType::MOUSE_CURSOR), xPos_(x), yPos_(y), xDelta_(xDelta), yDelta_(yDelta) 117 | { 118 | } 119 | 120 | [[nodiscard]] double 121 | GetXPos() const 122 | { 123 | return xPos_; 124 | } 125 | 126 | [[nodiscard]] double 127 | GetYPos() const 128 | { 129 | return yPos_; 130 | } 131 | 132 | [[nodiscard]] double 133 | GetXDelta() const 134 | { 135 | return xDelta_; 136 | } 137 | 138 | [[nodiscard]] double 139 | GetYDelta() const 140 | { 141 | return yDelta_; 142 | } 143 | 144 | private: 145 | double xPos_; 146 | double yPos_; 147 | double xDelta_; 148 | double yDelta_; 149 | }; 150 | 151 | struct MouseScrollEvent : public Event 152 | { 153 | MouseScrollEvent(double xOffset, double yOffset) 154 | : Event(EventType::MOUSE_SCROLL), xOffset_(xOffset), yOffset_(yOffset) 155 | { 156 | } 157 | 158 | [[nodiscard]] double 159 | GetXOffset() const 160 | { 161 | return xOffset_; 162 | } 163 | 164 | [[nodiscard]] double 165 | GetYOffset() const 166 | { 167 | return yOffset_; 168 | } 169 | 170 | private: 171 | double xOffset_; 172 | double yOffset_; 173 | }; 174 | 175 | } // namespace shady::app::input 176 | -------------------------------------------------------------------------------- /src/render/common.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "scene/camera.hpp" 4 | #include "scene/light.hpp" 5 | #include "types.hpp" 6 | #include "utils/assert.hpp" 7 | #include "vertex.hpp" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | 20 | namespace shady::render { 21 | 22 | // This should make use of when it's supported by clang/mvcc 23 | constexpr void 24 | VK_CHECK(VkResult result, std::string_view errorMessage) 25 | { 26 | if (result != VK_SUCCESS) 27 | { 28 | utils::Assert(false, 29 | fmt::format("{} Return value {}", errorMessage, string_VkResult(result))); 30 | } 31 | } 32 | 33 | static constexpr bool ENABLE_VALIDATION = true; 34 | static constexpr std::array< const char*, 1 > VALIDATION_LAYERS = {"VK_LAYER_KHRONOS_validation"}; 35 | static constexpr std::array< const char*, 1 > DEVICE_EXTENSIONS = {VK_KHR_SWAPCHAIN_EXTENSION_NAME}; 36 | 37 | /* 38 | * This is storage for common Vulkan objects that are needed for numerous 39 | * function calls. All these fields are assigned by Renderer on Init 40 | * and should only be read from other modules. 41 | */ 42 | struct Data 43 | { 44 | inline static VkInstance vk_instance = {}; 45 | inline static VkDevice vk_device = {}; 46 | inline static VkPhysicalDevice vk_physicalDevice = VK_NULL_HANDLE; 47 | inline static VkQueue vk_graphicsQueue = {}; 48 | inline static VkQueue m_presentQueue = {}; 49 | inline static VkExtent2D m_swapChainExtent = {}; 50 | inline static VkExtent2D m_deferredExtent = {}; 51 | inline static VkCommandPool vk_commandPool = {}; 52 | inline static VkSurfaceKHR m_surface = {}; 53 | 54 | inline static VkSampleCountFlagBits m_msaaSamples = VK_SAMPLE_COUNT_1_BIT; 55 | 56 | inline static std::vector< VkDrawIndexedIndirectCommand > m_renderCommands = {}; 57 | inline static VkBuffer m_indirectDrawsBuffer = {}; 58 | inline static VkDeviceMemory m_indirectDrawsBufferMemory = {}; 59 | inline static uint32_t m_currentVertex = {}; 60 | inline static uint32_t m_currentIndex = {}; 61 | inline static uint32_t m_numMeshes = {}; 62 | 63 | inline static std::vector< VkBuffer > m_ssbo = {}; 64 | inline static std::vector< VkDeviceMemory > m_ssboMemory = {}; 65 | 66 | inline static std::vector< VkBuffer > m_uniformBuffers = {}; 67 | inline static std::vector< VkDeviceMemory > m_uniformBuffersMemory = {}; 68 | 69 | inline static VkBuffer m_vertexBuffer = {}; 70 | inline static VkDeviceMemory m_vertexBufferMemory = {}; 71 | inline static VkBuffer m_indexBuffer = {}; 72 | inline static VkDeviceMemory m_indexBufferMemory = {}; 73 | 74 | inline static std::vector< PerInstanceBuffer > perInstance; 75 | inline static std::vector< Vertex > vertices; 76 | inline static std::vector< uint32_t > indices; 77 | inline static int32_t currTexIdx = 0; 78 | inline static std::unordered_map< std::string, std::pair< int32_t, VkImageView > > textures = {}; 79 | inline static std::vector< VkImageView > texturesVec = {}; 80 | 81 | inline static VkPipelineCache m_pipelineCache = {}; 82 | inline static VkPipeline m_graphicsPipeline = {}; 83 | inline static VkRenderPass m_renderPass = {}; 84 | inline static VkRenderPass m_deferredRenderPass = {}; 85 | 86 | inline static DebugData m_debugData = {}; 87 | }; 88 | 89 | uint32_t 90 | FindMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties); 91 | 92 | VkFormat 93 | FindSupportedFormat(const std::vector< VkFormat >& candidates, VkImageTiling tiling, 94 | VkFormatFeatureFlags features); 95 | 96 | VkFormat 97 | FindDepthFormat(); 98 | 99 | } // namespace shady::render 100 | -------------------------------------------------------------------------------- /src/app/shady.cpp: -------------------------------------------------------------------------------- 1 | #include "app/shady.hpp" 2 | #include "app/input/input_manager.hpp" 3 | #include "gui/gui.hpp" 4 | #include "scene/light.hpp" 5 | #include "scene/perspective_camera.hpp" 6 | #include "trace/logger.hpp" 7 | 8 | #include "render/renderer.hpp" 9 | #include 10 | 11 | namespace shady::app { 12 | 13 | void 14 | Shady::Init() 15 | { 16 | m_window.Create(m_windowWidth, m_windowHeight, "Shady"); 17 | 18 | input::InputManager::Init(m_window.GetWindowHandle()); 19 | input::InputManager::RegisterForKeyInput(this); 20 | input::InputManager::RegisterForMouseButtonInput(this); 21 | input::InputManager::RegisterForMouseMovementInput(this); 22 | input::InputManager::RegisterForMouseScrollInput(this); 23 | 24 | render::Renderer::Initialize(m_window.GetWindowHandle()); 25 | 26 | m_currentScene.LoadDefault(); 27 | 28 | render::Renderer::CreateRenderPipeline(); 29 | } 30 | 31 | void 32 | Shady::MainLoop() 33 | { 34 | while (m_active) 35 | { 36 | m_window.Clear(); 37 | 38 | input::InputManager::PollEvents(); 39 | 40 | // Check if GUI captures the input. This could be moved into some kind 41 | // of input layer stack, but since we only have UI and application, 42 | // there's no need for that 43 | if (!app::gui::Gui::UpdateUI({m_windowWidth, m_windowHeight}, m_currentScene)) 44 | { 45 | OnUpdate(); 46 | } 47 | 48 | m_currentScene.Render(m_windowWidth, m_windowHeight); 49 | 50 | m_window.SwapBuffers(); 51 | } 52 | } 53 | 54 | void 55 | Shady::OnUpdate() 56 | { 57 | auto& camera = m_currentScene.GetCamera(); 58 | auto& light = m_currentScene.GetLight(); 59 | 60 | constexpr auto cameraMoveBy = 0.05f; 61 | constexpr auto lightMoveBy = 0.02f; 62 | 63 | /* 64 | * Camera movement 65 | */ 66 | if (input::InputManager::CheckKeyPressed(GLFW_KEY_W)) 67 | { 68 | camera.MoveCamera({0.0f, cameraMoveBy}); 69 | } 70 | if (input::InputManager::CheckKeyPressed(GLFW_KEY_S)) 71 | { 72 | camera.MoveCamera({0.0f, -cameraMoveBy}); 73 | } 74 | if (input::InputManager::CheckKeyPressed(GLFW_KEY_A)) 75 | { 76 | camera.MoveCamera({-cameraMoveBy, 0.0f}); 77 | } 78 | if (input::InputManager::CheckKeyPressed(GLFW_KEY_D)) 79 | { 80 | camera.MoveCamera({cameraMoveBy, 0.0f}); 81 | } 82 | 83 | /* 84 | * Light movement 85 | */ 86 | if (input::InputManager::CheckKeyPressed(GLFW_KEY_LEFT)) 87 | { 88 | light.MoveBy({lightMoveBy, 0.0f, 0.0f}); 89 | } 90 | if (input::InputManager::CheckKeyPressed(GLFW_KEY_UP)) 91 | { 92 | light.MoveBy({0.0f, -lightMoveBy, 0.0f}); 93 | } 94 | if (input::InputManager::CheckKeyPressed(GLFW_KEY_DOWN)) 95 | { 96 | light.MoveBy({0.0f, lightMoveBy, 0.0f}); 97 | } 98 | if (input::InputManager::CheckKeyPressed(GLFW_KEY_RIGHT)) 99 | { 100 | light.MoveBy({-lightMoveBy, 0.0f, 0.0f}); 101 | } 102 | 103 | if (input::InputManager::CheckKeyPressed(GLFW_KEY_R)) 104 | { 105 | camera.SetView(light.GetViewMat()); 106 | } 107 | if (input::InputManager::CheckKeyPressed(GLFW_KEY_T)) 108 | { 109 | camera.SetViewProjection(light.GetLightSpaceMat()); 110 | } 111 | } 112 | 113 | void 114 | Shady::KeyCallback(const input::KeyEvent& event) 115 | { 116 | switch (event.GetKey()) 117 | { 118 | case GLFW_KEY_ESCAPE: { 119 | m_active = false; 120 | } 121 | break; 122 | } 123 | } 124 | 125 | void 126 | Shady::MouseButtonCallback(const input::MouseButtonEvent& /*event*/) 127 | { 128 | } 129 | 130 | void 131 | Shady::CursorPositionCallback(const input::CursorPositionEvent& event) 132 | { 133 | if (input::InputManager::CheckButtonPressed(GLFW_MOUSE_BUTTON_LEFT) 134 | and !app::gui::Gui::UpdateUI({m_windowWidth, m_windowHeight}, m_currentScene)) 135 | { 136 | m_currentScene.GetCamera().MouseMovement({event.GetXDelta(), event.GetYDelta()}); 137 | } 138 | } 139 | 140 | void 141 | Shady::MouseScrollCallback(const input::MouseScrollEvent& /*event*/) 142 | { 143 | } 144 | 145 | } // namespace shady::app 146 | -------------------------------------------------------------------------------- /cmake/compile_warnings.cmake: -------------------------------------------------------------------------------- 1 | # from here: 2 | # 3 | # https://github.com/lefticus/cppbestpractices/blob/master/02-Use_the_Tools_Available.md 4 | 5 | function(set_target_warnings target_name) 6 | option(WARNINGS_AS_ERRORS "Treat compiler warnings as errors" OFF) 7 | 8 | set(MSVC_WARNINGS 9 | /W4 # Baseline reasonable warnings 10 | /w14242 # 'identifier': conversion from 'type1' to 'type1', possible loss of data 11 | /w14254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data 12 | /w14263 # 'function': member function does not override any base class virtual member function 13 | /w14265 # 'classname': class has virtual functions, but destructor is not virtual instances of this class may not 14 | # be destructed correctly 15 | /w14287 # 'operator': unsigned/negative constant mismatch 16 | /we4289 # nonstandard extension used: 'variable': loop control variable declared in the for-loop is used outside 17 | # the for-loop scope 18 | /w14296 # 'operator': expression is always 'boolean_value' 19 | /w14311 # 'variable': pointer truncation from 'type1' to 'type2' 20 | /w14545 # expression before comma evaluates to a function which is missing an argument list 21 | /w14546 # function call before comma missing argument list 22 | /w14547 # 'operator': operator before comma has no effect; expected operator with side-effect 23 | /w14549 # 'operator': operator before comma has no effect; did you intend 'operator'? 24 | /w14555 # expression has no effect; expected expression with side- effect 25 | /w14619 # pragma warning: there is no warning number 'number' 26 | /w14640 # Enable warning on thread un-safe static member initialization 27 | /w14826 # Conversion from 'type1' to 'type_2' is sign-extended. This may cause unexpected runtime behavior. 28 | /w14905 # wide string literal cast to 'LPSTR' 29 | /w14906 # string literal cast to 'LPWSTR' 30 | /w14928 # illegal copy-initialization; more than one user-defined conversion has been implicitly applied 31 | /permissive- # standards conformance mode for MSVC compiler. 32 | ) 33 | 34 | set(CLANG_WARNINGS 35 | -Wall 36 | -Wextra # reasonable and standard 37 | -Wshadow # warn the user if a variable declaration shadows one from a parent context 38 | -Wnon-virtual-dtor # warn the user if a class with virtual functions has a non-virtual destructor. This helps 39 | # catch hard to track down memory errors 40 | -Wold-style-cast # warn for c-style casts 41 | -Wcast-align # warn for potential performance problem casts 42 | -Wunused # warn on anything being unused 43 | -Woverloaded-virtual # warn if you overload (not override) a virtual function 44 | -Wpedantic # warn if non-standard C++ is used 45 | -Wconversion # warn on type conversions that may lose data 46 | -Wsign-conversion # warn on sign conversions 47 | -Wnull-dereference # warn if a null dereference is detected 48 | -Wdouble-promotion # warn if float is implicit promoted to double 49 | -Wformat=2 # warn on security issues around functions that format output (ie printf) 50 | ) 51 | 52 | if(WARNINGS_AS_ERRORS) 53 | set(CLANG_WARNINGS ${CLANG_WARNINGS} -Werror) 54 | set(MSVC_WARNINGS ${MSVC_WARNINGS} /WX) 55 | endif() 56 | 57 | set(GCC_WARNINGS 58 | ${CLANG_WARNINGS} 59 | -Wmisleading-indentation # warn if indentation implies blocks where blocks do not exist 60 | -Wduplicated-cond # warn if if / else chain has duplicated conditions 61 | -Wduplicated-branches # warn if if / else branches have duplicated code 62 | -Wlogical-op # warn about logical operations being used where bitwise were probably wanted 63 | -Wuseless-cast # warn if you perform a cast to the same type 64 | ) 65 | 66 | if(MSVC) 67 | set(TARGET_WARNINGS ${MSVC_WARNINGS}) 68 | elseif(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") 69 | set(TARGET_WARNINGS ${CLANG_WARNINGS}) 70 | elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 71 | set(TARGET_WARNINGS ${GCC_WARNINGS}) 72 | else() 73 | message(AUTHOR_WARNING "No compiler warnings set for '${CMAKE_CXX_COMPILER_ID}' compiler.") 74 | endif() 75 | 76 | target_compile_options(${target_name} INTERFACE ${TARGET_WARNINGS}) 77 | 78 | endfunction() 79 | -------------------------------------------------------------------------------- /src/render/framebuffer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | 9 | namespace shady::render { 10 | 11 | /** 12 | * @brief Encapsulates a single frame buffer attachment 13 | */ 14 | struct FramebufferAttachment 15 | { 16 | /** 17 | * @brief Returns true if the attachment has a depth component 18 | */ 19 | [[nodiscard]] bool 20 | hasDepth() const 21 | { 22 | std::vector< VkFormat > formats = { 23 | VK_FORMAT_D16_UNORM, VK_FORMAT_X8_D24_UNORM_PACK32, VK_FORMAT_D32_SFLOAT, 24 | VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT, 25 | }; 26 | return std::find(formats.begin(), formats.end(), format_) != std::end(formats); 27 | } 28 | 29 | /** 30 | * @brief Returns true if the attachment has a stencil component 31 | */ 32 | [[nodiscard]] bool 33 | hasStencil() const 34 | { 35 | std::vector< VkFormat > formats = { 36 | VK_FORMAT_S8_UINT, 37 | VK_FORMAT_D16_UNORM_S8_UINT, 38 | VK_FORMAT_D24_UNORM_S8_UINT, 39 | VK_FORMAT_D32_SFLOAT_S8_UINT, 40 | }; 41 | return std::find(formats.begin(), formats.end(), format_) != std::end(formats); 42 | } 43 | 44 | /** 45 | * @brief Returns true if the attachment is a depth and/or stencil attachment 46 | */ 47 | [[nodiscard]] bool 48 | isDepthStencil() const 49 | { 50 | return (hasDepth() || hasStencil()); 51 | } 52 | 53 | public: 54 | VkImage image_ = {}; 55 | VkDeviceMemory memory_ = {}; 56 | VkImageView view_ = {}; 57 | VkFormat format_ = {}; 58 | VkImageSubresourceRange subresourceRange_ = {}; 59 | VkAttachmentDescription description_ = {}; 60 | }; 61 | 62 | /** 63 | * @brief Describes the attributes of an attachment to be created 64 | */ 65 | struct AttachmentCreateInfo 66 | { 67 | uint32_t width_ = {}; 68 | uint32_t height_ = {}; 69 | uint32_t layerCount_ = {}; 70 | VkFormat format_ = {}; 71 | VkImageUsageFlags usage_ = {}; 72 | VkSampleCountFlagBits imageSampleCount_ = VK_SAMPLE_COUNT_1_BIT; 73 | }; 74 | 75 | class Framebuffer 76 | { 77 | public: 78 | void 79 | Create(int32_t width, int32_t height); 80 | 81 | void 82 | CreateShadowMap(int32_t width, int32_t height, int32_t numLights); 83 | 84 | [[nodiscard]] glm::ivec2 85 | GetSize() const; 86 | 87 | [[nodiscard]] VkRenderPass 88 | GetRenderPass() const; 89 | 90 | [[nodiscard]] VkFramebuffer 91 | GetFramebuffer() const; 92 | 93 | [[nodiscard]] VkImageView 94 | GetPositionsImageView() const; 95 | 96 | [[nodiscard]] VkImageView 97 | GetNormalsImageView() const; 98 | 99 | [[nodiscard]] VkImageView 100 | GetAlbedoImageView() const; 101 | 102 | [[nodiscard]] VkImageView 103 | GetShadowMapView() const; 104 | 105 | [[nodiscard]] VkSampler 106 | GetSampler() const; 107 | 108 | private: 109 | /** 110 | * Creates a default render pass setup with one sub pass 111 | */ 112 | void 113 | CreateRenderPass(); 114 | 115 | /** 116 | * Add a new attachment described by createinfo to the framebuffer's attachment list 117 | * 118 | * @param createinfo Structure that specifies the framebuffer to be constructed 119 | * 120 | * @return Index of the new attachment 121 | */ 122 | uint32_t 123 | AddAttachment(AttachmentCreateInfo createinfo); 124 | 125 | void 126 | CreateAttachment(VkFormat format, VkImageUsageFlagBits usage, FramebufferAttachment* attachment); 127 | 128 | /** 129 | * Creates a default sampler for sampling from any of the framebuffer attachments 130 | * Applications are free to create their own samplers for different use cases 131 | * 132 | * @param magFilter Magnification filter for lookups 133 | * @param minFilter Minification filter for lookups 134 | * @param adressMode Addressing mode for the U,V and W coordinates 135 | * 136 | * @return VkResult for the sampler creation 137 | */ 138 | static VkSampler 139 | CreateSampler(VkFilter magFilter, VkFilter minFilter, VkSamplerAddressMode adressMode); 140 | 141 | private: 142 | int32_t m_width = {}; 143 | int32_t m_height = {}; 144 | VkFramebuffer m_framebuffer = {}; 145 | std::vector< FramebufferAttachment > m_attachments = {}; 146 | VkRenderPass m_renderPass = {}; 147 | VkSampler m_sampler = {}; 148 | }; 149 | 150 | } // namespace shady::render 151 | -------------------------------------------------------------------------------- /src/app/input/input_manager.cpp: -------------------------------------------------------------------------------- 1 | #include "input_manager.hpp" 2 | #include "event.hpp" 3 | #include "trace/logger.hpp" 4 | 5 | #include 6 | #include 7 | 8 | namespace shady::app::input { 9 | 10 | void 11 | InputManager::InternalKeyCallback(GLFWwindow* /* window */, int32_t key, int32_t scancode, int32_t action, 12 | int32_t mods) 13 | { 14 | trace::Logger::Trace("GLFW key {} {} scan code - {}", action, key, scancode); 15 | 16 | s_keyMap[key] = action; 17 | 18 | BroadcastEvent(KeyEvent{key, scancode, action, mods}); 19 | } 20 | 21 | void 22 | InputManager::InternalMouseButtonCallback(GLFWwindow* /* window */, int32_t button, int32_t action, 23 | int32_t mods) 24 | { 25 | trace::Logger::Trace("GLFW mouse button {} {} {}", button, action, mods); 26 | s_mouseButtonMap[button] = action; 27 | 28 | BroadcastEvent(MouseButtonEvent{button, action, mods}); 29 | } 30 | 31 | void 32 | InputManager::InternalCursorPositionCallback(GLFWwindow* /* window */, double xpos, double ypos) 33 | { 34 | trace::Logger::Trace("GLFW cursor pos {} {}", xpos, ypos); 35 | 36 | auto deltaPosition = glm::dvec2(xpos, ypos) - s_mousePosition; 37 | s_mousePosition = glm::dvec2(xpos, ypos); 38 | 39 | BroadcastEvent(CursorPositionEvent{xpos, ypos, deltaPosition.x, deltaPosition.y}); 40 | } 41 | 42 | void 43 | InputManager::InternalMouseScrollCallback(GLFWwindow* /* window */, double xoffset, double yoffset) 44 | { 45 | trace::Logger::Trace("GLFW scroll {} {}", xoffset, yoffset); 46 | 47 | BroadcastEvent(MouseScrollEvent{xoffset, yoffset}); 48 | } 49 | 50 | void 51 | InputManager::BroadcastEvent(const Event& event) 52 | { 53 | switch (event.GetType()) 54 | { 55 | case Event::EventType::KEY: { 56 | for (auto* listener : s_keyListeners) 57 | { 58 | listener->KeyCallback(dynamic_cast< const KeyEvent& >(event)); 59 | } 60 | } 61 | break; 62 | 63 | case Event::EventType::MOUSE_BUTTON: { 64 | for (auto* listener : s_mouseButtonListeners) 65 | { 66 | listener->MouseButtonCallback(dynamic_cast< const MouseButtonEvent& >(event)); 67 | } 68 | } 69 | break; 70 | 71 | case Event::EventType::MOUSE_CURSOR: { 72 | for (auto* listener : s_mouseMovementListeners) 73 | { 74 | listener->CursorPositionCallback(dynamic_cast< const CursorPositionEvent& >(event)); 75 | } 76 | } 77 | break; 78 | 79 | case Event::EventType::MOUSE_SCROLL: { 80 | for (auto* listener : s_mouseScrollListeners) 81 | { 82 | listener->MouseScrollCallback(dynamic_cast< const MouseScrollEvent& >(event)); 83 | } 84 | } 85 | break; 86 | 87 | default: 88 | break; 89 | } 90 | } 91 | 92 | void 93 | InputManager::Init(GLFWwindow* mainWindow) 94 | { 95 | s_windowHandle = mainWindow; 96 | glfwGetCursorPos(s_windowHandle, &s_mousePosition.x, &s_mousePosition.y); 97 | 98 | glfwSetKeyCallback(s_windowHandle, InternalKeyCallback); 99 | glfwSetMouseButtonCallback(s_windowHandle, InternalMouseButtonCallback); 100 | glfwSetCursorPosCallback(s_windowHandle, InternalCursorPositionCallback); 101 | glfwSetScrollCallback(s_windowHandle, InternalMouseScrollCallback); 102 | 103 | s_keyMap.clear(); 104 | } 105 | 106 | void 107 | InputManager::RegisterForKeyInput(InputListener* listener) 108 | { 109 | s_keyListeners.push_back(listener); 110 | } 111 | 112 | void 113 | InputManager::RegisterForMouseButtonInput(InputListener* listener) 114 | { 115 | s_mouseButtonListeners.push_back(listener); 116 | } 117 | 118 | void 119 | InputManager::RegisterForMouseMovementInput(InputListener* listener) 120 | { 121 | s_mouseMovementListeners.push_back(listener); 122 | } 123 | 124 | void 125 | InputManager::RegisterForMouseScrollInput(InputListener* listener) 126 | { 127 | s_mouseScrollListeners.push_back(listener); 128 | } 129 | 130 | void 131 | InputManager::PollEvents() 132 | { 133 | glfwPollEvents(); 134 | } 135 | 136 | bool 137 | InputManager::CheckButtonPressed(int32_t button) 138 | { 139 | return s_mouseButtonMap[button]; 140 | } 141 | 142 | bool 143 | InputManager::CheckKeyPressed(int32_t keyKode) 144 | { 145 | return s_keyMap[keyKode]; 146 | } 147 | 148 | glm::vec2 149 | InputManager::GetMousePos() 150 | { 151 | return s_mousePosition; 152 | } 153 | 154 | void 155 | InputManager::SetMousePos(const glm::vec2& position) 156 | { 157 | glfwSetCursorPos(s_windowHandle, static_cast< double >(position.x), 158 | static_cast< double >(position.y)); 159 | } 160 | 161 | } // namespace shady::app::input 162 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/windows,visualstudio,c++ 3 | 4 | ### Windows ### 5 | # Windows image file caches 6 | Thumbs.db 7 | ehthumbs.db 8 | 9 | # Folder config file 10 | Desktop.ini 11 | 12 | # Recycle Bin used on file shares 13 | $RECYCLE.BIN/ 14 | 15 | # Windows Installer files 16 | *.cab 17 | *.msi 18 | *.msm 19 | *.msp 20 | 21 | # Windows shortcuts 22 | *.lnk 23 | 24 | 25 | ### VisualStudio ### 26 | ## Ignore Visual Studio temporary files, build results, and 27 | ## files generated by popular Visual Studio add-ons. 28 | 29 | # User-specific files 30 | *.suo 31 | *.user 32 | *.userosscache 33 | *.sln.docstates 34 | 35 | # User-specific files (MonoDevelop/Xamarin Studio) 36 | *.userprefs 37 | 38 | # Build results 39 | [Dd]ebug/ 40 | [Dd]ebugPublic/ 41 | [Rr]elease/ 42 | [Rr]eleases/ 43 | x64/ 44 | x86/ 45 | bld/ 46 | [Bb]in/ 47 | [Oo]bj/ 48 | [Ll]og/ 49 | 50 | # Visual Studio 2015 cache/options directory 51 | .vs/ 52 | # Uncomment if you have tasks that create the project's static files in wwwroot 53 | #wwwroot/ 54 | 55 | # MSTest test Results 56 | [Tt]est[Rr]esult*/ 57 | [Bb]uild[Ll]og.* 58 | 59 | # NUNIT 60 | *.VisualState.xml 61 | TestResult.xml 62 | 63 | # Build Results of an ATL Project 64 | [Dd]ebugPS/ 65 | [Rr]eleasePS/ 66 | dlldata.c 67 | 68 | # DNX 69 | project.lock.json 70 | artifacts/ 71 | 72 | *_i.c 73 | *_p.c 74 | *_i.h 75 | *.ilk 76 | *.meta 77 | *.pch 78 | *.pdb 79 | *.pgc 80 | *.pgd 81 | *.rsp 82 | *.sbr 83 | *.tlb 84 | *.tli 85 | *.tlh 86 | *.tmp 87 | *.tmp_proj 88 | *.log 89 | *.vspscc 90 | *.vssscc 91 | .builds 92 | *.pidb 93 | *.svclog 94 | *.scc 95 | 96 | # Chutzpah Test files 97 | _Chutzpah* 98 | 99 | # Visual C++ cache files 100 | ipch/ 101 | *.aps 102 | *.ncb 103 | *.opendb 104 | *.opensdf 105 | *.sdf 106 | *.cachefile 107 | *.VC.db 108 | *.VC.VC.opendb 109 | 110 | # Visual Studio profiler 111 | *.psess 112 | *.vsp 113 | *.vspx 114 | *.sap 115 | 116 | # TFS 2012 Local Workspace 117 | $tf/ 118 | 119 | # Guidance Automation Toolkit 120 | *.gpState 121 | 122 | # ReSharper is a .NET coding add-in 123 | _ReSharper*/ 124 | *.[Rr]e[Ss]harper 125 | *.DotSettings.user 126 | 127 | # JustCode is a .NET coding add-in 128 | .JustCode 129 | 130 | # TeamCity is a build add-in 131 | _TeamCity* 132 | 133 | # DotCover is a Code Coverage Tool 134 | *.dotCover 135 | 136 | # NCrunch 137 | _NCrunch_* 138 | .*crunch*.local.xml 139 | nCrunchTemp_* 140 | 141 | # MightyMoose 142 | *.mm.* 143 | AutoTest.Net/ 144 | 145 | # Web workbench (sass) 146 | .sass-cache/ 147 | 148 | # Installshield output folder 149 | [Ee]xpress/ 150 | 151 | # DocProject is a documentation generator add-in 152 | DocProject/buildhelp/ 153 | DocProject/Help/*.HxT 154 | DocProject/Help/*.HxC 155 | DocProject/Help/*.hhc 156 | DocProject/Help/*.hhk 157 | DocProject/Help/*.hhp 158 | DocProject/Help/Html2 159 | DocProject/Help/html 160 | 161 | # Click-Once directory 162 | publish/ 163 | 164 | # Publish Web Output 165 | *.[Pp]ublish.xml 166 | *.azurePubxml 167 | # TODO: Comment the next line if you want to checkin your web deploy settings 168 | # but database connection strings (with potential passwords) will be unencrypted 169 | *.pubxml 170 | *.publishproj 171 | 172 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 173 | # checkin your Azure Web App publish settings, but sensitive information contained 174 | # in these scripts will be unencrypted 175 | PublishScripts/ 176 | 177 | # NuGet Packages 178 | *.nupkg 179 | # The packages folder can be ignored because of Package Restore 180 | **/packages/* 181 | # except build/, which is used as an MSBuild target. 182 | !**/packages/build/ 183 | # Uncomment if necessary however generally it will be regenerated when needed 184 | #!**/packages/repositories.config 185 | # NuGet v3's project.json files produces more ignoreable files 186 | *.nuget.props 187 | *.nuget.targets 188 | 189 | # Microsoft Azure Build Output 190 | csx/ 191 | *.build.csdef 192 | 193 | # Microsoft Azure Emulator 194 | ecf/ 195 | rcf/ 196 | 197 | # Windows Store app package directories and files 198 | AppPackages/ 199 | BundleArtifacts/ 200 | Package.StoreAssociation.xml 201 | _pkginfo.txt 202 | 203 | # Visual Studio cache files 204 | # files ending in .cache can be ignored 205 | *.[Cc]ache 206 | # but keep track of directories ending in .cache 207 | !*.[Cc]ache/ 208 | 209 | # Others 210 | ClientBin/ 211 | ~$* 212 | *~ 213 | *.dbmdl 214 | *.dbproj.schemaview 215 | *.pfx 216 | *.publishsettings 217 | node_modules/ 218 | orleans.codegen.cs 219 | 220 | # Since there are multiple workflows, uncomment next line to ignore bower_components 221 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 222 | #bower_components/ 223 | 224 | # RIA/Silverlight projects 225 | Generated_Code/ 226 | 227 | # Backup & report files from converting an old project file 228 | # to a newer Visual Studio version. Backup files are not needed, 229 | # because we have git ;-) 230 | _UpgradeReport_Files/ 231 | Backup*/ 232 | UpgradeLog*.XML 233 | UpgradeLog*.htm 234 | 235 | # SQL Server files 236 | *.mdf 237 | *.ldf 238 | 239 | # Business Intelligence projects 240 | *.rdl.data 241 | *.bim.layout 242 | *.bim_*.settings 243 | 244 | # Microsoft Fakes 245 | FakesAssemblies/ 246 | 247 | # GhostDoc plugin setting file 248 | *.GhostDoc.xml 249 | 250 | # Node.js Tools for Visual Studio 251 | .ntvs_analysis.dat 252 | 253 | # Visual Studio 6 build log 254 | *.plg 255 | 256 | # Visual Studio 6 workspace options file 257 | *.opt 258 | 259 | # Visual Studio LightSwitch build output 260 | **/*.HTMLClient/GeneratedArtifacts 261 | **/*.DesktopClient/GeneratedArtifacts 262 | **/*.DesktopClient/ModelManifest.xml 263 | **/*.Server/GeneratedArtifacts 264 | **/*.Server/ModelManifest.xml 265 | _Pvt_Extensions 266 | 267 | # Paket dependency manager 268 | .paket/paket.exe 269 | paket-files/ 270 | 271 | # FAKE - F# Make 272 | .fake/ 273 | 274 | # JetBrains Rider 275 | .idea/ 276 | *.sln.iml 277 | 278 | 279 | ### C++ ### 280 | # Compiled Object files 281 | *.slo 282 | *.lo 283 | *.o 284 | 285 | # Precompiled Headers 286 | *.gch 287 | *.pch 288 | 289 | # Compiled Dynamic libraries 290 | *.so 291 | *.dylib 292 | 293 | # Fortran module files 294 | *.mod 295 | 296 | # Compiled Static libraries 297 | *.lai 298 | *.la 299 | *.a 300 | *.lib 301 | 302 | # Executables 303 | *.exe 304 | *.out 305 | *.app 306 | 307 | # Project specific folders 308 | build 309 | .vscode 310 | 311 | # dependencies 312 | lib/assimp/assimp* 313 | lib/glm/glm* 314 | lib/glm/GLM* 315 | lib/stb_image/stb_image* 316 | lib/glfw/glfw* 317 | lib/fmt/fmt* 318 | lib/imgui/imgui* 319 | *.cache 320 | compile_commands.json -------------------------------------------------------------------------------- /src/render/buffer.cpp: -------------------------------------------------------------------------------- 1 | #include "buffer.hpp" 2 | #include "command.hpp" 3 | #include "common.hpp" 4 | #include "utils/assert.hpp" 5 | 6 | #include 7 | 8 | namespace shady::render { 9 | 10 | void 11 | Buffer::Map(VkDeviceSize size) 12 | { 13 | vkMapMemory(Data::vk_device, bufferMemory_, 0, size, 0, &mappedMemory_); 14 | mapped_ = true; 15 | } 16 | 17 | void 18 | Buffer::Unmap() 19 | { 20 | if (mapped_) 21 | { 22 | vkUnmapMemory(Data::vk_device, bufferMemory_); 23 | mapped_ = false; 24 | mappedMemory_ = nullptr; 25 | } 26 | } 27 | 28 | void 29 | Buffer::CopyData(const void* data) const 30 | { 31 | utils::Assert(mapped_, "Buffer is not mapped!"); 32 | memcpy(mappedMemory_, data, bufferSize_); 33 | } 34 | 35 | void 36 | Buffer::CopyDataWithStaging(void* data, size_t dataSize) 37 | { 38 | VkBuffer stagingBuffer{}; 39 | VkDeviceMemory stagingBufferMemory{}; 40 | Buffer::CreateBuffer(dataSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, 41 | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 42 | stagingBuffer, stagingBufferMemory); 43 | 44 | void* mapped_data{}; 45 | vkMapMemory(Data::vk_device, stagingBufferMemory, 0, dataSize, 0, &mapped_data); 46 | memcpy(mapped_data, data, dataSize); 47 | vkUnmapMemory(Data::vk_device, stagingBufferMemory); 48 | 49 | Buffer::CopyBuffer(stagingBuffer, buffer_, dataSize); 50 | } 51 | 52 | void 53 | Buffer::CopyDataToImageWithStaging(VkImage image, void* data, size_t dataSize, 54 | const std::vector< VkBufferImageCopy >& copyRegions) 55 | { 56 | VkBuffer stagingBuffer{}; 57 | VkDeviceMemory stagingBufferMemory{}; 58 | Buffer::CreateBuffer(dataSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, 59 | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 60 | stagingBuffer, stagingBufferMemory); 61 | 62 | void* mapped_data{}; 63 | vkMapMemory(Data::vk_device, stagingBufferMemory, 0, dataSize, 0, &mapped_data); 64 | memcpy(mapped_data, data, dataSize); 65 | vkUnmapMemory(Data::vk_device, stagingBufferMemory); 66 | 67 | VkCommandBuffer commandBuffer = Command::BeginSingleTimeCommands(); 68 | 69 | vkCmdCopyBufferToImage(commandBuffer, stagingBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 70 | static_cast< uint32_t >(copyRegions.size()), copyRegions.data()); 71 | 72 | Command::EndSingleTimeCommands(commandBuffer); 73 | 74 | vkDestroyBuffer(Data::vk_device, stagingBuffer, nullptr); 75 | vkFreeMemory(Data::vk_device, stagingBufferMemory, nullptr); 76 | } 77 | 78 | void 79 | Buffer::SetupDescriptor(VkDeviceSize /*size*/, VkDeviceSize offset) 80 | { 81 | descriptor_.offset = offset; 82 | descriptor_.buffer = buffer_; 83 | descriptor_.range = bufferSize_; 84 | } 85 | 86 | void 87 | AllocateMemory(VkMemoryRequirements memReq, VkDeviceMemory& bufferMemory, 88 | VkMemoryPropertyFlags properties) 89 | { 90 | VkMemoryAllocateInfo allocInfo{}; 91 | allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; 92 | allocInfo.allocationSize = memReq.size; 93 | allocInfo.memoryTypeIndex = FindMemoryType(memReq.memoryTypeBits, properties); 94 | 95 | VK_CHECK(vkAllocateMemory(Data::vk_device, &allocInfo, nullptr, &bufferMemory), 96 | "failed to allocate buffer memory!"); 97 | } 98 | 99 | void 100 | Buffer::AllocateImageMemory(VkImage image, VkDeviceMemory& bufferMemory, 101 | VkMemoryPropertyFlags properties) 102 | { 103 | VkMemoryRequirements memRequirements; 104 | vkGetImageMemoryRequirements(Data::vk_device, image, &memRequirements); 105 | 106 | AllocateMemory(memRequirements, bufferMemory, properties); 107 | } 108 | 109 | void 110 | Buffer::AllocateBufferMemory(VkBuffer buffer, VkDeviceMemory& bufferMemory, 111 | VkMemoryPropertyFlags properties) 112 | { 113 | VkMemoryRequirements memRequirements; 114 | vkGetBufferMemoryRequirements(Data::vk_device, buffer, &memRequirements); 115 | 116 | AllocateMemory(memRequirements, bufferMemory, properties); 117 | } 118 | 119 | Buffer 120 | Buffer::CreateBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties) 121 | { 122 | Buffer newBuffer; 123 | newBuffer.bufferSize_ = size; 124 | CreateBuffer(size, usage, properties, newBuffer.buffer_, newBuffer.bufferMemory_); 125 | newBuffer.SetupDescriptor(); 126 | 127 | return newBuffer; 128 | } 129 | 130 | void 131 | Buffer::CreateBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, 132 | VkBuffer& buffer, VkDeviceMemory& bufferMemory) 133 | { 134 | VkBufferCreateInfo bufferInfo{}; 135 | bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; 136 | bufferInfo.size = size; 137 | bufferInfo.usage = usage; 138 | bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 139 | 140 | VK_CHECK(vkCreateBuffer(Data::vk_device, &bufferInfo, nullptr, &buffer), 141 | "failed to create buffer!"); 142 | 143 | AllocateBufferMemory(buffer, bufferMemory, properties); 144 | 145 | vkBindBufferMemory(Data::vk_device, buffer, bufferMemory, 0); 146 | } 147 | 148 | void 149 | Buffer::CopyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) 150 | { 151 | VkCommandBuffer commandBuffer = Command::BeginSingleTimeCommands(); 152 | 153 | VkBufferCopy copyRegion{}; 154 | copyRegion.size = size; 155 | vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, 1, ©Region); 156 | 157 | Command::EndSingleTimeCommands(commandBuffer); 158 | } 159 | 160 | void 161 | Buffer::Flush(VkDeviceSize size, VkDeviceSize offset) const 162 | { 163 | VkMappedMemoryRange mappedRange = {}; 164 | mappedRange.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; 165 | mappedRange.memory = bufferMemory_; 166 | mappedRange.offset = offset; 167 | mappedRange.size = size; 168 | 169 | VK_CHECK(vkFlushMappedMemoryRanges(Data::vk_device, 1, &mappedRange), "Buffer::Flush error!"); 170 | } 171 | 172 | void 173 | Buffer::Destroy() 174 | { 175 | if (buffer_) 176 | { 177 | vkDestroyBuffer(Data::vk_device, buffer_, nullptr); 178 | } 179 | if (bufferMemory_) 180 | { 181 | vkFreeMemory(Data::vk_device, bufferMemory_, nullptr); 182 | } 183 | } 184 | 185 | VkBuffer& 186 | Buffer::GetBuffer() 187 | { 188 | return buffer_; 189 | } 190 | 191 | void* 192 | Buffer::GetMappedMemory() 193 | { 194 | return mappedMemory_; 195 | } 196 | 197 | [[nodiscard]] VkDescriptorBufferInfo& 198 | Buffer::GetDescriptor() 199 | { 200 | return descriptor_; 201 | } 202 | 203 | } // namespace shady::render 204 | -------------------------------------------------------------------------------- /src/scene/model.cpp: -------------------------------------------------------------------------------- 1 | #include "model.hpp" 2 | #include "render/texture.hpp" 3 | #include "render/vertex.hpp" 4 | #include "trace/logger.hpp" 5 | #include "utils/file_manager.hpp" 6 | 7 | #include 8 | #include 9 | 10 | namespace shady::scene { 11 | 12 | static render::TextureType 13 | GetShadyTexFromAssimpTex(aiTextureType assimpTex) 14 | { 15 | switch (assimpTex) 16 | { 17 | case aiTextureType_SPECULAR: 18 | case aiTextureType_UNKNOWN: 19 | return render::TextureType::SPECULAR_MAP; 20 | case aiTextureType_NORMALS: 21 | return render::TextureType::NORMAL_MAP; 22 | case aiTextureType_DIFFUSE: 23 | default: { 24 | return render::TextureType::DIFFUSE_MAP; 25 | } 26 | } 27 | } 28 | 29 | static void 30 | LoadMaterialTextures(aiMaterial* mat, aiTextureType type, render::TextureMaps& textures) 31 | { 32 | for (uint32_t i = 0; i < mat->GetTextureCount(type); i++) 33 | { 34 | aiString str; 35 | mat->GetTexture(type, i, &str); 36 | 37 | const auto texType = GetShadyTexFromAssimpTex(type); 38 | render::TextureLibrary::CreateTexture(texType, str.C_Str()); 39 | textures[static_cast< uint32_t >(texType)] = str.C_Str(); 40 | } 41 | } 42 | 43 | Model::Model(const std::string& path, LoadFlags additionalAssimpFlags) 44 | { 45 | Assimp::Importer importer; 46 | 47 | const auto* scene = importer.ReadFile( 48 | path, aiProcess_FlipWindingOrder | aiProcess_GenSmoothNormals | aiProcess_Triangulate 49 | | /*aiProcess_CalcTangentSpace |*/ aiProcess_JoinIdenticalVertices 50 | | aiProcess_ValidateDataStructure | static_cast< uint32_t >(additionalAssimpFlags)); 51 | 52 | // Check for errors 53 | if (!scene || scene->mFlags == AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) 54 | { 55 | trace::Logger::Fatal("Error loading model: {} \n Error message: {}", path, 56 | importer.GetErrorString()); 57 | return; 58 | } 59 | 60 | trace::Logger::Debug("Loading model: {}", path); 61 | 62 | // Process ASSIMP's root node recursively 63 | ProcessNode(scene->mRootNode, scene); 64 | 65 | name_ = scene->mRootNode->mName.C_Str(); 66 | trace::Logger::Info("Loaded model: {} numVertices: {} numIndices: {}", name_, numVertices_, 67 | numIndices_); 68 | } 69 | 70 | void 71 | Model::ScaleModel(const glm::vec3& scale) 72 | { 73 | for (auto& mesh : meshes_) 74 | { 75 | mesh.Scale(scale); 76 | } 77 | } 78 | 79 | void 80 | Model::TranslateModel(const glm::vec3& translate) 81 | { 82 | for (auto& mesh : meshes_) 83 | { 84 | mesh.Translate(translate); 85 | } 86 | } 87 | 88 | void 89 | Model::RotateModel(const glm::vec3& rotate, float angle) 90 | { 91 | for (auto& mesh : meshes_) 92 | { 93 | mesh.Rotate(angle, rotate); 94 | } 95 | } 96 | 97 | void 98 | Model::Submit() 99 | { 100 | for (auto& mesh : meshes_) 101 | { 102 | mesh.Submit(); 103 | } 104 | } 105 | 106 | void 107 | Model::Draw() 108 | { 109 | for (auto& mesh : meshes_) 110 | { 111 | mesh.Draw(name_, glm::mat4(1.0f), {1.0f, 1.0f, 1.0f, 1.0f}); 112 | } 113 | } 114 | 115 | std::vector< Mesh >& 116 | Model::GetMeshes() 117 | { 118 | return meshes_; 119 | } 120 | 121 | void 122 | Model::ProcessNode(aiNode* node, const aiScene* scene) 123 | { 124 | for (uint32_t i = 0; i < node->mNumMeshes; i++) 125 | { 126 | // The node object only contains indices to index the actual objects in the scene. 127 | // The scene contains all the data, node is just to keep stuff organized (like relations 128 | // between nodes). 129 | auto* mesh = scene->mMeshes[node->mMeshes[i]]; 130 | meshes_.push_back(ProcessMesh(mesh, scene)); 131 | } 132 | 133 | trace::Logger::Debug("Processed node: {}", node->mName.C_Str()); 134 | 135 | // After we've processed all of the meshes (if any) we then recursively process each of the 136 | // children nodes 137 | for (uint32_t i = 0; i < node->mNumChildren; i++) 138 | { 139 | ProcessNode(node->mChildren[i], scene); 140 | } 141 | } 142 | 143 | Mesh 144 | Model::ProcessMesh(aiMesh* mesh, const aiScene* scene) 145 | { 146 | // Data to fill 147 | std::vector< render::Vertex > vertices; 148 | 149 | // Walk through each of the mesh's vertices 150 | for (uint32_t i = 0; i < mesh->mNumVertices; i++) 151 | { 152 | render::Vertex vertex{}; 153 | glm::vec3 vector{}; 154 | // Positions 155 | vector.x = mesh->mVertices[i].x; 156 | vector.y = mesh->mVertices[i].y; 157 | vector.z = mesh->mVertices[i].z; 158 | vertex.m_position = vector; 159 | 160 | // Normals 161 | if (mesh->HasNormals()) 162 | { 163 | vector.x = mesh->mNormals[i].x; 164 | vector.y = mesh->mNormals[i].y; 165 | vector.z = mesh->mNormals[i].z; 166 | vertex.m_normal = vector; 167 | } 168 | 169 | // Texture Coordinates 170 | if (mesh->HasTextureCoords(0)) 171 | { 172 | glm::vec2 vec{}; 173 | // A vertex can contain up to 8 different texture coordinates. We thus make the assumption 174 | // that we won't use models where a vertex can have multiple texture coordinates so we 175 | // always take the first set (0). 176 | vec.x = mesh->mTextureCoords[0][i].x; 177 | vec.y = mesh->mTextureCoords[0][i].y; 178 | vertex.m_texCoords = vec; 179 | } 180 | else 181 | { 182 | vertex.m_texCoords = glm::vec2(0.0f, 0.0f); 183 | } 184 | 185 | if (mesh->HasTangentsAndBitangents()) 186 | { 187 | // Tangents 188 | vector.x = mesh->mTangents[i].x; 189 | vector.y = mesh->mTangents[i].y; 190 | vector.z = mesh->mTangents[i].z; 191 | vertex.m_tangent = vector; 192 | } 193 | 194 | vertices.push_back(vertex); 195 | } 196 | 197 | std::vector< uint32_t > indices{}; 198 | // Now walk through each of the mesh's faces (a face is a mesh its triangle) and retrieve the 199 | // corresponding vertex indices. 200 | for (uint32_t i = 0; i < mesh->mNumFaces; i++) 201 | { 202 | const auto face = mesh->mFaces[i]; 203 | // Retrieve all indices of the face and store them in the indices vector 204 | for (uint32_t j = 0; j < face.mNumIndices; j++) 205 | { 206 | indices.push_back(face.mIndices[j]); 207 | } 208 | } 209 | 210 | // render::TexturePtrVec textures; 211 | render::TextureMaps textures = {}; 212 | 213 | // Process materials 214 | aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex]; 215 | LoadMaterialTextures(material, aiTextureType_DIFFUSE, textures); 216 | // LoadMaterialTextures(material, aiTextureType_SPECULAR, textures); 217 | LoadMaterialTextures(material, aiTextureType_UNKNOWN, textures); 218 | LoadMaterialTextures(material, aiTextureType_NORMALS, textures); 219 | 220 | 221 | trace::Logger::Debug("Processed mesh: {}", mesh->mName.C_Str()); 222 | numVertices_ += mesh->mNumVertices; 223 | numIndices_ += static_cast< uint32_t >(indices.size()); 224 | 225 | // NOLINTNEXTLINE 226 | return Mesh(mesh->mName.C_Str(), std::move(vertices), std::move(indices), std::move(textures)); 227 | } 228 | 229 | std::unique_ptr< Model > 230 | Model::CreatePlane() 231 | { 232 | auto model = std::make_unique< Model >(); 233 | model->GetMeshes().push_back({"Plane", 234 | {{ 235 | {25.0f, -0.5f, 25.0f}, // Position 236 | {0.0f, 1.0f, 0.0f}, // Normal 237 | {25.0f, 0.0f}, // Texcoord 238 | {50.0f, 0.0f, 0.0f} // Tangent 239 | }, 240 | { 241 | {-25.0f, -0.5f, 25.0f}, // Position 242 | {0.0f, 1.0f, 0.0f}, // Normal 243 | {0.0f, 0.0f}, // Texcoord 244 | {50.0f, 0.0f, 0.0f} // Tangent 245 | }, 246 | { 247 | {-25.0f, -0.5f, -25.0f}, // Position 248 | {0.0f, 1.0f, 0.0f}, // Normal 249 | {0.0f, 25.0f}, // Texcoord 250 | {50.0f, 0.0f, 0.0f} // Tangent 251 | }, 252 | { 253 | {25.0f, -0.5f, -25.0f}, // Position 254 | {0.0f, 1.0f, 0.0f}, // Normal 255 | {25.0f, 25.0f}, // Texcoord 256 | {50.0f, 0.0f, 0.0f} // Tangent 257 | }}, 258 | {2, 1, 0, 3, 2, 0}, // Indices 259 | {}}); 260 | 261 | return model; 262 | } 263 | 264 | } // namespace shady::scene 265 | -------------------------------------------------------------------------------- /src/render/framebuffer.cpp: -------------------------------------------------------------------------------- 1 | #include "framebuffer.hpp" 2 | #include "assert.hpp" 3 | #include "common.hpp" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | namespace shady::render { 11 | 12 | void 13 | Framebuffer::Create(int32_t width, int32_t height) 14 | { 15 | m_width = width; 16 | m_height = height; 17 | 18 | // Four attachments (3 color, 1 depth) 19 | AttachmentCreateInfo attachmentInfo = {}; 20 | attachmentInfo.width_ = static_cast< uint32_t >(width); 21 | attachmentInfo.height_ = static_cast< uint32_t >(height); 22 | attachmentInfo.layerCount_ = 1; 23 | attachmentInfo.usage_ = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; 24 | 25 | // Color attachments 26 | // Attachment 0: (World space) Positions 27 | attachmentInfo.format_ = VK_FORMAT_R16G16B16A16_SFLOAT; 28 | AddAttachment(attachmentInfo); 29 | 30 | // Attachment 1: (World space) Normals 31 | attachmentInfo.format_ = VK_FORMAT_R16G16B16A16_SFLOAT; 32 | AddAttachment(attachmentInfo); 33 | 34 | // Attachment 2: Albedo (color) 35 | attachmentInfo.format_ = VK_FORMAT_R8G8B8A8_UNORM; 36 | AddAttachment(attachmentInfo); 37 | 38 | // Depth attachment 39 | // Find a suitable depth format 40 | const auto attDepthFormat = FindDepthFormat(); 41 | 42 | attachmentInfo.format_ = attDepthFormat; 43 | attachmentInfo.usage_ = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; 44 | AddAttachment(attachmentInfo); 45 | 46 | // Create sampler to sample from the color attachments 47 | m_sampler = 48 | CreateSampler(VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE); 49 | 50 | // Create default renderpass for the framebuffer 51 | CreateRenderPass(); 52 | } 53 | 54 | void 55 | Framebuffer::CreateShadowMap(int32_t width, int32_t height, int32_t numLights) 56 | { 57 | m_width = width; 58 | m_height = height; 59 | 60 | // 16 bits of depth is enough for such a small scene 61 | constexpr auto SHADOWMAP_FORMAT = VK_FORMAT_D32_SFLOAT_S8_UINT; 62 | 63 | // Create a layered depth attachment for rendering the depth maps from the lights' point of view 64 | // Each layer corresponds to one of the lights 65 | // The actual output to the separate layers is done in the geometry shader using shader 66 | // instancing We will pass the matrices of the lights to the GS that selects the layer by the 67 | // current invocation 68 | AttachmentCreateInfo attachmentInfo = {}; 69 | attachmentInfo.format_ = SHADOWMAP_FORMAT; 70 | attachmentInfo.width_ = static_cast< uint32_t >(width); 71 | attachmentInfo.height_ = static_cast< uint32_t >(height); 72 | attachmentInfo.layerCount_ = static_cast< uint32_t >(numLights); 73 | attachmentInfo.usage_ = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; 74 | 75 | AddAttachment(attachmentInfo); 76 | 77 | // Create sampler to sample from to depth attachment 78 | // Used to sample in the fragment shader for shadowed rendering 79 | m_sampler = 80 | CreateSampler(VK_FILTER_LINEAR, VK_FILTER_LINEAR, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE); 81 | 82 | // Create default renderpass for the framebuffer 83 | CreateRenderPass(); 84 | } 85 | 86 | glm::ivec2 87 | Framebuffer::GetSize() const 88 | { 89 | return {m_width, m_height}; 90 | } 91 | 92 | VkRenderPass 93 | Framebuffer::GetRenderPass() const 94 | { 95 | return m_renderPass; 96 | } 97 | 98 | VkFramebuffer 99 | Framebuffer::GetFramebuffer() const 100 | { 101 | return m_framebuffer; 102 | } 103 | 104 | VkSampler 105 | Framebuffer::GetSampler() const 106 | { 107 | return m_sampler; 108 | } 109 | 110 | VkImageView 111 | Framebuffer::GetPositionsImageView() const 112 | { 113 | utils::Assert(not m_attachments.empty(), ""); 114 | return m_attachments[0].view_; 115 | } 116 | 117 | VkImageView 118 | Framebuffer::GetNormalsImageView() const 119 | { 120 | utils::Assert(m_attachments.size() > 1, ""); 121 | return m_attachments[1].view_; 122 | } 123 | 124 | VkImageView 125 | Framebuffer::GetAlbedoImageView() const 126 | { 127 | utils::Assert(m_attachments.size() > 2, ""); 128 | return m_attachments[2].view_; 129 | } 130 | 131 | VkImageView 132 | Framebuffer::GetShadowMapView() const 133 | { 134 | utils::Assert(not m_attachments.empty(), ""); 135 | return m_attachments[0].view_; 136 | } 137 | 138 | VkSampler 139 | Framebuffer::CreateSampler(VkFilter magFilter, VkFilter minFilter, VkSamplerAddressMode adressMode) 140 | { 141 | VkSampler sampler{}; 142 | 143 | VkSamplerCreateInfo samplerInfo{}; 144 | samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; 145 | samplerInfo.magFilter = magFilter; 146 | samplerInfo.minFilter = minFilter; 147 | samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; 148 | samplerInfo.addressModeU = adressMode; 149 | samplerInfo.addressModeV = adressMode; 150 | samplerInfo.addressModeW = adressMode; 151 | samplerInfo.mipLodBias = 0.0f; 152 | samplerInfo.maxAnisotropy = 1.0f; 153 | samplerInfo.minLod = 0.0f; 154 | samplerInfo.maxLod = 1.0f; 155 | samplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; 156 | 157 | VK_CHECK(vkCreateSampler(Data::vk_device, &samplerInfo, nullptr, &sampler), ""); 158 | 159 | return sampler; 160 | } 161 | 162 | uint32_t 163 | Framebuffer::AddAttachment(AttachmentCreateInfo createinfo) 164 | { 165 | FramebufferAttachment attachment{}; 166 | 167 | attachment.format_ = createinfo.format_; 168 | 169 | VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_NONE_KHR; 170 | 171 | // Select aspect mask and layout depending on usage 172 | 173 | // Color attachment 174 | if (createinfo.usage_ & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) 175 | { 176 | aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 177 | } 178 | 179 | // Depth (and/or stencil) attachment 180 | if (createinfo.usage_ & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) 181 | { 182 | if (attachment.hasDepth()) 183 | { 184 | aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; 185 | } 186 | if (attachment.hasStencil()) 187 | { 188 | aspectMask = aspectMask | VK_IMAGE_ASPECT_STENCIL_BIT; 189 | } 190 | } 191 | 192 | utils::Assert(aspectMask > 0, "Framebuffer::AddAttachment: aspectMask > 0 failed!\n"); 193 | 194 | VkImageCreateInfo image = {}; 195 | image.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; 196 | image.imageType = VK_IMAGE_TYPE_2D; 197 | image.format = createinfo.format_; 198 | image.extent.width = createinfo.width_; 199 | image.extent.height = createinfo.height_; 200 | image.extent.depth = 1; 201 | image.mipLevels = 1; 202 | image.arrayLayers = createinfo.layerCount_; 203 | image.samples = createinfo.imageSampleCount_; 204 | image.tiling = VK_IMAGE_TILING_OPTIMAL; 205 | image.usage = createinfo.usage_; 206 | 207 | VkMemoryAllocateInfo memAlloc = {}; 208 | memAlloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; 209 | VkMemoryRequirements memReqs; 210 | 211 | // Create image for this attachment 212 | VK_CHECK(vkCreateImage(Data::vk_device, &image, nullptr, &attachment.image_), ""); 213 | vkGetImageMemoryRequirements(Data::vk_device, attachment.image_, &memReqs); 214 | memAlloc.allocationSize = memReqs.size; 215 | memAlloc.memoryTypeIndex = 216 | FindMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); 217 | VK_CHECK(vkAllocateMemory(Data::vk_device, &memAlloc, nullptr, &attachment.memory_), ""); 218 | VK_CHECK(vkBindImageMemory(Data::vk_device, attachment.image_, attachment.memory_, 0), ""); 219 | 220 | attachment.subresourceRange_ = {}; 221 | attachment.subresourceRange_.aspectMask = aspectMask; 222 | attachment.subresourceRange_.levelCount = 1; 223 | attachment.subresourceRange_.layerCount = createinfo.layerCount_; 224 | 225 | VkImageViewCreateInfo imageView = {}; 226 | imageView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 227 | imageView.viewType = 228 | (createinfo.layerCount_ == 1) ? VK_IMAGE_VIEW_TYPE_2D : VK_IMAGE_VIEW_TYPE_2D_ARRAY; 229 | imageView.format = createinfo.format_; 230 | imageView.subresourceRange = attachment.subresourceRange_; 231 | // todo: workaround for depth+stencil attachments 232 | imageView.subresourceRange.aspectMask = 233 | (attachment.hasDepth()) ? VK_IMAGE_ASPECT_DEPTH_BIT : aspectMask; 234 | imageView.image = attachment.image_; 235 | VK_CHECK(vkCreateImageView(Data::vk_device, &imageView, nullptr, &attachment.view_), ""); 236 | 237 | // Fill attachment description 238 | attachment.description_ = {}; 239 | attachment.description_.samples = createinfo.imageSampleCount_; 240 | attachment.description_.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; 241 | attachment.description_.storeOp = (createinfo.usage_ & VK_IMAGE_USAGE_SAMPLED_BIT) 242 | ? VK_ATTACHMENT_STORE_OP_STORE 243 | : VK_ATTACHMENT_STORE_OP_DONT_CARE; 244 | attachment.description_.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; 245 | attachment.description_.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; 246 | attachment.description_.format = createinfo.format_; 247 | attachment.description_.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; 248 | // Final layout 249 | // If not, final layout depends on attachment type 250 | if (attachment.hasDepth() || attachment.hasStencil()) 251 | { 252 | attachment.description_.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; 253 | } 254 | else 255 | { 256 | attachment.description_.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; 257 | } 258 | 259 | m_attachments.push_back(attachment); 260 | 261 | return static_cast< uint32_t >(m_attachments.size() - 1); 262 | } 263 | 264 | void 265 | Framebuffer::CreateRenderPass() 266 | { 267 | std::vector< VkAttachmentDescription > attachmentDescriptions; 268 | std::transform(m_attachments.begin(), m_attachments.end(), 269 | std::back_inserter(attachmentDescriptions), 270 | [](const auto& attachment) { return attachment.description_; }); 271 | 272 | // Collect attachment references 273 | std::vector< VkAttachmentReference > colorReferences; 274 | VkAttachmentReference depthReference = {}; 275 | bool hasDepth = false; 276 | bool hasColor = false; 277 | 278 | uint32_t attachmentIndex = 0; 279 | 280 | for (const auto& attachment : m_attachments) 281 | { 282 | if (attachment.isDepthStencil()) 283 | { 284 | // Only one depth attachment allowed 285 | utils::Assert(!hasDepth, 286 | "Framebuffer::CreateRenderPass: Only one depth attackment allowed!\n"); 287 | depthReference.attachment = attachmentIndex; 288 | depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; 289 | hasDepth = true; 290 | } 291 | else 292 | { 293 | colorReferences.push_back({attachmentIndex, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}); 294 | hasColor = true; 295 | } 296 | attachmentIndex++; 297 | }; 298 | 299 | // Default render pass setup uses only one subpass 300 | VkSubpassDescription subpass = {}; 301 | subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; 302 | if (hasColor) 303 | { 304 | subpass.pColorAttachments = colorReferences.data(); 305 | subpass.colorAttachmentCount = static_cast< uint32_t >(colorReferences.size()); 306 | } 307 | if (hasDepth) 308 | { 309 | subpass.pDepthStencilAttachment = &depthReference; 310 | } 311 | 312 | // Use subpass dependencies for attachment layout transitions 313 | std::array< VkSubpassDependency, 2 > dependencies{}; 314 | 315 | dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; 316 | dependencies[0].dstSubpass = 0; 317 | dependencies[0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; 318 | dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 319 | dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; 320 | dependencies[0].dstAccessMask = 321 | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 322 | dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; 323 | 324 | dependencies[1].srcSubpass = 0; 325 | dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; 326 | dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 327 | dependencies[1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; 328 | dependencies[1].srcAccessMask = 329 | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 330 | dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; 331 | dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; 332 | 333 | // Create render pass 334 | VkRenderPassCreateInfo renderPassInfo = {}; 335 | renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; 336 | renderPassInfo.pAttachments = attachmentDescriptions.data(); 337 | renderPassInfo.attachmentCount = static_cast< uint32_t >(attachmentDescriptions.size()); 338 | renderPassInfo.subpassCount = 1; 339 | renderPassInfo.pSubpasses = &subpass; 340 | renderPassInfo.dependencyCount = 2; 341 | renderPassInfo.pDependencies = dependencies.data(); 342 | VK_CHECK(vkCreateRenderPass(Data::vk_device, &renderPassInfo, nullptr, &m_renderPass), ""); 343 | 344 | std::vector< VkImageView > attachmentViews; 345 | std::transform(m_attachments.begin(), m_attachments.end(), std::back_inserter(attachmentViews), 346 | [](const auto& attachment) { return attachment.view_; }); 347 | 348 | // Find. max number of layers across attachments 349 | const uint32_t maxLayers = 350 | std::accumulate(m_attachments.begin(), m_attachments.end(), uint32_t{0}, 351 | [](uint32_t curMax, const auto& right) { 352 | return std::max({curMax, right.subresourceRange_.layerCount}); 353 | }); 354 | 355 | VkFramebufferCreateInfo framebufferInfo = {}; 356 | framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; 357 | framebufferInfo.renderPass = m_renderPass; 358 | framebufferInfo.pAttachments = attachmentViews.data(); 359 | framebufferInfo.attachmentCount = static_cast< uint32_t >(attachmentViews.size()); 360 | framebufferInfo.width = static_cast< uint32_t >(m_width); 361 | framebufferInfo.height = static_cast< uint32_t >(m_height); 362 | framebufferInfo.layers = maxLayers; 363 | VK_CHECK(vkCreateFramebuffer(Data::vk_device, &framebufferInfo, nullptr, &m_framebuffer), ""); 364 | } 365 | 366 | } // namespace shady::render 367 | -------------------------------------------------------------------------------- /src/scene/skybox.cpp: -------------------------------------------------------------------------------- 1 | #include "skybox.hpp" 2 | 3 | #include "render/command.hpp" 4 | #include "render/common.hpp" 5 | #include "render/shader.hpp" 6 | #include "render/texture.hpp" 7 | #include "utils/file_manager.hpp" 8 | 9 | #include 10 | 11 | namespace shady::scene { 12 | 13 | using namespace render; 14 | 15 | void 16 | Skybox::LoadCubeMap(std::string_view skyboxName) 17 | { 18 | // Positions 19 | std::array< float, 24 > vertices = { 20 | -1.0f, 1.0f, 1.0f, // vertex 0 21 | -1.0f, -1.0f, 1.0f, // vertex 1 22 | 1.0f, -1.0f, 1.0f, // vertex 2 23 | 1.0f, 1.0f, 1.0f, // vertex 3 24 | -1.0f, -1.0f, -1.0f, // vertex 4 25 | -1.0f, 1.0f, -1.0f, // vertex 5 26 | 1.0f, -1.0f, -1.0f, // vertex 6 27 | 1.0f, 1.0f, -1.0f // vertex 7 28 | }; 29 | 30 | std::array< uint32_t, 36 > indicies = { 31 | 3, 2, 0, 0, 2, 1, // face 1 32 | 6, 2, 3, 7, 6, 3, // face 2 33 | 6, 7, 4, 7, 5, 4, // face 3 34 | 4, 0, 1, 5, 0, 4, // face 4 35 | 7, 3, 0, 5, 7, 0, // face 5 36 | 2, 6, 4, 1, 2, 4 // face 6 37 | }; 38 | 39 | // Create vertex buffer with device local memory 40 | // ---------------------- 41 | const auto vertex_buffer_size = vertices.size() * sizeof(float); 42 | 43 | m_vertexBuffer = Buffer::CreateBuffer( 44 | vertex_buffer_size, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, 45 | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); 46 | m_vertexBuffer.CopyDataWithStaging(vertices.data(), vertex_buffer_size); 47 | 48 | // Create index buffer with device local memory 49 | // ---------------------- 50 | constexpr auto index_buffer_size = indicies.size() * sizeof(uint32_t); 51 | 52 | m_indexBuffer = Buffer::CreateBuffer( 53 | index_buffer_size, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, 54 | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); 55 | m_indexBuffer.CopyDataWithStaging(indicies.data(), index_buffer_size); 56 | 57 | CreateBuffers(); 58 | CreateImageAndSampler(skyboxName); 59 | CreateDescriptorSet(); 60 | CreatePipeline(); 61 | } 62 | 63 | void 64 | Skybox::CreateImageAndSampler(std::string_view skyboxName) 65 | { 66 | // Load faces to memory 67 | // ----------------------- 68 | constexpr auto num_faces = 6; 69 | 70 | auto name = std::string{skyboxName}; 71 | 72 | const std::unordered_map< uint32_t, std::string > textureFaces = { 73 | {0, name + "_right.jpg"}, {1, name + "_left.jpg"}, {2, name + "_top.jpg"}, 74 | {3, name + "_bottom.jpg"}, {4, name + "_front.jpg"}, {5, name + "_back.jpg"}}; 75 | 76 | 77 | // Per face data 78 | std::array< render::ImageData, num_faces > faces; 79 | 80 | // Combined bytes for all faces 81 | std::vector< uint8_t > combined_faces_bytes; 82 | 83 | for (const auto& [face, textureName] : textureFaces) 84 | { 85 | faces[face] = utils::FileManager::ReadTexture(fmt::format("skybox/{}", textureName)); 86 | const auto width = faces[face].m_size.x; 87 | const auto height = faces[face].m_size.y; 88 | const auto single_face_size = 4 * width * height; 89 | 90 | std::copy(&faces[face].m_bytes[0], &faces[face].m_bytes[single_face_size], 91 | std::back_inserter(combined_faces_bytes)); 92 | } 93 | 94 | // Create Image and Sampler 95 | // ----------------------- 96 | const auto width = faces[0].m_size.x; 97 | const auto height = faces[0].m_size.y; 98 | 99 | std::tie(m_image, m_imageMemory) = Texture::CreateImage( 100 | width, height, 1, VK_SAMPLE_COUNT_1_BIT, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_TILING_OPTIMAL, 101 | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, 102 | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, true); 103 | 104 | Texture::CopyBufferToCubemapImage(m_image, width, height, combined_faces_bytes.data()); 105 | 106 | m_sampler = Texture::CreateSampler(); 107 | m_imageView = Texture::CreateImageView(m_image, VK_FORMAT_R8G8B8A8_UNORM, 108 | VK_IMAGE_ASPECT_COLOR_BIT, 1, true); 109 | } 110 | 111 | void 112 | Skybox::CreateBuffers() 113 | { 114 | m_uniformBuffer = Buffer::CreateBuffer(sizeof(SkyboxUBO), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, 115 | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT 116 | | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); 117 | 118 | m_uniformBuffer.Map(); 119 | } 120 | 121 | void 122 | Skybox::UpdateBuffers(const scene::Camera* camera) 123 | { 124 | SkyboxUBO buffer{}; 125 | buffer.viewProjection = camera->GetProjection() * glm::mat4(glm::mat3(camera->GetView())); 126 | 127 | m_uniformBuffer.CopyData(&buffer); 128 | } 129 | 130 | void 131 | Skybox::CreateDescriptorSet() 132 | { 133 | std::array< VkDescriptorPoolSize, 2 > poolSizes{}; 134 | poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; 135 | poolSizes[0].descriptorCount = 1; 136 | poolSizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 137 | poolSizes[1].descriptorCount = 1; 138 | 139 | VkDescriptorPoolCreateInfo poolInfo{}; 140 | poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; 141 | poolInfo.poolSizeCount = static_cast< uint32_t >(poolSizes.size()); 142 | poolInfo.pPoolSizes = poolSizes.data(); 143 | poolInfo.maxSets = 1; 144 | 145 | VK_CHECK(vkCreateDescriptorPool(Data::vk_device, &poolInfo, nullptr, &m_descriptorPool), 146 | "failed to create descriptor pool!"); 147 | 148 | VkDescriptorSetLayoutBinding uboLayoutBinding{}; 149 | uboLayoutBinding.binding = 0; 150 | uboLayoutBinding.descriptorCount = 1; 151 | uboLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; 152 | uboLayoutBinding.pImmutableSamplers = nullptr; 153 | uboLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; 154 | 155 | VkDescriptorSetLayoutBinding samplerLayoutBinding{}; 156 | samplerLayoutBinding.binding = 1; 157 | samplerLayoutBinding.descriptorCount = 1; 158 | samplerLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 159 | samplerLayoutBinding.pImmutableSamplers = nullptr; 160 | samplerLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; 161 | 162 | std::array< VkDescriptorSetLayoutBinding, 2 > bindings = {uboLayoutBinding, 163 | samplerLayoutBinding}; 164 | 165 | VkDescriptorSetLayoutCreateInfo layoutInfo{}; 166 | layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; 167 | layoutInfo.bindingCount = static_cast< uint32_t >(bindings.size()); 168 | layoutInfo.pBindings = bindings.data(); 169 | 170 | VK_CHECK( 171 | vkCreateDescriptorSetLayout(Data::vk_device, &layoutInfo, nullptr, &m_descriptorSetLayout), 172 | "Failed to create Skybox's descriptor set layout!"); 173 | 174 | VkDescriptorSetAllocateInfo allocateInfo = {}; 175 | allocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; 176 | allocateInfo.pSetLayouts = &m_descriptorSetLayout; 177 | allocateInfo.descriptorPool = m_descriptorPool; 178 | allocateInfo.descriptorSetCount = 1; 179 | 180 | VK_CHECK(vkAllocateDescriptorSets(Data::vk_device, &allocateInfo, &m_descriptorSet), 181 | "Skybox's vkAllocateDescriptorSets failed!"); 182 | 183 | 184 | VkDescriptorBufferInfo bufferInfo{}; 185 | bufferInfo.buffer = m_uniformBuffer.GetBuffer(); 186 | bufferInfo.offset = 0; 187 | bufferInfo.range = sizeof(SkyboxUBO); 188 | 189 | std::array< VkWriteDescriptorSet, 2 > descriptorWrites{}; 190 | descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 191 | descriptorWrites[0].dstSet = m_descriptorSet; 192 | descriptorWrites[0].dstBinding = 0; 193 | descriptorWrites[0].dstArrayElement = 0; 194 | descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; 195 | descriptorWrites[0].descriptorCount = 1; 196 | descriptorWrites[0].pBufferInfo = &bufferInfo; 197 | 198 | VkDescriptorImageInfo descriptorImageInfo = {}; 199 | descriptorImageInfo.sampler = m_sampler; 200 | descriptorImageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; 201 | descriptorImageInfo.imageView = m_imageView; 202 | 203 | descriptorWrites[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 204 | descriptorWrites[1].dstSet = m_descriptorSet; 205 | descriptorWrites[1].dstBinding = 1; 206 | descriptorWrites[1].dstArrayElement = 0; 207 | descriptorWrites[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 208 | descriptorWrites[1].descriptorCount = 1; 209 | descriptorWrites[1].pImageInfo = &descriptorImageInfo; 210 | 211 | vkUpdateDescriptorSets(Data::vk_device, static_cast< uint32_t >(descriptorWrites.size()), 212 | descriptorWrites.data(), 0, nullptr); 213 | } 214 | 215 | void 216 | Skybox::CreatePipeline() 217 | { 218 | VkPipelineLayoutCreateInfo pipelineLayoutInfo = {}; 219 | pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; 220 | pipelineLayoutInfo.setLayoutCount = 1; 221 | pipelineLayoutInfo.pSetLayouts = &m_descriptorSetLayout; 222 | 223 | 224 | VK_CHECK( 225 | vkCreatePipelineLayout(Data::vk_device, &pipelineLayoutInfo, nullptr, &m_pipelineLayout), 226 | "Skybox pipeline layout failed!"); 227 | 228 | //----------------------------------------------------------------------------------------// 229 | 230 | auto [vertexInfo, fragmentInfo] = 231 | Shader::CreateShader(Data::vk_device, "default/skybox.vert.spv", "default/skybox.frag.spv"); 232 | std::array< VkPipelineShaderStageCreateInfo, 2 > shaderStages = {vertexInfo.shaderInfo, 233 | fragmentInfo.shaderInfo}; 234 | 235 | VkPipelineVertexInputStateCreateInfo vertexInputInfo{}; 236 | vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; 237 | auto bindingDescription = SkyboxVertex::getBindingDescription(); 238 | auto attributeDescriptions = SkyboxVertex::getAttributeDescriptions(); 239 | vertexInputInfo.vertexBindingDescriptionCount = 1; 240 | vertexInputInfo.vertexAttributeDescriptionCount = 241 | static_cast< uint32_t >(attributeDescriptions.size()); 242 | vertexInputInfo.pVertexBindingDescriptions = &bindingDescription; 243 | vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions.data(); 244 | 245 | VkPipelineInputAssemblyStateCreateInfo inputAssembly{}; 246 | inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; 247 | inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; 248 | inputAssembly.primitiveRestartEnable = VK_FALSE; 249 | 250 | VkViewport viewport{}; 251 | viewport.x = 0.0f; 252 | viewport.y = 0.0f; 253 | viewport.width = static_cast< float >(Data::m_deferredExtent.width); 254 | viewport.height = static_cast< float >(Data::m_deferredExtent.height); 255 | viewport.minDepth = 0.0f; 256 | viewport.maxDepth = 1.0f; 257 | 258 | VkRect2D scissor{}; 259 | scissor.offset = {0, 0}; 260 | scissor.extent = Data::m_deferredExtent; 261 | 262 | VkPipelineViewportStateCreateInfo viewportState{}; 263 | viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; 264 | viewportState.viewportCount = 1; 265 | viewportState.pViewports = &viewport; 266 | viewportState.scissorCount = 1; 267 | viewportState.pScissors = &scissor; 268 | 269 | VkPipelineRasterizationStateCreateInfo rasterizer{}; 270 | rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; 271 | rasterizer.depthClampEnable = VK_FALSE; 272 | rasterizer.rasterizerDiscardEnable = VK_FALSE; 273 | rasterizer.polygonMode = VK_POLYGON_MODE_FILL; 274 | rasterizer.lineWidth = 1.0f; 275 | rasterizer.cullMode = VK_CULL_MODE_FRONT_BIT; 276 | rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; 277 | rasterizer.depthBiasEnable = VK_FALSE; 278 | 279 | VkPipelineMultisampleStateCreateInfo multisampling{}; 280 | multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; 281 | multisampling.sampleShadingEnable = VK_FALSE; 282 | multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; 283 | 284 | VkPipelineDepthStencilStateCreateInfo depthStencil{}; 285 | depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; 286 | depthStencil.depthTestEnable = VK_FALSE; 287 | depthStencil.depthWriteEnable = VK_FALSE; 288 | depthStencil.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL; 289 | depthStencil.back.compareOp = VK_COMPARE_OP_ALWAYS; 290 | depthStencil.depthBoundsTestEnable = VK_FALSE; 291 | depthStencil.stencilTestEnable = VK_FALSE; 292 | 293 | std::array< VkPipelineColorBlendAttachmentState, 3 > colorBlendAttachment{}; 294 | 295 | colorBlendAttachment[0].colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT 296 | | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; 297 | colorBlendAttachment[0].blendEnable = VK_FALSE; 298 | 299 | colorBlendAttachment[1].colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT 300 | | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; 301 | colorBlendAttachment[1].blendEnable = VK_FALSE; 302 | 303 | colorBlendAttachment[2].colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT 304 | | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; 305 | colorBlendAttachment[2].blendEnable = VK_FALSE; 306 | 307 | VkPipelineColorBlendStateCreateInfo colorBlending{}; 308 | colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; 309 | colorBlending.logicOpEnable = VK_FALSE; 310 | colorBlending.logicOp = VK_LOGIC_OP_COPY; 311 | colorBlending.attachmentCount = 3; 312 | colorBlending.pAttachments = colorBlendAttachment.data(); 313 | colorBlending.blendConstants[0] = 0.0f; 314 | colorBlending.blendConstants[1] = 0.0f; 315 | colorBlending.blendConstants[2] = 0.0f; 316 | colorBlending.blendConstants[3] = 0.0f; 317 | 318 | VkGraphicsPipelineCreateInfo pipelineInfo{}; 319 | pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; 320 | pipelineInfo.stageCount = 2; 321 | pipelineInfo.pStages = shaderStages.data(); 322 | pipelineInfo.pVertexInputState = &vertexInputInfo; 323 | pipelineInfo.pInputAssemblyState = &inputAssembly; 324 | pipelineInfo.pViewportState = &viewportState; 325 | pipelineInfo.pRasterizationState = &rasterizer; 326 | pipelineInfo.pMultisampleState = &multisampling; 327 | pipelineInfo.pDepthStencilState = &depthStencil; 328 | pipelineInfo.pColorBlendState = &colorBlending; 329 | pipelineInfo.layout = m_pipelineLayout; 330 | pipelineInfo.renderPass = Data::m_deferredRenderPass; 331 | pipelineInfo.subpass = 0; 332 | pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; 333 | 334 | VK_CHECK(vkCreateGraphicsPipelines(Data::vk_device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, 335 | &m_pipeline), 336 | "Skybox pipeline creation failed!"); 337 | } 338 | 339 | void 340 | Skybox::Draw(VkCommandBuffer commandBuffer) 341 | { 342 | vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineLayout, 0, 1, 343 | &m_descriptorSet, 0, nullptr); 344 | vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline); 345 | 346 | std::array offsets = {0}; 347 | vkCmdBindVertexBuffers(commandBuffer, 0, 1, &m_vertexBuffer.GetBuffer(), offsets.data()); 348 | vkCmdBindIndexBuffer(commandBuffer, m_indexBuffer.GetBuffer(), 0, VK_INDEX_TYPE_UINT32); 349 | 350 | vkCmdDrawIndexed(commandBuffer, 36, 1, 0, 0, 0); 351 | } 352 | 353 | } // namespace shady::scene 354 | --------------------------------------------------------------------------------