From 3d04ad4c43f689de7b5938430c2e0b7e311ad1c0 Mon Sep 17 00:00:00 2001 From: matthew Date: Sat, 22 Nov 2025 19:06:52 +1100 Subject: [PATCH] loading/rendering set up, has bugs --- assets/shaders/gradient.comp.spv | Bin 4392 -> 4652 bytes assets/shaders/pbr.frag.spv | Bin 3128 -> 3436 bytes assets/shaders/pbr.vert.spv | Bin 4692 -> 4984 bytes src/VulkanRenderer | 2 +- src/dlib | 2 +- src/gears/game2.d | 402 +++++++++++++++++++++++-------- src/shaders/structures.layout | 83 ++++--- 7 files changed, 356 insertions(+), 133 deletions(-) diff --git a/assets/shaders/gradient.comp.spv b/assets/shaders/gradient.comp.spv index 6fdb5166acaa237094e8f7eb6fa8f8ecc36087a4..241bd2c21aa716496c42c071362833516e37b150 100644 GIT binary patch literal 4652 zcmZveX>%Jz5Qf**VUrMYp9Etk+zBQ(fshc#7P3LMg5^Lsm9@07m8>Kqt(}7aNk}L@ z@)P*Z7x*9i9g3rhD&A*yJDzeeRqg5bou2NV-kz~?gNKKL!a%S&*b@8@q+@$97z{{d zej}TYXY&con}ecTFIQ@n@qW@AKXv+;=-`#?eTXIKoSMsgof#i{7n_}W?yVJpGoSb3~O8;F6=Yvf_xl%7ztK~|m-dI_w z_mewuRF7MosNQV#qDInMi?AE^>{^{hyxQ~)3bOF?F6bmrDMk|Aj^cWw+wC>Q47>9z z#r1OBT@2%y&RVw-CarE~W=gjB*rB=Kx~qubf;;*S0^VcS86lWxs;awV$c*{nw_b6wBz|+wXnSsN4>cy>_z<~&HtwOv;ckWE(Bo4 zS}WpniYq#fep=~uZ}1Je>IUQac5!QIIZ<7yLNOR}_HaYff>uI>|;Rio61*)WNEtuUSn6F#9k13W|35H2`7 zSG%y;Y;~5NaMW!rj91e>D!991{@72>-)WxhHlw(fC{kKKI7S=3-VT#qD?4}I-L=eA zyNkg?*Xxr z-8S$37qHG?o%_hT*>e~DSYUshhW7n~{dNAouufg@5BAr&udLfQ2d}T^+?^a0N6qcN zQa6Ti1JdEPc^rG-c1eiK|2N`Lcf)=h?rIt*@9whTlb*19?DvFmmJ2=~Xb&+MhKZ4L zIOpzi8l&*!UfX`o@=$hm7V2Rfd$1e!IDEoA?Qzy;RtNl9pIIFqi{sAjm+aJu@ja#t z@rS-!=O}6(m5|F`Va^T5`lv8@z#-Uga=iX%V2^(|d}2?I_<}!|Vcr_^|BQ6(@xMpA zc4{7#?AI>=@&;q;4{R-;-Pr=R_y_ZLF?Pv{vmOyoj02Dw1plqK}i_j__SQ+rSmNf*Q7T+ydd2_ z+ZAE_n*B%8sgdE2rSnY;UzN_;41Xe>elh&1biTXc&!m&1;m@Vh3x>at&TluvUrOhE zhU?Plf#b@8ysvqB=;@1|-tctJen2ORG*iRtni*hf3|@lJ*eATKnQy`w>C2X8>Prp4 zH!@6(Ms$*!n%QIf*vlU5h!<YAK_OYKk{hS2eY(}KB&$oGA82&f;;l7Sa*a!co;vCY<_(wiRHIGT)s1dsP zenC3%sj0<(Q98WYyd<6YzRkFk65TQMva^B<}hIld|xmGF(QCl7KxqM1Ri z*t{lzBUg0l#s_oZ*_qYuQv+n$PaILmETI)30Sw>jzL#`hsNFm`+gt0S}B$EtMhBX~&jWeK^1 Zc?Um~;IAQ!E$eXjvp!`0S1-U>$$tw?-QEA`YkH^0F6_B58I&f1{lS4?JIL1IU{5e15&pX8 zmp#8CzCS3t{d%L>m>s2^*=yG?2@Vbh1(@4A6dVmol8d5l827*rh)#%z^|9znQ7Gz& zHbq;aSoBcT6%9lq(bLLDoWo8=&vF!$Z;#~PRctZX7t|ZA`pQbZQERmagVrehHi=qE z+>2VBco?+R3<+Hz>&>Uvo*P*sC0A^f*dd?S6mQ5i;e@vYE8%Nq;>| zmU`R$c9_Qf-qM0>iE%`H6o03T=p}dVg<<$;sT*zrVlyk=?kD}B)2Cct6tkgNyF
@{RS#mzcW8#) zK@tt`Md2_SrCDvC3(pQWl2s`{XKlyPBY0UqVBC|zu>X+$_Vtww=es2F=2ohnal&#i z>Fl{7VRt=_dbWd4wnyJHAOFD=kS|Xj?vkn#FSvVCcUaloAJ^0B+<0RnqLs2KxjU8N z8s#!e_1mg}i2T^;RghN0u?qoF?Y=xPtkaF;~u;nm~hH;oI zgeg~9XvyKo{+v%RdewS)iPa#{ zVGP@HzY`_RRMlnubpt583*PF6=`i+vDY`lHrt&Wb-^gxtJldM?_eN>hOSAk%hifZH zHSK&C>^M`Zfi|73mo6tj_D+DK>A#e$iPGI`77`h-Lcu zOm(_SaQ4smeP)H)SlBnk(IIqZ1eto#nGJO6MQ1LiJ!bk&zJj}x_%6!UW`naV>LjL5 zO6RT0V;7{e%#WOTKlI&xVEEk?SuApc{gA_`9qgwZM!&&+&SB&O`&Go*c!xPF%XH34 z-nu#xil6j*$k=9kMYor??c{8cv87hxqVL!i-J8!oi+$#keY0ma^SRLT`^;%RK6-wi znPs285FdSKzu@MST=bM#X3-axVH1+U>^owI4_HNHcH{uNl*6p|*MyOuS*0Fu)ARK( zqgg%0z~S%w{=CPv+VDIg8CS77)ZNx)9E}OD=MKmEgDV=kJv0sr+9bgdl`y8%c zTG$gGjF{L{BeB45d7U@L;vbZZJ@HS->!^4|bXtG?sT&>J{KD4iIqo;GB|bWD7VDU- zIO|2>|Ybd9vpl2_#cfmqaASWAXuL4%)FDtCYGLQ zCuhAY1~uu#Cgx@JfSP$nO>XAowVce`c}8daP@K3QiL=nji_Uw>Iwk!Raq8que5+5z z$;r1u|IF+3_ME;n?)Uk8M%k~#Xh|z##ep=TVkMx z9wWxOWMWKs%os7IMZ{=(5L;rPcRWUnNHXW#9m8~DYf z#Cw20`p9E;?^Ef#8#9`8=9G5=47wn?p)W{2?hUIT`b!Akm6*H<h)5yd)jm^1mz@Kk&bm!*ap@P{*k86;VaRH^QDesP&>ai(0XHRRl(@ z$n=eGbxA}`SH!Q1c)zSC+_h^S|Hb#@y2r2~&l}<_^00S91V$cYi+xivvF*IXep3W) zvET9-u{p2Bf!ld+NhS|xz@8k`aa){49oW1r0;3LO>-!zayYI$3!od6TWp?k1z|5yA zdG}qJbNf3!^U}e7RG)~kAi668Cr(ZLT@gL!eDoh3JIhm-y!+lP3In&=mL!9j&wG-0 z-=p`1ftyc5GMLr2ESWgqR@*(v)W-LrHgxRx4%SDw&Etw><`I2Td{sp4=riIUh=|vg SjxGCO#It({|5q=-P0@dAzhtlg diff --git a/assets/shaders/pbr.frag.spv b/assets/shaders/pbr.frag.spv index f91b9e30611a4f3672ed5c339b55cb50c7a66c16..799cd648044dfa060f45b753c0bea22e3e7d1cf3 100644 GIT binary patch literal 3436 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 bj+8#&uK%F@oM%A_|D$%`2mGJD(7N=0?!D>0 diff --git a/assets/shaders/pbr.vert.spv b/assets/shaders/pbr.vert.spv index 1a9aa139ecb3f2dd9486748c132d469d80d6cbcb..fec49026f0688035b1240b126e6e93c589ec6517 100644 GIT binary patch delta 1920 zcmYk6-%e9O5XQHh7C~t-sY!z|MnO%CF%gYd#>5JZVp@t6{I7VR1*^^xZnipK zDV7~KWE$csrG;X-JTtX4UtPR$bGB5gIsc$pmA^VQRbH&kRA&=fI}MsO@ukX4&7*A& zDxKa8bFXLG;ToG0+>U<+g)xe^Z1MWm>S|+C&@So5sdPT#NX6E2quyC)a4ZVuh_ju| zcGz-U+8((w@9>~KesyJ~wbgBQ))U&U@_xZ+7VFFyO5*+vtw_vkJ+tv zv5y1rr9Mszx4rcl;jVDT1h&(2Q^_^$>}_X8la`YLxuH|hZZHa_Xl&AgX)TzvU|I?$ zEtpoGlp+p~C(vRZB!1S&AK4e$4+!jQEhJ8Bd%+eHn=B6Ot9G%xaAIAd;C^h{zJB}& zh4FO8jc(X2;NAGiz--|Bye~fi*!MG1_}$HbeLrstzq={$I2}$B1or)4-~9iUWSR;7 zNgS7w4R_e%SOa%N%E_2%647~w`-KFY+2&-=s{q7L1m_Y_ErD(kaYK%ae+=i(;vvc} z3y$=DSvz}whpRz!PQiJ(YEn+&@Ph2RhZkj!dH9ZOJ^TImyRs3tUO!j%R1V)44m|$@ z*(x*IU+_=_HM#|lWDk1yvFrmLej=NbyZ9y9!ybMr`=EzI*@vV@RMxV-lPYJ~T+#2v zK1fcSIE)=NXESEbX2iyn>RJ3TSBSr6M{YO8AkU;%bSf}|ha6S97y6zM-?EIcm^d&4 zh_K_jzVsp!?`HGy;oQ*a4lW5ER)9AkB&>L;Z$946<>R^B$VvNaEC!ZnFms0x-BZOA z(N;p3p1wqZnLfl}h7EC;;X)i{m=K2<9^|-M$PYA);v_Wim~wp37hX*`W3S?)0E2>q rO~4Ea+;R0aiYG@4@wL(PSuXCgSbEDlCK|jgg#%ah-PwCN`g`CX6rRF* delta 1585 zcmYk6%T7~K6oz+iU^S%}Fa!q(R!NwNmyvN$pb-*;YK!6xdT0-{*qgmXXB{&nCp>_U zV2JTKOnd{Mz?nn;Z=Y`3)vWCG|Ld~XIcxR&TmF476^mvjO(J4$n3VZ^p2|h$&kIjh z-Wg*)N=wqR^jLZ#tx9Xsy0j&2fB*3_Iw;D@Zm;Dwb`OiWePa^(?ZLfR+sf?}EtxPA z=C!y&KDWNNoqZKXhOuvKett7MB*~|PjgI$atKpsavdO2Tg4bx*{mzc>b^LD6@=;R? zZpP<)8nxls{#Ti{4I0nZkNirj=tEMP2gx>$YJRh4NjM&?(Duvyy4Qh(<3Y3acGU}0 z#Y~vf;9LAwD`8IML%gt#JRuhmSE(Hz_q)D0#S2HJ-C=E+S9}bmOw5iszpm1>(!M-Pq{D%82l8BZGHfskX3*H&3ueGz?gca4B`M)3cq_3;E_LewJ)1`*>1-&ia{I~33AEwz-<=Z#W63H;WWOh4CV{>SjuDZ z_oWMXhsV2Mr+5Nxbo)gOxE7|JM<;7W^sJON+Lx*8 zyRm1py1O81Rd0!t&x^C!G-tDA&St~rP15WK7gL$7w?c@%MdqmrgV{OcwyM9^xhVdF zWsJqdf!Q^LY6n3iomn~z33H&6C~#@W5#o+e9DlDlqfJu zhB(ZUAr7-ch{Nm*vS23dj!epSIw2e7=|1UXAZ!Y`!c%tikPDhoBX~J|=YCTtDP>B8 Sf%&$>fp>MbFE6J5ME?UNA*Bld diff --git a/src/VulkanRenderer b/src/VulkanRenderer index c42238a..748c8ec 160000 --- a/src/VulkanRenderer +++ b/src/VulkanRenderer @@ -1 +1 @@ -Subproject commit c42238a456f5048c7d1b2d5ebd71ecf13bb10ece +Subproject commit 748c8ec00e098ba2a55ba1a6b831ed6f5b63f85a diff --git a/src/dlib b/src/dlib index 493c17c..292bb10 160000 --- a/src/dlib +++ b/src/dlib @@ -1 +1 @@ -Subproject commit 493c17cba26952861ae4c5402f1676013b8317c6 +Subproject commit 292bb10214869da59a8fcaeda9bfce813ac28ad7 diff --git a/src/gears/game2.d b/src/gears/game2.d index 7a80349..5bed4ec 100644 --- a/src/gears/game2.d +++ b/src/gears/game2.d @@ -21,6 +21,9 @@ struct RenderState Arena[2] frame_arenas; Arena perm_arena; + u64 frame; + u64 frame_idx; + PushConst pc; ShaderGlobals globals; @@ -36,8 +39,9 @@ struct RenderState Buffer[] model_states; u64 itex, imat, istate; - ImageView placeholder_tex; - Buffer globals_buffer; + Descriptor default_tex; + Descriptor default_mat; + Descriptor[2] globals_buffer; } struct ShaderGlobals @@ -49,12 +53,29 @@ struct ShaderGlobals f32 alpha = 0.0; } -struct ModelRenderInfo +struct Model { - PushConst pc; - PipelineID pid; + Buffer vtx_buf; + Buffer idx_buf; + Descriptor[] tex; + Descriptor[] mats; + PipelineID[] mat_pipelines; + DescSet[] resource_sets; + Mesh[] meshes; +} - alias pc this; +struct RenderObject +{ + Model* model; + Descriptor[2] state_descs; + ModelState[2] state; + DescSet[2] state_sets; + bool[2] pending_update; +} + +struct Entity +{ + Model* model; } struct ModelState @@ -64,45 +85,59 @@ struct ModelState enum PBRMod : u32 { - AlbedoValue = 0x0001, - AmbientValue = 0x0002, - SpecularValue = 0x0004, - AlphaValue = 0x0008, - AlbedoTexture = 0x0010, - AmbientTexture = 0x0020, - SpecularTexture = 0x0040, - AlphaTexture = 0x0080, + None = 0x000, + AlbedoTexture = 0x001, + NormalTexture = 0x002, + MetalRoughTexture = 0x004, + OcclusionTexture = 0x008, + EmissionTexture = 0x010, } -enum PipelineID : u32 +enum PipelineID { None, - PBRVVVV, - PBRTVVV, - PBRVTVV, - PBRVVTV, - PBRVVVT, - PBRTTVV, - PBRTVTV, - PBRTVVT, - PBRVTTV, - PBRVTVT, - PBRVVTT, - PBRVTTT, - PBRTVTT, - PBRTTVT, - PBRTTTV, - PBRTTTT, + PBRVVVVV, + PBRTVVVV, + PBRVTVVV, + PBRTTVVV, + PBRVVTVV, + PBRTVTVV, + PBRVTTVV, + PBRTTTVV, + PBRVVVTV, + PBRTVVTV, + PBRVTVTV, + PBRTTVTV, + PBRVVTTV, + PBRTVTTV, + PBRVTTTV, + PBRTTTTV, + PBRVVVVT, + PBRTVVVT, + PBRVTVVT, + PBRTTVVT, + PBRVVTVT, + PBRTVTVT, + PBRVTTVT, + PBRTTTVT, + PBRVVVTT, + PBRTVVTT, + PBRVTVTT, + PBRTTVTT, + PBRVVTTT, + PBRTVTTT, + PBRVTTTT, + PBRTTTTT, Max, } alias PID = PipelineID; const PID[] PBR_PIPELINES = [ - PID.PBRVVVV, PID.PBRTVVV, PID.PBRVTVV, PID.PBRVVTV, - PID.PBRVVVT, PID.PBRTTVV, PID.PBRTVTV, PID.PBRTVVT, - PID.PBRVTTV, PID.PBRVTVT, PID.PBRVVTT, PID.PBRTTTV, - PID.PBRTTVT, PID.PBRTVTT, PID.PBRVTTT, PID.PBRTTTT, + PID.PBRVVVVV, PID.PBRTVVVV, PID.PBRVTVVV, PID.PBRTTVVV, PID.PBRVVTVV, PID.PBRTVTVV, PID.PBRVTTVV, PID.PBRTTTVV, + PID.PBRVVVTV, PID.PBRTVVTV, PID.PBRVTVTV, PID.PBRTTVTV, PID.PBRVVTTV, PID.PBRTVTTV, PID.PBRVTTTV, PID.PBRTTTTV, + PID.PBRVVVVT, PID.PBRTVVVT, PID.PBRVTVVT, PID.PBRTTVVT, PID.PBRVVTVT, PID.PBRTVTVT, PID.PBRVTTVT, PID.PBRTTTVT, + PID.PBRVVVTT, PID.PBRTVVTT, PID.PBRVTVTT, PID.PBRTTVTT, PID.PBRVVTTT, PID.PBRTVTTT, PID.PBRVTTTT, PID.PBRTTTTT, ]; struct PushConst @@ -130,12 +165,22 @@ struct PushConst } } -ModelData g_box; +Model g_model; +RenderObject g_object; void RunCycle(GameState* g) { + BeginFrame(&g.rds.rd); + BeginRendering(&g.rds.rd); + Render(&g.rds, &g_object); + + FinishRendering(&g.rds.rd); + SubmitAndPresent(&g.rds.rd); + + g.rds.frame += 1; + g.rds.frame_idx = g.rds.frame % 2; } GameState @@ -175,7 +220,7 @@ Init(RenderState* rds, PlatformWindow* window) { binding: 1, descriptorType: DT.Image, descriptorCount: 1, stageFlags: SS.All }, { binding: 2, descriptorType: DT.Image, descriptorCount: 1, stageFlags: SS.All }, { binding: 3, descriptorType: DT.Image, descriptorCount: 1, stageFlags: SS.All }, - { binding: 4, descriptorType: DT.Uniform, descriptorCount: 1, stageFlags: SS.All }, + { binding: 4, descriptorType: DT.Image, descriptorCount: 1, stageFlags: SS.All }, { binding: 5, descriptorType: DT.Uniform, descriptorCount: 1, stageFlags: SS.All }, ]; @@ -209,7 +254,7 @@ Init(RenderState* rds, PlatformWindow* window) rds.desc_set_globals[i] = AllocDescSet(&rds.rd, rds.desc_layout_globals); } - u32[4] spec_data; + u32[5] spec_data; Specialization spec = { data: spec_data.ptr, @@ -219,6 +264,7 @@ Init(RenderState* rds, PlatformWindow* window) { constantID: 1, size: u32.sizeof, offset: u32.sizeof*1 }, { constantID: 2, size: u32.sizeof, offset: u32.sizeof*2 }, { constantID: 3, size: u32.sizeof, offset: u32.sizeof*3 }, + { constantID: 4, size: u32.sizeof, offset: u32.sizeof*4 }, ], }; @@ -237,59 +283,198 @@ Init(RenderState* rds, PlatformWindow* window) { u32 mod = PIDToPBR(pid); spec_data[0] = mod & PBRMod.AlbedoTexture; - spec_data[1] = mod & PBRMod.AmbientTexture; - spec_data[2] = mod & PBRMod.SpecularTexture; - spec_data[3] = mod & PBRMod.AlphaTexture; + spec_data[1] = mod & PBRMod.NormalTexture; + spec_data[2] = mod & PBRMod.MetalRoughTexture; + spec_data[3] = mod & PBRMod.OcclusionTexture; + spec_data[4] = mod & PBRMod.EmissionTexture; bool result = CreateGraphicsPipeline(&rds.rd, &rds.pipelines[pid], &pbr_info); assert(result); } - const u64 tex_size = 32*32*4; - u8[tex_size] placeholder_tex; - - u8[4] magenta = [255, 0, 255, 255]; - u8[4] black = [0, 0, 0, 255]; - u64 half = tex_size/2; - for(u64 i = 0; i < tex_size; i += 32) - { - bool swap = i <= half; - for(u64 j = 0; j < 16; j += 4) - { - placeholder_tex[i+j .. i+j+4] = !swap ? magenta[0 .. $] : black[0 .. $]; - placeholder_tex[i+j+16 .. i+j+16+4] = !swap ? black[0 .. $] : magenta[0 .. $]; - } - } - - CreateImageView(&rds.rd, &rds.placeholder_tex, 32, 32, 4, placeholder_tex); - - CreateBuffer(&rds.rd, &rds.globals_buffer, BT.Uniform, ShaderGlobals.sizeof, false); + CreateBuffer(&rds.rd, &rds.globals_buffer[0], BT.Uniform, ShaderGlobals.sizeof, false, DT.Uniform); + CreateBuffer(&rds.rd, &rds.globals_buffer[1], BT.Uniform, ShaderGlobals.sizeof, false, DT.Uniform); ModelData md = LoadGLTF(&rds.frame_arenas[0], "assets/models/DamagedHelmet.glb"); + + rds.default_tex = Upload(rds, &DEFAULT_IMAGE); + + CreateBuffer(&rds.rd, &rds.default_mat, BT.Uniform, Material.sizeof, false, DT.Uniform); + + bool result = Transfer(&rds.rd, &rds.default_mat.buf, &DEFAULT_MATERIAL); + assert(result); + + g_model = Upload(rds, &md); + g_object = CreateRenderObject(rds, &g_model); +} + +void +Render(RenderState* rds, RenderObject* obj) +{ + DescSet[3] sets; + sets[0] = rds.desc_set_globals[rds.frame_idx]; + sets[2] = obj.state_sets[rds.frame_idx]; + + BindBuffers(&rds.rd, &obj.model.idx_buf, &obj.model.vtx_buf); + foreach(i; 0 .. obj.model.meshes.length) + { + Mesh* mesh = obj.model.meshes.ptr + i; + + sets[1] = obj.model.resource_sets[i]; + + Bind(&rds.rd, rds.pipelines[obj.model.mat_pipelines[mesh.mat_id]], sets, false); + DrawIndexed(&rds.rd, mesh.length, 1, mesh.offset); + } +} + +Descriptor +Upload(RenderState* rds, ImageData* image) +{ + Descriptor desc; + CreateImageView(&rds.rd, &desc, image.w, image.h, image.ch, image.data, DT.Image); + return desc; +} + +Model +Upload(RenderState* rds, ModelData* md) +{ + Model model = { + meshes: md.meshes, + }; + + CreateBuffer(&rds.rd, &model.vtx_buf, BT.Vertex, Vertex.sizeof*md.vtx_buf.length, false); + CreateBuffer(&rds.rd, &model.idx_buf, BT.Index, u32.sizeof*md.idx_buf.length, false); + + bool result = true; + result &= Transfer(&rds.rd, &model.vtx_buf, md.vtx_buf); + result &= Transfer(&rds.rd, &model.idx_buf, md.idx_buf); + + assert(result, "Failed to transfer vtx/idx buffer"); + + model.tex = Alloc!(Descriptor)(md.tex.length); + model.mats = Alloc!(Descriptor)(md.mats.length); + model.mat_pipelines = Alloc!(PipelineID)(md.mats.length); + model.resource_sets = Alloc!(DescSet)(md.mats.length); + + model.tex[0] = rds.default_tex; + model.mats[0] = rds.default_mat; + model.mat_pipelines[0] = PID.PBRVVVVV; + + foreach(i; 1 .. md.tex.length) + { + CreateImageView(&rds.rd, &model.tex[i], md.tex[i].w, md.tex[i].h, md.tex[i].ch, md.tex[i].data, DT.Image); + } + + foreach(i; 1 .. md.mats.length) + { + MaterialMap[] maps = md.mats[i].maps; + + bool albedo = maps[MMI.Albedo].tex_id > 0, + normal = maps[MMI.Normal].tex_id > 0, + metal_rough = maps[MMI.Metallic].tex_id > 0, + occlusion = maps[MMI.Occlusion].tex_id > 0, + emission = maps[MMI.Emission].tex_id > 0; + + model.resource_sets[i] = AllocDescSet(&rds.rd, rds.desc_layout_resources); + model.mat_pipelines[i] = GetPBRID(albedo, normal, metal_rough, occlusion, emission); + + CreateBuffer(&rds.rd, &model.mats[i], BT.Uniform, Material.sizeof, false, DT.Uniform); + + result = Transfer(&rds.rd, &model.mats[i].buf, &md.mats[i]); + assert(result); + + Descriptor[6] descs = [ + model.tex[maps[MMI.Albedo].tex_id], + model.tex[maps[MMI.Normal].tex_id], + model.tex[maps[MMI.Metallic].tex_id], + model.tex[maps[MMI.Occlusion].tex_id], + model.tex[maps[MMI.Emission].tex_id], + model.mats[i], + ]; + + foreach(j; 0 .. descs.length) + { + descs[j].binding = cast(u32)j; + } + + Write(&rds.rd, model.resource_sets[i], descs); + } + + return model; +} + +RenderObject +CreateRenderObject(RenderState* rds, Model* model) +{ + RenderObject rdobj = { + model: model, + state: [DefaultModelState(), DefaultModelState()], + }; + + foreach(i; 0 .. 2) + { + CreateBuffer(&rds.rd, &rdobj.state_descs[i], BT.Uniform, ModelState.sizeof, false, DT.Uniform); + bool result = Transfer(&rds.rd, &rdobj.state_descs[i].buf, &rdobj.state[i]); + + rdobj.state_sets[i] = AllocDescSet(&rds.rd, rds.desc_layout_state); + Write(&rds.rd, rdobj.state_sets[i], &rdobj.state_descs[i]); + } + + return rdobj; +} + +ModelState +DefaultModelState() +{ + return ModelState( + matrix: Mat4Identity(), + ); +} + +PipelineID +GetPBRID(bool albedo, bool normal, bool metal_rough, bool occlusion, bool emission) +{ + return PBRToPID(GetPBRMod(albedo, normal, metal_rough, occlusion, emission)); } PipelineID PBRToPID(u32 mod) { - switch(mod) + switch(mod) with(PID) { - case GetPBRMod(false, false, false, false): return PID.PBRVVVV; - case GetPBRMod(true , false, false, false): return PID.PBRTVVV; - case GetPBRMod(false, true , false, false): return PID.PBRVTVV; - case GetPBRMod(false, false, true , false): return PID.PBRVVTV; - case GetPBRMod(false, false, false, true ): return PID.PBRVVVT; - case GetPBRMod(true , true , false, false): return PID.PBRTTVV; - case GetPBRMod(true , false, true , false): return PID.PBRTVTV; - case GetPBRMod(true , false, false, true ): return PID.PBRTVVT; - case GetPBRMod(false, true , true , false): return PID.PBRVTTV; - case GetPBRMod(false, true , false, true ): return PID.PBRVTVT; - case GetPBRMod(false, false, true , true ): return PID.PBRVVTT; - case GetPBRMod(false, true , true , true ): return PID.PBRVTTT; - case GetPBRMod(true , false, true , true ): return PID.PBRTVTT; - case GetPBRMod(true , true , false, true ): return PID.PBRTTVT; - case GetPBRMod(true , true , true , false): return PID.PBRTTTV; - case GetPBRMod(true , true , true , true ): return PID.PBRTTTT; - default: return PID.None; + case GetPBRMod(false, false, false, false, false): return PBRVVVVV; + case GetPBRMod(true , false, false, false, false): return PBRTVVVV; + case GetPBRMod(false, true , false, false, false): return PBRVTVVV; + case GetPBRMod(true , true , false, false, false): return PBRTTVVV; + case GetPBRMod(false, false, true , false, false): return PBRVVTVV; + case GetPBRMod(true , false, true , false, false): return PBRTVTVV; + case GetPBRMod(false, true , true , false, false): return PBRVTTVV; + case GetPBRMod(true , true , true , false, false): return PBRTTTVV; + case GetPBRMod(false, false, false, true , false): return PBRVVVTV; + case GetPBRMod(true , false, false, true , false): return PBRTVVTV; + case GetPBRMod(false, true , false, true , false): return PBRVTVTV; + case GetPBRMod(true , true , false, true , false): return PBRTTVTV; + case GetPBRMod(false, false, true , true , false): return PBRVVTTV; + case GetPBRMod(true , false, true , true , false): return PBRTVTTV; + case GetPBRMod(false, true , true , true , false): return PBRVTTTV; + case GetPBRMod(true , true , true , true , false): return PBRTTTTV; + case GetPBRMod(false, false, false, false, true ): return PBRVVVVT; + case GetPBRMod(true , false, false, false, true ): return PBRTVVVT; + case GetPBRMod(false, true , false, false, true ): return PBRVTVVT; + case GetPBRMod(true , true , false, false, true ): return PBRTTVVT; + case GetPBRMod(false, false, true , false, true ): return PBRVVTVT; + case GetPBRMod(true , false, true , false, true ): return PBRTVTVT; + case GetPBRMod(false, true , true , false, true ): return PBRVTTVT; + case GetPBRMod(true , true , true , false, true ): return PBRTTTVT; + case GetPBRMod(false, false, false, true , true ): return PBRVVVTT; + case GetPBRMod(true , false, false, true , true ): return PBRTVVTT; + case GetPBRMod(false, true , false, true , true ): return PBRVTVTT; + case GetPBRMod(true , true , false, true , true ): return PBRTTVTT; + case GetPBRMod(false, false, true , true , true ): return PBRVVTTT; + case GetPBRMod(true , false, true , true , true ): return PBRTVTTT; + case GetPBRMod(false, true , true , true , true ): return PBRVTTTT; + case GetPBRMod(true , true , true , true , true ): return PBRTTTTT; + default: return None; } } @@ -298,36 +483,53 @@ PIDToPBR(PipelineID pid) { switch(pid) with(PID) { - case PBRVVVV: return GetPBRMod(false, false, false, false); - case PBRTVVV: return GetPBRMod(true , false, false, false); - case PBRVTVV: return GetPBRMod(false, true , false, false); - case PBRVVTV: return GetPBRMod(false, false, true , false); - case PBRVVVT: return GetPBRMod(false, false, false, true ); - case PBRTTVV: return GetPBRMod(true , true , false, false); - case PBRTVTV: return GetPBRMod(true , false, true , false); - case PBRTVVT: return GetPBRMod(true , false, false, true ); - case PBRVTTV: return GetPBRMod(false, true , true , false); - case PBRVTVT: return GetPBRMod(false, true , false, true ); - case PBRVVTT: return GetPBRMod(false, false, true , true ); - case PBRTTTV: return GetPBRMod(true , true , true , false); - case PBRTTVT: return GetPBRMod(true , true , false, true ); - case PBRTVTT: return GetPBRMod(true , false, true , true ); - case PBRVTTT: return GetPBRMod(false, true , true , true ); - case PBRTTTT: return GetPBRMod(true , true , true , true ); - default: return 0; + case PBRVVVVV: return GetPBRMod(false, false, false, false, false); + case PBRTVVVV: return GetPBRMod(true , false, false, false, false); + case PBRVTVVV: return GetPBRMod(false, true , false, false, false); + case PBRTTVVV: return GetPBRMod(true , true , false, false, false); + case PBRVVTVV: return GetPBRMod(false, false, true , false, false); + case PBRTVTVV: return GetPBRMod(true , false, true , false, false); + case PBRVTTVV: return GetPBRMod(false, true , true , false, false); + case PBRTTTVV: return GetPBRMod(true , true , true , false, false); + case PBRVVVTV: return GetPBRMod(false, false, false, true , false); + case PBRTVVTV: return GetPBRMod(true , false, false, true , false); + case PBRVTVTV: return GetPBRMod(false, true , false, true , false); + case PBRTTVTV: return GetPBRMod(true , true , false, true , false); + case PBRVVTTV: return GetPBRMod(false, false, true , true , false); + case PBRTVTTV: return GetPBRMod(true , false, true , true , false); + case PBRVTTTV: return GetPBRMod(false, true , true , true , false); + case PBRTTTTV: return GetPBRMod(true , true , true , true , false); + case PBRVVVVT: return GetPBRMod(false, false, false, false, true ); + case PBRTVVVT: return GetPBRMod(true , false, false, false, true ); + case PBRVTVVT: return GetPBRMod(false, true , false, false, true ); + case PBRTTVVT: return GetPBRMod(true , true , false, false, true ); + case PBRVVTVT: return GetPBRMod(false, false, true , false, true ); + case PBRTVTVT: return GetPBRMod(true , false, true , false, true ); + case PBRVTTVT: return GetPBRMod(false, true , true , false, true ); + case PBRTTTVT: return GetPBRMod(true , true , true , false, true ); + case PBRVVVTT: return GetPBRMod(false, false, false, true , true ); + case PBRTVVTT: return GetPBRMod(true , false, false, true , true ); + case PBRVTVTT: return GetPBRMod(false, true , false, true , true ); + case PBRTTVTT: return GetPBRMod(true , true , false, true , true ); + case PBRVVTTT: return GetPBRMod(false, false, true , true , true ); + case PBRTVTTT: return GetPBRMod(true , false, true , true , true ); + case PBRVTTTT: return GetPBRMod(false, true , true , true , true ); + case PBRTTTTT: return GetPBRMod(true , true , true , true , true ); + default: return 0; } } static u32 -GetPBRMod(bool albedo = false, bool ambient = false, bool specular = false, bool alpha = false) +GetPBRMod(bool albedo = false, bool normal = false, bool metal_rough = false, bool occlusion = false, bool emission = false) { with(PBRMod) { return - (albedo ? AlbedoTexture : AlbedoValue) | - (ambient ? AmbientTexture : AmbientValue) | - (specular ? SpecularTexture : SpecularValue) | - (alpha ? AlphaTexture : AlphaValue); + (albedo ? AlbedoTexture : None) | + (normal ? NormalTexture : None) | + (metal_rough ? MetalRoughTexture : None) | + (occlusion ? OcclusionTexture : None) | + (emission ? EmissionTexture : None); } } diff --git a/src/shaders/structures.layout b/src/shaders/structures.layout index fafab1a..5b9a729 100644 --- a/src/shaders/structures.layout +++ b/src/shaders/structures.layout @@ -1,17 +1,38 @@ -// DEFINES +// TYPES -#define OIT_LAYERS 16 +#define u32 uint +#define i32 int +#define b32 bool +#define f32 float +#define f64 double -#define IMG_MAX 100 -#define BUF_MAX 25 -#define UNI_MAX 50 +// CONSTANTS + +const u32 OIT_LAYERS = 16; +const u32 IMG_MAX = 100; +const u32 BUF_MAX = 25; +const u32 UNI_MAX = 50; + +const u32 MAT_ALBEDO = 0; +const u32 MAT_NORMAL = 1; +const u32 MAT_METALLIC = 2; +const u32 MAT_ROUGHNESS = 3; +const u32 MAT_OCCLUSION = 4; +const u32 MAT_EMISSION = 5; +const u32 MAT_HEIGHT = 6; +const u32 MAT_CUBEMAP = 7; +const u32 MAT_IRRADIANCE = 8; +const u32 MAT_PREFILTER = 9; +const u32 MAT_BRDF = 10; +const u32 MAT_MAX = 11; // SPEC CONSTANTS -layout (constant_id = 0) const bool ALBEDO_TEX = false; -layout (constant_id = 1) const bool AMBIENT_TEX = false; -layout (constant_id = 2) const bool SPECULAR_TEX = false; -layout (constant_id = 3) const bool ALPHA_TEX = false; +layout (constant_id = 0) const bool ALBEDO_TEX = false; +layout (constant_id = 1) const bool NORMAL_TEX = false; +layout (constant_id = 2) const bool METALLIC_ROUGHNESS_TEX = false; +layout (constant_id = 3) const bool OCCLUSION_TEX = false; +layout (constant_id = 4) const bool EMISSION_TEX = false; // SET 0 @@ -34,16 +55,15 @@ layout (set = 1, binding = 2, r32ui) uniform coherent uimage2D ImageAux; // SET 2 layout (set = 2, binding = 0) uniform texture2D AlbedoTex; -layout (set = 2, binding = 1) uniform texture2D AmbientTex; -layout (set = 2, binding = 2) uniform texture2D SpecularTex; -layout (set = 2, binding = 3) uniform texture2D AlphaTex; -layout (set = 2, binding = 4) uniform MaterialData { - vec4 ambient; - vec4 diffuse; - vec4 specular; - float shininess; - float alpha; -} Material; +layout (set = 2, binding = 1) uniform texture2D NormalTex; +layout (set = 2, binding = 2) uniform texture2D MRTex; // Metallic Roughness +layout (set = 2, binding = 3) uniform texture2D OcclusionTex; +layout (set = 2, binding = 4) uniform texture2D EmissionTex; +layout (set = 2, binding = 5) uniform MaterialData { + vec4 col; + u32 padding; + f32 value; +} Material[MAT_MAX]; layout (set = 3, binding = 0) uniform ModelState { mat4 model_matrix; @@ -52,19 +72,20 @@ layout (set = 3, binding = 0) uniform ModelState { // PUSH CONSTANTS layout (push_constant) uniform PushConstants { - uint t0; - uint t1; - uint t2; - uint t3; - uint m0; - uint s0; + u32 t0; + u32 t1; + u32 t2; + u32 t3; + u32 m0; + u32 s0; } PC; // ALIAS MACROS -#define ModelMatrix State.model_matrix -#define ModelAmbient Material.ambient -#define ModelDiffuse Material.diffuse -#define ModelSpecular Material.specular -#define ModelShininess Material.shininess -#define ModelAlpha Material.alpha +#define ModelMatrix State.model_matrix +#define Albedo Material[MAT_ALBEDO].col; +#define Metallic(uv) texture(sampler2D(MRTex, SamplerNearest), uv).b +#define Roughness(uv) texture(sampler2D(MRTex, SamplerNearest), uv).g +#define MetallicFactor Material[MAT_METALLIC].value +#define RoughnessFactor Material[MAT_ROUGHNESS].value +#define EmissiveFactor Material[MAT_EMISSION].value