├── .gitignore ├── Example ├── Application.cpp ├── Application.h ├── Example.vcxproj ├── Example.vcxproj.filters ├── Example.vcxproj.user ├── LogWindow.h ├── PerformanceWindow.h ├── assets │ ├── AntiqueCamera.glb │ ├── DamagedHelmet │ │ ├── DamagedHelmet.bin │ │ ├── DamagedHelmet.gltf │ │ ├── Default_AO.jpg │ │ ├── Default_albedo.jpg │ │ ├── Default_emissive.jpg │ │ ├── Default_metalRoughness.jpg │ │ └── Default_normal.jpg │ ├── Sponza │ │ ├── 10381718147657362067.jpg │ │ ├── 10388182081421875623.jpg │ │ ├── 11474523244911310074.jpg │ │ ├── 11490520546946913238.jpg │ │ ├── 11872827283454512094.jpg │ │ ├── 11968150294050148237.jpg │ │ ├── 1219024358953944284.jpg │ │ ├── 12501374198249454378.jpg │ │ ├── 13196865903111448057.jpg │ │ ├── 13824894030729245199.jpg │ │ ├── 13982482287905699490.jpg │ │ ├── 14118779221266351425.jpg │ │ ├── 14170708867020035030.jpg │ │ ├── 14267839433702832875.jpg │ │ ├── 14650633544276105767.jpg │ │ ├── 15295713303328085182.jpg │ │ ├── 15722799267630235092.jpg │ │ ├── 16275776544635328252.png │ │ ├── 16299174074766089871.jpg │ │ ├── 16885566240357350108.jpg │ │ ├── 17556969131407844942.jpg │ │ ├── 17876391417123941155.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 │ │ ├── Sponza.bin │ │ ├── Sponza.gltf │ │ └── white.png │ ├── beach │ │ ├── beach.dds │ │ ├── beachirradiance.dds │ │ ├── beachradiance.dds │ │ └── brdfLUT.dds │ ├── cube.obj │ ├── scenes │ │ ├── AntiqueCamera.json │ │ ├── DamagedHelmet.json │ │ └── sponza.json │ └── uvsphere.obj └── imgui.ini ├── PlaygroundEngine.sln ├── PlaygroundEngine ├── Assets │ └── Shaders │ │ ├── BRDF.hlsli │ │ ├── DebugShader.hlsl │ │ ├── DepthGen.hlsl │ │ ├── HDRPostProcess.hlsl │ │ ├── PBRForward.hlsl │ │ ├── ShaderDefinitions.h │ │ ├── ShadowUtils.hlsli │ │ └── Skybox.hlsl ├── Core.h ├── Events │ ├── PGEvent.h │ ├── PGSystemEventDispatcher.cpp │ └── PGSystemEventDispatcher.h ├── Imgui │ ├── LICENSE.txt │ ├── imconfig.h │ ├── imgui.cpp │ ├── imgui.h │ ├── imgui_demo.cpp │ ├── imgui_draw.cpp │ ├── imgui_impl.cpp │ ├── imgui_impl.h │ ├── imgui_impl_dx11.cpp │ ├── imgui_impl_dx11.h │ ├── imgui_internal.h │ ├── imgui_widgets.cpp │ ├── imstb_rectpack.h │ ├── imstb_textedit.h │ └── imstb_truetype.h ├── Main.cpp ├── Math │ ├── math_matrix.h │ ├── math_util.h │ ├── math_vector.h │ ├── simd.h │ ├── simd_avx2.h │ └── simd_sse.h ├── Mesh.h ├── MeshUtils.cpp ├── MeshUtils.h ├── PGApplication.h ├── PGCamera.cpp ├── PGCamera.h ├── PGGameApplication.h ├── PGLog.cpp ├── PGLog.h ├── PGProfiler.cpp ├── PGProfiler.h ├── PGResouceManager.h ├── PGResource.h ├── PGResourceManager.cpp ├── PGSystem.cpp ├── PGSystem.h ├── Platform │ ├── PGInput.h │ ├── PGKeycode.h │ ├── PGLibrary.h │ ├── PGTime.h │ ├── PGWindow.h │ └── Win32 │ │ ├── PGInputWin32.cpp │ │ ├── PGLibraryWin32.cpp │ │ ├── PGPlatformDefinesWin32.h │ │ ├── PGTimeWin32.cpp │ │ └── PGWindowWin32.cpp ├── PlaygroundEngine.vcxproj ├── PlaygroundEngine.vcxproj.filters ├── PlaygroundEngine.vcxproj.user ├── Renderer │ ├── BaseRenderPass.h │ ├── DX11 │ │ ├── DX11Buffer.cpp │ │ ├── DX11Buffer.h │ │ ├── DX11PipelineStates.cpp │ │ ├── DX11PipelineStates.h │ │ ├── DX11Query.cpp │ │ ├── DX11Query.h │ │ ├── DX11RenderTargets.cpp │ │ ├── DX11RenderTargets.h │ │ ├── DX11RendererAPI.cpp │ │ ├── DX11RendererAPI.h │ │ ├── DX11SamplerState.cpp │ │ ├── DX11SamplerState.h │ │ ├── DX11ShaderResourceView.cpp │ │ ├── DX11ShaderResourceView.h │ │ ├── DX11Texture2D.cpp │ │ └── DX11Texture2D.h │ ├── FullscreenPass.h │ ├── HWBuffer.h │ ├── HWPipelineStates.h │ ├── HWQuery.h │ ├── HWRenderTarget.h │ ├── HWRendererAPI.h │ ├── HWResource.h │ ├── HWSamplerState.h │ ├── HWShaderResourceView.h │ ├── HWTexture2D.h │ ├── Material.h │ ├── PGRenderList.cpp │ ├── PGRenderList.h │ ├── PGRenderer.cpp │ ├── PGRenderer.h │ ├── PGRendererResources.cpp │ ├── PGRendererResources.h │ ├── PGShader.cpp │ ├── PGShader.h │ ├── PGShaderLib.cpp │ ├── PGShaderLib.h │ ├── PGTexture.cpp │ ├── PGTexture.h │ ├── SceneRenderPass.h │ ├── ShadowMapStage.cpp │ ├── ShadowMapStage.h │ ├── Skybox.cpp │ └── Skybox.h ├── Scene.h ├── Transform.h └── Utility │ ├── rapidjson │ ├── allocators.h │ ├── cursorstreamwrapper.h │ ├── document.h │ ├── encodedstream.h │ ├── encodings.h │ ├── error │ │ ├── en.h │ │ └── error.h │ ├── filereadstream.h │ ├── filewritestream.h │ ├── fwd.h │ ├── internal │ │ ├── biginteger.h │ │ ├── clzll.h │ │ ├── diyfp.h │ │ ├── dtoa.h │ │ ├── ieee754.h │ │ ├── itoa.h │ │ ├── meta.h │ │ ├── pow10.h │ │ ├── regex.h │ │ ├── stack.h │ │ ├── strfunc.h │ │ ├── strtod.h │ │ └── swap.h │ ├── istreamwrapper.h │ ├── memorybuffer.h │ ├── memorystream.h │ ├── msinttypes │ │ ├── inttypes.h │ │ └── stdint.h │ ├── ostreamwrapper.h │ ├── pointer.h │ ├── prettywriter.h │ ├── rapidjson.h │ ├── reader.h │ ├── schema.h │ ├── stream.h │ ├── stringbuffer.h │ └── writer.h │ ├── stb_image.h │ ├── tiny_gltf.h │ ├── tiny_obj_loader.cpp │ ├── tiny_obj_loader.h │ ├── tinyddsloader.cpp │ └── tinyddsloader.h ├── README.md └── screenshots ├── screenshot1.png ├── screenshot2.png └── screenshot3.png /.gitignore: -------------------------------------------------------------------------------- 1 | .vs 2 | Debug 3 | Release 4 | bin 5 | build 6 | -------------------------------------------------------------------------------- /Example/Application.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | class Application : public IApplication { 8 | public: 9 | Application(PGSystem* system); 10 | ~Application() override; 11 | 12 | virtual void OnSystemEvent(SystemEvent event, uint64_t param1, uint64_t param2) override; 13 | 14 | void OnInit() override; 15 | void OnUpdate(float deltaTime) override; 16 | void OnUIRender() override; 17 | void OnExit() override; 18 | 19 | private: 20 | PGSystem* m_System; 21 | Material* m_DefaultMaterial; 22 | ShaderRef m_PBRShader; 23 | PGScene m_Scene; 24 | 25 | }; 26 | REGISTER_GAME_APPLICATION(Application) 27 | -------------------------------------------------------------------------------- /Example/Example.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Header Files 25 | 26 | 27 | Header Files 28 | 29 | 30 | Header Files 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /Example/Example.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | true 5 | 6 | 7 | $(OutDir)PlaygroundEngine.exe 8 | WindowsLocalDebugger 9 | $(TargetPath) 10 | 11 | 12 | $(OutDir)PlaygroundEngine.exe 13 | WindowsLocalDebugger 14 | $(TargetPath) 15 | 16 | -------------------------------------------------------------------------------- /Example/LogWindow.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | void DrawLogWindow() { 6 | if (!ImGui::Begin("Logs")) 7 | { 8 | ImGui::End(); 9 | return; 10 | } 11 | 12 | static ImGuiTextFilter textFilter; 13 | static bool autoScroll = true; 14 | // Options menu 15 | if (ImGui::BeginPopup("Options")) 16 | { 17 | ImGui::Checkbox("Auto-scroll", &autoScroll); 18 | ImGui::EndPopup(); 19 | } 20 | 21 | // Main window 22 | if (ImGui::Button("Options")) 23 | ImGui::OpenPopup("Options"); 24 | ImGui::SameLine(); 25 | bool clear = ImGui::Button("Clear"); 26 | ImGui::SameLine(); 27 | textFilter.Draw("Filter", -100.0f); 28 | 29 | ImGui::Separator(); 30 | ImGui::BeginChild("scrolling", ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar); 31 | 32 | if (clear) 33 | PGLog::ClearLogList(); 34 | 35 | ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0)); 36 | 37 | LogList logList = PGLog::GetLogList(); 38 | for (LogItem item : logList) { 39 | if (!textFilter.PassFilter(item.logData)) { 40 | continue; 41 | } 42 | 43 | switch (item.type) { 44 | case LOG_WARNING: 45 | { 46 | ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.8f, 0.6f, 1.0f)); 47 | } break; 48 | case LOG_ERROR: 49 | { 50 | ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.4f, 0.4f, 1.0f)); 51 | } break; 52 | default: 53 | { 54 | ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 1.0f, 1.0f, 1.0f)); 55 | } break; 56 | } 57 | 58 | ImGui::TextUnformatted(item.logData); 59 | ImGui::PopStyleColor(); 60 | } 61 | ImGui::PopStyleVar(); 62 | 63 | if (autoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY()) 64 | ImGui::SetScrollHereY(1.0f); 65 | 66 | ImGui::EndChild(); 67 | ImGui::End(); 68 | } 69 | 70 | -------------------------------------------------------------------------------- /Example/PerformanceWindow.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | static bool CompareProfile(const ProfileData& left, const ProfileData& right) 7 | { 8 | return (left.startNanoSeconds < right.startNanoSeconds); 9 | } 10 | 11 | struct ProfileNode { 12 | ProfileData data; 13 | std::vector childNodes; 14 | }; 15 | 16 | static bool InsertProfileData(std::vector& profileList, const ProfileData& data) { 17 | bool inserted = false; 18 | for (ProfileNode& node : profileList) { 19 | uint64_t nodeStartTime = node.data.startNanoSeconds; 20 | uint64_t nodeEndTime = node.data.startNanoSeconds + node.data.durationNanoSeconds; 21 | 22 | if (data.startNanoSeconds >= nodeStartTime && data.startNanoSeconds < nodeEndTime) { 23 | if (!node.childNodes.empty()) { 24 | inserted = InsertProfileData(node.childNodes, data); 25 | } 26 | if (!inserted) { 27 | ProfileNode newNode; 28 | newNode.data = data; 29 | node.childNodes.push_back(newNode); 30 | inserted = true; 31 | } 32 | } 33 | } 34 | if (!inserted) { 35 | ProfileNode newNode; 36 | newNode.data = data; 37 | profileList.push_back(newNode); 38 | inserted = true; 39 | } 40 | return inserted; 41 | } 42 | 43 | static void DrawChildNodes(const std::vector& profileTree) { 44 | for (auto& profileNode : profileTree) { 45 | const char* profileName = profileNode.data.name.c_str(); 46 | double durationMilliseconds = profileNode.data.durationNanoSeconds / 1000000.0; 47 | if (profileNode.childNodes.empty()) { 48 | ImGui::Text("%s %.3f ms", profileName, durationMilliseconds); 49 | } else { 50 | //ImGui::SetNextItemOpen(true, ImGuiCond_FirstUseEver); 51 | if (ImGui::TreeNode(profileName, "%s %.3f ms", profileName, durationMilliseconds)) { 52 | DrawChildNodes(profileNode.childNodes); 53 | ImGui::TreePop(); 54 | } 55 | } 56 | } 57 | } 58 | 59 | static void DrawPerformanceWindow() { 60 | ProfileList profileList = PGProfileTimer::s_ProfileResults; 61 | std::sort(profileList.begin(), profileList.end(), CompareProfile); 62 | 63 | // Put profile data into a tree-like structure, so that we can look profile data in a hierarchical view 64 | std::vector profileTree; 65 | for (ProfileData profileData : profileList) { 66 | InsertProfileData(profileTree, profileData); 67 | } 68 | 69 | if (ImGui::Begin("Performance")) { 70 | DrawChildNodes(profileTree); 71 | } 72 | ImGui::End(); 73 | PGProfileTimer::s_ProfileResults.clear(); 74 | 75 | std::vector gpuProfileData; 76 | PGGPUProfilerTimer::GetProfileList(PGRenderer::GetRendererAPI(), gpuProfileData); 77 | std::sort(gpuProfileData.begin(), gpuProfileData.end(), CompareProfile); 78 | 79 | std::vector gpuProfileTree; 80 | for (ProfileData profileData : gpuProfileData) { 81 | InsertProfileData(gpuProfileTree, profileData); 82 | } 83 | 84 | if (ImGui::Begin("GPU Performance")) { 85 | DrawChildNodes(gpuProfileTree); 86 | } 87 | ImGui::End(); 88 | 89 | 90 | } 91 | 92 | -------------------------------------------------------------------------------- /Example/assets/AntiqueCamera.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/AntiqueCamera.glb -------------------------------------------------------------------------------- /Example/assets/DamagedHelmet/DamagedHelmet.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/DamagedHelmet/DamagedHelmet.bin -------------------------------------------------------------------------------- /Example/assets/DamagedHelmet/Default_AO.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/DamagedHelmet/Default_AO.jpg -------------------------------------------------------------------------------- /Example/assets/DamagedHelmet/Default_albedo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/DamagedHelmet/Default_albedo.jpg -------------------------------------------------------------------------------- /Example/assets/DamagedHelmet/Default_emissive.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/DamagedHelmet/Default_emissive.jpg -------------------------------------------------------------------------------- /Example/assets/DamagedHelmet/Default_metalRoughness.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/DamagedHelmet/Default_metalRoughness.jpg -------------------------------------------------------------------------------- /Example/assets/DamagedHelmet/Default_normal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/DamagedHelmet/Default_normal.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/10381718147657362067.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/10381718147657362067.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/10388182081421875623.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/10388182081421875623.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/11474523244911310074.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/11474523244911310074.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/11490520546946913238.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/11490520546946913238.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/11872827283454512094.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/11872827283454512094.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/11968150294050148237.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/11968150294050148237.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/1219024358953944284.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/1219024358953944284.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/12501374198249454378.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/12501374198249454378.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/13196865903111448057.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/13196865903111448057.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/13824894030729245199.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/13824894030729245199.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/13982482287905699490.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/13982482287905699490.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/14118779221266351425.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/14118779221266351425.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/14170708867020035030.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/14170708867020035030.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/14267839433702832875.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/14267839433702832875.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/14650633544276105767.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/14650633544276105767.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/15295713303328085182.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/15295713303328085182.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/15722799267630235092.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/15722799267630235092.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/16275776544635328252.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/16275776544635328252.png -------------------------------------------------------------------------------- /Example/assets/Sponza/16299174074766089871.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/16299174074766089871.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/16885566240357350108.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/16885566240357350108.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/17556969131407844942.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/17556969131407844942.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/17876391417123941155.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/17876391417123941155.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/2051777328469649772.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/2051777328469649772.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/2185409758123873465.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/2185409758123873465.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/2299742237651021498.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/2299742237651021498.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/2374361008830720677.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/2374361008830720677.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/2411100444841994089.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/2411100444841994089.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/2775690330959970771.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/2775690330959970771.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/2969916736137545357.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/2969916736137545357.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/332936164838540657.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/332936164838540657.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/3371964815757888145.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/3371964815757888145.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/3455394979645218238.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/3455394979645218238.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/3628158980083700836.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/3628158980083700836.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/3827035219084910048.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/3827035219084910048.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/4477655471536070370.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/4477655471536070370.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/4601176305987539675.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/4601176305987539675.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/466164707995436622.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/466164707995436622.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/4675343432951571524.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/4675343432951571524.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/4871783166746854860.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/4871783166746854860.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/4910669866631290573.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/4910669866631290573.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/4975155472559461469.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/4975155472559461469.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/5061699253647017043.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/5061699253647017043.png -------------------------------------------------------------------------------- /Example/assets/Sponza/5792855332885324923.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/5792855332885324923.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/5823059166183034438.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/5823059166183034438.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/6047387724914829168.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/6047387724914829168.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/6151467286084645207.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/6151467286084645207.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/6593109234861095314.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/6593109234861095314.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/6667038893015345571.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/6667038893015345571.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/6772804448157695701.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/6772804448157695701.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/7056944414013900257.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/7056944414013900257.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/715093869573992647.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/715093869573992647.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/7268504077753552595.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/7268504077753552595.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/7441062115984513793.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/7441062115984513793.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/755318871556304029.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/755318871556304029.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/759203620573749278.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/759203620573749278.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/7645212358685992005.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/7645212358685992005.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/7815564343179553343.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/7815564343179553343.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/8006627369776289000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/8006627369776289000.png -------------------------------------------------------------------------------- /Example/assets/Sponza/8051790464816141987.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/8051790464816141987.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/8114461559286000061.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/8114461559286000061.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/8481240838833932244.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/8481240838833932244.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/8503262930880235456.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/8503262930880235456.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/8747919177698443163.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/8747919177698443163.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/8750083169368950601.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/8750083169368950601.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/8773302468495022225.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/8773302468495022225.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/8783994986360286082.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/8783994986360286082.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/9288698199695299068.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/9288698199695299068.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/9916269861720640319.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/9916269861720640319.jpg -------------------------------------------------------------------------------- /Example/assets/Sponza/Sponza.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/Sponza.bin -------------------------------------------------------------------------------- /Example/assets/Sponza/white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/Sponza/white.png -------------------------------------------------------------------------------- /Example/assets/beach/beach.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/beach/beach.dds -------------------------------------------------------------------------------- /Example/assets/beach/beachirradiance.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/beach/beachirradiance.dds -------------------------------------------------------------------------------- /Example/assets/beach/beachradiance.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/beach/beachradiance.dds -------------------------------------------------------------------------------- /Example/assets/beach/brdfLUT.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/Example/assets/beach/brdfLUT.dds -------------------------------------------------------------------------------- /Example/assets/scenes/AntiqueCamera.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "AntiqueCamera", 3 | 4 | "models": [ 5 | { 6 | "filepath": "../AntiqueCamera.glb", 7 | "leftHandedNormalMap": false 8 | } 9 | ], 10 | 11 | "camera": { 12 | "fov": 45.0, 13 | "nearPlane": 0.1, 14 | "farPlane": 100.0, 15 | "position": [ 0.0, 3.0, -4.0 ] 16 | }, 17 | 18 | "directionalLight": { 19 | "direction": [ -20.0, -54.0, 20.0 ], 20 | "color": [ 1.0, 0.8, 0.6 ], 21 | "intensity": 4.0 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Example/assets/scenes/DamagedHelmet.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "DamagedHelmet", 3 | 4 | "models": [ 5 | { 6 | "filepath": "../DamagedHelmet/DamagedHelmet.gltf", 7 | "leftHandedNormalMap": false 8 | } 9 | ], 10 | 11 | "camera": { 12 | "fov": 45.0, 13 | "nearPlane": 0.1, 14 | "farPlane": 100.0, 15 | "position": [ 0.0, -0.5, -4.0 ] 16 | }, 17 | 18 | "directionalLight": { 19 | "direction": [ -20.0, -54.0, 20.0 ], 20 | "color": [ 1.0, 0.8, 0.6 ], 21 | "intensity": 4.0 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Example/assets/scenes/sponza.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Sponza", 3 | 4 | "models": [ 5 | { 6 | "filepath": "../Sponza/Sponza.gltf", 7 | "leftHandedNormalMap": true 8 | } 9 | ], 10 | 11 | "camera": { 12 | "fov": 45.0, 13 | "nearPlane": 0.1, 14 | "farPlane": 100.0, 15 | "position": [ 1.0, 3.0, 0.0 ] 16 | }, 17 | 18 | "directionalLight": { 19 | "direction": [ -20.0, -54.0, 20.0 ], 20 | "color": [ 1.0, 0.8, 0.6 ], 21 | "intensity": 4.0 22 | }, 23 | 24 | "pointLights": [ 25 | { 26 | "position": [ -3.0, 1.0, 1.0 ], 27 | "color": [ 0.0, 0.8, 1.0 ], 28 | "intensity": 5.0 29 | }, 30 | 31 | { 32 | "position": [ 3.0, 1.0, 1.0 ], 33 | "color": [ 1.0, 0.0, 1.0 ], 34 | "intensity": 5.0 35 | }, 36 | 37 | { 38 | "position": [ -3.0, 5.0, 3.0 ], 39 | "color": [ 0.0, 0.8, 0.0 ], 40 | "intensity": 4.0 41 | }, 42 | 43 | { 44 | "position": [ -5.0, 5.0, -2.0 ], 45 | "color": [ 1.0, 0.0, 0.0 ], 46 | "intensity": 3.0 47 | } 48 | ], 49 | 50 | "spotLights": [ 51 | { 52 | "position": [ 0.0, 1.0, 0.5 ], 53 | "direction": [ -1.0, -0.5, 0.0 ], 54 | "minConeAngle": 38.0, 55 | "maxConeAngle": 45.0, 56 | "color": [ 1.0, 1.0, 0.3 ], 57 | "intensity": 2.0 58 | }, 59 | 60 | { 61 | "position": [ 0.0, 1.0, -0.5 ], 62 | "direction": [ -1.0, -0.5, 0.0 ], 63 | "minConeAngle": 38.0, 64 | "maxConeAngle": 45.0, 65 | "color": [ 1.0, 1.0, 0.3 ], 66 | "intensity": 2.0 67 | } 68 | ] 69 | } 70 | -------------------------------------------------------------------------------- /Example/imgui.ini: -------------------------------------------------------------------------------- 1 | [Window][Debug##Default] 2 | Pos=60,60 3 | Size=400,400 4 | Collapsed=1 5 | 6 | [Window][Dear ImGui Demo] 7 | Pos=771,0 8 | Size=490,517 9 | Collapsed=0 10 | 11 | [Window][Hello, world!] 12 | Pos=1008,7 13 | Size=252,150 14 | Collapsed=0 15 | 16 | [Window][Another Window] 17 | Pos=139,106 18 | Size=198,71 19 | Collapsed=0 20 | 21 | [Window][Example: Console] 22 | Pos=60,60 23 | Size=520,600 24 | Collapsed=0 25 | 26 | [Window][Example: Log] 27 | Pos=60,60 28 | Size=500,400 29 | Collapsed=0 30 | 31 | [Window][Example: Auto-resizing window] 32 | Pos=60,60 33 | Size=485,335 34 | Collapsed=0 35 | 36 | [Window][Same title as another window##2] 37 | Pos=100,200 38 | Size=450,61 39 | Collapsed=0 40 | 41 | [Window][###AnimatedTitle] 42 | Pos=100,300 43 | Size=247,48 44 | Collapsed=0 45 | 46 | [Window][Same title as another window##1] 47 | Pos=103,100 48 | Size=450,61 49 | Collapsed=0 50 | 51 | [Window][Example: Custom rendering] 52 | Pos=192,312 53 | Size=466,265 54 | Collapsed=0 55 | 56 | [Window][Example: Documents] 57 | Pos=60,60 58 | Size=621,675 59 | Collapsed=0 60 | 61 | [Window][Performance] 62 | Pos=970,0 63 | Size=292,359 64 | Collapsed=0 65 | DockId=0x00000009,0 66 | 67 | [Window][Material] 68 | Size=250,787 69 | Collapsed=0 70 | DockId=0x00000004,0 71 | 72 | [Window][Logs] 73 | Pos=0,547 74 | Size=968,126 75 | Collapsed=0 76 | DockId=0x00000006,0 77 | 78 | [Window][DockSpace Demo] 79 | Pos=0,0 80 | Size=1262,673 81 | Collapsed=0 82 | 83 | [Window][Renderer Settings] 84 | Pos=0,0 85 | Size=225,545 86 | Collapsed=0 87 | DockId=0x00000002,0 88 | 89 | [Window][GPU Performance] 90 | Pos=970,361 91 | Size=292,312 92 | Collapsed=0 93 | DockId=0x0000000A,0 94 | 95 | [Docking][Data] 96 | DockSpace ID=0x3BC79352 Window=0x4647B76E Pos=0,0 Size=1262,673 Split=X 97 | DockNode ID=0x00000005 Parent=0x3BC79352 SizeRef=968,673 Split=Y 98 | DockNode ID=0x00000001 Parent=0x00000005 SizeRef=1264,811 Split=X 99 | DockNode ID=0x00000004 Parent=0x00000001 SizeRef=250,470 Selected=0x85C817C3 100 | DockNode ID=0x00000007 Parent=0x00000001 SizeRef=1668,470 Split=X 101 | DockNode ID=0x00000002 Parent=0x00000007 SizeRef=225,545 Selected=0xDD921666 102 | DockNode ID=0x00000003 Parent=0x00000007 SizeRef=741,545 CentralNode=1 103 | DockNode ID=0x00000006 Parent=0x00000005 SizeRef=1264,188 Selected=0x50BD6962 104 | DockNode ID=0x00000008 Parent=0x3BC79352 SizeRef=292,673 Split=Y Selected=0x044B1956 105 | DockNode ID=0x00000009 Parent=0x00000008 SizeRef=292,359 Selected=0x044B1956 106 | DockNode ID=0x0000000A Parent=0x00000008 SizeRef=292,312 Selected=0xC27A4B3D 107 | 108 | -------------------------------------------------------------------------------- /PlaygroundEngine.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29123.88 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Example", "Example\Example.vcxproj", "{B40D4D62-CA32-4B3B-911C-8352A3F4F02B}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PlaygroundEngine", "PlaygroundEngine\PlaygroundEngine.vcxproj", "{544846F0-5760-42C4-B944-D296820C6464}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|x64 = Debug|x64 13 | Release|x64 = Release|x64 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {544846F0-5760-42C4-B944-D296820C6464}.Debug|x64.ActiveCfg = Debug|x64 17 | {544846F0-5760-42C4-B944-D296820C6464}.Debug|x64.Build.0 = Debug|x64 18 | {544846F0-5760-42C4-B944-D296820C6464}.Release|x64.ActiveCfg = Release|x64 19 | {544846F0-5760-42C4-B944-D296820C6464}.Release|x64.Build.0 = Release|x64 20 | {B40D4D62-CA32-4B3B-911C-8352A3F4F02B}.Debug|x64.ActiveCfg = Debug|x64 21 | {B40D4D62-CA32-4B3B-911C-8352A3F4F02B}.Debug|x64.Build.0 = Debug|x64 22 | {B40D4D62-CA32-4B3B-911C-8352A3F4F02B}.Release|x64.ActiveCfg = Release|x64 23 | {B40D4D62-CA32-4B3B-911C-8352A3F4F02B}.Release|x64.Build.0 = Release|x64 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {652B9258-FE53-4404-B6AF-06F7EC446DB9} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /PlaygroundEngine/Assets/Shaders/BRDF.hlsli: -------------------------------------------------------------------------------- 1 | #define PI 3.14159265f 2 | 3 | // Diffuse 4 | inline float3 DiffuseLambert() { 5 | return 1.0f / PI; 6 | } 7 | 8 | // Specular distrubution function 9 | inline float DistributionGGX(float3 normalVector, float3 halfwayVector, float roughness) { 10 | float a = roughness * roughness; 11 | float a2 = a * a; 12 | float NdotH = saturate(dot(normalVector, halfwayVector)); 13 | float NdotH2 = NdotH * NdotH; 14 | 15 | float denom = NdotH2 * (a2 - 1.0f) + 1; 16 | denom = PI * denom * denom; 17 | 18 | return a2 / denom; 19 | } 20 | 21 | inline float GeometryGGX(float3 normalVector, float3 v, float k) { 22 | float NdotV = saturate(dot(normalVector, v)); 23 | 24 | float denom = NdotV * (1.0f - k) + k; 25 | return NdotV / denom; 26 | } 27 | 28 | inline float GeometrySmith(float3 viewVector, float3 normalVector, float3 lightVector, float roughness) { 29 | float a = roughness * roughness; 30 | float k = pow((a + 1), 2) / 8.0f; 31 | 32 | float ggxL = GeometryGGX(normalVector, lightVector, k); 33 | float ggxV = GeometryGGX(normalVector, viewVector, k); 34 | 35 | return ggxL * ggxV; 36 | } 37 | 38 | inline float3 FresnelSchlick(float angle, float3 f0, float f90) { 39 | return f0 + (f90 - f0) * pow(1.0 - angle, 5.0f); 40 | } 41 | 42 | inline float3 FresnelSchlickRoughness(float angle, float3 F0, float roughness) { 43 | return F0 + (max((float3)(1.0 - roughness), F0) - F0) * pow(1.0 - angle, 5.0); 44 | } 45 | 46 | inline float DisneyDiffuse(float3 lightVector, float3 halfwayVector, float3 normalVector, float3 viewVector, float roughness) { 47 | float LdotH = saturate(dot(lightVector, halfwayVector)); 48 | float NdotL = saturate(dot(lightVector, normalVector)); 49 | float NdotV = saturate(dot(viewVector, normalVector)); 50 | 51 | float energyBias = lerp(0, 0.5, roughness); 52 | float energyFactor = lerp(1.0, 1.0 / 1.51, roughness); 53 | float3 f0 = float3(1.0f, 1.0f, 1.0f); 54 | float f90 = energyBias + 2.0 * roughness * LdotH * LdotH; 55 | float lightScatter = FresnelSchlick(NdotL, f0, f90).r; 56 | float viewScatter = FresnelSchlick(NdotV, f0, f90).r; 57 | return lightScatter * viewScatter * energyFactor * (1.0 / PI); 58 | } 59 | 60 | float3 BRDF(float3 lightVector, float3 normalVector, float3 viewVector, float3 albedo, float roughness, float metallic) { 61 | float3 halfwayVector = normalize(viewVector + lightVector); 62 | 63 | float D = DistributionGGX(normalVector, halfwayVector, roughness); 64 | float G = GeometrySmith(viewVector, normalVector, lightVector, roughness); 65 | 66 | float3 f0 = lerp((float3) 0.04f, albedo, metallic); 67 | 68 | float VdotH = saturate(dot(viewVector, halfwayVector)); 69 | float3 F = FresnelSchlick(VdotH, f0, 1.0f); 70 | 71 | float3 kS = F; 72 | float3 kD = 1.0f - kS; 73 | kD *= 1.0 - metallic; 74 | 75 | float NdotL = saturate(dot(normalVector, lightVector)); 76 | 77 | float3 numerator = D * G * F; 78 | float3 denom = 4.0f * saturate(dot(normalVector, viewVector)) * NdotL; 79 | float3 specularBRDF = numerator / max(denom, 0.001f); 80 | 81 | float3 diffuseBRDF = kD * albedo * DisneyDiffuse(lightVector, halfwayVector, normalVector, viewVector, roughness); 82 | 83 | float3 brdf = diffuseBRDF + specularBRDF; 84 | float3 Lo = brdf * NdotL; 85 | 86 | return Lo; 87 | } 88 | -------------------------------------------------------------------------------- /PlaygroundEngine/Assets/Shaders/DebugShader.hlsl: -------------------------------------------------------------------------------- 1 | #include "ShaderDefinitions.h" 2 | 3 | /////////////////////////////////////////////////////////////////////////// 4 | /////// VERTEX SHADER 5 | /////////////////////////////////////////////////////////////////////////// 6 | struct VSInput { 7 | float3 pos : POSITION; 8 | }; 9 | 10 | struct VSOut { 11 | float4 pos : SV_Position; 12 | }; 13 | 14 | VSOut VSMain(VSInput input) { 15 | VSOut output; 16 | output.pos = mul(g_ProjViewMatrix, float4(input.pos, 1.0f)); 17 | 18 | return output; 19 | } 20 | 21 | /////////////////////////////////////////////////////////////////////////// 22 | /////// FRAGMENT SHADER 23 | /////////////////////////////////////////////////////////////////////////// 24 | float4 PSMain(VSOut input) : SV_Target{ 25 | return float4(1.0f, 1.0f, 0.0f, 1.0f); 26 | } 27 | -------------------------------------------------------------------------------- /PlaygroundEngine/Assets/Shaders/DepthGen.hlsl: -------------------------------------------------------------------------------- 1 | #include "ShaderDefinitions.h" 2 | 3 | /////////////////////////////////////////////////////////////////////////// 4 | /////// VERTEX SHADER 5 | /////////////////////////////////////////////////////////////////////////// 6 | 7 | struct VSInput { 8 | float3 pos : POSITION; 9 | #ifdef ALPHA_TEST 10 | float2 texCoord : TEXCOORD; 11 | #endif 12 | }; 13 | 14 | struct VSOut { 15 | #ifdef ALPHA_TEST 16 | float2 texCoord : TEXCOORD; 17 | #endif 18 | float4 pos : SV_Position; 19 | }; 20 | 21 | VSOut VSMain(VSInput input) { 22 | VSOut output; 23 | #ifdef ALPHA_TEST 24 | output.texCoord = input.texCoord; 25 | #endif 26 | output.pos = mul(g_ProjViewMatrix, mul(g_ModelMatrix, float4(input.pos, 1.0f))); 27 | return output; 28 | } 29 | 30 | /////////////////////////////////////////////////////////////////////////// 31 | /////// FRAGMENT SHADER 32 | /////////////////////////////////////////////////////////////////////////// 33 | #ifdef ALPHA_TEST 34 | void PSMain(VSOut input) { 35 | float alpha = g_Material.diffuseColor.a; 36 | if (g_Material.hasAlbedoTexture) { 37 | alpha = g_AlbedoTexture.SampleLevel(g_LinearWrapSampler, input.texCoord, 0.0f).a; 38 | } 39 | 40 | clip(alpha - 0.1f); 41 | } 42 | #endif 43 | 44 | -------------------------------------------------------------------------------- /PlaygroundEngine/Assets/Shaders/HDRPostProcess.hlsl: -------------------------------------------------------------------------------- 1 | #include "ShaderDefinitions.h" 2 | 3 | /////////////////////////////////////////////////////////////////////////// 4 | /////// VERTEX SHADER 5 | /////////////////////////////////////////////////////////////////////////// 6 | 7 | struct VSOut { 8 | float2 texCoords : TEXCOORD0; 9 | float4 pos : SV_POSITION; 10 | }; 11 | 12 | VSOut VSMain(uint vid : SV_VertexID) 13 | { 14 | VSOut output; 15 | output.texCoords = float2((vid << 1) & 2, vid & 2); 16 | output.pos = float4(output.texCoords * float2(2, -2) + float2(-1, 1), 0, 1); 17 | 18 | return output; 19 | } 20 | 21 | /////////////////////////////////////////////////////////////////////////// 22 | /////// FRAGMENT SHADER 23 | /////////////////////////////////////////////////////////////////////////// 24 | // https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/ 25 | float3 ACESFast(float3 x) 26 | { 27 | x *= 0.6f; 28 | float a = 2.51f; 29 | float b = 0.03f; 30 | float c = 2.43f; 31 | float d = 0.59f; 32 | float e = 0.14f; 33 | return saturate((x * (a * x + b)) / (x * (c * x + d) + e)); 34 | } 35 | 36 | static const float3x3 ACESInputMat = 37 | { 38 | {0.59719, 0.35458, 0.04823}, 39 | {0.07600, 0.90834, 0.01566}, 40 | {0.02840, 0.13383, 0.83777} 41 | }; 42 | 43 | // ODT_SAT => XYZ => D60_2_D65 => sRGB 44 | static const float3x3 ACESOutputMat = 45 | { 46 | { 1.60475, -0.53108, -0.07367}, 47 | {-0.10208, 1.10813, -0.00605}, 48 | {-0.00327, -0.07276, 1.07602} 49 | }; 50 | 51 | float3 RRTAndODTFit(float3 v) 52 | { 53 | float3 a = v * (v + 0.0245786f) - 0.000090537f; 54 | float3 b = v * (0.983729f * v + 0.4329510f) + 0.238081f; 55 | return a / b; 56 | } 57 | 58 | float3 ACESFitted(float3 color) 59 | { 60 | color = mul(ACESInputMat, color); 61 | 62 | // Apply RRT and ODT 63 | color = RRTAndODTFit(color); 64 | 65 | color = mul(ACESOutputMat, color); 66 | 67 | // Clamp to [0, 1] 68 | color = saturate(color); 69 | 70 | return color; 71 | } 72 | 73 | 74 | float4 PSMain(VSOut input) : SV_Target 75 | { 76 | float3 hdrColor = g_PostProcessTexture0.Load(input.pos.xyz).rgb; 77 | hdrColor *= g_PPExposure; 78 | 79 | // ACES film curve from https://github.com/TheRealMJP/BakingLab/blob/master/BakingLab/ACES.hlsl 80 | float3 tonemappedColor = ACESFitted(hdrColor); 81 | 82 | // Gamma correction 83 | float inverseGamma = 1.0f / g_PPGamma; 84 | tonemappedColor = pow(tonemappedColor, inverseGamma); 85 | 86 | return float4(tonemappedColor, 1.0f); 87 | } 88 | -------------------------------------------------------------------------------- /PlaygroundEngine/Assets/Shaders/ShadowUtils.hlsli: -------------------------------------------------------------------------------- 1 | 2 | inline float PCFShadowMap(float3 shadowCoord, uint cascadeIndex, float bias) { 3 | float texelSize = 1.0f / g_ShadowMapSize; 4 | float kernelSize = 3; 5 | int index = floor(kernelSize / 2); 6 | float shadowValue = 0; 7 | float compareValue = shadowCoord.z - bias; 8 | [unroll] 9 | for (int i = -index; i <= index; ++i) { 10 | [unroll] 11 | for (int j = -index; j <= index; ++j) { 12 | int2 offset = int2(i, j); 13 | float sampleCmp = g_ShadowMapTexture.SampleCmpLevelZero(g_ShadowMapSampler, float3(shadowCoord.xy, cascadeIndex), compareValue, offset); 14 | shadowValue += sampleCmp; 15 | } 16 | } 17 | shadowValue /= (kernelSize * kernelSize); 18 | return shadowValue; 19 | } 20 | 21 | inline float CalculateShadowValue(float3 worldSpacePos, out uint hitCascadeIndex) { 22 | float shadowFactor = 1; 23 | float3 visualizeColor = float3(1.0f, 1.0f, 1.0f); 24 | 25 | for (uint cascadeIndex = 0; cascadeIndex < g_ShadowCascadeCount; ++cascadeIndex) { 26 | // ShadowCoordinates 27 | float4 worldPosLightSpace = mul(g_DirectionLightProjViewMatrices[cascadeIndex], float4(worldSpacePos, 1.0f)); 28 | float3 shadowCoord = worldPosLightSpace.xyz / worldPosLightSpace.w; 29 | shadowCoord.x = shadowCoord.x * 0.5f + 0.5f; 30 | shadowCoord.y = shadowCoord.y * -0.5f + 0.5f; 31 | 32 | [branch] 33 | float bias = 0.0015f; 34 | if (all(saturate(shadowCoord) == shadowCoord)) { 35 | bias += (0.0015f * cascadeIndex * cascadeIndex); 36 | float shadowValue = PCFShadowMap(shadowCoord, cascadeIndex, bias); 37 | shadowFactor = shadowValue; 38 | hitCascadeIndex = cascadeIndex; 39 | 40 | // TODO: Blend cascade edges for smooth cascade transition 41 | break; 42 | } 43 | } 44 | 45 | return shadowFactor; 46 | } 47 | 48 | static const float3 sampleOffsetDirections[20] = { 49 | float3(1, 1, 1), float3(1, -1, 1), float3(-1, -1, 1), float3(-1, 1, 1), 50 | float3(1, 1, -1), float3(1, -1, -1), float3(-1, -1, -1), float3(-1, 1, -1), 51 | float3(1, 1, 0), float3(1, -1, 0), float3(-1, -1, 0), float3(-1, 1, 0), 52 | float3(1, 0, 1), float3(-1, 0, 1), float3(1, 0, -1), float3(-1, 0, -1), 53 | float3(0, 1, 1), float3(0, -1, 1), float3(0, -1, -1), float3(0, 1, -1) 54 | }; 55 | 56 | inline float PointLightPCFShadowMap(float3 shadowCoord, uint lightIndex, float bias) { 57 | float n = g_PointLightProjNearPlane; 58 | float f = g_PointLightProjFarPlane; 59 | 60 | float3 absVec = abs(shadowCoord); 61 | float viewZ = max(absVec.x, max(absVec.y, absVec.z)); 62 | 63 | float projectedZ = (f + n) / (f - n) - ((2 * f * n) / (f - n)) / viewZ; 64 | projectedZ = (projectedZ + 1.0) * 0.5; 65 | float compareValue = projectedZ - bias; 66 | 67 | float shadowValue = 0; 68 | float diskRadius = 0.01f; 69 | uint sampleCount = 20; 70 | for (uint i = 0; i < sampleCount; ++i) { 71 | float3 offset = sampleOffsetDirections[i] * diskRadius; 72 | float sampleCmp = g_PointLightShadowMapArray.SampleCmpLevelZero(g_ShadowMapSampler, float4(shadowCoord + offset, lightIndex), compareValue); 73 | shadowValue += sampleCmp; 74 | } 75 | 76 | return shadowValue / sampleCount; 77 | } 78 | 79 | inline float CalculatePointLightShadow(float3 unnormalizedLightVector, uint lightIndex) { 80 | float bias = 0.005f; 81 | 82 | return PointLightPCFShadowMap(-unnormalizedLightVector, lightIndex, bias); 83 | } 84 | 85 | inline float SpotLightPCFShadowMap(float3 shadowCoord, uint lightIndex, float bias) { 86 | float kernelSize = 3; 87 | int index = floor(kernelSize / 2); 88 | float shadowValue = 0; 89 | float compareValue = shadowCoord.z - bias; 90 | [unroll] 91 | for (int i = -index; i <= index; ++i) { 92 | [unroll] 93 | for (int j = -index; j <= index; ++j) { 94 | float2 offset = float2(i, j) * 0.002f; 95 | float sampleCmp = g_SpotLightShadowMapArray.SampleCmpLevelZero(g_ShadowMapSampler, float3(shadowCoord.xy + offset, lightIndex), compareValue); 96 | shadowValue += sampleCmp; 97 | } 98 | } 99 | shadowValue /= (kernelSize * kernelSize); 100 | return shadowValue; 101 | } 102 | 103 | inline float CalculateSpotLightShadow(float3 worldSpacePos, uint lightIndex) { 104 | float bias = 0.001f; 105 | 106 | float4 worldPosLightClipSpace = mul(g_SpotLightProjViewMatrices[lightIndex], float4(worldSpacePos, 1.0f)); 107 | float3 shadowCoord = worldPosLightClipSpace.xyz / worldPosLightClipSpace.w; 108 | shadowCoord.x = shadowCoord.x * 0.5f + 0.5f; 109 | shadowCoord.y = shadowCoord.y * -0.5f + 0.5f; 110 | 111 | return SpotLightPCFShadowMap(shadowCoord, lightIndex, bias); 112 | } 113 | 114 | -------------------------------------------------------------------------------- /PlaygroundEngine/Assets/Shaders/Skybox.hlsl: -------------------------------------------------------------------------------- 1 | #include "ShaderDefinitions.h" 2 | /////////////////////////////////////////////////////////////////////////// 3 | /////// VERTEX SHADER 4 | /////////////////////////////////////////////////////////////////////////// 5 | 6 | struct VSOut { 7 | float3 rawPosition : POSITION; 8 | float4 pos : SV_Position; 9 | }; 10 | 11 | VSOut VSMain(float3 pos : POSITION) 12 | { 13 | VSOut output; 14 | output.rawPosition = pos; 15 | float3x3 viewWithoutTranslate = (float3x3) g_ViewMatrix; 16 | float4x4 viewMatrix = float4x4(float4(viewWithoutTranslate[0], 0.0f), float4(viewWithoutTranslate[1], 0.0f), 17 | float4(viewWithoutTranslate[2], 0.0f), float4(0.0f, 0.0f, 0.0f, 1.0f)); 18 | float4 transformedPos = mul(g_ProjMatrix, mul(viewMatrix, float4(pos, 1.0f))); 19 | output.pos = transformedPos.xyww; 20 | 21 | return output; 22 | } 23 | 24 | /////////////////////////////////////////////////////////////////////////// 25 | /////// FRAGMENT SHADER 26 | /////////////////////////////////////////////////////////////////////////// 27 | float4 PSMain(VSOut input) : SV_Target 28 | { 29 | float4 color = g_SkyboxTexture.Sample(g_LinearWrapSampler, input.rawPosition); 30 | return color; 31 | } -------------------------------------------------------------------------------- /PlaygroundEngine/Core.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #pragma warning(disable:4251) // std libraries dll interface warning. We use same compiler and same configuration for the dll and application. 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define PG_ASSERT(x, string) { if(!(x)) { printf("Assertion Failed: %s\n", string); __debugbreak(); } } 11 | 12 | #define SAFE_DELETE(p) { if(p) { delete p; p = nullptr; } } 13 | #define SAFE_RELEASE(p) { if(p) { p->Release(); p = nullptr; } } 14 | 15 | #define BIT(x) (1u << (x)) 16 | 17 | #ifdef PLATFORM_WINDOWS 18 | #define DLL_EXPORT __declspec(dllexport) 19 | #define DLL_IMPORT __declspec(dllimport) 20 | #ifdef _WINDLL 21 | #define PG_API DLL_IMPORT 22 | #else 23 | #define PG_API DLL_EXPORT 24 | #endif 25 | #endif 26 | 27 | #define PG_DEBUG_GPU_DEVICE 1 28 | 29 | // Simple stupid hash function 30 | static size_t Hash(const uint8_t* data, size_t size) { 31 | std::hash hasher; 32 | size_t hash = 0; 33 | for (size_t i = 0; i < size; ++i) { 34 | hash += hasher(*(data + i)) | *(data + i); 35 | } 36 | 37 | return hash; 38 | } 39 | 40 | struct SystemInitArguments { 41 | const char* executablePath; 42 | const char* gameLibraryPath; 43 | }; 44 | 45 | -------------------------------------------------------------------------------- /PlaygroundEngine/Events/PGEvent.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../Core.h" 4 | #include 5 | 6 | enum SystemEvent { 7 | INITIALIZE, 8 | // Trigger resize event when window resized 9 | // param1 = client width, param2 = client height 10 | RESIZE, 11 | CLOSE, 12 | }; 13 | 14 | class PG_API ISystemEventListener { 15 | public: 16 | virtual ~ISystemEventListener() = default; 17 | virtual void OnSystemEvent(SystemEvent event, uint64_t param1, uint64_t param2) = 0; 18 | }; 19 | -------------------------------------------------------------------------------- /PlaygroundEngine/Events/PGSystemEventDispatcher.cpp: -------------------------------------------------------------------------------- 1 | #include "PGSystemEventDispatcher.h" 2 | 3 | PGSystemEventDispatcher::PGSystemEventDispatcher() { 4 | 5 | } 6 | 7 | void PGSystemEventDispatcher::RegisterListener(ISystemEventListener* listener) { 8 | m_listeners.insert(listener); 9 | } 10 | 11 | void PGSystemEventDispatcher::RemoveListener(ISystemEventListener* listener) { 12 | m_listeners.erase(listener); 13 | } 14 | 15 | void PGSystemEventDispatcher::DispatchSystemEvent(SystemEvent event, uint64_t param1, uint64_t param2) { 16 | for (ISystemEventListener* listener : m_listeners) { 17 | if (listener) { 18 | listener->OnSystemEvent(event, param1, param2); 19 | } 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /PlaygroundEngine/Events/PGSystemEventDispatcher.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PGEvent.h" 4 | #include 5 | 6 | class PG_API PGSystemEventDispatcher { 7 | 8 | public: 9 | PGSystemEventDispatcher(); 10 | virtual ~PGSystemEventDispatcher() = default; 11 | 12 | void RegisterListener(ISystemEventListener* listener); 13 | void RemoveListener(ISystemEventListener* listener); 14 | void DispatchSystemEvent(SystemEvent event, uint64_t param1 = 0, uint64_t param2 = 0); 15 | 16 | private: 17 | std::set m_listeners; 18 | }; 19 | 20 | -------------------------------------------------------------------------------- /PlaygroundEngine/Imgui/LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-2019 Omar Cornut 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 all 13 | 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 THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /PlaygroundEngine/Imgui/imgui_impl.cpp: -------------------------------------------------------------------------------- 1 | #include "imgui_impl.h" 2 | 3 | #include "../Renderer/DX11/DX11RendererAPI.h" 4 | 5 | PGWindow* ImguiModule::m_Window = nullptr; 6 | 7 | void ImguiModule::Initialize(PGWindow* window, HWRendererAPI* rendererAPI) { 8 | IMGUI_CHECKVERSION(); 9 | ImGui::CreateContext(); 10 | ImGuiIO& io = ImGui::GetIO(); 11 | io.BackendPlatformName = "imgui_impl"; 12 | //io.ImeWindowHandle = window->GetWindowHandle(); 13 | io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; 14 | 15 | ImGuiViewport* main_viewport = ImGui::GetMainViewport(); 16 | main_viewport->PlatformHandle = main_viewport->PlatformHandleRaw = window->GetWindowHandle(); 17 | 18 | // Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array that we will update during the application lifetime. 19 | io.KeyMap[ImGuiKey_Tab] = PGKEY_TAB; 20 | io.KeyMap[ImGuiKey_LeftArrow] = PGKEY_LEFT; 21 | io.KeyMap[ImGuiKey_RightArrow] = PGKEY_RIGHT; 22 | io.KeyMap[ImGuiKey_UpArrow] = PGKEY_UP; 23 | io.KeyMap[ImGuiKey_DownArrow] = PGKEY_DOWN; 24 | io.KeyMap[ImGuiKey_PageUp] = PGKEY_PAGE_UP; 25 | io.KeyMap[ImGuiKey_PageDown] = PGKEY_PAGE_DOWN; 26 | io.KeyMap[ImGuiKey_Home] = PGKEY_HOME; 27 | io.KeyMap[ImGuiKey_End] = PGKEY_END; 28 | io.KeyMap[ImGuiKey_Insert] = PGKEY_INSERT; 29 | io.KeyMap[ImGuiKey_Delete] = PGKEY_DELETE; 30 | io.KeyMap[ImGuiKey_Backspace] = PGKEY_BACKSPACE; 31 | io.KeyMap[ImGuiKey_Space] = PGKEY_SPACE; 32 | io.KeyMap[ImGuiKey_Enter] = PGKEY_ENTER; 33 | io.KeyMap[ImGuiKey_Escape] = PGKEY_ESCAPE; 34 | io.KeyMap[ImGuiKey_KeyPadEnter] = PGKEY_ENTER; 35 | io.KeyMap[ImGuiKey_A] = PGKEY_A; 36 | io.KeyMap[ImGuiKey_C] = PGKEY_C; 37 | io.KeyMap[ImGuiKey_V] = PGKEY_V; 38 | io.KeyMap[ImGuiKey_X] = PGKEY_X; 39 | io.KeyMap[ImGuiKey_Y] = PGKEY_Y; 40 | io.KeyMap[ImGuiKey_Z] = PGKEY_Z; 41 | 42 | ImGui::CreateContext(); 43 | // Setup Dear ImGui style 44 | ImGui::StyleColorsDark(); 45 | 46 | DX11RendererAPI* renderer = (DX11RendererAPI*) rendererAPI; 47 | ImGui_ImplDX11_Init(renderer->GetDX11Device(), renderer->GetDX11DeviceContext()); 48 | 49 | m_Window = window; 50 | } 51 | 52 | ImguiModule::~ImguiModule() { 53 | ImGui_ImplDX11_Shutdown(); 54 | ImGui::DestroyContext(); 55 | } 56 | 57 | void ImguiModule::Begin(float deltaTime) { 58 | // Start the Dear ImGui frame 59 | ImGui_ImplDX11_NewFrame(); 60 | 61 | ImGuiIO& io = ImGui::GetIO(); 62 | IM_ASSERT(io.Fonts->IsBuilt() && "Font atlas not built! It is generally built by the renderer back-end. Missing call to renderer _NewFrame() function? e.g. ImGui_ImplOpenGL3_NewFrame()."); 63 | 64 | // Setup display size (every frame to accommodate for window resizing) 65 | Vector2 clientSize = m_Window->GetClientSize(); 66 | io.DisplaySize = ImVec2(clientSize.x, clientSize.y); 67 | 68 | io.DeltaTime = deltaTime; 69 | 70 | // Read keyboard modifiers inputs 71 | io.KeyCtrl = PGInput::IsKeyPressed(PGKEY_LEFT_CONTROL) || PGInput::IsKeyPressed(PGKEY_RIGHT_CONTROL); 72 | io.KeyShift = PGInput::IsKeyPressed(PGKEY_LEFT_SHIFT) || PGInput::IsKeyPressed(PGKEY_RIGHT_SHIFT); 73 | io.KeyAlt = PGInput::IsKeyPressed(PGKEY_LEFT_ALT) || PGInput::IsKeyPressed(PGKEY_RIGHT_ALT); 74 | io.KeySuper = PGInput::IsKeyPressed(PGKEY_LEFT_SYSTEM) || PGInput::IsKeyPressed(PGKEY_RIGHT_SYSTEM); 75 | 76 | for (uint32_t i = 0; i < 256; ++i) { 77 | io.KeysDown[i] = PGInput::IsKeyPressed(i); 78 | } 79 | for (uint32_t i = 0; i < 3; ++i) { 80 | io.MouseDown[i] = PGInput::IsMouseButtonPressed(i); 81 | } 82 | 83 | // Update OS mouse position 84 | Vector2 mousePos = PGInput::GetMousePos(); 85 | io.MousePos = ImVec2(mousePos.x, mousePos.y); 86 | 87 | ImGui::NewFrame(); 88 | } 89 | 90 | void ImguiModule::Render() { 91 | // Rendering 92 | ImGui::Render(); 93 | ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); 94 | } 95 | 96 | -------------------------------------------------------------------------------- /PlaygroundEngine/Imgui/imgui_impl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "imgui.h" 4 | // We will use imgui_dx11 implementation for now. 5 | // TODO: We should implement with our own graphics API. 6 | #include "imgui_impl_dx11.h" 7 | #include "../Platform/PGWindow.h" 8 | #include "../Platform/PGInput.h" 9 | #include "../Renderer/HWRendererAPI.h" 10 | 11 | class IMGUI_IMPL_API ImguiModule { 12 | public: 13 | ~ImguiModule(); 14 | 15 | static void Initialize(PGWindow* window, HWRendererAPI* rendererAPI); 16 | static void Begin(float deltaTime); 17 | static void Render(); 18 | 19 | private: 20 | static PGWindow* m_Window; 21 | 22 | ImguiModule(); 23 | }; 24 | 25 | -------------------------------------------------------------------------------- /PlaygroundEngine/Imgui/imgui_impl_dx11.h: -------------------------------------------------------------------------------- 1 | // dear imgui: Renderer for DirectX11 2 | // This needs to be used along with a Platform Binding (e.g. Win32) 3 | 4 | // Implemented features: 5 | // [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! 6 | // [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. 7 | // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. 8 | 9 | // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. 10 | // If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp. 11 | // https://github.com/ocornut/imgui 12 | 13 | #pragma once 14 | 15 | struct ID3D11Device; 16 | struct ID3D11DeviceContext; 17 | 18 | IMGUI_IMPL_API bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context); 19 | IMGUI_IMPL_API void ImGui_ImplDX11_Shutdown(); 20 | IMGUI_IMPL_API void ImGui_ImplDX11_NewFrame(); 21 | IMGUI_IMPL_API void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data); 22 | 23 | // Use if you want to reset your rendering device without losing ImGui state. 24 | IMGUI_IMPL_API void ImGui_ImplDX11_InvalidateDeviceObjects(); 25 | IMGUI_IMPL_API bool ImGui_ImplDX11_CreateDeviceObjects(); 26 | -------------------------------------------------------------------------------- /PlaygroundEngine/Main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "PGSystem.h" 4 | #include "PGApplication.h" 5 | 6 | extern "C" { 7 | _declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; 8 | } 9 | 10 | int main(int argc, char** argv) 11 | { 12 | SystemInitArguments initArguments = {}; 13 | initArguments.executablePath = argv[0]; 14 | initArguments.gameLibraryPath = argv[1]; 15 | 16 | PGSystem system = PGSystem(); 17 | system.InitializeSystem(&initArguments); 18 | 19 | system.RunMainLoop(); 20 | 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /PlaygroundEngine/Math/math_util.h: -------------------------------------------------------------------------------- 1 | #ifndef _MATH_H_ 2 | #define _MATH_H_ 3 | 4 | #include 5 | #include 6 | #include "math_vector.h" 7 | #include "math_matrix.h" 8 | 9 | #define U32Max ((uint32_t)-1) 10 | #define F32Max FLT_MAX 11 | 12 | #define PI 3.141592654f 13 | #define TWOPI 6.283185307f 14 | #define IVVPI 0.318309886f 15 | #define INV2PI 0.159154943f 16 | #define PIDIV2 1.570796327f 17 | #define PIDIV4 0.785398163f 18 | 19 | inline float toRadians(float x) { 20 | return x * PI / 180.0f; 21 | } 22 | 23 | inline float Clamp(float low, float value, float high) { 24 | if (value < low) { 25 | return low; 26 | } else if (value > high) { 27 | return high; 28 | } else { 29 | return value; 30 | } 31 | } 32 | 33 | inline Vector3 Lerp(Vector3 left, float factor, Vector3 right) { 34 | return left * (1.0f - factor) + right * factor; 35 | } 36 | 37 | inline Vector4 Lerp(Vector4 left, float factor, Vector4 right) { 38 | return left * (1.0f - factor) + right * factor; 39 | } 40 | 41 | // The state must be initialized to non-zero value 42 | inline uint32_t XOrShift32(uint32_t *state) 43 | { 44 | // https://en.wikipedia.org/wiki/Xorshift 45 | uint32_t x = *state; 46 | x ^= x << 13; 47 | x ^= x >> 17; 48 | x ^= x << 5; 49 | *state = x; 50 | return x; 51 | } 52 | 53 | inline float RandomUnilateral(uint32_t *state) { 54 | return (float) XOrShift32(state) / (float) U32Max; 55 | } 56 | 57 | inline float RandomBilateral(uint32_t *state) { 58 | return 2.0f * RandomUnilateral(state) - 1.0f; 59 | } 60 | 61 | inline bool Refract(Vector3 incidentVector, Vector3 normal, 62 | float refractiveIndex, Vector3* refractionDirection) { 63 | // Clamp cos value for avoiding any NaN errors; 64 | float cosIncidentAngle = Clamp(-1.0f, DotProduct(incidentVector, normal), 1.0f); 65 | Vector3 hitNormal = normal; 66 | float refractiveIndexRatio; 67 | // NOTE: we assume incident ray comes from the air which has refraction index equals 1. 68 | if (cosIncidentAngle < 0.0f) { 69 | // We are coming from outside the surface 70 | cosIncidentAngle = -cosIncidentAngle; 71 | refractiveIndexRatio = 1.0f / refractiveIndex; 72 | } else { 73 | hitNormal = -normal; 74 | refractiveIndexRatio = refractiveIndex; // / 1.0f 75 | } 76 | 77 | float discriminant = 1 - refractiveIndexRatio * refractiveIndexRatio * 78 | (1 - cosIncidentAngle * cosIncidentAngle); 79 | // If discriminant lower than 0 we cannot refract. 80 | // This is called total internal reflection. 81 | if (discriminant < 0) { 82 | return false; 83 | } else { 84 | *refractionDirection = incidentVector * refractiveIndexRatio + hitNormal * 85 | (refractiveIndexRatio * cosIncidentAngle - sqrtf(discriminant)); 86 | return true; 87 | } 88 | } 89 | 90 | inline float Schlick(Vector3 incidentVector, Vector3 normal, 91 | float refractiveIndex) { 92 | float cosIncidentAngle = Clamp(-1.0f, DotProduct(incidentVector, normal), 1.0f); 93 | float cosine; 94 | if (cosIncidentAngle > 0) { 95 | cosine = cosIncidentAngle; 96 | } else { 97 | cosine = -cosIncidentAngle; 98 | } 99 | float r0 = (1 - refractiveIndex) / (1 + refractiveIndex); 100 | r0 = r0 * r0; 101 | return r0 + (1 - r0) * powf((1 - cosine), 5); 102 | } 103 | 104 | inline uint32_t RGBPackToUInt32(Vector3 color) { 105 | return (255 << 24 | 106 | (int32_t) (255 * color.x) << 16 | 107 | (int32_t) (255 * color.y) << 8 | 108 | (int32_t) (255 * color.z) << 0); 109 | } 110 | 111 | inline float LinearTosRGB(float value) { 112 | value = Clamp(0.0f, value, 1.0f); 113 | 114 | float result = value * 12.92f; 115 | if (value >= 0.0031308f) { 116 | result = (1.055f * powf(value, 1.0f / 2.4f)) - 0.055f; 117 | } 118 | 119 | return result; 120 | } 121 | 122 | inline uint32_t RGBPackToUInt32WithGamma2(Vector3 color) { 123 | return (255 << 24 | 124 | (int32_t) (255 * sqrtf(color.x)) << 16 | 125 | (int32_t) (255 * sqrtf(color.y)) << 8 | 126 | (int32_t) (255 * sqrtf(color.z)) << 0); 127 | } 128 | 129 | inline uint32_t RGBPackToUInt32WithsRGB(Vector3 color) { 130 | return (255 << 24 | 131 | (int32_t)(255 * LinearTosRGB(color.x)) << 16 | 132 | (int32_t)(255 * LinearTosRGB(color.y)) << 8 | 133 | (int32_t)(255 * LinearTosRGB(color.z)) << 0); 134 | } 135 | 136 | #endif 137 | -------------------------------------------------------------------------------- /PlaygroundEngine/Math/simd_avx2.h: -------------------------------------------------------------------------------- 1 | #ifndef _SIMD_AVX2_H_ 2 | #define _SIMD_AVX2_H_ 3 | 4 | struct LaneF32 { 5 | __m256 m; 6 | 7 | LaneF32(); 8 | LaneF32(float value); 9 | LaneF32(const float* value); 10 | LaneF32(const LaneF32& copy); 11 | }; 12 | 13 | inline LaneF32::LaneF32() { 14 | 15 | }; 16 | 17 | inline LaneF32::LaneF32(float value) { 18 | this->m = _mm256_set1_ps(value); 19 | }; 20 | 21 | inline LaneF32::LaneF32(const float* value) { 22 | this->m = _mm256_load_ps(value); 23 | }; 24 | 25 | inline LaneF32::LaneF32(const LaneF32& copy) { 26 | this->m = copy.m; 27 | }; 28 | 29 | inline LaneF32 operator-(const LaneF32 left, const LaneF32 right) { 30 | LaneF32 result; 31 | result.m = _mm256_sub_ps(left.m, right.m); 32 | 33 | return result; 34 | }; 35 | 36 | inline LaneF32 operator+(const LaneF32 left, const LaneF32 right) { 37 | LaneF32 result; 38 | result.m = _mm256_add_ps(left.m, right.m); 39 | 40 | return result; 41 | }; 42 | 43 | inline LaneF32 operator*(const LaneF32 left, const LaneF32 right) { 44 | LaneF32 result; 45 | result.m = _mm256_mul_ps(left.m, right.m); 46 | 47 | return result; 48 | }; 49 | 50 | inline LaneF32 operator/(const LaneF32 left, const LaneF32 right) { 51 | LaneF32 result; 52 | result.m = _mm256_div_ps(left.m, right.m); 53 | 54 | return result; 55 | }; 56 | 57 | inline LaneF32 operator>(const LaneF32 left, const LaneF32 right) { 58 | LaneF32 result; 59 | result.m = _mm256_cmp_ps(left.m, right.m, _CMP_GT_OQ); 60 | 61 | return result; 62 | }; 63 | 64 | inline LaneF32 operator<(const LaneF32 left, const LaneF32 right) { 65 | LaneF32 result; 66 | result.m = _mm256_cmp_ps(left.m, right.m, _CMP_LT_OQ); 67 | 68 | return result; 69 | }; 70 | 71 | inline LaneF32 operator<=(const LaneF32 left, const LaneF32 right) { 72 | LaneF32 result; 73 | result.m = _mm256_cmp_ps(left.m, right.m, _CMP_LE_OQ); 74 | 75 | return result; 76 | } 77 | 78 | inline LaneF32 operator>=(const LaneF32 left, const LaneF32 right) { 79 | LaneF32 result; 80 | result.m = _mm256_cmp_ps(left.m, right.m, _CMP_GE_OQ); 81 | 82 | return result; 83 | } 84 | 85 | inline LaneF32 operator|(const LaneF32 left, const LaneF32 right) { 86 | LaneF32 result; 87 | result.m = _mm256_or_ps(left.m, right.m); 88 | 89 | return result; 90 | }; 91 | 92 | inline LaneF32 operator&(const LaneF32 left, const LaneF32 right) { 93 | LaneF32 result; 94 | result.m = _mm256_and_ps(left.m, right.m); 95 | 96 | return result; 97 | }; 98 | 99 | inline LaneF32 operator-(const LaneF32 value) { 100 | LaneF32 result; 101 | result.m = _mm256_xor_ps(value.m, _mm256_set1_ps(-0.0f)); 102 | 103 | return result; 104 | }; 105 | 106 | inline LaneF32 FMulAdd(const LaneF32 left, const LaneF32 right, const LaneF32 addend) { 107 | LaneF32 result; 108 | #ifdef __FMA__ 109 | result.m = _mm256_fmadd_ps(left.m, right.m, addend.m); 110 | #else 111 | result = (left * right) + addend; 112 | #endif 113 | 114 | return result; 115 | }; 116 | 117 | inline LaneF32 FMulSub(const LaneF32 left, const LaneF32 right, const LaneF32 sub) { 118 | LaneF32 result; 119 | #ifdef __FMA__ 120 | result.m = _mm256_fmsub_ps(left.m, right.m, sub.m); 121 | #else 122 | result = (left * right) - sub; 123 | #endif 124 | 125 | return result; 126 | }; 127 | 128 | inline void StoreLane(float* dest, LaneF32 lane) { 129 | _mm256_store_ps(dest, lane.m); 130 | }; 131 | 132 | inline LaneF32 SquareRoot(LaneF32 value) { 133 | LaneF32 result; 134 | result.m = _mm256_sqrt_ps(value.m); 135 | 136 | return result; 137 | }; 138 | 139 | inline LaneF32 RSquareRoot(LaneF32 value) { 140 | LaneF32 result; 141 | result.m = _mm256_rsqrt_ps(value.m); 142 | 143 | return result; 144 | }; 145 | 146 | inline bool MaskIsZeroed(LaneF32 mask) { 147 | bool result = _mm256_movemask_ps(mask.m) == 0; 148 | 149 | return result; 150 | }; 151 | 152 | inline void Select(LaneF32* dest, LaneF32 mask, LaneF32 right) { 153 | dest->m = _mm256_blendv_ps(dest->m, right.m, mask.m); 154 | }; 155 | 156 | #endif -------------------------------------------------------------------------------- /PlaygroundEngine/Math/simd_sse.h: -------------------------------------------------------------------------------- 1 | #ifndef _SIMD_SSE_H_ 2 | #define _SIMD_SSE_H_ 3 | 4 | struct LaneF32 { 5 | __m128 m; 6 | 7 | LaneF32(); 8 | LaneF32(float value); 9 | LaneF32(const float* value); 10 | LaneF32(const LaneF32& copy); 11 | }; 12 | 13 | inline LaneF32::LaneF32() { 14 | 15 | }; 16 | 17 | inline LaneF32::LaneF32(float value) { 18 | this->m = _mm_set_ps1(value); 19 | }; 20 | 21 | inline LaneF32::LaneF32(const float* value) { 22 | this->m = _mm_load_ps(value); 23 | }; 24 | 25 | inline LaneF32::LaneF32(const LaneF32& copy) { 26 | this->m = copy.m; 27 | }; 28 | 29 | inline LaneF32 operator-(const LaneF32 left, const LaneF32 right) { 30 | LaneF32 result; 31 | result.m = _mm_sub_ps(left.m, right.m); 32 | 33 | return result; 34 | }; 35 | 36 | inline LaneF32 operator+(const LaneF32 left, const LaneF32 right) { 37 | LaneF32 result; 38 | result.m = _mm_add_ps(left.m, right.m); 39 | 40 | return result; 41 | }; 42 | 43 | inline LaneF32 operator*(const LaneF32 left, const LaneF32 right) { 44 | LaneF32 result; 45 | result.m = _mm_mul_ps(left.m, right.m); 46 | 47 | return result; 48 | }; 49 | 50 | inline LaneF32 operator/(const LaneF32 left, const LaneF32 right) { 51 | LaneF32 result; 52 | result.m = _mm_div_ps(left.m, right.m); 53 | 54 | return result; 55 | }; 56 | 57 | inline LaneF32 operator>(const LaneF32 left, const LaneF32 right) { 58 | LaneF32 result; 59 | result.m = _mm_cmpgt_ps(left.m, right.m); 60 | 61 | return result; 62 | }; 63 | 64 | inline LaneF32 operator<(const LaneF32 left, const LaneF32 right) { 65 | LaneF32 result; 66 | result.m = _mm_cmplt_ps(left.m, right.m); 67 | 68 | return result; 69 | }; 70 | 71 | inline LaneF32 operator<=(const LaneF32 left, const LaneF32 right) { 72 | LaneF32 result; 73 | result.m = _mm_cmple_ps(left.m, right.m); 74 | 75 | return result; 76 | } 77 | 78 | inline LaneF32 operator>=(const LaneF32 left, const LaneF32 right) { 79 | LaneF32 result; 80 | result.m = _mm_cmpge_ps(left.m, right.m); 81 | 82 | return result; 83 | } 84 | 85 | inline LaneF32 operator|(const LaneF32 left, const LaneF32 right) { 86 | LaneF32 result; 87 | result.m = _mm_or_ps(left.m, right.m); 88 | 89 | return result; 90 | }; 91 | 92 | inline LaneF32 operator&(const LaneF32 left, const LaneF32 right) { 93 | LaneF32 result; 94 | result.m = _mm_and_ps(left.m, right.m); 95 | 96 | return result; 97 | }; 98 | 99 | inline LaneF32 operator-(const LaneF32 value) { 100 | LaneF32 result; 101 | result.m = _mm_xor_ps(value.m, _mm_set1_ps(-0.0f)); 102 | 103 | return result; 104 | }; 105 | 106 | inline LaneF32 FMulAdd(const LaneF32 left, const LaneF32 right, const LaneF32 addend) { 107 | LaneF32 result; 108 | #ifdef __FMA__ 109 | result.m = _mm_fmadd_ps(left.m, right.m, addend.m); 110 | #else 111 | result = (left * right) + addend; 112 | #endif 113 | return result; 114 | }; 115 | 116 | inline LaneF32 FMulSub(const LaneF32 left, const LaneF32 right, const LaneF32 sub) { 117 | LaneF32 result; 118 | #ifdef __FMA__ 119 | result.m = _mm_fmsub_ps(left.m, right.m, sub.m); 120 | #else 121 | result = (left * right) - sub; 122 | #endif 123 | 124 | return result; 125 | }; 126 | 127 | inline void StoreLane(float* dest, LaneF32 lane) { 128 | _mm_store_ps(dest, lane.m); 129 | }; 130 | 131 | inline LaneF32 SquareRoot(LaneF32 value) { 132 | LaneF32 result; 133 | result.m = _mm_sqrt_ps(value.m); 134 | 135 | return result; 136 | }; 137 | 138 | inline LaneF32 RSquareRoot(LaneF32 value) { 139 | LaneF32 result; 140 | result.m = _mm_rsqrt_ps(value.m); 141 | 142 | return result; 143 | }; 144 | 145 | inline bool MaskIsZeroed(LaneF32 mask) { 146 | bool result = _mm_movemask_ps(mask.m) == 0; 147 | 148 | return result; 149 | }; 150 | 151 | inline void Select(LaneF32* dest, LaneF32 mask, LaneF32 right) { 152 | dest->m = _mm_blendv_ps(dest->m, right.m, mask.m); 153 | }; 154 | 155 | #endif -------------------------------------------------------------------------------- /PlaygroundEngine/Mesh.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Math/math_util.h" 4 | #include "Renderer/Material.h" 5 | #include "Transform.h" 6 | 7 | #include "Renderer/HWRendererAPI.h" 8 | 9 | #include 10 | #include 11 | 12 | struct Vertex_POS { 13 | Vector3 position; 14 | }; 15 | 16 | struct Vertex_NOR { 17 | Vector3 normal; 18 | }; 19 | 20 | struct Vertex_TEXCOORD { 21 | Vector2 texCoord; 22 | }; 23 | 24 | enum VertexBuffers : uint8_t { 25 | VERTEX_BUFFER_POSITIONS, 26 | VERTEX_BUFFER_NORMAL, 27 | VERTEX_BUFFER_TEXCOORD, 28 | VERTEX_BUFFER_TANGENT, 29 | 30 | VERTEX_BUFFER_COUNT 31 | }; 32 | 33 | struct Box { 34 | Vector3 min; 35 | Vector3 max; 36 | }; 37 | 38 | struct SubMesh { 39 | // TODO: Instead of storing raw pointers we should have handles for buffers. Because this is not a safe struct to copy. 40 | // If one of the copies get deleted, other's buffers will be invalidated. 41 | HWBuffer* vertexBuffers[VertexBuffers::VERTEX_BUFFER_COUNT] = {0}; 42 | uint32_t vertexStrides[VertexBuffers::VERTEX_BUFFER_COUNT] = {0}; 43 | uint32_t vertexOffsets[VertexBuffers::VERTEX_BUFFER_COUNT] = {0}; 44 | 45 | 46 | HWBuffer* indexBuffer = nullptr; 47 | uint32_t indexBufferStride = 0; 48 | uint32_t indexBufferOffset = 0; 49 | 50 | uint32_t indexStart = 0; 51 | uint32_t indexCount = 0; 52 | 53 | // Not included in hash 54 | Material* material = nullptr; 55 | Box boundingBox; 56 | 57 | size_t GetGeometryHash() { 58 | size_t materialOffset = offsetof(SubMesh, material); 59 | size_t hash = Hash(((const uint8_t*) this), materialOffset); 60 | 61 | return hash; 62 | } 63 | 64 | ~SubMesh() { 65 | for (size_t i = 0; i < VertexBuffers::VERTEX_BUFFER_COUNT; ++i) { 66 | SAFE_DELETE(vertexBuffers[i]); 67 | } 68 | SAFE_DELETE(indexBuffer); 69 | } 70 | }; 71 | 72 | struct Mesh { 73 | std::string name; 74 | std::vector submeshes; 75 | }; 76 | 77 | typedef Mesh* MeshRef; 78 | 79 | -------------------------------------------------------------------------------- /PlaygroundEngine/MeshUtils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Mesh.h" 4 | #include "Scene.h" 5 | #include "Renderer/Material.h" 6 | 7 | #include "Core.h" 8 | #include "PGLog.h" 9 | 10 | #include "PGResouceManager.h" 11 | 12 | PG_API void LoadScene(HWRendererAPI* rendererAPI, PGScene* scene, Material* defaultMaterial, const std::string& filename); 13 | PG_API void LoadSceneFromGLTFFile(HWRendererAPI* rendererAPI, PGScene* scene, Material* defaultMaterial, const std::string& filename, bool leftHandedNormalMap); 14 | PG_API void CreateQuad(HWRendererAPI* rendererAPI, PGSceneObject* outSceneObject, Material* defaultMaterial, Vector2 leftBottom, Vector2 rightTop, float zVal); 15 | -------------------------------------------------------------------------------- /PlaygroundEngine/PGApplication.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Events/PGEvent.h" 4 | 5 | class IApplication : public ISystemEventListener { 6 | public: 7 | virtual ~IApplication() = default; 8 | 9 | virtual void OnSystemEvent(SystemEvent event, uint64_t param1, uint64_t param2) = 0; 10 | 11 | virtual void OnInit() = 0; 12 | virtual void OnUpdate(float deltaTime) = 0; 13 | virtual void OnUIRender() = 0; 14 | virtual void OnExit() = 0; 15 | }; 16 | 17 | -------------------------------------------------------------------------------- /PlaygroundEngine/PGCamera.cpp: -------------------------------------------------------------------------------- 1 | #include "PGCamera.h" 2 | 3 | 4 | PGCamera::PGCamera() 5 | : m_Position(0.0f, 3.0f, -10.0f) 6 | { 7 | 8 | } 9 | 10 | void PGCamera::SetFrustum(uint32_t imageWidth, uint32_t imageHeight, float nearPlaneDistance, float farPlaneDistance, float fovRadians) { 11 | m_ProjectionMatrix = PerspectiveMatrixLH(imageWidth, imageHeight, nearPlaneDistance, farPlaneDistance, fovRadians); 12 | 13 | m_NearPlaneDistance = nearPlaneDistance; 14 | m_FarPlaneDistance = farPlaneDistance; 15 | m_FovRadians = fovRadians; 16 | } 17 | 18 | void PGCamera::SetView(Vector3 cameraPosition, Vector3 targetPoint) { 19 | // Left-handed look-at function 20 | m_ViewMatrix = LookAtLH(cameraPosition, targetPoint, Vector3(0.0f, 1.0f, 0.0f)); 21 | m_Position = cameraPosition; 22 | } 23 | 24 | void PGCamera::UpdateAspectRatio(uint32_t width, uint32_t height) { 25 | m_ProjectionMatrix = PerspectiveMatrixLH(width, height, m_NearPlaneDistance, m_FarPlaneDistance, m_FovRadians); 26 | } 27 | 28 | void PGCamera::TransformCamera(Transform* transform) { 29 | m_Position = transform->position; 30 | 31 | Matrix4 orientation = transform->rotationMatrix; 32 | Vector3 up = (orientation * Vector4(0.0f, 1.0f, 0.0f, 0.0f)).xyz(); 33 | Vector3 target = (orientation * Vector4(0.0f, 0.0f, 1.0f, 0.0f)).xyz(); 34 | 35 | Vector3 lookAtTarget = m_Position + target; 36 | m_ViewMatrix = LookAtLH(m_Position, lookAtTarget, up); 37 | } 38 | 39 | 40 | -------------------------------------------------------------------------------- /PlaygroundEngine/PGCamera.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Core.h" 4 | #include "Transform.h" 5 | #include "Math/math_util.h" 6 | 7 | class PG_API PGCamera { 8 | public: 9 | PGCamera(); 10 | ~PGCamera() = default; 11 | 12 | void SetFrustum(uint32_t imageWidth, uint32_t imageHeight, float nearPlaneDistance, float farPlaneDistance, float fovRadians); 13 | void SetView(Vector3 cameraPosition, Vector3 targetPoint); 14 | 15 | void UpdateAspectRatio(uint32_t width, uint32_t height); 16 | void TransformCamera(Transform* transform); 17 | 18 | inline Vector3 GetPosition() { 19 | return m_Position; 20 | } 21 | 22 | inline Matrix4 GetProjectionMatrix() { 23 | return m_ProjectionMatrix; 24 | } 25 | 26 | inline Matrix4 GetViewMatrix() { 27 | return m_ViewMatrix; 28 | } 29 | 30 | inline Matrix4 GetProjectionViewMatrix() { 31 | return m_ProjectionMatrix * m_ViewMatrix; 32 | } 33 | 34 | inline Matrix4 GetInverseProjectionViewMatrix() { 35 | Matrix4 projectionViewMatrix = GetProjectionViewMatrix(); 36 | return Inverse(projectionViewMatrix); 37 | } 38 | private: 39 | Matrix4 m_ProjectionMatrix; 40 | Matrix4 m_ViewMatrix; 41 | 42 | Vector3 m_Position; 43 | 44 | float m_NearPlaneDistance = 0.1f; 45 | float m_FarPlaneDistance = 100.0f; 46 | float m_FovRadians = (PI / 4.0f); 47 | }; 48 | 49 | -------------------------------------------------------------------------------- /PlaygroundEngine/PGGameApplication.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Core.h" 4 | #include "PGApplication.h" 5 | #include "PGSystem.h" 6 | 7 | typedef IApplication* (*GameApplicationProc)(PGSystem* system); 8 | #define REGISTER_GAME_APPLICATION(classname) extern "C" DLL_EXPORT IApplication* GetGameApplication(PGSystem* system) { return new classname(system); } 9 | 10 | 11 | -------------------------------------------------------------------------------- /PlaygroundEngine/PGLog.cpp: -------------------------------------------------------------------------------- 1 | #include "PGLog.h" 2 | 3 | #include 4 | 5 | LogList PGLog::m_LogList = LogList(); 6 | 7 | PGLog::PGLog() { 8 | 9 | } 10 | 11 | void PGLog::Log(LogType type, const char* fmt, ...) { 12 | const size_t logBufferMaxSize = 1024; 13 | char logBuffer[logBufferMaxSize] = {0}; 14 | 15 | // Get time 16 | time_t rawtime; 17 | tm timeinfo; 18 | time(&rawtime); 19 | localtime_s(&timeinfo, &rawtime); 20 | 21 | // Format [HH:MM:SS] 22 | // TODO: Print milliseconds! 23 | const size_t timeFormatMaxSize = 12; // length of "[HH:MM:SS] \0" 24 | const size_t timeFormatSize = timeFormatMaxSize - 1; // without terminating character 25 | strftime(logBuffer, timeFormatMaxSize, "[%T] ", &timeinfo); 26 | 27 | va_list args; 28 | va_start(args, fmt); 29 | vsnprintf(logBuffer + timeFormatSize, logBufferMaxSize - timeFormatSize, fmt, args); 30 | va_end(args); 31 | 32 | size_t logLength = strlen(logBuffer) + 2; // Length of the log text plus new line and termination character 33 | if (logBuffer[logLength - 3] != '\n') { 34 | logBuffer[logLength - 2] = '\n'; 35 | } 36 | char* logData = (char*) malloc(logLength); 37 | memcpy((void*) logData, (const void*) logBuffer, logLength); 38 | 39 | // Print log to stdout 40 | printf(logData); 41 | 42 | LogItem logItem; 43 | logItem.type = type; 44 | logItem.logData = (const char*) logData; 45 | 46 | m_LogList.push_back(logItem); 47 | } 48 | 49 | void PGLog::ClearLogList() { 50 | for (LogItem item : m_LogList) { 51 | free((void*) item.logData); 52 | } 53 | m_LogList.clear(); 54 | } 55 | 56 | -------------------------------------------------------------------------------- /PlaygroundEngine/PGLog.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Core.h" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | enum LogType { 10 | LOG_DEBUG, 11 | LOG_WARNING, 12 | LOG_ERROR 13 | }; 14 | 15 | struct LogItem { 16 | LogType type; 17 | const char* logData; 18 | }; 19 | 20 | typedef std::vector LogList; 21 | 22 | class PG_API PGLog { 23 | public: 24 | static void Log(LogType type, const char* fmt, ...); 25 | 26 | static void ClearLogList(); 27 | static const LogList& GetLogList() { return m_LogList; }; 28 | 29 | private: 30 | PGLog(); 31 | 32 | static LogList m_LogList; 33 | }; 34 | 35 | #define PG_LOG_DEBUG(...) PGLog::Log(LogType::LOG_DEBUG, __VA_ARGS__) 36 | #define PG_LOG_WARNING(...) PGLog::Log(LogType::LOG_WARNING, __VA_ARGS__) 37 | #define PG_LOG_ERROR(...) PGLog::Log(LogType::LOG_ERROR, __VA_ARGS__) 38 | 39 | 40 | -------------------------------------------------------------------------------- /PlaygroundEngine/PGProfiler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Core.h" 4 | #include "Renderer/HWRendererAPI.h" 5 | 6 | #include 7 | #include 8 | 9 | struct ProfileData { 10 | std::string name; 11 | uint64_t startNanoSeconds; 12 | uint64_t durationNanoSeconds; 13 | }; 14 | 15 | inline bool operator==(const ProfileData& left, const ProfileData& right) { 16 | return left.name == right.name; 17 | } 18 | 19 | typedef std::vector ProfileList; 20 | 21 | class PG_API PGProfileTimer { 22 | public: 23 | PGProfileTimer(const char* name); 24 | ~PGProfileTimer(); 25 | void Stop(); 26 | 27 | // public members 28 | const char* name; 29 | uint64_t startNanoSeconds; 30 | bool isStopped; 31 | 32 | static ProfileList s_ProfileResults; 33 | }; 34 | 35 | #define PG_PROFILE(name, line) PGProfileTimer timer##line(name); 36 | // Need some extra layer of indirection for concatenating a line number instead of "__LINE__" string 37 | // https://stackoverflow.com/a/1597129 38 | #define PG_PROFILE2(name, line) PG_PROFILE(name, line) 39 | #define PG_PROFILE_SCOPE(name) PG_PROFILE2(name, __LINE__) 40 | #define PG_PROFILE_FUNCTION() PG_PROFILE_SCOPE(__FUNCTION__) 41 | 42 | #define GPU_PROFILER_FRAME_LATENCY 4 43 | #define GPU_PROFILER_MAX_QUERY_COUNT 20 44 | 45 | class PG_API PGGPUProfilerTimer { 46 | public: 47 | PGGPUProfilerTimer(HWRendererAPI* rendererAPI, const char* name); 48 | ~PGGPUProfilerTimer(); 49 | void Stop(HWRendererAPI* rendererAPI, const char* name); 50 | 51 | // public members 52 | const char* name; 53 | HWRendererAPI* rendererAPI; 54 | bool isStopped; 55 | 56 | // Static members 57 | public: 58 | static void BeginFrame(HWRendererAPI* rendererAPI); 59 | static void EndFrame(HWRendererAPI* rendererAPI); 60 | 61 | static void Initialize(HWRendererAPI* rendererAPI); 62 | static void Destroy(); 63 | 64 | static void GetProfileList(HWRendererAPI* rendererAPI, ProfileList& outProfileList); 65 | 66 | private: 67 | static std::unordered_map s_ProfileEntries; 68 | 69 | static bool s_FirstPass; 70 | static size_t s_CurrentFrameIndex; 71 | static size_t s_FreeQueryIndex; 72 | static HWQuery* s_TimestampDisjointQueries[GPU_PROFILER_FRAME_LATENCY]; 73 | 74 | static HWQuery* s_StartQueries[GPU_PROFILER_MAX_QUERY_COUNT][GPU_PROFILER_FRAME_LATENCY]; 75 | static HWQuery* s_EndQueries[GPU_PROFILER_MAX_QUERY_COUNT][GPU_PROFILER_FRAME_LATENCY]; 76 | }; 77 | 78 | #define PG_GPU_PROFILE(pRendererAPI, name, line) PGGPUProfilerTimer gputimer##line(pRendererAPI, name); 79 | // Need some extra layer of indirection for concatenating a line number instead of "__LINE__" string 80 | // https://stackoverflow.com/a/1597129 81 | #define PG_GPU_PROFILE2(pRendererAPI, name, line) PG_GPU_PROFILE(pRendererAPI, name, line) 82 | #define PG_GPU_PROFILE_SCOPE(pRendererAPI, name) PG_GPU_PROFILE2(pRendererAPI, name, __LINE__) 83 | #define PG_GPU_PROFILE_FUNCTION(pRendererAPI) PG_GPU_PROFILE_SCOPE(pRendererAPI, __FUNCTION__) 84 | 85 | -------------------------------------------------------------------------------- /PlaygroundEngine/PGResouceManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Core.h" 4 | #include "PGResource.h" 5 | 6 | #include 7 | #include 8 | 9 | typedef std::unordered_map ResourcePool; 10 | 11 | class PG_API PGResourceManager { 12 | public: 13 | static void ReleaseResourcePool(); 14 | static IResource* CreateResource(const std::string& resourceFilePath, bool generateMips = false); 15 | 16 | private: 17 | PGResourceManager(); 18 | 19 | static ResourcePool s_ResourcePool; 20 | }; 21 | 22 | -------------------------------------------------------------------------------- /PlaygroundEngine/PGResource.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class IResource { 4 | public: 5 | virtual ~IResource() = default; 6 | }; 7 | 8 | -------------------------------------------------------------------------------- /PlaygroundEngine/PGResourceManager.cpp: -------------------------------------------------------------------------------- 1 | #include "PGResouceManager.h" 2 | #include "Renderer/PGTexture.h" 3 | 4 | #include 5 | 6 | ResourcePool PGResourceManager::s_ResourcePool; 7 | 8 | PGResourceManager::PGResourceManager() { 9 | 10 | } 11 | 12 | void PGResourceManager::ReleaseResourcePool() { 13 | for (auto& pair : s_ResourcePool) { 14 | delete pair.second; 15 | } 16 | 17 | s_ResourcePool.clear(); 18 | } 19 | 20 | 21 | IResource* PGResourceManager::CreateResource(const std::string& resourceFilePath, bool generateMips) { 22 | auto searchIndex = s_ResourcePool.find(resourceFilePath); 23 | if (searchIndex != s_ResourcePool.end()) { 24 | return searchIndex->second; 25 | } 26 | 27 | size_t extIndex = resourceFilePath.find_last_of('.') + 1; 28 | size_t extSize = resourceFilePath.size() - extIndex; 29 | std::string_view extension(resourceFilePath.c_str() + extIndex, extSize); 30 | 31 | if (!extension.compare("dds")) { 32 | IResource* pResource = PGTexture::CreateTextureFromDDSFile(resourceFilePath); 33 | s_ResourcePool[resourceFilePath] = pResource; 34 | return pResource; 35 | } else if (!extension.compare("png") || !extension.compare("jpg")) { 36 | IResource* pResource = PGTexture::CreateTexture2D(resourceFilePath, generateMips); 37 | s_ResourcePool[resourceFilePath] = pResource; 38 | return pResource; 39 | } else { 40 | PG_ASSERT(false, "Unhandled resource extension"); 41 | } 42 | 43 | return nullptr; 44 | } 45 | 46 | -------------------------------------------------------------------------------- /PlaygroundEngine/PGSystem.cpp: -------------------------------------------------------------------------------- 1 | #include "PGSystem.h" 2 | #include "Renderer/DX11/DX11RendererAPI.h" 3 | #include "PGGameApplication.h" 4 | #include "Platform/PGTime.h" 5 | #include "PGProfiler.h" 6 | 7 | // Static members 8 | std::shared_ptr PGSystem::s_systemEventDispatcher = std::make_shared(); 9 | 10 | PGSystem::PGSystem() { 11 | s_systemEventDispatcher->RegisterListener(this); 12 | } 13 | 14 | PGSystem::~PGSystem() { 15 | s_systemEventDispatcher->RemoveListener(this); 16 | 17 | delete m_GameApplication; 18 | delete m_GameLibrary; 19 | delete m_Window; 20 | } 21 | 22 | bool PGSystem::InitializeSystem(SystemInitArguments* initArguments) { 23 | 24 | m_GameLibrary = new DLibrary(initArguments->gameLibraryPath); 25 | bool isLoaded = m_GameLibrary->Load(); 26 | PG_ASSERT(isLoaded, "Couldn't load game library"); 27 | 28 | GameApplicationProc GetGameApplication = m_GameLibrary->GetFunctionAddress("GetGameApplication"); 29 | PG_ASSERT(GetGameApplication, "Couldn't get the game application proc"); 30 | m_GameApplication = GetGameApplication(this); 31 | PG_ASSERT(m_GameApplication, "Couldn't get the game application"); 32 | 33 | const char* windowName = "PlaygroundEngine"; 34 | m_Window = new PGWindow(windowName, 1280, 720, s_systemEventDispatcher.get()); 35 | 36 | PGRenderer::Initialize(m_Window); 37 | 38 | s_systemEventDispatcher->DispatchSystemEvent(SystemEvent::INITIALIZE); 39 | m_GameApplication->OnInit(); 40 | 41 | ImguiModule::Initialize(m_Window, PGRenderer::GetRendererAPI()); 42 | return true; 43 | } 44 | 45 | void PGSystem::RunMainLoop() { 46 | m_Window->Show(); 47 | 48 | while (true) { 49 | PG_PROFILE_SCOPE("Frame"); 50 | if (!m_Window->ProcessMessages()) { 51 | // Close requested 52 | s_systemEventDispatcher->DispatchSystemEvent(SystemEvent::CLOSE); 53 | m_GameApplication->OnExit(); 54 | PGResourceManager::ReleaseResourcePool(); 55 | PGRenderer::Destroy(); 56 | break; 57 | } 58 | 59 | static uint64_t lastTime; 60 | uint64_t time = PGTime::GetTimeMacroseconds(); 61 | uint64_t timePast = time - lastTime; 62 | float deltaTime = (float) (timePast / 1000000.0); 63 | lastTime = time; 64 | 65 | PGRenderer::BeginFrame(); 66 | { 67 | PG_PROFILE_SCOPE("Update"); 68 | m_GameApplication->OnUpdate(deltaTime); 69 | } 70 | 71 | { 72 | PG_PROFILE_SCOPE("Render"); 73 | PGRenderer::RenderFrame(); 74 | } 75 | 76 | ImguiModule::Begin(deltaTime); 77 | m_GameApplication->OnUIRender(); 78 | ImguiModule::Render(); 79 | 80 | PGRenderer::EndFrame(); 81 | } 82 | } 83 | 84 | void PGSystem::OnSystemEvent(SystemEvent event, uint64_t param1, uint64_t param2) { 85 | if (event == SystemEvent::RESIZE) { 86 | PGRenderer::ResizeResources(param1, param2); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /PlaygroundEngine/PGSystem.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Core.h" 4 | #include "Events/PGSystemEventDispatcher.h" 5 | #include "Platform/PGWindow.h" 6 | #include "Platform/PGLibrary.h" 7 | #include "Renderer/PGRenderer.h" 8 | #include "Renderer/PGShaderLib.h" 9 | #include "Imgui/imgui_impl.h" 10 | #include "PGApplication.h" 11 | #include "MeshUtils.h" 12 | #include "PGResouceManager.h" 13 | 14 | #include 15 | 16 | class PG_API PGSystem : public ISystemEventListener { 17 | public: 18 | PGSystem(); 19 | ~PGSystem(); 20 | 21 | bool InitializeSystem(SystemInitArguments* initArguments); 22 | void RunMainLoop(); 23 | 24 | virtual void OnSystemEvent(SystemEvent event, uint64_t param1, uint64_t param2) override; 25 | 26 | static std::shared_ptr GetSystemEventDispatcher() { return s_systemEventDispatcher; }; 27 | 28 | inline PGShaderLib* GetShaderLib() { 29 | return PGRenderer::GetShaderLib(); 30 | } 31 | 32 | private: 33 | PGWindow* m_Window; 34 | DLibrary* m_GameLibrary; 35 | IApplication* m_GameApplication; 36 | 37 | static std::shared_ptr s_systemEventDispatcher; 38 | }; 39 | 40 | -------------------------------------------------------------------------------- /PlaygroundEngine/Platform/PGInput.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../Core.h" 4 | #include "../Math/math_util.h" 5 | #include "PGKeycode.h" 6 | 7 | #include 8 | 9 | class PG_API PGInput { 10 | friend class PGWindow; 11 | public: 12 | static bool IsKeyPressed(KeyCode keycode); 13 | static bool IsMouseButtonPressed(KeyCode keycode); 14 | static Vector2 GetMousePos(); 15 | 16 | private: 17 | PGInput(); 18 | 19 | static bool keyPressedState[256]; 20 | static bool mouseButtonPressedState[5]; 21 | }; 22 | 23 | -------------------------------------------------------------------------------- /PlaygroundEngine/Platform/PGKeycode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | typedef int KeyCode; 4 | 5 | #define PGMOUSE_LBUTTON 0 6 | #define PGMOUSE_RBUTTON 1 7 | #define PGMOUSE_MBUTTON 2 8 | 9 | #ifdef PLATFORM_WINDOWS 10 | #include 11 | 12 | #define PGKEY_UNKNOWN -1 13 | 14 | #define PGKEY_NP_0 VK_NUMPAD0 15 | #define PGKEY_NP_1 VK_NUMPAD1 16 | #define PGKEY_NP_2 VK_NUMPAD2 17 | #define PGKEY_NP_3 VK_NUMPAD3 18 | #define PGKEY_NP_4 VK_NUMPAD4 19 | #define PGKEY_NP_5 VK_NUMPAD5 20 | #define PGKEY_NP_6 VK_NUMPAD6 21 | #define PGKEY_NP_7 VK_NUMPAD7 22 | #define PGKEY_NP_8 VK_NUMPAD8 23 | #define PGKEY_NP_9 VK_NUMPAD9 24 | 25 | #define PGKEY_0 48 26 | #define PGKEY_1 49 27 | #define PGKEY_2 50 28 | #define PGKEY_3 51 29 | #define PGKEY_4 52 30 | #define PGKEY_5 53 31 | #define PGKEY_6 54 32 | #define PGKEY_7 55 33 | #define PGKEY_8 56 34 | #define PGKEY_9 57 35 | 36 | #define PGKEY_A 65 37 | #define PGKEY_B 66 38 | #define PGKEY_C 67 39 | #define PGKEY_D 68 40 | #define PGKEY_E 69 41 | #define PGKEY_F 70 42 | #define PGKEY_G 71 43 | #define PGKEY_H 72 44 | #define PGKEY_I 73 45 | #define PGKEY_J 74 46 | #define PGKEY_K 75 47 | #define PGKEY_L 76 48 | #define PGKEY_M 77 49 | #define PGKEY_N 78 50 | #define PGKEY_O 79 51 | #define PGKEY_P 80 52 | #define PGKEY_Q 81 53 | #define PGKEY_R 82 54 | #define PGKEY_S 83 55 | #define PGKEY_T 84 56 | #define PGKEY_U 85 57 | #define PGKEY_V 86 58 | #define PGKEY_W 87 59 | #define PGKEY_X 88 60 | #define PGKEY_Y 89 61 | #define PGKEY_Z 90 62 | 63 | #define PGKEY_SEMICOLON VK_OEM_1 /* ; */ 64 | #define PGKEY_SLASH VK_OEM_2 /* / */ 65 | #define PGKEY_APOSTROPHE VK_OEM_3 /* ` */ 66 | #define PGKEY_LEFT_BRACKET VK_OEM_4 /* [ */ 67 | #define PGKEY_BACKSLASH VK_OEM_5 /* \ */ 68 | #define PGKEY_RIGHT_BRACKET VK_OEM_6 /* ] */ 69 | #define PGKEY_QUOTE VK_OEM_7 /* ' */ 70 | #define PGKEY_COMMA VK_OEM_COMMA /* , */ 71 | #define PGKEY_MINUS VK_OEM_MINUS /* - */ 72 | #define PGKEY_PERIOD VK_OEM_PERIOD /* . */ 73 | #define PGKEY_EQUAL VK_OEM_PLUS /* = */ 74 | 75 | #define PGKEY_SPACE VK_SPACE 76 | #define PGKEY_ESCAPE VK_ESCAPE 77 | #define PGKEY_ENTER VK_RETURN 78 | #define PGKEY_TAB VK_TAB 79 | #define PGKEY_BACKSPACE VK_BACK 80 | #define PGKEY_INSERT VK_INSERT 81 | #define PGKEY_DELETE VK_DELETE 82 | #define PGKEY_RIGHT VK_RIGHT 83 | #define PGKEY_LEFT VK_LEFT 84 | #define PGKEY_DOWN VK_DOWN 85 | #define PGKEY_UP VK_UP 86 | #define PGKEY_PAGE_UP VK_PRIOR 87 | #define PGKEY_PAGE_DOWN VK_NEXT 88 | #define PGKEY_HOME VK_HOME 89 | #define PGKEY_END VK_END 90 | #define PGKEY_CAPS_LOCK VK_CAPITAL 91 | #define PGKEY_NUM_LOCK VK_NUMLOCK 92 | #define PGKEY_PAUSE VK_PAUSE 93 | 94 | #define PGKEY_F1 VK_F1 95 | #define PGKEY_F2 VK_F2 96 | #define PGKEY_F3 VK_F3 97 | #define PGKEY_F4 VK_F4 98 | #define PGKEY_F5 VK_F5 99 | #define PGKEY_F6 VK_F6 100 | #define PGKEY_F7 VK_F7 101 | #define PGKEY_F8 VK_F8 102 | #define PGKEY_F9 VK_F9 103 | #define PGKEY_F10 VK_F10 104 | #define PGKEY_F11 VK_F11 105 | #define PGKEY_F12 VK_F12 106 | #define PGKEY_F13 VK_F13 107 | #define PGKEY_F14 VK_F14 108 | #define PGKEY_F15 VK_F15 109 | #define PGKEY_F16 VK_F16 110 | #define PGKEY_F17 VK_F17 111 | #define PGKEY_F18 VK_F18 112 | #define PGKEY_F19 VK_F19 113 | #define PGKEY_F20 VK_F20 114 | #define PGKEY_F21 VK_F21 115 | #define PGKEY_F22 VK_F22 116 | #define PGKEY_F23 VK_F23 117 | #define PGKEY_F24 VK_F24 118 | 119 | #define PGKEY_LEFT_SHIFT VK_LSHIFT 120 | #define PGKEY_LEFT_CONTROL VK_LCONTROL 121 | #define PGKEY_LEFT_ALT VK_LMENU 122 | #define PGKEY_LEFT_SYSTEM VK_LWIN 123 | #define PGKEY_RIGHT_SHIFT VK_RSHIFT 124 | #define PGKEY_RIGHT_CONTROL VK_RCONTROL 125 | #define PGKEY_RIGHT_ALT VK_RMENU 126 | #define PGKEY_RIGHT_SYSTEM VK_RWIN 127 | 128 | #endif 129 | -------------------------------------------------------------------------------- /PlaygroundEngine/Platform/PGLibrary.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef PLATFORM_WINDOWS 4 | #include "Win32/PGPlatformDefinesWin32.h" 5 | #endif // PLATFORM_WINDOWS 6 | 7 | class DLibrary { 8 | public: 9 | DLibrary(const char* filePath); 10 | ~DLibrary(); 11 | 12 | bool Load(); 13 | bool Unload(); 14 | 15 | template 16 | ProcType GetFunctionAddress(const char* procName) { 17 | return (ProcType) _GetProcAddress(procName); 18 | } 19 | 20 | private: 21 | const char* m_FilePath; 22 | DLibraryHandle m_Handle; 23 | 24 | void* _GetProcAddress(const char* procName); 25 | }; 26 | 27 | -------------------------------------------------------------------------------- /PlaygroundEngine/Platform/PGTime.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../Core.h" 4 | 5 | // Returns time since the device was last rebooted 6 | class PG_API PGTime { 7 | public: 8 | static uint64_t GetTimeNanoseconds(); 9 | static uint64_t GetTimeSeconds(); 10 | static uint64_t GetTimeMilliseconds(); 11 | static uint64_t GetTimeMacroseconds(); 12 | }; 13 | 14 | -------------------------------------------------------------------------------- /PlaygroundEngine/Platform/PGWindow.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef PLATFORM_WINDOWS 4 | #include "Win32/PGPlatformDefinesWin32.h" 5 | #endif // PLATFORM_WINDOWS 6 | 7 | #include "../Core.h" 8 | #include "../Events/PGSystemEventDispatcher.h" 9 | #include "../Math/math_util.h" 10 | 11 | class PG_API PGWindow { 12 | public: 13 | PGWindow(const char* name, uint32_t width, uint32_t height, PGSystemEventDispatcher* eventDispatcher); 14 | ~PGWindow(); 15 | 16 | void Show(); 17 | 18 | // Processes all window messages 19 | // Returns false if quit requested otherwise returns true 20 | bool ProcessMessages(); 21 | 22 | WindowHandle GetWindowHandle(); 23 | uint32_t GetWidth(); 24 | uint32_t GetHeight(); 25 | Vector2 GetClientSize(); 26 | 27 | private: 28 | WindowHandle m_Handle; 29 | uint32_t m_Width; 30 | uint32_t m_Height; 31 | PGSystemEventDispatcher* m_SystemEventDispatcher = nullptr; 32 | 33 | #ifdef PLATFORM_WINDOWS 34 | static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); 35 | LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); 36 | #endif 37 | }; 38 | -------------------------------------------------------------------------------- /PlaygroundEngine/Platform/Win32/PGInputWin32.cpp: -------------------------------------------------------------------------------- 1 | #include "../PGInput.h" 2 | 3 | bool PGInput::keyPressedState[256]; 4 | bool PGInput::mouseButtonPressedState[5]; 5 | 6 | inline bool PGInput::IsKeyPressed(KeyCode keycode) { 7 | return keyPressedState[keycode]; 8 | } 9 | 10 | inline bool PGInput::IsMouseButtonPressed(KeyCode keycode) { 11 | return mouseButtonPressedState[keycode]; 12 | } 13 | 14 | inline Vector2 PGInput::GetMousePos() { 15 | POINT point; 16 | GetCursorPos(&point); 17 | HWND foregroundWindow = GetForegroundWindow(); 18 | ScreenToClient(foregroundWindow, &point); 19 | 20 | return { (float) point.x, (float) point.y }; 21 | } 22 | 23 | 24 | -------------------------------------------------------------------------------- /PlaygroundEngine/Platform/Win32/PGLibraryWin32.cpp: -------------------------------------------------------------------------------- 1 | #include "../PGLibrary.h" 2 | 3 | DLibrary::DLibrary(const char* filePath) 4 | : m_FilePath(filePath) 5 | , m_Handle(nullptr) { 6 | } 7 | 8 | DLibrary::~DLibrary() { 9 | Unload(); 10 | } 11 | 12 | bool DLibrary::Load() { 13 | m_Handle = LoadLibrary(m_FilePath); 14 | return m_Handle != nullptr; 15 | } 16 | 17 | bool DLibrary::Unload() { 18 | return FreeLibrary(m_Handle); 19 | } 20 | 21 | void* DLibrary::_GetProcAddress(const char* procName) { 22 | return GetProcAddress(m_Handle, procName); 23 | } 24 | 25 | 26 | -------------------------------------------------------------------------------- /PlaygroundEngine/Platform/Win32/PGPlatformDefinesWin32.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | typedef HWND WindowHandle; 6 | typedef HMODULE DLibraryHandle; 7 | -------------------------------------------------------------------------------- /PlaygroundEngine/Platform/Win32/PGTimeWin32.cpp: -------------------------------------------------------------------------------- 1 | #include "../PGTime.h" 2 | 3 | #include 4 | 5 | inline uint64_t PGTime::GetTimeNanoseconds() { 6 | // TODO: This operation may not be success. Check return value. 7 | LARGE_INTEGER time, frequency; 8 | QueryPerformanceFrequency(&frequency); 9 | QueryPerformanceCounter(&time); 10 | 11 | time.QuadPart *= 1000000000; 12 | time.QuadPart /= frequency.QuadPart; 13 | return time.QuadPart; 14 | } 15 | 16 | inline uint64_t PGTime::GetTimeMacroseconds() { 17 | uint64_t nanoseconds = GetTimeNanoseconds(); 18 | return nanoseconds / 1000; 19 | } 20 | 21 | inline uint64_t PGTime::GetTimeMilliseconds() { 22 | uint64_t macroseconds = GetTimeMacroseconds(); 23 | return macroseconds / 1000; 24 | } 25 | 26 | inline uint64_t PGTime::GetTimeSeconds() { 27 | uint64_t milliseconds = GetTimeMilliseconds(); 28 | return milliseconds / 1000; 29 | } 30 | -------------------------------------------------------------------------------- /PlaygroundEngine/Platform/Win32/PGWindowWin32.cpp: -------------------------------------------------------------------------------- 1 | #include "../PGWindow.h" 2 | #include "../PGInput.h" 3 | #include "../../Imgui/imgui.h" 4 | 5 | 6 | LRESULT CALLBACK PGWindow::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { 7 | PGWindow* window = nullptr; 8 | 9 | if (uMsg == WM_NCCREATE) { 10 | CREATESTRUCT* create = reinterpret_cast(lParam); 11 | window = reinterpret_cast(create->lpCreateParams); 12 | SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) window); 13 | 14 | window->m_Handle = hwnd; 15 | } else { 16 | window = reinterpret_cast(GetWindowLongPtr(hwnd, GWLP_USERDATA)); 17 | } 18 | 19 | if (window) { 20 | return window->HandleMessage(uMsg, wParam, lParam); 21 | } else { 22 | return DefWindowProc(hwnd, uMsg, wParam, lParam); 23 | } 24 | }; 25 | 26 | PGWindow::PGWindow(const char* name, uint32_t width, uint32_t height, PGSystemEventDispatcher* eventDispatcher) 27 | : m_Width(width) 28 | , m_Height(height) { 29 | 30 | HINSTANCE hInstance = GetModuleHandle(0); 31 | SetProcessDPIAware(); 32 | 33 | const char* windowClassName = "WindowClass"; 34 | WNDCLASS windowClass = {}; 35 | windowClass.lpfnWndProc = &PGWindow::WindowProc; 36 | windowClass.hInstance = hInstance; 37 | windowClass.lpszClassName = windowClassName; 38 | 39 | RegisterClass(&windowClass); 40 | 41 | HWND windowHandle = CreateWindowEx(0, 42 | windowClassName, 43 | name, 44 | WS_OVERLAPPEDWINDOW, 45 | CW_USEDEFAULT, 46 | CW_USEDEFAULT, 47 | width, 48 | height, 49 | NULL, 50 | NULL, 51 | hInstance, 52 | this); 53 | 54 | m_Handle = windowHandle; 55 | m_SystemEventDispatcher = eventDispatcher; 56 | } 57 | 58 | PGWindow::~PGWindow() { 59 | DestroyWindow(m_Handle); 60 | } 61 | 62 | WindowHandle PGWindow::GetWindowHandle() { 63 | return m_Handle; 64 | } 65 | 66 | uint32_t PGWindow::GetWidth() { 67 | return m_Width; 68 | } 69 | 70 | uint32_t PGWindow::GetHeight() { 71 | return m_Height; 72 | } 73 | 74 | Vector2 PGWindow::GetClientSize() { 75 | RECT rect; 76 | GetClientRect(m_Handle, &rect); 77 | return Vector2((float)(rect.right - rect.left), (float)(rect.bottom - rect.top)); 78 | } 79 | 80 | 81 | void PGWindow::Show() { 82 | ShowWindow(m_Handle, SW_SHOWDEFAULT); 83 | } 84 | 85 | bool PGWindow::ProcessMessages() { 86 | MSG msg; 87 | while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { 88 | TranslateMessage(&msg); 89 | DispatchMessage(&msg); 90 | 91 | if (msg.message == WM_QUIT || msg.message == WM_DESTROY) { 92 | return false; 93 | } 94 | } 95 | 96 | return true; 97 | } 98 | 99 | LRESULT PGWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) { 100 | switch (uMsg) { 101 | case WM_DESTROY: 102 | { 103 | PostQuitMessage(0); 104 | } return 0; 105 | case WM_KEYDOWN: 106 | case WM_SYSKEYDOWN: 107 | { 108 | PGInput::keyPressedState[wParam] = true; 109 | } break; 110 | case WM_KEYUP: 111 | case WM_SYSKEYUP: 112 | { 113 | PGInput::keyPressedState[wParam] = false; 114 | } break; 115 | case WM_LBUTTONDOWN: 116 | { 117 | PGInput::mouseButtonPressedState[PGMOUSE_LBUTTON] = true; 118 | } break; 119 | case WM_RBUTTONDOWN: 120 | { 121 | PGInput::mouseButtonPressedState[PGMOUSE_RBUTTON] = true; 122 | } break; 123 | case WM_MBUTTONDOWN: 124 | { 125 | PGInput::mouseButtonPressedState[PGMOUSE_MBUTTON] = true; 126 | } break; 127 | case WM_LBUTTONUP: 128 | { 129 | PGInput::mouseButtonPressedState[PGMOUSE_LBUTTON] = false; 130 | } break; 131 | case WM_RBUTTONUP: 132 | { 133 | PGInput::mouseButtonPressedState[PGMOUSE_RBUTTON] = false; 134 | } break; 135 | case WM_MBUTTONUP: 136 | { 137 | PGInput::mouseButtonPressedState[PGMOUSE_MBUTTON] = false; 138 | } break; 139 | case WM_CHAR: 140 | { 141 | // NOTE: We may need to store input characters for our input system too. 142 | ImGuiIO& io = ImGui::GetIO(); 143 | io.AddInputCharacter((unsigned int) wParam); 144 | } break; 145 | case WM_SIZE: 146 | { 147 | m_Width = LOWORD(lParam); 148 | m_Height = HIWORD(lParam); 149 | 150 | RECT rect; 151 | GetClientRect(m_Handle, &rect); 152 | if (m_SystemEventDispatcher) { 153 | m_SystemEventDispatcher->DispatchSystemEvent(SystemEvent::RESIZE, (uint64_t)(rect.right - rect.left), (uint64_t)(rect.bottom - rect.top)); 154 | } 155 | } break; 156 | } 157 | 158 | return DefWindowProc(m_Handle, uMsg, wParam, lParam); 159 | } 160 | 161 | 162 | -------------------------------------------------------------------------------- /PlaygroundEngine/PlaygroundEngine.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | true 5 | 6 | -------------------------------------------------------------------------------- /PlaygroundEngine/Renderer/BaseRenderPass.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "HWRendererAPI.h" 4 | #include "PGShader.h" 5 | 6 | #define MAX_RENDER_TARGET_COUNT 4 7 | #define MAX_SHADER_RESOURCE_COUNT 64 8 | 9 | enum ShaderStage : uint8_t { 10 | VERTEX = BIT(1), 11 | PIXEL = BIT(2), 12 | COMPUTE = BIT(3) 13 | }; 14 | 15 | class RenderPass { 16 | public: 17 | virtual ~RenderPass() = default; 18 | 19 | inline void SetRenderTarget(size_t slot, HWRenderTargetView* renderTarget) { 20 | m_RenderTargets[slot] = renderTarget; 21 | } 22 | 23 | inline void SetDepthStencilTarget(HWDepthStencilView* depthStencilTarget) { 24 | m_DepthStencilView = depthStencilTarget; 25 | } 26 | 27 | inline void SetViewport(HWViewport& viewport) { 28 | m_Viewport = viewport; 29 | } 30 | 31 | inline void SetShaderResource(size_t slot, HWShaderResourceView* shaderResource, uint8_t shaderStage) { 32 | if (shaderStage & ShaderStage::VERTEX) { 33 | m_ShaderResourcesVS[slot] = shaderResource; 34 | } 35 | if (shaderStage & ShaderStage::PIXEL) { 36 | m_ShaderResourcesPS[slot] = shaderResource; 37 | } 38 | } 39 | 40 | protected: 41 | HWDepthStencilView* m_DepthStencilView = nullptr; 42 | HWRenderTargetView* m_RenderTargets[MAX_RENDER_TARGET_COUNT] = { 0 }; 43 | HWViewport m_Viewport; 44 | 45 | HWShaderResourceView* m_ShaderResourcesVS[MAX_SHADER_RESOURCE_COUNT] = { 0 }; 46 | HWShaderResourceView* m_ShaderResourcesPS[MAX_SHADER_RESOURCE_COUNT] = { 0 }; 47 | 48 | }; 49 | 50 | -------------------------------------------------------------------------------- /PlaygroundEngine/Renderer/DX11/DX11Buffer.cpp: -------------------------------------------------------------------------------- 1 | #include "DX11Buffer.h" 2 | 3 | static inline D3D11_BIND_FLAG GetBindFlagsFromResourceFlags(uint32_t resourceFlags) { 4 | return D3D11_BIND_FLAG( 5 | ((resourceFlags & HWResourceFlags::BIND_DEPTH_STENCIL) ? D3D11_BIND_DEPTH_STENCIL : 0) | 6 | ((resourceFlags & HWResourceFlags::BIND_RENDER_TARGET) ? D3D11_BIND_RENDER_TARGET : 0) | 7 | ((resourceFlags & HWResourceFlags::BIND_VERTEX_BUFFER) ? D3D11_BIND_VERTEX_BUFFER : 0) | 8 | ((resourceFlags & HWResourceFlags::BIND_INDEX_BUFFER) ? D3D11_BIND_INDEX_BUFFER : 0) | 9 | ((resourceFlags & HWResourceFlags::BIND_CONSTANT_BUFFER) ? D3D11_BIND_CONSTANT_BUFFER : 0) | 10 | ((resourceFlags & HWResourceFlags::BIND_SHADER_RESOURCE) ? D3D11_BIND_SHADER_RESOURCE : 0) 11 | ); 12 | } 13 | 14 | static inline D3D11_USAGE GetUsageFromResourceFlags(uint32_t resourceFlags) { 15 | return D3D11_USAGE( 16 | ((resourceFlags & HWResourceFlags::USAGE_STAGING) ? D3D11_USAGE_STAGING : 17 | ((resourceFlags & HWResourceFlags::USAGE_DYNAMIC) ? D3D11_USAGE_DYNAMIC : 18 | ((resourceFlags & HWResourceFlags::USAGE_IMMUTABLE) ? D3D11_USAGE_IMMUTABLE : 19 | D3D11_USAGE_DEFAULT))) 20 | ); 21 | } 22 | 23 | static inline D3D11_CPU_ACCESS_FLAG GetCPUAccessFlagFromResourceFlags(uint32_t resourceFlags) { 24 | return D3D11_CPU_ACCESS_FLAG( 25 | ((resourceFlags & HWResourceFlags::CPU_ACCESS_READ) ? D3D11_CPU_ACCESS_READ : 0) | 26 | ((resourceFlags & HWResourceFlags::CPU_ACCESS_WRITE) ? D3D11_CPU_ACCESS_WRITE : 0) 27 | ); 28 | } 29 | 30 | DX11Buffer::DX11Buffer(ID3D11Device* device, SubresourceData* subresource, size_t size, uint32_t flags, const char* debugName) { 31 | D3D11_BUFFER_DESC bufferDesc = {}; 32 | bufferDesc.ByteWidth = (UINT) size; 33 | bufferDesc.Usage = GetUsageFromResourceFlags(flags); 34 | bufferDesc.BindFlags = GetBindFlagsFromResourceFlags(flags); 35 | bufferDesc.CPUAccessFlags = GetCPUAccessFlagFromResourceFlags(flags); 36 | bufferDesc.MiscFlags = 0; 37 | bufferDesc.StructureByteStride = 0; 38 | 39 | if (subresource) { 40 | D3D11_SUBRESOURCE_DATA bufferSubresourceData = {}; 41 | bufferSubresourceData.pSysMem = subresource->data; 42 | bufferSubresourceData.SysMemPitch = subresource->memPitch; 43 | bufferSubresourceData.SysMemSlicePitch = subresource->memSlicePitch; 44 | 45 | HRESULT result = device->CreateBuffer(&bufferDesc, &bufferSubresourceData, &m_Buffer); 46 | PG_ASSERT(SUCCEEDED(result), "Error at creating buffer"); 47 | } else { 48 | HRESULT result = device->CreateBuffer(&bufferDesc, nullptr, &m_Buffer); 49 | PG_ASSERT(SUCCEEDED(result), "Error at creating buffer"); 50 | } 51 | 52 | #ifdef PG_DEBUG_GPU_DEVICE 53 | if (debugName) { 54 | size_t debugNameLen = strlen(debugName); 55 | m_Buffer->SetPrivateData(WKPDID_D3DDebugObjectName, (UINT) debugNameLen, debugName); 56 | } 57 | #endif 58 | } 59 | 60 | DX11Buffer::~DX11Buffer() { 61 | SAFE_RELEASE(m_Buffer); 62 | } 63 | -------------------------------------------------------------------------------- /PlaygroundEngine/Renderer/DX11/DX11Buffer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../HWBuffer.h" 4 | 5 | #include 6 | 7 | class DX11Buffer : public HWBuffer { 8 | public: 9 | DX11Buffer(ID3D11Device* device, SubresourceData* subresource, size_t size, uint32_t flags, const char* debugName = 0); 10 | ~DX11Buffer() override; 11 | 12 | ID3D11Buffer* GetDXBuffer() { return m_Buffer; } 13 | void* GetResourceHandle() override { return (void*) m_Buffer; } 14 | 15 | private: 16 | ID3D11Buffer* m_Buffer; 17 | }; 18 | -------------------------------------------------------------------------------- /PlaygroundEngine/Renderer/DX11/DX11PipelineStates.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../HWPipelineStates.h" 4 | 5 | #include 6 | 7 | class DX11GraphicsPipelineState : public HWGraphicsPipelineState { 8 | public: 9 | DX11GraphicsPipelineState(ID3D11Device* device, const HWGraphicsPipelineStateDesc& pipelineDesc, const char* debugName); 10 | ~DX11GraphicsPipelineState() override; 11 | 12 | inline ID3D11VertexShader* GetDXVertexShader() { return m_VertexShader; } 13 | inline ID3D11PixelShader* GetDXPixelShader() { return m_PixelShader; } 14 | 15 | inline ID3D11BlendState* GetDXBlendState() { return m_BlendState; } 16 | inline ID3D11RasterizerState* GetDXRasterizerState() { return m_RasterizerState; } 17 | inline ID3D11InputLayout* GetDXInputLayout() { return m_InputLayout; } 18 | inline ID3D11DepthStencilState* GetDXDepthStencilState() { return m_DepthStencilState; } 19 | 20 | inline D3D11_PRIMITIVE_TOPOLOGY GetDXPrimitiveTopology() { return m_PrimitiveTopology; } 21 | inline uint32_t GetSampleMask() { return m_SampleMask; } 22 | 23 | private: 24 | ID3D11VertexShader* m_VertexShader = nullptr; 25 | ID3D11PixelShader* m_PixelShader = nullptr; 26 | 27 | ID3D11BlendState* m_BlendState = nullptr; 28 | ID3D11RasterizerState* m_RasterizerState = nullptr; 29 | ID3D11InputLayout* m_InputLayout = nullptr; 30 | ID3D11DepthStencilState* m_DepthStencilState = nullptr; 31 | 32 | D3D11_PRIMITIVE_TOPOLOGY m_PrimitiveTopology; 33 | uint32_t m_SampleMask; 34 | }; 35 | 36 | class DX11ComputePipelineState : public HWComputePipelineState { 37 | public: 38 | DX11ComputePipelineState(ID3D11Device* device, const HWComputePipelineStateDesc& pipelineDesc, const char* debugName); 39 | ~DX11ComputePipelineState() override; 40 | 41 | inline ID3D11ComputeShader* GetDXComputeShader() { return m_ComputeShader; } 42 | 43 | private: 44 | ID3D11ComputeShader* m_ComputeShader = nullptr; 45 | }; 46 | 47 | -------------------------------------------------------------------------------- /PlaygroundEngine/Renderer/DX11/DX11Query.cpp: -------------------------------------------------------------------------------- 1 | #include "DX11Query.h" 2 | 3 | static D3D11_QUERY GetD3D11Query(HWQueryType queryType) { 4 | switch (queryType) { 5 | case QUERY_EVENT: 6 | return D3D11_QUERY_EVENT; 7 | case QUERY_OCCLUSION: 8 | return D3D11_QUERY_OCCLUSION; 9 | case QUERY_TIMESTAMP: 10 | return D3D11_QUERY_TIMESTAMP; 11 | case QUERY_TIMESTAMP_DISJOINT: 12 | return D3D11_QUERY_TIMESTAMP_DISJOINT; 13 | case QUERY_PIPELINE_STATISTICS: 14 | return D3D11_QUERY_PIPELINE_STATISTICS; 15 | case QUERY_OCCLUSION_PREDICATE: 16 | return D3D11_QUERY_OCCLUSION_PREDICATE; 17 | default: 18 | return D3D11_QUERY(); 19 | } 20 | } 21 | 22 | static D3D11_QUERY_MISC_FLAG GetD3D11QueryMiscFlags(uint8_t flags) { 23 | return D3D11_QUERY_MISC_FLAG( 24 | ((flags & HWQueryFlags::QUERY_MISC_PREDICATEHINT) ? D3D11_QUERY_MISC_PREDICATEHINT : 0) 25 | ); 26 | } 27 | 28 | DX11Query::DX11Query(ID3D11Device* device, const HWQueryDesc& queryDesc, const char* debugName) { 29 | D3D11_QUERY_DESC dxQueryDesc; 30 | dxQueryDesc.Query = GetD3D11Query(queryDesc.queryType); 31 | dxQueryDesc.MiscFlags = GetD3D11QueryMiscFlags(queryDesc.flags); 32 | 33 | HRESULT result = device->CreateQuery(&dxQueryDesc, &m_Query); 34 | PG_ASSERT(SUCCEEDED(result), "Error at creating query"); 35 | 36 | #ifdef PG_DEBUG_GPU_DEVICE 37 | if (debugName) { 38 | size_t debugNameLen = strlen(debugName); 39 | m_Query->SetPrivateData(WKPDID_D3DDebugObjectName, (UINT)debugNameLen, debugName); 40 | } 41 | #endif 42 | } 43 | 44 | DX11Query::~DX11Query() { 45 | SAFE_RELEASE(m_Query); 46 | } 47 | 48 | -------------------------------------------------------------------------------- /PlaygroundEngine/Renderer/DX11/DX11Query.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../HWQuery.h" 4 | 5 | #include 6 | 7 | class DX11Query : public HWQuery { 8 | public: 9 | DX11Query(ID3D11Device* device, const HWQueryDesc& queryDesc, const char* debugName = 0); 10 | ~DX11Query() override; 11 | 12 | ID3D11Query* GetDXQuery() { return m_Query; } 13 | 14 | private: 15 | ID3D11Query* m_Query; 16 | }; 17 | 18 | -------------------------------------------------------------------------------- /PlaygroundEngine/Renderer/DX11/DX11RenderTargets.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../../Core.h" 4 | #include "../HWRenderTarget.h" 5 | 6 | #include 7 | 8 | class DX11RenderTargetView : public HWRenderTargetView { 9 | public: 10 | DX11RenderTargetView(ID3D11Device* device, ID3D11Texture2D* texture, const HWResourceViewDesc& resourceViewDesc, const char* debugName = 0); 11 | ~DX11RenderTargetView(); 12 | 13 | inline ID3D11RenderTargetView* GetDXRenderTargetView() { return m_RenderTargetView; } 14 | 15 | private: 16 | ID3D11RenderTargetView* m_RenderTargetView = nullptr; 17 | }; 18 | 19 | class DX11DepthStencilView : public HWDepthStencilView { 20 | public: 21 | DX11DepthStencilView(ID3D11Device* device, ID3D11Texture2D* texture, const HWResourceViewDesc& resourceViewDesc, const char* debugName = 0); 22 | ~DX11DepthStencilView(); 23 | 24 | inline ID3D11DepthStencilView* GetDXDepthStencilView() { return m_DepthStencilView; } 25 | 26 | private: 27 | ID3D11DepthStencilView* m_DepthStencilView = nullptr; 28 | }; 29 | 30 | -------------------------------------------------------------------------------- /PlaygroundEngine/Renderer/DX11/DX11SamplerState.cpp: -------------------------------------------------------------------------------- 1 | #include "DX11SamplerState.h" 2 | 3 | static inline D3D11_TEXTURE_ADDRESS_MODE GetD3DAddressModeFromAddressMode(SamplerStateTextureAddressMode mode) { 4 | D3D11_TEXTURE_ADDRESS_MODE result = {}; 5 | switch (mode) { 6 | case TextureAddressMode_NONE: 7 | break; 8 | case TextureAddressMode_WRAP: 9 | result = D3D11_TEXTURE_ADDRESS_WRAP; 10 | break; 11 | case TextureAddressMode_MIRROR: 12 | result = D3D11_TEXTURE_ADDRESS_MIRROR; 13 | break; 14 | case TextureAddressMode_CLAMP: 15 | result = D3D11_TEXTURE_ADDRESS_CLAMP; 16 | break; 17 | case TextureAddressMode_BORDER: 18 | result = D3D11_TEXTURE_ADDRESS_BORDER; 19 | break; 20 | default: 21 | PG_ASSERT(false, "Unhandled sampler state texture address mode!"); 22 | break; 23 | } 24 | 25 | return result; 26 | } 27 | 28 | static inline D3D11_FILTER GetD3DFilterFromFilterMode(SamplerStateTextureFilterMode mode, ComparisonFunction cmpFunc) { 29 | // TODO; Handle mode filters 30 | D3D11_FILTER result; 31 | bool isComparison = cmpFunc != ComparisonFunction::NONE; 32 | switch (mode) { 33 | case TextureFilterMode_MIN_MAG_MIP_POINT: 34 | result = isComparison ? D3D11_FILTER_COMPARISON_MIN_MAG_MIP_POINT : D3D11_FILTER_MIN_MAG_MIP_POINT; 35 | break; 36 | case TextureFilterMode_MIN_MAG_MIP_LINEAR: 37 | result = isComparison ? D3D11_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR : D3D11_FILTER_MIN_MAG_MIP_LINEAR; 38 | break; 39 | case TextureFilterMode_MIN_MAG_LINEAR_MIP_POINT: 40 | result = isComparison ? D3D11_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT : D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT; 41 | break; 42 | case TextureFilterMode_ANISOTROPIC: 43 | result = isComparison ? D3D11_FILTER_COMPARISON_ANISOTROPIC: D3D11_FILTER_ANISOTROPIC; 44 | break; 45 | default: 46 | PG_ASSERT(false, "Unhandled sampler state texture filter mode!"); 47 | break; 48 | } 49 | 50 | return result; 51 | } 52 | 53 | static inline D3D11_COMPARISON_FUNC GetD3DComparisonFunc(ComparisonFunction func) { 54 | D3D11_COMPARISON_FUNC result = {}; 55 | switch (func) { 56 | case NONE: 57 | break; 58 | case NEVER: 59 | result = D3D11_COMPARISON_NEVER; 60 | break; 61 | case LESS: 62 | result = D3D11_COMPARISON_LESS; 63 | break; 64 | case EQUAL: 65 | result = D3D11_COMPARISON_EQUAL; 66 | break; 67 | case LESS_EQUAL: 68 | result = D3D11_COMPARISON_LESS_EQUAL; 69 | break; 70 | case GREATER: 71 | result = D3D11_COMPARISON_GREATER; 72 | break; 73 | case NOT_EQUAL: 74 | result = D3D11_COMPARISON_NOT_EQUAL; 75 | break; 76 | case GREATER_EQUAL: 77 | result = D3D11_COMPARISON_GREATER_EQUAL; 78 | break; 79 | case ALWAYS: 80 | result = D3D11_COMPARISON_ALWAYS; 81 | break; 82 | default: 83 | PG_ASSERT(false, "Unhandled sampler state comparison function!"); 84 | break; 85 | } 86 | 87 | return result; 88 | } 89 | 90 | DX11SamplerState::DX11SamplerState(ID3D11Device* device, SamplerStateInitParams* initParams, const char* debugName) { 91 | D3D11_SAMPLER_DESC samplerStateDesc = {}; 92 | samplerStateDesc.Filter = GetD3DFilterFromFilterMode(initParams->filterMode, initParams->comparisonFunction); 93 | samplerStateDesc.AddressU = GetD3DAddressModeFromAddressMode(initParams->addressModeU); 94 | samplerStateDesc.AddressV = GetD3DAddressModeFromAddressMode(initParams->addressModeV); 95 | samplerStateDesc.AddressW = GetD3DAddressModeFromAddressMode(initParams->addressModeW); 96 | samplerStateDesc.ComparisonFunc = GetD3DComparisonFunc(initParams->comparisonFunction); 97 | samplerStateDesc.MaxAnisotropy = initParams->maxAnisotropy; 98 | samplerStateDesc.MaxLOD = D3D11_FLOAT32_MAX; 99 | memcpy(samplerStateDesc.BorderColor, initParams->borderColor, sizeof(float) * 4); 100 | 101 | HRESULT result = device->CreateSamplerState(&samplerStateDesc, &m_SamplerState); 102 | PG_ASSERT(SUCCEEDED(result), "Error at creating sampler state"); 103 | 104 | #ifdef PG_DEBUG_GPU_DEVICE 105 | if (debugName) { 106 | size_t debugNameLen = strlen(debugName); 107 | m_SamplerState->SetPrivateData(WKPDID_D3DDebugObjectName, (UINT) debugNameLen, debugName); 108 | } 109 | #endif 110 | } 111 | 112 | DX11SamplerState::~DX11SamplerState() { 113 | SAFE_RELEASE(m_SamplerState); 114 | } 115 | -------------------------------------------------------------------------------- /PlaygroundEngine/Renderer/DX11/DX11SamplerState.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../HWSamplerState.h" 4 | 5 | #include 6 | 7 | class DX11SamplerState : public HWSamplerState { 8 | public: 9 | DX11SamplerState(ID3D11Device* device, SamplerStateInitParams* initParams, const char* debugName = 0); 10 | ~DX11SamplerState(); 11 | 12 | inline ID3D11SamplerState* GetDXSamplerState() { return m_SamplerState; } 13 | 14 | private: 15 | ID3D11SamplerState* m_SamplerState = nullptr; 16 | }; 17 | 18 | -------------------------------------------------------------------------------- /PlaygroundEngine/Renderer/DX11/DX11ShaderResourceView.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../HWShaderResourceView.h" 4 | 5 | #include 6 | 7 | class DX11ShaderResourceView : public HWShaderResourceView { 8 | public: 9 | DX11ShaderResourceView(ID3D11Device* device, ID3D11Texture2D* texture, const HWResourceViewDesc& resourceViewDesc, const char* debugName = 0); 10 | ~DX11ShaderResourceView(); 11 | 12 | inline ID3D11ShaderResourceView* GetDXShaderResouceView() { return m_ShaderResourceView; } 13 | 14 | private: 15 | ID3D11ShaderResourceView* m_ShaderResourceView = nullptr; 16 | }; 17 | 18 | class DX11UnorderedAccessView : public HWUnorderedAccessView { 19 | public: 20 | DX11UnorderedAccessView(ID3D11Device* device, ID3D11Texture2D* texture, const HWResourceViewDesc& resourceViewDesc, const char* debugName = 0); 21 | ~DX11UnorderedAccessView(); 22 | 23 | inline ID3D11UnorderedAccessView* GetDXUnorderedAccessView() { return m_UnorderedAccessView; } 24 | 25 | private: 26 | ID3D11UnorderedAccessView* m_UnorderedAccessView = nullptr; 27 | }; 28 | 29 | -------------------------------------------------------------------------------- /PlaygroundEngine/Renderer/DX11/DX11Texture2D.cpp: -------------------------------------------------------------------------------- 1 | #include "DX11Texture2D.h" 2 | 3 | #include 4 | 5 | static inline UINT GetMiscFlagsFromResourceFlags(uint32_t resourceFlags) { 6 | return UINT( 7 | ((resourceFlags & HWResourceFlags::MISC_TEXTURE_CUBE) ? D3D11_RESOURCE_MISC_TEXTURECUBE : 0) | 8 | ((resourceFlags & HWResourceFlags::MISC_GENERATE_MIPS) ? D3D11_RESOURCE_MISC_GENERATE_MIPS : 0) 9 | ); 10 | } 11 | 12 | static inline D3D11_BIND_FLAG GetBindFlagsFromResourceFlags(uint32_t resourceFlags) { 13 | return D3D11_BIND_FLAG( 14 | ((resourceFlags & HWResourceFlags::BIND_DEPTH_STENCIL) ? D3D11_BIND_DEPTH_STENCIL : 0) | 15 | ((resourceFlags & HWResourceFlags::BIND_RENDER_TARGET) ? D3D11_BIND_RENDER_TARGET : 0) | 16 | ((resourceFlags & HWResourceFlags::BIND_UNORDERED_ACCESS) ? D3D11_BIND_UNORDERED_ACCESS : 0) | 17 | ((resourceFlags & HWResourceFlags::BIND_SHADER_RESOURCE) ? D3D11_BIND_SHADER_RESOURCE : 0) 18 | ); 19 | } 20 | 21 | static inline D3D11_USAGE GetUsageFromResourceFlags(uint32_t resourceFlags) { 22 | return D3D11_USAGE( 23 | ((resourceFlags & HWResourceFlags::USAGE_STAGING) ? D3D11_USAGE_STAGING : 24 | ((resourceFlags & HWResourceFlags::USAGE_DYNAMIC) ? D3D11_USAGE_DYNAMIC : 25 | ((resourceFlags & HWResourceFlags::USAGE_IMMUTABLE) ? D3D11_USAGE_IMMUTABLE : 26 | D3D11_USAGE_DEFAULT))) 27 | ); 28 | } 29 | 30 | static inline D3D11_CPU_ACCESS_FLAG GetCPUAccessFlagFromResourceFlags(uint32_t resourceFlags) { 31 | return D3D11_CPU_ACCESS_FLAG( 32 | ((resourceFlags & HWResourceFlags::CPU_ACCESS_READ) ? D3D11_CPU_ACCESS_READ : 0) | 33 | ((resourceFlags & HWResourceFlags::CPU_ACCESS_WRITE) ? D3D11_CPU_ACCESS_WRITE : 0) 34 | ); 35 | } 36 | 37 | DX11Texture2D::DX11Texture2D(ID3D11Device* device, Texture2DDesc* initParams, SubresourceData* subresources, const char* debugName) { 38 | D3D11_TEXTURE2D_DESC textureDesc = {}; 39 | textureDesc.Width = (UINT) initParams->width; 40 | textureDesc.Height = (UINT) initParams->height; 41 | textureDesc.MipLevels = (UINT) initParams->mipCount; 42 | textureDesc.ArraySize = (UINT) initParams->arraySize; 43 | textureDesc.Format = initParams->format; 44 | textureDesc.SampleDesc.Count = (UINT) initParams->sampleCount; 45 | textureDesc.SampleDesc.Quality = 0; 46 | textureDesc.Usage = GetUsageFromResourceFlags(initParams->flags); 47 | textureDesc.BindFlags = GetBindFlagsFromResourceFlags(initParams->flags); 48 | textureDesc.CPUAccessFlags = GetCPUAccessFlagFromResourceFlags(initParams->flags); 49 | textureDesc.MiscFlags = GetMiscFlagsFromResourceFlags(initParams->flags); 50 | 51 | if (subresources) { 52 | D3D11_SUBRESOURCE_DATA* subresourceDatas = (D3D11_SUBRESOURCE_DATA*) alloca(sizeof(D3D11_SUBRESOURCE_DATA) * initParams->arraySize * initParams->mipCount); 53 | SubresourceData* textureSubresource = subresources; 54 | for (size_t arrayIndex = 0; arrayIndex < initParams->arraySize; ++arrayIndex) { 55 | for (size_t mipIndex = 0; mipIndex < initParams->mipCount; ++mipIndex) { 56 | D3D11_SUBRESOURCE_DATA* subresourceData = subresourceDatas + (arrayIndex * initParams->mipCount + mipIndex); 57 | subresourceData->pSysMem = textureSubresource->data; 58 | subresourceData->SysMemPitch = textureSubresource->memPitch; 59 | subresourceData->SysMemSlicePitch = textureSubresource->memSlicePitch; 60 | ++textureSubresource; 61 | } 62 | } 63 | 64 | HRESULT result = device->CreateTexture2D(&textureDesc, subresourceDatas, &m_Texture); 65 | PG_ASSERT(SUCCEEDED(result), "Error at creating texture"); 66 | } else { 67 | HRESULT result = device->CreateTexture2D(&textureDesc, nullptr, &m_Texture); 68 | PG_ASSERT(SUCCEEDED(result), "Error at creating texture"); 69 | } 70 | 71 | #ifdef PG_DEBUG_GPU_DEVICE 72 | if (debugName) { 73 | size_t debugNameLen = strlen(debugName); 74 | m_Texture->SetPrivateData(WKPDID_D3DDebugObjectName, (UINT) debugNameLen, debugName); 75 | } 76 | #endif 77 | 78 | m_Desc = *initParams; 79 | } 80 | 81 | Texture2DDesc DX11Texture2D::GetDesc() { 82 | return m_Desc; 83 | } 84 | 85 | 86 | DX11Texture2D::~DX11Texture2D() { 87 | SAFE_RELEASE(m_Texture); 88 | } 89 | 90 | -------------------------------------------------------------------------------- /PlaygroundEngine/Renderer/DX11/DX11Texture2D.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../HWTexture2D.h" 4 | 5 | #include 6 | 7 | class DX11Texture2D : public HWTexture2D { 8 | public: 9 | DX11Texture2D(ID3D11Device* device, Texture2DDesc* initParams, SubresourceData* subresources, const char* debugName = 0); 10 | ~DX11Texture2D(); 11 | 12 | Texture2DDesc GetDesc() override; 13 | 14 | inline ID3D11Texture2D* GetDXTexture2D() { return m_Texture; } 15 | void* GetResourceHandle() override { return (void*) m_Texture; } 16 | 17 | private: 18 | ID3D11Texture2D* m_Texture; 19 | Texture2DDesc m_Desc; 20 | }; 21 | 22 | -------------------------------------------------------------------------------- /PlaygroundEngine/Renderer/FullscreenPass.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "BaseRenderPass.h" 4 | 5 | class FullscreenPass : public RenderPass { 6 | public: 7 | virtual ~FullscreenPass() = default; 8 | 9 | void Execute(HWRendererAPI* rendererAPI, bool clearRenderTargets, const char* eventName) { 10 | rendererAPI->BeginEvent(eventName); 11 | rendererAPI->SetRenderTargets(m_RenderTargets, MAX_RENDER_TARGET_COUNT, nullptr); 12 | if (clearRenderTargets) { 13 | for (size_t i = 0; i < MAX_RENDER_TARGET_COUNT; ++i) { 14 | HWRenderTargetView* renderTarget = m_RenderTargets[i]; 15 | if (renderTarget) { 16 | float color[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; 17 | rendererAPI->ClearRenderTarget(m_RenderTargets[0], color); 18 | } 19 | } 20 | } 21 | 22 | rendererAPI->SetViewport(&m_Viewport); 23 | rendererAPI->SetGraphicsPipelineState(m_PipelineState); 24 | 25 | // Vertex shader only used for generating fullscreen quad, we don't need to bind any resources for vertex shader 26 | rendererAPI->SetShaderResourcesPS(0, m_ShaderResourcesPS, MAX_SHADER_RESOURCE_COUNT); 27 | rendererAPI->Draw(3, 0); 28 | rendererAPI->EndEvent(); 29 | } 30 | 31 | void SetShader(HWRendererAPI* rendererAPI, PGShader* shader) { 32 | SAFE_DELETE(m_PipelineState); 33 | 34 | HWDepthStencilDesc depthStencilDesc; 35 | depthStencilDesc.depthEnable = false; 36 | depthStencilDesc.depthWriteMask = DEPTH_WRITE_MASK_ZERO; 37 | 38 | HWGraphicsPipelineStateDesc pipelineDesc; 39 | pipelineDesc.vertexShader = shader->GetVertexBytecode(); 40 | pipelineDesc.pixelShader = shader->GetPixelBytecode(); 41 | pipelineDesc.depthStencilDesc = depthStencilDesc; 42 | pipelineDesc.primitiveTopology = PRIMITIVE_TOPOLOGY_TRIANGLELIST; 43 | 44 | m_PipelineState = rendererAPI->CreateGraphicsPipelineState(pipelineDesc); 45 | } 46 | 47 | private: 48 | HWGraphicsPipelineState* m_PipelineState; 49 | }; 50 | 51 | -------------------------------------------------------------------------------- /PlaygroundEngine/Renderer/HWBuffer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "HWResource.h" 4 | 5 | class HWBuffer : public HWResource { 6 | public: 7 | virtual ~HWBuffer() = default; 8 | }; 9 | -------------------------------------------------------------------------------- /PlaygroundEngine/Renderer/HWQuery.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../Core.h" 4 | 5 | enum HWQueryType { 6 | QUERY_EVENT, 7 | QUERY_OCCLUSION, 8 | QUERY_TIMESTAMP, 9 | QUERY_TIMESTAMP_DISJOINT, 10 | QUERY_PIPELINE_STATISTICS, 11 | QUERY_OCCLUSION_PREDICATE 12 | }; 13 | 14 | enum HWQueryFlags : uint8_t { 15 | QUERY_MISC_PREDICATEHINT = BIT(1) 16 | }; 17 | 18 | struct HWQueryDesc { 19 | HWQueryType queryType; 20 | uint8_t flags; 21 | }; 22 | 23 | class HWQuery { 24 | public: 25 | virtual ~HWQuery() = default; 26 | }; 27 | 28 | -------------------------------------------------------------------------------- /PlaygroundEngine/Renderer/HWRenderTarget.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "HWResource.h" 4 | 5 | class HWRenderTargetView { 6 | public: 7 | virtual ~HWRenderTargetView() = default; 8 | }; 9 | 10 | class HWDepthStencilView { 11 | public: 12 | virtual ~HWDepthStencilView() = default; 13 | }; 14 | 15 | -------------------------------------------------------------------------------- /PlaygroundEngine/Renderer/HWResource.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../Core.h" 4 | 5 | enum HWResourceFlags { 6 | // Bind flags 7 | BIND_SHADER_RESOURCE = BIT(1), 8 | BIND_RENDER_TARGET = BIT(2), 9 | BIND_DEPTH_STENCIL = BIT(3), 10 | BIND_UNORDERED_ACCESS = BIT(4), 11 | 12 | BIND_VERTEX_BUFFER = BIT(5), 13 | BIND_INDEX_BUFFER = BIT(6), 14 | BIND_CONSTANT_BUFFER = BIT(7), 15 | 16 | // Usage flags 17 | CPU_ACCESS_READ = BIT(10), 18 | CPU_ACCESS_WRITE = BIT(11), 19 | 20 | USAGE_DYNAMIC = BIT(12), 21 | USAGE_STAGING = BIT(13), 22 | USAGE_IMMUTABLE = BIT(14), 23 | 24 | MISC_TEXTURE_CUBE = BIT(15), 25 | MISC_GENERATE_MIPS = BIT(16) 26 | }; 27 | 28 | struct HWResourceViewDesc { 29 | uint32_t firstArraySlice = 0; 30 | uint32_t sliceArrayCount = 1; 31 | uint32_t firstMip = 0; 32 | uint32_t mipCount = 1; 33 | }; 34 | 35 | struct SubresourceData { 36 | const void* data = nullptr; 37 | uint32_t memPitch = 0; 38 | uint32_t memSlicePitch = 0; 39 | }; 40 | 41 | class HWResource { 42 | public: 43 | virtual ~HWResource() = default; 44 | 45 | virtual void* GetResourceHandle() = 0; 46 | }; 47 | 48 | -------------------------------------------------------------------------------- /PlaygroundEngine/Renderer/HWSamplerState.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../Core.h" 4 | 5 | enum SamplerStateTextureAddressMode { 6 | TextureAddressMode_NONE, 7 | TextureAddressMode_WRAP, 8 | TextureAddressMode_MIRROR, 9 | TextureAddressMode_CLAMP, 10 | TextureAddressMode_BORDER 11 | }; 12 | 13 | enum SamplerStateTextureFilterMode { 14 | TextureFilterMode_MIN_MAG_MIP_LINEAR, 15 | TextureFilterMode_MIN_MAG_MIP_POINT, 16 | TextureFilterMode_MIN_MAG_LINEAR_MIP_POINT, 17 | TextureFilterMode_ANISOTROPIC 18 | }; 19 | 20 | enum ComparisonFunction { 21 | NONE, 22 | NEVER, 23 | LESS, 24 | EQUAL, 25 | LESS_EQUAL, 26 | GREATER, 27 | NOT_EQUAL, 28 | GREATER_EQUAL, 29 | ALWAYS 30 | }; 31 | 32 | struct SamplerStateInitParams { 33 | SamplerStateTextureFilterMode filterMode; 34 | SamplerStateTextureAddressMode addressModeU; 35 | SamplerStateTextureAddressMode addressModeV; 36 | SamplerStateTextureAddressMode addressModeW; 37 | ComparisonFunction comparisonFunction; 38 | uint32_t maxAnisotropy; 39 | float borderColor[4]; 40 | }; 41 | 42 | class HWSamplerState { 43 | public: 44 | virtual ~HWSamplerState() = default; 45 | }; 46 | 47 | -------------------------------------------------------------------------------- /PlaygroundEngine/Renderer/HWShaderResourceView.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../Core.h" 4 | #include "HWResource.h" 5 | 6 | class HWShaderResourceView { 7 | public: 8 | virtual ~HWShaderResourceView() = default; 9 | }; 10 | 11 | class HWUnorderedAccessView { 12 | public: 13 | virtual ~HWUnorderedAccessView() = default; 14 | }; 15 | 16 | -------------------------------------------------------------------------------- /PlaygroundEngine/Renderer/HWTexture2D.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../Core.h" 4 | #include "HWResource.h" 5 | 6 | // TODO: We use DXGI_FORMAT for texture format but we need cross platform enum for supporting different APIs. 7 | #include 8 | typedef DXGI_FORMAT TextureDataFormat; 9 | 10 | struct Texture2DDesc { 11 | size_t width; 12 | size_t height; 13 | TextureDataFormat format; 14 | uint32_t flags; 15 | size_t sampleCount; 16 | size_t arraySize; 17 | size_t mipCount; 18 | }; 19 | 20 | class HWTexture2D : public HWResource { 21 | public: 22 | virtual ~HWTexture2D() = default; 23 | 24 | virtual Texture2DDesc GetDesc() = 0; 25 | }; 26 | 27 | -------------------------------------------------------------------------------- /PlaygroundEngine/Renderer/Material.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PGShaderLib.h" 4 | #include "PGTexture.h" 5 | #include "../Assets/Shaders/ShaderDefinitions.h" 6 | 7 | #include 8 | 9 | enum AlphaMode { 10 | AlphaMode_ALWAYS_PASS, 11 | AlphaMode_ALPHA_TEST, 12 | AlphaMode_BLEND_OVER_OP // Over operator c0 = as * cs + (1 - as) cd 13 | }; 14 | 15 | struct Material : DrawMaterial { 16 | PGTexture* albedoTexture; 17 | PGTexture* roughnessTexture; 18 | PGTexture* metallicTexture; 19 | PGTexture* aoTexture; 20 | PGTexture* metallicRoughnessTexture; 21 | PGTexture* normalTexture; 22 | PGTexture* emmisiveTexture; 23 | 24 | PGTexture* radianceMap; 25 | PGTexture* irradianceMap; 26 | PGTexture* envBrdf; 27 | 28 | // Pipeline variables 29 | ShaderRef shader; // TODO: Store technique instead of shader itself? 30 | AlphaMode alphaMode; 31 | bool doubleSided; 32 | bool normalMappingEnabled; 33 | 34 | uint16_t GetMaterialHash() { 35 | size_t pipelineOffset = offsetof(Material, shader); 36 | uint16_t materialHash = Hash(((const uint8_t*) this), pipelineOffset) & 0xFFFF; 37 | 38 | return materialHash; 39 | } 40 | 41 | uint16_t GetPipelineHash() { 42 | union { 43 | struct { 44 | uint16_t shader : 12; 45 | uint16_t normalMapping : 1; 46 | uint16_t doubleSided : 1; 47 | uint16_t alphaMode : 2; 48 | }; 49 | 50 | uint16_t hash; 51 | } pipelineKey; 52 | 53 | pipelineKey.normalMapping = normalMappingEnabled; 54 | pipelineKey.shader = ((size_t) shader) & 0xFFFF; 55 | pipelineKey.doubleSided = doubleSided; 56 | pipelineKey.alphaMode = (uint16_t) alphaMode; 57 | 58 | return pipelineKey.hash; 59 | } 60 | }; 61 | 62 | -------------------------------------------------------------------------------- /PlaygroundEngine/Renderer/PGShader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../Core.h" 4 | #include "HWRendererAPI.h" 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | enum PGShaderFlags : uint32_t { 12 | ALPHA_TEST = BIT(1), 13 | NORMAL_MAPPING = BIT(2), 14 | 15 | ALL_FLAGS = ALPHA_TEST | NORMAL_MAPPING 16 | }; 17 | 18 | struct PGShaderBlob { 19 | ID3DBlob* shaderBlob = nullptr; 20 | bool isDirty = true; 21 | }; 22 | 23 | struct PGShaderPermutation { 24 | PGShaderBlob vertexShaderBlob; 25 | PGShaderBlob pixelShaderBlob; 26 | PGShaderBlob computeShaderBlob; 27 | uint32_t shaderFlags = 0; 28 | }; 29 | 30 | class PGShader { 31 | public: 32 | PGShader(); 33 | ~PGShader(); 34 | 35 | HWShaderBytecode GetVertexBytecode(uint32_t shaderFlags = 0); 36 | HWShaderBytecode GetPixelBytecode(uint32_t shaderFlags = 0); 37 | HWShaderBytecode GetComputeBytecode(uint32_t shaderFlags = 0); 38 | 39 | void LoadFromFilename(const std::string& filename); 40 | void Reload(); 41 | 42 | bool needsUpdate = false; 43 | 44 | private: 45 | std::string m_Filepath; 46 | std::vector m_Permutations; 47 | }; 48 | 49 | -------------------------------------------------------------------------------- /PlaygroundEngine/Renderer/PGShaderLib.cpp: -------------------------------------------------------------------------------- 1 | #include "PGShaderLib.h" 2 | #include "../PGLog.h" 3 | 4 | PGShaderLib::PGShaderLib(HWRendererAPI* rendererAPI) 5 | : m_RendererAPI(rendererAPI) { 6 | } 7 | 8 | PGShaderLib::~PGShaderLib() { 9 | for (auto pair : m_Shaders) { 10 | delete (pair.second); 11 | } 12 | } 13 | 14 | ShaderRef PGShaderLib::LoadShaderFromDisk(const std::filesystem::path& shaderFilePath) { 15 | const std::string name = shaderFilePath.stem().string(); 16 | 17 | auto shaderSearch = m_Shaders.find(name); 18 | if (shaderSearch != m_Shaders.end()) { 19 | return shaderSearch->second; 20 | } 21 | 22 | std::filesystem::file_time_type fileTime = std::filesystem::last_write_time(shaderFilePath); 23 | m_ShaderFileLastWriteTimeMap[shaderFilePath.string()] = fileTime; 24 | 25 | PGShader* shader = new PGShader(); 26 | shader->LoadFromFilename(shaderFilePath.string()); 27 | m_Shaders[name] = shader; 28 | return shader; 29 | } 30 | 31 | void PGShaderLib::ReloadShadersIfNeeded() { 32 | for (const auto& pair : m_ShaderFileLastWriteTimeMap) { 33 | std::filesystem::path filepath(pair.first); 34 | std::error_code errorCode; 35 | std::filesystem::file_time_type newFileTime = std::filesystem::last_write_time(filepath, errorCode); 36 | 37 | if (!errorCode.value()) { 38 | std::filesystem::file_time_type oldFileTime = pair.second; 39 | if (newFileTime.time_since_epoch() - oldFileTime.time_since_epoch() > std::chrono::seconds(0)) { 40 | auto shaderSearch = m_Shaders.find(filepath.stem().string()); 41 | if (shaderSearch != m_Shaders.end()) { 42 | shaderSearch->second->needsUpdate = true; 43 | m_ShaderFileLastWriteTimeMap[filepath.string()] = newFileTime; 44 | } 45 | else { 46 | PG_ASSERT(false, "Shader file cannot found!"); 47 | } 48 | } 49 | } else { 50 | PG_LOG_WARNING("Get file last write time error! Code value: %d, message: %s", errorCode.value(), errorCode.message().c_str()); 51 | } 52 | } 53 | } 54 | 55 | void PGShaderLib::LoadDefaultShaders() { 56 | std::string shaderDirectory = "../PlaygroundEngine/Assets/Shaders/"; 57 | for (const auto& entry : std::filesystem::directory_iterator(shaderDirectory)) { 58 | if (!entry.path().extension().compare(".hlsl")) { 59 | LoadShaderFromDisk(entry.path()); 60 | } 61 | } 62 | } 63 | 64 | ShaderRef PGShaderLib::GetDefaultShader(const std::string& name) { 65 | return m_Shaders[name]; 66 | } 67 | 68 | -------------------------------------------------------------------------------- /PlaygroundEngine/Renderer/PGShaderLib.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../Core.h" 4 | #include "PGShader.h" 5 | 6 | #include 7 | #include 8 | 9 | typedef PGShader* ShaderRef; 10 | 11 | class PG_API PGShaderLib { 12 | public: 13 | PGShaderLib(HWRendererAPI* rendererAPI); 14 | ~PGShaderLib(); 15 | 16 | ShaderRef LoadShaderFromDisk(const std::filesystem::path& shaderFileName); 17 | void ReloadShadersIfNeeded(); 18 | void LoadDefaultShaders(); 19 | ShaderRef GetDefaultShader(const std::string& name); 20 | 21 | private: 22 | HWRendererAPI* m_RendererAPI; 23 | std::unordered_map m_Shaders; 24 | std::unordered_map m_ShaderFileLastWriteTimeMap; 25 | }; 26 | 27 | -------------------------------------------------------------------------------- /PlaygroundEngine/Renderer/PGTexture.cpp: -------------------------------------------------------------------------------- 1 | #include "PGTexture.h" 2 | #include "PGRenderer.h" 3 | 4 | #include "../Utility/tinyddsloader.h" 5 | 6 | #define STB_IMAGE_IMPLEMENTATION 7 | #include "../Utility/stb_image.h" 8 | 9 | PGTexture* PGTexture::CreateTexture2D(const std::string& filepath, bool generateMips) { 10 | int32_t width, height, bytesPerPixel; 11 | void* imageData = stbi_load(filepath.c_str(), &width, &height, &bytesPerPixel, STBI_rgb_alpha); 12 | 13 | // Subresources 14 | SubresourceData subresource; 15 | subresource.data = imageData; 16 | subresource.memPitch = width * 4; 17 | subresource.memSlicePitch = 0; 18 | 19 | 20 | Texture2DDesc initParams = {}; 21 | initParams.arraySize = 1; 22 | initParams.format = DXGI_FORMAT_R8G8B8A8_UNORM; 23 | initParams.width = width; 24 | initParams.height = height; 25 | initParams.sampleCount = 1; 26 | initParams.mipCount = generateMips ? 0 : 1; 27 | initParams.flags = HWResourceFlags::BIND_SHADER_RESOURCE; 28 | if (generateMips) { 29 | initParams.flags |= (HWResourceFlags::MISC_GENERATE_MIPS | HWResourceFlags::BIND_RENDER_TARGET); 30 | } else { 31 | initParams.flags |= HWResourceFlags::USAGE_IMMUTABLE; 32 | } 33 | 34 | PGTexture* texture = new PGTexture(&initParams, &subresource, generateMips); 35 | 36 | stbi_image_free(imageData); 37 | return texture; 38 | } 39 | 40 | PGTexture* PGTexture::CreateTextureFromDDSFile(const std::string& filepath) { 41 | tinyddsloader::DDSFile ddsFile; 42 | tinyddsloader::Result result = ddsFile.Load(filepath.c_str()); 43 | PG_ASSERT(result == tinyddsloader::Result::Success, "Error at loading dds file"); 44 | 45 | uint32_t arraySize = ddsFile.GetArraySize(); 46 | uint32_t mipCount = ddsFile.GetMipCount(); 47 | 48 | // Subresources 49 | SubresourceData* subresources = (SubresourceData*) alloca(sizeof(SubresourceData) * arraySize * mipCount); 50 | for (uint32_t arrayIndex = 0; arrayIndex < arraySize; ++arrayIndex) { 51 | for (uint32_t mipIndex = 0; mipIndex < mipCount; ++mipIndex) { 52 | const tinyddsloader::DDSFile::ImageData* imageData = ddsFile.GetImageData(mipIndex, arrayIndex); 53 | SubresourceData* subresource = subresources + (arrayIndex * mipCount + mipIndex); 54 | subresource->data = imageData->m_mem; 55 | subresource->memPitch = imageData->m_memPitch; 56 | subresource->memSlicePitch = imageData->m_memSlicePitch; 57 | } 58 | } 59 | 60 | 61 | Texture2DDesc initParams = {}; 62 | initParams.arraySize = arraySize; 63 | initParams.format = (DXGI_FORMAT) ddsFile.GetFormat(); 64 | initParams.width = ddsFile.GetWidth(); 65 | initParams.height = ddsFile.GetHeight(); 66 | initParams.sampleCount = 1; 67 | initParams.mipCount = mipCount; 68 | initParams.flags = HWResourceFlags::BIND_SHADER_RESOURCE | HWResourceFlags::USAGE_IMMUTABLE; 69 | 70 | if (ddsFile.IsCubemap()) { 71 | initParams.flags |= HWResourceFlags::MISC_TEXTURE_CUBE; 72 | } 73 | 74 | PGTexture* texture = new PGTexture(&initParams, subresources, false); 75 | return texture; 76 | } 77 | 78 | PGTexture::PGTexture(Texture2DDesc* initParams, SubresourceData* subresources, bool generateMips) { 79 | HWRendererAPI* rendererAPI = PGRenderer::GetRendererAPI(); 80 | HWResourceViewDesc resourceViewDesc; 81 | resourceViewDesc.firstArraySlice = 0; 82 | resourceViewDesc.sliceArrayCount = (uint32_t) initParams->arraySize; 83 | resourceViewDesc.firstMip = 0; 84 | if (generateMips) { 85 | resourceViewDesc.mipCount = -1; 86 | m_HWTexture2D = rendererAPI->CreateTexture2D(initParams, nullptr); 87 | m_HWShaderResourceView = rendererAPI->CreateShaderResourceView(m_HWTexture2D, resourceViewDesc); 88 | 89 | rendererAPI->UpdateSubresource(m_HWTexture2D, 0, nullptr, subresources[0]); 90 | rendererAPI->GenerateMips(m_HWShaderResourceView); 91 | } else { 92 | resourceViewDesc.mipCount = (uint32_t) initParams->mipCount; 93 | m_HWTexture2D = rendererAPI->CreateTexture2D(initParams, subresources); 94 | m_HWShaderResourceView = rendererAPI->CreateShaderResourceView(m_HWTexture2D, resourceViewDesc); 95 | } 96 | } 97 | 98 | 99 | PGTexture::~PGTexture() { 100 | delete m_HWShaderResourceView; 101 | delete m_HWTexture2D; 102 | } 103 | 104 | -------------------------------------------------------------------------------- /PlaygroundEngine/Renderer/PGTexture.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../Core.h" 4 | #include "HWRendererAPI.h" 5 | #include "../PGResource.h" 6 | 7 | #include 8 | 9 | class PGTexture : public IResource { 10 | public: 11 | PGTexture(Texture2DDesc* initParams, SubresourceData* subresources, bool generateMips); 12 | ~PGTexture(); 13 | 14 | static PGTexture* CreateTexture2D(const std::string& filepath, bool generateMips); 15 | static PGTexture* CreateTextureFromDDSFile(const std::string& filepath); 16 | 17 | inline HWTexture2D* GetHWTexture() { return m_HWTexture2D; } 18 | inline HWShaderResourceView* GetHWResourceView() { return m_HWShaderResourceView; } 19 | 20 | private: 21 | 22 | HWTexture2D* m_HWTexture2D = nullptr; 23 | HWShaderResourceView* m_HWShaderResourceView = nullptr; 24 | 25 | }; 26 | 27 | -------------------------------------------------------------------------------- /PlaygroundEngine/Renderer/SceneRenderPass.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "HWRendererAPI.h" 4 | #include "PGRenderList.h" 5 | 6 | #include "BaseRenderPass.h" 7 | #include "../PGProfiler.h" 8 | 9 | class SceneRenderPass : public RenderPass { 10 | public: 11 | virtual ~SceneRenderPass() = default; 12 | 13 | virtual void Execute(HWRendererAPI* rendererAPI, PGRenderView& renderView, SceneRenderPassType scenePassType, bool clearOutputTargets, 14 | const char* eventName) { 15 | rendererAPI->BeginEvent(eventName); 16 | rendererAPI->SetRenderTargets(m_RenderTargets, MAX_RENDER_TARGET_COUNT, m_DepthStencilView); 17 | if (clearOutputTargets) { 18 | for (size_t i = 0; i < MAX_RENDER_TARGET_COUNT; ++i) { 19 | HWRenderTargetView* renderTarget = m_RenderTargets[i]; 20 | if (renderTarget) { 21 | float color[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; 22 | rendererAPI->ClearRenderTarget(m_RenderTargets[0], color); 23 | } 24 | } 25 | if (m_DepthStencilView) { 26 | rendererAPI->ClearDepthStencilView(m_DepthStencilView, false, 1.0f, 0); 27 | } 28 | } 29 | rendererAPI->SetViewport(&m_Viewport); 30 | rendererAPI->SetShaderResourcesVS(0, m_ShaderResourcesVS, MAX_SHADER_RESOURCE_COUNT); 31 | rendererAPI->SetShaderResourcesPS(0, m_ShaderResourcesPS, MAX_SHADER_RESOURCE_COUNT); 32 | 33 | renderView.UpdatePerViewConstantBuffer(rendererAPI); 34 | RenderScene(rendererAPI, renderView.renderList, scenePassType); 35 | rendererAPI->EndEvent(); 36 | } 37 | }; 38 | -------------------------------------------------------------------------------- /PlaygroundEngine/Renderer/ShadowMapStage.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PGShaderLib.h" 4 | #include "SceneRenderPass.h" 5 | 6 | class ShadowGenStage { 7 | public: 8 | void Initialize(HWRendererAPI* rendererAPI); 9 | void Execute(HWRendererAPI* rendererAPI, PGRenderView renderViews[MAX_SHADOW_CASCADE_COUNT], const PGRendererConfig& rendererConfig, bool clear = true); 10 | void ExecutePointLightShadow(HWRendererAPI* rendererAPI, GPUResource* pointLightShadowTexture, PGRenderView& renderView, const PGRendererConfig& rendererConfig, uint32_t pointLightShadowIndex, uint32_t cubeMapFaceIndex, bool clear = true); 11 | void ExecuteSpotLightShadow(HWRendererAPI* rendererAPI, GPUResource* pointLightShadowTexture, PGRenderView& renderView, const PGRendererConfig& rendererConfig, uint32_t spotLightShadowIndex, bool clear = true); 12 | 13 | 14 | void SetShadowMapTarget(HWRendererAPI* rendererAPI, const PGRendererConfig& rendererConfig, 15 | HWTexture2D* directionalShadowMapTexture, HWTexture2D* pointShadowMapTexture, HWTexture2D* spotShadowMapTexture); 16 | 17 | private: 18 | HWDepthStencilView* m_ShadowMapTargets[MAX_SHADOW_CASCADE_COUNT] = {0}; 19 | 20 | HWDepthStencilView* m_PointShadowMapTargets[MAX_POINT_LIGHT_COUNT * 6] = {0}; 21 | HWDepthStencilView* m_SpotShadowMapTargets[MAX_SPOT_LIGHT_COUNT] = {0}; 22 | 23 | HWViewport m_ShadowMapViewport; 24 | }; 25 | 26 | -------------------------------------------------------------------------------- /PlaygroundEngine/Renderer/Skybox.cpp: -------------------------------------------------------------------------------- 1 | #include "Skybox.h" 2 | #include "../Assets/Shaders/ShaderDefinitions.h" 3 | #include "../Math/math_vector.h" 4 | #include "../PGProfiler.h" 5 | 6 | const Vector3 vertices[] = { 7 | { -1, 1, 1 }, 8 | { -1, 1, -1 }, 9 | { -1, -1, -1 }, 10 | { -1, -1, 1 }, 11 | { -1, 1, -1 }, 12 | { 1, 1, -1 }, 13 | { 1, -1, -1 }, 14 | { -1, -1, -1 }, 15 | { 1, 1, -1 }, 16 | { 1, 1, 1 }, 17 | { 1, -1, 1 }, 18 | { 1, -1, -1 }, 19 | { 1, 1, 1 }, 20 | { -1, 1, 1 }, 21 | { -1, -1, 1 }, 22 | { 1, -1, 1 }, 23 | { -1, -1, 1 }, 24 | { -1, -1, -1 }, 25 | { 1, -1, -1 }, 26 | { 1, -1, 1 }, 27 | { 1, 1, 1 }, 28 | { 1, 1, -1 }, 29 | { -1, 1, -1 }, 30 | { -1, 1, 1 } 31 | }; 32 | 33 | const uint16_t indices[] = { 34 | 0, 3, 1, 35 | 1, 3, 2, 36 | 4, 7, 5, 37 | 5, 7, 6, 38 | 8, 11, 9, 39 | 9, 11, 10, 40 | 12, 15, 13, 41 | 13, 15, 14, 42 | 16, 19, 17, 43 | 17, 19, 18, 44 | 20, 23, 21, 45 | 21, 23, 22 46 | }; 47 | 48 | Skybox::Skybox(HWRendererAPI* rendererAPI, PGShaderLib* shaderLib) { 49 | SubresourceData bufferSubresourceData = {}; 50 | bufferSubresourceData.data = vertices; 51 | m_VertexBuffer = rendererAPI->CreateBuffer(&bufferSubresourceData, sizeof(vertices), HWResourceFlags::USAGE_IMMUTABLE | HWResourceFlags::BIND_VERTEX_BUFFER); 52 | 53 | bufferSubresourceData.data = indices; 54 | m_IndexBuffer = rendererAPI->CreateBuffer(&bufferSubresourceData, sizeof(indices), HWResourceFlags::USAGE_IMMUTABLE | HWResourceFlags::BIND_INDEX_BUFFER); 55 | 56 | PGShader* shader = shaderLib->GetDefaultShader("Skybox"); 57 | HWVertexInputElement inputElements[] = { 58 | { "POSITION", 0, VertexDataFormat_FLOAT3, 0, PER_VERTEX_DATA, 0 }, 59 | }; 60 | HWInputLayoutDesc inputLayoutDesc = {}; 61 | inputLayoutDesc.elements = inputElements; 62 | inputLayoutDesc.elementCount = ARRAYSIZE(inputElements); 63 | 64 | HWRasterizerDesc rasterizerDesc = {}; 65 | rasterizerDesc.cullMode = CULL_NONE; // We need to disable back-face culling because we are rendering a cube from inside 66 | 67 | HWDepthStencilDesc depthStencilDesc = {}; 68 | depthStencilDesc.depthFunc = COMPARISON_LESS_EQUAL; // Skybox z value is always 1. 69 | 70 | HWGraphicsPipelineStateDesc pipelineDesc; 71 | pipelineDesc.rasterizerDesc = rasterizerDesc; 72 | pipelineDesc.depthStencilDesc = depthStencilDesc; 73 | pipelineDesc.inputLayoutDesc = inputLayoutDesc; 74 | pipelineDesc.primitiveTopology = PRIMITIVE_TOPOLOGY_TRIANGLELIST; 75 | 76 | pipelineDesc.vertexShader = shader->GetVertexBytecode(); 77 | pipelineDesc.pixelShader = shader->GetPixelBytecode(); 78 | 79 | m_PipelineState = rendererAPI->CreateGraphicsPipelineState(pipelineDesc); 80 | 81 | } 82 | 83 | Skybox::~Skybox() { 84 | delete m_VertexBuffer; 85 | delete m_IndexBuffer; 86 | delete m_PipelineState; 87 | } 88 | 89 | void Skybox::RenderSkybox(HWRendererAPI* rendererAPI, PGTexture* skyboxCubemap) { 90 | PG_PROFILE_FUNCTION(); 91 | rendererAPI->BeginEvent("SKYBOX"); 92 | uint32_t offset = 0; 93 | uint32_t stride = sizeof(Vector3); 94 | rendererAPI->SetVertexBuffers(&m_VertexBuffer, 1, &stride, &offset); 95 | rendererAPI->SetIndexBuffer(m_IndexBuffer, sizeof(indices[0]), 0); 96 | rendererAPI->SetGraphicsPipelineState(m_PipelineState); 97 | 98 | HWShaderResourceView* skyboxView = skyboxCubemap->GetHWResourceView(); 99 | rendererAPI->SetShaderResourcesPS(SKYBOX_TEXTURECUBE_SLOT, &skyboxView, 1); 100 | 101 | rendererAPI->DrawIndexed(ARRAYSIZE(indices), 0, 0); 102 | rendererAPI->EndEvent(); 103 | } 104 | -------------------------------------------------------------------------------- /PlaygroundEngine/Renderer/Skybox.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../Core.h" 4 | #include "HWRendererAPI.h" 5 | #include "PGTexture.h" 6 | #include "PGShaderLib.h" 7 | 8 | class Skybox { 9 | public: 10 | Skybox(HWRendererAPI* rendererAPI, PGShaderLib* shaderLib); 11 | ~Skybox(); 12 | 13 | void RenderSkybox(HWRendererAPI* rendererAPI, PGTexture* skyboxCube); 14 | 15 | private: 16 | HWBuffer* m_VertexBuffer; 17 | HWBuffer* m_IndexBuffer; 18 | HWGraphicsPipelineState* m_PipelineState; 19 | }; 20 | -------------------------------------------------------------------------------- /PlaygroundEngine/Scene.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PGCamera.h" 4 | #include "Renderer/Skybox.h" 5 | 6 | struct PGDirectionalLight { 7 | Vector3 direction; 8 | Vector3 color; 9 | float intensity; 10 | }; 11 | 12 | struct PGPointLight { 13 | Vector3 position; 14 | Vector3 color; 15 | float intensity; 16 | }; 17 | 18 | struct PGSpotLight { 19 | Vector3 position; 20 | float minConeAngleCos; 21 | Vector3 direction; 22 | float maxConeAngleCos; 23 | Vector3 color; 24 | float intensity; 25 | }; 26 | 27 | struct PGSceneObject { 28 | MeshRef mesh; 29 | Transform transform; 30 | }; 31 | 32 | struct PGScene { 33 | PGCamera* camera; 34 | PGDirectionalLight directionalLight; 35 | std::vector pointLights; 36 | std::vector spotLights; 37 | PGTexture* skyboxTexture; 38 | Box boundingBox; 39 | std::vector sceneObjects; 40 | }; 41 | 42 | -------------------------------------------------------------------------------- /PlaygroundEngine/Transform.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Math/math_util.h" 4 | 5 | class Transform { 6 | public: 7 | Transform() { 8 | position = Vector3(0.0f, 0.0f, 0.0f); 9 | translateMatrix = IdentityMatrix; 10 | rotationMatrix = IdentityMatrix; 11 | scaleMatrix = IdentityMatrix; 12 | } 13 | 14 | Transform(const Vector3& position, const Matrix4& translateMatrix, const Matrix4& rotationMatrix, const Matrix4& scaleMatrix) 15 | : position(position), translateMatrix(translateMatrix), rotationMatrix(rotationMatrix), scaleMatrix(scaleMatrix) { 16 | } 17 | 18 | inline void Translate(const Vector3& translateVector) { 19 | // World space translation 20 | position += translateVector; 21 | } 22 | 23 | inline void Scale(const Vector3& scaleVector) { 24 | Matrix4 matrix = ScaleMatrix(scaleVector); 25 | scaleMatrix = matrix * scaleMatrix; 26 | } 27 | 28 | inline void RotateXAxis(float degreeRadians) { 29 | Matrix4 matrix = RotateMatrixXAxis(degreeRadians); 30 | rotationMatrix = matrix * rotationMatrix; 31 | } 32 | 33 | inline void RotateYAxis(float degreeRadians) { 34 | Matrix4 matrix = RotateMatrixYAxis(degreeRadians); 35 | rotationMatrix = matrix * rotationMatrix; 36 | } 37 | 38 | inline void RotateZAxis(float degreeRadians) { 39 | Matrix4 matrix = RotateMatrixZAxis(degreeRadians); 40 | rotationMatrix = matrix * rotationMatrix; 41 | } 42 | 43 | inline Matrix4 GetTransformMatrix() { 44 | Matrix4 translateMatrix = TranslateMatrix(position); 45 | return translateMatrix * rotationMatrix * scaleMatrix; 46 | } 47 | 48 | 49 | public: 50 | Vector3 position; 51 | 52 | Matrix4 translateMatrix; // Currently we don't use this 53 | Matrix4 rotationMatrix; 54 | Matrix4 scaleMatrix; 55 | }; 56 | 57 | -------------------------------------------------------------------------------- /PlaygroundEngine/Utility/rapidjson/cursorstreamwrapper.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_CURSORSTREAMWRAPPER_H_ 16 | #define RAPIDJSON_CURSORSTREAMWRAPPER_H_ 17 | 18 | #include "stream.h" 19 | 20 | #if defined(__GNUC__) 21 | RAPIDJSON_DIAG_PUSH 22 | RAPIDJSON_DIAG_OFF(effc++) 23 | #endif 24 | 25 | #if defined(_MSC_VER) && _MSC_VER <= 1800 26 | RAPIDJSON_DIAG_PUSH 27 | RAPIDJSON_DIAG_OFF(4702) // unreachable code 28 | RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated 29 | #endif 30 | 31 | RAPIDJSON_NAMESPACE_BEGIN 32 | 33 | 34 | //! Cursor stream wrapper for counting line and column number if error exists. 35 | /*! 36 | \tparam InputStream Any stream that implements Stream Concept 37 | */ 38 | template > 39 | class CursorStreamWrapper : public GenericStreamWrapper { 40 | public: 41 | typedef typename Encoding::Ch Ch; 42 | 43 | CursorStreamWrapper(InputStream& is): 44 | GenericStreamWrapper(is), line_(1), col_(0) {} 45 | 46 | // counting line and column number 47 | Ch Take() { 48 | Ch ch = this->is_.Take(); 49 | if(ch == '\n') { 50 | line_ ++; 51 | col_ = 0; 52 | } else { 53 | col_ ++; 54 | } 55 | return ch; 56 | } 57 | 58 | //! Get the error line number, if error exists. 59 | size_t GetLine() const { return line_; } 60 | //! Get the error column number, if error exists. 61 | size_t GetColumn() const { return col_; } 62 | 63 | private: 64 | size_t line_; //!< Current Line 65 | size_t col_; //!< Current Column 66 | }; 67 | 68 | #if defined(_MSC_VER) && _MSC_VER <= 1800 69 | RAPIDJSON_DIAG_POP 70 | #endif 71 | 72 | #if defined(__GNUC__) 73 | RAPIDJSON_DIAG_POP 74 | #endif 75 | 76 | RAPIDJSON_NAMESPACE_END 77 | 78 | #endif // RAPIDJSON_CURSORSTREAMWRAPPER_H_ 79 | -------------------------------------------------------------------------------- /PlaygroundEngine/Utility/rapidjson/error/en.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_ERROR_EN_H_ 16 | #define RAPIDJSON_ERROR_EN_H_ 17 | 18 | #include "error.h" 19 | 20 | #ifdef __clang__ 21 | RAPIDJSON_DIAG_PUSH 22 | RAPIDJSON_DIAG_OFF(switch-enum) 23 | RAPIDJSON_DIAG_OFF(covered-switch-default) 24 | #endif 25 | 26 | RAPIDJSON_NAMESPACE_BEGIN 27 | 28 | //! Maps error code of parsing into error message. 29 | /*! 30 | \ingroup RAPIDJSON_ERRORS 31 | \param parseErrorCode Error code obtained in parsing. 32 | \return the error message. 33 | \note User can make a copy of this function for localization. 34 | Using switch-case is safer for future modification of error codes. 35 | */ 36 | inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode) { 37 | switch (parseErrorCode) { 38 | case kParseErrorNone: return RAPIDJSON_ERROR_STRING("No error."); 39 | 40 | case kParseErrorDocumentEmpty: return RAPIDJSON_ERROR_STRING("The document is empty."); 41 | case kParseErrorDocumentRootNotSingular: return RAPIDJSON_ERROR_STRING("The document root must not be followed by other values."); 42 | 43 | case kParseErrorValueInvalid: return RAPIDJSON_ERROR_STRING("Invalid value."); 44 | 45 | case kParseErrorObjectMissName: return RAPIDJSON_ERROR_STRING("Missing a name for object member."); 46 | case kParseErrorObjectMissColon: return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member."); 47 | case kParseErrorObjectMissCommaOrCurlyBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member."); 48 | 49 | case kParseErrorArrayMissCommaOrSquareBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element."); 50 | 51 | case kParseErrorStringUnicodeEscapeInvalidHex: return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string."); 52 | case kParseErrorStringUnicodeSurrogateInvalid: return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid."); 53 | case kParseErrorStringEscapeInvalid: return RAPIDJSON_ERROR_STRING("Invalid escape character in string."); 54 | case kParseErrorStringMissQuotationMark: return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string."); 55 | case kParseErrorStringInvalidEncoding: return RAPIDJSON_ERROR_STRING("Invalid encoding in string."); 56 | 57 | case kParseErrorNumberTooBig: return RAPIDJSON_ERROR_STRING("Number too big to be stored in double."); 58 | case kParseErrorNumberMissFraction: return RAPIDJSON_ERROR_STRING("Miss fraction part in number."); 59 | case kParseErrorNumberMissExponent: return RAPIDJSON_ERROR_STRING("Miss exponent in number."); 60 | 61 | case kParseErrorTermination: return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error."); 62 | case kParseErrorUnspecificSyntaxError: return RAPIDJSON_ERROR_STRING("Unspecific syntax error."); 63 | 64 | default: return RAPIDJSON_ERROR_STRING("Unknown error."); 65 | } 66 | } 67 | 68 | RAPIDJSON_NAMESPACE_END 69 | 70 | #ifdef __clang__ 71 | RAPIDJSON_DIAG_POP 72 | #endif 73 | 74 | #endif // RAPIDJSON_ERROR_EN_H_ 75 | -------------------------------------------------------------------------------- /PlaygroundEngine/Utility/rapidjson/filereadstream.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_FILEREADSTREAM_H_ 16 | #define RAPIDJSON_FILEREADSTREAM_H_ 17 | 18 | #include "stream.h" 19 | #include 20 | 21 | #ifdef __clang__ 22 | RAPIDJSON_DIAG_PUSH 23 | RAPIDJSON_DIAG_OFF(padded) 24 | RAPIDJSON_DIAG_OFF(unreachable-code) 25 | RAPIDJSON_DIAG_OFF(missing-noreturn) 26 | #endif 27 | 28 | RAPIDJSON_NAMESPACE_BEGIN 29 | 30 | //! File byte stream for input using fread(). 31 | /*! 32 | \note implements Stream concept 33 | */ 34 | class FileReadStream { 35 | public: 36 | typedef char Ch; //!< Character type (byte). 37 | 38 | //! Constructor. 39 | /*! 40 | \param fp File pointer opened for read. 41 | \param buffer user-supplied buffer. 42 | \param bufferSize size of buffer in bytes. Must >=4 bytes. 43 | */ 44 | FileReadStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { 45 | RAPIDJSON_ASSERT(fp_ != 0); 46 | RAPIDJSON_ASSERT(bufferSize >= 4); 47 | Read(); 48 | } 49 | 50 | Ch Peek() const { return *current_; } 51 | Ch Take() { Ch c = *current_; Read(); return c; } 52 | size_t Tell() const { return count_ + static_cast(current_ - buffer_); } 53 | 54 | // Not implemented 55 | void Put(Ch) { RAPIDJSON_ASSERT(false); } 56 | void Flush() { RAPIDJSON_ASSERT(false); } 57 | Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } 58 | size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } 59 | 60 | // For encoding detection only. 61 | const Ch* Peek4() const { 62 | return (current_ + 4 - !eof_ <= bufferLast_) ? current_ : 0; 63 | } 64 | 65 | private: 66 | void Read() { 67 | if (current_ < bufferLast_) 68 | ++current_; 69 | else if (!eof_) { 70 | count_ += readCount_; 71 | readCount_ = std::fread(buffer_, 1, bufferSize_, fp_); 72 | bufferLast_ = buffer_ + readCount_ - 1; 73 | current_ = buffer_; 74 | 75 | if (readCount_ < bufferSize_) { 76 | buffer_[readCount_] = '\0'; 77 | ++bufferLast_; 78 | eof_ = true; 79 | } 80 | } 81 | } 82 | 83 | std::FILE* fp_; 84 | Ch *buffer_; 85 | size_t bufferSize_; 86 | Ch *bufferLast_; 87 | Ch *current_; 88 | size_t readCount_; 89 | size_t count_; //!< Number of characters read 90 | bool eof_; 91 | }; 92 | 93 | RAPIDJSON_NAMESPACE_END 94 | 95 | #ifdef __clang__ 96 | RAPIDJSON_DIAG_POP 97 | #endif 98 | 99 | #endif // RAPIDJSON_FILESTREAM_H_ 100 | -------------------------------------------------------------------------------- /PlaygroundEngine/Utility/rapidjson/filewritestream.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_FILEWRITESTREAM_H_ 16 | #define RAPIDJSON_FILEWRITESTREAM_H_ 17 | 18 | #include "stream.h" 19 | #include 20 | 21 | #ifdef __clang__ 22 | RAPIDJSON_DIAG_PUSH 23 | RAPIDJSON_DIAG_OFF(unreachable-code) 24 | #endif 25 | 26 | RAPIDJSON_NAMESPACE_BEGIN 27 | 28 | //! Wrapper of C file stream for output using fwrite(). 29 | /*! 30 | \note implements Stream concept 31 | */ 32 | class FileWriteStream { 33 | public: 34 | typedef char Ch; //!< Character type. Only support char. 35 | 36 | FileWriteStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferEnd_(buffer + bufferSize), current_(buffer_) { 37 | RAPIDJSON_ASSERT(fp_ != 0); 38 | } 39 | 40 | void Put(char c) { 41 | if (current_ >= bufferEnd_) 42 | Flush(); 43 | 44 | *current_++ = c; 45 | } 46 | 47 | void PutN(char c, size_t n) { 48 | size_t avail = static_cast(bufferEnd_ - current_); 49 | while (n > avail) { 50 | std::memset(current_, c, avail); 51 | current_ += avail; 52 | Flush(); 53 | n -= avail; 54 | avail = static_cast(bufferEnd_ - current_); 55 | } 56 | 57 | if (n > 0) { 58 | std::memset(current_, c, n); 59 | current_ += n; 60 | } 61 | } 62 | 63 | void Flush() { 64 | if (current_ != buffer_) { 65 | size_t result = std::fwrite(buffer_, 1, static_cast(current_ - buffer_), fp_); 66 | if (result < static_cast(current_ - buffer_)) { 67 | // failure deliberately ignored at this time 68 | // added to avoid warn_unused_result build errors 69 | } 70 | current_ = buffer_; 71 | } 72 | } 73 | 74 | // Not implemented 75 | char Peek() const { RAPIDJSON_ASSERT(false); return 0; } 76 | char Take() { RAPIDJSON_ASSERT(false); return 0; } 77 | size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } 78 | char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } 79 | size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; } 80 | 81 | private: 82 | // Prohibit copy constructor & assignment operator. 83 | FileWriteStream(const FileWriteStream&); 84 | FileWriteStream& operator=(const FileWriteStream&); 85 | 86 | std::FILE* fp_; 87 | char *buffer_; 88 | char *bufferEnd_; 89 | char *current_; 90 | }; 91 | 92 | //! Implement specialized version of PutN() with memset() for better performance. 93 | template<> 94 | inline void PutN(FileWriteStream& stream, char c, size_t n) { 95 | stream.PutN(c, n); 96 | } 97 | 98 | RAPIDJSON_NAMESPACE_END 99 | 100 | #ifdef __clang__ 101 | RAPIDJSON_DIAG_POP 102 | #endif 103 | 104 | #endif // RAPIDJSON_FILESTREAM_H_ 105 | -------------------------------------------------------------------------------- /PlaygroundEngine/Utility/rapidjson/fwd.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_FWD_H_ 16 | #define RAPIDJSON_FWD_H_ 17 | 18 | #include "rapidjson.h" 19 | 20 | RAPIDJSON_NAMESPACE_BEGIN 21 | 22 | // encodings.h 23 | 24 | template struct UTF8; 25 | template struct UTF16; 26 | template struct UTF16BE; 27 | template struct UTF16LE; 28 | template struct UTF32; 29 | template struct UTF32BE; 30 | template struct UTF32LE; 31 | template struct ASCII; 32 | template struct AutoUTF; 33 | 34 | template 35 | struct Transcoder; 36 | 37 | // allocators.h 38 | 39 | class CrtAllocator; 40 | 41 | template 42 | class MemoryPoolAllocator; 43 | 44 | // stream.h 45 | 46 | template 47 | struct GenericStringStream; 48 | 49 | typedef GenericStringStream > StringStream; 50 | 51 | template 52 | struct GenericInsituStringStream; 53 | 54 | typedef GenericInsituStringStream > InsituStringStream; 55 | 56 | // stringbuffer.h 57 | 58 | template 59 | class GenericStringBuffer; 60 | 61 | typedef GenericStringBuffer, CrtAllocator> StringBuffer; 62 | 63 | // filereadstream.h 64 | 65 | class FileReadStream; 66 | 67 | // filewritestream.h 68 | 69 | class FileWriteStream; 70 | 71 | // memorybuffer.h 72 | 73 | template 74 | struct GenericMemoryBuffer; 75 | 76 | typedef GenericMemoryBuffer MemoryBuffer; 77 | 78 | // memorystream.h 79 | 80 | struct MemoryStream; 81 | 82 | // reader.h 83 | 84 | template 85 | struct BaseReaderHandler; 86 | 87 | template 88 | class GenericReader; 89 | 90 | typedef GenericReader, UTF8, CrtAllocator> Reader; 91 | 92 | // writer.h 93 | 94 | template 95 | class Writer; 96 | 97 | // prettywriter.h 98 | 99 | template 100 | class PrettyWriter; 101 | 102 | // document.h 103 | 104 | template 105 | class GenericMember; 106 | 107 | template 108 | class GenericMemberIterator; 109 | 110 | template 111 | struct GenericStringRef; 112 | 113 | template 114 | class GenericValue; 115 | 116 | typedef GenericValue, MemoryPoolAllocator > Value; 117 | 118 | template 119 | class GenericDocument; 120 | 121 | typedef GenericDocument, MemoryPoolAllocator, CrtAllocator> Document; 122 | 123 | // pointer.h 124 | 125 | template 126 | class GenericPointer; 127 | 128 | typedef GenericPointer Pointer; 129 | 130 | // schema.h 131 | 132 | template 133 | class IGenericRemoteSchemaDocumentProvider; 134 | 135 | template 136 | class GenericSchemaDocument; 137 | 138 | typedef GenericSchemaDocument SchemaDocument; 139 | typedef IGenericRemoteSchemaDocumentProvider IRemoteSchemaDocumentProvider; 140 | 141 | template < 142 | typename SchemaDocumentType, 143 | typename OutputHandler, 144 | typename StateAllocator> 145 | class GenericSchemaValidator; 146 | 147 | typedef GenericSchemaValidator, void>, CrtAllocator> SchemaValidator; 148 | 149 | RAPIDJSON_NAMESPACE_END 150 | 151 | #endif // RAPIDJSON_RAPIDJSONFWD_H_ 152 | -------------------------------------------------------------------------------- /PlaygroundEngine/Utility/rapidjson/internal/clzll.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_CLZLL_H_ 16 | #define RAPIDJSON_CLZLL_H_ 17 | 18 | #include "../rapidjson.h" 19 | 20 | #if defined(_MSC_VER) 21 | #include 22 | #if defined(_WIN64) 23 | #pragma intrinsic(_BitScanReverse64) 24 | #else 25 | #pragma intrinsic(_BitScanReverse) 26 | #endif 27 | #endif 28 | 29 | RAPIDJSON_NAMESPACE_BEGIN 30 | namespace internal { 31 | 32 | inline uint32_t clzll(uint64_t x) { 33 | // Passing 0 to __builtin_clzll is UB in GCC and results in an 34 | // infinite loop in the software implementation. 35 | RAPIDJSON_ASSERT(x != 0); 36 | 37 | #if defined(_MSC_VER) 38 | unsigned long r = 0; 39 | #if defined(_WIN64) 40 | _BitScanReverse64(&r, x); 41 | #else 42 | // Scan the high 32 bits. 43 | if (_BitScanReverse(&r, static_cast(x >> 32))) 44 | return 63 - (r + 32); 45 | 46 | // Scan the low 32 bits. 47 | _BitScanReverse(&r, static_cast(x & 0xFFFFFFFF)); 48 | #endif // _WIN64 49 | 50 | return 63 - r; 51 | #elif (defined(__GNUC__) && __GNUC__ >= 4) || RAPIDJSON_HAS_BUILTIN(__builtin_clzll) 52 | // __builtin_clzll wrapper 53 | return static_cast(__builtin_clzll(x)); 54 | #else 55 | // naive version 56 | uint32_t r; 57 | while (!(x & (static_cast(1) << 63))) { 58 | x <<= 1; 59 | ++r; 60 | } 61 | 62 | return r; 63 | #endif // _MSC_VER 64 | } 65 | 66 | #define RAPIDJSON_CLZLL RAPIDJSON_NAMESPACE::internal::clzll 67 | 68 | } // namespace internal 69 | RAPIDJSON_NAMESPACE_END 70 | 71 | #endif // RAPIDJSON_CLZLL_H_ 72 | -------------------------------------------------------------------------------- /PlaygroundEngine/Utility/rapidjson/internal/ieee754.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_IEEE754_ 16 | #define RAPIDJSON_IEEE754_ 17 | 18 | #include "../rapidjson.h" 19 | 20 | RAPIDJSON_NAMESPACE_BEGIN 21 | namespace internal { 22 | 23 | class Double { 24 | public: 25 | Double() {} 26 | Double(double d) : d_(d) {} 27 | Double(uint64_t u) : u_(u) {} 28 | 29 | double Value() const { return d_; } 30 | uint64_t Uint64Value() const { return u_; } 31 | 32 | double NextPositiveDouble() const { 33 | RAPIDJSON_ASSERT(!Sign()); 34 | return Double(u_ + 1).Value(); 35 | } 36 | 37 | bool Sign() const { return (u_ & kSignMask) != 0; } 38 | uint64_t Significand() const { return u_ & kSignificandMask; } 39 | int Exponent() const { return static_cast(((u_ & kExponentMask) >> kSignificandSize) - kExponentBias); } 40 | 41 | bool IsNan() const { return (u_ & kExponentMask) == kExponentMask && Significand() != 0; } 42 | bool IsInf() const { return (u_ & kExponentMask) == kExponentMask && Significand() == 0; } 43 | bool IsNanOrInf() const { return (u_ & kExponentMask) == kExponentMask; } 44 | bool IsNormal() const { return (u_ & kExponentMask) != 0 || Significand() == 0; } 45 | bool IsZero() const { return (u_ & (kExponentMask | kSignificandMask)) == 0; } 46 | 47 | uint64_t IntegerSignificand() const { return IsNormal() ? Significand() | kHiddenBit : Significand(); } 48 | int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; } 49 | uint64_t ToBias() const { return (u_ & kSignMask) ? ~u_ + 1 : u_ | kSignMask; } 50 | 51 | static int EffectiveSignificandSize(int order) { 52 | if (order >= -1021) 53 | return 53; 54 | else if (order <= -1074) 55 | return 0; 56 | else 57 | return order + 1074; 58 | } 59 | 60 | private: 61 | static const int kSignificandSize = 52; 62 | static const int kExponentBias = 0x3FF; 63 | static const int kDenormalExponent = 1 - kExponentBias; 64 | static const uint64_t kSignMask = RAPIDJSON_UINT64_C2(0x80000000, 0x00000000); 65 | static const uint64_t kExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000); 66 | static const uint64_t kSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF); 67 | static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000); 68 | 69 | union { 70 | double d_; 71 | uint64_t u_; 72 | }; 73 | }; 74 | 75 | } // namespace internal 76 | RAPIDJSON_NAMESPACE_END 77 | 78 | #endif // RAPIDJSON_IEEE754_ 79 | -------------------------------------------------------------------------------- /PlaygroundEngine/Utility/rapidjson/internal/pow10.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_POW10_ 16 | #define RAPIDJSON_POW10_ 17 | 18 | #include "../rapidjson.h" 19 | 20 | RAPIDJSON_NAMESPACE_BEGIN 21 | namespace internal { 22 | 23 | //! Computes integer powers of 10 in double (10.0^n). 24 | /*! This function uses lookup table for fast and accurate results. 25 | \param n non-negative exponent. Must <= 308. 26 | \return 10.0^n 27 | */ 28 | inline double Pow10(int n) { 29 | static const double e[] = { // 1e-0...1e308: 309 * 8 bytes = 2472 bytes 30 | 1e+0, 31 | 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20, 32 | 1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40, 33 | 1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60, 34 | 1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80, 35 | 1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100, 36 | 1e+101,1e+102,1e+103,1e+104,1e+105,1e+106,1e+107,1e+108,1e+109,1e+110,1e+111,1e+112,1e+113,1e+114,1e+115,1e+116,1e+117,1e+118,1e+119,1e+120, 37 | 1e+121,1e+122,1e+123,1e+124,1e+125,1e+126,1e+127,1e+128,1e+129,1e+130,1e+131,1e+132,1e+133,1e+134,1e+135,1e+136,1e+137,1e+138,1e+139,1e+140, 38 | 1e+141,1e+142,1e+143,1e+144,1e+145,1e+146,1e+147,1e+148,1e+149,1e+150,1e+151,1e+152,1e+153,1e+154,1e+155,1e+156,1e+157,1e+158,1e+159,1e+160, 39 | 1e+161,1e+162,1e+163,1e+164,1e+165,1e+166,1e+167,1e+168,1e+169,1e+170,1e+171,1e+172,1e+173,1e+174,1e+175,1e+176,1e+177,1e+178,1e+179,1e+180, 40 | 1e+181,1e+182,1e+183,1e+184,1e+185,1e+186,1e+187,1e+188,1e+189,1e+190,1e+191,1e+192,1e+193,1e+194,1e+195,1e+196,1e+197,1e+198,1e+199,1e+200, 41 | 1e+201,1e+202,1e+203,1e+204,1e+205,1e+206,1e+207,1e+208,1e+209,1e+210,1e+211,1e+212,1e+213,1e+214,1e+215,1e+216,1e+217,1e+218,1e+219,1e+220, 42 | 1e+221,1e+222,1e+223,1e+224,1e+225,1e+226,1e+227,1e+228,1e+229,1e+230,1e+231,1e+232,1e+233,1e+234,1e+235,1e+236,1e+237,1e+238,1e+239,1e+240, 43 | 1e+241,1e+242,1e+243,1e+244,1e+245,1e+246,1e+247,1e+248,1e+249,1e+250,1e+251,1e+252,1e+253,1e+254,1e+255,1e+256,1e+257,1e+258,1e+259,1e+260, 44 | 1e+261,1e+262,1e+263,1e+264,1e+265,1e+266,1e+267,1e+268,1e+269,1e+270,1e+271,1e+272,1e+273,1e+274,1e+275,1e+276,1e+277,1e+278,1e+279,1e+280, 45 | 1e+281,1e+282,1e+283,1e+284,1e+285,1e+286,1e+287,1e+288,1e+289,1e+290,1e+291,1e+292,1e+293,1e+294,1e+295,1e+296,1e+297,1e+298,1e+299,1e+300, 46 | 1e+301,1e+302,1e+303,1e+304,1e+305,1e+306,1e+307,1e+308 47 | }; 48 | RAPIDJSON_ASSERT(n >= 0 && n <= 308); 49 | return e[n]; 50 | } 51 | 52 | } // namespace internal 53 | RAPIDJSON_NAMESPACE_END 54 | 55 | #endif // RAPIDJSON_POW10_ 56 | -------------------------------------------------------------------------------- /PlaygroundEngine/Utility/rapidjson/internal/strfunc.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_INTERNAL_STRFUNC_H_ 16 | #define RAPIDJSON_INTERNAL_STRFUNC_H_ 17 | 18 | #include "../stream.h" 19 | #include 20 | 21 | RAPIDJSON_NAMESPACE_BEGIN 22 | namespace internal { 23 | 24 | //! Custom strlen() which works on different character types. 25 | /*! \tparam Ch Character type (e.g. char, wchar_t, short) 26 | \param s Null-terminated input string. 27 | \return Number of characters in the string. 28 | \note This has the same semantics as strlen(), the return value is not number of Unicode codepoints. 29 | */ 30 | template 31 | inline SizeType StrLen(const Ch* s) { 32 | RAPIDJSON_ASSERT(s != 0); 33 | const Ch* p = s; 34 | while (*p) ++p; 35 | return SizeType(p - s); 36 | } 37 | 38 | template <> 39 | inline SizeType StrLen(const char* s) { 40 | return SizeType(std::strlen(s)); 41 | } 42 | 43 | template <> 44 | inline SizeType StrLen(const wchar_t* s) { 45 | return SizeType(std::wcslen(s)); 46 | } 47 | 48 | //! Returns number of code points in a encoded string. 49 | template 50 | bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) { 51 | RAPIDJSON_ASSERT(s != 0); 52 | RAPIDJSON_ASSERT(outCount != 0); 53 | GenericStringStream is(s); 54 | const typename Encoding::Ch* end = s + length; 55 | SizeType count = 0; 56 | while (is.src_ < end) { 57 | unsigned codepoint; 58 | if (!Encoding::Decode(is, &codepoint)) 59 | return false; 60 | count++; 61 | } 62 | *outCount = count; 63 | return true; 64 | } 65 | 66 | } // namespace internal 67 | RAPIDJSON_NAMESPACE_END 68 | 69 | #endif // RAPIDJSON_INTERNAL_STRFUNC_H_ 70 | -------------------------------------------------------------------------------- /PlaygroundEngine/Utility/rapidjson/internal/swap.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_INTERNAL_SWAP_H_ 16 | #define RAPIDJSON_INTERNAL_SWAP_H_ 17 | 18 | #include "../rapidjson.h" 19 | 20 | #if defined(__clang__) 21 | RAPIDJSON_DIAG_PUSH 22 | RAPIDJSON_DIAG_OFF(c++98-compat) 23 | #endif 24 | 25 | RAPIDJSON_NAMESPACE_BEGIN 26 | namespace internal { 27 | 28 | //! Custom swap() to avoid dependency on C++ header 29 | /*! \tparam T Type of the arguments to swap, should be instantiated with primitive C++ types only. 30 | \note This has the same semantics as std::swap(). 31 | */ 32 | template 33 | inline void Swap(T& a, T& b) RAPIDJSON_NOEXCEPT { 34 | T tmp = a; 35 | a = b; 36 | b = tmp; 37 | } 38 | 39 | } // namespace internal 40 | RAPIDJSON_NAMESPACE_END 41 | 42 | #if defined(__clang__) 43 | RAPIDJSON_DIAG_POP 44 | #endif 45 | 46 | #endif // RAPIDJSON_INTERNAL_SWAP_H_ 47 | -------------------------------------------------------------------------------- /PlaygroundEngine/Utility/rapidjson/istreamwrapper.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_ISTREAMWRAPPER_H_ 16 | #define RAPIDJSON_ISTREAMWRAPPER_H_ 17 | 18 | #include "stream.h" 19 | #include 20 | #include 21 | 22 | #ifdef __clang__ 23 | RAPIDJSON_DIAG_PUSH 24 | RAPIDJSON_DIAG_OFF(padded) 25 | #elif defined(_MSC_VER) 26 | RAPIDJSON_DIAG_PUSH 27 | RAPIDJSON_DIAG_OFF(4351) // new behavior: elements of array 'array' will be default initialized 28 | #endif 29 | 30 | RAPIDJSON_NAMESPACE_BEGIN 31 | 32 | //! Wrapper of \c std::basic_istream into RapidJSON's Stream concept. 33 | /*! 34 | The classes can be wrapped including but not limited to: 35 | 36 | - \c std::istringstream 37 | - \c std::stringstream 38 | - \c std::wistringstream 39 | - \c std::wstringstream 40 | - \c std::ifstream 41 | - \c std::fstream 42 | - \c std::wifstream 43 | - \c std::wfstream 44 | 45 | \tparam StreamType Class derived from \c std::basic_istream. 46 | */ 47 | 48 | template 49 | class BasicIStreamWrapper { 50 | public: 51 | typedef typename StreamType::char_type Ch; 52 | 53 | //! Constructor. 54 | /*! 55 | \param stream stream opened for read. 56 | */ 57 | BasicIStreamWrapper(StreamType &stream) : stream_(stream), buffer_(peekBuffer_), bufferSize_(4), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { 58 | Read(); 59 | } 60 | 61 | //! Constructor. 62 | /*! 63 | \param stream stream opened for read. 64 | \param buffer user-supplied buffer. 65 | \param bufferSize size of buffer in bytes. Must >=4 bytes. 66 | */ 67 | BasicIStreamWrapper(StreamType &stream, char* buffer, size_t bufferSize) : stream_(stream), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { 68 | RAPIDJSON_ASSERT(bufferSize >= 4); 69 | Read(); 70 | } 71 | 72 | Ch Peek() const { return *current_; } 73 | Ch Take() { Ch c = *current_; Read(); return c; } 74 | size_t Tell() const { return count_ + static_cast(current_ - buffer_); } 75 | 76 | // Not implemented 77 | void Put(Ch) { RAPIDJSON_ASSERT(false); } 78 | void Flush() { RAPIDJSON_ASSERT(false); } 79 | Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } 80 | size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } 81 | 82 | // For encoding detection only. 83 | const Ch* Peek4() const { 84 | return (current_ + 4 - !eof_ <= bufferLast_) ? current_ : 0; 85 | } 86 | 87 | private: 88 | BasicIStreamWrapper(); 89 | BasicIStreamWrapper(const BasicIStreamWrapper&); 90 | BasicIStreamWrapper& operator=(const BasicIStreamWrapper&); 91 | 92 | void Read() { 93 | if (current_ < bufferLast_) 94 | ++current_; 95 | else if (!eof_) { 96 | count_ += readCount_; 97 | readCount_ = bufferSize_; 98 | bufferLast_ = buffer_ + readCount_ - 1; 99 | current_ = buffer_; 100 | 101 | if (!stream_.read(buffer_, static_cast(bufferSize_))) { 102 | readCount_ = static_cast(stream_.gcount()); 103 | *(bufferLast_ = buffer_ + readCount_) = '\0'; 104 | eof_ = true; 105 | } 106 | } 107 | } 108 | 109 | StreamType &stream_; 110 | Ch peekBuffer_[4], *buffer_; 111 | size_t bufferSize_; 112 | Ch *bufferLast_; 113 | Ch *current_; 114 | size_t readCount_; 115 | size_t count_; //!< Number of characters read 116 | bool eof_; 117 | }; 118 | 119 | typedef BasicIStreamWrapper IStreamWrapper; 120 | typedef BasicIStreamWrapper WIStreamWrapper; 121 | 122 | #if defined(__clang__) || defined(_MSC_VER) 123 | RAPIDJSON_DIAG_POP 124 | #endif 125 | 126 | RAPIDJSON_NAMESPACE_END 127 | 128 | #endif // RAPIDJSON_ISTREAMWRAPPER_H_ 129 | -------------------------------------------------------------------------------- /PlaygroundEngine/Utility/rapidjson/memorybuffer.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_MEMORYBUFFER_H_ 16 | #define RAPIDJSON_MEMORYBUFFER_H_ 17 | 18 | #include "stream.h" 19 | #include "internal/stack.h" 20 | 21 | RAPIDJSON_NAMESPACE_BEGIN 22 | 23 | //! Represents an in-memory output byte stream. 24 | /*! 25 | This class is mainly for being wrapped by EncodedOutputStream or AutoUTFOutputStream. 26 | 27 | It is similar to FileWriteBuffer but the destination is an in-memory buffer instead of a file. 28 | 29 | Differences between MemoryBuffer and StringBuffer: 30 | 1. StringBuffer has Encoding but MemoryBuffer is only a byte buffer. 31 | 2. StringBuffer::GetString() returns a null-terminated string. MemoryBuffer::GetBuffer() returns a buffer without terminator. 32 | 33 | \tparam Allocator type for allocating memory buffer. 34 | \note implements Stream concept 35 | */ 36 | template 37 | struct GenericMemoryBuffer { 38 | typedef char Ch; // byte 39 | 40 | GenericMemoryBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} 41 | 42 | void Put(Ch c) { *stack_.template Push() = c; } 43 | void Flush() {} 44 | 45 | void Clear() { stack_.Clear(); } 46 | void ShrinkToFit() { stack_.ShrinkToFit(); } 47 | Ch* Push(size_t count) { return stack_.template Push(count); } 48 | void Pop(size_t count) { stack_.template Pop(count); } 49 | 50 | const Ch* GetBuffer() const { 51 | return stack_.template Bottom(); 52 | } 53 | 54 | size_t GetSize() const { return stack_.GetSize(); } 55 | 56 | static const size_t kDefaultCapacity = 256; 57 | mutable internal::Stack stack_; 58 | }; 59 | 60 | typedef GenericMemoryBuffer<> MemoryBuffer; 61 | 62 | //! Implement specialized version of PutN() with memset() for better performance. 63 | template<> 64 | inline void PutN(MemoryBuffer& memoryBuffer, char c, size_t n) { 65 | std::memset(memoryBuffer.stack_.Push(n), c, n * sizeof(c)); 66 | } 67 | 68 | RAPIDJSON_NAMESPACE_END 69 | 70 | #endif // RAPIDJSON_MEMORYBUFFER_H_ 71 | -------------------------------------------------------------------------------- /PlaygroundEngine/Utility/rapidjson/memorystream.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_MEMORYSTREAM_H_ 16 | #define RAPIDJSON_MEMORYSTREAM_H_ 17 | 18 | #include "stream.h" 19 | 20 | #ifdef __clang__ 21 | RAPIDJSON_DIAG_PUSH 22 | RAPIDJSON_DIAG_OFF(unreachable-code) 23 | RAPIDJSON_DIAG_OFF(missing-noreturn) 24 | #endif 25 | 26 | RAPIDJSON_NAMESPACE_BEGIN 27 | 28 | //! Represents an in-memory input byte stream. 29 | /*! 30 | This class is mainly for being wrapped by EncodedInputStream or AutoUTFInputStream. 31 | 32 | It is similar to FileReadBuffer but the source is an in-memory buffer instead of a file. 33 | 34 | Differences between MemoryStream and StringStream: 35 | 1. StringStream has encoding but MemoryStream is a byte stream. 36 | 2. MemoryStream needs size of the source buffer and the buffer don't need to be null terminated. StringStream assume null-terminated string as source. 37 | 3. MemoryStream supports Peek4() for encoding detection. StringStream is specified with an encoding so it should not have Peek4(). 38 | \note implements Stream concept 39 | */ 40 | struct MemoryStream { 41 | typedef char Ch; // byte 42 | 43 | MemoryStream(const Ch *src, size_t size) : src_(src), begin_(src), end_(src + size), size_(size) {} 44 | 45 | Ch Peek() const { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_; } 46 | Ch Take() { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_++; } 47 | size_t Tell() const { return static_cast(src_ - begin_); } 48 | 49 | Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } 50 | void Put(Ch) { RAPIDJSON_ASSERT(false); } 51 | void Flush() { RAPIDJSON_ASSERT(false); } 52 | size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } 53 | 54 | // For encoding detection only. 55 | const Ch* Peek4() const { 56 | return Tell() + 4 <= size_ ? src_ : 0; 57 | } 58 | 59 | const Ch* src_; //!< Current read position. 60 | const Ch* begin_; //!< Original head of the string. 61 | const Ch* end_; //!< End of stream. 62 | size_t size_; //!< Size of the stream. 63 | }; 64 | 65 | RAPIDJSON_NAMESPACE_END 66 | 67 | #ifdef __clang__ 68 | RAPIDJSON_DIAG_POP 69 | #endif 70 | 71 | #endif // RAPIDJSON_MEMORYBUFFER_H_ 72 | -------------------------------------------------------------------------------- /PlaygroundEngine/Utility/rapidjson/ostreamwrapper.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_OSTREAMWRAPPER_H_ 16 | #define RAPIDJSON_OSTREAMWRAPPER_H_ 17 | 18 | #include "stream.h" 19 | #include 20 | 21 | #ifdef __clang__ 22 | RAPIDJSON_DIAG_PUSH 23 | RAPIDJSON_DIAG_OFF(padded) 24 | #endif 25 | 26 | RAPIDJSON_NAMESPACE_BEGIN 27 | 28 | //! Wrapper of \c std::basic_ostream into RapidJSON's Stream concept. 29 | /*! 30 | The classes can be wrapped including but not limited to: 31 | 32 | - \c std::ostringstream 33 | - \c std::stringstream 34 | - \c std::wpstringstream 35 | - \c std::wstringstream 36 | - \c std::ifstream 37 | - \c std::fstream 38 | - \c std::wofstream 39 | - \c std::wfstream 40 | 41 | \tparam StreamType Class derived from \c std::basic_ostream. 42 | */ 43 | 44 | template 45 | class BasicOStreamWrapper { 46 | public: 47 | typedef typename StreamType::char_type Ch; 48 | BasicOStreamWrapper(StreamType& stream) : stream_(stream) {} 49 | 50 | void Put(Ch c) { 51 | stream_.put(c); 52 | } 53 | 54 | void Flush() { 55 | stream_.flush(); 56 | } 57 | 58 | // Not implemented 59 | char Peek() const { RAPIDJSON_ASSERT(false); return 0; } 60 | char Take() { RAPIDJSON_ASSERT(false); return 0; } 61 | size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } 62 | char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } 63 | size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; } 64 | 65 | private: 66 | BasicOStreamWrapper(const BasicOStreamWrapper&); 67 | BasicOStreamWrapper& operator=(const BasicOStreamWrapper&); 68 | 69 | StreamType& stream_; 70 | }; 71 | 72 | typedef BasicOStreamWrapper OStreamWrapper; 73 | typedef BasicOStreamWrapper WOStreamWrapper; 74 | 75 | #ifdef __clang__ 76 | RAPIDJSON_DIAG_POP 77 | #endif 78 | 79 | RAPIDJSON_NAMESPACE_END 80 | 81 | #endif // RAPIDJSON_OSTREAMWRAPPER_H_ 82 | -------------------------------------------------------------------------------- /PlaygroundEngine/Utility/rapidjson/stringbuffer.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_STRINGBUFFER_H_ 16 | #define RAPIDJSON_STRINGBUFFER_H_ 17 | 18 | #include "stream.h" 19 | #include "internal/stack.h" 20 | 21 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS 22 | #include // std::move 23 | #endif 24 | 25 | #include "internal/stack.h" 26 | 27 | #if defined(__clang__) 28 | RAPIDJSON_DIAG_PUSH 29 | RAPIDJSON_DIAG_OFF(c++98-compat) 30 | #endif 31 | 32 | RAPIDJSON_NAMESPACE_BEGIN 33 | 34 | //! Represents an in-memory output stream. 35 | /*! 36 | \tparam Encoding Encoding of the stream. 37 | \tparam Allocator type for allocating memory buffer. 38 | \note implements Stream concept 39 | */ 40 | template 41 | class GenericStringBuffer { 42 | public: 43 | typedef typename Encoding::Ch Ch; 44 | 45 | GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} 46 | 47 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS 48 | GenericStringBuffer(GenericStringBuffer&& rhs) : stack_(std::move(rhs.stack_)) {} 49 | GenericStringBuffer& operator=(GenericStringBuffer&& rhs) { 50 | if (&rhs != this) 51 | stack_ = std::move(rhs.stack_); 52 | return *this; 53 | } 54 | #endif 55 | 56 | void Put(Ch c) { *stack_.template Push() = c; } 57 | void PutUnsafe(Ch c) { *stack_.template PushUnsafe() = c; } 58 | void Flush() {} 59 | 60 | void Clear() { stack_.Clear(); } 61 | void ShrinkToFit() { 62 | // Push and pop a null terminator. This is safe. 63 | *stack_.template Push() = '\0'; 64 | stack_.ShrinkToFit(); 65 | stack_.template Pop(1); 66 | } 67 | 68 | void Reserve(size_t count) { stack_.template Reserve(count); } 69 | Ch* Push(size_t count) { return stack_.template Push(count); } 70 | Ch* PushUnsafe(size_t count) { return stack_.template PushUnsafe(count); } 71 | void Pop(size_t count) { stack_.template Pop(count); } 72 | 73 | const Ch* GetString() const { 74 | // Push and pop a null terminator. This is safe. 75 | *stack_.template Push() = '\0'; 76 | stack_.template Pop(1); 77 | 78 | return stack_.template Bottom(); 79 | } 80 | 81 | //! Get the size of string in bytes in the string buffer. 82 | size_t GetSize() const { return stack_.GetSize(); } 83 | 84 | //! Get the length of string in Ch in the string buffer. 85 | size_t GetLength() const { return stack_.GetSize() / sizeof(Ch); } 86 | 87 | static const size_t kDefaultCapacity = 256; 88 | mutable internal::Stack stack_; 89 | 90 | private: 91 | // Prohibit copy constructor & assignment operator. 92 | GenericStringBuffer(const GenericStringBuffer&); 93 | GenericStringBuffer& operator=(const GenericStringBuffer&); 94 | }; 95 | 96 | //! String buffer with UTF8 encoding 97 | typedef GenericStringBuffer > StringBuffer; 98 | 99 | template 100 | inline void PutReserve(GenericStringBuffer& stream, size_t count) { 101 | stream.Reserve(count); 102 | } 103 | 104 | template 105 | inline void PutUnsafe(GenericStringBuffer& stream, typename Encoding::Ch c) { 106 | stream.PutUnsafe(c); 107 | } 108 | 109 | //! Implement specialized version of PutN() with memset() for better performance. 110 | template<> 111 | inline void PutN(GenericStringBuffer >& stream, char c, size_t n) { 112 | std::memset(stream.stack_.Push(n), c, n * sizeof(c)); 113 | } 114 | 115 | RAPIDJSON_NAMESPACE_END 116 | 117 | #if defined(__clang__) 118 | RAPIDJSON_DIAG_POP 119 | #endif 120 | 121 | #endif // RAPIDJSON_STRINGBUFFER_H_ 122 | -------------------------------------------------------------------------------- /PlaygroundEngine/Utility/tiny_obj_loader.cpp: -------------------------------------------------------------------------------- 1 | #define TINYOBJLOADER_IMPLEMENTATION 2 | #include "tiny_obj_loader.h" 3 | 4 | #define TINYGLTF_IMPLEMENTATION 5 | #define TINYGLTF_USE_RAPIDJSON 6 | #define TINYGLTF_NO_STB_IMAGE_WRITE 7 | #include "tiny_gltf.h" 8 | 9 | -------------------------------------------------------------------------------- /PlaygroundEngine/Utility/tinyddsloader.cpp: -------------------------------------------------------------------------------- 1 | #define TINYDDSLOADER_IMPLEMENTATION 2 | #include "tinyddsloader.h" 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This is my personal game engine project for learning and testing real-time rendering tecniques. 2 | It is more like a renderer than a game engine now but I want to implement animation, physics, audio, etc. in the future. 3 | 4 | ### Some Features: 5 | - Abstracted Direct3D 11 rendering API 6 | - GLTF 2.0 scene loading 7 | - Physically based rendering with Cook-Torrance BRDF 8 | - Image Based Lighting 9 | - Normal mapping 10 | - Multisample Anti-aliasing (MSAA) 11 | - HDR rendering 12 | - Cascaded Shadow Mapping 13 | - Omnidirectional Shadow Mapping 14 | - Forward shading with Z prepass 15 | - Logging, Profiling, etc 16 | 17 | ### Roadmap: 18 | I am planning to add mode features into this project. You can see the roadmap [here](https://github.com/imgeself/PlaygroundEngine/projects/1) 19 | 20 | ### Requirements: 21 | - Windows 10 22 | - Visual Studio 2019 23 | 24 | ### Building and Running: 25 | You can just clone this repo and open the solution file in VS2019 and press F5. It should build and run without any problem. 26 | 27 | Use WASD keys to move the camera, hold left-click and drag the mouse to rotate the camera. 28 | 29 | ### Screenshots 30 | ![scrrenshot3](https://github.com/imgeself/PlaygroundEngine/blob/master/screenshots/screenshot3.png) 31 | 32 | ![scrrenshot1](https://github.com/imgeself/PlaygroundEngine/blob/master/screenshots/screenshot1.png) 33 | 34 | ![scrrenshot2](https://github.com/imgeself/PlaygroundEngine/blob/master/screenshots/screenshot2.png) -------------------------------------------------------------------------------- /screenshots/screenshot1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/screenshots/screenshot1.png -------------------------------------------------------------------------------- /screenshots/screenshot2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/screenshots/screenshot2.png -------------------------------------------------------------------------------- /screenshots/screenshot3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imgeself/PlaygroundEngine/da76957f86ce241fde49bac013739e4efd26a257/screenshots/screenshot3.png --------------------------------------------------------------------------------