diff --git a/Demo/Demo.cpp b/Demo/Demo.cpp new file mode 100644 index 0000000..2af86d3 --- /dev/null +++ b/Demo/Demo.cpp @@ -0,0 +1,8 @@ +#include +#include "DemoWorld.h" + +int main() +{ + MainWindow::instance().initialize(); + return MainWindow::instance().exec(std::make_unique()); +} \ No newline at end of file diff --git a/Demo/Demo.vcxproj b/Demo/Demo.vcxproj new file mode 100644 index 0000000..b6e1ddd --- /dev/null +++ b/Demo/Demo.vcxproj @@ -0,0 +1,156 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {02eea281-f0a1-4be3-b833-5a9b4150f6b0} + Demo + 10.0 + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + stdcpp20 + stdc17 + $(SolutionDir)ToyEngine\include;$(SolutionDir)ToyEngine\src;%(AdditionalIncludeDirectories) + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + stdcpp20 + stdc17 + $(SolutionDir)ToyEngine\include;$(SolutionDir)ToyEngine\src;%(AdditionalIncludeDirectories) + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + stdcpp20 + stdc17 + $(SolutionDir)ToyEngine\include;$(SolutionDir)ToyEngine\src;%(AdditionalIncludeDirectories) + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + stdcpp20 + stdc17 + $(SolutionDir)ToyEngine\include;$(SolutionDir)ToyEngine\src;%(AdditionalIncludeDirectories) + + + Console + true + true + true + + + + + + + + + {65d6ee2b-fffa-4ef6-8042-9ca7a0f8e67e} + + + + + + + + + \ No newline at end of file diff --git a/Demo/Demo.vcxproj.filters b/Demo/Demo.vcxproj.filters new file mode 100644 index 0000000..cbb6427 --- /dev/null +++ b/Demo/Demo.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + 源文件 + + + 源文件 + + + + + 头文件 + + + \ No newline at end of file diff --git a/ToyEngine/src/DemoWorld.cpp b/Demo/DemoWorld.cpp similarity index 99% rename from ToyEngine/src/DemoWorld.cpp rename to Demo/DemoWorld.cpp index 2ab9f11..0f78aa7 100644 --- a/ToyEngine/src/DemoWorld.cpp +++ b/Demo/DemoWorld.cpp @@ -1,6 +1,6 @@ #include "DemoWorld.h" -#include "Particle.h" -#include "RenderingSystem.h" +#include +#include DemoWorld::DemoWorld() { diff --git a/ToyEngine/src/DemoWorld.h b/Demo/DemoWorld.h similarity index 97% rename from ToyEngine/src/DemoWorld.h rename to Demo/DemoWorld.h index 05888e1..1349162 100644 --- a/ToyEngine/src/DemoWorld.h +++ b/Demo/DemoWorld.h @@ -1,5 +1,5 @@ #pragma once -#include "World.h" +#include class DemoWorld : public World { diff --git a/ToyEngine/HDRI/clarens_midday_4k.hdr b/Demo/Engine/HDRI/clarens_midday_4k.hdr similarity index 100% rename from ToyEngine/HDRI/clarens_midday_4k.hdr rename to Demo/Engine/HDRI/clarens_midday_4k.hdr diff --git a/ToyEngine/Shaders/brdf_lut.comp b/Demo/Engine/Shaders/brdf_lut.comp similarity index 100% rename from ToyEngine/Shaders/brdf_lut.comp rename to Demo/Engine/Shaders/brdf_lut.comp diff --git a/ToyEngine/Shaders/cubemap.frag b/Demo/Engine/Shaders/cubemap.frag similarity index 100% rename from ToyEngine/Shaders/cubemap.frag rename to Demo/Engine/Shaders/cubemap.frag diff --git a/ToyEngine/Shaders/cubemap.vert b/Demo/Engine/Shaders/cubemap.vert similarity index 100% rename from ToyEngine/Shaders/cubemap.vert rename to Demo/Engine/Shaders/cubemap.vert diff --git a/ToyEngine/Shaders/cubemap_prefilter.frag b/Demo/Engine/Shaders/cubemap_prefilter.frag similarity index 100% rename from ToyEngine/Shaders/cubemap_prefilter.frag rename to Demo/Engine/Shaders/cubemap_prefilter.frag diff --git a/ToyEngine/Shaders/debug.frag b/Demo/Engine/Shaders/debug.frag similarity index 100% rename from ToyEngine/Shaders/debug.frag rename to Demo/Engine/Shaders/debug.frag diff --git a/ToyEngine/Shaders/debug.vert b/Demo/Engine/Shaders/debug.vert similarity index 100% rename from ToyEngine/Shaders/debug.vert rename to Demo/Engine/Shaders/debug.vert diff --git a/ToyEngine/Shaders/final.frag b/Demo/Engine/Shaders/final.frag similarity index 100% rename from ToyEngine/Shaders/final.frag rename to Demo/Engine/Shaders/final.frag diff --git a/ToyEngine/Shaders/final.vert b/Demo/Engine/Shaders/final.vert similarity index 100% rename from ToyEngine/Shaders/final.vert rename to Demo/Engine/Shaders/final.vert diff --git a/ToyEngine/Shaders/irradiance_convolution.frag b/Demo/Engine/Shaders/irradiance_convolution.frag similarity index 100% rename from ToyEngine/Shaders/irradiance_convolution.frag rename to Demo/Engine/Shaders/irradiance_convolution.frag diff --git a/ToyEngine/Shaders/model.frag b/Demo/Engine/Shaders/model.frag similarity index 100% rename from ToyEngine/Shaders/model.frag rename to Demo/Engine/Shaders/model.frag diff --git a/ToyEngine/Shaders/model.vert b/Demo/Engine/Shaders/model.vert similarity index 100% rename from ToyEngine/Shaders/model.vert rename to Demo/Engine/Shaders/model.vert diff --git a/ToyEngine/Shaders/model_shadow.frag b/Demo/Engine/Shaders/model_shadow.frag similarity index 100% rename from ToyEngine/Shaders/model_shadow.frag rename to Demo/Engine/Shaders/model_shadow.frag diff --git a/ToyEngine/Shaders/model_shadow.geom b/Demo/Engine/Shaders/model_shadow.geom similarity index 100% rename from ToyEngine/Shaders/model_shadow.geom rename to Demo/Engine/Shaders/model_shadow.geom diff --git a/ToyEngine/Shaders/model_shadow.vert b/Demo/Engine/Shaders/model_shadow.vert similarity index 100% rename from ToyEngine/Shaders/model_shadow.vert rename to Demo/Engine/Shaders/model_shadow.vert diff --git a/ToyEngine/Shaders/pbr.comp b/Demo/Engine/Shaders/pbr.comp similarity index 100% rename from ToyEngine/Shaders/pbr.comp rename to Demo/Engine/Shaders/pbr.comp diff --git a/ToyEngine/Shaders/plain.frag b/Demo/Engine/Shaders/plain.frag similarity index 100% rename from ToyEngine/Shaders/plain.frag rename to Demo/Engine/Shaders/plain.frag diff --git a/ToyEngine/Shaders/plain.vert b/Demo/Engine/Shaders/plain.vert similarity index 100% rename from ToyEngine/Shaders/plain.vert rename to Demo/Engine/Shaders/plain.vert diff --git a/ToyEngine/Shaders/skybox.frag b/Demo/Engine/Shaders/skybox.frag similarity index 100% rename from ToyEngine/Shaders/skybox.frag rename to Demo/Engine/Shaders/skybox.frag diff --git a/ToyEngine/Shaders/skybox.vert b/Demo/Engine/Shaders/skybox.vert similarity index 100% rename from ToyEngine/Shaders/skybox.vert rename to Demo/Engine/Shaders/skybox.vert diff --git a/ToyEngine/Models/Sponza/10381718147657362067.jpg b/Demo/Models/Sponza/10381718147657362067.jpg similarity index 100% rename from ToyEngine/Models/Sponza/10381718147657362067.jpg rename to Demo/Models/Sponza/10381718147657362067.jpg diff --git a/ToyEngine/Models/Sponza/10388182081421875623.jpg b/Demo/Models/Sponza/10388182081421875623.jpg similarity index 100% rename from ToyEngine/Models/Sponza/10388182081421875623.jpg rename to Demo/Models/Sponza/10388182081421875623.jpg diff --git a/ToyEngine/Models/Sponza/11474523244911310074.jpg b/Demo/Models/Sponza/11474523244911310074.jpg similarity index 100% rename from ToyEngine/Models/Sponza/11474523244911310074.jpg rename to Demo/Models/Sponza/11474523244911310074.jpg diff --git a/ToyEngine/Models/Sponza/11490520546946913238.jpg b/Demo/Models/Sponza/11490520546946913238.jpg similarity index 100% rename from ToyEngine/Models/Sponza/11490520546946913238.jpg rename to Demo/Models/Sponza/11490520546946913238.jpg diff --git a/ToyEngine/Models/Sponza/11872827283454512094.jpg b/Demo/Models/Sponza/11872827283454512094.jpg similarity index 100% rename from ToyEngine/Models/Sponza/11872827283454512094.jpg rename to Demo/Models/Sponza/11872827283454512094.jpg diff --git a/ToyEngine/Models/Sponza/11968150294050148237.jpg b/Demo/Models/Sponza/11968150294050148237.jpg similarity index 100% rename from ToyEngine/Models/Sponza/11968150294050148237.jpg rename to Demo/Models/Sponza/11968150294050148237.jpg diff --git a/ToyEngine/Models/Sponza/1219024358953944284.jpg b/Demo/Models/Sponza/1219024358953944284.jpg similarity index 100% rename from ToyEngine/Models/Sponza/1219024358953944284.jpg rename to Demo/Models/Sponza/1219024358953944284.jpg diff --git a/ToyEngine/Models/Sponza/12501374198249454378.jpg b/Demo/Models/Sponza/12501374198249454378.jpg similarity index 100% rename from ToyEngine/Models/Sponza/12501374198249454378.jpg rename to Demo/Models/Sponza/12501374198249454378.jpg diff --git a/ToyEngine/Models/Sponza/13196865903111448057.jpg b/Demo/Models/Sponza/13196865903111448057.jpg similarity index 100% rename from ToyEngine/Models/Sponza/13196865903111448057.jpg rename to Demo/Models/Sponza/13196865903111448057.jpg diff --git a/ToyEngine/Models/Sponza/13824894030729245199.jpg b/Demo/Models/Sponza/13824894030729245199.jpg similarity index 100% rename from ToyEngine/Models/Sponza/13824894030729245199.jpg rename to Demo/Models/Sponza/13824894030729245199.jpg diff --git a/ToyEngine/Models/Sponza/13982482287905699490.jpg b/Demo/Models/Sponza/13982482287905699490.jpg similarity index 100% rename from ToyEngine/Models/Sponza/13982482287905699490.jpg rename to Demo/Models/Sponza/13982482287905699490.jpg diff --git a/ToyEngine/Models/Sponza/14118779221266351425.jpg b/Demo/Models/Sponza/14118779221266351425.jpg similarity index 100% rename from ToyEngine/Models/Sponza/14118779221266351425.jpg rename to Demo/Models/Sponza/14118779221266351425.jpg diff --git a/ToyEngine/Models/Sponza/14170708867020035030.jpg b/Demo/Models/Sponza/14170708867020035030.jpg similarity index 100% rename from ToyEngine/Models/Sponza/14170708867020035030.jpg rename to Demo/Models/Sponza/14170708867020035030.jpg diff --git a/ToyEngine/Models/Sponza/14267839433702832875.jpg b/Demo/Models/Sponza/14267839433702832875.jpg similarity index 100% rename from ToyEngine/Models/Sponza/14267839433702832875.jpg rename to Demo/Models/Sponza/14267839433702832875.jpg diff --git a/ToyEngine/Models/Sponza/14650633544276105767.jpg b/Demo/Models/Sponza/14650633544276105767.jpg similarity index 100% rename from ToyEngine/Models/Sponza/14650633544276105767.jpg rename to Demo/Models/Sponza/14650633544276105767.jpg diff --git a/ToyEngine/Models/Sponza/15295713303328085182.jpg b/Demo/Models/Sponza/15295713303328085182.jpg similarity index 100% rename from ToyEngine/Models/Sponza/15295713303328085182.jpg rename to Demo/Models/Sponza/15295713303328085182.jpg diff --git a/ToyEngine/Models/Sponza/15722799267630235092.jpg b/Demo/Models/Sponza/15722799267630235092.jpg similarity index 100% rename from ToyEngine/Models/Sponza/15722799267630235092.jpg rename to Demo/Models/Sponza/15722799267630235092.jpg diff --git a/ToyEngine/Models/Sponza/16275776544635328252.png b/Demo/Models/Sponza/16275776544635328252.png similarity index 100% rename from ToyEngine/Models/Sponza/16275776544635328252.png rename to Demo/Models/Sponza/16275776544635328252.png diff --git a/ToyEngine/Models/Sponza/16299174074766089871.jpg b/Demo/Models/Sponza/16299174074766089871.jpg similarity index 100% rename from ToyEngine/Models/Sponza/16299174074766089871.jpg rename to Demo/Models/Sponza/16299174074766089871.jpg diff --git a/ToyEngine/Models/Sponza/16885566240357350108.jpg b/Demo/Models/Sponza/16885566240357350108.jpg similarity index 100% rename from ToyEngine/Models/Sponza/16885566240357350108.jpg rename to Demo/Models/Sponza/16885566240357350108.jpg diff --git a/ToyEngine/Models/Sponza/17556969131407844942.jpg b/Demo/Models/Sponza/17556969131407844942.jpg similarity index 100% rename from ToyEngine/Models/Sponza/17556969131407844942.jpg rename to Demo/Models/Sponza/17556969131407844942.jpg diff --git a/ToyEngine/Models/Sponza/17876391417123941155.jpg b/Demo/Models/Sponza/17876391417123941155.jpg similarity index 100% rename from ToyEngine/Models/Sponza/17876391417123941155.jpg rename to Demo/Models/Sponza/17876391417123941155.jpg diff --git a/ToyEngine/Models/Sponza/2051777328469649772.jpg b/Demo/Models/Sponza/2051777328469649772.jpg similarity index 100% rename from ToyEngine/Models/Sponza/2051777328469649772.jpg rename to Demo/Models/Sponza/2051777328469649772.jpg diff --git a/ToyEngine/Models/Sponza/2185409758123873465.jpg b/Demo/Models/Sponza/2185409758123873465.jpg similarity index 100% rename from ToyEngine/Models/Sponza/2185409758123873465.jpg rename to Demo/Models/Sponza/2185409758123873465.jpg diff --git a/ToyEngine/Models/Sponza/2299742237651021498.jpg b/Demo/Models/Sponza/2299742237651021498.jpg similarity index 100% rename from ToyEngine/Models/Sponza/2299742237651021498.jpg rename to Demo/Models/Sponza/2299742237651021498.jpg diff --git a/ToyEngine/Models/Sponza/2374361008830720677.jpg b/Demo/Models/Sponza/2374361008830720677.jpg similarity index 100% rename from ToyEngine/Models/Sponza/2374361008830720677.jpg rename to Demo/Models/Sponza/2374361008830720677.jpg diff --git a/ToyEngine/Models/Sponza/2411100444841994089.jpg b/Demo/Models/Sponza/2411100444841994089.jpg similarity index 100% rename from ToyEngine/Models/Sponza/2411100444841994089.jpg rename to Demo/Models/Sponza/2411100444841994089.jpg diff --git a/ToyEngine/Models/Sponza/2775690330959970771.jpg b/Demo/Models/Sponza/2775690330959970771.jpg similarity index 100% rename from ToyEngine/Models/Sponza/2775690330959970771.jpg rename to Demo/Models/Sponza/2775690330959970771.jpg diff --git a/ToyEngine/Models/Sponza/2969916736137545357.jpg b/Demo/Models/Sponza/2969916736137545357.jpg similarity index 100% rename from ToyEngine/Models/Sponza/2969916736137545357.jpg rename to Demo/Models/Sponza/2969916736137545357.jpg diff --git a/ToyEngine/Models/Sponza/332936164838540657.jpg b/Demo/Models/Sponza/332936164838540657.jpg similarity index 100% rename from ToyEngine/Models/Sponza/332936164838540657.jpg rename to Demo/Models/Sponza/332936164838540657.jpg diff --git a/ToyEngine/Models/Sponza/3371964815757888145.jpg b/Demo/Models/Sponza/3371964815757888145.jpg similarity index 100% rename from ToyEngine/Models/Sponza/3371964815757888145.jpg rename to Demo/Models/Sponza/3371964815757888145.jpg diff --git a/ToyEngine/Models/Sponza/3455394979645218238.jpg b/Demo/Models/Sponza/3455394979645218238.jpg similarity index 100% rename from ToyEngine/Models/Sponza/3455394979645218238.jpg rename to Demo/Models/Sponza/3455394979645218238.jpg diff --git a/ToyEngine/Models/Sponza/3628158980083700836.jpg b/Demo/Models/Sponza/3628158980083700836.jpg similarity index 100% rename from ToyEngine/Models/Sponza/3628158980083700836.jpg rename to Demo/Models/Sponza/3628158980083700836.jpg diff --git a/ToyEngine/Models/Sponza/3827035219084910048.jpg b/Demo/Models/Sponza/3827035219084910048.jpg similarity index 100% rename from ToyEngine/Models/Sponza/3827035219084910048.jpg rename to Demo/Models/Sponza/3827035219084910048.jpg diff --git a/ToyEngine/Models/Sponza/4477655471536070370.jpg b/Demo/Models/Sponza/4477655471536070370.jpg similarity index 100% rename from ToyEngine/Models/Sponza/4477655471536070370.jpg rename to Demo/Models/Sponza/4477655471536070370.jpg diff --git a/ToyEngine/Models/Sponza/4601176305987539675.jpg b/Demo/Models/Sponza/4601176305987539675.jpg similarity index 100% rename from ToyEngine/Models/Sponza/4601176305987539675.jpg rename to Demo/Models/Sponza/4601176305987539675.jpg diff --git a/ToyEngine/Models/Sponza/466164707995436622.jpg b/Demo/Models/Sponza/466164707995436622.jpg similarity index 100% rename from ToyEngine/Models/Sponza/466164707995436622.jpg rename to Demo/Models/Sponza/466164707995436622.jpg diff --git a/ToyEngine/Models/Sponza/4675343432951571524.jpg b/Demo/Models/Sponza/4675343432951571524.jpg similarity index 100% rename from ToyEngine/Models/Sponza/4675343432951571524.jpg rename to Demo/Models/Sponza/4675343432951571524.jpg diff --git a/ToyEngine/Models/Sponza/4871783166746854860.jpg b/Demo/Models/Sponza/4871783166746854860.jpg similarity index 100% rename from ToyEngine/Models/Sponza/4871783166746854860.jpg rename to Demo/Models/Sponza/4871783166746854860.jpg diff --git a/ToyEngine/Models/Sponza/4910669866631290573.jpg b/Demo/Models/Sponza/4910669866631290573.jpg similarity index 100% rename from ToyEngine/Models/Sponza/4910669866631290573.jpg rename to Demo/Models/Sponza/4910669866631290573.jpg diff --git a/ToyEngine/Models/Sponza/4975155472559461469.jpg b/Demo/Models/Sponza/4975155472559461469.jpg similarity index 100% rename from ToyEngine/Models/Sponza/4975155472559461469.jpg rename to Demo/Models/Sponza/4975155472559461469.jpg diff --git a/ToyEngine/Models/Sponza/5061699253647017043.png b/Demo/Models/Sponza/5061699253647017043.png similarity index 100% rename from ToyEngine/Models/Sponza/5061699253647017043.png rename to Demo/Models/Sponza/5061699253647017043.png diff --git a/ToyEngine/Models/Sponza/5792855332885324923.jpg b/Demo/Models/Sponza/5792855332885324923.jpg similarity index 100% rename from ToyEngine/Models/Sponza/5792855332885324923.jpg rename to Demo/Models/Sponza/5792855332885324923.jpg diff --git a/ToyEngine/Models/Sponza/5823059166183034438.jpg b/Demo/Models/Sponza/5823059166183034438.jpg similarity index 100% rename from ToyEngine/Models/Sponza/5823059166183034438.jpg rename to Demo/Models/Sponza/5823059166183034438.jpg diff --git a/ToyEngine/Models/Sponza/6047387724914829168.jpg b/Demo/Models/Sponza/6047387724914829168.jpg similarity index 100% rename from ToyEngine/Models/Sponza/6047387724914829168.jpg rename to Demo/Models/Sponza/6047387724914829168.jpg diff --git a/ToyEngine/Models/Sponza/6151467286084645207.jpg b/Demo/Models/Sponza/6151467286084645207.jpg similarity index 100% rename from ToyEngine/Models/Sponza/6151467286084645207.jpg rename to Demo/Models/Sponza/6151467286084645207.jpg diff --git a/ToyEngine/Models/Sponza/6593109234861095314.jpg b/Demo/Models/Sponza/6593109234861095314.jpg similarity index 100% rename from ToyEngine/Models/Sponza/6593109234861095314.jpg rename to Demo/Models/Sponza/6593109234861095314.jpg diff --git a/ToyEngine/Models/Sponza/6667038893015345571.jpg b/Demo/Models/Sponza/6667038893015345571.jpg similarity index 100% rename from ToyEngine/Models/Sponza/6667038893015345571.jpg rename to Demo/Models/Sponza/6667038893015345571.jpg diff --git a/ToyEngine/Models/Sponza/6772804448157695701.jpg b/Demo/Models/Sponza/6772804448157695701.jpg similarity index 100% rename from ToyEngine/Models/Sponza/6772804448157695701.jpg rename to Demo/Models/Sponza/6772804448157695701.jpg diff --git a/ToyEngine/Models/Sponza/7056944414013900257.jpg b/Demo/Models/Sponza/7056944414013900257.jpg similarity index 100% rename from ToyEngine/Models/Sponza/7056944414013900257.jpg rename to Demo/Models/Sponza/7056944414013900257.jpg diff --git a/ToyEngine/Models/Sponza/715093869573992647.jpg b/Demo/Models/Sponza/715093869573992647.jpg similarity index 100% rename from ToyEngine/Models/Sponza/715093869573992647.jpg rename to Demo/Models/Sponza/715093869573992647.jpg diff --git a/ToyEngine/Models/Sponza/7268504077753552595.jpg b/Demo/Models/Sponza/7268504077753552595.jpg similarity index 100% rename from ToyEngine/Models/Sponza/7268504077753552595.jpg rename to Demo/Models/Sponza/7268504077753552595.jpg diff --git a/ToyEngine/Models/Sponza/7441062115984513793.jpg b/Demo/Models/Sponza/7441062115984513793.jpg similarity index 100% rename from ToyEngine/Models/Sponza/7441062115984513793.jpg rename to Demo/Models/Sponza/7441062115984513793.jpg diff --git a/ToyEngine/Models/Sponza/755318871556304029.jpg b/Demo/Models/Sponza/755318871556304029.jpg similarity index 100% rename from ToyEngine/Models/Sponza/755318871556304029.jpg rename to Demo/Models/Sponza/755318871556304029.jpg diff --git a/ToyEngine/Models/Sponza/759203620573749278.jpg b/Demo/Models/Sponza/759203620573749278.jpg similarity index 100% rename from ToyEngine/Models/Sponza/759203620573749278.jpg rename to Demo/Models/Sponza/759203620573749278.jpg diff --git a/ToyEngine/Models/Sponza/7645212358685992005.jpg b/Demo/Models/Sponza/7645212358685992005.jpg similarity index 100% rename from ToyEngine/Models/Sponza/7645212358685992005.jpg rename to Demo/Models/Sponza/7645212358685992005.jpg diff --git a/ToyEngine/Models/Sponza/7815564343179553343.jpg b/Demo/Models/Sponza/7815564343179553343.jpg similarity index 100% rename from ToyEngine/Models/Sponza/7815564343179553343.jpg rename to Demo/Models/Sponza/7815564343179553343.jpg diff --git a/ToyEngine/Models/Sponza/8006627369776289000.png b/Demo/Models/Sponza/8006627369776289000.png similarity index 100% rename from ToyEngine/Models/Sponza/8006627369776289000.png rename to Demo/Models/Sponza/8006627369776289000.png diff --git a/ToyEngine/Models/Sponza/8051790464816141987.jpg b/Demo/Models/Sponza/8051790464816141987.jpg similarity index 100% rename from ToyEngine/Models/Sponza/8051790464816141987.jpg rename to Demo/Models/Sponza/8051790464816141987.jpg diff --git a/ToyEngine/Models/Sponza/8114461559286000061.jpg b/Demo/Models/Sponza/8114461559286000061.jpg similarity index 100% rename from ToyEngine/Models/Sponza/8114461559286000061.jpg rename to Demo/Models/Sponza/8114461559286000061.jpg diff --git a/ToyEngine/Models/Sponza/8481240838833932244.jpg b/Demo/Models/Sponza/8481240838833932244.jpg similarity index 100% rename from ToyEngine/Models/Sponza/8481240838833932244.jpg rename to Demo/Models/Sponza/8481240838833932244.jpg diff --git a/ToyEngine/Models/Sponza/8503262930880235456.jpg b/Demo/Models/Sponza/8503262930880235456.jpg similarity index 100% rename from ToyEngine/Models/Sponza/8503262930880235456.jpg rename to Demo/Models/Sponza/8503262930880235456.jpg diff --git a/ToyEngine/Models/Sponza/8747919177698443163.jpg b/Demo/Models/Sponza/8747919177698443163.jpg similarity index 100% rename from ToyEngine/Models/Sponza/8747919177698443163.jpg rename to Demo/Models/Sponza/8747919177698443163.jpg diff --git a/ToyEngine/Models/Sponza/8750083169368950601.jpg b/Demo/Models/Sponza/8750083169368950601.jpg similarity index 100% rename from ToyEngine/Models/Sponza/8750083169368950601.jpg rename to Demo/Models/Sponza/8750083169368950601.jpg diff --git a/ToyEngine/Models/Sponza/8773302468495022225.jpg b/Demo/Models/Sponza/8773302468495022225.jpg similarity index 100% rename from ToyEngine/Models/Sponza/8773302468495022225.jpg rename to Demo/Models/Sponza/8773302468495022225.jpg diff --git a/ToyEngine/Models/Sponza/8783994986360286082.jpg b/Demo/Models/Sponza/8783994986360286082.jpg similarity index 100% rename from ToyEngine/Models/Sponza/8783994986360286082.jpg rename to Demo/Models/Sponza/8783994986360286082.jpg diff --git a/ToyEngine/Models/Sponza/9288698199695299068.jpg b/Demo/Models/Sponza/9288698199695299068.jpg similarity index 100% rename from ToyEngine/Models/Sponza/9288698199695299068.jpg rename to Demo/Models/Sponza/9288698199695299068.jpg diff --git a/ToyEngine/Models/Sponza/9916269861720640319.jpg b/Demo/Models/Sponza/9916269861720640319.jpg similarity index 100% rename from ToyEngine/Models/Sponza/9916269861720640319.jpg rename to Demo/Models/Sponza/9916269861720640319.jpg diff --git a/ToyEngine/Models/Sponza/Sponza.bin b/Demo/Models/Sponza/Sponza.bin similarity index 100% rename from ToyEngine/Models/Sponza/Sponza.bin rename to Demo/Models/Sponza/Sponza.bin diff --git a/ToyEngine/Models/Sponza/Sponza.gltf b/Demo/Models/Sponza/Sponza.gltf similarity index 100% rename from ToyEngine/Models/Sponza/Sponza.gltf rename to Demo/Models/Sponza/Sponza.gltf diff --git a/ToyEngine/Models/Sponza/white.png b/Demo/Models/Sponza/white.png similarity index 100% rename from ToyEngine/Models/Sponza/white.png rename to Demo/Models/Sponza/white.png diff --git a/ToyEngine/Models/grenade_throw/PackedMaterial0mat_diffuse.png b/Demo/Models/grenade_throw/PackedMaterial0mat_diffuse.png similarity index 100% rename from ToyEngine/Models/grenade_throw/PackedMaterial0mat_diffuse.png rename to Demo/Models/grenade_throw/PackedMaterial0mat_diffuse.png diff --git a/ToyEngine/Models/grenade_throw/PackedMaterial0mat_normal.png b/Demo/Models/grenade_throw/PackedMaterial0mat_normal.png similarity index 100% rename from ToyEngine/Models/grenade_throw/PackedMaterial0mat_normal.png rename to Demo/Models/grenade_throw/PackedMaterial0mat_normal.png diff --git a/ToyEngine/Models/grenade_throw/PackedMaterial0mat_specularGlossiness.png b/Demo/Models/grenade_throw/PackedMaterial0mat_specularGlossiness.png similarity index 100% rename from ToyEngine/Models/grenade_throw/PackedMaterial0mat_specularGlossiness.png rename to Demo/Models/grenade_throw/PackedMaterial0mat_specularGlossiness.png diff --git a/ToyEngine/Models/grenade_throw/grenade_throw.bin b/Demo/Models/grenade_throw/grenade_throw.bin similarity index 100% rename from ToyEngine/Models/grenade_throw/grenade_throw.bin rename to Demo/Models/grenade_throw/grenade_throw.bin diff --git a/ToyEngine/Models/grenade_throw/grenade_throw.gltf b/Demo/Models/grenade_throw/grenade_throw.gltf similarity index 100% rename from ToyEngine/Models/grenade_throw/grenade_throw.gltf rename to Demo/Models/grenade_throw/grenade_throw.gltf diff --git a/ToyEngine/Models/mk2-frag-grenade.blend b/Demo/Models/mk2-frag-grenade.blend similarity index 100% rename from ToyEngine/Models/mk2-frag-grenade.blend rename to Demo/Models/mk2-frag-grenade.blend diff --git a/ToyEngine/Models/mk2-frag-grenade/Grenade_B.png b/Demo/Models/mk2-frag-grenade/Grenade_B.png similarity index 100% rename from ToyEngine/Models/mk2-frag-grenade/Grenade_B.png rename to Demo/Models/mk2-frag-grenade/Grenade_B.png diff --git a/ToyEngine/Models/mk2-frag-grenade/Grenade_M-Grenade_R.png b/Demo/Models/mk2-frag-grenade/Grenade_M-Grenade_R.png similarity index 100% rename from ToyEngine/Models/mk2-frag-grenade/Grenade_M-Grenade_R.png rename to Demo/Models/mk2-frag-grenade/Grenade_M-Grenade_R.png diff --git a/ToyEngine/Models/mk2-frag-grenade/Grenade_N.png b/Demo/Models/mk2-frag-grenade/Grenade_N.png similarity index 100% rename from ToyEngine/Models/mk2-frag-grenade/Grenade_N.png rename to Demo/Models/mk2-frag-grenade/Grenade_N.png diff --git a/ToyEngine/Models/mk2-frag-grenade/mk2-frag-grenade.bin b/Demo/Models/mk2-frag-grenade/mk2-frag-grenade.bin similarity index 100% rename from ToyEngine/Models/mk2-frag-grenade/mk2-frag-grenade.bin rename to Demo/Models/mk2-frag-grenade/mk2-frag-grenade.bin diff --git a/ToyEngine/Models/mk2-frag-grenade/mk2-frag-grenade.gltf b/Demo/Models/mk2-frag-grenade/mk2-frag-grenade.gltf similarity index 100% rename from ToyEngine/Models/mk2-frag-grenade/mk2-frag-grenade.gltf rename to Demo/Models/mk2-frag-grenade/mk2-frag-grenade.gltf diff --git a/ToyEngine/Models/pallet_wood/Material_106_baseColor.jpg b/Demo/Models/pallet_wood/Material_106_baseColor.jpg similarity index 100% rename from ToyEngine/Models/pallet_wood/Material_106_baseColor.jpg rename to Demo/Models/pallet_wood/Material_106_baseColor.jpg diff --git a/ToyEngine/Models/pallet_wood/Material_106_metallicRoughness.png b/Demo/Models/pallet_wood/Material_106_metallicRoughness.png similarity index 100% rename from ToyEngine/Models/pallet_wood/Material_106_metallicRoughness.png rename to Demo/Models/pallet_wood/Material_106_metallicRoughness.png diff --git a/ToyEngine/Models/pallet_wood/Material_106_normal.png b/Demo/Models/pallet_wood/Material_106_normal.png similarity index 100% rename from ToyEngine/Models/pallet_wood/Material_106_normal.png rename to Demo/Models/pallet_wood/Material_106_normal.png diff --git a/ToyEngine/Models/pallet_wood/pallet_wood.bin b/Demo/Models/pallet_wood/pallet_wood.bin similarity index 100% rename from ToyEngine/Models/pallet_wood/pallet_wood.bin rename to Demo/Models/pallet_wood/pallet_wood.bin diff --git a/ToyEngine/Models/pallet_wood/pallet_wood.gltf b/Demo/Models/pallet_wood/pallet_wood.gltf similarity index 100% rename from ToyEngine/Models/pallet_wood/pallet_wood.gltf rename to Demo/Models/pallet_wood/pallet_wood.gltf diff --git a/ToyEngine/Models/shoot_gun/scene.bin b/Demo/Models/shoot_gun/scene.bin similarity index 100% rename from ToyEngine/Models/shoot_gun/scene.bin rename to Demo/Models/shoot_gun/scene.bin diff --git a/ToyEngine/Models/shoot_gun/scene.gltf b/Demo/Models/shoot_gun/scene.gltf similarity index 100% rename from ToyEngine/Models/shoot_gun/scene.gltf rename to Demo/Models/shoot_gun/scene.gltf diff --git a/ToyEngine/Models/shoot_gun/textures/Bodymat_diffuse.png b/Demo/Models/shoot_gun/textures/Bodymat_diffuse.png similarity index 100% rename from ToyEngine/Models/shoot_gun/textures/Bodymat_diffuse.png rename to Demo/Models/shoot_gun/textures/Bodymat_diffuse.png diff --git a/ToyEngine/Models/shoot_gun/textures/Bodymat_normal.png b/Demo/Models/shoot_gun/textures/Bodymat_normal.png similarity index 100% rename from ToyEngine/Models/shoot_gun/textures/Bodymat_normal.png rename to Demo/Models/shoot_gun/textures/Bodymat_normal.png diff --git a/ToyEngine/Models/shoot_gun/textures/Bodymat_specularGlossiness.png b/Demo/Models/shoot_gun/textures/Bodymat_specularGlossiness.png similarity index 100% rename from ToyEngine/Models/shoot_gun/textures/Bodymat_specularGlossiness.png rename to Demo/Models/shoot_gun/textures/Bodymat_specularGlossiness.png diff --git a/ToyEngine/Models/shoot_gun/textures/Bottommat_diffuse.png b/Demo/Models/shoot_gun/textures/Bottommat_diffuse.png similarity index 100% rename from ToyEngine/Models/shoot_gun/textures/Bottommat_diffuse.png rename to Demo/Models/shoot_gun/textures/Bottommat_diffuse.png diff --git a/ToyEngine/Models/shoot_gun/textures/Bottommat_normal.png b/Demo/Models/shoot_gun/textures/Bottommat_normal.png similarity index 100% rename from ToyEngine/Models/shoot_gun/textures/Bottommat_normal.png rename to Demo/Models/shoot_gun/textures/Bottommat_normal.png diff --git a/ToyEngine/Models/shoot_gun/textures/Bottommat_specularGlossiness.png b/Demo/Models/shoot_gun/textures/Bottommat_specularGlossiness.png similarity index 100% rename from ToyEngine/Models/shoot_gun/textures/Bottommat_specularGlossiness.png rename to Demo/Models/shoot_gun/textures/Bottommat_specularGlossiness.png diff --git a/ToyEngine/Models/shoot_gun/textures/Glovemat_diffuse.png b/Demo/Models/shoot_gun/textures/Glovemat_diffuse.png similarity index 100% rename from ToyEngine/Models/shoot_gun/textures/Glovemat_diffuse.png rename to Demo/Models/shoot_gun/textures/Glovemat_diffuse.png diff --git a/ToyEngine/Models/shoot_gun/textures/Glovemat_normal.png b/Demo/Models/shoot_gun/textures/Glovemat_normal.png similarity index 100% rename from ToyEngine/Models/shoot_gun/textures/Glovemat_normal.png rename to Demo/Models/shoot_gun/textures/Glovemat_normal.png diff --git a/ToyEngine/Models/shoot_gun/textures/Glovemat_specularGlossiness.png b/Demo/Models/shoot_gun/textures/Glovemat_specularGlossiness.png similarity index 100% rename from ToyEngine/Models/shoot_gun/textures/Glovemat_specularGlossiness.png rename to Demo/Models/shoot_gun/textures/Glovemat_specularGlossiness.png diff --git a/ToyEngine/Models/shoot_gun/textures/Hairmat_diffuse.png b/Demo/Models/shoot_gun/textures/Hairmat_diffuse.png similarity index 100% rename from ToyEngine/Models/shoot_gun/textures/Hairmat_diffuse.png rename to Demo/Models/shoot_gun/textures/Hairmat_diffuse.png diff --git a/ToyEngine/Models/shoot_gun/textures/Hairmat_normal.png b/Demo/Models/shoot_gun/textures/Hairmat_normal.png similarity index 100% rename from ToyEngine/Models/shoot_gun/textures/Hairmat_normal.png rename to Demo/Models/shoot_gun/textures/Hairmat_normal.png diff --git a/ToyEngine/Models/shoot_gun/textures/Hairmat_specularGlossiness.png b/Demo/Models/shoot_gun/textures/Hairmat_specularGlossiness.png similarity index 100% rename from ToyEngine/Models/shoot_gun/textures/Hairmat_specularGlossiness.png rename to Demo/Models/shoot_gun/textures/Hairmat_specularGlossiness.png diff --git a/ToyEngine/Models/shoot_gun/textures/Hatmat_diffuse.png b/Demo/Models/shoot_gun/textures/Hatmat_diffuse.png similarity index 100% rename from ToyEngine/Models/shoot_gun/textures/Hatmat_diffuse.png rename to Demo/Models/shoot_gun/textures/Hatmat_diffuse.png diff --git a/ToyEngine/Models/shoot_gun/textures/Hatmat_normal.png b/Demo/Models/shoot_gun/textures/Hatmat_normal.png similarity index 100% rename from ToyEngine/Models/shoot_gun/textures/Hatmat_normal.png rename to Demo/Models/shoot_gun/textures/Hatmat_normal.png diff --git a/ToyEngine/Models/shoot_gun/textures/Hatmat_specularGlossiness.png b/Demo/Models/shoot_gun/textures/Hatmat_specularGlossiness.png similarity index 100% rename from ToyEngine/Models/shoot_gun/textures/Hatmat_specularGlossiness.png rename to Demo/Models/shoot_gun/textures/Hatmat_specularGlossiness.png diff --git a/ToyEngine/Models/shoot_gun/textures/Shoesmat_diffuse.png b/Demo/Models/shoot_gun/textures/Shoesmat_diffuse.png similarity index 100% rename from ToyEngine/Models/shoot_gun/textures/Shoesmat_diffuse.png rename to Demo/Models/shoot_gun/textures/Shoesmat_diffuse.png diff --git a/ToyEngine/Models/shoot_gun/textures/Shoesmat_normal.png b/Demo/Models/shoot_gun/textures/Shoesmat_normal.png similarity index 100% rename from ToyEngine/Models/shoot_gun/textures/Shoesmat_normal.png rename to Demo/Models/shoot_gun/textures/Shoesmat_normal.png diff --git a/ToyEngine/Models/shoot_gun/textures/Shoesmat_specularGlossiness.png b/Demo/Models/shoot_gun/textures/Shoesmat_specularGlossiness.png similarity index 100% rename from ToyEngine/Models/shoot_gun/textures/Shoesmat_specularGlossiness.png rename to Demo/Models/shoot_gun/textures/Shoesmat_specularGlossiness.png diff --git a/ToyEngine/Models/shoot_gun/textures/Topmat_diffuse.png b/Demo/Models/shoot_gun/textures/Topmat_diffuse.png similarity index 100% rename from ToyEngine/Models/shoot_gun/textures/Topmat_diffuse.png rename to Demo/Models/shoot_gun/textures/Topmat_diffuse.png diff --git a/ToyEngine/Models/shoot_gun/textures/Topmat_normal.png b/Demo/Models/shoot_gun/textures/Topmat_normal.png similarity index 100% rename from ToyEngine/Models/shoot_gun/textures/Topmat_normal.png rename to Demo/Models/shoot_gun/textures/Topmat_normal.png diff --git a/ToyEngine/Models/shoot_gun/textures/Topmat_specularGlossiness.png b/Demo/Models/shoot_gun/textures/Topmat_specularGlossiness.png similarity index 100% rename from ToyEngine/Models/shoot_gun/textures/Topmat_specularGlossiness.png rename to Demo/Models/shoot_gun/textures/Topmat_specularGlossiness.png diff --git a/ToyEngine/Models/vampire/Vampire_diffuse.png b/Demo/Models/vampire/Vampire_diffuse.png similarity index 100% rename from ToyEngine/Models/vampire/Vampire_diffuse.png rename to Demo/Models/vampire/Vampire_diffuse.png diff --git a/ToyEngine/Models/vampire/Vampire_emission.png b/Demo/Models/vampire/Vampire_emission.png similarity index 100% rename from ToyEngine/Models/vampire/Vampire_emission.png rename to Demo/Models/vampire/Vampire_emission.png diff --git a/ToyEngine/Models/vampire/vampire.bin b/Demo/Models/vampire/vampire.bin similarity index 100% rename from ToyEngine/Models/vampire/vampire.bin rename to Demo/Models/vampire/vampire.bin diff --git a/ToyEngine/Models/vampire/vampire.gltf b/Demo/Models/vampire/vampire.gltf similarity index 100% rename from ToyEngine/Models/vampire/vampire.gltf rename to Demo/Models/vampire/vampire.gltf diff --git a/Exp1/Engine/HDRI/clarens_midday_4k.hdr b/Exp1/Engine/HDRI/clarens_midday_4k.hdr new file mode 100644 index 0000000..55d4894 Binary files /dev/null and b/Exp1/Engine/HDRI/clarens_midday_4k.hdr differ diff --git a/Exp1/Engine/Shaders/brdf_lut.comp b/Exp1/Engine/Shaders/brdf_lut.comp new file mode 100644 index 0000000..b52ac90 --- /dev/null +++ b/Exp1/Engine/Shaders/brdf_lut.comp @@ -0,0 +1,116 @@ +#version 450 core + +layout(local_size_x = 8, local_size_y = 8) in; +layout(rg16f, binding = 0) uniform image2D brdfLUT; + +const float PI = 3.14159265359; +// ---------------------------------------------------------------------------- +// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html +// efficient VanDerCorpus calculation. +float RadicalInverse_VdC(uint bits) +{ + bits = (bits << 16u) | (bits >> 16u); + bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); + bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); + bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); + bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); + return float(bits) * 2.3283064365386963e-10; // / 0x100000000 +} +// ---------------------------------------------------------------------------- +vec2 Hammersley(uint i, uint N) +{ + return vec2(float(i)/float(N), RadicalInverse_VdC(i)); +} +// ---------------------------------------------------------------------------- +vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness) +{ + float a = roughness*roughness; + + float phi = 2.0 * PI * Xi.x; + float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y)); + float sinTheta = sqrt(1.0 - cosTheta*cosTheta); + + // from spherical coordinates to cartesian coordinates - halfway vector + vec3 H; + H.x = cos(phi) * sinTheta; + H.y = sin(phi) * sinTheta; + H.z = cosTheta; + + // from tangent-space H vector to world-space sample vector + vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); + vec3 tangent = normalize(cross(up, N)); + vec3 bitangent = cross(N, tangent); + + vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z; + return normalize(sampleVec); +} +// ---------------------------------------------------------------------------- +float GeometrySchlickGGX(float NdotV, float roughness) +{ + // note that we use a different k for IBL + float a = roughness; + float k = (a * a) / 2.0; + + float nom = NdotV; + float denom = NdotV * (1.0 - k) + k; + + return nom / denom; +} +// ---------------------------------------------------------------------------- +float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness) +{ + float NdotV = max(dot(N, V), 0.0); + float NdotL = max(dot(N, L), 0.0); + float ggx2 = GeometrySchlickGGX(NdotV, roughness); + float ggx1 = GeometrySchlickGGX(NdotL, roughness); + + return ggx1 * ggx2; +} +// ---------------------------------------------------------------------------- +vec2 IntegrateBRDF(float NdotV, float roughness) +{ + vec3 V; + V.x = sqrt(1.0 - NdotV*NdotV); + V.y = 0.0; + V.z = NdotV; + + float A = 0.0; + float B = 0.0; + + vec3 N = vec3(0.0, 0.0, 1.0); + + const uint SAMPLE_COUNT = 1024u; + for(uint i = 0u; i < SAMPLE_COUNT; ++i) + { + // generates a sample vector that's biased towards the + // preferred alignment direction (importance sampling). + vec2 Xi = Hammersley(i, SAMPLE_COUNT); + vec3 H = ImportanceSampleGGX(Xi, N, roughness); + vec3 L = normalize(2.0 * dot(V, H) * H - V); + + float NdotL = max(L.z, 0.0); + float NdotH = max(H.z, 0.0); + float VdotH = max(dot(V, H), 0.0); + + if(NdotL > 0.0) + { + float G = GeometrySmith(N, V, L, roughness); + float G_Vis = (G * VdotH) / (NdotH * NdotV); + float Fc = pow(1.0 - VdotH, 5.0); + + A += (1.0 - Fc) * G_Vis; + B += Fc * G_Vis; + } + } + A /= float(SAMPLE_COUNT); + B /= float(SAMPLE_COUNT); + return vec2(A, B); +} +// ---------------------------------------------------------------------------- +void main() +{ + uvec2 pixelLocation = gl_GlobalInvocationID.xy; + vec2 texCoords = (vec2(pixelLocation)+vec2(0.5))/vec2(imageSize(brdfLUT)); + vec2 integratedBRDF = IntegrateBRDF(texCoords.x, texCoords.y); + imageStore(brdfLUT, ivec2(pixelLocation), vec4(integratedBRDF,0,0)); +} \ No newline at end of file diff --git a/Exp1/Engine/Shaders/cubemap.frag b/Exp1/Engine/Shaders/cubemap.frag new file mode 100644 index 0000000..8e9bd85 --- /dev/null +++ b/Exp1/Engine/Shaders/cubemap.frag @@ -0,0 +1,22 @@ +#version 450 core +out vec4 FragColor; +in vec3 WorldPos; + +uniform sampler2D equirectangularMap; + +const vec2 invAtan = vec2(0.1591, 0.3183); +vec2 SampleSphericalMap(vec3 v) +{ + vec2 uv = vec2(atan(v.z, v.x), asin(v.y)); + uv *= invAtan; + uv += 0.5; + return uv; +} + +void main() +{ + vec2 uv = SampleSphericalMap(normalize(WorldPos)); + vec3 color = texture(equirectangularMap, uv).rgb; + + FragColor = vec4(color, 1.0); +} diff --git a/Exp1/Engine/Shaders/cubemap.vert b/Exp1/Engine/Shaders/cubemap.vert new file mode 100644 index 0000000..19dc4ef --- /dev/null +++ b/Exp1/Engine/Shaders/cubemap.vert @@ -0,0 +1,13 @@ +#version 450 core +layout (location = 0) in vec3 aPos; + +out vec3 WorldPos; + +uniform mat4 projection; +uniform mat4 view; + +void main() +{ + WorldPos = aPos; + gl_Position = projection * view * vec4(WorldPos, 1.0); +} \ No newline at end of file diff --git a/Exp1/Engine/Shaders/cubemap_prefilter.frag b/Exp1/Engine/Shaders/cubemap_prefilter.frag new file mode 100644 index 0000000..9214443 --- /dev/null +++ b/Exp1/Engine/Shaders/cubemap_prefilter.frag @@ -0,0 +1,107 @@ +#version 450 core +out vec4 FragColor; +in vec3 WorldPos; + +uniform samplerCube environmentMap; +uniform float roughness; + +const float PI = 3.14159265359; +// ---------------------------------------------------------------------------- +float DistributionGGX(vec3 N, vec3 H, float roughness) +{ + float a = roughness*roughness; + float a2 = a*a; + float NdotH = max(dot(N, H), 0.0); + float NdotH2 = NdotH*NdotH; + + float nom = a2; + float denom = (NdotH2 * (a2 - 1.0) + 1.0); + denom = PI * denom * denom; + + return nom / denom; +} +// ---------------------------------------------------------------------------- +// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html +// efficient VanDerCorpus calculation. +float RadicalInverse_VdC(uint bits) +{ + bits = (bits << 16u) | (bits >> 16u); + bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); + bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); + bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); + bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); + return float(bits) * 2.3283064365386963e-10; // / 0x100000000 +} +// ---------------------------------------------------------------------------- +vec2 Hammersley(uint i, uint N) +{ + return vec2(float(i)/float(N), RadicalInverse_VdC(i)); +} +// ---------------------------------------------------------------------------- +vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness) +{ + float a = roughness*roughness; + + float phi = 2.0 * PI * Xi.x; + float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y)); + float sinTheta = sqrt(1.0 - cosTheta*cosTheta); + + // from spherical coordinates to cartesian coordinates - halfway vector + vec3 H; + H.x = cos(phi) * sinTheta; + H.y = sin(phi) * sinTheta; + H.z = cosTheta; + + // from tangent-space H vector to world-space sample vector + vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); + vec3 tangent = normalize(cross(up, N)); + vec3 bitangent = cross(N, tangent); + + vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z; + return normalize(sampleVec); +} +// ---------------------------------------------------------------------------- +void main() +{ + vec3 N = normalize(WorldPos); + + // make the simplyfying assumption that V equals R equals the normal + vec3 R = N; + vec3 V = R; + + const uint SAMPLE_COUNT = 1024u; + vec3 prefilteredColor = vec3(0.0); + float totalWeight = 0.0; + + for(uint i = 0u; i < SAMPLE_COUNT; ++i) + { + // generates a sample vector that's biased towards the preferred alignment direction (importance sampling). + vec2 Xi = Hammersley(i, SAMPLE_COUNT); + vec3 H = ImportanceSampleGGX(Xi, N, roughness); + vec3 L = normalize(2.0 * dot(V, H) * H - V); + + float NdotL = max(dot(N, L), 0.0); + if(NdotL > 0.0) + { + // sample from the environment's mip level based on roughness/pdf + float D = DistributionGGX(N, H, roughness); + float NdotH = max(dot(N, H), 0.0); + float HdotV = max(dot(H, V), 0.0); + float pdf = D * NdotH / (4.0 * HdotV) + 0.0001; + + //float resolution = 512.0; // resolution of source cubemap (per face) + float resolution = float(textureSize(environmentMap,0).x); // resolution of source cubemap (per face) + float saTexel = 4.0 * PI / (6.0 * resolution * resolution); + float saSample = 1.0 / (float(SAMPLE_COUNT) * pdf + 0.0001); + + float mipLevel = roughness == 0.0 ? 0.0 : 0.5 * log2(saSample / saTexel); + + prefilteredColor += textureLod(environmentMap, L, mipLevel).rgb * NdotL; + totalWeight += NdotL; + } + } + + prefilteredColor = prefilteredColor / totalWeight; + + FragColor = vec4(prefilteredColor, 1.0); +} diff --git a/Exp1/Engine/Shaders/debug.frag b/Exp1/Engine/Shaders/debug.frag new file mode 100644 index 0000000..a182182 --- /dev/null +++ b/Exp1/Engine/Shaders/debug.frag @@ -0,0 +1,14 @@ +#version 450 core + +layout (location = 4) out vec4 gDebug; + +in vec2 TexCoords; +in vec3 WorldPos; +in vec3 Normal; + +uniform vec3 color; + +void main() +{ + gDebug = vec4(color,1); +} \ No newline at end of file diff --git a/Exp1/Engine/Shaders/debug.vert b/Exp1/Engine/Shaders/debug.vert new file mode 100644 index 0000000..8e2587b --- /dev/null +++ b/Exp1/Engine/Shaders/debug.vert @@ -0,0 +1,22 @@ +#version 330 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; +layout (location = 2) in vec2 aTexCoords; + +out vec2 TexCoords; +out vec3 WorldPos; +out vec3 Normal; + +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; + +void main() +{ + TexCoords = aTexCoords; + WorldPos = vec3(model * vec4(aPos, 1.0)); + Normal = mat3(model) * aNormal; + + gl_Position = projection * view * vec4(WorldPos, 1.0); + +} \ No newline at end of file diff --git a/Exp1/Engine/Shaders/final.frag b/Exp1/Engine/Shaders/final.frag new file mode 100644 index 0000000..9c894c6 --- /dev/null +++ b/Exp1/Engine/Shaders/final.frag @@ -0,0 +1,42 @@ +#version 450 core + +out vec4 FragColor; + +in vec2 TexCoords; + +uniform sampler2D gBaseColor; +uniform sampler2D gDebug; +uniform float exposure = 1; +uniform bool showDebug = false; + +vec3 ACESToneMapping(vec3 color) +{ + const float A = 2.51; + const float B = 0.03; + const float C = 2.43; + const float D = 0.59; + const float E = 0.14; + return (color * (A * color + B)) / (color * (C * color + D) + E); +} + +void main() +{ + vec4 rgbm = texture(gBaseColor, TexCoords); + vec4 debug = texture(gDebug, TexCoords); + if(rgbm.a==0 && (showDebug ? debug.a==0 : true)) + { + //FragColor = vec4(1,0,0,1); + //return; + discard; + } + vec3 color = 8 * rgbm.rgb * rgbm.a; + + color *= exposure; + color = ACESToneMapping(color); + + //color = color / (color + vec3(1.0)); + color = pow(color, vec3(1.0/2.2)); + FragColor = vec4(color, 1.0); + if(showDebug) + FragColor = mix(FragColor, debug, debug.a); +} \ No newline at end of file diff --git a/Exp1/Engine/Shaders/final.vert b/Exp1/Engine/Shaders/final.vert new file mode 100644 index 0000000..6317aab --- /dev/null +++ b/Exp1/Engine/Shaders/final.vert @@ -0,0 +1,11 @@ +#version 450 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec2 aTexCoords; + +out vec2 TexCoords; + +void main() +{ + TexCoords = aTexCoords; + gl_Position = vec4(aPos, 1.0); +} \ No newline at end of file diff --git a/Exp1/Engine/Shaders/irradiance_convolution.frag b/Exp1/Engine/Shaders/irradiance_convolution.frag new file mode 100644 index 0000000..7e9e642 --- /dev/null +++ b/Exp1/Engine/Shaders/irradiance_convolution.frag @@ -0,0 +1,43 @@ +#version 450 core +out vec4 FragColor; +in vec3 WorldPos; + +uniform samplerCube environmentMap; + +const float PI = 3.14159265359; + +void main() +{ + // The world vector acts as the normal of a tangent surface + // from the origin, aligned to WorldPos. Given this normal, calculate all + // incoming radiance of the environment. The result of this radiance + // is the radiance of light coming from -Normal direction, which is what + // we use in the PBR shader to sample irradiance. + vec3 N = normalize(WorldPos); + + vec3 irradiance = vec3(0.0); + + // tangent space calculation from origin point + vec3 up = vec3(0.0, 1.0, 0.0); + vec3 right = normalize(cross(up, N)); + up = normalize(cross(N, right)); + + float sampleDelta = 0.025; + float nrSamples = 0.0; + for(float phi = 0.0; phi < 2.0 * PI; phi += sampleDelta) + { + for(float theta = 0.0; theta < 0.5 * PI; theta += sampleDelta) + { + // spherical to cartesian (in tangent space) + vec3 tangentSample = vec3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta)); + // tangent space to world + vec3 sampleVec = tangentSample.x * right + tangentSample.y * up + tangentSample.z * N; + + irradiance += texture(environmentMap, sampleVec).rgb * cos(theta) * sin(theta); + nrSamples++; + } + } + irradiance = PI * irradiance * (1.0 / float(nrSamples)); + + FragColor = vec4(irradiance, 1.0); +} diff --git a/Exp1/Engine/Shaders/model.frag b/Exp1/Engine/Shaders/model.frag new file mode 100644 index 0000000..22c49e2 --- /dev/null +++ b/Exp1/Engine/Shaders/model.frag @@ -0,0 +1,61 @@ +#version 450 core +uniform sampler2D texture_basecolor; +uniform sampler2D texture_metallic_roughness; +uniform sampler2D texture_normal; + +uniform bool texture_basecolor_available = false; +uniform bool texture_metallic_roughness_available = false; +uniform bool texture_normal_available = false; + +uniform vec3 baseColor; +uniform vec2 metallicRoughness; + +layout (location = 0) out vec4 gBaseColor; +layout (location = 1) out vec3 gNormal; +layout (location = 2) out vec3 gPosition; +layout (location = 3) out vec2 gMetallicRoughness; +layout (location = 4) out vec4 gDebug; + +in vec2 TexCoords; +in vec3 WorldPos; +in vec3 Normal; + +vec3 getNormalFromMap() +{ + vec3 tangentNormal = texture(texture_normal, TexCoords).xyz * 2.0 - 1.0; + + vec3 Q1 = dFdx(WorldPos); + vec3 Q2 = dFdy(WorldPos); + vec2 st1 = dFdx(TexCoords); + vec2 st2 = dFdy(TexCoords); + + vec3 N = normalize(Normal); + vec3 T = normalize(Q1*st2.t - Q2*st1.t); + vec3 B = -normalize(cross(N, T)); + mat3 TBN = mat3(T, B, N); + + return normalize(TBN * tangentNormal); +} + +void main() +{ + if(texture_basecolor_available) + gBaseColor = texture(texture_basecolor, TexCoords); + else + gBaseColor = vec4(baseColor, 1); + if(gBaseColor.a<0.4) + discard; + gPosition = WorldPos; + if(texture_normal_available) + gNormal = getNormalFromMap(); + else + gNormal = Normal; + if(!gl_FrontFacing) + gNormal = -gNormal; + if(texture_metallic_roughness_available) + gMetallicRoughness = texture(texture_metallic_roughness, TexCoords).bg; + else + gMetallicRoughness = metallicRoughness; + + gDebug = vec4(0); +} \ No newline at end of file diff --git a/Exp1/Engine/Shaders/model.vert b/Exp1/Engine/Shaders/model.vert new file mode 100644 index 0000000..28f5787 --- /dev/null +++ b/Exp1/Engine/Shaders/model.vert @@ -0,0 +1,55 @@ +#version 450 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; +layout (location = 2) in vec2 aTexCoords; +layout (location = 3) in ivec4 boneIds; +layout (location = 4) in vec4 weights; + +out vec2 TexCoords; +out vec3 WorldPos; +out vec3 Normal; + +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; + +const int MAX_BONES = 100; +const int MAX_BONE_INFLUENCE = 4; +layout (std140, binding = 1) uniform FinalBonesMatrices +{ + mat4 finalBonesMatrices[MAX_BONES]; +}; + +void main() +{ + vec4 totalPosition = vec4(0.0f); + vec3 totalNormal = vec3(0); + int boneCount = 0; + for(int i = 0 ; i < MAX_BONE_INFLUENCE ; i++) + { + if(boneIds[i] == -1) + continue; + if(boneIds[i] >= MAX_BONES) + { + totalPosition = vec4(aPos,1.0f); + break; + } + boneCount++; + vec4 localPosition = finalBonesMatrices[boneIds[i]] * vec4(aPos,1.0f); + totalPosition += localPosition * weights[i]; + vec3 localNormal = mat3(finalBonesMatrices[boneIds[i]]) * aNormal; + totalNormal += localNormal * weights[i]; + } + + if(boneCount == 0) + { + totalPosition = vec4(aPos, 1); + totalNormal = vec3(aNormal); + } + + TexCoords = aTexCoords; + WorldPos = vec3(model * totalPosition); + Normal = mat3(model) * totalNormal; + + gl_Position = projection * view * vec4(WorldPos, 1.0); +} \ No newline at end of file diff --git a/Exp1/Engine/Shaders/model_shadow.frag b/Exp1/Engine/Shaders/model_shadow.frag new file mode 100644 index 0000000..8b44c38 --- /dev/null +++ b/Exp1/Engine/Shaders/model_shadow.frag @@ -0,0 +1,12 @@ +#version 450 core + +uniform sampler2D texture_basecolor; + +in vec2 TexCoords; + +void main() +{ + vec4 baseColor = texture(texture_basecolor, TexCoords); + if(baseColor.a<0.4) + discard; +} \ No newline at end of file diff --git a/Exp1/Engine/Shaders/model_shadow.geom b/Exp1/Engine/Shaders/model_shadow.geom new file mode 100644 index 0000000..d2960c9 --- /dev/null +++ b/Exp1/Engine/Shaders/model_shadow.geom @@ -0,0 +1,24 @@ +#version 450 core + +layout(triangles, invocations = 5) in; +layout(triangle_strip, max_vertices = 3) out; + +layout (std140, binding = 0) uniform LightSpaceMatrices +{ + mat4 lightSpaceMatrices[16]; +}; + +in vec2 vTexCoords[]; +out vec2 TexCoords; + +void main() +{ + for (int i = 0; i < 3; ++i) + { + TexCoords = vTexCoords[i]; + gl_Position = lightSpaceMatrices[gl_InvocationID] * gl_in[i].gl_Position; + gl_Layer = gl_InvocationID; + EmitVertex(); + } + EndPrimitive(); +} \ No newline at end of file diff --git a/Exp1/Engine/Shaders/model_shadow.vert b/Exp1/Engine/Shaders/model_shadow.vert new file mode 100644 index 0000000..f48641d --- /dev/null +++ b/Exp1/Engine/Shaders/model_shadow.vert @@ -0,0 +1,48 @@ +#version 450 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; +layout (location = 2) in vec2 aTexCoords; +layout (location = 3) in ivec4 boneIds; +layout (location = 4) in vec4 weights; + +out vec2 vTexCoords; + +uniform mat4 model; + +const int MAX_BONES = 100; +const int MAX_BONE_INFLUENCE = 4; +layout (std140, binding = 1) uniform FinalBonesMatrices +{ + mat4 finalBonesMatrices[MAX_BONES]; +}; + +void main() +{ + vec4 totalPosition = vec4(0.0f); + vec3 totalNormal = vec3(0); + int boneCount = 0; + for(int i = 0 ; i < MAX_BONE_INFLUENCE ; i++) + { + if(boneIds[i] == -1) + continue; + if(boneIds[i] >= MAX_BONES) + { + totalPosition = vec4(aPos,1.0f); + break; + } + boneCount++; + vec4 localPosition = finalBonesMatrices[boneIds[i]] * vec4(aPos,1.0f); + totalPosition += localPosition * weights[i]; + vec3 localNormal = mat3(finalBonesMatrices[boneIds[i]]) * aNormal; + totalNormal += localNormal * weights[i]; + } + + if(boneCount == 0) + { + totalPosition = vec4(aPos, 1); + totalNormal = vec3(aNormal); + } + + vTexCoords = aTexCoords; + gl_Position = model * totalPosition; +} \ No newline at end of file diff --git a/Exp1/Engine/Shaders/pbr.comp b/Exp1/Engine/Shaders/pbr.comp new file mode 100644 index 0000000..4bd8675 --- /dev/null +++ b/Exp1/Engine/Shaders/pbr.comp @@ -0,0 +1,241 @@ +#version 450 core + +layout (local_size_x = 8, local_size_y = 8) in; + +layout(rgba8, binding = 0) uniform image2D gBaseColor; +uniform sampler2D gNormal; +uniform sampler2D gPosition; +uniform sampler2D gMetallicRoughness; +uniform sampler2DArray gShadowMap; + +uniform samplerCube irradianceMap; +uniform samplerCube prefilterMap; +uniform sampler2D brdfLUT; + +layout (std140, binding = 0) uniform LightSpaceMatrices +{ + mat4 lightSpaceMatrices[16]; +}; +uniform mat4 view; +uniform float farPlane; +uniform float shadowCascadePlaneDistances[16]; +uniform float shadowBiases[16]; +uniform int shadowCascadeCount; +uniform float shadowBlendRatio; + +uniform vec3 mainLightDirection; +uniform vec3 mainLightRadiance; + +uniform vec3 camPos; + +const float PI = 3.14159265359; + +float DistributionGGX(vec3 N, vec3 H, float roughness) +{ + float a = roughness*roughness; + float a2 = a*a; + float NdotH = max(dot(N, H), 0.0); + float NdotH2 = NdotH*NdotH; + + float nom = a2; + float denom = (NdotH2 * (a2 - 1.0) + 1.0); + denom = PI * denom * denom; + + return nom / denom; +} +// ---------------------------------------------------------------------------- +float GeometrySchlickGGX(float NdotV, float roughness) +{ + float r = (roughness + 1.0); + float k = (r*r) / 8.0; + + float nom = NdotV; + float denom = NdotV * (1.0 - k) + k; + + return nom / denom; +} +// ---------------------------------------------------------------------------- +float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness) +{ + float NdotV = max(dot(N, V), 0.0); + float NdotL = max(dot(N, L), 0.0); + float ggx2 = GeometrySchlickGGX(NdotV, roughness); + float ggx1 = GeometrySchlickGGX(NdotL, roughness); + + return ggx1 * ggx2; +} +// ---------------------------------------------------------------------------- +vec3 fresnelSchlick(float cosTheta, vec3 F0) +{ + return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); +} +vec3 fresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness) +{ + return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0); +} + +vec3 ambientLighting(vec3 N, vec3 V, vec3 F0, vec3 albedo, float metallic, float roughness, float ao) +{ + // ambient lighting (we now use IBL as the ambient term) + vec3 F = fresnelSchlickRoughness(clamp(dot(N, V),0.,1.), F0, roughness); + + vec3 kS = F; + vec3 kD = 1.0 - kS; + kD *= 1.0 - metallic; + + vec3 irradiance = texture(irradianceMap, N).rgb; + vec3 diffuse = irradiance * albedo; + + // sample both the pre-filter map and the BRDF lut and combine them together as per the Split-Sum approximation to get the IBL specular part. + const float MAX_REFLECTION_LOD = 4.0; + vec3 R = reflect(-V, N); + vec3 prefilteredColor = textureLod(prefilterMap, R, roughness * MAX_REFLECTION_LOD).rgb; + vec2 brdf = texture(brdfLUT, vec2(clamp(dot(N, V),0.,1.), roughness)).rg; + vec3 specular = prefilteredColor * (F * brdf.x + brdf.y); + + return (kD * diffuse + specular) * ao; +} + + +const int pcfRadius = 3; +float getShadowFromLayer(vec3 fragPosWorldSpace, vec3 normal,int layer) +{ + float normalBias = 1.2*4. /** (1+pcfRadius)*/ * shadowBiases[layer]*max((1.0 - dot(normal, mainLightDirection)), 0.1)/textureSize(gShadowMap, 0).x; + normalBias = max(normalBias, 0.05); + vec4 fragPosLightSpace = lightSpaceMatrices[layer] * vec4(fragPosWorldSpace+normal*normalBias, 1.0); + // perform perspective divide + vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w; + // transform to [0,1] range + projCoords = projCoords * 0.5 + 0.5; + + // get depth of current fragment from light's perspective + float currentDepth = projCoords.z; + + // keep the shadow at 0.0 when outside the far_plane region of the light's frustum. + if (currentDepth > 1.0) + { + return 0.0; + } + + // PCF + float shadow = 0.0; + vec2 texelSize = 1.0 / vec2(textureSize(gShadowMap, 0)); + for(int x = -pcfRadius; x <= pcfRadius; ++x) + { + for(int y = -pcfRadius; y <= pcfRadius; ++y) + { + float pcfDepth = texture(gShadowMap, vec3(projCoords.xy + vec2(x, y) * texelSize, layer)).r; + shadow += currentDepth > pcfDepth ? 1.0 : 0.0; + } + } + shadow /= (2*pcfRadius+1)*(2*pcfRadius+1); + return shadow; +} + +float ShadowCalculation(vec3 fragPosWorldSpace, vec3 normal, out int layer) +{ + // select cascade layer + vec4 fragPosViewSpace = view * vec4(fragPosWorldSpace, 1.0); + float depthValue = abs(fragPosViewSpace.z); + + layer = -1; + for (int i = 0; i < shadowCascadeCount; ++i) + { + if (depthValue < shadowCascadePlaneDistances[i]) + { + layer = i; + break; + } + } +// if (layer == -1) +// { +// layer = shadowCascadeCount; +// } + + float shadow = getShadowFromLayer(fragPosWorldSpace,normal,layer); + + + float nextLayerBeginDepth = layer==0? (1-shadowBlendRatio)*shadowCascadePlaneDistances[layer] + :(1-shadowBlendRatio)*shadowCascadePlaneDistances[layer]+shadowBlendRatio*shadowCascadePlaneDistances[layer-1]; + if(depthValue > nextLayerBeginDepth) + { + float shadowNext = getShadowFromLayer(fragPosWorldSpace,normal,layer+1); + shadow = mix(shadow,shadowNext, (depthValue-nextLayerBeginDepth)/(shadowCascadePlaneDistances[layer]-nextLayerBeginDepth)); + } + return shadow; +} + + + +vec4 encodeRGBM(vec3 color) +{ + if(dot(color,color)==0) + return vec4(0,0,0,1); + vec4 rgbm; + float range = 8; + color /= range; + rgbm.a = clamp(max(max(color.r, color.g), max(color.b, 1e-6)), 0.0, 1.0); + rgbm.a = ceil(rgbm.a * 255.0) / 255.0; + rgbm.rgb = color / rgbm.a; + return rgbm; +} + +void main() +{ + ivec2 pixelLocation = ivec2(gl_GlobalInvocationID.xy); + + + //vec3 albedo = pow(texelFetch(gBaseColor, pixelLocation, 0).rgb, vec3(2.2)); + vec3 albedo = pow(imageLoad(gBaseColor, pixelLocation).rgb, vec3(2.2)); + float metallic = texelFetch(gMetallicRoughness, pixelLocation, 0).r; + float roughness = texelFetch(gMetallicRoughness, pixelLocation, 0).g; + + vec3 worldPos = texelFetch(gPosition, pixelLocation,0).xyz; + vec3 normal = texelFetch(gNormal, pixelLocation,0).xyz; + + if(normal==vec3(0)) + { + //vec3 color = mainLightRadiance; + //imageStore(gBaseColor, pixelLocation, vec4(color, 1.0)); + imageStore(gBaseColor, pixelLocation, vec4(0)); + return; + } + normal = normalize(normal); + + vec3 V = normalize(camPos - worldPos); + + vec3 F0 = vec3(0.04); + F0 = mix(F0, albedo, metallic); + + // calculate light radiance + vec3 L = normalize(mainLightDirection); + vec3 H = normalize(V + L); + //float distance = length(lightPositions[i] - WorldPos); + //float attenuation = 1.0 / (distance * distance); + vec3 radiance = mainLightRadiance ;//* attenuation; + + // cook-torrance brdf + float NDF = DistributionGGX(normal, H, roughness); + float G = GeometrySmith(normal, V, L, roughness); + vec3 F = fresnelSchlick(clamp(dot(H, V),0.,1.), F0); + //F = clamp(F,vec3(0),vec3(1)); + + vec3 kS = F; + vec3 kD = vec3(1.0) - kS; + kD *= 1.0 - metallic; + + vec3 nominator = NDF * G * F; + float denominator = 4.0 * max(dot(normal, V), 0.0) * max(dot(normal, L), 0.0) + 0.001; + vec3 specular = nominator / denominator; + + float NdotL = max(dot(normal, L), 0.0); + vec3 Lo = (kD * albedo / PI + specular) * radiance * NdotL; + + vec3 ambient = ambientLighting(normal, V, F0, albedo, metallic, roughness, 1); + + int debugLayer; + float shadow = ShadowCalculation(worldPos, normal, debugLayer); + + vec3 color = (1-shadow)*Lo + ambient; + imageStore(gBaseColor, pixelLocation, encodeRGBM(color)); +} \ No newline at end of file diff --git a/Exp1/Engine/Shaders/plain.frag b/Exp1/Engine/Shaders/plain.frag new file mode 100644 index 0000000..6c11f5b --- /dev/null +++ b/Exp1/Engine/Shaders/plain.frag @@ -0,0 +1,23 @@ +#version 450 core + +layout (location = 0) out vec4 gBaseColor; +layout (location = 1) out vec3 gNormal; +layout (location = 2) out vec3 gPosition; +layout (location = 3) out vec2 gMetallicRoughness; + +in vec2 TexCoords; +in vec3 WorldPos; +in vec3 Normal; + +// material parameters +uniform vec3 albedo; +uniform float metallic; +uniform float roughness; + +void main() +{ + gBaseColor = vec4(albedo, 1); + gPosition = WorldPos; + gNormal = normalize(Normal); + gMetallicRoughness = vec2(metallic,roughness); +} \ No newline at end of file diff --git a/Exp1/Engine/Shaders/plain.vert b/Exp1/Engine/Shaders/plain.vert new file mode 100644 index 0000000..8e2587b --- /dev/null +++ b/Exp1/Engine/Shaders/plain.vert @@ -0,0 +1,22 @@ +#version 330 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; +layout (location = 2) in vec2 aTexCoords; + +out vec2 TexCoords; +out vec3 WorldPos; +out vec3 Normal; + +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; + +void main() +{ + TexCoords = aTexCoords; + WorldPos = vec3(model * vec4(aPos, 1.0)); + Normal = mat3(model) * aNormal; + + gl_Position = projection * view * vec4(WorldPos, 1.0); + +} \ No newline at end of file diff --git a/Exp1/Engine/Shaders/skybox.frag b/Exp1/Engine/Shaders/skybox.frag new file mode 100644 index 0000000..fa086dd --- /dev/null +++ b/Exp1/Engine/Shaders/skybox.frag @@ -0,0 +1,32 @@ +#version 450 core +out vec4 FragColor; +in vec3 WorldPos; + +uniform samplerCube environmentMap; +uniform float exposure = 1; + +vec3 ACESToneMapping(vec3 color) +{ + const float A = 2.51; + const float B = 0.03; + const float C = 2.43; + const float D = 0.59; + const float E = 0.14; + return (color * (A * color + B)) / (color * (C * color + D) + E); +} + +void main() +{ + vec3 color = texture(environmentMap, WorldPos).rgb; + + // HDR tonemap + //envColor = envColor / (envColor + vec3(1.0)); + + color *= exposure; + color = ACESToneMapping(color); + + // gamma correct + color = pow(color, vec3(1.0/2.2)); + + FragColor = vec4(color, 1.0); +} diff --git a/Exp1/Engine/Shaders/skybox.vert b/Exp1/Engine/Shaders/skybox.vert new file mode 100644 index 0000000..f2d2cbb --- /dev/null +++ b/Exp1/Engine/Shaders/skybox.vert @@ -0,0 +1,17 @@ +#version 450 core +layout (location = 0) in vec3 aPos; + +uniform mat4 projection; +uniform mat4 view; + +out vec3 WorldPos; + +void main() +{ + WorldPos = aPos; + + mat4 rotView = mat4(mat3(view)); + vec4 clipPos = projection * rotView * vec4(WorldPos, 1.0); + + gl_Position = clipPos.xyww; +} \ No newline at end of file diff --git a/Exp1/Exp1.cpp b/Exp1/Exp1.cpp new file mode 100644 index 0000000..404c306 --- /dev/null +++ b/Exp1/Exp1.cpp @@ -0,0 +1,8 @@ +#include +#include "ModelWorld.h" + +int main() +{ + MainWindow::instance().initialize(); + return MainWindow::instance().exec(std::make_unique()); +} \ No newline at end of file diff --git a/Exp1/Exp1.vcxproj b/Exp1/Exp1.vcxproj new file mode 100644 index 0000000..fbaa9a3 --- /dev/null +++ b/Exp1/Exp1.vcxproj @@ -0,0 +1,156 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {8013f6a0-c953-415b-a48d-f425e63ead09} + Exp1 + 10.0 + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + $(SolutionDir)ToyEngine\include;$(SolutionDir)ToyEngine\src;%(AdditionalIncludeDirectories) + stdcpp20 + stdc17 + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + $(SolutionDir)ToyEngine\include;$(SolutionDir)ToyEngine\src;%(AdditionalIncludeDirectories) + stdcpp20 + stdc17 + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + $(SolutionDir)ToyEngine\include;$(SolutionDir)ToyEngine\src;%(AdditionalIncludeDirectories) + stdcpp20 + stdc17 + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + $(SolutionDir)ToyEngine\include;$(SolutionDir)ToyEngine\src;%(AdditionalIncludeDirectories) + stdcpp20 + stdc17 + + + Console + true + true + true + + + + + + + + + {65d6ee2b-fffa-4ef6-8042-9ca7a0f8e67e} + + + + + + + + + \ No newline at end of file diff --git a/Exp1/Exp1.vcxproj.filters b/Exp1/Exp1.vcxproj.filters new file mode 100644 index 0000000..5013415 --- /dev/null +++ b/Exp1/Exp1.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + 源文件 + + + 源文件 + + + + + 头文件 + + + \ No newline at end of file diff --git a/Exp1/ModelWorld.cpp b/Exp1/ModelWorld.cpp new file mode 100644 index 0000000..9b33451 --- /dev/null +++ b/Exp1/ModelWorld.cpp @@ -0,0 +1,68 @@ +#include "ModelWorld.h" +#include + +ModelWorld::ModelWorld() +{ + light.lightDirection = glm::normalize(glm::vec3((cos(lightPitch) * cos(lightYaw)), (sin(lightPitch)), (cos(lightPitch) * sin(lightYaw)))); + light.radiance = 3.f * lightColor; + RenderingSystem::instance().exposure = 0.45f; + + model = std::make_shared("Models/David_Brown_25D_tractor_SF/David_Brown_25D_tractor_SF.obj"); + model->setPosition({ 0,0,0 }); + addActor(model); + + camera.Position = { 0,10,20 }; +} + +void ModelWorld::logicalTick(float deltaTime) +{ + World::logicalTick(deltaTime); +} + +void ModelWorld::rendererTick(float deltaTime) +{ + World::rendererTick(deltaTime); +} + +void ModelWorld::cursorPosCallback(GLFWwindow* window, double xpos, double ypos) +{ + static bool firstMouse = true; + static float lastX; + static float lastY; + + float xoffset = xpos - lastX; + float yoffset = lastY - ypos; + + lastX = xpos; + lastY = ypos; + + if (firstMouse) + { + firstMouse = false; + return; + } + + if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS) + camera.processMouseMovement(xoffset, yoffset); +} + +void ModelWorld::scrollCallback(GLFWwindow* window, double xoffset, double yoffset) +{ + camera.processMouseScroll(yoffset); +} + +void ModelWorld::processInput(GLFWwindow* window, float deltaTime) +{ + if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) + camera.processKeyboard(FORWARD, deltaTime); + if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) + camera.processKeyboard(BACKWARD, deltaTime); + if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) + camera.processKeyboard(LEFT, deltaTime); + if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) + camera.processKeyboard(RIGHT, deltaTime); + if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS) + camera.processKeyboard(UP, deltaTime); + if (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS) + camera.processKeyboard(DOWN, deltaTime); +} diff --git a/Exp1/ModelWorld.h b/Exp1/ModelWorld.h new file mode 100644 index 0000000..4709891 --- /dev/null +++ b/Exp1/ModelWorld.h @@ -0,0 +1,21 @@ +#pragma once +#include + +class ModelWorld : public World +{ +public: + ModelWorld(); + void logicalTick(float deltaTime) override; + void rendererTick(float deltaTime) override; + virtual void cursorPosCallback(GLFWwindow* window, double xpos, double ypos) override; + virtual void scrollCallback(GLFWwindow* window, double xoffset, double yoffset) override; + virtual void processInput(GLFWwindow* window, float deltaTime) override; + +private: + std::shared_ptr model; + + glm::vec3 lightColor = glm::normalize(glm::vec3(0.7529, 0.7450, 0.6784)); + float lightYaw = glm::radians(80.f); + float lightPitch = glm::radians(105.f); +}; + diff --git a/Exp1/Models/David_Brown_25D_tractor_SF/David_Brown_25D_tractor.jpg b/Exp1/Models/David_Brown_25D_tractor_SF/David_Brown_25D_tractor.jpg new file mode 100644 index 0000000..806eaad Binary files /dev/null and b/Exp1/Models/David_Brown_25D_tractor_SF/David_Brown_25D_tractor.jpg differ diff --git a/Exp1/Models/David_Brown_25D_tractor_SF/David_Brown_25D_tractor_SF.mtl b/Exp1/Models/David_Brown_25D_tractor_SF/David_Brown_25D_tractor_SF.mtl new file mode 100644 index 0000000..97a2dda --- /dev/null +++ b/Exp1/Models/David_Brown_25D_tractor_SF/David_Brown_25D_tractor_SF.mtl @@ -0,0 +1,14 @@ +# Blender MTL File: 'None' +# Material Count: 1 + +newmtl David_Brown_25D_tractor +Ns 0.000000 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ke 0.000000 0.000000 0.000000 +Ni 1.450000 +d 1.000000 +illum 1 +map_Bump david_brown_25d_tractor_Normal Map from Mesh.jpg +map_Kd David_Brown_25D_tractor.jpg diff --git a/Exp1/Models/David_Brown_25D_tractor_SF/david_brown_25d_tractor_Normal Map from Mesh.jpg b/Exp1/Models/David_Brown_25D_tractor_SF/david_brown_25d_tractor_Normal Map from Mesh.jpg new file mode 100644 index 0000000..168e27b Binary files /dev/null and b/Exp1/Models/David_Brown_25D_tractor_SF/david_brown_25d_tractor_Normal Map from Mesh.jpg differ diff --git a/Exp2/Engine/HDRI/clarens_midday_4k.hdr b/Exp2/Engine/HDRI/clarens_midday_4k.hdr new file mode 100644 index 0000000..55d4894 Binary files /dev/null and b/Exp2/Engine/HDRI/clarens_midday_4k.hdr differ diff --git a/Exp2/Engine/Shaders/brdf_lut.comp b/Exp2/Engine/Shaders/brdf_lut.comp new file mode 100644 index 0000000..b52ac90 --- /dev/null +++ b/Exp2/Engine/Shaders/brdf_lut.comp @@ -0,0 +1,116 @@ +#version 450 core + +layout(local_size_x = 8, local_size_y = 8) in; +layout(rg16f, binding = 0) uniform image2D brdfLUT; + +const float PI = 3.14159265359; +// ---------------------------------------------------------------------------- +// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html +// efficient VanDerCorpus calculation. +float RadicalInverse_VdC(uint bits) +{ + bits = (bits << 16u) | (bits >> 16u); + bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); + bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); + bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); + bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); + return float(bits) * 2.3283064365386963e-10; // / 0x100000000 +} +// ---------------------------------------------------------------------------- +vec2 Hammersley(uint i, uint N) +{ + return vec2(float(i)/float(N), RadicalInverse_VdC(i)); +} +// ---------------------------------------------------------------------------- +vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness) +{ + float a = roughness*roughness; + + float phi = 2.0 * PI * Xi.x; + float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y)); + float sinTheta = sqrt(1.0 - cosTheta*cosTheta); + + // from spherical coordinates to cartesian coordinates - halfway vector + vec3 H; + H.x = cos(phi) * sinTheta; + H.y = sin(phi) * sinTheta; + H.z = cosTheta; + + // from tangent-space H vector to world-space sample vector + vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); + vec3 tangent = normalize(cross(up, N)); + vec3 bitangent = cross(N, tangent); + + vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z; + return normalize(sampleVec); +} +// ---------------------------------------------------------------------------- +float GeometrySchlickGGX(float NdotV, float roughness) +{ + // note that we use a different k for IBL + float a = roughness; + float k = (a * a) / 2.0; + + float nom = NdotV; + float denom = NdotV * (1.0 - k) + k; + + return nom / denom; +} +// ---------------------------------------------------------------------------- +float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness) +{ + float NdotV = max(dot(N, V), 0.0); + float NdotL = max(dot(N, L), 0.0); + float ggx2 = GeometrySchlickGGX(NdotV, roughness); + float ggx1 = GeometrySchlickGGX(NdotL, roughness); + + return ggx1 * ggx2; +} +// ---------------------------------------------------------------------------- +vec2 IntegrateBRDF(float NdotV, float roughness) +{ + vec3 V; + V.x = sqrt(1.0 - NdotV*NdotV); + V.y = 0.0; + V.z = NdotV; + + float A = 0.0; + float B = 0.0; + + vec3 N = vec3(0.0, 0.0, 1.0); + + const uint SAMPLE_COUNT = 1024u; + for(uint i = 0u; i < SAMPLE_COUNT; ++i) + { + // generates a sample vector that's biased towards the + // preferred alignment direction (importance sampling). + vec2 Xi = Hammersley(i, SAMPLE_COUNT); + vec3 H = ImportanceSampleGGX(Xi, N, roughness); + vec3 L = normalize(2.0 * dot(V, H) * H - V); + + float NdotL = max(L.z, 0.0); + float NdotH = max(H.z, 0.0); + float VdotH = max(dot(V, H), 0.0); + + if(NdotL > 0.0) + { + float G = GeometrySmith(N, V, L, roughness); + float G_Vis = (G * VdotH) / (NdotH * NdotV); + float Fc = pow(1.0 - VdotH, 5.0); + + A += (1.0 - Fc) * G_Vis; + B += Fc * G_Vis; + } + } + A /= float(SAMPLE_COUNT); + B /= float(SAMPLE_COUNT); + return vec2(A, B); +} +// ---------------------------------------------------------------------------- +void main() +{ + uvec2 pixelLocation = gl_GlobalInvocationID.xy; + vec2 texCoords = (vec2(pixelLocation)+vec2(0.5))/vec2(imageSize(brdfLUT)); + vec2 integratedBRDF = IntegrateBRDF(texCoords.x, texCoords.y); + imageStore(brdfLUT, ivec2(pixelLocation), vec4(integratedBRDF,0,0)); +} \ No newline at end of file diff --git a/Exp2/Engine/Shaders/cubemap.frag b/Exp2/Engine/Shaders/cubemap.frag new file mode 100644 index 0000000..8e9bd85 --- /dev/null +++ b/Exp2/Engine/Shaders/cubemap.frag @@ -0,0 +1,22 @@ +#version 450 core +out vec4 FragColor; +in vec3 WorldPos; + +uniform sampler2D equirectangularMap; + +const vec2 invAtan = vec2(0.1591, 0.3183); +vec2 SampleSphericalMap(vec3 v) +{ + vec2 uv = vec2(atan(v.z, v.x), asin(v.y)); + uv *= invAtan; + uv += 0.5; + return uv; +} + +void main() +{ + vec2 uv = SampleSphericalMap(normalize(WorldPos)); + vec3 color = texture(equirectangularMap, uv).rgb; + + FragColor = vec4(color, 1.0); +} diff --git a/Exp2/Engine/Shaders/cubemap.vert b/Exp2/Engine/Shaders/cubemap.vert new file mode 100644 index 0000000..19dc4ef --- /dev/null +++ b/Exp2/Engine/Shaders/cubemap.vert @@ -0,0 +1,13 @@ +#version 450 core +layout (location = 0) in vec3 aPos; + +out vec3 WorldPos; + +uniform mat4 projection; +uniform mat4 view; + +void main() +{ + WorldPos = aPos; + gl_Position = projection * view * vec4(WorldPos, 1.0); +} \ No newline at end of file diff --git a/Exp2/Engine/Shaders/cubemap_prefilter.frag b/Exp2/Engine/Shaders/cubemap_prefilter.frag new file mode 100644 index 0000000..9214443 --- /dev/null +++ b/Exp2/Engine/Shaders/cubemap_prefilter.frag @@ -0,0 +1,107 @@ +#version 450 core +out vec4 FragColor; +in vec3 WorldPos; + +uniform samplerCube environmentMap; +uniform float roughness; + +const float PI = 3.14159265359; +// ---------------------------------------------------------------------------- +float DistributionGGX(vec3 N, vec3 H, float roughness) +{ + float a = roughness*roughness; + float a2 = a*a; + float NdotH = max(dot(N, H), 0.0); + float NdotH2 = NdotH*NdotH; + + float nom = a2; + float denom = (NdotH2 * (a2 - 1.0) + 1.0); + denom = PI * denom * denom; + + return nom / denom; +} +// ---------------------------------------------------------------------------- +// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html +// efficient VanDerCorpus calculation. +float RadicalInverse_VdC(uint bits) +{ + bits = (bits << 16u) | (bits >> 16u); + bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); + bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); + bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); + bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); + return float(bits) * 2.3283064365386963e-10; // / 0x100000000 +} +// ---------------------------------------------------------------------------- +vec2 Hammersley(uint i, uint N) +{ + return vec2(float(i)/float(N), RadicalInverse_VdC(i)); +} +// ---------------------------------------------------------------------------- +vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness) +{ + float a = roughness*roughness; + + float phi = 2.0 * PI * Xi.x; + float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y)); + float sinTheta = sqrt(1.0 - cosTheta*cosTheta); + + // from spherical coordinates to cartesian coordinates - halfway vector + vec3 H; + H.x = cos(phi) * sinTheta; + H.y = sin(phi) * sinTheta; + H.z = cosTheta; + + // from tangent-space H vector to world-space sample vector + vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); + vec3 tangent = normalize(cross(up, N)); + vec3 bitangent = cross(N, tangent); + + vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z; + return normalize(sampleVec); +} +// ---------------------------------------------------------------------------- +void main() +{ + vec3 N = normalize(WorldPos); + + // make the simplyfying assumption that V equals R equals the normal + vec3 R = N; + vec3 V = R; + + const uint SAMPLE_COUNT = 1024u; + vec3 prefilteredColor = vec3(0.0); + float totalWeight = 0.0; + + for(uint i = 0u; i < SAMPLE_COUNT; ++i) + { + // generates a sample vector that's biased towards the preferred alignment direction (importance sampling). + vec2 Xi = Hammersley(i, SAMPLE_COUNT); + vec3 H = ImportanceSampleGGX(Xi, N, roughness); + vec3 L = normalize(2.0 * dot(V, H) * H - V); + + float NdotL = max(dot(N, L), 0.0); + if(NdotL > 0.0) + { + // sample from the environment's mip level based on roughness/pdf + float D = DistributionGGX(N, H, roughness); + float NdotH = max(dot(N, H), 0.0); + float HdotV = max(dot(H, V), 0.0); + float pdf = D * NdotH / (4.0 * HdotV) + 0.0001; + + //float resolution = 512.0; // resolution of source cubemap (per face) + float resolution = float(textureSize(environmentMap,0).x); // resolution of source cubemap (per face) + float saTexel = 4.0 * PI / (6.0 * resolution * resolution); + float saSample = 1.0 / (float(SAMPLE_COUNT) * pdf + 0.0001); + + float mipLevel = roughness == 0.0 ? 0.0 : 0.5 * log2(saSample / saTexel); + + prefilteredColor += textureLod(environmentMap, L, mipLevel).rgb * NdotL; + totalWeight += NdotL; + } + } + + prefilteredColor = prefilteredColor / totalWeight; + + FragColor = vec4(prefilteredColor, 1.0); +} diff --git a/Exp2/Engine/Shaders/debug.frag b/Exp2/Engine/Shaders/debug.frag new file mode 100644 index 0000000..a182182 --- /dev/null +++ b/Exp2/Engine/Shaders/debug.frag @@ -0,0 +1,14 @@ +#version 450 core + +layout (location = 4) out vec4 gDebug; + +in vec2 TexCoords; +in vec3 WorldPos; +in vec3 Normal; + +uniform vec3 color; + +void main() +{ + gDebug = vec4(color,1); +} \ No newline at end of file diff --git a/Exp2/Engine/Shaders/debug.vert b/Exp2/Engine/Shaders/debug.vert new file mode 100644 index 0000000..8e2587b --- /dev/null +++ b/Exp2/Engine/Shaders/debug.vert @@ -0,0 +1,22 @@ +#version 330 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; +layout (location = 2) in vec2 aTexCoords; + +out vec2 TexCoords; +out vec3 WorldPos; +out vec3 Normal; + +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; + +void main() +{ + TexCoords = aTexCoords; + WorldPos = vec3(model * vec4(aPos, 1.0)); + Normal = mat3(model) * aNormal; + + gl_Position = projection * view * vec4(WorldPos, 1.0); + +} \ No newline at end of file diff --git a/Exp2/Engine/Shaders/final.frag b/Exp2/Engine/Shaders/final.frag new file mode 100644 index 0000000..9c894c6 --- /dev/null +++ b/Exp2/Engine/Shaders/final.frag @@ -0,0 +1,42 @@ +#version 450 core + +out vec4 FragColor; + +in vec2 TexCoords; + +uniform sampler2D gBaseColor; +uniform sampler2D gDebug; +uniform float exposure = 1; +uniform bool showDebug = false; + +vec3 ACESToneMapping(vec3 color) +{ + const float A = 2.51; + const float B = 0.03; + const float C = 2.43; + const float D = 0.59; + const float E = 0.14; + return (color * (A * color + B)) / (color * (C * color + D) + E); +} + +void main() +{ + vec4 rgbm = texture(gBaseColor, TexCoords); + vec4 debug = texture(gDebug, TexCoords); + if(rgbm.a==0 && (showDebug ? debug.a==0 : true)) + { + //FragColor = vec4(1,0,0,1); + //return; + discard; + } + vec3 color = 8 * rgbm.rgb * rgbm.a; + + color *= exposure; + color = ACESToneMapping(color); + + //color = color / (color + vec3(1.0)); + color = pow(color, vec3(1.0/2.2)); + FragColor = vec4(color, 1.0); + if(showDebug) + FragColor = mix(FragColor, debug, debug.a); +} \ No newline at end of file diff --git a/Exp2/Engine/Shaders/final.vert b/Exp2/Engine/Shaders/final.vert new file mode 100644 index 0000000..6317aab --- /dev/null +++ b/Exp2/Engine/Shaders/final.vert @@ -0,0 +1,11 @@ +#version 450 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec2 aTexCoords; + +out vec2 TexCoords; + +void main() +{ + TexCoords = aTexCoords; + gl_Position = vec4(aPos, 1.0); +} \ No newline at end of file diff --git a/Exp2/Engine/Shaders/irradiance_convolution.frag b/Exp2/Engine/Shaders/irradiance_convolution.frag new file mode 100644 index 0000000..7e9e642 --- /dev/null +++ b/Exp2/Engine/Shaders/irradiance_convolution.frag @@ -0,0 +1,43 @@ +#version 450 core +out vec4 FragColor; +in vec3 WorldPos; + +uniform samplerCube environmentMap; + +const float PI = 3.14159265359; + +void main() +{ + // The world vector acts as the normal of a tangent surface + // from the origin, aligned to WorldPos. Given this normal, calculate all + // incoming radiance of the environment. The result of this radiance + // is the radiance of light coming from -Normal direction, which is what + // we use in the PBR shader to sample irradiance. + vec3 N = normalize(WorldPos); + + vec3 irradiance = vec3(0.0); + + // tangent space calculation from origin point + vec3 up = vec3(0.0, 1.0, 0.0); + vec3 right = normalize(cross(up, N)); + up = normalize(cross(N, right)); + + float sampleDelta = 0.025; + float nrSamples = 0.0; + for(float phi = 0.0; phi < 2.0 * PI; phi += sampleDelta) + { + for(float theta = 0.0; theta < 0.5 * PI; theta += sampleDelta) + { + // spherical to cartesian (in tangent space) + vec3 tangentSample = vec3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta)); + // tangent space to world + vec3 sampleVec = tangentSample.x * right + tangentSample.y * up + tangentSample.z * N; + + irradiance += texture(environmentMap, sampleVec).rgb * cos(theta) * sin(theta); + nrSamples++; + } + } + irradiance = PI * irradiance * (1.0 / float(nrSamples)); + + FragColor = vec4(irradiance, 1.0); +} diff --git a/Exp2/Engine/Shaders/model.frag b/Exp2/Engine/Shaders/model.frag new file mode 100644 index 0000000..22c49e2 --- /dev/null +++ b/Exp2/Engine/Shaders/model.frag @@ -0,0 +1,61 @@ +#version 450 core +uniform sampler2D texture_basecolor; +uniform sampler2D texture_metallic_roughness; +uniform sampler2D texture_normal; + +uniform bool texture_basecolor_available = false; +uniform bool texture_metallic_roughness_available = false; +uniform bool texture_normal_available = false; + +uniform vec3 baseColor; +uniform vec2 metallicRoughness; + +layout (location = 0) out vec4 gBaseColor; +layout (location = 1) out vec3 gNormal; +layout (location = 2) out vec3 gPosition; +layout (location = 3) out vec2 gMetallicRoughness; +layout (location = 4) out vec4 gDebug; + +in vec2 TexCoords; +in vec3 WorldPos; +in vec3 Normal; + +vec3 getNormalFromMap() +{ + vec3 tangentNormal = texture(texture_normal, TexCoords).xyz * 2.0 - 1.0; + + vec3 Q1 = dFdx(WorldPos); + vec3 Q2 = dFdy(WorldPos); + vec2 st1 = dFdx(TexCoords); + vec2 st2 = dFdy(TexCoords); + + vec3 N = normalize(Normal); + vec3 T = normalize(Q1*st2.t - Q2*st1.t); + vec3 B = -normalize(cross(N, T)); + mat3 TBN = mat3(T, B, N); + + return normalize(TBN * tangentNormal); +} + +void main() +{ + if(texture_basecolor_available) + gBaseColor = texture(texture_basecolor, TexCoords); + else + gBaseColor = vec4(baseColor, 1); + if(gBaseColor.a<0.4) + discard; + gPosition = WorldPos; + if(texture_normal_available) + gNormal = getNormalFromMap(); + else + gNormal = Normal; + if(!gl_FrontFacing) + gNormal = -gNormal; + if(texture_metallic_roughness_available) + gMetallicRoughness = texture(texture_metallic_roughness, TexCoords).bg; + else + gMetallicRoughness = metallicRoughness; + + gDebug = vec4(0); +} \ No newline at end of file diff --git a/Exp2/Engine/Shaders/model.vert b/Exp2/Engine/Shaders/model.vert new file mode 100644 index 0000000..28f5787 --- /dev/null +++ b/Exp2/Engine/Shaders/model.vert @@ -0,0 +1,55 @@ +#version 450 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; +layout (location = 2) in vec2 aTexCoords; +layout (location = 3) in ivec4 boneIds; +layout (location = 4) in vec4 weights; + +out vec2 TexCoords; +out vec3 WorldPos; +out vec3 Normal; + +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; + +const int MAX_BONES = 100; +const int MAX_BONE_INFLUENCE = 4; +layout (std140, binding = 1) uniform FinalBonesMatrices +{ + mat4 finalBonesMatrices[MAX_BONES]; +}; + +void main() +{ + vec4 totalPosition = vec4(0.0f); + vec3 totalNormal = vec3(0); + int boneCount = 0; + for(int i = 0 ; i < MAX_BONE_INFLUENCE ; i++) + { + if(boneIds[i] == -1) + continue; + if(boneIds[i] >= MAX_BONES) + { + totalPosition = vec4(aPos,1.0f); + break; + } + boneCount++; + vec4 localPosition = finalBonesMatrices[boneIds[i]] * vec4(aPos,1.0f); + totalPosition += localPosition * weights[i]; + vec3 localNormal = mat3(finalBonesMatrices[boneIds[i]]) * aNormal; + totalNormal += localNormal * weights[i]; + } + + if(boneCount == 0) + { + totalPosition = vec4(aPos, 1); + totalNormal = vec3(aNormal); + } + + TexCoords = aTexCoords; + WorldPos = vec3(model * totalPosition); + Normal = mat3(model) * totalNormal; + + gl_Position = projection * view * vec4(WorldPos, 1.0); +} \ No newline at end of file diff --git a/Exp2/Engine/Shaders/model_shadow.frag b/Exp2/Engine/Shaders/model_shadow.frag new file mode 100644 index 0000000..8b44c38 --- /dev/null +++ b/Exp2/Engine/Shaders/model_shadow.frag @@ -0,0 +1,12 @@ +#version 450 core + +uniform sampler2D texture_basecolor; + +in vec2 TexCoords; + +void main() +{ + vec4 baseColor = texture(texture_basecolor, TexCoords); + if(baseColor.a<0.4) + discard; +} \ No newline at end of file diff --git a/Exp2/Engine/Shaders/model_shadow.geom b/Exp2/Engine/Shaders/model_shadow.geom new file mode 100644 index 0000000..d2960c9 --- /dev/null +++ b/Exp2/Engine/Shaders/model_shadow.geom @@ -0,0 +1,24 @@ +#version 450 core + +layout(triangles, invocations = 5) in; +layout(triangle_strip, max_vertices = 3) out; + +layout (std140, binding = 0) uniform LightSpaceMatrices +{ + mat4 lightSpaceMatrices[16]; +}; + +in vec2 vTexCoords[]; +out vec2 TexCoords; + +void main() +{ + for (int i = 0; i < 3; ++i) + { + TexCoords = vTexCoords[i]; + gl_Position = lightSpaceMatrices[gl_InvocationID] * gl_in[i].gl_Position; + gl_Layer = gl_InvocationID; + EmitVertex(); + } + EndPrimitive(); +} \ No newline at end of file diff --git a/Exp2/Engine/Shaders/model_shadow.vert b/Exp2/Engine/Shaders/model_shadow.vert new file mode 100644 index 0000000..f48641d --- /dev/null +++ b/Exp2/Engine/Shaders/model_shadow.vert @@ -0,0 +1,48 @@ +#version 450 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; +layout (location = 2) in vec2 aTexCoords; +layout (location = 3) in ivec4 boneIds; +layout (location = 4) in vec4 weights; + +out vec2 vTexCoords; + +uniform mat4 model; + +const int MAX_BONES = 100; +const int MAX_BONE_INFLUENCE = 4; +layout (std140, binding = 1) uniform FinalBonesMatrices +{ + mat4 finalBonesMatrices[MAX_BONES]; +}; + +void main() +{ + vec4 totalPosition = vec4(0.0f); + vec3 totalNormal = vec3(0); + int boneCount = 0; + for(int i = 0 ; i < MAX_BONE_INFLUENCE ; i++) + { + if(boneIds[i] == -1) + continue; + if(boneIds[i] >= MAX_BONES) + { + totalPosition = vec4(aPos,1.0f); + break; + } + boneCount++; + vec4 localPosition = finalBonesMatrices[boneIds[i]] * vec4(aPos,1.0f); + totalPosition += localPosition * weights[i]; + vec3 localNormal = mat3(finalBonesMatrices[boneIds[i]]) * aNormal; + totalNormal += localNormal * weights[i]; + } + + if(boneCount == 0) + { + totalPosition = vec4(aPos, 1); + totalNormal = vec3(aNormal); + } + + vTexCoords = aTexCoords; + gl_Position = model * totalPosition; +} \ No newline at end of file diff --git a/Exp2/Engine/Shaders/pbr.comp b/Exp2/Engine/Shaders/pbr.comp new file mode 100644 index 0000000..4bd8675 --- /dev/null +++ b/Exp2/Engine/Shaders/pbr.comp @@ -0,0 +1,241 @@ +#version 450 core + +layout (local_size_x = 8, local_size_y = 8) in; + +layout(rgba8, binding = 0) uniform image2D gBaseColor; +uniform sampler2D gNormal; +uniform sampler2D gPosition; +uniform sampler2D gMetallicRoughness; +uniform sampler2DArray gShadowMap; + +uniform samplerCube irradianceMap; +uniform samplerCube prefilterMap; +uniform sampler2D brdfLUT; + +layout (std140, binding = 0) uniform LightSpaceMatrices +{ + mat4 lightSpaceMatrices[16]; +}; +uniform mat4 view; +uniform float farPlane; +uniform float shadowCascadePlaneDistances[16]; +uniform float shadowBiases[16]; +uniform int shadowCascadeCount; +uniform float shadowBlendRatio; + +uniform vec3 mainLightDirection; +uniform vec3 mainLightRadiance; + +uniform vec3 camPos; + +const float PI = 3.14159265359; + +float DistributionGGX(vec3 N, vec3 H, float roughness) +{ + float a = roughness*roughness; + float a2 = a*a; + float NdotH = max(dot(N, H), 0.0); + float NdotH2 = NdotH*NdotH; + + float nom = a2; + float denom = (NdotH2 * (a2 - 1.0) + 1.0); + denom = PI * denom * denom; + + return nom / denom; +} +// ---------------------------------------------------------------------------- +float GeometrySchlickGGX(float NdotV, float roughness) +{ + float r = (roughness + 1.0); + float k = (r*r) / 8.0; + + float nom = NdotV; + float denom = NdotV * (1.0 - k) + k; + + return nom / denom; +} +// ---------------------------------------------------------------------------- +float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness) +{ + float NdotV = max(dot(N, V), 0.0); + float NdotL = max(dot(N, L), 0.0); + float ggx2 = GeometrySchlickGGX(NdotV, roughness); + float ggx1 = GeometrySchlickGGX(NdotL, roughness); + + return ggx1 * ggx2; +} +// ---------------------------------------------------------------------------- +vec3 fresnelSchlick(float cosTheta, vec3 F0) +{ + return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); +} +vec3 fresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness) +{ + return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0); +} + +vec3 ambientLighting(vec3 N, vec3 V, vec3 F0, vec3 albedo, float metallic, float roughness, float ao) +{ + // ambient lighting (we now use IBL as the ambient term) + vec3 F = fresnelSchlickRoughness(clamp(dot(N, V),0.,1.), F0, roughness); + + vec3 kS = F; + vec3 kD = 1.0 - kS; + kD *= 1.0 - metallic; + + vec3 irradiance = texture(irradianceMap, N).rgb; + vec3 diffuse = irradiance * albedo; + + // sample both the pre-filter map and the BRDF lut and combine them together as per the Split-Sum approximation to get the IBL specular part. + const float MAX_REFLECTION_LOD = 4.0; + vec3 R = reflect(-V, N); + vec3 prefilteredColor = textureLod(prefilterMap, R, roughness * MAX_REFLECTION_LOD).rgb; + vec2 brdf = texture(brdfLUT, vec2(clamp(dot(N, V),0.,1.), roughness)).rg; + vec3 specular = prefilteredColor * (F * brdf.x + brdf.y); + + return (kD * diffuse + specular) * ao; +} + + +const int pcfRadius = 3; +float getShadowFromLayer(vec3 fragPosWorldSpace, vec3 normal,int layer) +{ + float normalBias = 1.2*4. /** (1+pcfRadius)*/ * shadowBiases[layer]*max((1.0 - dot(normal, mainLightDirection)), 0.1)/textureSize(gShadowMap, 0).x; + normalBias = max(normalBias, 0.05); + vec4 fragPosLightSpace = lightSpaceMatrices[layer] * vec4(fragPosWorldSpace+normal*normalBias, 1.0); + // perform perspective divide + vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w; + // transform to [0,1] range + projCoords = projCoords * 0.5 + 0.5; + + // get depth of current fragment from light's perspective + float currentDepth = projCoords.z; + + // keep the shadow at 0.0 when outside the far_plane region of the light's frustum. + if (currentDepth > 1.0) + { + return 0.0; + } + + // PCF + float shadow = 0.0; + vec2 texelSize = 1.0 / vec2(textureSize(gShadowMap, 0)); + for(int x = -pcfRadius; x <= pcfRadius; ++x) + { + for(int y = -pcfRadius; y <= pcfRadius; ++y) + { + float pcfDepth = texture(gShadowMap, vec3(projCoords.xy + vec2(x, y) * texelSize, layer)).r; + shadow += currentDepth > pcfDepth ? 1.0 : 0.0; + } + } + shadow /= (2*pcfRadius+1)*(2*pcfRadius+1); + return shadow; +} + +float ShadowCalculation(vec3 fragPosWorldSpace, vec3 normal, out int layer) +{ + // select cascade layer + vec4 fragPosViewSpace = view * vec4(fragPosWorldSpace, 1.0); + float depthValue = abs(fragPosViewSpace.z); + + layer = -1; + for (int i = 0; i < shadowCascadeCount; ++i) + { + if (depthValue < shadowCascadePlaneDistances[i]) + { + layer = i; + break; + } + } +// if (layer == -1) +// { +// layer = shadowCascadeCount; +// } + + float shadow = getShadowFromLayer(fragPosWorldSpace,normal,layer); + + + float nextLayerBeginDepth = layer==0? (1-shadowBlendRatio)*shadowCascadePlaneDistances[layer] + :(1-shadowBlendRatio)*shadowCascadePlaneDistances[layer]+shadowBlendRatio*shadowCascadePlaneDistances[layer-1]; + if(depthValue > nextLayerBeginDepth) + { + float shadowNext = getShadowFromLayer(fragPosWorldSpace,normal,layer+1); + shadow = mix(shadow,shadowNext, (depthValue-nextLayerBeginDepth)/(shadowCascadePlaneDistances[layer]-nextLayerBeginDepth)); + } + return shadow; +} + + + +vec4 encodeRGBM(vec3 color) +{ + if(dot(color,color)==0) + return vec4(0,0,0,1); + vec4 rgbm; + float range = 8; + color /= range; + rgbm.a = clamp(max(max(color.r, color.g), max(color.b, 1e-6)), 0.0, 1.0); + rgbm.a = ceil(rgbm.a * 255.0) / 255.0; + rgbm.rgb = color / rgbm.a; + return rgbm; +} + +void main() +{ + ivec2 pixelLocation = ivec2(gl_GlobalInvocationID.xy); + + + //vec3 albedo = pow(texelFetch(gBaseColor, pixelLocation, 0).rgb, vec3(2.2)); + vec3 albedo = pow(imageLoad(gBaseColor, pixelLocation).rgb, vec3(2.2)); + float metallic = texelFetch(gMetallicRoughness, pixelLocation, 0).r; + float roughness = texelFetch(gMetallicRoughness, pixelLocation, 0).g; + + vec3 worldPos = texelFetch(gPosition, pixelLocation,0).xyz; + vec3 normal = texelFetch(gNormal, pixelLocation,0).xyz; + + if(normal==vec3(0)) + { + //vec3 color = mainLightRadiance; + //imageStore(gBaseColor, pixelLocation, vec4(color, 1.0)); + imageStore(gBaseColor, pixelLocation, vec4(0)); + return; + } + normal = normalize(normal); + + vec3 V = normalize(camPos - worldPos); + + vec3 F0 = vec3(0.04); + F0 = mix(F0, albedo, metallic); + + // calculate light radiance + vec3 L = normalize(mainLightDirection); + vec3 H = normalize(V + L); + //float distance = length(lightPositions[i] - WorldPos); + //float attenuation = 1.0 / (distance * distance); + vec3 radiance = mainLightRadiance ;//* attenuation; + + // cook-torrance brdf + float NDF = DistributionGGX(normal, H, roughness); + float G = GeometrySmith(normal, V, L, roughness); + vec3 F = fresnelSchlick(clamp(dot(H, V),0.,1.), F0); + //F = clamp(F,vec3(0),vec3(1)); + + vec3 kS = F; + vec3 kD = vec3(1.0) - kS; + kD *= 1.0 - metallic; + + vec3 nominator = NDF * G * F; + float denominator = 4.0 * max(dot(normal, V), 0.0) * max(dot(normal, L), 0.0) + 0.001; + vec3 specular = nominator / denominator; + + float NdotL = max(dot(normal, L), 0.0); + vec3 Lo = (kD * albedo / PI + specular) * radiance * NdotL; + + vec3 ambient = ambientLighting(normal, V, F0, albedo, metallic, roughness, 1); + + int debugLayer; + float shadow = ShadowCalculation(worldPos, normal, debugLayer); + + vec3 color = (1-shadow)*Lo + ambient; + imageStore(gBaseColor, pixelLocation, encodeRGBM(color)); +} \ No newline at end of file diff --git a/Exp2/Engine/Shaders/plain.frag b/Exp2/Engine/Shaders/plain.frag new file mode 100644 index 0000000..6c11f5b --- /dev/null +++ b/Exp2/Engine/Shaders/plain.frag @@ -0,0 +1,23 @@ +#version 450 core + +layout (location = 0) out vec4 gBaseColor; +layout (location = 1) out vec3 gNormal; +layout (location = 2) out vec3 gPosition; +layout (location = 3) out vec2 gMetallicRoughness; + +in vec2 TexCoords; +in vec3 WorldPos; +in vec3 Normal; + +// material parameters +uniform vec3 albedo; +uniform float metallic; +uniform float roughness; + +void main() +{ + gBaseColor = vec4(albedo, 1); + gPosition = WorldPos; + gNormal = normalize(Normal); + gMetallicRoughness = vec2(metallic,roughness); +} \ No newline at end of file diff --git a/Exp2/Engine/Shaders/plain.vert b/Exp2/Engine/Shaders/plain.vert new file mode 100644 index 0000000..8e2587b --- /dev/null +++ b/Exp2/Engine/Shaders/plain.vert @@ -0,0 +1,22 @@ +#version 330 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; +layout (location = 2) in vec2 aTexCoords; + +out vec2 TexCoords; +out vec3 WorldPos; +out vec3 Normal; + +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; + +void main() +{ + TexCoords = aTexCoords; + WorldPos = vec3(model * vec4(aPos, 1.0)); + Normal = mat3(model) * aNormal; + + gl_Position = projection * view * vec4(WorldPos, 1.0); + +} \ No newline at end of file diff --git a/Exp2/Engine/Shaders/skybox.frag b/Exp2/Engine/Shaders/skybox.frag new file mode 100644 index 0000000..fa086dd --- /dev/null +++ b/Exp2/Engine/Shaders/skybox.frag @@ -0,0 +1,32 @@ +#version 450 core +out vec4 FragColor; +in vec3 WorldPos; + +uniform samplerCube environmentMap; +uniform float exposure = 1; + +vec3 ACESToneMapping(vec3 color) +{ + const float A = 2.51; + const float B = 0.03; + const float C = 2.43; + const float D = 0.59; + const float E = 0.14; + return (color * (A * color + B)) / (color * (C * color + D) + E); +} + +void main() +{ + vec3 color = texture(environmentMap, WorldPos).rgb; + + // HDR tonemap + //envColor = envColor / (envColor + vec3(1.0)); + + color *= exposure; + color = ACESToneMapping(color); + + // gamma correct + color = pow(color, vec3(1.0/2.2)); + + FragColor = vec4(color, 1.0); +} diff --git a/Exp2/Engine/Shaders/skybox.vert b/Exp2/Engine/Shaders/skybox.vert new file mode 100644 index 0000000..f2d2cbb --- /dev/null +++ b/Exp2/Engine/Shaders/skybox.vert @@ -0,0 +1,17 @@ +#version 450 core +layout (location = 0) in vec3 aPos; + +uniform mat4 projection; +uniform mat4 view; + +out vec3 WorldPos; + +void main() +{ + WorldPos = aPos; + + mat4 rotView = mat4(mat3(view)); + vec4 clipPos = projection * rotView * vec4(WorldPos, 1.0); + + gl_Position = clipPos.xyww; +} \ No newline at end of file diff --git a/Exp2/Exp2.cpp b/Exp2/Exp2.cpp new file mode 100644 index 0000000..404c306 --- /dev/null +++ b/Exp2/Exp2.cpp @@ -0,0 +1,8 @@ +#include +#include "ModelWorld.h" + +int main() +{ + MainWindow::instance().initialize(); + return MainWindow::instance().exec(std::make_unique()); +} \ No newline at end of file diff --git a/Exp2/Exp2.vcxproj b/Exp2/Exp2.vcxproj new file mode 100644 index 0000000..ef5fea0 --- /dev/null +++ b/Exp2/Exp2.vcxproj @@ -0,0 +1,156 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {98e424b3-5b57-4ac2-8a95-79ddbb3472d3} + Exp2 + 10.0 + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + $(SolutionDir)ToyEngine\include;$(SolutionDir)ToyEngine\src;%(AdditionalIncludeDirectories) + stdcpp20 + stdc17 + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + $(SolutionDir)ToyEngine\include;$(SolutionDir)ToyEngine\src;%(AdditionalIncludeDirectories) + stdcpp20 + stdc17 + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + $(SolutionDir)ToyEngine\include;$(SolutionDir)ToyEngine\src;%(AdditionalIncludeDirectories) + stdcpp20 + stdc17 + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + $(SolutionDir)ToyEngine\include;$(SolutionDir)ToyEngine\src;%(AdditionalIncludeDirectories) + stdcpp20 + stdc17 + + + Console + true + true + true + + + + + + + + + {65d6ee2b-fffa-4ef6-8042-9ca7a0f8e67e} + + + + + + + + + \ No newline at end of file diff --git a/Exp2/Exp2.vcxproj.filters b/Exp2/Exp2.vcxproj.filters new file mode 100644 index 0000000..d6ddcad --- /dev/null +++ b/Exp2/Exp2.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + 源文件 + + + 源文件 + + + + + 头文件 + + + \ No newline at end of file diff --git a/Exp2/ModelWorld.cpp b/Exp2/ModelWorld.cpp new file mode 100644 index 0000000..8ae6712 --- /dev/null +++ b/Exp2/ModelWorld.cpp @@ -0,0 +1,86 @@ +#include "ModelWorld.h" +#include + +ModelWorld::ModelWorld() +{ + light.lightDirection = glm::normalize(glm::vec3((cos(lightPitch) * cos(lightYaw)), (sin(lightPitch)), (cos(lightPitch) * sin(lightYaw)))); + light.radiance = 3.f * lightColor; + RenderingSystem::instance().exposure = 0.45f; + + model = std::make_shared("Models/David_Brown_25D_tractor_SF/David_Brown_25D_tractor_SF.obj"); + model->setPosition({ 0,0,0 }); + model->setScale(glm::vec3(0.5)); + addActor(model); + + camera.Position = { 0,5,10 }; +} + +void ModelWorld::logicalTick(float deltaTime) +{ + World::logicalTick(deltaTime); +} + +void ModelWorld::rendererTick(float deltaTime) +{ + World::rendererTick(deltaTime); +} + +void ModelWorld::cursorPosCallback(GLFWwindow* window, double xpos, double ypos) +{ + static bool firstMouse = true; + static float lastX; + static float lastY; + + float xoffset = xpos - lastX; + float yoffset = lastY - ypos; + + lastX = xpos; + lastY = ypos; + + if (firstMouse) + { + firstMouse = false; + return; + } + + if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS) + camera.processMouseMovement(xoffset, yoffset); + + if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS) + { + float speed = 0.2f; + model->setRotaion(glm::rotate(glm::quat(1, 0, 0, 0), + glm::radians(glm::length(glm::vec2(xoffset, yoffset)) * speed), glm::vec3(glm::vec2(-yoffset, xoffset), 0.0)) * model->getRotation()); + } +} + +void ModelWorld::scrollCallback(GLFWwindow* window, double xoffset, double yoffset) +{ + camera.processMouseScroll(yoffset); +} + +void ModelWorld::processInput(GLFWwindow* window, float deltaTime) +{ + if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) + camera.processKeyboard(FORWARD, deltaTime); + if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) + camera.processKeyboard(BACKWARD, deltaTime); + if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) + camera.processKeyboard(LEFT, deltaTime); + if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) + camera.processKeyboard(RIGHT, deltaTime); + if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS) + camera.processKeyboard(UP, deltaTime); + if (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS) + camera.processKeyboard(DOWN, deltaTime); + + float speed = 0.1; + if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS) + model->setPosition(model->getPosition() + glm::vec3(0, 0, -speed)); + if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS) + model->setPosition(model->getPosition() + glm::vec3(0, 0, speed)); + if (glfwGetKey(window, GLFW_KEY_LEFT) == GLFW_PRESS) + model->setPosition(model->getPosition() + glm::vec3(-speed, 0, 0)); + if (glfwGetKey(window, GLFW_KEY_RIGHT) == GLFW_PRESS) + model->setPosition(model->getPosition() + glm::vec3(speed, 0, 0)); +} diff --git a/Exp2/ModelWorld.h b/Exp2/ModelWorld.h new file mode 100644 index 0000000..4709891 --- /dev/null +++ b/Exp2/ModelWorld.h @@ -0,0 +1,21 @@ +#pragma once +#include + +class ModelWorld : public World +{ +public: + ModelWorld(); + void logicalTick(float deltaTime) override; + void rendererTick(float deltaTime) override; + virtual void cursorPosCallback(GLFWwindow* window, double xpos, double ypos) override; + virtual void scrollCallback(GLFWwindow* window, double xoffset, double yoffset) override; + virtual void processInput(GLFWwindow* window, float deltaTime) override; + +private: + std::shared_ptr model; + + glm::vec3 lightColor = glm::normalize(glm::vec3(0.7529, 0.7450, 0.6784)); + float lightYaw = glm::radians(80.f); + float lightPitch = glm::radians(105.f); +}; + diff --git a/Exp2/Models/David_Brown_25D_tractor_SF/David_Brown_25D_tractor.jpg b/Exp2/Models/David_Brown_25D_tractor_SF/David_Brown_25D_tractor.jpg new file mode 100644 index 0000000..806eaad Binary files /dev/null and b/Exp2/Models/David_Brown_25D_tractor_SF/David_Brown_25D_tractor.jpg differ diff --git a/Exp2/Models/David_Brown_25D_tractor_SF/David_Brown_25D_tractor_SF.mtl b/Exp2/Models/David_Brown_25D_tractor_SF/David_Brown_25D_tractor_SF.mtl new file mode 100644 index 0000000..97a2dda --- /dev/null +++ b/Exp2/Models/David_Brown_25D_tractor_SF/David_Brown_25D_tractor_SF.mtl @@ -0,0 +1,14 @@ +# Blender MTL File: 'None' +# Material Count: 1 + +newmtl David_Brown_25D_tractor +Ns 0.000000 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ke 0.000000 0.000000 0.000000 +Ni 1.450000 +d 1.000000 +illum 1 +map_Bump david_brown_25d_tractor_Normal Map from Mesh.jpg +map_Kd David_Brown_25D_tractor.jpg diff --git a/Exp2/Models/David_Brown_25D_tractor_SF/david_brown_25d_tractor_Normal Map from Mesh.jpg b/Exp2/Models/David_Brown_25D_tractor_SF/david_brown_25d_tractor_Normal Map from Mesh.jpg new file mode 100644 index 0000000..168e27b Binary files /dev/null and b/Exp2/Models/David_Brown_25D_tractor_SF/david_brown_25d_tractor_Normal Map from Mesh.jpg differ diff --git a/Exp3/Engine/HDRI/clarens_midday_4k.hdr b/Exp3/Engine/HDRI/clarens_midday_4k.hdr new file mode 100644 index 0000000..55d4894 Binary files /dev/null and b/Exp3/Engine/HDRI/clarens_midday_4k.hdr differ diff --git a/Exp3/Engine/Shaders/brdf_lut.comp b/Exp3/Engine/Shaders/brdf_lut.comp new file mode 100644 index 0000000..b52ac90 --- /dev/null +++ b/Exp3/Engine/Shaders/brdf_lut.comp @@ -0,0 +1,116 @@ +#version 450 core + +layout(local_size_x = 8, local_size_y = 8) in; +layout(rg16f, binding = 0) uniform image2D brdfLUT; + +const float PI = 3.14159265359; +// ---------------------------------------------------------------------------- +// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html +// efficient VanDerCorpus calculation. +float RadicalInverse_VdC(uint bits) +{ + bits = (bits << 16u) | (bits >> 16u); + bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); + bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); + bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); + bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); + return float(bits) * 2.3283064365386963e-10; // / 0x100000000 +} +// ---------------------------------------------------------------------------- +vec2 Hammersley(uint i, uint N) +{ + return vec2(float(i)/float(N), RadicalInverse_VdC(i)); +} +// ---------------------------------------------------------------------------- +vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness) +{ + float a = roughness*roughness; + + float phi = 2.0 * PI * Xi.x; + float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y)); + float sinTheta = sqrt(1.0 - cosTheta*cosTheta); + + // from spherical coordinates to cartesian coordinates - halfway vector + vec3 H; + H.x = cos(phi) * sinTheta; + H.y = sin(phi) * sinTheta; + H.z = cosTheta; + + // from tangent-space H vector to world-space sample vector + vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); + vec3 tangent = normalize(cross(up, N)); + vec3 bitangent = cross(N, tangent); + + vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z; + return normalize(sampleVec); +} +// ---------------------------------------------------------------------------- +float GeometrySchlickGGX(float NdotV, float roughness) +{ + // note that we use a different k for IBL + float a = roughness; + float k = (a * a) / 2.0; + + float nom = NdotV; + float denom = NdotV * (1.0 - k) + k; + + return nom / denom; +} +// ---------------------------------------------------------------------------- +float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness) +{ + float NdotV = max(dot(N, V), 0.0); + float NdotL = max(dot(N, L), 0.0); + float ggx2 = GeometrySchlickGGX(NdotV, roughness); + float ggx1 = GeometrySchlickGGX(NdotL, roughness); + + return ggx1 * ggx2; +} +// ---------------------------------------------------------------------------- +vec2 IntegrateBRDF(float NdotV, float roughness) +{ + vec3 V; + V.x = sqrt(1.0 - NdotV*NdotV); + V.y = 0.0; + V.z = NdotV; + + float A = 0.0; + float B = 0.0; + + vec3 N = vec3(0.0, 0.0, 1.0); + + const uint SAMPLE_COUNT = 1024u; + for(uint i = 0u; i < SAMPLE_COUNT; ++i) + { + // generates a sample vector that's biased towards the + // preferred alignment direction (importance sampling). + vec2 Xi = Hammersley(i, SAMPLE_COUNT); + vec3 H = ImportanceSampleGGX(Xi, N, roughness); + vec3 L = normalize(2.0 * dot(V, H) * H - V); + + float NdotL = max(L.z, 0.0); + float NdotH = max(H.z, 0.0); + float VdotH = max(dot(V, H), 0.0); + + if(NdotL > 0.0) + { + float G = GeometrySmith(N, V, L, roughness); + float G_Vis = (G * VdotH) / (NdotH * NdotV); + float Fc = pow(1.0 - VdotH, 5.0); + + A += (1.0 - Fc) * G_Vis; + B += Fc * G_Vis; + } + } + A /= float(SAMPLE_COUNT); + B /= float(SAMPLE_COUNT); + return vec2(A, B); +} +// ---------------------------------------------------------------------------- +void main() +{ + uvec2 pixelLocation = gl_GlobalInvocationID.xy; + vec2 texCoords = (vec2(pixelLocation)+vec2(0.5))/vec2(imageSize(brdfLUT)); + vec2 integratedBRDF = IntegrateBRDF(texCoords.x, texCoords.y); + imageStore(brdfLUT, ivec2(pixelLocation), vec4(integratedBRDF,0,0)); +} \ No newline at end of file diff --git a/Exp3/Engine/Shaders/cubemap.frag b/Exp3/Engine/Shaders/cubemap.frag new file mode 100644 index 0000000..8e9bd85 --- /dev/null +++ b/Exp3/Engine/Shaders/cubemap.frag @@ -0,0 +1,22 @@ +#version 450 core +out vec4 FragColor; +in vec3 WorldPos; + +uniform sampler2D equirectangularMap; + +const vec2 invAtan = vec2(0.1591, 0.3183); +vec2 SampleSphericalMap(vec3 v) +{ + vec2 uv = vec2(atan(v.z, v.x), asin(v.y)); + uv *= invAtan; + uv += 0.5; + return uv; +} + +void main() +{ + vec2 uv = SampleSphericalMap(normalize(WorldPos)); + vec3 color = texture(equirectangularMap, uv).rgb; + + FragColor = vec4(color, 1.0); +} diff --git a/Exp3/Engine/Shaders/cubemap.vert b/Exp3/Engine/Shaders/cubemap.vert new file mode 100644 index 0000000..19dc4ef --- /dev/null +++ b/Exp3/Engine/Shaders/cubemap.vert @@ -0,0 +1,13 @@ +#version 450 core +layout (location = 0) in vec3 aPos; + +out vec3 WorldPos; + +uniform mat4 projection; +uniform mat4 view; + +void main() +{ + WorldPos = aPos; + gl_Position = projection * view * vec4(WorldPos, 1.0); +} \ No newline at end of file diff --git a/Exp3/Engine/Shaders/cubemap_prefilter.frag b/Exp3/Engine/Shaders/cubemap_prefilter.frag new file mode 100644 index 0000000..9214443 --- /dev/null +++ b/Exp3/Engine/Shaders/cubemap_prefilter.frag @@ -0,0 +1,107 @@ +#version 450 core +out vec4 FragColor; +in vec3 WorldPos; + +uniform samplerCube environmentMap; +uniform float roughness; + +const float PI = 3.14159265359; +// ---------------------------------------------------------------------------- +float DistributionGGX(vec3 N, vec3 H, float roughness) +{ + float a = roughness*roughness; + float a2 = a*a; + float NdotH = max(dot(N, H), 0.0); + float NdotH2 = NdotH*NdotH; + + float nom = a2; + float denom = (NdotH2 * (a2 - 1.0) + 1.0); + denom = PI * denom * denom; + + return nom / denom; +} +// ---------------------------------------------------------------------------- +// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html +// efficient VanDerCorpus calculation. +float RadicalInverse_VdC(uint bits) +{ + bits = (bits << 16u) | (bits >> 16u); + bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); + bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); + bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); + bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); + return float(bits) * 2.3283064365386963e-10; // / 0x100000000 +} +// ---------------------------------------------------------------------------- +vec2 Hammersley(uint i, uint N) +{ + return vec2(float(i)/float(N), RadicalInverse_VdC(i)); +} +// ---------------------------------------------------------------------------- +vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness) +{ + float a = roughness*roughness; + + float phi = 2.0 * PI * Xi.x; + float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y)); + float sinTheta = sqrt(1.0 - cosTheta*cosTheta); + + // from spherical coordinates to cartesian coordinates - halfway vector + vec3 H; + H.x = cos(phi) * sinTheta; + H.y = sin(phi) * sinTheta; + H.z = cosTheta; + + // from tangent-space H vector to world-space sample vector + vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); + vec3 tangent = normalize(cross(up, N)); + vec3 bitangent = cross(N, tangent); + + vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z; + return normalize(sampleVec); +} +// ---------------------------------------------------------------------------- +void main() +{ + vec3 N = normalize(WorldPos); + + // make the simplyfying assumption that V equals R equals the normal + vec3 R = N; + vec3 V = R; + + const uint SAMPLE_COUNT = 1024u; + vec3 prefilteredColor = vec3(0.0); + float totalWeight = 0.0; + + for(uint i = 0u; i < SAMPLE_COUNT; ++i) + { + // generates a sample vector that's biased towards the preferred alignment direction (importance sampling). + vec2 Xi = Hammersley(i, SAMPLE_COUNT); + vec3 H = ImportanceSampleGGX(Xi, N, roughness); + vec3 L = normalize(2.0 * dot(V, H) * H - V); + + float NdotL = max(dot(N, L), 0.0); + if(NdotL > 0.0) + { + // sample from the environment's mip level based on roughness/pdf + float D = DistributionGGX(N, H, roughness); + float NdotH = max(dot(N, H), 0.0); + float HdotV = max(dot(H, V), 0.0); + float pdf = D * NdotH / (4.0 * HdotV) + 0.0001; + + //float resolution = 512.0; // resolution of source cubemap (per face) + float resolution = float(textureSize(environmentMap,0).x); // resolution of source cubemap (per face) + float saTexel = 4.0 * PI / (6.0 * resolution * resolution); + float saSample = 1.0 / (float(SAMPLE_COUNT) * pdf + 0.0001); + + float mipLevel = roughness == 0.0 ? 0.0 : 0.5 * log2(saSample / saTexel); + + prefilteredColor += textureLod(environmentMap, L, mipLevel).rgb * NdotL; + totalWeight += NdotL; + } + } + + prefilteredColor = prefilteredColor / totalWeight; + + FragColor = vec4(prefilteredColor, 1.0); +} diff --git a/Exp3/Engine/Shaders/debug.frag b/Exp3/Engine/Shaders/debug.frag new file mode 100644 index 0000000..a182182 --- /dev/null +++ b/Exp3/Engine/Shaders/debug.frag @@ -0,0 +1,14 @@ +#version 450 core + +layout (location = 4) out vec4 gDebug; + +in vec2 TexCoords; +in vec3 WorldPos; +in vec3 Normal; + +uniform vec3 color; + +void main() +{ + gDebug = vec4(color,1); +} \ No newline at end of file diff --git a/Exp3/Engine/Shaders/debug.vert b/Exp3/Engine/Shaders/debug.vert new file mode 100644 index 0000000..8e2587b --- /dev/null +++ b/Exp3/Engine/Shaders/debug.vert @@ -0,0 +1,22 @@ +#version 330 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; +layout (location = 2) in vec2 aTexCoords; + +out vec2 TexCoords; +out vec3 WorldPos; +out vec3 Normal; + +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; + +void main() +{ + TexCoords = aTexCoords; + WorldPos = vec3(model * vec4(aPos, 1.0)); + Normal = mat3(model) * aNormal; + + gl_Position = projection * view * vec4(WorldPos, 1.0); + +} \ No newline at end of file diff --git a/Exp3/Engine/Shaders/final.frag b/Exp3/Engine/Shaders/final.frag new file mode 100644 index 0000000..9c894c6 --- /dev/null +++ b/Exp3/Engine/Shaders/final.frag @@ -0,0 +1,42 @@ +#version 450 core + +out vec4 FragColor; + +in vec2 TexCoords; + +uniform sampler2D gBaseColor; +uniform sampler2D gDebug; +uniform float exposure = 1; +uniform bool showDebug = false; + +vec3 ACESToneMapping(vec3 color) +{ + const float A = 2.51; + const float B = 0.03; + const float C = 2.43; + const float D = 0.59; + const float E = 0.14; + return (color * (A * color + B)) / (color * (C * color + D) + E); +} + +void main() +{ + vec4 rgbm = texture(gBaseColor, TexCoords); + vec4 debug = texture(gDebug, TexCoords); + if(rgbm.a==0 && (showDebug ? debug.a==0 : true)) + { + //FragColor = vec4(1,0,0,1); + //return; + discard; + } + vec3 color = 8 * rgbm.rgb * rgbm.a; + + color *= exposure; + color = ACESToneMapping(color); + + //color = color / (color + vec3(1.0)); + color = pow(color, vec3(1.0/2.2)); + FragColor = vec4(color, 1.0); + if(showDebug) + FragColor = mix(FragColor, debug, debug.a); +} \ No newline at end of file diff --git a/Exp3/Engine/Shaders/final.vert b/Exp3/Engine/Shaders/final.vert new file mode 100644 index 0000000..6317aab --- /dev/null +++ b/Exp3/Engine/Shaders/final.vert @@ -0,0 +1,11 @@ +#version 450 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec2 aTexCoords; + +out vec2 TexCoords; + +void main() +{ + TexCoords = aTexCoords; + gl_Position = vec4(aPos, 1.0); +} \ No newline at end of file diff --git a/Exp3/Engine/Shaders/irradiance_convolution.frag b/Exp3/Engine/Shaders/irradiance_convolution.frag new file mode 100644 index 0000000..7e9e642 --- /dev/null +++ b/Exp3/Engine/Shaders/irradiance_convolution.frag @@ -0,0 +1,43 @@ +#version 450 core +out vec4 FragColor; +in vec3 WorldPos; + +uniform samplerCube environmentMap; + +const float PI = 3.14159265359; + +void main() +{ + // The world vector acts as the normal of a tangent surface + // from the origin, aligned to WorldPos. Given this normal, calculate all + // incoming radiance of the environment. The result of this radiance + // is the radiance of light coming from -Normal direction, which is what + // we use in the PBR shader to sample irradiance. + vec3 N = normalize(WorldPos); + + vec3 irradiance = vec3(0.0); + + // tangent space calculation from origin point + vec3 up = vec3(0.0, 1.0, 0.0); + vec3 right = normalize(cross(up, N)); + up = normalize(cross(N, right)); + + float sampleDelta = 0.025; + float nrSamples = 0.0; + for(float phi = 0.0; phi < 2.0 * PI; phi += sampleDelta) + { + for(float theta = 0.0; theta < 0.5 * PI; theta += sampleDelta) + { + // spherical to cartesian (in tangent space) + vec3 tangentSample = vec3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta)); + // tangent space to world + vec3 sampleVec = tangentSample.x * right + tangentSample.y * up + tangentSample.z * N; + + irradiance += texture(environmentMap, sampleVec).rgb * cos(theta) * sin(theta); + nrSamples++; + } + } + irradiance = PI * irradiance * (1.0 / float(nrSamples)); + + FragColor = vec4(irradiance, 1.0); +} diff --git a/Exp3/Engine/Shaders/model.frag b/Exp3/Engine/Shaders/model.frag new file mode 100644 index 0000000..22c49e2 --- /dev/null +++ b/Exp3/Engine/Shaders/model.frag @@ -0,0 +1,61 @@ +#version 450 core +uniform sampler2D texture_basecolor; +uniform sampler2D texture_metallic_roughness; +uniform sampler2D texture_normal; + +uniform bool texture_basecolor_available = false; +uniform bool texture_metallic_roughness_available = false; +uniform bool texture_normal_available = false; + +uniform vec3 baseColor; +uniform vec2 metallicRoughness; + +layout (location = 0) out vec4 gBaseColor; +layout (location = 1) out vec3 gNormal; +layout (location = 2) out vec3 gPosition; +layout (location = 3) out vec2 gMetallicRoughness; +layout (location = 4) out vec4 gDebug; + +in vec2 TexCoords; +in vec3 WorldPos; +in vec3 Normal; + +vec3 getNormalFromMap() +{ + vec3 tangentNormal = texture(texture_normal, TexCoords).xyz * 2.0 - 1.0; + + vec3 Q1 = dFdx(WorldPos); + vec3 Q2 = dFdy(WorldPos); + vec2 st1 = dFdx(TexCoords); + vec2 st2 = dFdy(TexCoords); + + vec3 N = normalize(Normal); + vec3 T = normalize(Q1*st2.t - Q2*st1.t); + vec3 B = -normalize(cross(N, T)); + mat3 TBN = mat3(T, B, N); + + return normalize(TBN * tangentNormal); +} + +void main() +{ + if(texture_basecolor_available) + gBaseColor = texture(texture_basecolor, TexCoords); + else + gBaseColor = vec4(baseColor, 1); + if(gBaseColor.a<0.4) + discard; + gPosition = WorldPos; + if(texture_normal_available) + gNormal = getNormalFromMap(); + else + gNormal = Normal; + if(!gl_FrontFacing) + gNormal = -gNormal; + if(texture_metallic_roughness_available) + gMetallicRoughness = texture(texture_metallic_roughness, TexCoords).bg; + else + gMetallicRoughness = metallicRoughness; + + gDebug = vec4(0); +} \ No newline at end of file diff --git a/Exp3/Engine/Shaders/model.vert b/Exp3/Engine/Shaders/model.vert new file mode 100644 index 0000000..28f5787 --- /dev/null +++ b/Exp3/Engine/Shaders/model.vert @@ -0,0 +1,55 @@ +#version 450 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; +layout (location = 2) in vec2 aTexCoords; +layout (location = 3) in ivec4 boneIds; +layout (location = 4) in vec4 weights; + +out vec2 TexCoords; +out vec3 WorldPos; +out vec3 Normal; + +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; + +const int MAX_BONES = 100; +const int MAX_BONE_INFLUENCE = 4; +layout (std140, binding = 1) uniform FinalBonesMatrices +{ + mat4 finalBonesMatrices[MAX_BONES]; +}; + +void main() +{ + vec4 totalPosition = vec4(0.0f); + vec3 totalNormal = vec3(0); + int boneCount = 0; + for(int i = 0 ; i < MAX_BONE_INFLUENCE ; i++) + { + if(boneIds[i] == -1) + continue; + if(boneIds[i] >= MAX_BONES) + { + totalPosition = vec4(aPos,1.0f); + break; + } + boneCount++; + vec4 localPosition = finalBonesMatrices[boneIds[i]] * vec4(aPos,1.0f); + totalPosition += localPosition * weights[i]; + vec3 localNormal = mat3(finalBonesMatrices[boneIds[i]]) * aNormal; + totalNormal += localNormal * weights[i]; + } + + if(boneCount == 0) + { + totalPosition = vec4(aPos, 1); + totalNormal = vec3(aNormal); + } + + TexCoords = aTexCoords; + WorldPos = vec3(model * totalPosition); + Normal = mat3(model) * totalNormal; + + gl_Position = projection * view * vec4(WorldPos, 1.0); +} \ No newline at end of file diff --git a/Exp3/Engine/Shaders/model_shadow.frag b/Exp3/Engine/Shaders/model_shadow.frag new file mode 100644 index 0000000..8b44c38 --- /dev/null +++ b/Exp3/Engine/Shaders/model_shadow.frag @@ -0,0 +1,12 @@ +#version 450 core + +uniform sampler2D texture_basecolor; + +in vec2 TexCoords; + +void main() +{ + vec4 baseColor = texture(texture_basecolor, TexCoords); + if(baseColor.a<0.4) + discard; +} \ No newline at end of file diff --git a/Exp3/Engine/Shaders/model_shadow.geom b/Exp3/Engine/Shaders/model_shadow.geom new file mode 100644 index 0000000..d2960c9 --- /dev/null +++ b/Exp3/Engine/Shaders/model_shadow.geom @@ -0,0 +1,24 @@ +#version 450 core + +layout(triangles, invocations = 5) in; +layout(triangle_strip, max_vertices = 3) out; + +layout (std140, binding = 0) uniform LightSpaceMatrices +{ + mat4 lightSpaceMatrices[16]; +}; + +in vec2 vTexCoords[]; +out vec2 TexCoords; + +void main() +{ + for (int i = 0; i < 3; ++i) + { + TexCoords = vTexCoords[i]; + gl_Position = lightSpaceMatrices[gl_InvocationID] * gl_in[i].gl_Position; + gl_Layer = gl_InvocationID; + EmitVertex(); + } + EndPrimitive(); +} \ No newline at end of file diff --git a/Exp3/Engine/Shaders/model_shadow.vert b/Exp3/Engine/Shaders/model_shadow.vert new file mode 100644 index 0000000..f48641d --- /dev/null +++ b/Exp3/Engine/Shaders/model_shadow.vert @@ -0,0 +1,48 @@ +#version 450 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; +layout (location = 2) in vec2 aTexCoords; +layout (location = 3) in ivec4 boneIds; +layout (location = 4) in vec4 weights; + +out vec2 vTexCoords; + +uniform mat4 model; + +const int MAX_BONES = 100; +const int MAX_BONE_INFLUENCE = 4; +layout (std140, binding = 1) uniform FinalBonesMatrices +{ + mat4 finalBonesMatrices[MAX_BONES]; +}; + +void main() +{ + vec4 totalPosition = vec4(0.0f); + vec3 totalNormal = vec3(0); + int boneCount = 0; + for(int i = 0 ; i < MAX_BONE_INFLUENCE ; i++) + { + if(boneIds[i] == -1) + continue; + if(boneIds[i] >= MAX_BONES) + { + totalPosition = vec4(aPos,1.0f); + break; + } + boneCount++; + vec4 localPosition = finalBonesMatrices[boneIds[i]] * vec4(aPos,1.0f); + totalPosition += localPosition * weights[i]; + vec3 localNormal = mat3(finalBonesMatrices[boneIds[i]]) * aNormal; + totalNormal += localNormal * weights[i]; + } + + if(boneCount == 0) + { + totalPosition = vec4(aPos, 1); + totalNormal = vec3(aNormal); + } + + vTexCoords = aTexCoords; + gl_Position = model * totalPosition; +} \ No newline at end of file diff --git a/Exp3/Engine/Shaders/pbr.comp b/Exp3/Engine/Shaders/pbr.comp new file mode 100644 index 0000000..4bd8675 --- /dev/null +++ b/Exp3/Engine/Shaders/pbr.comp @@ -0,0 +1,241 @@ +#version 450 core + +layout (local_size_x = 8, local_size_y = 8) in; + +layout(rgba8, binding = 0) uniform image2D gBaseColor; +uniform sampler2D gNormal; +uniform sampler2D gPosition; +uniform sampler2D gMetallicRoughness; +uniform sampler2DArray gShadowMap; + +uniform samplerCube irradianceMap; +uniform samplerCube prefilterMap; +uniform sampler2D brdfLUT; + +layout (std140, binding = 0) uniform LightSpaceMatrices +{ + mat4 lightSpaceMatrices[16]; +}; +uniform mat4 view; +uniform float farPlane; +uniform float shadowCascadePlaneDistances[16]; +uniform float shadowBiases[16]; +uniform int shadowCascadeCount; +uniform float shadowBlendRatio; + +uniform vec3 mainLightDirection; +uniform vec3 mainLightRadiance; + +uniform vec3 camPos; + +const float PI = 3.14159265359; + +float DistributionGGX(vec3 N, vec3 H, float roughness) +{ + float a = roughness*roughness; + float a2 = a*a; + float NdotH = max(dot(N, H), 0.0); + float NdotH2 = NdotH*NdotH; + + float nom = a2; + float denom = (NdotH2 * (a2 - 1.0) + 1.0); + denom = PI * denom * denom; + + return nom / denom; +} +// ---------------------------------------------------------------------------- +float GeometrySchlickGGX(float NdotV, float roughness) +{ + float r = (roughness + 1.0); + float k = (r*r) / 8.0; + + float nom = NdotV; + float denom = NdotV * (1.0 - k) + k; + + return nom / denom; +} +// ---------------------------------------------------------------------------- +float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness) +{ + float NdotV = max(dot(N, V), 0.0); + float NdotL = max(dot(N, L), 0.0); + float ggx2 = GeometrySchlickGGX(NdotV, roughness); + float ggx1 = GeometrySchlickGGX(NdotL, roughness); + + return ggx1 * ggx2; +} +// ---------------------------------------------------------------------------- +vec3 fresnelSchlick(float cosTheta, vec3 F0) +{ + return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); +} +vec3 fresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness) +{ + return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0); +} + +vec3 ambientLighting(vec3 N, vec3 V, vec3 F0, vec3 albedo, float metallic, float roughness, float ao) +{ + // ambient lighting (we now use IBL as the ambient term) + vec3 F = fresnelSchlickRoughness(clamp(dot(N, V),0.,1.), F0, roughness); + + vec3 kS = F; + vec3 kD = 1.0 - kS; + kD *= 1.0 - metallic; + + vec3 irradiance = texture(irradianceMap, N).rgb; + vec3 diffuse = irradiance * albedo; + + // sample both the pre-filter map and the BRDF lut and combine them together as per the Split-Sum approximation to get the IBL specular part. + const float MAX_REFLECTION_LOD = 4.0; + vec3 R = reflect(-V, N); + vec3 prefilteredColor = textureLod(prefilterMap, R, roughness * MAX_REFLECTION_LOD).rgb; + vec2 brdf = texture(brdfLUT, vec2(clamp(dot(N, V),0.,1.), roughness)).rg; + vec3 specular = prefilteredColor * (F * brdf.x + brdf.y); + + return (kD * diffuse + specular) * ao; +} + + +const int pcfRadius = 3; +float getShadowFromLayer(vec3 fragPosWorldSpace, vec3 normal,int layer) +{ + float normalBias = 1.2*4. /** (1+pcfRadius)*/ * shadowBiases[layer]*max((1.0 - dot(normal, mainLightDirection)), 0.1)/textureSize(gShadowMap, 0).x; + normalBias = max(normalBias, 0.05); + vec4 fragPosLightSpace = lightSpaceMatrices[layer] * vec4(fragPosWorldSpace+normal*normalBias, 1.0); + // perform perspective divide + vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w; + // transform to [0,1] range + projCoords = projCoords * 0.5 + 0.5; + + // get depth of current fragment from light's perspective + float currentDepth = projCoords.z; + + // keep the shadow at 0.0 when outside the far_plane region of the light's frustum. + if (currentDepth > 1.0) + { + return 0.0; + } + + // PCF + float shadow = 0.0; + vec2 texelSize = 1.0 / vec2(textureSize(gShadowMap, 0)); + for(int x = -pcfRadius; x <= pcfRadius; ++x) + { + for(int y = -pcfRadius; y <= pcfRadius; ++y) + { + float pcfDepth = texture(gShadowMap, vec3(projCoords.xy + vec2(x, y) * texelSize, layer)).r; + shadow += currentDepth > pcfDepth ? 1.0 : 0.0; + } + } + shadow /= (2*pcfRadius+1)*(2*pcfRadius+1); + return shadow; +} + +float ShadowCalculation(vec3 fragPosWorldSpace, vec3 normal, out int layer) +{ + // select cascade layer + vec4 fragPosViewSpace = view * vec4(fragPosWorldSpace, 1.0); + float depthValue = abs(fragPosViewSpace.z); + + layer = -1; + for (int i = 0; i < shadowCascadeCount; ++i) + { + if (depthValue < shadowCascadePlaneDistances[i]) + { + layer = i; + break; + } + } +// if (layer == -1) +// { +// layer = shadowCascadeCount; +// } + + float shadow = getShadowFromLayer(fragPosWorldSpace,normal,layer); + + + float nextLayerBeginDepth = layer==0? (1-shadowBlendRatio)*shadowCascadePlaneDistances[layer] + :(1-shadowBlendRatio)*shadowCascadePlaneDistances[layer]+shadowBlendRatio*shadowCascadePlaneDistances[layer-1]; + if(depthValue > nextLayerBeginDepth) + { + float shadowNext = getShadowFromLayer(fragPosWorldSpace,normal,layer+1); + shadow = mix(shadow,shadowNext, (depthValue-nextLayerBeginDepth)/(shadowCascadePlaneDistances[layer]-nextLayerBeginDepth)); + } + return shadow; +} + + + +vec4 encodeRGBM(vec3 color) +{ + if(dot(color,color)==0) + return vec4(0,0,0,1); + vec4 rgbm; + float range = 8; + color /= range; + rgbm.a = clamp(max(max(color.r, color.g), max(color.b, 1e-6)), 0.0, 1.0); + rgbm.a = ceil(rgbm.a * 255.0) / 255.0; + rgbm.rgb = color / rgbm.a; + return rgbm; +} + +void main() +{ + ivec2 pixelLocation = ivec2(gl_GlobalInvocationID.xy); + + + //vec3 albedo = pow(texelFetch(gBaseColor, pixelLocation, 0).rgb, vec3(2.2)); + vec3 albedo = pow(imageLoad(gBaseColor, pixelLocation).rgb, vec3(2.2)); + float metallic = texelFetch(gMetallicRoughness, pixelLocation, 0).r; + float roughness = texelFetch(gMetallicRoughness, pixelLocation, 0).g; + + vec3 worldPos = texelFetch(gPosition, pixelLocation,0).xyz; + vec3 normal = texelFetch(gNormal, pixelLocation,0).xyz; + + if(normal==vec3(0)) + { + //vec3 color = mainLightRadiance; + //imageStore(gBaseColor, pixelLocation, vec4(color, 1.0)); + imageStore(gBaseColor, pixelLocation, vec4(0)); + return; + } + normal = normalize(normal); + + vec3 V = normalize(camPos - worldPos); + + vec3 F0 = vec3(0.04); + F0 = mix(F0, albedo, metallic); + + // calculate light radiance + vec3 L = normalize(mainLightDirection); + vec3 H = normalize(V + L); + //float distance = length(lightPositions[i] - WorldPos); + //float attenuation = 1.0 / (distance * distance); + vec3 radiance = mainLightRadiance ;//* attenuation; + + // cook-torrance brdf + float NDF = DistributionGGX(normal, H, roughness); + float G = GeometrySmith(normal, V, L, roughness); + vec3 F = fresnelSchlick(clamp(dot(H, V),0.,1.), F0); + //F = clamp(F,vec3(0),vec3(1)); + + vec3 kS = F; + vec3 kD = vec3(1.0) - kS; + kD *= 1.0 - metallic; + + vec3 nominator = NDF * G * F; + float denominator = 4.0 * max(dot(normal, V), 0.0) * max(dot(normal, L), 0.0) + 0.001; + vec3 specular = nominator / denominator; + + float NdotL = max(dot(normal, L), 0.0); + vec3 Lo = (kD * albedo / PI + specular) * radiance * NdotL; + + vec3 ambient = ambientLighting(normal, V, F0, albedo, metallic, roughness, 1); + + int debugLayer; + float shadow = ShadowCalculation(worldPos, normal, debugLayer); + + vec3 color = (1-shadow)*Lo + ambient; + imageStore(gBaseColor, pixelLocation, encodeRGBM(color)); +} \ No newline at end of file diff --git a/Exp3/Engine/Shaders/plain.frag b/Exp3/Engine/Shaders/plain.frag new file mode 100644 index 0000000..6c11f5b --- /dev/null +++ b/Exp3/Engine/Shaders/plain.frag @@ -0,0 +1,23 @@ +#version 450 core + +layout (location = 0) out vec4 gBaseColor; +layout (location = 1) out vec3 gNormal; +layout (location = 2) out vec3 gPosition; +layout (location = 3) out vec2 gMetallicRoughness; + +in vec2 TexCoords; +in vec3 WorldPos; +in vec3 Normal; + +// material parameters +uniform vec3 albedo; +uniform float metallic; +uniform float roughness; + +void main() +{ + gBaseColor = vec4(albedo, 1); + gPosition = WorldPos; + gNormal = normalize(Normal); + gMetallicRoughness = vec2(metallic,roughness); +} \ No newline at end of file diff --git a/Exp3/Engine/Shaders/plain.vert b/Exp3/Engine/Shaders/plain.vert new file mode 100644 index 0000000..8e2587b --- /dev/null +++ b/Exp3/Engine/Shaders/plain.vert @@ -0,0 +1,22 @@ +#version 330 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; +layout (location = 2) in vec2 aTexCoords; + +out vec2 TexCoords; +out vec3 WorldPos; +out vec3 Normal; + +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; + +void main() +{ + TexCoords = aTexCoords; + WorldPos = vec3(model * vec4(aPos, 1.0)); + Normal = mat3(model) * aNormal; + + gl_Position = projection * view * vec4(WorldPos, 1.0); + +} \ No newline at end of file diff --git a/Exp3/Engine/Shaders/skybox.frag b/Exp3/Engine/Shaders/skybox.frag new file mode 100644 index 0000000..fa086dd --- /dev/null +++ b/Exp3/Engine/Shaders/skybox.frag @@ -0,0 +1,32 @@ +#version 450 core +out vec4 FragColor; +in vec3 WorldPos; + +uniform samplerCube environmentMap; +uniform float exposure = 1; + +vec3 ACESToneMapping(vec3 color) +{ + const float A = 2.51; + const float B = 0.03; + const float C = 2.43; + const float D = 0.59; + const float E = 0.14; + return (color * (A * color + B)) / (color * (C * color + D) + E); +} + +void main() +{ + vec3 color = texture(environmentMap, WorldPos).rgb; + + // HDR tonemap + //envColor = envColor / (envColor + vec3(1.0)); + + color *= exposure; + color = ACESToneMapping(color); + + // gamma correct + color = pow(color, vec3(1.0/2.2)); + + FragColor = vec4(color, 1.0); +} diff --git a/Exp3/Engine/Shaders/skybox.vert b/Exp3/Engine/Shaders/skybox.vert new file mode 100644 index 0000000..f2d2cbb --- /dev/null +++ b/Exp3/Engine/Shaders/skybox.vert @@ -0,0 +1,17 @@ +#version 450 core +layout (location = 0) in vec3 aPos; + +uniform mat4 projection; +uniform mat4 view; + +out vec3 WorldPos; + +void main() +{ + WorldPos = aPos; + + mat4 rotView = mat4(mat3(view)); + vec4 clipPos = projection * rotView * vec4(WorldPos, 1.0); + + gl_Position = clipPos.xyww; +} \ No newline at end of file diff --git a/Exp3/Exp3.cpp b/Exp3/Exp3.cpp new file mode 100644 index 0000000..091982d --- /dev/null +++ b/Exp3/Exp3.cpp @@ -0,0 +1,8 @@ +#include +#include "ParticleWorld.h" + +int main() +{ + MainWindow::instance().initialize(); + return MainWindow::instance().exec(std::make_unique()); +} \ No newline at end of file diff --git a/Exp3/Exp3.vcxproj b/Exp3/Exp3.vcxproj new file mode 100644 index 0000000..26ff668 --- /dev/null +++ b/Exp3/Exp3.vcxproj @@ -0,0 +1,156 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {73465bf0-e1e1-4ad2-a5f2-df14a54d1f5f} + Exp3 + 10.0 + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + $(SolutionDir)ToyEngine\include;$(SolutionDir)ToyEngine\src;%(AdditionalIncludeDirectories) + stdcpp20 + stdc17 + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + $(SolutionDir)ToyEngine\include;$(SolutionDir)ToyEngine\src;%(AdditionalIncludeDirectories) + stdcpp20 + stdc17 + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + $(SolutionDir)ToyEngine\include;$(SolutionDir)ToyEngine\src;%(AdditionalIncludeDirectories) + stdcpp20 + stdc17 + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + $(SolutionDir)ToyEngine\include;$(SolutionDir)ToyEngine\src;%(AdditionalIncludeDirectories) + stdcpp20 + stdc17 + + + Console + true + true + true + + + + + + + + + {65d6ee2b-fffa-4ef6-8042-9ca7a0f8e67e} + + + + + + + + + \ No newline at end of file diff --git a/Exp3/Exp3.vcxproj.filters b/Exp3/Exp3.vcxproj.filters new file mode 100644 index 0000000..1830ea5 --- /dev/null +++ b/Exp3/Exp3.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + 源文件 + + + 源文件 + + + + + 头文件 + + + \ No newline at end of file diff --git a/ToyEngine/src/ParticleWorld.cpp b/Exp3/ParticleWorld.cpp similarity index 98% rename from ToyEngine/src/ParticleWorld.cpp rename to Exp3/ParticleWorld.cpp index b0d7d57..7b76c2c 100644 --- a/ToyEngine/src/ParticleWorld.cpp +++ b/Exp3/ParticleWorld.cpp @@ -1,6 +1,6 @@ #include "ParticleWorld.h" -#include "Particle.h" -#include "RenderingSystem.h" +#include +#include ParticleWorld::ParticleWorld() { diff --git a/ToyEngine/src/ParticleWorld.h b/Exp3/ParticleWorld.h similarity index 97% rename from ToyEngine/src/ParticleWorld.h rename to Exp3/ParticleWorld.h index 051b6c4..5b283af 100644 --- a/ToyEngine/src/ParticleWorld.h +++ b/Exp3/ParticleWorld.h @@ -1,5 +1,5 @@ #pragma once -#include "World.h" +#include class ParticleWorld : public World { public: diff --git a/ToyEngine.sln b/ToyEngine.sln index fadc459..1af2947 100644 --- a/ToyEngine.sln +++ b/ToyEngine.sln @@ -5,6 +5,14 @@ VisualStudioVersion = 17.5.33414.496 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ToyEngine", "ToyEngine\ToyEngine.vcxproj", "{65D6EE2B-FFFA-4EF6-8042-9CA7A0F8E67E}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Exp1", "Exp1\Exp1.vcxproj", "{8013F6A0-C953-415B-A48D-F425E63EAD09}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Exp2", "Exp2\Exp2.vcxproj", "{98E424B3-5B57-4AC2-8A95-79DDBB3472D3}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Exp3", "Exp3\Exp3.vcxproj", "{73465BF0-E1E1-4AD2-A5F2-DF14A54D1F5F}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Demo", "Demo\Demo.vcxproj", "{02EEA281-F0A1-4BE3-B833-5A9B4150F6B0}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -21,6 +29,38 @@ Global {65D6EE2B-FFFA-4EF6-8042-9CA7A0F8E67E}.Release|x64.Build.0 = Release|x64 {65D6EE2B-FFFA-4EF6-8042-9CA7A0F8E67E}.Release|x86.ActiveCfg = Release|Win32 {65D6EE2B-FFFA-4EF6-8042-9CA7A0F8E67E}.Release|x86.Build.0 = Release|Win32 + {8013F6A0-C953-415B-A48D-F425E63EAD09}.Debug|x64.ActiveCfg = Debug|x64 + {8013F6A0-C953-415B-A48D-F425E63EAD09}.Debug|x64.Build.0 = Debug|x64 + {8013F6A0-C953-415B-A48D-F425E63EAD09}.Debug|x86.ActiveCfg = Debug|Win32 + {8013F6A0-C953-415B-A48D-F425E63EAD09}.Debug|x86.Build.0 = Debug|Win32 + {8013F6A0-C953-415B-A48D-F425E63EAD09}.Release|x64.ActiveCfg = Release|x64 + {8013F6A0-C953-415B-A48D-F425E63EAD09}.Release|x64.Build.0 = Release|x64 + {8013F6A0-C953-415B-A48D-F425E63EAD09}.Release|x86.ActiveCfg = Release|Win32 + {8013F6A0-C953-415B-A48D-F425E63EAD09}.Release|x86.Build.0 = Release|Win32 + {98E424B3-5B57-4AC2-8A95-79DDBB3472D3}.Debug|x64.ActiveCfg = Debug|x64 + {98E424B3-5B57-4AC2-8A95-79DDBB3472D3}.Debug|x64.Build.0 = Debug|x64 + {98E424B3-5B57-4AC2-8A95-79DDBB3472D3}.Debug|x86.ActiveCfg = Debug|Win32 + {98E424B3-5B57-4AC2-8A95-79DDBB3472D3}.Debug|x86.Build.0 = Debug|Win32 + {98E424B3-5B57-4AC2-8A95-79DDBB3472D3}.Release|x64.ActiveCfg = Release|x64 + {98E424B3-5B57-4AC2-8A95-79DDBB3472D3}.Release|x64.Build.0 = Release|x64 + {98E424B3-5B57-4AC2-8A95-79DDBB3472D3}.Release|x86.ActiveCfg = Release|Win32 + {98E424B3-5B57-4AC2-8A95-79DDBB3472D3}.Release|x86.Build.0 = Release|Win32 + {73465BF0-E1E1-4AD2-A5F2-DF14A54D1F5F}.Debug|x64.ActiveCfg = Debug|x64 + {73465BF0-E1E1-4AD2-A5F2-DF14A54D1F5F}.Debug|x64.Build.0 = Debug|x64 + {73465BF0-E1E1-4AD2-A5F2-DF14A54D1F5F}.Debug|x86.ActiveCfg = Debug|Win32 + {73465BF0-E1E1-4AD2-A5F2-DF14A54D1F5F}.Debug|x86.Build.0 = Debug|Win32 + {73465BF0-E1E1-4AD2-A5F2-DF14A54D1F5F}.Release|x64.ActiveCfg = Release|x64 + {73465BF0-E1E1-4AD2-A5F2-DF14A54D1F5F}.Release|x64.Build.0 = Release|x64 + {73465BF0-E1E1-4AD2-A5F2-DF14A54D1F5F}.Release|x86.ActiveCfg = Release|Win32 + {73465BF0-E1E1-4AD2-A5F2-DF14A54D1F5F}.Release|x86.Build.0 = Release|Win32 + {02EEA281-F0A1-4BE3-B833-5A9B4150F6B0}.Debug|x64.ActiveCfg = Debug|x64 + {02EEA281-F0A1-4BE3-B833-5A9B4150F6B0}.Debug|x64.Build.0 = Debug|x64 + {02EEA281-F0A1-4BE3-B833-5A9B4150F6B0}.Debug|x86.ActiveCfg = Debug|Win32 + {02EEA281-F0A1-4BE3-B833-5A9B4150F6B0}.Debug|x86.Build.0 = Debug|Win32 + {02EEA281-F0A1-4BE3-B833-5A9B4150F6B0}.Release|x64.ActiveCfg = Release|x64 + {02EEA281-F0A1-4BE3-B833-5A9B4150F6B0}.Release|x64.Build.0 = Release|x64 + {02EEA281-F0A1-4BE3-B833-5A9B4150F6B0}.Release|x86.ActiveCfg = Release|Win32 + {02EEA281-F0A1-4BE3-B833-5A9B4150F6B0}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/ToyEngine/Engine/HDRI/clarens_midday_4k.hdr b/ToyEngine/Engine/HDRI/clarens_midday_4k.hdr new file mode 100644 index 0000000..55d4894 Binary files /dev/null and b/ToyEngine/Engine/HDRI/clarens_midday_4k.hdr differ diff --git a/ToyEngine/Engine/Shaders/brdf_lut.comp b/ToyEngine/Engine/Shaders/brdf_lut.comp new file mode 100644 index 0000000..b52ac90 --- /dev/null +++ b/ToyEngine/Engine/Shaders/brdf_lut.comp @@ -0,0 +1,116 @@ +#version 450 core + +layout(local_size_x = 8, local_size_y = 8) in; +layout(rg16f, binding = 0) uniform image2D brdfLUT; + +const float PI = 3.14159265359; +// ---------------------------------------------------------------------------- +// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html +// efficient VanDerCorpus calculation. +float RadicalInverse_VdC(uint bits) +{ + bits = (bits << 16u) | (bits >> 16u); + bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); + bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); + bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); + bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); + return float(bits) * 2.3283064365386963e-10; // / 0x100000000 +} +// ---------------------------------------------------------------------------- +vec2 Hammersley(uint i, uint N) +{ + return vec2(float(i)/float(N), RadicalInverse_VdC(i)); +} +// ---------------------------------------------------------------------------- +vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness) +{ + float a = roughness*roughness; + + float phi = 2.0 * PI * Xi.x; + float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y)); + float sinTheta = sqrt(1.0 - cosTheta*cosTheta); + + // from spherical coordinates to cartesian coordinates - halfway vector + vec3 H; + H.x = cos(phi) * sinTheta; + H.y = sin(phi) * sinTheta; + H.z = cosTheta; + + // from tangent-space H vector to world-space sample vector + vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); + vec3 tangent = normalize(cross(up, N)); + vec3 bitangent = cross(N, tangent); + + vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z; + return normalize(sampleVec); +} +// ---------------------------------------------------------------------------- +float GeometrySchlickGGX(float NdotV, float roughness) +{ + // note that we use a different k for IBL + float a = roughness; + float k = (a * a) / 2.0; + + float nom = NdotV; + float denom = NdotV * (1.0 - k) + k; + + return nom / denom; +} +// ---------------------------------------------------------------------------- +float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness) +{ + float NdotV = max(dot(N, V), 0.0); + float NdotL = max(dot(N, L), 0.0); + float ggx2 = GeometrySchlickGGX(NdotV, roughness); + float ggx1 = GeometrySchlickGGX(NdotL, roughness); + + return ggx1 * ggx2; +} +// ---------------------------------------------------------------------------- +vec2 IntegrateBRDF(float NdotV, float roughness) +{ + vec3 V; + V.x = sqrt(1.0 - NdotV*NdotV); + V.y = 0.0; + V.z = NdotV; + + float A = 0.0; + float B = 0.0; + + vec3 N = vec3(0.0, 0.0, 1.0); + + const uint SAMPLE_COUNT = 1024u; + for(uint i = 0u; i < SAMPLE_COUNT; ++i) + { + // generates a sample vector that's biased towards the + // preferred alignment direction (importance sampling). + vec2 Xi = Hammersley(i, SAMPLE_COUNT); + vec3 H = ImportanceSampleGGX(Xi, N, roughness); + vec3 L = normalize(2.0 * dot(V, H) * H - V); + + float NdotL = max(L.z, 0.0); + float NdotH = max(H.z, 0.0); + float VdotH = max(dot(V, H), 0.0); + + if(NdotL > 0.0) + { + float G = GeometrySmith(N, V, L, roughness); + float G_Vis = (G * VdotH) / (NdotH * NdotV); + float Fc = pow(1.0 - VdotH, 5.0); + + A += (1.0 - Fc) * G_Vis; + B += Fc * G_Vis; + } + } + A /= float(SAMPLE_COUNT); + B /= float(SAMPLE_COUNT); + return vec2(A, B); +} +// ---------------------------------------------------------------------------- +void main() +{ + uvec2 pixelLocation = gl_GlobalInvocationID.xy; + vec2 texCoords = (vec2(pixelLocation)+vec2(0.5))/vec2(imageSize(brdfLUT)); + vec2 integratedBRDF = IntegrateBRDF(texCoords.x, texCoords.y); + imageStore(brdfLUT, ivec2(pixelLocation), vec4(integratedBRDF,0,0)); +} \ No newline at end of file diff --git a/ToyEngine/Engine/Shaders/cubemap.frag b/ToyEngine/Engine/Shaders/cubemap.frag new file mode 100644 index 0000000..8e9bd85 --- /dev/null +++ b/ToyEngine/Engine/Shaders/cubemap.frag @@ -0,0 +1,22 @@ +#version 450 core +out vec4 FragColor; +in vec3 WorldPos; + +uniform sampler2D equirectangularMap; + +const vec2 invAtan = vec2(0.1591, 0.3183); +vec2 SampleSphericalMap(vec3 v) +{ + vec2 uv = vec2(atan(v.z, v.x), asin(v.y)); + uv *= invAtan; + uv += 0.5; + return uv; +} + +void main() +{ + vec2 uv = SampleSphericalMap(normalize(WorldPos)); + vec3 color = texture(equirectangularMap, uv).rgb; + + FragColor = vec4(color, 1.0); +} diff --git a/ToyEngine/Engine/Shaders/cubemap.vert b/ToyEngine/Engine/Shaders/cubemap.vert new file mode 100644 index 0000000..19dc4ef --- /dev/null +++ b/ToyEngine/Engine/Shaders/cubemap.vert @@ -0,0 +1,13 @@ +#version 450 core +layout (location = 0) in vec3 aPos; + +out vec3 WorldPos; + +uniform mat4 projection; +uniform mat4 view; + +void main() +{ + WorldPos = aPos; + gl_Position = projection * view * vec4(WorldPos, 1.0); +} \ No newline at end of file diff --git a/ToyEngine/Engine/Shaders/cubemap_prefilter.frag b/ToyEngine/Engine/Shaders/cubemap_prefilter.frag new file mode 100644 index 0000000..9214443 --- /dev/null +++ b/ToyEngine/Engine/Shaders/cubemap_prefilter.frag @@ -0,0 +1,107 @@ +#version 450 core +out vec4 FragColor; +in vec3 WorldPos; + +uniform samplerCube environmentMap; +uniform float roughness; + +const float PI = 3.14159265359; +// ---------------------------------------------------------------------------- +float DistributionGGX(vec3 N, vec3 H, float roughness) +{ + float a = roughness*roughness; + float a2 = a*a; + float NdotH = max(dot(N, H), 0.0); + float NdotH2 = NdotH*NdotH; + + float nom = a2; + float denom = (NdotH2 * (a2 - 1.0) + 1.0); + denom = PI * denom * denom; + + return nom / denom; +} +// ---------------------------------------------------------------------------- +// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html +// efficient VanDerCorpus calculation. +float RadicalInverse_VdC(uint bits) +{ + bits = (bits << 16u) | (bits >> 16u); + bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); + bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); + bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); + bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); + return float(bits) * 2.3283064365386963e-10; // / 0x100000000 +} +// ---------------------------------------------------------------------------- +vec2 Hammersley(uint i, uint N) +{ + return vec2(float(i)/float(N), RadicalInverse_VdC(i)); +} +// ---------------------------------------------------------------------------- +vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness) +{ + float a = roughness*roughness; + + float phi = 2.0 * PI * Xi.x; + float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y)); + float sinTheta = sqrt(1.0 - cosTheta*cosTheta); + + // from spherical coordinates to cartesian coordinates - halfway vector + vec3 H; + H.x = cos(phi) * sinTheta; + H.y = sin(phi) * sinTheta; + H.z = cosTheta; + + // from tangent-space H vector to world-space sample vector + vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); + vec3 tangent = normalize(cross(up, N)); + vec3 bitangent = cross(N, tangent); + + vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z; + return normalize(sampleVec); +} +// ---------------------------------------------------------------------------- +void main() +{ + vec3 N = normalize(WorldPos); + + // make the simplyfying assumption that V equals R equals the normal + vec3 R = N; + vec3 V = R; + + const uint SAMPLE_COUNT = 1024u; + vec3 prefilteredColor = vec3(0.0); + float totalWeight = 0.0; + + for(uint i = 0u; i < SAMPLE_COUNT; ++i) + { + // generates a sample vector that's biased towards the preferred alignment direction (importance sampling). + vec2 Xi = Hammersley(i, SAMPLE_COUNT); + vec3 H = ImportanceSampleGGX(Xi, N, roughness); + vec3 L = normalize(2.0 * dot(V, H) * H - V); + + float NdotL = max(dot(N, L), 0.0); + if(NdotL > 0.0) + { + // sample from the environment's mip level based on roughness/pdf + float D = DistributionGGX(N, H, roughness); + float NdotH = max(dot(N, H), 0.0); + float HdotV = max(dot(H, V), 0.0); + float pdf = D * NdotH / (4.0 * HdotV) + 0.0001; + + //float resolution = 512.0; // resolution of source cubemap (per face) + float resolution = float(textureSize(environmentMap,0).x); // resolution of source cubemap (per face) + float saTexel = 4.0 * PI / (6.0 * resolution * resolution); + float saSample = 1.0 / (float(SAMPLE_COUNT) * pdf + 0.0001); + + float mipLevel = roughness == 0.0 ? 0.0 : 0.5 * log2(saSample / saTexel); + + prefilteredColor += textureLod(environmentMap, L, mipLevel).rgb * NdotL; + totalWeight += NdotL; + } + } + + prefilteredColor = prefilteredColor / totalWeight; + + FragColor = vec4(prefilteredColor, 1.0); +} diff --git a/ToyEngine/Engine/Shaders/debug.frag b/ToyEngine/Engine/Shaders/debug.frag new file mode 100644 index 0000000..a182182 --- /dev/null +++ b/ToyEngine/Engine/Shaders/debug.frag @@ -0,0 +1,14 @@ +#version 450 core + +layout (location = 4) out vec4 gDebug; + +in vec2 TexCoords; +in vec3 WorldPos; +in vec3 Normal; + +uniform vec3 color; + +void main() +{ + gDebug = vec4(color,1); +} \ No newline at end of file diff --git a/ToyEngine/Engine/Shaders/debug.vert b/ToyEngine/Engine/Shaders/debug.vert new file mode 100644 index 0000000..8e2587b --- /dev/null +++ b/ToyEngine/Engine/Shaders/debug.vert @@ -0,0 +1,22 @@ +#version 330 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; +layout (location = 2) in vec2 aTexCoords; + +out vec2 TexCoords; +out vec3 WorldPos; +out vec3 Normal; + +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; + +void main() +{ + TexCoords = aTexCoords; + WorldPos = vec3(model * vec4(aPos, 1.0)); + Normal = mat3(model) * aNormal; + + gl_Position = projection * view * vec4(WorldPos, 1.0); + +} \ No newline at end of file diff --git a/ToyEngine/Engine/Shaders/final.frag b/ToyEngine/Engine/Shaders/final.frag new file mode 100644 index 0000000..9c894c6 --- /dev/null +++ b/ToyEngine/Engine/Shaders/final.frag @@ -0,0 +1,42 @@ +#version 450 core + +out vec4 FragColor; + +in vec2 TexCoords; + +uniform sampler2D gBaseColor; +uniform sampler2D gDebug; +uniform float exposure = 1; +uniform bool showDebug = false; + +vec3 ACESToneMapping(vec3 color) +{ + const float A = 2.51; + const float B = 0.03; + const float C = 2.43; + const float D = 0.59; + const float E = 0.14; + return (color * (A * color + B)) / (color * (C * color + D) + E); +} + +void main() +{ + vec4 rgbm = texture(gBaseColor, TexCoords); + vec4 debug = texture(gDebug, TexCoords); + if(rgbm.a==0 && (showDebug ? debug.a==0 : true)) + { + //FragColor = vec4(1,0,0,1); + //return; + discard; + } + vec3 color = 8 * rgbm.rgb * rgbm.a; + + color *= exposure; + color = ACESToneMapping(color); + + //color = color / (color + vec3(1.0)); + color = pow(color, vec3(1.0/2.2)); + FragColor = vec4(color, 1.0); + if(showDebug) + FragColor = mix(FragColor, debug, debug.a); +} \ No newline at end of file diff --git a/ToyEngine/Engine/Shaders/final.vert b/ToyEngine/Engine/Shaders/final.vert new file mode 100644 index 0000000..6317aab --- /dev/null +++ b/ToyEngine/Engine/Shaders/final.vert @@ -0,0 +1,11 @@ +#version 450 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec2 aTexCoords; + +out vec2 TexCoords; + +void main() +{ + TexCoords = aTexCoords; + gl_Position = vec4(aPos, 1.0); +} \ No newline at end of file diff --git a/ToyEngine/Engine/Shaders/irradiance_convolution.frag b/ToyEngine/Engine/Shaders/irradiance_convolution.frag new file mode 100644 index 0000000..7e9e642 --- /dev/null +++ b/ToyEngine/Engine/Shaders/irradiance_convolution.frag @@ -0,0 +1,43 @@ +#version 450 core +out vec4 FragColor; +in vec3 WorldPos; + +uniform samplerCube environmentMap; + +const float PI = 3.14159265359; + +void main() +{ + // The world vector acts as the normal of a tangent surface + // from the origin, aligned to WorldPos. Given this normal, calculate all + // incoming radiance of the environment. The result of this radiance + // is the radiance of light coming from -Normal direction, which is what + // we use in the PBR shader to sample irradiance. + vec3 N = normalize(WorldPos); + + vec3 irradiance = vec3(0.0); + + // tangent space calculation from origin point + vec3 up = vec3(0.0, 1.0, 0.0); + vec3 right = normalize(cross(up, N)); + up = normalize(cross(N, right)); + + float sampleDelta = 0.025; + float nrSamples = 0.0; + for(float phi = 0.0; phi < 2.0 * PI; phi += sampleDelta) + { + for(float theta = 0.0; theta < 0.5 * PI; theta += sampleDelta) + { + // spherical to cartesian (in tangent space) + vec3 tangentSample = vec3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta)); + // tangent space to world + vec3 sampleVec = tangentSample.x * right + tangentSample.y * up + tangentSample.z * N; + + irradiance += texture(environmentMap, sampleVec).rgb * cos(theta) * sin(theta); + nrSamples++; + } + } + irradiance = PI * irradiance * (1.0 / float(nrSamples)); + + FragColor = vec4(irradiance, 1.0); +} diff --git a/ToyEngine/Engine/Shaders/model.frag b/ToyEngine/Engine/Shaders/model.frag new file mode 100644 index 0000000..22c49e2 --- /dev/null +++ b/ToyEngine/Engine/Shaders/model.frag @@ -0,0 +1,61 @@ +#version 450 core +uniform sampler2D texture_basecolor; +uniform sampler2D texture_metallic_roughness; +uniform sampler2D texture_normal; + +uniform bool texture_basecolor_available = false; +uniform bool texture_metallic_roughness_available = false; +uniform bool texture_normal_available = false; + +uniform vec3 baseColor; +uniform vec2 metallicRoughness; + +layout (location = 0) out vec4 gBaseColor; +layout (location = 1) out vec3 gNormal; +layout (location = 2) out vec3 gPosition; +layout (location = 3) out vec2 gMetallicRoughness; +layout (location = 4) out vec4 gDebug; + +in vec2 TexCoords; +in vec3 WorldPos; +in vec3 Normal; + +vec3 getNormalFromMap() +{ + vec3 tangentNormal = texture(texture_normal, TexCoords).xyz * 2.0 - 1.0; + + vec3 Q1 = dFdx(WorldPos); + vec3 Q2 = dFdy(WorldPos); + vec2 st1 = dFdx(TexCoords); + vec2 st2 = dFdy(TexCoords); + + vec3 N = normalize(Normal); + vec3 T = normalize(Q1*st2.t - Q2*st1.t); + vec3 B = -normalize(cross(N, T)); + mat3 TBN = mat3(T, B, N); + + return normalize(TBN * tangentNormal); +} + +void main() +{ + if(texture_basecolor_available) + gBaseColor = texture(texture_basecolor, TexCoords); + else + gBaseColor = vec4(baseColor, 1); + if(gBaseColor.a<0.4) + discard; + gPosition = WorldPos; + if(texture_normal_available) + gNormal = getNormalFromMap(); + else + gNormal = Normal; + if(!gl_FrontFacing) + gNormal = -gNormal; + if(texture_metallic_roughness_available) + gMetallicRoughness = texture(texture_metallic_roughness, TexCoords).bg; + else + gMetallicRoughness = metallicRoughness; + + gDebug = vec4(0); +} \ No newline at end of file diff --git a/ToyEngine/Engine/Shaders/model.vert b/ToyEngine/Engine/Shaders/model.vert new file mode 100644 index 0000000..28f5787 --- /dev/null +++ b/ToyEngine/Engine/Shaders/model.vert @@ -0,0 +1,55 @@ +#version 450 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; +layout (location = 2) in vec2 aTexCoords; +layout (location = 3) in ivec4 boneIds; +layout (location = 4) in vec4 weights; + +out vec2 TexCoords; +out vec3 WorldPos; +out vec3 Normal; + +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; + +const int MAX_BONES = 100; +const int MAX_BONE_INFLUENCE = 4; +layout (std140, binding = 1) uniform FinalBonesMatrices +{ + mat4 finalBonesMatrices[MAX_BONES]; +}; + +void main() +{ + vec4 totalPosition = vec4(0.0f); + vec3 totalNormal = vec3(0); + int boneCount = 0; + for(int i = 0 ; i < MAX_BONE_INFLUENCE ; i++) + { + if(boneIds[i] == -1) + continue; + if(boneIds[i] >= MAX_BONES) + { + totalPosition = vec4(aPos,1.0f); + break; + } + boneCount++; + vec4 localPosition = finalBonesMatrices[boneIds[i]] * vec4(aPos,1.0f); + totalPosition += localPosition * weights[i]; + vec3 localNormal = mat3(finalBonesMatrices[boneIds[i]]) * aNormal; + totalNormal += localNormal * weights[i]; + } + + if(boneCount == 0) + { + totalPosition = vec4(aPos, 1); + totalNormal = vec3(aNormal); + } + + TexCoords = aTexCoords; + WorldPos = vec3(model * totalPosition); + Normal = mat3(model) * totalNormal; + + gl_Position = projection * view * vec4(WorldPos, 1.0); +} \ No newline at end of file diff --git a/ToyEngine/Engine/Shaders/model_shadow.frag b/ToyEngine/Engine/Shaders/model_shadow.frag new file mode 100644 index 0000000..8b44c38 --- /dev/null +++ b/ToyEngine/Engine/Shaders/model_shadow.frag @@ -0,0 +1,12 @@ +#version 450 core + +uniform sampler2D texture_basecolor; + +in vec2 TexCoords; + +void main() +{ + vec4 baseColor = texture(texture_basecolor, TexCoords); + if(baseColor.a<0.4) + discard; +} \ No newline at end of file diff --git a/ToyEngine/Engine/Shaders/model_shadow.geom b/ToyEngine/Engine/Shaders/model_shadow.geom new file mode 100644 index 0000000..d2960c9 --- /dev/null +++ b/ToyEngine/Engine/Shaders/model_shadow.geom @@ -0,0 +1,24 @@ +#version 450 core + +layout(triangles, invocations = 5) in; +layout(triangle_strip, max_vertices = 3) out; + +layout (std140, binding = 0) uniform LightSpaceMatrices +{ + mat4 lightSpaceMatrices[16]; +}; + +in vec2 vTexCoords[]; +out vec2 TexCoords; + +void main() +{ + for (int i = 0; i < 3; ++i) + { + TexCoords = vTexCoords[i]; + gl_Position = lightSpaceMatrices[gl_InvocationID] * gl_in[i].gl_Position; + gl_Layer = gl_InvocationID; + EmitVertex(); + } + EndPrimitive(); +} \ No newline at end of file diff --git a/ToyEngine/Engine/Shaders/model_shadow.vert b/ToyEngine/Engine/Shaders/model_shadow.vert new file mode 100644 index 0000000..f48641d --- /dev/null +++ b/ToyEngine/Engine/Shaders/model_shadow.vert @@ -0,0 +1,48 @@ +#version 450 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; +layout (location = 2) in vec2 aTexCoords; +layout (location = 3) in ivec4 boneIds; +layout (location = 4) in vec4 weights; + +out vec2 vTexCoords; + +uniform mat4 model; + +const int MAX_BONES = 100; +const int MAX_BONE_INFLUENCE = 4; +layout (std140, binding = 1) uniform FinalBonesMatrices +{ + mat4 finalBonesMatrices[MAX_BONES]; +}; + +void main() +{ + vec4 totalPosition = vec4(0.0f); + vec3 totalNormal = vec3(0); + int boneCount = 0; + for(int i = 0 ; i < MAX_BONE_INFLUENCE ; i++) + { + if(boneIds[i] == -1) + continue; + if(boneIds[i] >= MAX_BONES) + { + totalPosition = vec4(aPos,1.0f); + break; + } + boneCount++; + vec4 localPosition = finalBonesMatrices[boneIds[i]] * vec4(aPos,1.0f); + totalPosition += localPosition * weights[i]; + vec3 localNormal = mat3(finalBonesMatrices[boneIds[i]]) * aNormal; + totalNormal += localNormal * weights[i]; + } + + if(boneCount == 0) + { + totalPosition = vec4(aPos, 1); + totalNormal = vec3(aNormal); + } + + vTexCoords = aTexCoords; + gl_Position = model * totalPosition; +} \ No newline at end of file diff --git a/ToyEngine/Engine/Shaders/pbr.comp b/ToyEngine/Engine/Shaders/pbr.comp new file mode 100644 index 0000000..4bd8675 --- /dev/null +++ b/ToyEngine/Engine/Shaders/pbr.comp @@ -0,0 +1,241 @@ +#version 450 core + +layout (local_size_x = 8, local_size_y = 8) in; + +layout(rgba8, binding = 0) uniform image2D gBaseColor; +uniform sampler2D gNormal; +uniform sampler2D gPosition; +uniform sampler2D gMetallicRoughness; +uniform sampler2DArray gShadowMap; + +uniform samplerCube irradianceMap; +uniform samplerCube prefilterMap; +uniform sampler2D brdfLUT; + +layout (std140, binding = 0) uniform LightSpaceMatrices +{ + mat4 lightSpaceMatrices[16]; +}; +uniform mat4 view; +uniform float farPlane; +uniform float shadowCascadePlaneDistances[16]; +uniform float shadowBiases[16]; +uniform int shadowCascadeCount; +uniform float shadowBlendRatio; + +uniform vec3 mainLightDirection; +uniform vec3 mainLightRadiance; + +uniform vec3 camPos; + +const float PI = 3.14159265359; + +float DistributionGGX(vec3 N, vec3 H, float roughness) +{ + float a = roughness*roughness; + float a2 = a*a; + float NdotH = max(dot(N, H), 0.0); + float NdotH2 = NdotH*NdotH; + + float nom = a2; + float denom = (NdotH2 * (a2 - 1.0) + 1.0); + denom = PI * denom * denom; + + return nom / denom; +} +// ---------------------------------------------------------------------------- +float GeometrySchlickGGX(float NdotV, float roughness) +{ + float r = (roughness + 1.0); + float k = (r*r) / 8.0; + + float nom = NdotV; + float denom = NdotV * (1.0 - k) + k; + + return nom / denom; +} +// ---------------------------------------------------------------------------- +float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness) +{ + float NdotV = max(dot(N, V), 0.0); + float NdotL = max(dot(N, L), 0.0); + float ggx2 = GeometrySchlickGGX(NdotV, roughness); + float ggx1 = GeometrySchlickGGX(NdotL, roughness); + + return ggx1 * ggx2; +} +// ---------------------------------------------------------------------------- +vec3 fresnelSchlick(float cosTheta, vec3 F0) +{ + return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); +} +vec3 fresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness) +{ + return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0); +} + +vec3 ambientLighting(vec3 N, vec3 V, vec3 F0, vec3 albedo, float metallic, float roughness, float ao) +{ + // ambient lighting (we now use IBL as the ambient term) + vec3 F = fresnelSchlickRoughness(clamp(dot(N, V),0.,1.), F0, roughness); + + vec3 kS = F; + vec3 kD = 1.0 - kS; + kD *= 1.0 - metallic; + + vec3 irradiance = texture(irradianceMap, N).rgb; + vec3 diffuse = irradiance * albedo; + + // sample both the pre-filter map and the BRDF lut and combine them together as per the Split-Sum approximation to get the IBL specular part. + const float MAX_REFLECTION_LOD = 4.0; + vec3 R = reflect(-V, N); + vec3 prefilteredColor = textureLod(prefilterMap, R, roughness * MAX_REFLECTION_LOD).rgb; + vec2 brdf = texture(brdfLUT, vec2(clamp(dot(N, V),0.,1.), roughness)).rg; + vec3 specular = prefilteredColor * (F * brdf.x + brdf.y); + + return (kD * diffuse + specular) * ao; +} + + +const int pcfRadius = 3; +float getShadowFromLayer(vec3 fragPosWorldSpace, vec3 normal,int layer) +{ + float normalBias = 1.2*4. /** (1+pcfRadius)*/ * shadowBiases[layer]*max((1.0 - dot(normal, mainLightDirection)), 0.1)/textureSize(gShadowMap, 0).x; + normalBias = max(normalBias, 0.05); + vec4 fragPosLightSpace = lightSpaceMatrices[layer] * vec4(fragPosWorldSpace+normal*normalBias, 1.0); + // perform perspective divide + vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w; + // transform to [0,1] range + projCoords = projCoords * 0.5 + 0.5; + + // get depth of current fragment from light's perspective + float currentDepth = projCoords.z; + + // keep the shadow at 0.0 when outside the far_plane region of the light's frustum. + if (currentDepth > 1.0) + { + return 0.0; + } + + // PCF + float shadow = 0.0; + vec2 texelSize = 1.0 / vec2(textureSize(gShadowMap, 0)); + for(int x = -pcfRadius; x <= pcfRadius; ++x) + { + for(int y = -pcfRadius; y <= pcfRadius; ++y) + { + float pcfDepth = texture(gShadowMap, vec3(projCoords.xy + vec2(x, y) * texelSize, layer)).r; + shadow += currentDepth > pcfDepth ? 1.0 : 0.0; + } + } + shadow /= (2*pcfRadius+1)*(2*pcfRadius+1); + return shadow; +} + +float ShadowCalculation(vec3 fragPosWorldSpace, vec3 normal, out int layer) +{ + // select cascade layer + vec4 fragPosViewSpace = view * vec4(fragPosWorldSpace, 1.0); + float depthValue = abs(fragPosViewSpace.z); + + layer = -1; + for (int i = 0; i < shadowCascadeCount; ++i) + { + if (depthValue < shadowCascadePlaneDistances[i]) + { + layer = i; + break; + } + } +// if (layer == -1) +// { +// layer = shadowCascadeCount; +// } + + float shadow = getShadowFromLayer(fragPosWorldSpace,normal,layer); + + + float nextLayerBeginDepth = layer==0? (1-shadowBlendRatio)*shadowCascadePlaneDistances[layer] + :(1-shadowBlendRatio)*shadowCascadePlaneDistances[layer]+shadowBlendRatio*shadowCascadePlaneDistances[layer-1]; + if(depthValue > nextLayerBeginDepth) + { + float shadowNext = getShadowFromLayer(fragPosWorldSpace,normal,layer+1); + shadow = mix(shadow,shadowNext, (depthValue-nextLayerBeginDepth)/(shadowCascadePlaneDistances[layer]-nextLayerBeginDepth)); + } + return shadow; +} + + + +vec4 encodeRGBM(vec3 color) +{ + if(dot(color,color)==0) + return vec4(0,0,0,1); + vec4 rgbm; + float range = 8; + color /= range; + rgbm.a = clamp(max(max(color.r, color.g), max(color.b, 1e-6)), 0.0, 1.0); + rgbm.a = ceil(rgbm.a * 255.0) / 255.0; + rgbm.rgb = color / rgbm.a; + return rgbm; +} + +void main() +{ + ivec2 pixelLocation = ivec2(gl_GlobalInvocationID.xy); + + + //vec3 albedo = pow(texelFetch(gBaseColor, pixelLocation, 0).rgb, vec3(2.2)); + vec3 albedo = pow(imageLoad(gBaseColor, pixelLocation).rgb, vec3(2.2)); + float metallic = texelFetch(gMetallicRoughness, pixelLocation, 0).r; + float roughness = texelFetch(gMetallicRoughness, pixelLocation, 0).g; + + vec3 worldPos = texelFetch(gPosition, pixelLocation,0).xyz; + vec3 normal = texelFetch(gNormal, pixelLocation,0).xyz; + + if(normal==vec3(0)) + { + //vec3 color = mainLightRadiance; + //imageStore(gBaseColor, pixelLocation, vec4(color, 1.0)); + imageStore(gBaseColor, pixelLocation, vec4(0)); + return; + } + normal = normalize(normal); + + vec3 V = normalize(camPos - worldPos); + + vec3 F0 = vec3(0.04); + F0 = mix(F0, albedo, metallic); + + // calculate light radiance + vec3 L = normalize(mainLightDirection); + vec3 H = normalize(V + L); + //float distance = length(lightPositions[i] - WorldPos); + //float attenuation = 1.0 / (distance * distance); + vec3 radiance = mainLightRadiance ;//* attenuation; + + // cook-torrance brdf + float NDF = DistributionGGX(normal, H, roughness); + float G = GeometrySmith(normal, V, L, roughness); + vec3 F = fresnelSchlick(clamp(dot(H, V),0.,1.), F0); + //F = clamp(F,vec3(0),vec3(1)); + + vec3 kS = F; + vec3 kD = vec3(1.0) - kS; + kD *= 1.0 - metallic; + + vec3 nominator = NDF * G * F; + float denominator = 4.0 * max(dot(normal, V), 0.0) * max(dot(normal, L), 0.0) + 0.001; + vec3 specular = nominator / denominator; + + float NdotL = max(dot(normal, L), 0.0); + vec3 Lo = (kD * albedo / PI + specular) * radiance * NdotL; + + vec3 ambient = ambientLighting(normal, V, F0, albedo, metallic, roughness, 1); + + int debugLayer; + float shadow = ShadowCalculation(worldPos, normal, debugLayer); + + vec3 color = (1-shadow)*Lo + ambient; + imageStore(gBaseColor, pixelLocation, encodeRGBM(color)); +} \ No newline at end of file diff --git a/ToyEngine/Engine/Shaders/plain.frag b/ToyEngine/Engine/Shaders/plain.frag new file mode 100644 index 0000000..6c11f5b --- /dev/null +++ b/ToyEngine/Engine/Shaders/plain.frag @@ -0,0 +1,23 @@ +#version 450 core + +layout (location = 0) out vec4 gBaseColor; +layout (location = 1) out vec3 gNormal; +layout (location = 2) out vec3 gPosition; +layout (location = 3) out vec2 gMetallicRoughness; + +in vec2 TexCoords; +in vec3 WorldPos; +in vec3 Normal; + +// material parameters +uniform vec3 albedo; +uniform float metallic; +uniform float roughness; + +void main() +{ + gBaseColor = vec4(albedo, 1); + gPosition = WorldPos; + gNormal = normalize(Normal); + gMetallicRoughness = vec2(metallic,roughness); +} \ No newline at end of file diff --git a/ToyEngine/Engine/Shaders/plain.vert b/ToyEngine/Engine/Shaders/plain.vert new file mode 100644 index 0000000..8e2587b --- /dev/null +++ b/ToyEngine/Engine/Shaders/plain.vert @@ -0,0 +1,22 @@ +#version 330 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; +layout (location = 2) in vec2 aTexCoords; + +out vec2 TexCoords; +out vec3 WorldPos; +out vec3 Normal; + +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; + +void main() +{ + TexCoords = aTexCoords; + WorldPos = vec3(model * vec4(aPos, 1.0)); + Normal = mat3(model) * aNormal; + + gl_Position = projection * view * vec4(WorldPos, 1.0); + +} \ No newline at end of file diff --git a/ToyEngine/Engine/Shaders/skybox.frag b/ToyEngine/Engine/Shaders/skybox.frag new file mode 100644 index 0000000..fa086dd --- /dev/null +++ b/ToyEngine/Engine/Shaders/skybox.frag @@ -0,0 +1,32 @@ +#version 450 core +out vec4 FragColor; +in vec3 WorldPos; + +uniform samplerCube environmentMap; +uniform float exposure = 1; + +vec3 ACESToneMapping(vec3 color) +{ + const float A = 2.51; + const float B = 0.03; + const float C = 2.43; + const float D = 0.59; + const float E = 0.14; + return (color * (A * color + B)) / (color * (C * color + D) + E); +} + +void main() +{ + vec3 color = texture(environmentMap, WorldPos).rgb; + + // HDR tonemap + //envColor = envColor / (envColor + vec3(1.0)); + + color *= exposure; + color = ACESToneMapping(color); + + // gamma correct + color = pow(color, vec3(1.0/2.2)); + + FragColor = vec4(color, 1.0); +} diff --git a/ToyEngine/Engine/Shaders/skybox.vert b/ToyEngine/Engine/Shaders/skybox.vert new file mode 100644 index 0000000..f2d2cbb --- /dev/null +++ b/ToyEngine/Engine/Shaders/skybox.vert @@ -0,0 +1,17 @@ +#version 450 core +layout (location = 0) in vec3 aPos; + +uniform mat4 projection; +uniform mat4 view; + +out vec3 WorldPos; + +void main() +{ + WorldPos = aPos; + + mat4 rotView = mat4(mat3(view)); + vec4 clipPos = projection * rotView * vec4(WorldPos, 1.0); + + gl_Position = clipPos.xyww; +} \ No newline at end of file diff --git a/ToyEngine/ToyEngine.vcxproj b/ToyEngine/ToyEngine.vcxproj index a72d952..ea63187 100644 --- a/ToyEngine/ToyEngine.vcxproj +++ b/ToyEngine/ToyEngine.vcxproj @@ -24,14 +24,12 @@ - - @@ -45,7 +43,6 @@ - @@ -54,7 +51,6 @@ - @@ -105,7 +101,7 @@ Unicode - Application + StaticLibrary true v143 Unicode @@ -136,10 +132,10 @@ - $(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)include + $(VC_IncludePath);$(WindowsSDK_IncludePath); - $(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)include + $(VC_IncludePath);$(WindowsSDK_IncludePath); @@ -147,6 +143,7 @@ true WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true + $(ProjectDir)include Console @@ -161,6 +158,7 @@ true WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true + $(ProjectDir)include Console @@ -181,6 +179,7 @@ MaxSpeed Speed Default + $(ProjectDir)include Console @@ -198,6 +197,7 @@ stdcpp20 stdc17 true + $(ProjectDir)include Console diff --git a/ToyEngine/ToyEngine.vcxproj.filters b/ToyEngine/ToyEngine.vcxproj.filters index 688fc93..0be9677 100644 --- a/ToyEngine/ToyEngine.vcxproj.filters +++ b/ToyEngine/ToyEngine.vcxproj.filters @@ -60,9 +60,6 @@ 头文件 - - 头文件 - 头文件 @@ -72,9 +69,6 @@ 头文件 - - 头文件 - @@ -122,9 +116,6 @@ 源文件 - - 源文件 - 源文件 @@ -134,9 +125,6 @@ 源文件 - - 源文件 - diff --git a/ToyEngine/src/IblUtils.h b/ToyEngine/src/IblUtils.h index 53063b8..7645ee6 100644 --- a/ToyEngine/src/IblUtils.h +++ b/ToyEngine/src/IblUtils.h @@ -7,7 +7,7 @@ struct GladGLContext; class IblUtils { public: - static constexpr char hdrPath[] = "HDRI/clarens_midday_4k.hdr"; + static constexpr char hdrPath[] = "Engine/HDRI/clarens_midday_4k.hdr"; static constexpr int cubemapSize = 1024; static constexpr int irradianceMapSize = 32; static constexpr int prefilterMapSize = 128; diff --git a/ToyEngine/src/MainWindow.cpp b/ToyEngine/src/MainWindow.cpp index 4656b24..38f8a82 100644 --- a/ToyEngine/src/MainWindow.cpp +++ b/ToyEngine/src/MainWindow.cpp @@ -1,7 +1,5 @@ #include "MainWindow.h" #include "Particle.h" -#include "DemoWorld.h" -#include "ParticleWorld.h" #include "RenderingSystem.h" @@ -9,50 +7,13 @@ MainWindow::MainWindow() { } -int MainWindow::exec() +int MainWindow::exec(std::unique_ptr world_) { - glfwInit(); - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - - GLFWmonitor* monitor = glfwGetPrimaryMonitor(); - float xscale, yscale; - glfwGetMonitorContentScale(monitor, &xscale, &yscale); - window = glfwCreateWindow(kWindowWidth * xscale, kWindowHeight * yscale, "ToyEngine", NULL, NULL); - glfwSetFramebufferSizeCallback(window, [](GLFWwindow* window, int width, int height) { - RenderingSystem::instance().framebufferSizeCallback(window, width, height); - }); - glfwSetCursorPosCallback(window, [](GLFWwindow* window, double xpos, double ypos) { - MainWindow::instance().cursorPosCallback(window, xpos, ypos); - }); - glfwSetMouseButtonCallback(window, [](GLFWwindow* window, int button, int action, int mods) { - MainWindow::instance().mouseButtonCallback(window, button, action, mods); - }); - glfwSetScrollCallback(window, [](GLFWwindow* window, double xoffset, double yoffset) { - MainWindow::instance().scrollCallback(window, xoffset, yoffset); - }); - glfwSetKeyCallback(window, [](GLFWwindow* window, int key, int scancode, int action, int mods) { - MainWindow::instance().keyCallback(window, key, scancode, action, mods); - }); - int xpos, ypos, width, height; - glfwGetMonitorWorkarea(monitor, &xpos, &ypos, &width, &height); - glfwSetWindowPos(window, xpos + (width - (kWindowWidth * xscale)) / 2, ypos + (height - kWindowHeight * yscale) / 2); - glfwMakeContextCurrent(window); - gl = std::make_unique(); - if (!gladLoadGLContext(gl.get(), [](const char* name) { return (GLADapiproc)glfwGetProcAddress(name); })) - { - std::cout << "Failed to initialize GLAD" << std::endl; - return -1; - } - - - world = std::make_unique(); - + world = std::move(world_); auto [minPos, maxPos] = world->getAABB(); std::cout << std::format("{},{},{} {},{},{}\n", minPos.x, minPos.y, minPos.z, maxPos.x, maxPos.y, maxPos.z); - RenderingSystem::instance().initialize(gl.get(), xscale, world.get()); + RenderingSystem::instance().initialize(gl.get(), pixelRatio, world.get()); int w, h; glfwGetFramebufferSize(window, &w, &h); @@ -107,6 +68,7 @@ int MainWindow::exec() } glfwTerminate(); + return 0; } void MainWindow::processInput(GLFWwindow* window, float deltaTime) @@ -154,3 +116,44 @@ GLFWwindow* MainWindow::getWindow() { return window; } + +int MainWindow::initialize() +{ + glfwInit(); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + + GLFWmonitor* monitor = glfwGetPrimaryMonitor(); + float xscale, yscale; + glfwGetMonitorContentScale(monitor, &xscale, &yscale); + pixelRatio = xscale; + window = glfwCreateWindow(kWindowWidth * xscale, kWindowHeight * yscale, "ToyEngine", NULL, NULL); + glfwSetFramebufferSizeCallback(window, [](GLFWwindow* window, int width, int height) { + RenderingSystem::instance().framebufferSizeCallback(window, width, height); + }); + glfwSetCursorPosCallback(window, [](GLFWwindow* window, double xpos, double ypos) { + MainWindow::instance().cursorPosCallback(window, xpos, ypos); + }); + glfwSetMouseButtonCallback(window, [](GLFWwindow* window, int button, int action, int mods) { + MainWindow::instance().mouseButtonCallback(window, button, action, mods); + }); + glfwSetScrollCallback(window, [](GLFWwindow* window, double xoffset, double yoffset) { + MainWindow::instance().scrollCallback(window, xoffset, yoffset); + }); + glfwSetKeyCallback(window, [](GLFWwindow* window, int key, int scancode, int action, int mods) { + MainWindow::instance().keyCallback(window, key, scancode, action, mods); + }); + int xpos, ypos, width, height; + glfwGetMonitorWorkarea(monitor, &xpos, &ypos, &width, &height); + glfwSetWindowPos(window, xpos + (width - (kWindowWidth * xscale)) / 2, ypos + (height - kWindowHeight * yscale) / 2); + glfwMakeContextCurrent(window); + gl = std::make_unique(); + if (!gladLoadGLContext(gl.get(), [](const char* name) { return (GLADapiproc)glfwGetProcAddress(name); })) + { + std::cout << "Failed to initialize GLAD" << std::endl; + return -1; + } + + return 0; +} diff --git a/ToyEngine/src/MainWindow.h b/ToyEngine/src/MainWindow.h index 85ca002..0e05fec 100644 --- a/ToyEngine/src/MainWindow.h +++ b/ToyEngine/src/MainWindow.h @@ -11,7 +11,8 @@ public: static MainWindow& instance(); static GladGLContext* getGLContext(); GLFWwindow* getWindow(); - int exec(); + int initialize(); + int exec(std::unique_ptr world); private: MainWindow(); @@ -23,6 +24,7 @@ private: static constexpr int kWindowWidth = 1200; static constexpr int kWindowHeight = 675; + float pixelRatio; GLFWwindow* window = nullptr; std::unique_ptr gl; diff --git a/ToyEngine/src/Shader.cpp b/ToyEngine/src/Shader.cpp index acecd6f..ac94ac9 100644 --- a/ToyEngine/src/Shader.cpp +++ b/ToyEngine/src/Shader.cpp @@ -1,5 +1,6 @@ #include #include "Shader.h" +#include Shader::Shader(GladGLContext* gl, const char* vertexPath, const char* fragmentPath, const char* geometryPath) : Shader(gl) @@ -33,7 +34,7 @@ bool Shader::addShaderFromSourceFile(ShaderType type, const char* path) shaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); try { - shaderFile.open(path); + shaderFile.open(std::format("Engine/{}", path)); std::stringstream gShaderStream; gShaderStream << shaderFile.rdbuf(); shaderFile.close(); diff --git a/ToyEngine/src/main.cpp b/ToyEngine/src/main.cpp index 30105f8..cf090bd 100644 --- a/ToyEngine/src/main.cpp +++ b/ToyEngine/src/main.cpp @@ -1,12 +1,14 @@ #define STB_IMAGE_IMPLEMENTATION #include -#include "MainWindow.h" +//#include "MainWindow.h" +//#include "ParticleWorld.h" extern "C" { _declspec(dllexport) unsigned long NvOptimusEnablement = 0x00000001; } -int main() -{ - return MainWindow::instance().exec(); -} \ No newline at end of file +//int main() +//{ +// MainWindow::instance().initialize(); +// return MainWindow::instance().exec(std::make_unique()); +//} \ No newline at end of file