From d88413860b59d5c9aa02670a69d2a9beb68b916f Mon Sep 17 00:00:00 2001 From: matthew Date: Sat, 2 Aug 2025 08:47:19 +1000 Subject: [PATCH] some restructuring, fix a crash --- assets/shaders/gradient.comp.spv | Bin 3776 -> 3944 bytes assets/shaders/gui.frag.spv | Bin 2548 -> 2716 bytes assets/shaders/gui.vert.spv | Bin 5020 -> 5204 bytes assets/shaders/pbr.frag.spv | Bin 2456 -> 5072 bytes assets/shaders/pbr.vert.spv | Bin 4628 -> 4184 bytes assets/shaders/triangle.frag.spv | Bin 2512 -> 2664 bytes assets/shaders/triangle.vert.spv | Bin 3404 -> 3556 bytes src/gears/game.d | 29 +++++++++++- src/gears/main.d | 6 +-- src/gears/platform.d | 9 +++- src/gears/renderer.d | 77 +++++++++++++++++++++---------- src/shaders/pbr.frag.glsl | 24 ++++++++-- src/shaders/pbr.vert.glsl | 18 +++----- src/shaders/structures.layout | 3 ++ src/shared/math.d | 22 +++++++-- 15 files changed, 138 insertions(+), 50 deletions(-) diff --git a/assets/shaders/gradient.comp.spv b/assets/shaders/gradient.comp.spv index 06f853335a1ef24a644bc00007ecdba683723930..a2239d5f187bb68c252dc0fd5e84a27be6dd62a7 100644 GIT binary patch delta 1495 zcmYjRO>fgc5MA4GN?Ia;tSTy1Q)tu^m7s_N5~`>KsFhGJw1GltQ#;utF0NfUE^tAC zpHS^D=ubdBajV3M0}}lQa6p0^S8lww_D0$0d3N4>cxQH;^SR&ks$(}MMA;HkqAFgW zRClJI3n5+tyMPZ!p#SOplr_`DZY@dzKWfHdH%Si%LX`1qs#B|GHPvTpen=l1coWLE zt)nzKknJo?;@l6s14Lo3pS9Xal%(J%1Y=5oe;9-^HWud2ZSE+h6Q-klB^_6WEtLb| zA~Q}tDb_%^2;Ej!?b_ltG_Iq_Z_9oXb!4htS>Pr>&t0`)*H&2SmVB2TGn=-!B7ofR zGns~dM6L{fa$Ln>b55Pw-V7})eQ+e($C01XizNi=n>}j<>W_Z9&OG*u`uSKtrPI){ z6~^|%IE>|hM{x0z>eTV3yU-pc@gVc#j233?s;|zhwpd^e{j3#s7~_b(`sX~EGZ(Rr z)^g9qMy})8RDQ|ZHEcuMXvsa9Z{&$R^$Fk#prZ?pajTlk<5>GBPF<9|(J;{SgZ9L` zAvpx(&HQk7{_enevEOvaB_cvHJq5^dIR7x`a-S_K{$dVz@za+W*nG+ivb)3 zCSaLHFA`{--vRATVW&QB_X|6O_NPv}B|H+2o)~k0KwXr*=|G$FI!sps_0#oMXyJ=^ zz}o;1P0n=Z?igpfbI)*Ux$F(;&D&yzRlsDpRB(^RI8Ge>)&Z6-Az3Py(HF3{weASc zA@`gV?zzm37rN?|s#cd(THUi>OZXp{f;=cV@MjMuKbHOjo0zGe delta 1348 zcmY+D&rVZO5XR5#?H>V2Od2GWP{78OB*w&rL`h6E0b|@q5fzXg$^kAZEw)A7n93uV z8<#G81VUW6Bk>7*2%}rx!0&hNy@=DyJ!ii8X3m_M(?8YI$b z_S_irQo1H>NVlXr#~((5N?p5!R%g?;mfO*Gr@P-Xrl?;%{u+!2_4s=*H3ugreH*!V z8wcIao@@4_PFt+J!52!qu4f9`angdcAn!_SbK^HwWFZGF+jP5~)|TsfCiN^yVXnnr za^v$2S#|fme@HU#DHyBusqMRNWLscG@xc(gzZto9Kf&U&T)BdWN_z*cdDyaDSVdDZ zHl7S80vpfy?{YY${h|MU_TO(|&BqQAyBoEmw(C(sLBFl|EG&;XSr0qyUf;I+c*yGF zN`At70wMdhzY(dibYUlcoPRQz^=&cjlSuL!v#4)9KF*idVIZ|+ktgXW`OcZzW0#~? zq&_;uh(V{5XOCnvbi5M(!a&K2a0_?xrt~8ikff@|$Vi`E&?W7sm2g=r9Q^lEn^7lm z$yn7R&wY{Nj2A98V}*N7-&b16xvCYBebo~I7$;KE{nz7PL$%wlWvxr8ny?M62sr7n z8&afdF6%!!H+*ZbDa%T;sHXN508SJ(9R#b&rej=uSjs8eTA2VieC(YRyD1yqu9PP- RtHzCJjZ#eb$?xH#{9pC|k757- diff --git a/assets/shaders/gui.frag.spv b/assets/shaders/gui.frag.spv index a9ba04a8f3e769d7f6ccefb87e1a4774cc19d2f1..bcbfac2dbc9f07bfcf4fb2a5fe5c17b0a42fb10e 100644 GIT binary patch literal 2716 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 g6o{=R_#!{m`deXDugRbJP9{_#h5dZ)H delta 1668 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 literal 2456 zcmZvd+inv{5QaM$+X;m8a$Yt}I4?+u3l<@k zw0!^`h#MsSuV>nxMU++UuD=dlRb6dI%hy-TV9BhRskLwsBOtN4`S;I|@<^jX&W zSwVYd)eLu%XK!C8d6CcZbiXJk$%mQE(*4wx(jP@XeED*?^DG%nr%6@+ler{IbC-j^}LR5m#)&;k?-kH zGI^ZQx_e;9uKa%<;LtR)BX>|_GVs3K#jcn-xs#`*{rLC9zEi7wJnm@MPNtbFUpT81 z>&7+~{@Q)2XCxuQe?#kYTe~u~>I!u<7<)U}OI=>iF=`*D`}?!X2^)A{>aC`3G|Mb) z7P{hbYPH#(8y8949J$bOS8eRMlKzrQUmW7imBNC4fNvA`z*Y;3pl1d{?5@E;6G8k{ z@jQOlKzOK$xvvh=Tw_?#DEh>_hdu@Drm(FduWFmuVAKuXI^q%kgjV8n_PTbwD{KOzCocDj4SLQ+ zX098*W`>)*d#bC!nPqH|nPF@%>D8apiY+;H2|dht=UWA~#6V`Qq06$ms1>_Q9-+3z z4w?CeIO}JvKRPR%eNHj1$R-v;_geWE?XkHcnfoFR7-wG93W1Xwax8|{%`rb$^gl51 zf5hZP{A*e_#34R2L?6J3kIcM+txIOExSuBPp1GwxGXRb~^6eHQ-#gk<3wMbgnK=Y| iq&X!n^8hhNUxf6v{vnhaj)|F}Kc(dy5_+ zHC^9cTv;PZd})QKZp{PZIXkMw_jw zd@Xq_@g;$zBdO`LS^XahUiY?m?M46Qqx*i6CZi-;O|!oL(30VMf0)0BLqCp^(CQxC1MXKiC@EUFnFZ_OxXVG(|Bc$o= zSHBkf%VG8~%<|CT%@T)$EgeRAlqN!_9G@CFJWBGF=x1f)jcu$`wz)VO%tymKNV?(J zMuoAB;&^Ops5aDLTM(d}&FrK6>Tft{t+ATlo5u@hL-SQmcx;uYS;tx^n1Se#8y2IX5{?g$9b@L6Hj~#J7=PdyB-WD46{#RFV9+)(Db&t_*<&+s|4Y;rmb++ zqeRcdkU~*s-XN<}fz{ocq`lN(FE|}>r0ZC&>8R`OsS3Oa)M!C57}K^F-58^;VD!er z2aGxz#u$wH5!>$Lf)K_u>IdI+>hbyp?3i?#`7v+R4}GH_7=E)7^CQQqANoc=F#KLh zEHBmp_Im|mO<;dkFk*xKRl(SQu)ig3t()JF841nwqlM~fbX;R{AZNxj%h~iPVOAr< zn1e>nVAb_A55HN{5@Mrs_t9zS+&fvkzY%4K>p-~&e{&@o1DPVTlyv+?BJJ5o&Q2$C#BODZ^O%L zroSePc1n?mwL=02+{Cy$g?Zk~-;BGfgXTv61&15^^9mG2re~ z?t9d?BsB6t-z%YZN2Kpl&-%coHR3I_dSOGT(E;_;7dtgV=RXY?^Bhv&k`R}9&<{&! z?7^GrnFl`lky2;BrnLjSi>$+h91#5Ak^^S|K3sA@=bZtwIa?Z&1N<5F*oZkT{dhSp zYEt*!m(JdU6A%4FiQ)f2ImRFTw0dHb6MS^u8!+tW)w4eGWyyChYmEgn5booqBvM{`VTQPH^I*^Df!if6$oxh>smTkbs%q zDfRPutMTK#p|M~82;p75Dvh^>`+Hr;jQXPz&UH(2MP8i0V-j%VyrVH3?wE1j)foI& z#lh!234Y-Cah^{~IOA2nQzdSGA4+&}Vc_IV9&-{f+LEeC4dx}_2#s~JF7vsmF+Sktb4z1zgtpPAEes#xn9qX7 x;0VopmR0#1(r-)1h1hUykG|BH`%f*&cToZtoVD{F+?7xpt0g+Te>KYm$$#U0Z5aRn literal 4628 zcmZve*>)6V5XU>2CG5z)#{h~bh^T-dA_)mjkN|-IMnIa*OlQ*A(=+tUgv|?Xd;on7 zZ`BLE&>7<-mo_$5&qNG zjQ^bTUvmDd_*$>({Ax3EGsn8U#<3G8kCS18S8|ESvC-S+sMzm8jDmpBB zPjpUnOSB+ridv$Ms3&?XdMbJ*dM+yI->~=}Dp2-Td9@k;;`~iNX(#<8T5P8+|4~1P zqs1spWnY86cI{ei=AvKkbo_4bX&m}-l!SgGO2c|DS`G(!a=$34$Nfgpp`uL1HB`Kc zTgOws74*{RiP{lT^|p&QV}CYGZ-;3wba*w#@xj*aM!l$=2pw_$%*o+V(wmE(sT*%# zW1X^1#!+V~>h^-99u90w8CyS&2eyi4!)*EJXRmlIZZ8D!t!y@3a%VU`%Tf5)mQd9! z@u#0o+J4Av+KE}Sp0LxCi+ky$jAa)~Pifdy?ULKynsjD$NPM!Lu!5dikpGCoBzmoO zBaB~`kuCG54^7vP8ssRsvobr0Ty|$BO8ib+$*`S~Z@nE$u6Q3yz7q7pGzwygE*}_Q z&{~MXq&L8*(TElo`(5T*b+N3k+X?IaI7o@1SK?V)5HEy{wy&M-^;7MX**F_{?tzhc z5?2vfzJXDg*{j56d6$CjOAoV;V9)yYiw;$9wadS%n7`=YYGi9#jn7h)=-79eKXc;F z*_<-0>|Gb8#rZZ%?&QsEvA8Iz>h9=V(CWltdNmBR+q$Ie3HMfe(qDFdWp{_${a&7{ z?Cvu<4&-6Db4x)ZO#gp2-Oy$0#6dk=YR7Vrf62WCb1rwqy$Mrk@c2?IXmVkw&l{oo zv@X5k-V5nEa!t0}VZ0y061@`caMYBSJIkI=%LAEjZN>%|=L8IHe#C%rE(}8k<2;bt z?#r|gWIoOV{-(3PudToiO6RjU>K5bBSH^)6H!iX`dMw7FuZ#mD?uE$uVjW<=i)!kf zw|c*b&-4SC>ek8qCJ%Ly`K+$##kz)3gO9pk#Whfe-v(-vn|X4dvO3v4m+Jb2lLNcu zu$fv6wZ;m5wnl!mES7!4??eG(9bl&mST)B!DPXJ*zwrXb-2|H|VBAHpX%TDW9u{Yd zen4bvo{;?G)@=Qg1(}?N*9!9I1^MzoF1z2?Vjb=_b%sRDc7EVn^6nJmy9N1PLB3y* z{efI|?*ny8BG$JcP8~k;I2GeYO@8ZheY5+4%{iKv6VTg1m6>=CC9`$HYxTKYD^PMv+?_+Y0FI(rRfd0&@I z9sI|{v5{v~`k`FT)?N1AlFt5ulMnrHjuHQME)!3m?~2nW>%x9aoLb<-qw@xWVLv5~ zFEc~uO+to7wUfMcro-v$RYc8w%5+wo7;^EJu{JPjqw^MlVgFQ|wb@!PPlwDVB|vY?C89EV5al#na;U;p6jRd z?ox;Mi;p$@C4}EaVmX6nM3x(!za!BNq#>DrFxMSR_bBgCK91ww<&q2xf zaHq}Z4awl&D-SVmiiiUzj=S}a=&-05cO=Ix?x=KP!O6{CJ1*j$T~{7v{eFX_V# zj2W5VhdIW4X0>A0d_qJ#{@8gpzf)dpCq>l9hn_h%ABlE~=$Uz;uFvxnDul= zGChIw4zS0}=&lHx#ofy>YVk(g7u^zp6LUk{7lETc5U-0CM7I^w5D!K8faAk`UlKJ% z^Z9v*B;yA@ELtaG{@f94#IZLIMeK>`UrWa4Th+oIi|_%r{R8`3S#5T3i%%qz4`1FU UbnEevWO~Hb5l8=5xBs;0KR;uVoB#j- diff --git a/assets/shaders/triangle.frag.spv b/assets/shaders/triangle.frag.spv index 4af8fe943350d47e45900ec90bff54cef95fbfb9..7c6c2436b8a7bfbcc330716943d278513807f405 100644 GIT binary patch delta 196 zcmca0{6b{IJjQS~22lnE24*16$xP2EiBHbY$uDAHV_*l1vjD{tbCWVt^I$Rza5+}E zo|Md@)Z~)P{5+r>3s@i9=B13x%$6PutZ-wLfyyrcF-#1k9VGSuNsJ9D_F?lv WoM6quKtUL02eLt!YjY`kG!pztq3&$ diff --git a/assets/shaders/triangle.vert.spv b/assets/shaders/triangle.vert.spv index c1859a74a300329fc23c2e8b18a9cd87a51f4d53..bdd93bf9ba7c6b8e793649e9bc2ff7d2483be9b2 100644 GIT binary patch delta 196 zcmX>j^+b9@7*jYKgE<2O12YikWTt17#3$$H1t WCs?x?P!NV?fou>K**ukNI}-qN3LtU- delta 46 ucmaDNeMV|S7!x}SgE<2O1M}v!O!3T{J=jjM@UwwM%z&a`yjhofI}-r>-3eF# diff --git a/src/gears/game.d b/src/gears/game.d index f019bd4..4c317a4 100644 --- a/src/gears/game.d +++ b/src/gears/game.d @@ -26,6 +26,7 @@ struct Game Pipeline ui_pipeline; GlobalUniforms globals; + PushConst pc; f32 delta; Timer timer; @@ -35,6 +36,7 @@ struct Game Model model; } + Game InitGame(PlatformWindow* window) { @@ -42,6 +44,11 @@ InitGame(PlatformWindow* window) rd: InitRenderer(window), window: window, timer: CreateTimer(), + globals: { + light_direction: Vec3(-0.57735), + light_color: Vec4(0.8, 0.8, 0.8, 1.0), + ambient_color: Vec4(0.7, 0.7, 0.7, 1.0), + }, }; GfxPipelineInfo triangle_info = { @@ -123,7 +130,7 @@ Update(Game* g, Camera* cam) Extent ext = GetExtent(&g.rd); g.globals.view_matrix = ViewMatrix(cam); - Perspective(&g.globals.projection_matrix, Radians(70.0), cast(f32)(ext.x), cast(f32)(ext.y), 10000.0, 0.1); + Perspective(&g.globals.projection_matrix, Radians(90.0), cast(f32)(ext.x), cast(f32)(ext.y), 0.1, 10000.0); g.globals.projection_matrix[1, 1] *= -1.0; g.globals.view_projection = g.globals.projection_matrix * g.globals.view_matrix; @@ -138,6 +145,7 @@ RotationMatrix(Camera* cam) Quat pitch_rotation, yaw_rotation; QuatFromAxis(&pitch_rotation, cam.pitch, Vec3(1.0, 0.0, 0.0)); QuatFromAxis(&yaw_rotation, cam.yaw, Vec3(0.0, -1.0, 0.0)); + Mat4 pitch_mat = cast(Mat4)(yaw_rotation) * cast(Mat4)(pitch_rotation); return cast(Mat4)(yaw_rotation) * cast(Mat4)(pitch_rotation); } @@ -185,11 +193,28 @@ Cycle(Game* g) Bind(&g.rd, &g.pbr_pipeline); - DrawModel(&g.rd, &g.model); + Quat q; + static f32 angle = 0.0; + angle += 1.0 * g.delta; + QuatFromAxis(&q, angle, Vec3(0.0, 1.0, 0.0)); + g.pc.model_matrix = cast(Mat4)(q); + DrawModel(g, &g.model); FinishFrame(&g.rd); } +pragma(inline): void +DrawModel(Game* g, Model* model) +{ + BindBuffers(&g.rd, &model.index_buffer, &model.vertex_buffer); + foreach(i, part; model.parts) + { + g.pc.mat_id = part.mat; + PushConstants(&g.rd, &g.pc); + DrawIndexed(&g.rd, part.length, 1, part.offset); + } +} + void Destroy(Game* g) { diff --git a/src/gears/main.d b/src/gears/main.d index c786d77..c2edf1e 100644 --- a/src/gears/main.d +++ b/src/gears/main.d @@ -18,21 +18,19 @@ import core.stdc.string : memcpy; void main(string[] argv) { PlatformWindow window = CreateWindow("Video Game", 1920, 1080); - Game g = InitGame(&window); - scope(exit) Destroy(&g); while (true) { HandleEvents(&window); if (window.close) { - Logf("quitting"); break; } - Cycle(&g); } + + Destroy(&g); } diff --git a/src/gears/platform.d b/src/gears/platform.d index a466d5f..2b73b6d 100644 --- a/src/gears/platform.d +++ b/src/gears/platform.d @@ -94,7 +94,8 @@ void CheckErr(PlatformWindow *window, xcb_void_cookie_t *cookie, xcb_generic_err pureFree(err); }; -PlatformWindow CreateWindow(string name, u16 width, u16 height) +PlatformWindow +CreateWindow(string name, u16 width, u16 height) { PlatformWindow window = { w: width, @@ -210,6 +211,9 @@ PlatformWindow CreateWindow(string name, u16 width, u16 height) xcb_xfixes_query_version(window.conn, 4, 0); + LockCursor(&window); + UnlockCursor(&window); + return window; }; @@ -345,6 +349,8 @@ HandleEvents(PlatformWindow* window) case XCB_BUTTON_PRESS: case XCB_BUTTON_RELEASE: { + if (window.input_count == window.inputs.length) continue; + xcb_button_press_event_t* mouse_event = cast(xcb_button_press_event_t*)e; bool pressed = e.response_type == XCB_BUTTON_PRESS; Input input = Input.None; @@ -367,6 +373,7 @@ HandleEvents(PlatformWindow* window) case XCB_MOTION_NOTIFY: { if (ignore_mouse_events) continue; + if (window.input_count == window.inputs.length) continue; xcb_motion_notify_event_t* move_event = cast(xcb_motion_notify_event_t*)e; diff --git a/src/gears/renderer.d b/src/gears/renderer.d index 59e3230..246ed4e 100644 --- a/src/gears/renderer.d +++ b/src/gears/renderer.d @@ -4,7 +4,7 @@ import assets; import util; import alloc; import vulkan; -import vulkan : Destroy, Init, Draw, DrawIndexed, Bind, BindUIBuffers, BeginRender, SetUniform, PrepComputeDrawImage, Dispatch, FinishFrame, BeginFrame, WaitIdle; +import vulkan : Destroy, Init, Draw, DrawIndexed, Bind, BindUIBuffers, BeginRender, SetUniform, PrepComputeDrawImage, Dispatch, FinishFrame, BeginFrame, WaitIdle, PushConstants, BindBuffers; import assets; import std.math.traits : isNaN; import util : Logf; @@ -56,6 +56,9 @@ struct GlobalUniforms Mat4 view_matrix = Mat4Identity(); Mat4 projection_matrix = Mat4Identity(); Mat4 view_projection = Mat4Identity(); + Vec4 light_color; + Vec4 ambient_color; + align(16): Vec3 light_direction; Vec2 res; } @@ -64,12 +67,6 @@ struct ShaderUniforms f32 placeholder; } -struct PushConst -{ - Mat4 model_matrix; - u32 mat_id; -} - enum PipelineType : int { Graphics, @@ -114,8 +111,12 @@ struct Renderer UIVertex[] ui_vertex_buf; u32[] ui_index_buf; u32 ui_count; +} - PushConst push_const; +struct PushConst +{ + Mat4 model_matrix; + u32 mat_id; } struct Extent @@ -179,22 +180,6 @@ InitRenderer(PlatformWindow* window) return rd; } -pragma(inline): void -DrawModel(Renderer* rd, Model* model) -{ - BindBuffers(&rd.vk, &model.index_buffer, &model.vertex_buffer); - - rd.push_const.model_matrix = Mat4Identity(); - Translate(&rd.push_const.model_matrix, Vec3(0.0, 0.0, 0.0)); - - foreach(i, part; model.parts) - { - rd.push_const.mat_id = part.mat; - PushConstants(&rd.vk, &rd.push_const); - DrawIndexed(rd, part.length, 1, part.offset); - } -} - pragma(inline): Extent GetExtent(Renderer* rd) { @@ -289,6 +274,18 @@ DrawRect(Renderer* rd, f32 p0_x, f32 p0_y, f32 p1_x, f32 p1_y, Vec4 col) rd.ui_count += 1; } +pragma(inline): void +BindBuffers(Renderer* rd, Buffer* index_buffer, Buffer* vertex_buffer) +{ + BindBuffers(&rd.vk, index_buffer, vertex_buffer); +} + +pragma(inline): void +PushConstants(Renderer* rd, PushConst* pc) +{ + PushConstants(&rd.vk, pc); +} + pragma(inline): Pipeline BuildGfxPipeline(Renderer* rd, GfxPipelineInfo* info) { @@ -473,6 +470,38 @@ LoadModel(Renderer* rd, string name) indices[i2] = i2; } + for(u64 i = 0; i < indices.length; i += 3) + { + u32 i0 = indices[i+0]; + u32 i1 = indices[i+1]; + u32 i2 = indices[i+2]; + + Vec3 edge1 = vertices[i1].pos - vertices[i0].pos; + Vec3 edge2 = vertices[i2].pos - vertices[i0].pos; + + Vec2 delta_uv1 = vertices[i1].uv - vertices[i0].uv; + Vec2 delta_uv2 = vertices[i2].uv - vertices[i0].uv; + + f32 dividend = delta_uv1.x * delta_uv2.y - delta_uv2.x * delta_uv1.y; + f32 fc = 1.0 / dividend; + + Vec3 tangent = Vec3( + fc * (delta_uv2.y * edge1.x - delta_uv1.y * edge2.x), + fc * (delta_uv2.y * edge1.y - delta_uv1.y * edge2.y), + fc * (delta_uv2.y * edge1.z - delta_uv1.y * edge2.z) + ); + + Normalize(&tangent); + + f32 handedness = ((delta_uv1.y * delta_uv2.x - delta_uv2.y * delta_uv1.x) < 0.0) ? -1.0 : 1.0; + + Vec3 t = tangent * handedness; + + vertices[i0].tangent = Vec4(t, handedness); + vertices[i1].tangent = Vec4(t, handedness); + vertices[i2].tangent = Vec4(t, handedness); + } + assert(vertices.length > 0 && indices.length > 0, "Error loading model"); CreateBuffer(&rd.vk, &model.vertex_buffer, BT.Vertex, vertices.length * Vertex.sizeof, false); diff --git a/src/shaders/pbr.frag.glsl b/src/shaders/pbr.frag.glsl index 776ab70..75542f5 100644 --- a/src/shaders/pbr.frag.glsl +++ b/src/shaders/pbr.frag.glsl @@ -5,12 +5,30 @@ #include "structures.layout" -layout (location = 0) in vec4 in_col; -layout (location = 1) in vec2 in_uv; +layout (location = 0) in struct FragDataIn { + vec3 normal; + vec2 uv; +} FragData; layout (location = 0) out vec4 FragColor; +vec4 CalculateDirectionalLight(vec4 diff_col, vec4 diff_samp, vec4 light_col, vec3 dir, vec3 normal) +{ + float diffuse_factor = max(dot(normal, -dir), 0.0); + + vec4 ambient = vec4(vec3(G.ambient_color * diff_col), diff_samp.a); + vec4 diffuse = vec4(vec3(light_col * diffuse_factor), diff_samp.a); + + diffuse *= diff_samp; + ambient *= diff_samp; + + return (ambient + diffuse); +} + void main() { - FragColor = in_col; + vec4 col = Materials[nonuniformEXT(PC.mat_id)].diffuse; + vec4 tex_col = texture(sampler2D(Textures[nonuniformEXT(Materials[nonuniformEXT(PC.mat_id)].albedo_texture)], SamplerNearest), FragData.uv); + + FragColor = CalculateDirectionalLight(col, tex_col, G.light_color, G.light_direction, FragData.normal); } diff --git a/src/shaders/pbr.vert.glsl b/src/shaders/pbr.vert.glsl index 1e37a61..b5551b4 100644 --- a/src/shaders/pbr.vert.glsl +++ b/src/shaders/pbr.vert.glsl @@ -11,8 +11,10 @@ layout (location = 2) in vec3 in_pos; layout (location = 3) in vec3 in_normal; layout (location = 4) in vec2 in_uv; -layout (location = 0) out vec4 out_col; -layout (location = 1) out vec2 out_uv; +layout (location = 0) out struct FragDataOut { + vec3 normal; + vec2 uv; +} FragData; mat4 y_matrix = mat4( 1.0, 0.0, 0.0, 0.0, @@ -25,14 +27,6 @@ void main() { gl_Position = G.projection_matrix * G.view_matrix * PC.model_matrix * vec4(in_pos, 1.0); - vec4 col = Materials[nonuniformEXT(PC.mat_id)].diffuse; - - if (Materials[nonuniformEXT(PC.mat_id)].albedo_has_texture) - { - vec4 tex_col = texture(sampler2D(Textures[nonuniformEXT(Materials[nonuniformEXT(PC.mat_id)].albedo_texture)], SamplerNearest), in_uv); - col = col * tex_col; - } - - out_col = col; - out_uv = in_uv; + FragData.uv = in_uv; + FragData.normal = mat3(PC.model_matrix) * in_normal; } diff --git a/src/shaders/structures.layout b/src/shaders/structures.layout index 92d2ccc..01a73e9 100644 --- a/src/shaders/structures.layout +++ b/src/shaders/structures.layout @@ -6,6 +6,9 @@ layout (set = 0, binding = 0) uniform GlobalUniforms { mat4 view_matrix; mat4 projection_matrix; mat4 view_projection; + vec4 light_color; + vec4 ambient_color; + vec3 light_direction; vec2 res; } G; diff --git a/src/shared/math.d b/src/shared/math.d index 2879caa..d8f09e5 100644 --- a/src/shared/math.d +++ b/src/shared/math.d @@ -702,7 +702,7 @@ struct Quat U opCast(U)() if (is(U: Mat4)) { - f32 norm = Normalize(&vec); + f32 norm = Norm(&vec); f32 s = norm > 0.0 ? 2.0 / norm : 0.0; f32 _x = x; @@ -818,22 +818,36 @@ Dot(Vec4* l, Vec4* r) } pragma(inline): f32 -Normalize(Vec3* v) +Norm(Vec3* v) { return sqrtf(Dot(v, v)); } pragma(inline): f32 -Normalize(Vec4* v) +Norm(Vec4* v) { // TODO: SIMD this return sqrtf(Dot(v, v)); } +pragma(inline): void +Normalize(T)(T* vec) if (is(T: Vec2) || is(T: Vec3) || is(T: Vec4)) +{ + f32 length = Norm(vec); + mixin(GenerateLoop!("vec.v[@] /= length;", vec._N)()); +} + +pragma(inline): Vector +Normalize(T)(T vec) if (is(T: Vec2) || is(T: Vec3) || is(T: Vec4)) +{ + Normalize(&vec); + return vec; +} + pragma(inline): void NormalizeTo(Vec3* v, Vec3* dst) { - f32 norm = Normalize(v); + f32 norm = Norm(v); if (norm < f32.epsilon) {