From 581656568b184a59983b169f02d9f9c08c0cbfe7 Mon Sep 17 00:00:00 2001 From: Patedam Date: Mon, 23 Feb 2026 22:05:46 -0500 Subject: [PATCH] Debug options: Stop moving light, camera and cubes. F1 to have free camera --- Assets/compiled/Debug.vert.dxil | Bin 5032 -> 5104 bytes Assets/compiled/ImGui.frag.dxil | Bin 4544 -> 4616 bytes Assets/compiled/ImGui.vert.dxil | Bin 4976 -> 5076 bytes Assets/compiled/Skybox.vert.dxil | Bin 5368 -> 5440 bytes Assets/compiled/SolidColor.frag.dxil | Bin 5684 -> 5752 bytes Assets/compiled/Triangle.vert.dxil | Bin 5748 -> 6016 bytes Assets/source/RootConstants.hlsl | 11 +- Assets/source/Triangle.vert.hlsl | 4 + Juliet/include/Core/Math/Matrix.h | 9 + Juliet/include/Graphics/PushConstants.h | 4 +- Juliet/src/Graphics/DebugDisplayRenderer.cpp | 12 +- Juliet/src/Graphics/MeshRenderer.cpp | 107 ++++++++---- Juliet/src/Graphics/SkyboxRenderer.cpp | 8 +- JulietApp/main.cpp | 164 +++++++++++++++++-- 14 files changed, 263 insertions(+), 56 deletions(-) diff --git a/Assets/compiled/Debug.vert.dxil b/Assets/compiled/Debug.vert.dxil index 5fdd7a03daafa9e187f6e6608ac9e804c2f52bd9..865e6a3f1b09cd2e95549991cde9d224fa46c6b7 100644 GIT binary patch delta 1715 zcmZ{keM}Q~7{~AWa&51zD^m3OqB$m1$AFzs%Zs|SMXN9{okgS*wAB{DKzZ{8-CRp6 zr5OdPg$X#^6_hjvmm;WuFQEq-XwU#tr$`){i6&}>PMzDbWXJF&F4-TKJo!D}=kxrY z=kC7V#nX!gt1^{IlRqC=dnm;V{W|qco5)r23IqUP`k+8WzXp>*M?xtW9>xNI8~_B8 zDFCo4GdUF^H9S(rAm%aw{yEo9oDLjVzE4sv-D#}+o*0x0S z_eMLDHMhiH91>{-cWC+s36px-k9O_ojL%3f(VI$h3QGz~mAi6sj3vn?gRw05fM;CC z+x$W+p6^MF?TqOOi#ru_o<-;iqn>X7V4vx{<__E)tWlV zMw#mH%PE-x>E%Lt#`Oi6^Ml&DVx{IpFLsJWOcr2{72fB4y+wKd+ButtxpLasvzjcs^98pHyB;;&+)C6G%<~!6OdhW`V$)wyNCFSNFm;$|_ zvtmv^DZ_H*h!xtXQtU%ZS5EFJ5ys1$L>s!R8fAWz33*r*jup~*{Ana zY`KYA`s4GFl5(+yMGuOg~?R7Q@@i$lxk?{vfPTq8EBqyPqINno*OmRjWe+I zQ>w*>885z_QpLrE$5%#^qHTq{OgqW$8cJE`x)1&Y-7c7y5aSj+{k(nnJnQeykVlMu zWah7b#hi74PygcrljQju7g+ZHF3?%ai3BM+dgldhE!BLOw1QxoB67w?xa1?PQx?}} zhYkb$$8s%P_gJ3CepSADj(S zi(P`-xk@0tNKSVO{mOtNaCAriKczcdS;{05*HUc~Q^H zh3y2{+$mxDa|zTb;n~vk==VWX8lb@XO3L|d7*oaJ0W?4GW5xOg0`=*vHOa=eihW?n zv6z1qW>WH7MY=11`sCJ{)p>6vM0rSy^bI7qGQ%;3`cP|)qTsC}0M5f@ZxpeWnU-n?dA4T>SYwTrJcJBs9KO+MT;<(am%Ly4iymwxK;&GQ5kj2O--RK z*u?74wy|I^t(Aq5Evw+v65ZOOq+(TyA9IQfoHC-AkVU66Gui3<*j%zdPI7YI-}{{N zzUMq=YDVV_VP=UuMb#!^P9)sYi+$?_7@P%8-wI6%nJ0{r^?Lltsbv;X!s&jI_{<} zTIE6a*Qn>rkL)j&F=TfrYD2F^mqdk2o%D&+<8*H~*JFjMvd&>w?*!e^Zu5tAoHOt7 zcbs-Y-A!7?#Y6;O%hJtyz}v%@8fr9jt%$dpFHLhKN%PmQtKOQirDjWAxXyM{LDU!C zYWyS&-w>Xcpt9%H*%MR;^X%sjQatqts`Y9YPy2c|vHXTGy1lTywY0T-KkUN@Tlqvr zvfnD&so1I0^iK>;4p@dR4o)#lv;Uwc1cd+EN{or}{-bxAIZt3Q5k&<^!4Y z7|N^Aq?_E$E(=9eIhfAo(A{qQn^F8*5TZ>W9YlzTRZ7WM=;l9s7?%a{ix9WE*^Rkc zu7^NHIy_32h|a#kN<5{R%{!rR$&+eZyPs-4hsEY?R~@8?4GyKS-WIuSEMl|rWD^ou zr&emMA*UTm3+E#s!Kz)Th#e%B3641MAEtCcp~=Tj(7jHshe8vFhQ}wyC0HNXlB=>G zw9h$E|NGhO>@`UbCO7Wgi&Y3mqHdOvKcQ7(uTAV56HB*}Lyh7qOqZv>>c{c@*~R18 zDe+iW%b4@J`P_xT9dh-OwcFH5^~#$1%DUw&J70L{y!b;Bw*T*EXach`nty$JrR;I> zjFe(oN_?$!-7OGCeVMI`JhX}Ix{@QK$V8=wZ37K?IW zWevyr67|{zQ>M$U6FY_jBL%X%^_UNfx)BVZkO-59pBF6#rx) l?B7cT6I75VzvAVo`iyttUJFmiUtA`XgW;egHhgaY`~^L5R4)Jk diff --git a/Assets/compiled/ImGui.frag.dxil b/Assets/compiled/ImGui.frag.dxil index 368b0b5d4dcb7e24acaaf64e8fa4c4a21a5d3752..0529b791da08adb9c0bce54b53f95b160c43683a 100644 GIT binary patch delta 1383 zcmZ`(eM}Q)9KLI>*Xz-;md|SoSV5R8A0A&-=9X{;!3k`gzyK|JEg(f(AuTL8bo7hL zB8|mDLhW!@Dw7zZAa05aNh^#2>I89wuOVbn8{HEA*b?KCWykd2y?_0lCr_T|`Q^>~ z`r_Jmh;qy2IsQe#&3{ZAnDpSoA0(Y776_0btw62G|CM@gEByf^U6(>d7V#BFI?20iv8=Fkc^tqV;Jp zJ(y5X=;+`iO+cL~5Dmg*wlD?h1yEv18K;Qc%%aoq^QZ0{G~yA#0sdp&c4{^@S}T>sc;5x-q$Ar^@y z_QF2vdw+24!O{+`IlDpJ%8h+T`r%NDw6LyL)0k7Qt=ES_eJdpYwBj#QlK?#)T99b) z7U;c+26ut?9^H8jw!E^SVT0%R#mhobucFsg;Zj}@R|wZ2(<{3A&Jr)FvzjLZkA9!& zdGzyaz_#{cH9&8HY4P@h1BL!&SuS_-jGBb&d~kiMgxzFhx2&^0+31xa6)q|1ksv;p z9480wO0`J2Y8)SsCl>N2NS+M3p52$6^uUgk3KnMPondp32eWYG1T1D$nH61r$b(xr z3;`^*qLH#BThe_-@?&!{_ZB%TPthVap1f374p;QB4lS|{V_Fr(I@c=*^MqS?|X-)-)eIS+CcLy9_|W_IYUH-(>d47sWeL0E@fVJb(fgjZ&hF{VvCi({ zB90@ix;aH(W2kS^SJfDb8CODtmx3x|loby5intQ1q%Bs%!0*@W4G7t>C;%~=!r9984opIiL@`?_wwf~Dc8Y5D zr>i%&~B&uipBM*`y4IFAcNAB3QFMs_pKo@gf+MhPbIIN)X@`w9N0 c{r;Vo!I*VZ6!NB$(JB|MgE7q@{Z-QEU+Qq}_W%F@ delta 1311 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 HdGa{`7s!_A delta 990 zcmZvbeM}m67{`An+yTeYQfnp%?dS$L(6N&^$XvG!M9kKb*!ohenm{auIC=(p6~M{ zPfWfi%hMUPrB^#_%~vH&g^{yuy#70600IE)<#_V)kQo*L>#T4|J0#^X0cZjcK(YYP z8Q(pQP!yK}0hMb@W4|210QeV*)Szde1MAjh9Q)>e8{i0Pj3|z?-JkL40o! zonO#SFwp=u7Z9U30pRxnTo^q`;4oT6m|)aMgkZFu*oM*b1ef9ci2gEskq5wv_b=>C z?;0J0n!Q_eF?80O4d>efaiq6TJfbnLFu7%O;8g_Udi#aSMzh^!IoK1Ytj!e@-4}`iSJ)jRjqFe(;nZdRMB}@a}OCGb4S-m>VEe;d@GTRIH9Fza)#JRO=Ac+I}>+6N@s7 zMsEaCthC?no0X6rUxupQ>eOs&(u}3@SFCPD@{U`!h4r^Soml8^b>JURE9{q7gudqN z_qLgEq-hYbZ6oa!jII#l6D}%1XxY6i2e1JZrk4#RT(KM#Mw5M(pl9lw9F2U?%0AZd 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 Z{7woli=N7tGJC~`9y3?T2uei&;J?|FpLzfQ delta 3043 zcmdT_dsGuw9=-{aVJ4Y`K@f+8>L8f%h&W0bMOe**pi!_VD7N_8COi~1Y6R=?Q8!N_ zD%xmtjZn9NfCnqx#uuWiJtScjD6;sdtAf;Li&j^Tt5)5f-JK|cZT)}G&N(yZ-uZp^ zyWj73fAfuT%wvgAnX5?O@YEf?ZR6U78F|L#281)XX9xg_^roI@41iR}GJbRIv6K zfA?f=#-pTeDUoxr8L@VwQA#<$4P|Cf(N3@RLNu>0au5A)5*uy2C@7|^LFS4 zW!7Uc*t=)68)Ihhj42myf3+=n<@+%+|{d_q$EpVW5+=oc=6LDS1}C0S^|Ivj#Hc@16*jP zBqFQHNn-7=mx{Z5b{T=2ourc%dA6@x?-s2qsdV#7+?ACib{1|{NB9XslisN#K@&@i z6!yWZ>d&|R!*#poV%zE7^F7^S#F9)Cf8zV4{4gu4g2c{2TDur&7wXhys_F#)iKOz3 z3!*uZU69r(i?bTU+21Z)Fzj?jT}OL;R#NNMdTfQ6QioZqt{U+LcjkOoy1gpF?>^v2 z%q)&c^fMwZ!4||a9jpJeeDLO9?0XTXKakPHAwFCMe=E!#7M5_FI+oI4piUe@eXeCxnXIn6=|nG8ySM6G zXl?7Rt>+nx)sHY z;w}xoT7Av*aVU35SY~30JG0oGSW=nk{)SQA16x`w(?jaF;Ipnq3iqn_?wPY^{tnR` zLu3!6ea1*1k+VUw!D?n|c)!hgzN53()^o4Bmq~%pQDu|slFUnk!<@x=dj;dTy9CS#ROf3HBmhX34E_g-;4+i>H2Q z+pUz+WQ)cu-|4kAIY|S)&_mbR_*=Z(FRydI0z6A1;lX(#_8d|%+xp()$FUgLXUQ|-P9 zAPkafEPQjeK*XJy%PC&dZn8yo%_FWwZIK>JIdL5Ik#Ow!?%wZ<+H3c2IJo_sGc)yH z6>g^B`Eu)@v4>k8j4sy&SpiUc-Vu= zSrJK$0ommI-4D|ybxJ#+EF~iKE1Zs`ArZrd>il<7KOF<*WaHU)LHabpXnfwXY@TD@ zkVyvU@A~H*x2778W@pgK+8}IFahF&fVEI~_5^9=xA$`UlR(7o>18@GVREDvY&X2kq zSU6^sGW!9bqGzeXUycA+ns!S?KA9bVp+@&~+~?f3fHe|~X$GwF^slTEFz*9a$q9Jn zssCHA?BNf3CA+}n_>Ukeh74|VrENC8>3<3y&RnK`=OarTlR{Etzi>S5pyOd@AulFl zhgrQ>jBz}7TzZfW`HT;Nv?k~VcEs^zNMxp!`4;x^P2*^?4)yiv@FQA(bnh0iL=$2Ja)jbxtZ2t5Je6H!Kb(g* z{4Y95O9Bwi{6xbbS`zq?3Yc3O{$c#i1<~zbXRX{T*m+;RI9z#7urq@mI>n1;3+~YE z2v}T#6kKnQ{)|q)7G+RgkVY`;Kn#okv*vo0Da_6qo2LgP0#^#<%+MYfmPV-;YT)mr zuL2iDxxVBIynjt+J1ac4wam*hl7w!Bnxh(OFDK#vVrJz8JMn^TG6v~J6;uUU#W^n z>|_z`-XaAk7bD&xA6YKO{jX%@9<&D+x`N#(i>e?YH)^3O$HghJv-KHY~@YCZ~%EhBD%)epy{uNqiiF}%Ss4(UQUpK2CxnJC%K8H@{EBV%AMY6 zdCVMqpwEo^mA_NX*JKL~1Eha!+}MJ>F2h{*i0ZLO{}v^iJ}GM=sXG4cka9Qg!*|~m6PQK_~rPE=1=-pyEhpol+Jz4bpW*oX7%BEdQxDCfzfi! zs@lm;dd+a7`Q=Q;{R{bd|H-bZj-8?%_FCI&->aD=aO!fOFIMLh|Gqk63N|EA50vNd zpp`~+E-_XGa40BNlI0WYsz)uTrl!o9a~)X zGX6R|cjRDLA=cd-^;k2=x5tAzJ(fXyfloYFAs7_oLMzvxO9$~44Bq}KOa=rq@gj85 OoAFJ%)B#6fuKxn^kRXo$ diff --git a/Assets/source/RootConstants.hlsl b/Assets/source/RootConstants.hlsl index 301fcf9..b2270a3 100644 --- a/Assets/source/RootConstants.hlsl +++ b/Assets/source/RootConstants.hlsl @@ -9,16 +9,23 @@ struct PointLight float Intensity; }; +struct TransformData +{ + row_major float4x4 Model; +}; + cbuffer RootConstants : register(b0, space0) { row_major float4x4 ViewProjection; - row_major float4x4 Model; + uint MeshIndex; + uint TransformsBufferIndex; uint BufferIndex; - uint TextureIndex; + uint TextureIndex; uint VertexOffset; // Base vertex for indexed drawing with bindless buffers uint _Padding; // Padding for alignment float2 Scale; // 2D scale factor float2 Translate; // 2D translation + float2 _Padding2; // Explicit padding to align LightDirection to 16 bytes float3 LightDirection; // Normalized, world-space float LightPad; diff --git a/Assets/source/Triangle.vert.hlsl b/Assets/source/Triangle.vert.hlsl index eb1c49b..3984130 100644 --- a/Assets/source/Triangle.vert.hlsl +++ b/Assets/source/Triangle.vert.hlsl @@ -21,6 +21,10 @@ Output main(uint vertexIndex : SV_VertexID) float3 normal = asfloat(buffer.Load3(offset + 12)); float4 col = asfloat(buffer.Load4(offset + 24)); + // Fetch Model Matrix + StructuredBuffer transformsBuffer = ResourceDescriptorHeap[TransformsBufferIndex]; + float4x4 Model = transformsBuffer[MeshIndex].Model; + float4 worldPos = mul(Model, float4(pos, 1.0f)); output.Position = mul(ViewProjection, worldPos); output.Color = col; diff --git a/Juliet/include/Core/Math/Matrix.h b/Juliet/include/Core/Math/Matrix.h index 4c7d876..79f3d85 100644 --- a/Juliet/include/Core/Math/Matrix.h +++ b/Juliet/include/Core/Math/Matrix.h @@ -45,6 +45,15 @@ namespace Juliet return result; } + [[nodiscard]] inline Matrix MatrixScale(float x, float y, float z) + { + Matrix result = MatrixIdentity(); + result.m[0][0] = x; + result.m[1][1] = y; + result.m[2][2] = z; + return result; + } + [[nodiscard]] inline Matrix MatrixRotationX(float radians) { float c = cosf(radians); diff --git a/Juliet/include/Graphics/PushConstants.h b/Juliet/include/Graphics/PushConstants.h index 5a3fa04..740ad74 100644 --- a/Juliet/include/Graphics/PushConstants.h +++ b/Juliet/include/Graphics/PushConstants.h @@ -9,13 +9,15 @@ namespace Juliet struct PushData { Matrix ViewProjection; - Matrix Model; + uint32 MeshIndex; + uint32 TransformsBufferIndex; uint32 BufferIndex; uint32 TextureIndex; uint32 VertexOffset; uint32 Padding; float Scale[2]; float Translate[2]; + float Padding2[2]; Vector3 LightDirection; float LightPad; diff --git a/Juliet/src/Graphics/DebugDisplayRenderer.cpp b/Juliet/src/Graphics/DebugDisplayRenderer.cpp index 6484971..bd56e5d 100644 --- a/Juliet/src/Graphics/DebugDisplayRenderer.cpp +++ b/Juliet/src/Graphics/DebugDisplayRenderer.cpp @@ -300,12 +300,11 @@ namespace Juliet // Render depth-tested primitives (vertices at offset 0 in buffer) if (g_DebugState.DepthTestedVertexCount > 0 && g_DebugState.DepthTestedPipeline && g_DebugState.VertexBuffer) { - BindGraphicsPipeline(renderPass, g_DebugState.DepthTestedPipeline); - - // Pack VP matrix + Model (identity for debug) + buffer index into push constants + // Pack VP matrix + buffer index into push constants PushData pushData = {}; pushData.ViewProjection = Camera_GetViewProjectionMatrix(camera); - pushData.Model = MatrixIdentity(); + pushData.MeshIndex = 0; + pushData.TransformsBufferIndex = 0; // Not used by debug shader but layout must match pushData.BufferIndex = bufferIndex; pushData.TextureIndex = 0; pushData.VertexOffset = 0; // Depth-tested vertices start at 0 @@ -329,10 +328,11 @@ namespace Juliet { BindGraphicsPipeline(renderPass, g_DebugState.OverlayPipeline); - // Pack VP matrix + Model (identity for debug) + buffer index into push constants + // Pack VP matrix + buffer index into push constants PushData pushData = {}; pushData.ViewProjection = Camera_GetViewProjectionMatrix(camera); - pushData.Model = MatrixIdentity(); + pushData.MeshIndex = 0; + pushData.TransformsBufferIndex = 0; pushData.BufferIndex = bufferIndex; pushData.TextureIndex = 0; pushData.VertexOffset = kMaxDebugVertices / 2; // Overlay vertices start at half diff --git a/Juliet/src/Graphics/MeshRenderer.cpp b/Juliet/src/Graphics/MeshRenderer.cpp index 2aa73ee..b56435a 100644 --- a/Juliet/src/Graphics/MeshRenderer.cpp +++ b/Juliet/src/Graphics/MeshRenderer.cpp @@ -12,7 +12,26 @@ namespace Juliet { namespace { - MeshRenderer g_MeshRenderer; + struct MeshRendererState + { + GraphicsDevice* Device = nullptr; + GraphicsPipeline* Pipeline = nullptr; + GraphicsBuffer* VertexBuffer = nullptr; + GraphicsBuffer* IndexBuffer = nullptr; + GraphicsBuffer* LightsBuffer = nullptr; + GraphicsBuffer* TransformsBuffer = nullptr; + GraphicsTransferBuffer* LoadCopyBuffer = nullptr; + + VectorArena Meshes; + VectorArena Vertices; + VectorArena Indices; + VectorArena PointLights; + + PointLight* MappedLights = nullptr; + Matrix* MappedTransforms = nullptr; + }; + + MeshRendererState g_MeshRenderer; } // namespace void InitializeMeshRenderer(NonNullPtr arena) @@ -92,6 +111,18 @@ namespace Juliet g_MeshRenderer.MappedLights = static_cast(MapGraphicsBuffer(graphicsDevice, g_MeshRenderer.LightsBuffer)); Assert(g_MeshRenderer.MappedLights != nullptr); + // Transforms Buffer + BufferCreateInfo transformsBufferCI = {}; + transformsBufferCI.Size = 10000 * sizeof(Matrix); // Max 10000 meshes for now + transformsBufferCI.Stride = sizeof(Matrix); + transformsBufferCI.Usage = BufferUsage::StructuredBuffer; + transformsBufferCI.IsDynamic = true; + g_MeshRenderer.TransformsBuffer = CreateGraphicsBuffer(graphicsDevice, transformsBufferCI); + Assert(g_MeshRenderer.TransformsBuffer != nullptr); + g_MeshRenderer.MappedTransforms = + static_cast(MapGraphicsBuffer(graphicsDevice, g_MeshRenderer.TransformsBuffer)); + Assert(g_MeshRenderer.MappedTransforms != nullptr); + // Sync existing lights that might have been added before graphics initialization for (index_t i = 0; i < g_MeshRenderer.PointLights.Count; ++i) { @@ -130,6 +161,14 @@ namespace Juliet { UnmapGraphicsBuffer(g_MeshRenderer.Device, g_MeshRenderer.LightsBuffer); DestroyGraphicsBuffer(g_MeshRenderer.Device, g_MeshRenderer.LightsBuffer); + g_MeshRenderer.LightsBuffer = nullptr; + } + + if (g_MeshRenderer.TransformsBuffer) + { + UnmapGraphicsBuffer(g_MeshRenderer.Device, g_MeshRenderer.TransformsBuffer); + DestroyGraphicsBuffer(g_MeshRenderer.Device, g_MeshRenderer.TransformsBuffer); + g_MeshRenderer.TransformsBuffer = nullptr; } } @@ -214,15 +253,24 @@ namespace Juliet uint32 vertexDescriptorIndex = GetDescriptorIndex(g_MeshRenderer.Device, g_MeshRenderer.VertexBuffer); uint32 lightDescriptorIndex = GetDescriptorIndex(g_MeshRenderer.Device, g_MeshRenderer.LightsBuffer); - pushData.BufferIndex = vertexDescriptorIndex; - pushData.LightBufferIndex = lightDescriptorIndex; - pushData.ActiveLightCount = static_cast(g_MeshRenderer.PointLights.Count); + uint32 transformsDescriptorIndex = GetDescriptorIndex(g_MeshRenderer.Device, g_MeshRenderer.TransformsBuffer); + + pushData.BufferIndex = vertexDescriptorIndex; + pushData.LightBufferIndex = lightDescriptorIndex; + pushData.TransformsBufferIndex = transformsDescriptorIndex; + pushData.ActiveLightCount = static_cast(g_MeshRenderer.PointLights.Count); SetIndexBuffer(cmdList, g_MeshRenderer.IndexBuffer, IndexFormat::UInt16, g_MeshRenderer.Indices.Count, 0); + uint32 meshIndex = 0; for (Mesh& mesh : g_MeshRenderer.Meshes) { - pushData.Model = mesh.Transform; + if (g_MeshRenderer.MappedTransforms) + { + g_MeshRenderer.MappedTransforms[meshIndex] = mesh.Transform; + } + + pushData.MeshIndex = meshIndex; pushData.TextureIndex = 0; pushData.VertexOffset = static_cast(mesh.VertexOffset); pushData.Padding = 0; @@ -233,6 +281,7 @@ namespace Juliet SetPushConstants(cmdList, ShaderStage::Vertex, 0, sizeof(pushData) / 4, &pushData); DrawIndexedPrimitives(pass, static_cast(mesh.IndexCount), 1, static_cast(mesh.IndexOffset), static_cast(mesh.VertexOffset), 0); + meshIndex++; } } @@ -278,40 +327,40 @@ namespace Juliet Mesh result = {}; constexpr Vertex vertexData[] = { // Front Face (Z = -0.5f) — Red - { { -0.5f, 0.5f, -0.5f }, { 0.0f, 0.0f, -1.0f }, { 0.8f, 0.2f, 0.2f, 1.0f } }, - { { 0.5f, 0.5f, -0.5f }, { 0.0f, 0.0f, -1.0f }, { 0.8f, 0.2f, 0.2f, 1.0f } }, - { { 0.5f, -0.5f, -0.5f }, { 0.0f, 0.0f, -1.0f }, { 0.8f, 0.2f, 0.2f, 1.0f } }, - { { -0.5f, -0.5f, -0.5f }, { 0.0f, 0.0f, -1.0f }, { 0.8f, 0.2f, 0.2f, 1.0f } }, + { { -0.5f, 0.5f, -0.5f }, { 0.0f, 0.0f, -1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { 0.5f, 0.5f, -0.5f }, { 0.0f, 0.0f, -1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { 0.5f, -0.5f, -0.5f }, { 0.0f, 0.0f, -1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { -0.5f, -0.5f, -0.5f }, { 0.0f, 0.0f, -1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // Back Face (Z = 0.5f) — Green - { { 0.5f, 0.5f, 0.5f }, { 0.0f, 0.0f, 1.0f }, { 0.2f, 0.8f, 0.2f, 1.0f } }, - { { -0.5f, 0.5f, 0.5f }, { 0.0f, 0.0f, 1.0f }, { 0.2f, 0.8f, 0.2f, 1.0f } }, - { { -0.5f, -0.5f, 0.5f }, { 0.0f, 0.0f, 1.0f }, { 0.2f, 0.8f, 0.2f, 1.0f } }, - { { 0.5f, -0.5f, 0.5f }, { 0.0f, 0.0f, 1.0f }, { 0.2f, 0.8f, 0.2f, 1.0f } }, + { { 0.5f, 0.5f, 0.5f }, { 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { -0.5f, 0.5f, 0.5f }, { 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { -0.5f, -0.5f, 0.5f }, { 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { 0.5f, -0.5f, 0.5f }, { 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // Top Face (Y = 0.5f) — Blue - { { -0.5f, 0.5f, 0.5f }, { 0.0f, 1.0f, 0.0f }, { 0.2f, 0.2f, 0.8f, 1.0f } }, - { { 0.5f, 0.5f, 0.5f }, { 0.0f, 1.0f, 0.0f }, { 0.2f, 0.2f, 0.8f, 1.0f } }, - { { 0.5f, 0.5f, -0.5f }, { 0.0f, 1.0f, 0.0f }, { 0.2f, 0.2f, 0.8f, 1.0f } }, - { { -0.5f, 0.5f, -0.5f }, { 0.0f, 1.0f, 0.0f }, { 0.2f, 0.2f, 0.8f, 1.0f } }, + { { -0.5f, 0.5f, 0.5f }, { 0.0f, 1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { 0.5f, 0.5f, 0.5f }, { 0.0f, 1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { 0.5f, 0.5f, -0.5f }, { 0.0f, 1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { -0.5f, 0.5f, -0.5f }, { 0.0f, 1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // Bottom Face (Y = -0.5f) — Yellow - { { -0.5f, -0.5f, -0.5f }, { 0.0f, -1.0f, 0.0f }, { 0.8f, 0.8f, 0.2f, 1.0f } }, - { { 0.5f, -0.5f, -0.5f }, { 0.0f, -1.0f, 0.0f }, { 0.8f, 0.8f, 0.2f, 1.0f } }, - { { 0.5f, -0.5f, 0.5f }, { 0.0f, -1.0f, 0.0f }, { 0.8f, 0.8f, 0.2f, 1.0f } }, - { { -0.5f, -0.5f, 0.5f }, { 0.0f, -1.0f, 0.0f }, { 0.8f, 0.8f, 0.2f, 1.0f } }, + { { -0.5f, -0.5f, -0.5f }, { 0.0f, -1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { 0.5f, -0.5f, -0.5f }, { 0.0f, -1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { 0.5f, -0.5f, 0.5f }, { 0.0f, -1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { -0.5f, -0.5f, 0.5f }, { 0.0f, -1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // Right Face (X = 0.5f) — Cyan - { { 0.5f, 0.5f, -0.5f }, { 1.0f, 0.0f, 0.0f }, { 0.2f, 0.8f, 0.8f, 1.0f } }, - { { 0.5f, 0.5f, 0.5f }, { 1.0f, 0.0f, 0.0f }, { 0.2f, 0.8f, 0.8f, 1.0f } }, - { { 0.5f, -0.5f, 0.5f }, { 1.0f, 0.0f, 0.0f }, { 0.2f, 0.8f, 0.8f, 1.0f } }, - { { 0.5f, -0.5f, -0.5f }, { 1.0f, 0.0f, 0.0f }, { 0.2f, 0.8f, 0.8f, 1.0f } }, + { { 0.5f, 0.5f, -0.5f }, { 1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { 0.5f, 0.5f, 0.5f }, { 1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { 0.5f, -0.5f, 0.5f }, { 1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { 0.5f, -0.5f, -0.5f }, { 1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // Left Face (X = -0.5f) — Magenta - { { -0.5f, 0.5f, 0.5f }, { -1.0f, 0.0f, 0.0f }, { 0.8f, 0.2f, 0.8f, 1.0f } }, - { { -0.5f, 0.5f, -0.5f }, { -1.0f, 0.0f, 0.0f }, { 0.8f, 0.2f, 0.8f, 1.0f } }, - { { -0.5f, -0.5f, -0.5f }, { -1.0f, 0.0f, 0.0f }, { 0.8f, 0.2f, 0.8f, 1.0f } }, - { { -0.5f, -0.5f, 0.5f }, { -1.0f, 0.0f, 0.0f }, { 0.8f, 0.2f, 0.8f, 1.0f } } + { { -0.5f, 0.5f, 0.5f }, { -1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { -0.5f, 0.5f, -0.5f }, { -1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { -0.5f, -0.5f, -0.5f }, { -1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { -0.5f, -0.5f, 0.5f }, { -1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } } }; constexpr size_t cubeVertexCount = ArraySize(vertexData); result.VertexCount = cubeVertexCount; diff --git a/Juliet/src/Graphics/SkyboxRenderer.cpp b/Juliet/src/Graphics/SkyboxRenderer.cpp index 70b1f5c..052ddb7 100644 --- a/Juliet/src/Graphics/SkyboxRenderer.cpp +++ b/Juliet/src/Graphics/SkyboxRenderer.cpp @@ -82,9 +82,11 @@ namespace Juliet return; } - PushData pushData = {}; - pushData.ViewProjection = viewProjection; - pushData.Model = MatrixIdentity(); + PushData pushData = {}; + pushData.ViewProjection = viewProjection; + pushData.MeshIndex = 0; + pushData.TransformsBufferIndex = 0; + pushData.BufferIndex = 0; BindGraphicsPipeline(pass, g_SkyboxRenderer.Pipeline); SetPushConstants(cmdList, ShaderStage::Vertex, 0, sizeof(pushData) / 4, &pushData); diff --git a/JulietApp/main.cpp b/JulietApp/main.cpp index 8eec4a9..3fe9816 100644 --- a/JulietApp/main.cpp +++ b/JulietApp/main.cpp @@ -38,6 +38,18 @@ #endif static bool ShowMemoryDebugger = false; +static bool animateCubes = true; +static bool animateLights = true; +static bool animateCamera = true; + +static bool freeCameraMode = false; +static float camYaw = 0.0f; +static float camPitch = 0.0f; +static Juliet::Vector3 camPos = { 25.0f, 0.0f, 12.5f }; + +static float animateCubesTime = 0.0f; +static float animateLightsTime = 0.0f; +static float animateCameraTime = 0.0f; // TODO : Replace with message box from framework + call main and not winmain + subsystem // TODO : Think how to do the draw pipeline. @@ -226,6 +238,7 @@ void JulietApplication::Update() bool reloadShaders = false; static bool reloadShadersDebounce = false; + static bool f1Debounce = false; SystemEvent evt; while (GetEvent(evt)) @@ -249,18 +262,112 @@ void JulietApplication::Update() { reloadShadersDebounce = false; } + + if (evt.Type == EventType::Mouse_Move && freeCameraMode) + { + float sensitivity = 0.005f; + camYaw += evt.Data.MouseMovement.X_Displacement * sensitivity; + camPitch -= evt.Data.MouseMovement.Y_Displacement * sensitivity; + + // Limit pitch to avoid flipping + if (camPitch > 1.5f) camPitch = 1.5f; + if (camPitch < -1.5f) camPitch = -1.5f; + } } + if (IsKeyDown(ScanCode::F1)) + { + if (!f1Debounce) + { + freeCameraMode = !freeCameraMode; + f1Debounce = true; + } + } + else + { + f1Debounce = false; + } + + if (freeCameraMode) + { + float speed = 10.0f * deltaTime; + if ((GetKeyModState() & KeyMod::Shift) != KeyMod::None) + { + speed *= 3.0f; + } + + Vector3 forward = { cosf(camYaw) * cosf(camPitch), sinf(camYaw) * cosf(camPitch), sinf(camPitch) }; + Vector3 right = { cosf(camYaw + 1.5708f), sinf(camYaw + 1.5708f), 0.0f }; + Vector3 up = { 0.0f, 0.0f, 1.0f }; + + if (IsKeyDown(ScanCode::W)) camPos = camPos + forward * speed; + if (IsKeyDown(ScanCode::S)) camPos = camPos - forward * speed; + if (IsKeyDown(ScanCode::D)) camPos = camPos + right * speed; + if (IsKeyDown(ScanCode::A)) camPos = camPos - right * speed; + if (IsKeyDown(ScanCode::E)) camPos = camPos + up * speed; + if (IsKeyDown(ScanCode::Q)) camPos = camPos - up * speed; + } + + if (animateCubes) animateCubesTime += deltaTime; + if (animateLights) animateLightsTime += deltaTime; + if (animateCamera) animateCameraTime += deltaTime; + +#ifdef JULIET_ENABLE_IMGUI + ImGui::Begin("Debug Controls"); + ImGui::Checkbox("Animate Cubes", &animateCubes); + ImGui::Checkbox("Animate Lights", &animateLights); + ImGui::Checkbox("Animate Camera", &animateCamera); + ImGui::End(); +#endif + ArenaClear(GameScratchArena); - Vector3 redLightPos{ cosf(CameraTime * 2.0f) * 5.0f, sinf(CameraTime * 2.0f) * 5.0f, 2.0f }; + Vector3 redLightPos = { 5.0f, 5.0f, 2.0f }; + Vector3 blueLightPos = { -5.0f, 0.0f, 2.0f }; + + if (animateLights || animateLightsTime > 0.0f) + { + redLightPos = { cosf(animateLightsTime * 2.0f) * 5.0f, sinf(animateLightsTime * 2.0f) * 5.0f, 2.0f }; + blueLightPos = { -5.0f, cosf(animateLightsTime) * 3.0f, 2.0f }; + } + SetPointLightPosition(RedLightID, redLightPos); - Vector3 blueLightPos{ -5.0f, cosf(CameraTime) * 3.0f, 2.0f }; SetPointLightPosition(BlueLightID, blueLightPos); -#ifdef JULIET_ENABLE_IMGUI - ImGui::ShowDemoWindow(); -#endif + // Animate the 100 cubes (10x10 grid) + constexpr int kGridSize = 10; + constexpr float kSpacing = 2.5f; + constexpr float kOffset = (kGridSize - 1) * kSpacing * 0.5f; + + for (int row = 0; row < kGridSize; ++row) + { + for (int col = 0; col < kGridSize; ++col) + { + MeshID cube = static_cast(row * kGridSize + col); // Assuming they were added first + float x = static_cast(col) * kSpacing - kOffset; + float y = static_cast(row) * kSpacing - kOffset; + + float seed = static_cast(cube); + float timeZ = animateCubesTime * 2.0f + seed * 0.5f; + float z = 0.0f; + + float scaleF = 1.0f; + Matrix rotation = MatrixIdentity(); + + if (animateCubes || animateCubesTime > 0.0f) + { + z = sinf(timeZ) * 1.5f; // Oscillate up and down + scaleF = 1.0f + sinf(animateCubesTime * 1.5f + seed) * 0.3f; // Pulse scale + rotation = MatrixRotation(animateCubesTime * 1.2f + seed * 0.73f, animateCubesTime * 0.8f + seed * 1.17f, + animateCubesTime * 0.5f + seed * 0.53f); + } + Matrix scale = MatrixScale(scaleF, scaleF, scaleF); + + SetMeshTransform(cube, MatrixTranslation(x, y, z) * rotation * scale); + } + } + + DebugDisplay_DrawLine({ 0.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f, 1.0f }, false); DebugDisplay_DrawLine({ 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 1.0f, 0.0f, 1.0f }, true); @@ -358,24 +465,51 @@ DepthStencilTargetInfo* JulietApplication::GetDepthTargetInfo() Camera JulietApplication::GetDebugCamera() { - float time = CameraTime; - - float orbitSpeed = 0.5f; - float currentOrbitTime = time * orbitSpeed; + if (freeCameraMode) + { + Camera cam = {}; + cam.Position = camPos; + cam.Target = camPos + Vector3{ cosf(camYaw) * cosf(camPitch), sinf(camYaw) * cosf(camPitch), sinf(camPitch) }; + cam.Up = { 0.0f, 0.0f, 1.0f }; + cam.FOV = 1.047f; + cam.AspectRatio = 1200.0f / 800.0f; + cam.NearPlane = 0.1f; + cam.FarPlane = 1000.0f; + return cam; + } // --- Adjusted for 1-Meter Scale --- float baseRadius = 25.0f; // Increased to see 10x10 cube grid float radius = baseRadius; - //* Uncomment for active zoom - float zoomAmplitude = 15.0f; - float zoomSpeed = 0.5f; - radius = baseRadius + (sinf(time * zoomSpeed) * zoomAmplitude); - //*/ + + if (animateCamera || animateCameraTime > 0.0f) + { + float orbitSpeed = 0.5f; + float currentOrbitTime = animateCameraTime * orbitSpeed; + + float zoomAmplitude = 15.0f; + float zoomSpeed = 0.5f; + radius = baseRadius + (sinf(animateCameraTime * zoomSpeed) * zoomAmplitude); + + float zHeight = radius * 0.5f; // Keep a nice downward viewing angle + + Camera cam = {}; + cam.Position = { cosf(currentOrbitTime) * radius, sinf(currentOrbitTime) * radius, zHeight }; + cam.Target = { 0.0f, 0.0f, 0.0f }; + cam.Up = { 0.0f, 0.0f, 1.0f }; + cam.FOV = 1.047f; + cam.AspectRatio = 1200.0f / 800.0f; + cam.NearPlane = 0.1f; + cam.FarPlane = 1000.0f; + + return cam; + } + float zHeight = radius * 0.5f; // Keep a nice downward viewing angle Camera cam = {}; - cam.Position = { cosf(currentOrbitTime) * radius, sinf(currentOrbitTime) * radius, zHeight }; + cam.Position = { radius, 0.0f, zHeight }; cam.Target = { 0.0f, 0.0f, 0.0f }; cam.Up = { 0.0f, 0.0f, 1.0f }; cam.FOV = 1.047f;