From c42133f426d1d1bfb7d5227ca76d9195cdc2ef3f Mon Sep 17 00:00:00 2001 From: Lillian Salehi <lillian@lillian.com> Date: Wed, 4 Dec 2024 01:55:40 -0600 Subject: [PATCH] Added vertex normal to the Agnosia_T::Vertex definition, pre-calculated using TinyObjLoader's built in vertex normal calculator --- .../index/buffers.h.CC15E40B6084C10D.idx | Bin 1846 -> 1876 bytes .../devicelibrary.cpp.A6A50BF3BD186A09.idx | Bin 12172 -> 12146 bytes .../index/entrypoint.cpp.9286A9B0BD8A276E.idx | Bin 5396 -> 5804 bytes .../clangd/index/model.h.C3ECCCBE7C04E4C8.idx | Bin 1808 -> 1876 bytes imgui.ini | 2 +- src/entrypoint.cpp | 16 +- src/graphics/buffers.cpp | 3 + src/graphics/buffers.h | 1 + src/graphics/model.cpp | 232 ++++++++++-------- src/graphics/model.h | 3 +- src/shaders/common.glsl | 1 + src/shaders/fragment.frag | 2 +- src/types.h | 7 +- 13 files changed, 150 insertions(+), 117 deletions(-) diff --git a/.cache/clangd/index/buffers.h.CC15E40B6084C10D.idx b/.cache/clangd/index/buffers.h.CC15E40B6084C10D.idx index 19a291615f43adaf14cf77101b146d2b121a31f6..80de00b1810cdc41fd8b836e2c2c5a65782562df 100644 GIT binary patch delta 1120 zcmdnScZIJ$$kWZuhn<1JImNRgH?<^@g@J)V7>J8YiZa<485kOw7#J$%%$<1A`>=t) zvCrp!+)BQ@d|z%>>V`&xgU@w#E^GH(r}A>kzpvY}yQ4&(DG2PlfA^#8_s-JbX%dSh z{@aLaE%32;5qKvtr18~}hZAr9YpC|wzj1BO&Y4=)B{H|_r*2)75-ui{%yq}_+u}Kr zQ&SAt8@gnhRI@#+Ivfw4s_0XBzgO{oIA1}^?@6K0{k|Mwi40$&B-19VH>YgP#eex` zTTSb>W+yRxI%OvHFfrPudE?X9U*&mUW$k<?r<1oSbsK}|WVQL{GHn;V(vP2X-C4^2 zuH2!7U8&EPTn`qT|HMtiNj-gIjdJaeVgt4N4|}gKF?jd#?~^T)^Ia$KJw7Hr&1dQn z_UGH4I}}&uCJ6$=LQ|NxLG-|Db|EHlAP)q%RfJR~doh}8KzNcuk_rqQU^c_@x6(bo z*YV2=F^R$y%Sy>kUdw2j22m`;C!`Kjtn2xvBKvf=kq{FzOtBcBm=s*vC*VNcazisA zCRUiVFrTm@O#0X{sjX>I6C8w?#9-3$3i6Zvn8Y|CR!Q?oPtJ$)lqHlWPk{3j)fFdi zWD-+>sFabG(SaFjeR}=&B^Q-<2r;ohjh+0K$<iF6P(esR4W_W?@JeaL19g9em^fkf zi}Hyo!=xFCQqzi;Pqt^4ky7MS6iHH4wn<Aj%Yua_BPTc%OPM2?f#Em#BD07gFrc*D z%ra^k?qzTv*l^=~fB8gJMjmc)3vmZnNEKTC_1JiKA4pi9Q+~1-ixV?2#3n}rX&FwL z$qQIS>VaWk1~a8AFW^k+RPO+wWx&9YfeG)CzjFI%_R$caDaxG6VwTq<{7h#r&V<oG z)xf|~gQ<qO94HJ7H4B(<YgG0usjpdiKtm*?B{X3!<XckY?k!xcT?teU4A#kxtlIYC z(&7d%c^+;lMJcnNbE^+*Uz{NMZR1bQihsUqfQE=ki>bpDl|EL|4RDLz4ir`tRh+z< z)rnb_Q+DzP)_`a+Ju!G_tUdZ;v+%prXF#h!5d(7>*P0J!ZD##@#=^rb$tfuavkS;m zl+;A<6gU+GVJ7f!t8l7Jp3P=10gF|jnV{H&naMEu5}UD1XY%@AX}|tfvGMcra0&1+ P@PbnXnBbbM$Sw*18!23b delta 1104 zcmcb@w~enp$kWYDkDY<RImNRgH?<^@g@J)V7>J8YiZVGF85mYGF)&ojSvu*W_hAEp zW53V;xRrc)`M%s&DH|FM4nEh}xvYJ9jOV4yzprzzi<N5mv^wm#Uw*v2AbwlUDIw=G z$M$O&$p)y(yxO?q;0oreo`?2w)HhoD+~3%nwRGkbT`SJ|w@r~-UOhRJ;Ny7f<UW;S zObl9u96o23*c@4qn7G#^X#2fM@2A?zw9NnX>Q3jp8w*}_m9+eQFzxlOf7k!qzcW|j z$^Em-wjJv)^W|}fD^3=8XSUjXLyTSgzY7cWpPhbp@Qv2|=f)QdB|p8KbB+1cKR4A% z<2!E`-d5f`W8G29r)NvH`ji))aSflR@>KX`auL_Do|1~UyqP`LRkl{SS5Iqcv=_b& z_u1xkQ#$_7*T)RSmAOeA!0^x%=4}u?@S0tSNt}s+YZjBxEG7kRWg+FsE{x_nTpJjL zHZUr1O9)9QFmM1v5(t*RmG1eyj$c-YNffA|ok^;lNsC)XN@nt6MpITU13m-w$#)s0 zxVfG)@;wLAqI{y0n8et*8W{N+7!@Z=GXbSKm=rpg%(&$g<R;rOiPdxUF!A*;$#6^Y zNy)%$vAiDPXF7XvrVx`b(3Y7@5;K|9xRoT7)L;sd6qRk#(#^7jn1p}|rZTBdWwPK_ zP*<>kDOghE?k!xcT`9yQ0#wk(B;CfO!!0c>tpihFeR}=&B^Q-<a0xN709EAj<tk0S z%4F%!HHArN3eYxrA$hoMMX71U6POtoLi~i(Ure-NW#Zu$Ru|UQ^$9pox7^T-hg*S9 zK?LR`SdcPuf&;ReIno0ZfNo|PH4XPNxM2YZlm-Ty7EJiSh8ySm%O|Qb@^Fh;h&kwb zzNyGQ-ECB8`PXCP-F+ZoIZnCBGAvHaz#yHR$l_El%_%Jj^X0K)Qd`raCO7~M1qQ1b z%+Rj9fHS32y#s*4pwNX0?~%W9`)Kyj5TKz-oJwM_z=qL4)u5n;sfPIrC=3c<m@r>! zRQ4>XuUUCOQ^cjkCmXPeFayJPvOBA`y_mF^0n7(H+>(ltW<TdvAK1P)LGs(ipPUu{ zeAfUqiAsyA!xWW1R?-b{i{1_tRuEN~yph$3S%y<)@;BB1DN#L9cxbFW`eU>3yVPeu zrvRg8asr!(t^}uqAk1(cZV5#RO$1M#Q(h3Jg@;?2Q+e`2HuK3J*o<Y?y%X)Zc{5m& Wjh~l?Q-F_w7m~O^B<Ey%c2NMr*K2G5 diff --git a/.cache/clangd/index/devicelibrary.cpp.A6A50BF3BD186A09.idx b/.cache/clangd/index/devicelibrary.cpp.A6A50BF3BD186A09.idx index f13b3c919cd18ea0fb116e02f25ef166c4cba8c8..1aa5d883123b0e78ceaec0d436cf2eb34748bd94 100644 GIT binary patch literal 12146 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 literal 12172 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 AWB>pF diff --git a/.cache/clangd/index/entrypoint.cpp.9286A9B0BD8A276E.idx b/.cache/clangd/index/entrypoint.cpp.9286A9B0BD8A276E.idx index b8608c456de5a88737c4591544431dc236f19bd5..57a90d7e5dd2df9310945809c5303561128d3b0b 100644 GIT binary patch literal 5804 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 literal 5396 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 diff --git a/.cache/clangd/index/model.h.C3ECCCBE7C04E4C8.idx b/.cache/clangd/index/model.h.C3ECCCBE7C04E4C8.idx index 763a7c1fec2a61673f2b1e58fc420f266e6c2f43..0d3b33115ee8cc8d743e332bb7f1dfae01eb179f 100644 GIT binary patch literal 1876 zcmYjSeN0nV6o0*?eZ74jeSNQmmX<<WTC*iOFbo-kFrz?<U?a@A!3N?exM)EsIw0Fr z%)b06LLd^rL1q*q{-Yt8Y#1<POEyMuAj7b@i7DcQC1zg)v*GS5p21Ce-hIE{J@=k_ z&hPZ)d$O`}X^PrX=Bf4jYDyz0ijv4LP*eTRQ}WD36jj@KE<evZoWPED%@ppFdVWs6 zH&i;#|8p$qP|<Nq_Q8!m9PwUj{Z#pJL+JJ8TJMQ2e{t8Sr#{qCRWvbMI&|rq%s%W* z+4d&?{r&yTd+To-e09TPEzZm4Pp+ztddef*<=1RUsVS$5TNX~nemk|Dj+$vKpZ@Mr zYvOc5Q$gE^*YU>k3pav)Z>lUrk90XdYC<t{wwvh-jbHCxytB{|laiOd)Tb)!b7oX- zF21$1|HzhL+SF98y-h!H@a`@=vY~e|{iOlpfO~!_)OVuxbg!eL<6?VfCij-d+dL9i zQ}O<M<%5@tzg%qS*?K?k%$a_h=eNsCsN}0rH5I7y@9~lx+%9eXeKK;FMnq~QNedY` zmXD30G%GLT!K|*y)}Ks96a}==W?Tn!Ae0d7zIeebAOp}Y-W3h>pQjfc_ZIAS9z`oD zEV5!$*Z?h+cyo5l6>Sob5xkw8Qv$lBZCY(hHKhtj0NTMj{-?)+y_<hI8`vWtJ<x8( zZ3OQ}sdIt9QezJBD3Y8lF;ZmM06ln;KAL`RwoXJU@V4+4C(yyCInRAi68RpF6vSJ{ z>x8fYdSAwlw1S+9V*=8Fx7})Y1D#jlcx^g)>{KK|K%0<>23oQH-CE~?xE>K%fVS~A zE6@%8!R{;L$8U;A1lsDdCIbCYR;QR<?Hm@61av$b9|d%UQq}fhqxu$)B1q(dRd9w4 z(35vU$v&!ThDT;X8+b!h*Z_UEvAKV5eZj9hG7(zO=%ug$I_ck`!})b(PiRD>gE=+F zgbjtmYEfVnRqZPel##ez-7c<s*p#M1EH?5+1L%mwR)aMfZV2L2;IQam_w`$COPPaD zIO0oc&%ljXY)5tmQV%;4Us;jh3yLJLtVDo8i3)94fdGR7$!b}70E6-fEGrJ+N@d*P zrgqD2IWA7Htci=WTOclwCGnNz2)>;=b7%hO9PleytVen+<e9~$=S>?yFD#Bn@meS_ zD44`7%NKS6<&pzr#R3e9C97q*0t{i1)v`hXh7$=aD-+-XoO#3V6M||M>u4PZd$QO- z8#s^-iCHq4VFwnQCG(m$2kqb>e=K&<E)Gg^R`W3Fi_e&L5}`_?GOhf<P!x0n2}SM# z2t}MtyZ*}H{B@Erkro*!AUQ74{Nn22PTI*p6+u>HC%Iu@C&(v(<wgM*%16SHy9D3~ z$AR4L&-14hEVjg3HbA!F@?^E#G_YEG<?(1*`|<-K2?<GBC>e|0$gKq_K(UFh+)>~Q z&j{^G6Fo}^X&9q18strqy{0~-eJs{ExM#I*f2r&gsD3+8B2O6EtPGstdW_CjWnZNk fPOG7LmeK-6QRKS_gM$f0@vBpIb^7c>AOrsak2?{p literal 1808 zcmYk7e@t6d6vtn0Deuz0_xjq`pR^<W3BfoVbF$Es%%NkU4i{kTA7&VIEvVy%?Zj2b zf~ZWR>jK;4$GQz?TufM)o0+f#!*FV*q*j?M8;b51`=v39!yk+}yzj9ycuDWOJ>Pro zJ@=f?X-f(V3NTGkPi-pPS{v9>nM6^PKtACuq38c3Zx5oVt+D-W!*!=^Olzd;Isb|A z%>KrS${oHYMZWcNd>F@kO*8rX%5sCdPaTiXrcC!wd%8ZII+Hm6+2MUVWTiP-AC!5o zxNbIXG*p+ho8LaBXf94qN)H~Fg+dLtS1!GfxS0842iNz-iul0Zj~5->Z2czC`EBBz zM`w*kKfJedto+Nt{A;o1mMbS$H`LGgb3b{l{_i-q;oO0iy0&1E?w(;%KQaExiP1aj z>L35Q#(V3f3u_BU{&<1O%iWffzuxlx<-yK>&-6Ntz5c~n?QC9;x@*KXb!dCj^0Uu8 zHu1_2yW5il_jemy8NKIzmetgJ)fbM`RxKg79*q_p9NYVoNskP2k_hr(eVRUl!gF83 zSC>S44u53kkpQxbbESejweugx#oz6A4w>Z?)-qb7G=MBrto0RNFJI0h9e6ufhXC@P z&hg|lkIBO$HOO|({!mUtdsqJ25w7A953*b3)`Ryg&-L(Mo<%QnNKeidRDwYoKpuLR zZqD038POsIcw0D&6XfWuFLQf^VH<~J#9Pg&d1(Oo#TCWgQeXA!JmSFHX0@e*TvY8? zKc16#&wvofCS;;Pu6naIa%?8Mk4LE>r_pH-FV<2!)N^F?jbSa)fNXVJv%$NyAf{a% za-Qaq7Gx*mG=f|$S9HF$EBSj4C6UN^EANyBkjKtn%?VKTmpEi1vX0Xkr2*uLUF|1p zUM;=JAtRABDvclwATRsxRAWhG(_I=7HZYsas-%HRk#LY<MJNyq7m={mJ*&;Q(dJbk z2J1P!4lrV{RcB3w3od>-ZF<$vU6w2&MN~oL47MSg3Q`QNvJ{CthychVW|25B1938? zL>icZG_qPG49q|nF^gn@xlV3tZ0ojc6ysuf%YwLAn+4(m{D`lJ9r(t|)?B(18?2Qx zSc5c5$R~qMkC>JM7YueHrxFSYq>`9LOkpP=lpG+E31%RZtQN5ZGlWG}izI>>P9$cL zKrol4topn*z(<oAtftj0?8#sqtz!WZ60=}3!ww8K3+4si?6jSQ{4v-?yI3em2fnea z|A4BSM5w?D)7&owMFI6B6p?laMLX#ocyj2s0g^B+tyMt*$#L1{C*}`#&<+(;5%?iH ziH!j}K|YCDYzQzz`A9foH-P!9qhU?Yp^|YKgDoyg7GxVPPgaY~0jrfqZpXdd_pcEo z1SBY-WDIsAw-Qi*ViRAnbHEqgNy@oqd5{p&8G3yx;7yXfpgyEeELI!blL`ekSBhTY xkUv}@PL$#>_h7&0X!-r>;0Uc`QfShV51LU@lVKG_G4oS)eyW<ElK($={s&um1iAnK diff --git a/imgui.ini b/imgui.ini index ca80a3a..ff29567 100644 --- a/imgui.ini +++ b/imgui.ini @@ -3,6 +3,6 @@ Pos=60,60 Size=400,400 [Window][Agnosia Debug] -Pos=40,377 +Pos=59,322 Size=623,438 diff --git a/src/entrypoint.cpp b/src/entrypoint.cpp index b296faf..5946517 100644 --- a/src/entrypoint.cpp +++ b/src/entrypoint.cpp @@ -87,8 +87,7 @@ void createInstance() { throw std::runtime_error("failed to create instance!"); } } - -void initVulkan() { +void initAgnosia() { Material *vikingRoomMaterial = new Material("vikingRoomMaterial", "assets/textures/viking_room.png"); Material *stanfordDragonMaterial = @@ -104,7 +103,8 @@ void initVulkan() { Model *teapot = new Model("teapot", *teapotMaterial, "assets/models/teapot.obj", glm::vec3(1.0f, -3.0f, -1.0f)); - +} +void initVulkan() { // Initialize volk and continue if successful. volkInitialize(); // Initialize vulkan and set up pipeline. @@ -122,9 +122,7 @@ void initVulkan() { Graphics::createCommandPool(); // Image creation MUST be after command pool, because command // buffers. - vikingRoom->populateData(); - stanfordDragon->populateData(); - teapot->populateData(); + Model::populateModels(); Texture::createMaterialTextures(Model::getInstances()); Texture::createColorResources(); Texture::createDepthResources(); @@ -150,6 +148,11 @@ void mainLoop() { void cleanup() { Render::cleanupSwapChain(); Graphics::destroyGraphicsPipeline(); + Buffers::destroyDescriptorPool(); + Model::destroyTextures(); + + vkDestroyDescriptorSetLayout(DeviceControl::getDevice(), + Buffers::getDescriptorSetLayout(), nullptr); Buffers::destroyBuffers(); Render::destroyFenceSemaphores(); @@ -179,6 +182,7 @@ GLFWwindow *EntryApp::getWindow() { return window; } void EntryApp::run() { initWindow(); + initAgnosia(); initVulkan(); mainLoop(); cleanup(); diff --git a/src/graphics/buffers.cpp b/src/graphics/buffers.cpp index 78af9a7..a808344 100644 --- a/src/graphics/buffers.cpp +++ b/src/graphics/buffers.cpp @@ -122,6 +122,9 @@ void Buffers::createDescriptorPool() { throw std::runtime_error("failed to create descriptor pool!"); } } +void Buffers::destroyDescriptorPool() { + vkDestroyDescriptorPool(DeviceControl::getDevice(), descriptorPool, nullptr); +} void Buffers::createDescriptorSet(std::vector<Model *> models) { VkDescriptorSetAllocateInfo allocInfo{}; allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; diff --git a/src/graphics/buffers.h b/src/graphics/buffers.h index be65a6d..33f308b 100644 --- a/src/graphics/buffers.h +++ b/src/graphics/buffers.h @@ -19,6 +19,7 @@ public: static void createDescriptorSetLayout(); static void createDescriptorSet(std::vector<Model *> models); static void createDescriptorPool(); + static void destroyDescriptorPool(); static void createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags props, VkBuffer &buffer, VkDeviceMemory &bufferMemory); diff --git a/src/graphics/model.cpp b/src/graphics/model.cpp index 3a39550..64b3376 100644 --- a/src/graphics/model.cpp +++ b/src/graphics/model.cpp @@ -20,15 +20,21 @@ std::vector<Model *> Model::instances; VmaAllocator _allocator; +// chatgpt did this and the haters can WEEP fuck hash functions. namespace std { template <> struct hash<Agnosia_T::Vertex> { size_t operator()(Agnosia_T::Vertex const &vertex) const { - return ((hash<glm::vec3>()(vertex.pos) ^ - (hash<glm::vec3>()(vertex.color) << 1)) >> - 1) ^ - (hash<glm::vec2>()(vertex.texCoord) << 1); + size_t hashPos = hash<glm::vec3>()(vertex.pos); + size_t hashColor = hash<glm::vec3>()(vertex.color); + size_t hashUV = hash<glm::vec2>()(vertex.uv); + size_t hashNormal = hash<glm::vec3>()(vertex.normal); + + // Combine all hashes + return ((hashPos ^ (hashColor << 1)) >> 1) ^ (hashUV << 1) ^ + (hashNormal << 2); } }; + } // namespace std void Model::createMemoryAllocator(VkInstance vkInstance) { VmaVulkanFunctions vulkanFuncs{ @@ -105,112 +111,128 @@ Model::Model(const std::string &modelID, const Material &material, instances.push_back(this); } -void Model::populateData() { +void Model::populateModels() { + for (Model *model : getInstances()) { - std::vector<Agnosia_T::Vertex> vertices; - // Index buffer definition, showing which points to reuse. - std::vector<uint32_t> indices; - tinyobj::ObjReaderConfig readerConfig; - tinyobj::ObjReader reader; + std::vector<Agnosia_T::Vertex> vertices; + // Index buffer definition, showing which points to reuse. + std::vector<uint32_t> indices; + tinyobj::ObjReaderConfig readerConfig; + tinyobj::ObjReader reader; - if (!reader.ParseFromFile(modelPath, readerConfig)) { - if (!reader.Error().empty()) { - throw std::runtime_error(reader.Error()); - } - if (!reader.Warning().empty()) { - throw std::runtime_error(reader.Warning()); - } - } - - auto &attrib = reader.GetAttrib(); - auto &shapes = reader.GetShapes(); - auto &materials = reader.GetMaterials(); - - std::unordered_map<Agnosia_T::Vertex, uint32_t> uniqueVertices{}; - - for (const auto &shape : shapes) { - for (const auto &index : shape.mesh.indices) { - Agnosia_T::Vertex vertex{}; - - vertex.pos = {attrib.vertices[3 * index.vertex_index + 0], - attrib.vertices[3 * index.vertex_index + 1], - attrib.vertices[3 * index.vertex_index + 2]}; - - // TODO: Small fix here, handle if there are no UV's unwrapped for the - // model. - // As of now, if it is not unwrapped, it segfaults on texCoord - // assignment. Obviously we should always have UV's, but it - // shouldn't crash, just unwrap in a default method. - vertex.texCoord = {attrib.texcoords[2 * index.texcoord_index + 0], - 1.0f - attrib.texcoords[2 * index.texcoord_index + 1]}; - vertex.color = {1.0f, 1.0f, 1.0f}; - - if (uniqueVertices.count(vertex) == 0) { - uniqueVertices[vertex] = static_cast<uint32_t>(vertices.size()); - vertices.push_back(vertex); + if (!reader.ParseFromFile(model->modelPath, readerConfig)) { + if (!reader.Error().empty()) { + throw std::runtime_error(reader.Error()); + } + if (!reader.Warning().empty()) { + throw std::runtime_error(reader.Warning()); } - indices.push_back(uniqueVertices[vertex]); } + + auto &attrib = reader.GetAttrib(); + auto &shapes = reader.GetShapes(); + auto &materials = reader.GetMaterials(); + + std::unordered_map<Agnosia_T::Vertex, uint32_t> uniqueVertices{}; + + for (const auto &shape : shapes) { + for (const auto &index : shape.mesh.indices) { + Agnosia_T::Vertex vertex{}; + + vertex.pos = {attrib.vertices[3 * index.vertex_index + 0], + attrib.vertices[3 * index.vertex_index + 1], + attrib.vertices[3 * index.vertex_index + 2]}; + + vertex.normal = {attrib.normals[3 * index.normal_index + 0], + attrib.normals[3 * index.normal_index + 1], + attrib.normals[3 * index.normal_index + 2]}; + // TODO: Small fix here, handle if there are no UV's unwrapped for the + // model. + // As of now, if it is not unwrapped, it segfaults on texCoord + // assignment. Obviously we should always have UV's, but it + // shouldn't crash, just unwrap in a default method. + vertex.uv = {attrib.texcoords[2 * index.texcoord_index + 0], + 1.0f - attrib.texcoords[2 * index.texcoord_index + 1]}; + vertex.color = {1.0f, 1.0f, 1.0f}; + + if (uniqueVertices.count(vertex) == 0) { + uniqueVertices[vertex] = static_cast<uint32_t>(vertices.size()); + vertices.push_back(vertex); + } + indices.push_back(uniqueVertices[vertex]); + } + } + + const size_t vertexBufferSize = vertices.size() * sizeof(Agnosia_T::Vertex); + const size_t indexBufferSize = indices.size() * sizeof(uint32_t); + + Agnosia_T::GPUMeshBuffers newSurface; + + // Create a Vertex Buffer here, infinitely easier than the old Vulkan + // method! + newSurface.vertexBuffer = createBuffer( + vertexBufferSize, + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | + VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, + VMA_MEMORY_USAGE_GPU_ONLY); + // Find the address of the vertex buffer! + VkBufferDeviceAddressInfo deviceAddressInfo{ + .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, + .buffer = newSurface.vertexBuffer.buffer, + }; + newSurface.vertexBufferAddress = vkGetBufferDeviceAddress( + DeviceControl::getDevice(), &deviceAddressInfo); + + // Create the index buffer to iterate over and check for duplicate vertices + newSurface.indexBuffer = createBuffer(indexBufferSize, + VK_BUFFER_USAGE_INDEX_BUFFER_BIT | + VK_BUFFER_USAGE_TRANSFER_DST_BIT, + VMA_MEMORY_USAGE_GPU_ONLY); + + Agnosia_T::AllocatedBuffer stagingBuffer = createBuffer( + vertexBufferSize + indexBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + VMA_MEMORY_USAGE_CPU_ONLY); + + void *data = stagingBuffer.allocation->GetMappedData(); + + // Copy the vertex buffer + memcpy(data, vertices.data(), vertexBufferSize); + // Copy the index buffer + memcpy((char *)data + vertexBufferSize, indices.data(), indexBufferSize); + + immediate_submit([&](VkCommandBuffer cmd) { + VkBufferCopy vertexCopy{0}; + vertexCopy.dstOffset = 0; + vertexCopy.srcOffset = 0; + vertexCopy.size = vertexBufferSize; + + vkCmdCopyBuffer(cmd, stagingBuffer.buffer, newSurface.vertexBuffer.buffer, + 1, &vertexCopy); + + VkBufferCopy indexCopy{0}; + indexCopy.dstOffset = 0; + indexCopy.srcOffset = vertexBufferSize; + indexCopy.size = indexBufferSize; + + vkCmdCopyBuffer(cmd, stagingBuffer.buffer, newSurface.indexBuffer.buffer, + 1, &indexCopy); + }); + vmaDestroyBuffer(_allocator, stagingBuffer.buffer, + stagingBuffer.allocation); + + model->buffers = newSurface; + model->indiceCount = indices.size(); + } +} +void Model::destroyTextures() { + for (Model *model : Model::getInstances()) { + vkDestroySampler(DeviceControl::getDevice(), + model->getMaterial().getTextureSampler(), nullptr); + vkDestroyImageView(DeviceControl::getDevice(), + model->getMaterial().getTextureView(), nullptr); + vkDestroyImage(DeviceControl::getDevice(), + model->getMaterial().getTextureImage(), nullptr); } - - const size_t vertexBufferSize = vertices.size() * sizeof(Agnosia_T::Vertex); - const size_t indexBufferSize = indices.size() * sizeof(uint32_t); - - Agnosia_T::GPUMeshBuffers newSurface; - - // Create a Vertex Buffer here, infinitely easier than the old Vulkan method! - newSurface.vertexBuffer = createBuffer( - vertexBufferSize, - VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | - VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, - VMA_MEMORY_USAGE_GPU_ONLY); - // Find the address of the vertex buffer! - VkBufferDeviceAddressInfo deviceAddressInfo{ - .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, - .buffer = newSurface.vertexBuffer.buffer, - }; - newSurface.vertexBufferAddress = - vkGetBufferDeviceAddress(DeviceControl::getDevice(), &deviceAddressInfo); - - // Create the index buffer to iterate over and check for duplicate vertices - newSurface.indexBuffer = createBuffer(indexBufferSize, - VK_BUFFER_USAGE_INDEX_BUFFER_BIT | - VK_BUFFER_USAGE_TRANSFER_DST_BIT, - VMA_MEMORY_USAGE_GPU_ONLY); - - Agnosia_T::AllocatedBuffer stagingBuffer = - createBuffer(vertexBufferSize + indexBufferSize, - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY); - - void *data = stagingBuffer.allocation->GetMappedData(); - - // Copy the vertex buffer - memcpy(data, vertices.data(), vertexBufferSize); - // Copy the index buffer - memcpy((char *)data + vertexBufferSize, indices.data(), indexBufferSize); - - immediate_submit([&](VkCommandBuffer cmd) { - VkBufferCopy vertexCopy{0}; - vertexCopy.dstOffset = 0; - vertexCopy.srcOffset = 0; - vertexCopy.size = vertexBufferSize; - - vkCmdCopyBuffer(cmd, stagingBuffer.buffer, newSurface.vertexBuffer.buffer, - 1, &vertexCopy); - - VkBufferCopy indexCopy{0}; - indexCopy.dstOffset = 0; - indexCopy.srcOffset = vertexBufferSize; - indexCopy.size = indexBufferSize; - - vkCmdCopyBuffer(cmd, stagingBuffer.buffer, newSurface.indexBuffer.buffer, 1, - &indexCopy); - }); - vmaDestroyBuffer(_allocator, stagingBuffer.buffer, stagingBuffer.allocation); - - this->buffers = newSurface; - this->objPosition = objPosition; - this->indiceCount = indices.size(); } std::string Model::getID() { return this->ID; } diff --git a/src/graphics/model.h b/src/graphics/model.h index d2bdd0f..0feeadc 100644 --- a/src/graphics/model.h +++ b/src/graphics/model.h @@ -28,7 +28,8 @@ public: static void createMemoryAllocator(VkInstance instance); static const std::vector<Model *> &getInstances(); - void populateData(); + static void populateModels(); + static void destroyTextures(); Agnosia_T::GPUMeshBuffers getBuffers(); std::string getID(); diff --git a/src/shaders/common.glsl b/src/shaders/common.glsl index f117a1d..2448db0 100644 --- a/src/shaders/common.glsl +++ b/src/shaders/common.glsl @@ -4,6 +4,7 @@ struct Vertex { vec3 pos; + vec3 normal; vec3 color; vec2 texCoord; }; diff --git a/src/shaders/fragment.frag b/src/shaders/fragment.frag index 27d6329..65dfb87 100644 --- a/src/shaders/fragment.frag +++ b/src/shaders/fragment.frag @@ -11,5 +11,5 @@ layout(location = 1) in vec2 fragTexCoord; layout(location = 0) out vec4 outColor; void main() { - outColor = texture(texSampler[PushConstants.textureID], fragTexCoord); + outColor = texture(texSampler[PushConstants.textureID], fragTexCoord) * vec4(fragColor, 1.0f); } diff --git a/src/types.h b/src/types.h index 5108fc4..e824c42 100644 --- a/src/types.h +++ b/src/types.h @@ -10,12 +10,13 @@ public: // This defines what a vertex is! // We control the position, color and texture coordinate here! glm::vec3 pos; + glm::vec3 normal; glm::vec3 color; - glm::vec2 texCoord; + glm::vec2 uv; bool operator==(const Vertex &other) const { - return pos == other.pos && color == other.color && - texCoord == other.texCoord; + return pos == other.pos && normal == other.normal && + color == other.color && uv == other.uv; } }; struct AllocatedBuffer {