diff options
Diffstat (limited to '3rdparty/bgfx/examples/16-shadowmaps/shadowmaps.cpp')
-rw-r--r-- | 3rdparty/bgfx/examples/16-shadowmaps/shadowmaps.cpp | 3621 |
1 files changed, 1851 insertions, 1770 deletions
diff --git a/3rdparty/bgfx/examples/16-shadowmaps/shadowmaps.cpp b/3rdparty/bgfx/examples/16-shadowmaps/shadowmaps.cpp index 191a3426df3..9ee44d7fbbb 100644 --- a/3rdparty/bgfx/examples/16-shadowmaps/shadowmaps.cpp +++ b/3rdparty/bgfx/examples/16-shadowmaps/shadowmaps.cpp @@ -12,12 +12,20 @@ #include <bgfx/bgfx.h> #include <bx/timer.h> -#include <bx/fpumath.h> -#include <bx/crtimpl.h> +#include <bx/math.h> +#include <bx/file.h> #include "entry/entry.h" #include "camera.h" #include "imgui/imgui.h" +namespace bgfx +{ + int32_t read(bx::ReaderI* _reader, bgfx::VertexDecl& _decl, bx::Error* _err = NULL); +} + +namespace +{ + #define RENDERVIEW_SHADOWMAP_0_ID 1 #define RENDERVIEW_SHADOWMAP_1_ID 2 #define RENDERVIEW_SHADOWMAP_2_ID 3 @@ -38,31 +46,6 @@ #define RENDERVIEW_DRAWDEPTH_2_ID 18 #define RENDERVIEW_DRAWDEPTH_3_ID 19 -uint32_t packUint32(uint8_t _x, uint8_t _y, uint8_t _z, uint8_t _w) -{ - union - { - uint32_t ui32; - uint8_t arr[4]; - } un; - - un.arr[0] = _x; - un.arr[1] = _y; - un.arr[2] = _z; - un.arr[3] = _w; - - return un.ui32; -} - -uint32_t packF4u(float _x, float _y = 0.0f, float _z = 0.0f, float _w = 0.0f) -{ - const uint8_t xx = uint8_t(_x*127.0f + 128.0f); - const uint8_t yy = uint8_t(_y*127.0f + 128.0f); - const uint8_t zz = uint8_t(_z*127.0f + 128.0f); - const uint8_t ww = uint8_t(_w*127.0f + 128.0f); - return packUint32(xx, yy, zz, ww); -} - struct LightType { enum Enum @@ -160,33 +143,6 @@ struct ShadowMapRenderTargets }; }; -void imguiEnum(SmImpl::Enum& _enum) -{ - _enum = (SmImpl::Enum)imguiChoose(_enum - , "Hard" - , "PCF" - , "VSM" - , "ESM" - ); -} - -void imguiEnum(DepthImpl::Enum& _enum) -{ - _enum = (DepthImpl::Enum)imguiChoose(_enum - , "InvZ" - , "Linear" - ); -} - -void imguiEnum(LightType::Enum& _enum) -{ - _enum = (LightType::Enum)imguiChoose(_enum - , "Spot light" - , "Point light" - , "Directional light" - ); -} - struct PosNormalTexcoordVertex { float m_x; @@ -200,18 +156,18 @@ struct PosNormalTexcoordVertex static const float s_texcoord = 5.0f; static PosNormalTexcoordVertex s_hplaneVertices[] = { - { -1.0f, 0.0f, 1.0f, packF4u(0.0f, 1.0f, 0.0f), s_texcoord, s_texcoord }, - { 1.0f, 0.0f, 1.0f, packF4u(0.0f, 1.0f, 0.0f), s_texcoord, 0.0f }, - { -1.0f, 0.0f, -1.0f, packF4u(0.0f, 1.0f, 0.0f), 0.0f, s_texcoord }, - { 1.0f, 0.0f, -1.0f, packF4u(0.0f, 1.0f, 0.0f), 0.0f, 0.0f }, + { -1.0f, 0.0f, 1.0f, encodeNormalRgba8(0.0f, 1.0f, 0.0f), s_texcoord, s_texcoord }, + { 1.0f, 0.0f, 1.0f, encodeNormalRgba8(0.0f, 1.0f, 0.0f), s_texcoord, 0.0f }, + { -1.0f, 0.0f, -1.0f, encodeNormalRgba8(0.0f, 1.0f, 0.0f), 0.0f, s_texcoord }, + { 1.0f, 0.0f, -1.0f, encodeNormalRgba8(0.0f, 1.0f, 0.0f), 0.0f, 0.0f }, }; static PosNormalTexcoordVertex s_vplaneVertices[] = { - { -1.0f, 1.0f, 0.0f, packF4u(0.0f, 0.0f, -1.0f), 1.0f, 1.0f }, - { 1.0f, 1.0f, 0.0f, packF4u(0.0f, 0.0f, -1.0f), 1.0f, 0.0f }, - { -1.0f, -1.0f, 0.0f, packF4u(0.0f, 0.0f, -1.0f), 0.0f, 1.0f }, - { 1.0f, -1.0f, 0.0f, packF4u(0.0f, 0.0f, -1.0f), 0.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, encodeNormalRgba8(0.0f, 0.0f, -1.0f), 1.0f, 1.0f }, + { 1.0f, 1.0f, 0.0f, encodeNormalRgba8(0.0f, 0.0f, -1.0f), 1.0f, 0.0f }, + { -1.0f, -1.0f, 0.0f, encodeNormalRgba8(0.0f, 0.0f, -1.0f), 0.0f, 1.0f }, + { 1.0f, -1.0f, 0.0f, encodeNormalRgba8(0.0f, 0.0f, -1.0f), 0.0f, 0.0f }, }; static const uint16_t s_planeIndices[] = @@ -536,34 +492,34 @@ struct Uniforms void destroy() { - bgfx::destroyUniform(u_params0); - bgfx::destroyUniform(u_params1); - bgfx::destroyUniform(u_params2); - bgfx::destroyUniform(u_color); - bgfx::destroyUniform(u_smSamplingParams); - bgfx::destroyUniform(u_csmFarDistances); - - bgfx::destroyUniform(u_materialKa); - bgfx::destroyUniform(u_materialKd); - bgfx::destroyUniform(u_materialKs); - - bgfx::destroyUniform(u_tetraNormalGreen); - bgfx::destroyUniform(u_tetraNormalYellow); - bgfx::destroyUniform(u_tetraNormalBlue); - bgfx::destroyUniform(u_tetraNormalRed); - - bgfx::destroyUniform(u_shadowMapMtx0); - bgfx::destroyUniform(u_shadowMapMtx1); - bgfx::destroyUniform(u_shadowMapMtx2); - bgfx::destroyUniform(u_shadowMapMtx3); - - bgfx::destroyUniform(u_lightMtx); - bgfx::destroyUniform(u_lightPosition); - bgfx::destroyUniform(u_lightAmbientPower); - bgfx::destroyUniform(u_lightDiffusePower); - bgfx::destroyUniform(u_lightSpecularPower); - bgfx::destroyUniform(u_lightSpotDirectionInner); - bgfx::destroyUniform(u_lightAttenuationSpotOuter); + bgfx::destroy(u_params0); + bgfx::destroy(u_params1); + bgfx::destroy(u_params2); + bgfx::destroy(u_color); + bgfx::destroy(u_smSamplingParams); + bgfx::destroy(u_csmFarDistances); + + bgfx::destroy(u_materialKa); + bgfx::destroy(u_materialKd); + bgfx::destroy(u_materialKs); + + bgfx::destroy(u_tetraNormalGreen); + bgfx::destroy(u_tetraNormalYellow); + bgfx::destroy(u_tetraNormalBlue); + bgfx::destroy(u_tetraNormalRed); + + bgfx::destroy(u_shadowMapMtx0); + bgfx::destroy(u_shadowMapMtx1); + bgfx::destroy(u_shadowMapMtx2); + bgfx::destroy(u_shadowMapMtx3); + + bgfx::destroy(u_lightMtx); + bgfx::destroy(u_lightPosition); + bgfx::destroy(u_lightAmbientPower); + bgfx::destroy(u_lightDiffusePower); + bgfx::destroy(u_lightSpecularPower); + bgfx::destroy(u_lightSpotDirectionInner); + bgfx::destroy(u_lightAttenuationSpotOuter); } union @@ -841,8 +797,8 @@ struct Group void reset() { - m_vbh.idx = bgfx::invalidHandle; - m_ibh.idx = bgfx::invalidHandle; + m_vbh.idx = bgfx::kInvalidHandle; + m_ibh.idx = bgfx::kInvalidHandle; m_prims.clear(); } @@ -854,11 +810,6 @@ struct Group PrimitiveArray m_prims; }; -namespace bgfx -{ - int32_t read(bx::ReaderI* _reader, bgfx::VertexDecl& _decl, bx::Error* _err = NULL); -} - struct Mesh { void load(const void* _vertices, uint32_t _numVertices, const bgfx::VertexDecl _decl, const uint16_t* _indices, uint32_t _numIndices) @@ -973,11 +924,11 @@ struct Mesh for (GroupArray::const_iterator it = m_groups.begin(), itEnd = m_groups.end(); it != itEnd; ++it) { const Group& group = *it; - bgfx::destroyVertexBuffer(group.m_vbh); + bgfx::destroy(group.m_vbh); - if (bgfx::invalidHandle != group.m_ibh.idx) + if (bgfx::kInvalidHandle != group.m_ibh.idx) { - bgfx::destroyIndexBuffer(group.m_ibh); + bgfx::destroy(group.m_ibh); } } m_groups.clear(); @@ -1001,10 +952,10 @@ struct Mesh // Set model matrix for rendering. bgfx::setTransform(_mtx); bgfx::setIndexBuffer(group.m_ibh); - bgfx::setVertexBuffer(group.m_vbh); + bgfx::setVertexBuffer(0, group.m_vbh); // Set textures. - if (bgfx::invalidHandle != _texture.idx) + if (bgfx::kInvalidHandle != _texture.idx) { bgfx::setTexture(0, s_texColor, _texture); } @@ -1106,17 +1057,17 @@ void screenSpaceQuad(float _textureWidth, float _textureHeight, bool _originBott vertex[2].m_u = maxu; vertex[2].m_v = maxv; - bgfx::setVertexBuffer(&vb); + bgfx::setVertexBuffer(0, &vb); } } void worldSpaceFrustumCorners(float* _corners24f - , float _near - , float _far - , float _projWidth - , float _projHeight - , const float* __restrict _invViewMtx - ) + , float _near + , float _far + , float _projWidth + , float _projHeight + , const float* __restrict _invViewMtx + ) { // Define frustum corners in view space. const float nw = _near * _projWidth; @@ -1239,7 +1190,7 @@ struct Programs { for (uint8_t kk = 0; kk < SmImpl::Count; ++kk) { - bgfx::destroyProgram(m_colorLighting[ii][jj][kk]); + bgfx::destroy(m_colorLighting[ii][jj][kk]); } } } @@ -1249,32 +1200,32 @@ struct Programs { for (uint8_t jj = 0; jj < PackDepth::Count; ++jj) { - bgfx::destroyProgram(m_packDepth[ii][jj]); + bgfx::destroy(m_packDepth[ii][jj]); } } // Draw depth. for (uint8_t ii = 0; ii < PackDepth::Count; ++ii) { - bgfx::destroyProgram(m_drawDepth[ii]); + bgfx::destroy(m_drawDepth[ii]); } // Hblur. for (uint8_t ii = 0; ii < PackDepth::Count; ++ii) { - bgfx::destroyProgram(m_hBlur[ii]); + bgfx::destroy(m_hBlur[ii]); } // Vblur. for (uint8_t ii = 0; ii < PackDepth::Count; ++ii) { - bgfx::destroyProgram(m_vBlur[ii]); + bgfx::destroy(m_vBlur[ii]); } // Misc. - bgfx::destroyProgram(m_colorTexture); - bgfx::destroyProgram(m_texture); - bgfx::destroyProgram(m_black); + bgfx::destroy(m_colorTexture); + bgfx::destroy(m_texture); + bgfx::destroy(m_black); } bgfx::ProgramHandle m_black; @@ -1310,1863 +1261,1993 @@ struct ShadowMapSettings #undef IMGUI_FLOAT_PARAM }; -int _main_(int _argc, char** _argv) +struct SceneSettings { - Args args(_argc, _argv); - - uint32_t debug = BGFX_DEBUG_TEXT; - uint32_t reset = BGFX_RESET_VSYNC; - - ViewState viewState(1280, 720); - ClearValues clearValues(0x00000000, 1.0f, 0); - - bgfx::init(args.m_type, args.m_pciId); - bgfx::reset(viewState.m_width, viewState.m_height, reset); - - // Enable debug text. - bgfx::setDebug(debug); + LightType::Enum m_lightType; + DepthImpl::Enum m_depthImpl; + SmImpl::Enum m_smImpl; + float m_spotOuterAngle; + float m_spotInnerAngle; + float m_fovXAdjust; + float m_fovYAdjust; + float m_coverageSpotL; + float m_splitDistribution; + int m_numSplits; + bool m_updateLights; + bool m_updateScene; + bool m_drawDepthBuffer; + bool m_showSmCoverage; + bool m_stencilPack; + bool m_stabilize; +}; - // Setup root path for binary shaders. Shader binaries are different - // for each renderer. - switch (bgfx::getRendererType() ) +class ExampleShadowmaps : public entry::AppI +{ +public: + ExampleShadowmaps(const char* _name, const char* _description) + : entry::AppI(_name, _description) { - case bgfx::RendererType::Direct3D9: - s_texelHalf = 0.5f; - break; - - case bgfx::RendererType::OpenGL: - case bgfx::RendererType::OpenGLES: - s_flipV = true; - break; - - default: - break; } - // Imgui. - imguiCreate(); - - // Uniforms. - s_uniforms.init(); - s_texColor = bgfx::createUniform("s_texColor", bgfx::UniformType::Int1); - s_shadowMap[0] = bgfx::createUniform("s_shadowMap0", bgfx::UniformType::Int1); - s_shadowMap[1] = bgfx::createUniform("s_shadowMap1", bgfx::UniformType::Int1); - s_shadowMap[2] = bgfx::createUniform("s_shadowMap2", bgfx::UniformType::Int1); - s_shadowMap[3] = bgfx::createUniform("s_shadowMap3", bgfx::UniformType::Int1); - - // Programs. - s_programs.init(); - - // Vertex declarations. - bgfx::VertexDecl PosNormalTexcoordDecl; - PosNormalTexcoordDecl.begin() - .add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float) - .add(bgfx::Attrib::Normal, 4, bgfx::AttribType::Uint8, true, true) - .add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float) - .end(); - - bgfx::VertexDecl posDecl; - posDecl.begin(); - posDecl.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float); - posDecl.end(); - - PosColorTexCoord0Vertex::init(); - - // Textures. - bgfx::TextureHandle texFigure = loadTexture("textures/figure-rgba.dds"); - bgfx::TextureHandle texFlare = loadTexture("textures/flare.dds"); - bgfx::TextureHandle texFieldstone = loadTexture("textures/fieldstone-rgba.dds"); - - // Meshes. - Mesh bunnyMesh; - Mesh treeMesh; - Mesh cubeMesh; - Mesh hollowcubeMesh; - Mesh hplaneMesh; - Mesh vplaneMesh; - bunnyMesh.load("meshes/bunny.bin"); - treeMesh.load("meshes/tree.bin"); - cubeMesh.load("meshes/cube.bin"); - hollowcubeMesh.load("meshes/hollowcube.bin"); - hplaneMesh.load(s_hplaneVertices, BX_COUNTOF(s_hplaneVertices), PosNormalTexcoordDecl, s_planeIndices, BX_COUNTOF(s_planeIndices) ); - vplaneMesh.load(s_vplaneVertices, BX_COUNTOF(s_vplaneVertices), PosNormalTexcoordDecl, s_planeIndices, BX_COUNTOF(s_planeIndices) ); - - // Materials. - Material defaultMaterial = + void init(int32_t _argc, const char* const* _argv, uint32_t _width, uint32_t _height) override { - { { 1.0f, 1.0f, 1.0f, 0.0f } }, //ambient - { { 1.0f, 1.0f, 1.0f, 0.0f } }, //diffuse - { { 1.0f, 1.0f, 1.0f, 0.0f } }, //specular, exponent - }; + Args args(_argc, _argv); - // Lights. - Light pointLight = - { - { { 0.0f, 0.0f, 0.0f, 1.0f } }, //position - { 0.0f, 0.0f, 0.0f, 0.0f }, //-ignore - { { 1.0f, 1.0f, 1.0f, 0.0f } }, //ambient - { { 1.0f, 1.0f, 1.0f, 850.0f } }, //diffuse - { { 1.0f, 1.0f, 1.0f, 0.0f } }, //specular - { { 0.0f,-0.4f,-0.6f, 0.0f } }, //spotdirection, spotexponent - { 0.0f, 0.0f, 0.0f, 0.0f }, //-ignore - { { 1.0f, 0.0f, 1.0f, 91.0f } }, //attenuation, spotcutoff - }; + m_debug = BGFX_DEBUG_NONE; + m_reset = BGFX_RESET_VSYNC; - Light directionalLight = - { - { { 0.5f,-1.0f, 0.1f, 0.0f } }, //position - { 0.0f, 0.0f, 0.0f, 0.0f }, //-ignore - { { 1.0f, 1.0f, 1.0f, 0.02f } }, //ambient - { { 1.0f, 1.0f, 1.0f, 0.4f } }, //diffuse - { { 1.0f, 1.0f, 1.0f, 0.0f } }, //specular - { { 0.0f, 0.0f, 0.0f, 1.0f } }, //spotdirection, spotexponent - { 0.0f, 0.0f, 0.0f, 0.0f }, //-ignore - { { 0.0f, 0.0f, 0.0f, 1.0f } }, //attenuation, spotcutoff - }; + m_width = _width; + m_height = _height; + m_viewState = ViewState(uint16_t(m_width), uint16_t(m_height)); + m_clearValues = ClearValues(0x00000000, 1.0f, 0); - // Setup uniforms. - float color[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; - float lightMtx[16]; - float shadowMapMtx[ShadowMapRenderTargets::Count][16]; - s_uniforms.setPtrs(&defaultMaterial - , &pointLight - , color - , lightMtx - , &shadowMapMtx[ShadowMapRenderTargets::First][0] - , &shadowMapMtx[ShadowMapRenderTargets::Second][0] - , &shadowMapMtx[ShadowMapRenderTargets::Third][0] - , &shadowMapMtx[ShadowMapRenderTargets::Fourth][0] - ); - s_uniforms.submitConstUniforms(); - - // Settings. - ShadowMapSettings smSettings[LightType::Count][DepthImpl::Count][SmImpl::Count] = - { - { //LightType::Spot - - { //DepthImpl::InvZ - - { //SmImpl::Hard - 10.0f, 7.0f, 12.0f, 1.0f // m_sizePwrTwo - , 10.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow - , 1.0f, 1.0f, 10.0f, 1.0f // m_near - , 250.0f, 100.0f, 2000.0f, 50.0f // m_far - , 0.0035f, 0.0f, 0.01f, 0.00001f // m_bias - , 0.0012f, 0.0f, 0.05f, 0.00001f // m_normalOffset - , 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0 - , 500.0f, 1.0f, 1000.0f, 1.0f // m_customParam1 - , 2.0f, 0.0f, 4.0f, 1.0f // m_xNum - , 2.0f, 0.0f, 4.0f, 1.0f // m_yNum - , 1.0f, 0.0f, 3.0f, 0.01f // m_xOffset - , 1.0f, 0.0f, 3.0f, 0.01f // m_yOffset - , true // m_doBlur - , &s_programs.m_packDepth[DepthImpl::InvZ][PackDepth::RGBA] //m_progPack - , &s_programs.m_colorLighting[SmType::Single][DepthImpl::InvZ][SmImpl::Hard] //m_progDraw - }, - { //SmImpl::PCF - 10.0f, 7.0f, 12.0f, 1.0f // m_sizePwrTwo - , 10.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow - , 1.0f, 1.0f, 99.0f, 1.0f // m_near - , 250.0f, 100.0f, 2000.0f, 50.0f // m_far - , 0.007f, 0.0f, 0.01f, 0.00001f // m_bias - , 0.001f, 0.0f, 0.05f, 0.00001f // m_normalOffset - , 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0 - , 500.0f, 1.0f, 1000.0f, 1.0f // m_customParam1 - , 2.0f, 0.0f, 8.0f, 1.0f // m_xNum - , 2.0f, 0.0f, 8.0f, 1.0f // m_yNum - , 1.0f, 0.0f, 3.0f, 0.01f // m_xOffset - , 1.0f, 0.0f, 3.0f, 0.01f // m_yOffset - , true // m_doBlur - , &s_programs.m_packDepth[DepthImpl::InvZ][PackDepth::RGBA] //m_progPack - , &s_programs.m_colorLighting[SmType::Single][DepthImpl::InvZ][SmImpl::PCF] //m_progDraw - }, - { //SmImpl::VSM - 10.0f, 7.0f, 12.0f, 1.0f // m_sizePwrTwo - , 10.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow - , 8.0f, 1.0f, 10.0f, 1.0f // m_near - , 250.0f, 100.0f, 2000.0f, 50.0f // m_far - , 0.045f, 0.0f, 0.1f, 0.00001f // m_bias - , 0.001f, 0.0f, 0.05f, 0.00001f // m_normalOffset - , 0.02f, 0.0f, 0.04f, 0.00001f // m_customParam0 - , 450.0f, 1.0f, 1000.0f, 1.0f // m_customParam1 - , 2.0f, 0.0f, 4.0f, 1.0f // m_xNum - , 2.0f, 0.0f, 4.0f, 1.0f // m_yNum - , 1.0f, 0.0f, 3.0f, 0.01f // m_xOffset - , 1.0f, 0.0f, 3.0f, 0.01f // m_yOffset - , true // m_doBlur - , &s_programs.m_packDepth[DepthImpl::InvZ][PackDepth::VSM] //m_progPack - , &s_programs.m_colorLighting[SmType::Single][DepthImpl::InvZ][SmImpl::VSM] //m_progDraw - }, - { //SmImpl::ESM - 10.0f, 7.0f, 12.0f, 1.0f // m_sizePwrTwo - , 10.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow - , 3.0f, 1.0f, 10.0f, 0.01f // m_near - , 250.0f, 100.0f, 2000.0f, 50.0f // m_far - , 0.02f, 0.0f, 0.3f, 0.00001f // m_bias - , 0.001f, 0.0f, 0.05f, 0.00001f // m_normalOffset - , 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0 - , 9000.0f, 1.0f, 15000.0f, 1.0f // m_customParam1 - , 2.0f, 0.0f, 4.0f, 1.0f // m_xNum - , 2.0f, 0.0f, 4.0f, 1.0f // m_yNum - , 1.0f, 0.0f, 3.0f, 0.01f // m_xOffset - , 1.0f, 0.0f, 3.0f, 0.01f // m_yOffset - , true // m_doBlur - , &s_programs.m_packDepth[DepthImpl::InvZ][PackDepth::RGBA] //m_progPack - , &s_programs.m_colorLighting[SmType::Single][DepthImpl::InvZ][SmImpl::ESM] //m_progDraw - } + bgfx::init(args.m_type, args.m_pciId); + bgfx::reset(m_viewState.m_width, m_viewState.m_height, m_reset); - }, - { //DepthImpl::Linear - - { //SmImpl::Hard - 10.0f, 7.0f, 12.0f, 1.0f // m_sizePwrTwo - , 1.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow - , 1.0f, 1.0f, 10.0f, 1.0f // m_near - , 250.0f, 100.0f, 2000.0f, 50.0f // m_far - , 0.0025f, 0.0f, 0.01f, 0.00001f // m_bias - , 0.0012f, 0.0f, 0.05f, 0.00001f // m_normalOffset - , 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0 - , 500.0f, 1.0f, 1000.0f, 1.0f // m_customParam1 - , 2.0f, 0.0f, 4.0f, 1.0f // m_xNum - , 2.0f, 0.0f, 4.0f, 1.0f // m_yNum - , 1.0f, 0.0f, 3.0f, 0.01f // m_xOffset - , 1.0f, 0.0f, 3.0f, 0.01f // m_yOffset - , true // m_doBlur - , &s_programs.m_packDepth[DepthImpl::Linear][PackDepth::RGBA] //m_progPack - , &s_programs.m_colorLighting[SmType::Single][DepthImpl::Linear][SmImpl::Hard] //m_progDraw - }, - { //SmImpl::PCF - 10.0f, 7.0f, 12.0f, 1.0f // m_sizePwrTwo - , 1.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow - , 1.0f, 1.0f, 99.0f, 1.0f // m_near - , 250.0f, 100.0f, 2000.0f, 50.0f // m_far - , 0.0025f, 0.0f, 0.01f, 0.00001f // m_bias - , 0.001f, 0.0f, 0.05f, 0.00001f // m_normalOffset - , 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0 - , 2000.0f, 1.0f, 2000.0f, 1.0f // m_customParam1 - , 2.0f, 0.0f, 8.0f, 1.0f // m_xNum - , 2.0f, 0.0f, 8.0f, 1.0f // m_yNum - , 1.0f, 0.0f, 3.0f, 0.01f // m_xOffset - , 1.0f, 0.0f, 3.0f, 0.01f // m_yOffset - , true // m_doBlur - , &s_programs.m_packDepth[DepthImpl::Linear][PackDepth::RGBA] //m_progPack - , &s_programs.m_colorLighting[SmType::Single][DepthImpl::Linear][SmImpl::PCF] //m_progDraw - }, - { //SmImpl::VSM - 10.0f, 7.0f, 12.0f, 1.0f // m_sizePwrTwo - , 1.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow - , 1.0f, 1.0f, 10.0f, 1.0f // m_near - , 250.0f, 100.0f, 2000.0f, 50.0f // m_far - , 0.006f, 0.0f, 0.01f, 0.00001f // m_bias - , 0.001f, 0.0f, 0.05f, 0.00001f // m_normalOffset - , 0.02f, 0.0f, 0.1f, 0.00001f // m_customParam0 - , 300.0f, 1.0f, 1500.0f, 1.0f // m_customParam1 - , 2.0f, 0.0f, 4.0f, 1.0f // m_xNum - , 2.0f, 0.0f, 4.0f, 1.0f // m_yNum - , 1.0f, 0.0f, 3.0f, 0.01f // m_xOffset - , 1.0f, 0.0f, 3.0f, 0.01f // m_yOffset - , true // m_doBlur - , &s_programs.m_packDepth[DepthImpl::Linear][PackDepth::VSM] //m_progPack - , &s_programs.m_colorLighting[SmType::Single][DepthImpl::Linear][SmImpl::VSM] //m_progDraw - }, - { //SmImpl::ESM - 10.0f, 7.0f, 12.0f, 1.0f // m_sizePwrTwo - , 1.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow - , 1.0f, 1.0f, 10.0f, 0.01f // m_near - , 250.0f, 100.0f, 2000.0f, 50.0f // m_far - , 0.0055f, 0.0f, 0.01f, 0.00001f // m_bias - , 0.001f, 0.0f, 0.05f, 0.00001f // m_normalOffset - , 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0 - , 2500.0f, 1.0f, 5000.0f, 1.0f // m_customParam1 - , 2.0f, 0.0f, 4.0f, 1.0f // m_xNum - , 2.0f, 0.0f, 4.0f, 1.0f // m_yNum - , 1.0f, 0.0f, 3.0f, 0.01f // m_xOffset - , 1.0f, 0.0f, 3.0f, 0.01f // m_yOffset - , true // m_doBlur - , &s_programs.m_packDepth[DepthImpl::Linear][PackDepth::RGBA] //m_progPack - , &s_programs.m_colorLighting[SmType::Single][DepthImpl::Linear][SmImpl::ESM] //m_progDraw - } + // Enable debug text. + bgfx::setDebug(m_debug); - } + // Setup root path for binary shaders. Shader binaries are different + // for each renderer. + switch (bgfx::getRendererType() ) + { + case bgfx::RendererType::Direct3D9: + s_texelHalf = 0.5f; + break; - }, - { //LightType::Point - - { //DepthImpl::InvZ - - { //SmImpl::Hard - 12.0f, 9.0f, 12.0f, 1.0f // m_sizePwrTwo - , 10.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow - , 1.0f, 1.0f, 10.0f, 1.0f // m_near - , 250.0f, 100.0f, 2000.0f, 50.0f // m_far - , 0.006f, 0.0f, 0.01f, 0.00001f // m_bias - , 0.001f, 0.0f, 0.05f, 0.00001f // m_normalOffset - , 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0 - , 50.0f, 1.0f, 300.0f, 1.0f // m_customParam1 - , 2.0f, 0.0f, 4.0f, 1.0f // m_xNum - , 2.0f, 0.0f, 4.0f, 1.0f // m_yNum - , 0.25f, 0.0f, 2.0f, 0.001f // m_xOffset - , 0.25f, 0.0f, 2.0f, 0.001f // m_yOffset - , true // m_doBlur - , &s_programs.m_packDepth[DepthImpl::InvZ][PackDepth::RGBA] //m_progPack - , &s_programs.m_colorLighting[SmType::Omni][DepthImpl::InvZ][SmImpl::Hard] //m_progDraw - }, - { //SmImpl::PCF - 12.0f, 9.0f, 12.0f, 1.0f // m_sizePwrTwo - , 10.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow - , 1.0f, 1.0f, 99.0f, 1.0f // m_near - , 250.0f, 100.0f, 2000.0f, 50.0f // m_far - , 0.004f, 0.0f, 0.01f, 0.00001f // m_bias - , 0.001f, 0.0f, 0.05f, 0.00001f // m_normalOffset - , 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0 - , 50.0f, 1.0f, 300.0f, 1.0f // m_customParam1 - , 2.0f, 0.0f, 8.0f, 1.0f // m_xNum - , 2.0f, 0.0f, 8.0f, 1.0f // m_yNum - , 1.0f, 0.0f, 3.0f, 0.001f // m_xOffset - , 1.0f, 0.0f, 3.0f, 0.001f // m_yOffset - , true // m_doBlur - , &s_programs.m_packDepth[DepthImpl::InvZ][PackDepth::RGBA] //m_progPack - , &s_programs.m_colorLighting[SmType::Omni][DepthImpl::InvZ][SmImpl::PCF] //m_progDraw - }, - { //SmImpl::VSM - 12.0f, 9.0f, 12.0f, 1.0f // m_sizePwrTwo - , 10.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow - , 8.0f, 1.0f, 10.0f, 1.0f // m_near - , 250.0f, 100.0f, 2000.0f, 50.0f // m_far - , 0.055f, 0.0f, 0.1f, 0.00001f // m_bias - , 0.001f, 0.0f, 0.05f, 0.00001f // m_normalOffset - , 0.02f, 0.0f, 0.04f, 0.00001f // m_customParam0 - , 450.0f, 1.0f, 900.0f, 1.0f // m_customParam1 - , 2.0f, 0.0f, 4.0f, 1.0f // m_xNum - , 2.0f, 0.0f, 4.0f, 1.0f // m_yNum - , 0.25f, 0.0f, 2.0f, 0.001f // m_xOffset - , 0.25f, 0.0f, 2.0f, 0.001f // m_yOffset - , true // m_doBlur - , &s_programs.m_packDepth[DepthImpl::InvZ][PackDepth::VSM] //m_progPack - , &s_programs.m_colorLighting[SmType::Omni][DepthImpl::InvZ][SmImpl::VSM] //m_progDraw - }, - { //SmImpl::ESM - 12.0f, 9.0f, 12.0f, 1.0f // m_sizePwrTwo - , 10.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow - , 3.0f, 1.0f, 10.0f, 0.01f // m_near - , 250.0f, 100.0f, 2000.0f, 50.0f // m_far - , 0.035f, 0.0f, 0.1f, 0.00001f // m_bias - , 0.001f, 0.0f, 0.05f, 0.00001f // m_normalOffset - , 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0 - , 9000.0f, 1.0f, 15000.0f, 1.0f // m_customParam1 - , 2.0f, 0.0f, 4.0f, 1.0f // m_xNum - , 2.0f, 0.0f, 4.0f, 1.0f // m_yNum - , 0.25f, 0.0f, 2.0f, 0.001f // m_xOffset - , 0.25f, 0.0f, 2.0f, 0.001f // m_yOffset - , true // m_doBlur - , &s_programs.m_packDepth[DepthImpl::InvZ][PackDepth::RGBA] //m_progPack - , &s_programs.m_colorLighting[SmType::Omni][DepthImpl::InvZ][SmImpl::ESM] //m_progDraw - } + case bgfx::RendererType::OpenGL: + case bgfx::RendererType::OpenGLES: + s_flipV = true; + break; - }, - { //DepthImpl::Linear - - { //SmImpl::Hard - 12.0f, 9.0f, 12.0f, 1.0f // m_sizePwrTwo - , 1.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow - , 1.0f, 1.0f, 10.0f, 1.0f // m_near - , 250.0f, 100.0f, 2000.0f, 50.0f // m_far - , 0.003f, 0.0f, 0.01f, 0.00001f // m_bias - , 0.001f, 0.0f, 0.05f, 0.00001f // m_normalOffset - , 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0 - , 120.0f, 1.0f, 300.0f, 1.0f // m_customParam1 - , 2.0f, 0.0f, 4.0f, 1.0f // m_xNum - , 2.0f, 0.0f, 4.0f, 1.0f // m_yNum - , 0.25f, 0.0f, 2.0f, 0.001f // m_xOffset - , 0.25f, 0.0f, 2.0f, 0.001f // m_yOffset - , true // m_doBlur - , &s_programs.m_packDepth[DepthImpl::Linear][PackDepth::RGBA] //m_progPack - , &s_programs.m_colorLighting[SmType::Omni][DepthImpl::Linear][SmImpl::Hard] //m_progDraw - }, - { //SmImpl::PCF - 12.0f, 9.0f, 12.0f, 1.0f // m_sizePwrTwo - , 1.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow - , 1.0f, 1.0f, 99.0f, 1.0f // m_near - , 250.0f, 100.0f, 2000.0f, 50.0f // m_far - , 0.0035f, 0.0f, 0.01f, 0.00001f // m_bias - , 0.001f, 0.0f, 0.05f, 0.00001f // m_normalOffset - , 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0 - , 120.0f, 1.0f, 300.0f, 1.0f // m_customParam1 - , 2.0f, 0.0f, 8.0f, 1.0f // m_xNum - , 2.0f, 0.0f, 8.0f, 1.0f // m_yNum - , 1.0f, 0.0f, 3.0f, 0.001f // m_xOffset - , 1.0f, 0.0f, 3.0f, 0.001f // m_yOffset - , true // m_doBlur - , &s_programs.m_packDepth[DepthImpl::Linear][PackDepth::RGBA] //m_progPack - , &s_programs.m_colorLighting[SmType::Omni][DepthImpl::Linear][SmImpl::PCF] //m_progDraw - }, - { //SmImpl::VSM - 12.0f, 9.0f, 12.0f, 1.0f // m_sizePwrTwo - , 1.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow - , 1.0f, 1.0f, 10.0f, 1.0f // m_near - , 250.0f, 100.0f, 2000.0f, 50.0f // m_far - , 0.006f, 0.0f, 0.1f, 0.00001f // m_bias - , 0.001f, 0.0f, 0.05f, 0.00001f // m_normalOffset - , 0.02f, 0.0f, 0.1f, 0.00001f // m_customParam0 - , 400.0f, 1.0f, 900.0f, 1.0f // m_customParam1 - , 2.0f, 0.0f, 4.0f, 1.0f // m_xNum - , 2.0f, 0.0f, 4.0f, 1.0f // m_yNum - , 0.25f, 0.0f, 2.0f, 0.001f // m_xOffset - , 0.25f, 0.0f, 2.0f, 0.001f // m_yOffset - , true // m_doBlur - , &s_programs.m_packDepth[DepthImpl::Linear][PackDepth::VSM] //m_progPack - , &s_programs.m_colorLighting[SmType::Omni][DepthImpl::Linear][SmImpl::VSM] //m_progDraw - }, - { //SmImpl::ESM - 12.0f, 9.0f, 12.0f, 1.0f // m_sizePwrTwo - , 1.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow - , 1.0f, 1.0f, 10.0f, 0.01f // m_near - , 250.0f, 100.0f, 2000.0f, 50.0f // m_far - , 0.007f, 0.0f, 0.01f, 0.00001f // m_bias - , 0.001f, 0.0f, 0.05f, 0.00001f // m_normalOffset - , 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0 - , 8000.0f, 1.0f, 15000.0f, 1.0f // m_customParam1 - , 2.0f, 0.0f, 4.0f, 1.0f // m_xNum - , 2.0f, 0.0f, 4.0f, 1.0f // m_yNum - , 0.25f, 0.0f, 2.0f, 0.001f // m_xOffset - , 0.25f, 0.0f, 2.0f, 0.001f // m_yOffset - , true // m_doBlur - , &s_programs.m_packDepth[DepthImpl::Linear][PackDepth::RGBA] //m_progPack - , &s_programs.m_colorLighting[SmType::Omni][DepthImpl::Linear][SmImpl::ESM] //m_progDraw + default: + break; } - } + // Imgui. + imguiCreate(); + + // Uniforms. + s_uniforms.init(); + s_texColor = bgfx::createUniform("s_texColor", bgfx::UniformType::Int1); + s_shadowMap[0] = bgfx::createUniform("s_shadowMap0", bgfx::UniformType::Int1); + s_shadowMap[1] = bgfx::createUniform("s_shadowMap1", bgfx::UniformType::Int1); + s_shadowMap[2] = bgfx::createUniform("s_shadowMap2", bgfx::UniformType::Int1); + s_shadowMap[3] = bgfx::createUniform("s_shadowMap3", bgfx::UniformType::Int1); + + // Programs. + s_programs.init(); + + // Vertex declarations. + bgfx::VertexDecl PosNormalTexcoordDecl; + PosNormalTexcoordDecl.begin() + .add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float) + .add(bgfx::Attrib::Normal, 4, bgfx::AttribType::Uint8, true, true) + .add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float) + .end(); - }, - { //LightType::Directional - - { //DepthImpl::InvZ - - { //SmImpl::Hard - 11.0f, 7.0f, 12.0f, 1.0f // m_sizePwrTwo - , 1.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow - , 1.0f, 1.0f, 10.0f, 1.0f // m_near - , 550.0f, 100.0f, 2000.0f, 50.0f // m_far - , 0.0012f, 0.0f, 0.01f, 0.00001f // m_bias - , 0.001f, 0.0f, 0.04f, 0.00001f // m_normalOffset - , 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0 - , 200.0f, 1.0f, 400.0f, 1.0f // m_customParam1 - , 2.0f, 0.0f, 4.0f, 1.0f // m_xNum - , 2.0f, 0.0f, 4.0f, 1.0f // m_yNum - , 0.2f, 0.0f, 1.0f, 0.01f // m_xOffset - , 0.2f, 0.0f, 1.0f, 0.01f // m_yOffset - , true // m_doBlur - , &s_programs.m_packDepth[DepthImpl::InvZ][PackDepth::RGBA] //m_progPack - , &s_programs.m_colorLighting[SmType::Cascade][DepthImpl::InvZ][SmImpl::Hard] //m_progDraw - }, - { //SmImpl::PCF - 11.0f, 7.0f, 12.0f, 1.0f // m_sizePwrTwo - , 1.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow - , 1.0f, 1.0f, 99.0f, 1.0f // m_near - , 550.0f, 100.0f, 2000.0f, 50.0f // m_far - , 0.0012f, 0.0f, 0.01f, 0.00001f // m_bias - , 0.001f, 0.0f, 0.04f, 0.00001f // m_normalOffset - , 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0 - , 200.0f, 1.0f, 400.0f, 1.0f // m_customParam1 - , 2.0f, 0.0f, 8.0f, 1.0f // m_xNum - , 2.0f, 0.0f, 8.0f, 1.0f // m_yNum - , 1.0f, 0.0f, 3.0f, 0.01f // m_xOffset - , 1.0f, 0.0f, 3.0f, 0.01f // m_yOffset - , true // m_doBlur - , &s_programs.m_packDepth[DepthImpl::InvZ][PackDepth::RGBA] //m_progPack - , &s_programs.m_colorLighting[SmType::Cascade][DepthImpl::InvZ][SmImpl::PCF] //m_progDraw - }, - { //SmImpl::VSM - 11.0f, 7.0f, 12.0f, 1.0f // m_sizePwrTwo - , 1.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow - , 1.0f, 1.0f, 10.0f, 1.0f // m_near - , 550.0f, 100.0f, 2000.0f, 50.0f // m_far - , 0.004f, 0.0f, 0.01f, 0.00001f // m_bias - , 0.001f, 0.0f, 0.04f, 0.00001f // m_normalOffset - , 0.02f, 0.0f, 0.04f, 0.00001f // m_customParam0 - , 2500.0f, 1.0f, 5000.0f, 1.0f // m_customParam1 - , 2.0f, 0.0f, 4.0f, 1.0f // m_xNum - , 2.0f, 0.0f, 4.0f, 1.0f // m_yNum - , 0.2f, 0.0f, 1.0f, 0.01f // m_xOffset - , 0.2f, 0.0f, 1.0f, 0.01f // m_yOffset - , true // m_doBlur - , &s_programs.m_packDepth[DepthImpl::InvZ][PackDepth::VSM] //m_progPack - , &s_programs.m_colorLighting[SmType::Cascade][DepthImpl::InvZ][SmImpl::VSM] //m_progDraw - }, - { //SmImpl::ESM - 11.0f, 7.0f, 12.0f, 1.0f // m_sizePwrTwo - , 1.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow - , 1.0f, 1.0f, 10.0f, 0.01f // m_near - , 550.0f, 100.0f, 2000.0f, 50.0f // m_far - , 0.004f, 0.0f, 0.01f, 0.00001f // m_bias - , 0.001f, 0.0f, 0.04f, 0.00001f // m_normalOffset - , 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0 - , 9500.0f, 1.0f, 15000.0f, 1.0f // m_customParam1 - , 2.0f, 0.0f, 4.0f, 1.0f // m_xNum - , 2.0f, 0.0f, 4.0f, 1.0f // m_yNum - , 0.2f, 0.0f, 1.0f, 0.01f // m_xOffset - , 0.2f, 0.0f, 1.0f, 0.01f // m_yOffset - , true // m_doBlur - , &s_programs.m_packDepth[DepthImpl::InvZ][PackDepth::RGBA] //m_progPack - , &s_programs.m_colorLighting[SmType::Cascade][DepthImpl::InvZ][SmImpl::ESM] //m_progDraw - } + m_posDecl.begin(); + m_posDecl.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float); + m_posDecl.end(); - }, - { //DepthImpl::Linear - - { //SmImpl::Hard - 11.0f, 7.0f, 12.0f, 1.0f // m_sizePwrTwo - , 1.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow - , 1.0f, 1.0f, 10.0f, 1.0f // m_near - , 550.0f, 100.0f, 2000.0f, 50.0f // m_far - , 0.0012f, 0.0f, 0.01f, 0.00001f // m_bias - , 0.001f, 0.0f, 0.04f, 0.00001f // m_normalOffset - , 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0 - , 500.0f, 1.0f, 1000.0f, 1.0f // m_customParam1 - , 2.0f, 0.0f, 4.0f, 1.0f // m_xNum - , 2.0f, 0.0f, 4.0f, 1.0f // m_yNum - , 0.2f, 0.0f, 1.0f, 0.01f // m_xOffset - , 0.2f, 0.0f, 1.0f, 0.01f // m_yOffset - , true // m_doBlur - , &s_programs.m_packDepth[DepthImpl::Linear][PackDepth::RGBA] //m_progPack - , &s_programs.m_colorLighting[SmType::Cascade][DepthImpl::Linear][SmImpl::Hard] //m_progDraw - }, - { //SmImpl::PCF - 11.0f, 7.0f, 12.0f, 1.0f // m_sizePwrTwo - , 1.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow - , 1.0f, 1.0f, 99.0f, 1.0f // m_near - , 550.0f, 100.0f, 2000.0f, 50.0f // m_far - , 0.0012f, 0.0f, 0.01f, 0.00001f // m_bias - , 0.001f, 0.0f, 0.04f, 0.00001f // m_normalOffset - , 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0 - , 200.0f, 1.0f, 400.0f, 1.0f // m_customParam1 - , 2.0f, 0.0f, 8.0f, 1.0f // m_xNum - , 2.0f, 0.0f, 8.0f, 1.0f // m_yNum - , 1.0f, 0.0f, 3.0f, 0.01f // m_xOffset - , 1.0f, 0.0f, 3.0f, 0.01f // m_yOffset - , true // m_doBlur - , &s_programs.m_packDepth[DepthImpl::Linear][PackDepth::RGBA] //m_progPack - , &s_programs.m_colorLighting[SmType::Cascade][DepthImpl::Linear][SmImpl::PCF] //m_progDraw - }, - { //SmImpl::VSM - 11.0f, 7.0f, 12.0f, 1.0f // m_sizePwrTwo - , 1.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow - , 1.0f, 1.0f, 10.0f, 1.0f // m_near - , 550.0f, 100.0f, 2000.0f, 50.0f // m_far - , 0.004f, 0.0f, 0.01f, 0.00001f // m_bias - , 0.001f, 0.0f, 0.04f, 0.00001f // m_normalOffset - , 0.02f, 0.0f, 0.04f, 0.00001f // m_customParam0 - , 2500.0f, 1.0f, 5000.0f, 1.0f // m_customParam1 - , 2.0f, 0.0f, 4.0f, 1.0f // m_xNum - , 2.0f, 0.0f, 4.0f, 1.0f // m_yNum - , 0.2f, 0.0f, 1.0f, 0.01f // m_xOffset - , 0.2f, 0.0f, 1.0f, 0.01f // m_yOffset - , true // m_doBlur - , &s_programs.m_packDepth[DepthImpl::Linear][PackDepth::VSM] //m_progPack - , &s_programs.m_colorLighting[SmType::Cascade][DepthImpl::Linear][SmImpl::VSM] //m_progDraw - }, - { //SmImpl::ESM - 11.0f, 7.0f, 12.0f, 1.0f // m_sizePwrTwo - , 1.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow - , 1.0f, 1.0f, 10.0f, 0.01f // m_near - , 550.0f, 100.0f, 2000.0f, 50.0f // m_far - , 0.004f, 0.0f, 0.01f, 0.00001f // m_bias - , 0.001f, 0.0f, 0.04f, 0.00001f // m_normalOffset - , 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0 - , 9500.0f, 1.0f, 15000.0f, 1.0f // m_customParam1 - , 2.0f, 0.0f, 4.0f, 1.0f // m_xNum - , 2.0f, 0.0f, 4.0f, 1.0f // m_yNum - , 0.2f, 0.0f, 1.0f, 0.01f // m_xOffset - , 0.2f, 0.0f, 1.0f, 0.01f // m_yOffset - , true // m_doBlur - , &s_programs.m_packDepth[DepthImpl::Linear][PackDepth::RGBA] //m_progPack - , &s_programs.m_colorLighting[SmType::Cascade][DepthImpl::Linear][SmImpl::ESM] //m_progDraw - } + PosColorTexCoord0Vertex::init(); - } - } - }; + // Textures. + m_texFigure = loadTexture("textures/figure-rgba.dds"); + m_texFlare = loadTexture("textures/flare.dds"); + m_texFieldstone = loadTexture("textures/fieldstone-rgba.dds"); - struct SceneSettings - { - LightType::Enum m_lightType; - DepthImpl::Enum m_depthImpl; - SmImpl::Enum m_smImpl; - float m_spotOuterAngle; - float m_spotInnerAngle; - float m_fovXAdjust; - float m_fovYAdjust; - float m_coverageSpotL; - float m_numSplitsf; - float m_splitDistribution; - uint8_t m_numSplits; - bool m_updateLights; - bool m_updateScene; - bool m_drawDepthBuffer; - bool m_showSmCoverage; - bool m_stencilPack; - bool m_stabilize; - }; + // Meshes. + m_bunnyMesh.load("meshes/bunny.bin"); + m_treeMesh.load("meshes/tree.bin"); + m_cubeMesh.load("meshes/cube.bin"); + m_hollowcubeMesh.load("meshes/hollowcube.bin"); + m_hplaneMesh.load(s_hplaneVertices, BX_COUNTOF(s_hplaneVertices), PosNormalTexcoordDecl, s_planeIndices, BX_COUNTOF(s_planeIndices) ); + m_vplaneMesh.load(s_vplaneVertices, BX_COUNTOF(s_vplaneVertices), PosNormalTexcoordDecl, s_planeIndices, BX_COUNTOF(s_planeIndices) ); - SceneSettings settings; - settings.m_lightType = LightType::SpotLight; - settings.m_depthImpl = DepthImpl::InvZ; - settings.m_smImpl = SmImpl::Hard; - settings.m_spotOuterAngle = 45.0f; - settings.m_spotInnerAngle = 30.0f; - settings.m_fovXAdjust = 0.0f; - settings.m_fovYAdjust = 0.0f; - settings.m_coverageSpotL = 90.0f; - settings.m_numSplitsf = 4.0f; - settings.m_splitDistribution = 0.6f; - settings.m_numSplits = uint8_t(settings.m_numSplitsf); - settings.m_updateLights = true; - settings.m_updateScene = true; - settings.m_drawDepthBuffer = false; - settings.m_showSmCoverage = false; - settings.m_stencilPack = true; - settings.m_stabilize = true; - - ShadowMapSettings* currentSmSettings = &smSettings[settings.m_lightType][settings.m_depthImpl][settings.m_smImpl]; - - // Render targets. - uint16_t shadowMapSize = 1 << uint32_t(currentSmSettings->m_sizePwrTwo); - uint16_t currentShadowMapSize = shadowMapSize; - float currentShadowMapSizef = float(int16_t(currentShadowMapSize) ); - s_uniforms.m_shadowMapTexelSize = 1.0f / currentShadowMapSizef; - for (uint8_t ii = 0; ii < ShadowMapRenderTargets::Count; ++ii) - { - bgfx::TextureHandle fbtextures[] = + // Materials. + m_defaultMaterial = { - bgfx::createTexture2D(currentShadowMapSize, currentShadowMapSize, false, 1, bgfx::TextureFormat::BGRA8, BGFX_TEXTURE_RT), - bgfx::createTexture2D(currentShadowMapSize, currentShadowMapSize, false, 1, bgfx::TextureFormat::D24S8, BGFX_TEXTURE_RT), + { { 1.0f, 1.0f, 1.0f, 0.0f } }, //ambient + { { 1.0f, 1.0f, 1.0f, 0.0f } }, //diffuse + { { 1.0f, 1.0f, 1.0f, 0.0f } }, //specular, exponent }; - s_rtShadowMap[ii] = bgfx::createFrameBuffer(BX_COUNTOF(fbtextures), fbtextures, true); - } - s_rtBlur = bgfx::createFrameBuffer(currentShadowMapSize, currentShadowMapSize, bgfx::TextureFormat::BGRA8); - - // Setup camera. - float initialPos[3] = { 0.0f, 60.0f, -105.0f }; - cameraCreate(); - cameraSetPosition(initialPos); - cameraSetVerticalAngle(-0.45f); - - // Set view and projection matrices. - const float camFovy = 60.0f; - const float camAspect = float(int32_t(viewState.m_width) ) / float(int32_t(viewState.m_height) ); - const float camNear = 0.1f; - const float camFar = 2000.0f; - const float projHeight = 1.0f/bx::ftan(bx::toRad(camFovy)*0.5f); - const float projWidth = projHeight * camAspect; - bx::mtxProj(viewState.m_proj, camFovy, camAspect, camNear, camFar, bgfx::getCaps()->homogeneousDepth); - cameraGetViewMtx(viewState.m_view); - - float timeAccumulatorLight = 0.0f; - float timeAccumulatorScene = 0.0f; - - entry::MouseState mouseState; - uint32_t width; - uint32_t height; - while (!entry::processEvents(width, height, debug, reset, &mouseState) ) - { - viewState.m_width = uint16_t(width); - viewState.m_height = uint16_t(height); - // Imgui. - imguiBeginFrame(mouseState.m_mx - , mouseState.m_my - , (mouseState.m_buttons[entry::MouseButton::Left ] ? IMGUI_MBUT_LEFT : 0) - | (mouseState.m_buttons[entry::MouseButton::Right ] ? IMGUI_MBUT_RIGHT : 0) - | (mouseState.m_buttons[entry::MouseButton::Middle] ? IMGUI_MBUT_MIDDLE : 0) - , mouseState.m_mz - , viewState.m_width - , viewState.m_height - ); - - static int32_t rightScrollArea = 0; - imguiBeginScrollArea("Settings", viewState.m_width - 256 - 10, 10, 256, 660, &rightScrollArea); - -#define IMGUI_FLOAT_SLIDER(_name, _val) \ - imguiSlider(_name \ - , _val \ - , *( ((float*)&_val)+1) \ - , *( ((float*)&_val)+2) \ - , *( ((float*)&_val)+3) \ - ) - - imguiBool("Update lights", settings.m_updateLights); - imguiBool("Update scene", settings.m_updateScene); - - imguiSeparatorLine(); - imguiLabel("Shadow map depth:"); - imguiEnum(settings.m_depthImpl); - currentSmSettings = &smSettings[settings.m_lightType][settings.m_depthImpl][settings.m_smImpl]; - - imguiSeparator(); - imguiBool("Draw depth buffer.", settings.m_drawDepthBuffer); - if (settings.m_drawDepthBuffer) + // Lights. + m_pointLight = { - IMGUI_FLOAT_SLIDER("Depth value pow:", currentSmSettings->m_depthValuePow); - } - - imguiSeparatorLine(); - imguiLabel("Shadow Map implementation:"); - imguiEnum(settings.m_smImpl); - currentSmSettings = &smSettings[settings.m_lightType][settings.m_depthImpl][settings.m_smImpl]; + { { 0.0f, 0.0f, 0.0f, 1.0f } }, //position + { 0.0f, 0.0f, 0.0f, 0.0f }, //-ignore + { { 1.0f, 1.0f, 1.0f, 0.0f } }, //ambient + { { 1.0f, 1.0f, 1.0f, 850.0f } }, //diffuse + { { 1.0f, 1.0f, 1.0f, 0.0f } }, //specular + { { 0.0f,-0.4f,-0.6f, 0.0f } }, //spotdirection, spotexponent + { 0.0f, 0.0f, 0.0f, 0.0f }, //-ignore + { { 1.0f, 0.0f, 1.0f, 91.0f } }, //attenuation, spotcutoff + }; - imguiSeparator(); - IMGUI_FLOAT_SLIDER("Bias:", currentSmSettings->m_bias); - IMGUI_FLOAT_SLIDER("Normal offset:", currentSmSettings->m_normalOffset); - imguiSeparator(); - if (LightType::DirectionalLight != settings.m_lightType) + m_directionalLight = { - IMGUI_FLOAT_SLIDER("Near plane:", currentSmSettings->m_near); - } - IMGUI_FLOAT_SLIDER("Far plane:", currentSmSettings->m_far); + { { 0.5f,-1.0f, 0.1f, 0.0f } }, //position + { 0.0f, 0.0f, 0.0f, 0.0f }, //-ignore + { { 1.0f, 1.0f, 1.0f, 0.02f } }, //ambient + { { 1.0f, 1.0f, 1.0f, 0.4f } }, //diffuse + { { 1.0f, 1.0f, 1.0f, 0.0f } }, //specular + { { 0.0f, 0.0f, 0.0f, 1.0f } }, //spotdirection, spotexponent + { 0.0f, 0.0f, 0.0f, 0.0f }, //-ignore + { { 0.0f, 0.0f, 0.0f, 1.0f } }, //attenuation, spotcutoff + }; - imguiSeparator(); - switch(settings.m_smImpl) + // Setup uniforms. + m_color[0] = m_color[1] = m_color[2] = m_color[3] = 1.0f; + s_uniforms.setPtrs(&m_defaultMaterial + , &m_pointLight + , m_color + , m_lightMtx + , &m_shadowMapMtx[ShadowMapRenderTargets::First][0] + , &m_shadowMapMtx[ShadowMapRenderTargets::Second][0] + , &m_shadowMapMtx[ShadowMapRenderTargets::Third][0] + , &m_shadowMapMtx[ShadowMapRenderTargets::Fourth][0] + ); + s_uniforms.submitConstUniforms(); + + // Settings. + ShadowMapSettings smSettings[LightType::Count][DepthImpl::Count][SmImpl::Count] = { - case SmImpl::Hard: - //imguiLabel("Hard"); - break; + { //LightType::Spot + + { //DepthImpl::InvZ + + { //SmImpl::Hard + 10.0f, 7.0f, 12.0f, 1.0f // m_sizePwrTwo + , 10.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow + , 1.0f, 1.0f, 10.0f, 1.0f // m_near + , 250.0f, 100.0f, 2000.0f, 50.0f // m_far + , 0.0035f, 0.0f, 0.01f, 0.00001f // m_bias + , 0.0012f, 0.0f, 0.05f, 0.00001f // m_normalOffset + , 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0 + , 500.0f, 1.0f, 1000.0f, 1.0f // m_customParam1 + , 2.0f, 0.0f, 4.0f, 1.0f // m_xNum + , 2.0f, 0.0f, 4.0f, 1.0f // m_yNum + , 1.0f, 0.0f, 3.0f, 0.01f // m_xOffset + , 1.0f, 0.0f, 3.0f, 0.01f // m_yOffset + , true // m_doBlur + , &s_programs.m_packDepth[DepthImpl::InvZ][PackDepth::RGBA] //m_progPack + , &s_programs.m_colorLighting[SmType::Single][DepthImpl::InvZ][SmImpl::Hard] //m_progDraw + }, + { //SmImpl::PCF + 10.0f, 7.0f, 12.0f, 1.0f // m_sizePwrTwo + , 10.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow + , 1.0f, 1.0f, 99.0f, 1.0f // m_near + , 250.0f, 100.0f, 2000.0f, 50.0f // m_far + , 0.007f, 0.0f, 0.01f, 0.00001f // m_bias + , 0.001f, 0.0f, 0.05f, 0.00001f // m_normalOffset + , 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0 + , 500.0f, 1.0f, 1000.0f, 1.0f // m_customParam1 + , 2.0f, 0.0f, 8.0f, 1.0f // m_xNum + , 2.0f, 0.0f, 8.0f, 1.0f // m_yNum + , 1.0f, 0.0f, 3.0f, 0.01f // m_xOffset + , 1.0f, 0.0f, 3.0f, 0.01f // m_yOffset + , true // m_doBlur + , &s_programs.m_packDepth[DepthImpl::InvZ][PackDepth::RGBA] //m_progPack + , &s_programs.m_colorLighting[SmType::Single][DepthImpl::InvZ][SmImpl::PCF] //m_progDraw + }, + { //SmImpl::VSM + 10.0f, 7.0f, 12.0f, 1.0f // m_sizePwrTwo + , 10.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow + , 8.0f, 1.0f, 10.0f, 1.0f // m_near + , 250.0f, 100.0f, 2000.0f, 50.0f // m_far + , 0.045f, 0.0f, 0.1f, 0.00001f // m_bias + , 0.001f, 0.0f, 0.05f, 0.00001f // m_normalOffset + , 0.02f, 0.0f, 0.04f, 0.00001f // m_customParam0 + , 450.0f, 1.0f, 1000.0f, 1.0f // m_customParam1 + , 2.0f, 0.0f, 4.0f, 1.0f // m_xNum + , 2.0f, 0.0f, 4.0f, 1.0f // m_yNum + , 1.0f, 0.0f, 3.0f, 0.01f // m_xOffset + , 1.0f, 0.0f, 3.0f, 0.01f // m_yOffset + , true // m_doBlur + , &s_programs.m_packDepth[DepthImpl::InvZ][PackDepth::VSM] //m_progPack + , &s_programs.m_colorLighting[SmType::Single][DepthImpl::InvZ][SmImpl::VSM] //m_progDraw + }, + { //SmImpl::ESM + 10.0f, 7.0f, 12.0f, 1.0f // m_sizePwrTwo + , 10.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow + , 3.0f, 1.0f, 10.0f, 0.01f // m_near + , 250.0f, 100.0f, 2000.0f, 50.0f // m_far + , 0.02f, 0.0f, 0.3f, 0.00001f // m_bias + , 0.001f, 0.0f, 0.05f, 0.00001f // m_normalOffset + , 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0 + , 9000.0f, 1.0f, 15000.0f, 1.0f // m_customParam1 + , 2.0f, 0.0f, 4.0f, 1.0f // m_xNum + , 2.0f, 0.0f, 4.0f, 1.0f // m_yNum + , 1.0f, 0.0f, 3.0f, 0.01f // m_xOffset + , 1.0f, 0.0f, 3.0f, 0.01f // m_yOffset + , true // m_doBlur + , &s_programs.m_packDepth[DepthImpl::InvZ][PackDepth::RGBA] //m_progPack + , &s_programs.m_colorLighting[SmType::Single][DepthImpl::InvZ][SmImpl::ESM] //m_progDraw + } - case SmImpl::PCF: - imguiLabel("PCF"); - IMGUI_FLOAT_SLIDER("X Offset:", currentSmSettings->m_xOffset); - IMGUI_FLOAT_SLIDER("Y Offset:", currentSmSettings->m_yOffset); - break; + }, + { //DepthImpl::Linear + + { //SmImpl::Hard + 10.0f, 7.0f, 12.0f, 1.0f // m_sizePwrTwo + , 1.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow + , 1.0f, 1.0f, 10.0f, 1.0f // m_near + , 250.0f, 100.0f, 2000.0f, 50.0f // m_far + , 0.0025f, 0.0f, 0.01f, 0.00001f // m_bias + , 0.0012f, 0.0f, 0.05f, 0.00001f // m_normalOffset + , 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0 + , 500.0f, 1.0f, 1000.0f, 1.0f // m_customParam1 + , 2.0f, 0.0f, 4.0f, 1.0f // m_xNum + , 2.0f, 0.0f, 4.0f, 1.0f // m_yNum + , 1.0f, 0.0f, 3.0f, 0.01f // m_xOffset + , 1.0f, 0.0f, 3.0f, 0.01f // m_yOffset + , true // m_doBlur + , &s_programs.m_packDepth[DepthImpl::Linear][PackDepth::RGBA] //m_progPack + , &s_programs.m_colorLighting[SmType::Single][DepthImpl::Linear][SmImpl::Hard] //m_progDraw + }, + { //SmImpl::PCF + 10.0f, 7.0f, 12.0f, 1.0f // m_sizePwrTwo + , 1.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow + , 1.0f, 1.0f, 99.0f, 1.0f // m_near + , 250.0f, 100.0f, 2000.0f, 50.0f // m_far + , 0.0025f, 0.0f, 0.01f, 0.00001f // m_bias + , 0.001f, 0.0f, 0.05f, 0.00001f // m_normalOffset + , 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0 + , 2000.0f, 1.0f, 2000.0f, 1.0f // m_customParam1 + , 2.0f, 0.0f, 8.0f, 1.0f // m_xNum + , 2.0f, 0.0f, 8.0f, 1.0f // m_yNum + , 1.0f, 0.0f, 3.0f, 0.01f // m_xOffset + , 1.0f, 0.0f, 3.0f, 0.01f // m_yOffset + , true // m_doBlur + , &s_programs.m_packDepth[DepthImpl::Linear][PackDepth::RGBA] //m_progPack + , &s_programs.m_colorLighting[SmType::Single][DepthImpl::Linear][SmImpl::PCF] //m_progDraw + }, + { //SmImpl::VSM + 10.0f, 7.0f, 12.0f, 1.0f // m_sizePwrTwo + , 1.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow + , 1.0f, 1.0f, 10.0f, 1.0f // m_near + , 250.0f, 100.0f, 2000.0f, 50.0f // m_far + , 0.006f, 0.0f, 0.01f, 0.00001f // m_bias + , 0.001f, 0.0f, 0.05f, 0.00001f // m_normalOffset + , 0.02f, 0.0f, 0.1f, 0.00001f // m_customParam0 + , 300.0f, 1.0f, 1500.0f, 1.0f // m_customParam1 + , 2.0f, 0.0f, 4.0f, 1.0f // m_xNum + , 2.0f, 0.0f, 4.0f, 1.0f // m_yNum + , 1.0f, 0.0f, 3.0f, 0.01f // m_xOffset + , 1.0f, 0.0f, 3.0f, 0.01f // m_yOffset + , true // m_doBlur + , &s_programs.m_packDepth[DepthImpl::Linear][PackDepth::VSM] //m_progPack + , &s_programs.m_colorLighting[SmType::Single][DepthImpl::Linear][SmImpl::VSM] //m_progDraw + }, + { //SmImpl::ESM + 10.0f, 7.0f, 12.0f, 1.0f // m_sizePwrTwo + , 1.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow + , 1.0f, 1.0f, 10.0f, 0.01f // m_near + , 250.0f, 100.0f, 2000.0f, 50.0f // m_far + , 0.0055f, 0.0f, 0.01f, 0.00001f // m_bias + , 0.001f, 0.0f, 0.05f, 0.00001f // m_normalOffset + , 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0 + , 2500.0f, 1.0f, 5000.0f, 1.0f // m_customParam1 + , 2.0f, 0.0f, 4.0f, 1.0f // m_xNum + , 2.0f, 0.0f, 4.0f, 1.0f // m_yNum + , 1.0f, 0.0f, 3.0f, 0.01f // m_xOffset + , 1.0f, 0.0f, 3.0f, 0.01f // m_yOffset + , true // m_doBlur + , &s_programs.m_packDepth[DepthImpl::Linear][PackDepth::RGBA] //m_progPack + , &s_programs.m_colorLighting[SmType::Single][DepthImpl::Linear][SmImpl::ESM] //m_progDraw + } - case SmImpl::VSM: - imguiLabel("VSM"); - IMGUI_FLOAT_SLIDER("Min variance", currentSmSettings->m_customParam0); - IMGUI_FLOAT_SLIDER("Depth multiplier", currentSmSettings->m_customParam1); - imguiBool("Blur shadow map", currentSmSettings->m_doBlur); - if (currentSmSettings->m_doBlur) - { - IMGUI_FLOAT_SLIDER("Blur X Offset:", currentSmSettings->m_xOffset); - IMGUI_FLOAT_SLIDER("Blur Y Offset:", currentSmSettings->m_yOffset); } - break; - case SmImpl::ESM: - imguiLabel("ESM"); - IMGUI_FLOAT_SLIDER("ESM Hardness", currentSmSettings->m_customParam0); - IMGUI_FLOAT_SLIDER("Depth multiplier", currentSmSettings->m_customParam1); - imguiBool("Blur shadow map", currentSmSettings->m_doBlur); - if (currentSmSettings->m_doBlur) - { - IMGUI_FLOAT_SLIDER("Blur X Offset:", currentSmSettings->m_xOffset); - IMGUI_FLOAT_SLIDER("Blur Y Offset:", currentSmSettings->m_yOffset); + }, + { //LightType::Point + + { //DepthImpl::InvZ + + { //SmImpl::Hard + 12.0f, 9.0f, 12.0f, 1.0f // m_sizePwrTwo + , 10.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow + , 1.0f, 1.0f, 10.0f, 1.0f // m_near + , 250.0f, 100.0f, 2000.0f, 50.0f // m_far + , 0.006f, 0.0f, 0.01f, 0.00001f // m_bias + , 0.001f, 0.0f, 0.05f, 0.00001f // m_normalOffset + , 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0 + , 50.0f, 1.0f, 300.0f, 1.0f // m_customParam1 + , 2.0f, 0.0f, 4.0f, 1.0f // m_xNum + , 2.0f, 0.0f, 4.0f, 1.0f // m_yNum + , 0.25f, 0.0f, 2.0f, 0.001f // m_xOffset + , 0.25f, 0.0f, 2.0f, 0.001f // m_yOffset + , true // m_doBlur + , &s_programs.m_packDepth[DepthImpl::InvZ][PackDepth::RGBA] //m_progPack + , &s_programs.m_colorLighting[SmType::Omni][DepthImpl::InvZ][SmImpl::Hard] //m_progDraw + }, + { //SmImpl::PCF + 12.0f, 9.0f, 12.0f, 1.0f // m_sizePwrTwo + , 10.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow + , 1.0f, 1.0f, 99.0f, 1.0f // m_near + , 250.0f, 100.0f, 2000.0f, 50.0f // m_far + , 0.004f, 0.0f, 0.01f, 0.00001f // m_bias + , 0.001f, 0.0f, 0.05f, 0.00001f // m_normalOffset + , 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0 + , 50.0f, 1.0f, 300.0f, 1.0f // m_customParam1 + , 2.0f, 0.0f, 8.0f, 1.0f // m_xNum + , 2.0f, 0.0f, 8.0f, 1.0f // m_yNum + , 1.0f, 0.0f, 3.0f, 0.001f // m_xOffset + , 1.0f, 0.0f, 3.0f, 0.001f // m_yOffset + , true // m_doBlur + , &s_programs.m_packDepth[DepthImpl::InvZ][PackDepth::RGBA] //m_progPack + , &s_programs.m_colorLighting[SmType::Omni][DepthImpl::InvZ][SmImpl::PCF] //m_progDraw + }, + { //SmImpl::VSM + 12.0f, 9.0f, 12.0f, 1.0f // m_sizePwrTwo + , 10.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow + , 8.0f, 1.0f, 10.0f, 1.0f // m_near + , 250.0f, 100.0f, 2000.0f, 50.0f // m_far + , 0.055f, 0.0f, 0.1f, 0.00001f // m_bias + , 0.001f, 0.0f, 0.05f, 0.00001f // m_normalOffset + , 0.02f, 0.0f, 0.04f, 0.00001f // m_customParam0 + , 450.0f, 1.0f, 900.0f, 1.0f // m_customParam1 + , 2.0f, 0.0f, 4.0f, 1.0f // m_xNum + , 2.0f, 0.0f, 4.0f, 1.0f // m_yNum + , 0.25f, 0.0f, 2.0f, 0.001f // m_xOffset + , 0.25f, 0.0f, 2.0f, 0.001f // m_yOffset + , true // m_doBlur + , &s_programs.m_packDepth[DepthImpl::InvZ][PackDepth::VSM] //m_progPack + , &s_programs.m_colorLighting[SmType::Omni][DepthImpl::InvZ][SmImpl::VSM] //m_progDraw + }, + { //SmImpl::ESM + 12.0f, 9.0f, 12.0f, 1.0f // m_sizePwrTwo + , 10.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow + , 3.0f, 1.0f, 10.0f, 0.01f // m_near + , 250.0f, 100.0f, 2000.0f, 50.0f // m_far + , 0.035f, 0.0f, 0.1f, 0.00001f // m_bias + , 0.001f, 0.0f, 0.05f, 0.00001f // m_normalOffset + , 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0 + , 9000.0f, 1.0f, 15000.0f, 1.0f // m_customParam1 + , 2.0f, 0.0f, 4.0f, 1.0f // m_xNum + , 2.0f, 0.0f, 4.0f, 1.0f // m_yNum + , 0.25f, 0.0f, 2.0f, 0.001f // m_xOffset + , 0.25f, 0.0f, 2.0f, 0.001f // m_yOffset + , true // m_doBlur + , &s_programs.m_packDepth[DepthImpl::InvZ][PackDepth::RGBA] //m_progPack + , &s_programs.m_colorLighting[SmType::Omni][DepthImpl::InvZ][SmImpl::ESM] //m_progDraw + } + + }, + { //DepthImpl::Linear + + { //SmImpl::Hard + 12.0f, 9.0f, 12.0f, 1.0f // m_sizePwrTwo + , 1.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow + , 1.0f, 1.0f, 10.0f, 1.0f // m_near + , 250.0f, 100.0f, 2000.0f, 50.0f // m_far + , 0.003f, 0.0f, 0.01f, 0.00001f // m_bias + , 0.001f, 0.0f, 0.05f, 0.00001f // m_normalOffset + , 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0 + , 120.0f, 1.0f, 300.0f, 1.0f // m_customParam1 + , 2.0f, 0.0f, 4.0f, 1.0f // m_xNum + , 2.0f, 0.0f, 4.0f, 1.0f // m_yNum + , 0.25f, 0.0f, 2.0f, 0.001f // m_xOffset + , 0.25f, 0.0f, 2.0f, 0.001f // m_yOffset + , true // m_doBlur + , &s_programs.m_packDepth[DepthImpl::Linear][PackDepth::RGBA] //m_progPack + , &s_programs.m_colorLighting[SmType::Omni][DepthImpl::Linear][SmImpl::Hard] //m_progDraw + }, + { //SmImpl::PCF + 12.0f, 9.0f, 12.0f, 1.0f // m_sizePwrTwo + , 1.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow + , 1.0f, 1.0f, 99.0f, 1.0f // m_near + , 250.0f, 100.0f, 2000.0f, 50.0f // m_far + , 0.0035f, 0.0f, 0.01f, 0.00001f // m_bias + , 0.001f, 0.0f, 0.05f, 0.00001f // m_normalOffset + , 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0 + , 120.0f, 1.0f, 300.0f, 1.0f // m_customParam1 + , 2.0f, 0.0f, 8.0f, 1.0f // m_xNum + , 2.0f, 0.0f, 8.0f, 1.0f // m_yNum + , 1.0f, 0.0f, 3.0f, 0.001f // m_xOffset + , 1.0f, 0.0f, 3.0f, 0.001f // m_yOffset + , true // m_doBlur + , &s_programs.m_packDepth[DepthImpl::Linear][PackDepth::RGBA] //m_progPack + , &s_programs.m_colorLighting[SmType::Omni][DepthImpl::Linear][SmImpl::PCF] //m_progDraw + }, + { //SmImpl::VSM + 12.0f, 9.0f, 12.0f, 1.0f // m_sizePwrTwo + , 1.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow + , 1.0f, 1.0f, 10.0f, 1.0f // m_near + , 250.0f, 100.0f, 2000.0f, 50.0f // m_far + , 0.006f, 0.0f, 0.1f, 0.00001f // m_bias + , 0.001f, 0.0f, 0.05f, 0.00001f // m_normalOffset + , 0.02f, 0.0f, 0.1f, 0.00001f // m_customParam0 + , 400.0f, 1.0f, 900.0f, 1.0f // m_customParam1 + , 2.0f, 0.0f, 4.0f, 1.0f // m_xNum + , 2.0f, 0.0f, 4.0f, 1.0f // m_yNum + , 0.25f, 0.0f, 2.0f, 0.001f // m_xOffset + , 0.25f, 0.0f, 2.0f, 0.001f // m_yOffset + , true // m_doBlur + , &s_programs.m_packDepth[DepthImpl::Linear][PackDepth::VSM] //m_progPack + , &s_programs.m_colorLighting[SmType::Omni][DepthImpl::Linear][SmImpl::VSM] //m_progDraw + }, + { //SmImpl::ESM + 12.0f, 9.0f, 12.0f, 1.0f // m_sizePwrTwo + , 1.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow + , 1.0f, 1.0f, 10.0f, 0.01f // m_near + , 250.0f, 100.0f, 2000.0f, 50.0f // m_far + , 0.007f, 0.0f, 0.01f, 0.00001f // m_bias + , 0.001f, 0.0f, 0.05f, 0.00001f // m_normalOffset + , 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0 + , 8000.0f, 1.0f, 15000.0f, 1.0f // m_customParam1 + , 2.0f, 0.0f, 4.0f, 1.0f // m_xNum + , 2.0f, 0.0f, 4.0f, 1.0f // m_yNum + , 0.25f, 0.0f, 2.0f, 0.001f // m_xOffset + , 0.25f, 0.0f, 2.0f, 0.001f // m_yOffset + , true // m_doBlur + , &s_programs.m_packDepth[DepthImpl::Linear][PackDepth::RGBA] //m_progPack + , &s_programs.m_colorLighting[SmType::Omni][DepthImpl::Linear][SmImpl::ESM] //m_progDraw + } + } - break; - default: - break; + }, + { //LightType::Directional + + { //DepthImpl::InvZ + + { //SmImpl::Hard + 11.0f, 7.0f, 12.0f, 1.0f // m_sizePwrTwo + , 1.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow + , 1.0f, 1.0f, 10.0f, 1.0f // m_near + , 550.0f, 100.0f, 2000.0f, 50.0f // m_far + , 0.0012f, 0.0f, 0.01f, 0.00001f // m_bias + , 0.001f, 0.0f, 0.04f, 0.00001f // m_normalOffset + , 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0 + , 200.0f, 1.0f, 400.0f, 1.0f // m_customParam1 + , 2.0f, 0.0f, 4.0f, 1.0f // m_xNum + , 2.0f, 0.0f, 4.0f, 1.0f // m_yNum + , 0.2f, 0.0f, 1.0f, 0.01f // m_xOffset + , 0.2f, 0.0f, 1.0f, 0.01f // m_yOffset + , true // m_doBlur + , &s_programs.m_packDepth[DepthImpl::InvZ][PackDepth::RGBA] //m_progPack + , &s_programs.m_colorLighting[SmType::Cascade][DepthImpl::InvZ][SmImpl::Hard] //m_progDraw + }, + { //SmImpl::PCF + 11.0f, 7.0f, 12.0f, 1.0f // m_sizePwrTwo + , 1.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow + , 1.0f, 1.0f, 99.0f, 1.0f // m_near + , 550.0f, 100.0f, 2000.0f, 50.0f // m_far + , 0.0012f, 0.0f, 0.01f, 0.00001f // m_bias + , 0.001f, 0.0f, 0.04f, 0.00001f // m_normalOffset + , 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0 + , 200.0f, 1.0f, 400.0f, 1.0f // m_customParam1 + , 2.0f, 0.0f, 8.0f, 1.0f // m_xNum + , 2.0f, 0.0f, 8.0f, 1.0f // m_yNum + , 1.0f, 0.0f, 3.0f, 0.01f // m_xOffset + , 1.0f, 0.0f, 3.0f, 0.01f // m_yOffset + , true // m_doBlur + , &s_programs.m_packDepth[DepthImpl::InvZ][PackDepth::RGBA] //m_progPack + , &s_programs.m_colorLighting[SmType::Cascade][DepthImpl::InvZ][SmImpl::PCF] //m_progDraw + }, + { //SmImpl::VSM + 11.0f, 7.0f, 12.0f, 1.0f // m_sizePwrTwo + , 1.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow + , 1.0f, 1.0f, 10.0f, 1.0f // m_near + , 550.0f, 100.0f, 2000.0f, 50.0f // m_far + , 0.004f, 0.0f, 0.01f, 0.00001f // m_bias + , 0.001f, 0.0f, 0.04f, 0.00001f // m_normalOffset + , 0.02f, 0.0f, 0.04f, 0.00001f // m_customParam0 + , 2500.0f, 1.0f, 5000.0f, 1.0f // m_customParam1 + , 2.0f, 0.0f, 4.0f, 1.0f // m_xNum + , 2.0f, 0.0f, 4.0f, 1.0f // m_yNum + , 0.2f, 0.0f, 1.0f, 0.01f // m_xOffset + , 0.2f, 0.0f, 1.0f, 0.01f // m_yOffset + , true // m_doBlur + , &s_programs.m_packDepth[DepthImpl::InvZ][PackDepth::VSM] //m_progPack + , &s_programs.m_colorLighting[SmType::Cascade][DepthImpl::InvZ][SmImpl::VSM] //m_progDraw + }, + { //SmImpl::ESM + 11.0f, 7.0f, 12.0f, 1.0f // m_sizePwrTwo + , 1.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow + , 1.0f, 1.0f, 10.0f, 0.01f // m_near + , 550.0f, 100.0f, 2000.0f, 50.0f // m_far + , 0.004f, 0.0f, 0.01f, 0.00001f // m_bias + , 0.001f, 0.0f, 0.04f, 0.00001f // m_normalOffset + , 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0 + , 9500.0f, 1.0f, 15000.0f, 1.0f // m_customParam1 + , 2.0f, 0.0f, 4.0f, 1.0f // m_xNum + , 2.0f, 0.0f, 4.0f, 1.0f // m_yNum + , 0.2f, 0.0f, 1.0f, 0.01f // m_xOffset + , 0.2f, 0.0f, 1.0f, 0.01f // m_yOffset + , true // m_doBlur + , &s_programs.m_packDepth[DepthImpl::InvZ][PackDepth::RGBA] //m_progPack + , &s_programs.m_colorLighting[SmType::Cascade][DepthImpl::InvZ][SmImpl::ESM] //m_progDraw + } + + }, + { //DepthImpl::Linear + + { //SmImpl::Hard + 11.0f, 7.0f, 12.0f, 1.0f // m_sizePwrTwo + , 1.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow + , 1.0f, 1.0f, 10.0f, 1.0f // m_near + , 550.0f, 100.0f, 2000.0f, 50.0f // m_far + , 0.0012f, 0.0f, 0.01f, 0.00001f // m_bias + , 0.001f, 0.0f, 0.04f, 0.00001f // m_normalOffset + , 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0 + , 500.0f, 1.0f, 1000.0f, 1.0f // m_customParam1 + , 2.0f, 0.0f, 4.0f, 1.0f // m_xNum + , 2.0f, 0.0f, 4.0f, 1.0f // m_yNum + , 0.2f, 0.0f, 1.0f, 0.01f // m_xOffset + , 0.2f, 0.0f, 1.0f, 0.01f // m_yOffset + , true // m_doBlur + , &s_programs.m_packDepth[DepthImpl::Linear][PackDepth::RGBA] //m_progPack + , &s_programs.m_colorLighting[SmType::Cascade][DepthImpl::Linear][SmImpl::Hard] //m_progDraw + }, + { //SmImpl::PCF + 11.0f, 7.0f, 12.0f, 1.0f // m_sizePwrTwo + , 1.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow + , 1.0f, 1.0f, 99.0f, 1.0f // m_near + , 550.0f, 100.0f, 2000.0f, 50.0f // m_far + , 0.0012f, 0.0f, 0.01f, 0.00001f // m_bias + , 0.001f, 0.0f, 0.04f, 0.00001f // m_normalOffset + , 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0 + , 200.0f, 1.0f, 400.0f, 1.0f // m_customParam1 + , 2.0f, 0.0f, 8.0f, 1.0f // m_xNum + , 2.0f, 0.0f, 8.0f, 1.0f // m_yNum + , 1.0f, 0.0f, 3.0f, 0.01f // m_xOffset + , 1.0f, 0.0f, 3.0f, 0.01f // m_yOffset + , true // m_doBlur + , &s_programs.m_packDepth[DepthImpl::Linear][PackDepth::RGBA] //m_progPack + , &s_programs.m_colorLighting[SmType::Cascade][DepthImpl::Linear][SmImpl::PCF] //m_progDraw + }, + { //SmImpl::VSM + 11.0f, 7.0f, 12.0f, 1.0f // m_sizePwrTwo + , 1.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow + , 1.0f, 1.0f, 10.0f, 1.0f // m_near + , 550.0f, 100.0f, 2000.0f, 50.0f // m_far + , 0.004f, 0.0f, 0.01f, 0.00001f // m_bias + , 0.001f, 0.0f, 0.04f, 0.00001f // m_normalOffset + , 0.02f, 0.0f, 0.04f, 0.00001f // m_customParam0 + , 2500.0f, 1.0f, 5000.0f, 1.0f // m_customParam1 + , 2.0f, 0.0f, 4.0f, 1.0f // m_xNum + , 2.0f, 0.0f, 4.0f, 1.0f // m_yNum + , 0.2f, 0.0f, 1.0f, 0.01f // m_xOffset + , 0.2f, 0.0f, 1.0f, 0.01f // m_yOffset + , true // m_doBlur + , &s_programs.m_packDepth[DepthImpl::Linear][PackDepth::VSM] //m_progPack + , &s_programs.m_colorLighting[SmType::Cascade][DepthImpl::Linear][SmImpl::VSM] //m_progDraw + }, + { //SmImpl::ESM + 11.0f, 7.0f, 12.0f, 1.0f // m_sizePwrTwo + , 1.0f, 1.0f, 20.0f, 1.0f // m_depthValuePow + , 1.0f, 1.0f, 10.0f, 0.01f // m_near + , 550.0f, 100.0f, 2000.0f, 50.0f // m_far + , 0.004f, 0.0f, 0.01f, 0.00001f // m_bias + , 0.001f, 0.0f, 0.04f, 0.00001f // m_normalOffset + , 0.7f, 0.0f, 1.0f, 0.01f // m_customParam0 + , 9500.0f, 1.0f, 15000.0f, 1.0f // m_customParam1 + , 2.0f, 0.0f, 4.0f, 1.0f // m_xNum + , 2.0f, 0.0f, 4.0f, 1.0f // m_yNum + , 0.2f, 0.0f, 1.0f, 0.01f // m_xOffset + , 0.2f, 0.0f, 1.0f, 0.01f // m_yOffset + , true // m_doBlur + , &s_programs.m_packDepth[DepthImpl::Linear][PackDepth::RGBA] //m_progPack + , &s_programs.m_colorLighting[SmType::Cascade][DepthImpl::Linear][SmImpl::ESM] //m_progDraw + } + + } + } }; + bx::memCopy(m_smSettings, smSettings, sizeof(smSettings)); + + m_settings.m_lightType = LightType::SpotLight; + m_settings.m_depthImpl = DepthImpl::InvZ; + m_settings.m_smImpl = SmImpl::Hard; + m_settings.m_spotOuterAngle = 45.0f; + m_settings.m_spotInnerAngle = 30.0f; + m_settings.m_fovXAdjust = 0.0f; + m_settings.m_fovYAdjust = 0.0f; + m_settings.m_coverageSpotL = 90.0f; + m_settings.m_splitDistribution = 0.6f; + m_settings.m_numSplits = 4; + m_settings.m_updateLights = true; + m_settings.m_updateScene = true; + m_settings.m_drawDepthBuffer = false; + m_settings.m_showSmCoverage = false; + m_settings.m_stencilPack = true; + m_settings.m_stabilize = true; + + ShadowMapSettings* currentSmSettings = &m_smSettings[m_settings.m_lightType][m_settings.m_depthImpl][m_settings.m_smImpl]; + + // Render targets. + uint16_t shadowMapSize = 1 << uint32_t(currentSmSettings->m_sizePwrTwo); + m_currentShadowMapSize = shadowMapSize; + float currentShadowMapSizef = float(int16_t(m_currentShadowMapSize) ); + s_uniforms.m_shadowMapTexelSize = 1.0f / currentShadowMapSizef; + for (uint8_t ii = 0; ii < ShadowMapRenderTargets::Count; ++ii) + { + bgfx::TextureHandle fbtextures[] = + { + bgfx::createTexture2D(m_currentShadowMapSize, m_currentShadowMapSize, false, 1, bgfx::TextureFormat::BGRA8, BGFX_TEXTURE_RT), + bgfx::createTexture2D(m_currentShadowMapSize, m_currentShadowMapSize, false, 1, bgfx::TextureFormat::D24S8, BGFX_TEXTURE_RT), + }; + s_rtShadowMap[ii] = bgfx::createFrameBuffer(BX_COUNTOF(fbtextures), fbtextures, true); + } + s_rtBlur = bgfx::createFrameBuffer(m_currentShadowMapSize, m_currentShadowMapSize, bgfx::TextureFormat::BGRA8); - imguiEndScrollArea(); + // Setup camera. + float initialPos[3] = { 0.0f, 60.0f, -105.0f }; + cameraCreate(); + cameraSetPosition(initialPos); + cameraSetVerticalAngle(-0.45f); - static int32_t leftScrollArea = 0; - imguiBeginScrollArea("Light", 10, 70, 256, 334, &leftScrollArea); + m_timeAccumulatorLight = 0.0f; + m_timeAccumulatorScene = 0.0f; + } - const LightType::Enum ltBefore = settings.m_lightType; - imguiEnum(settings.m_lightType); - const LightType::Enum ltAfter = settings.m_lightType; - const bool bLtChanged = (ltAfter != ltBefore); + virtual int shutdown() override + { + m_bunnyMesh.unload(); + m_treeMesh.unload(); + m_cubeMesh.unload(); + m_hollowcubeMesh.unload(); + m_hplaneMesh.unload(); + m_vplaneMesh.unload(); + + bgfx::destroy(m_texFigure); + bgfx::destroy(m_texFieldstone); + bgfx::destroy(m_texFlare); + + for (uint8_t ii = 0; ii < ShadowMapRenderTargets::Count; ++ii) + { + bgfx::destroy(s_rtShadowMap[ii]); + } + bgfx::destroy(s_rtBlur); - imguiSeparator(); - imguiBool("Show shadow map coverage.", settings.m_showSmCoverage); + s_programs.destroy(); - imguiSeparator(); - imguiLabel("Shadow map resolution: %ux%u", currentShadowMapSize, currentShadowMapSize); - IMGUI_FLOAT_SLIDER(" ", currentSmSettings->m_sizePwrTwo); + bgfx::destroy(s_texColor); + bgfx::destroy(s_shadowMap[3]); + bgfx::destroy(s_shadowMap[2]); + bgfx::destroy(s_shadowMap[1]); + bgfx::destroy(s_shadowMap[0]); - imguiSeparatorLine(); - if (LightType::SpotLight == settings.m_lightType) - { - imguiLabel("Spot light"); - imguiSlider("Shadow map area:", settings.m_coverageSpotL, 45.0f, 120.0f, 1.0f); + s_uniforms.destroy(); - imguiSeparator(); - imguiSlider("Spot outer cone:", settings.m_spotOuterAngle, 0.0f, 91.0f, 0.1f); - imguiSlider("Spot inner cone:", settings.m_spotInnerAngle, 0.0f, 90.0f, 0.1f); - } - else if (LightType::PointLight == settings.m_lightType) - { - imguiLabel("Point light"); - imguiBool("Stencil pack", settings.m_stencilPack); + cameraDestroy(); + imguiDestroy(); - imguiSlider("Fov X adjust:", settings.m_fovXAdjust, -20.0f, 20.0f, 0.0001f); - imguiSlider("Fov Y adjust:", settings.m_fovYAdjust, -20.0f, 20.0f, 0.0001f); - } - else if (LightType::DirectionalLight == settings.m_lightType) - { - imguiLabel("Directional light"); - imguiBool("Stabilize cascades", settings.m_stabilize); - imguiSlider("Cascade splits:", settings.m_numSplitsf, 1.0f, 4.0f, 1.0f); - imguiSlider("Cascade distribution:", settings.m_splitDistribution, 0.0f, 1.0f, 0.001f); - settings.m_numSplits = uint8_t(settings.m_numSplitsf); - } + // Shutdown bgfx. + bgfx::shutdown(); -#undef IMGUI_FLOAT_SLIDER + return 0; + } - imguiEndScrollArea(); - imguiEndFrame(); - - // Update uniforms. - s_uniforms.m_shadowMapBias = currentSmSettings->m_bias; - s_uniforms.m_shadowMapOffset = currentSmSettings->m_normalOffset; - s_uniforms.m_shadowMapParam0 = currentSmSettings->m_customParam0; - s_uniforms.m_shadowMapParam1 = currentSmSettings->m_customParam1; - s_uniforms.m_depthValuePow = currentSmSettings->m_depthValuePow; - s_uniforms.m_XNum = currentSmSettings->m_xNum; - s_uniforms.m_YNum = currentSmSettings->m_yNum; - s_uniforms.m_XOffset = currentSmSettings->m_xOffset; - s_uniforms.m_YOffset = currentSmSettings->m_yOffset; - s_uniforms.m_showSmCoverage = float(settings.m_showSmCoverage); - s_uniforms.m_lightPtr = (LightType::DirectionalLight == settings.m_lightType) ? &directionalLight : &pointLight; - - if (LightType::SpotLight == settings.m_lightType) - { - pointLight.m_attenuationSpotOuter.m_outer = settings.m_spotOuterAngle; - pointLight.m_spotDirectionInner.m_inner = settings.m_spotInnerAngle; - } - else + bool update() override + { + if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) ) { - pointLight.m_attenuationSpotOuter.m_outer = 91.0f; //above 90.0f means point light - } + m_viewState.m_width = uint16_t(m_width); + m_viewState.m_height = uint16_t(m_height); + + const bgfx::Caps* caps = bgfx::getCaps(); + + // Set view and projection matrices. + const float camFovy = 60.0f; + const float camAspect = float(int32_t(m_viewState.m_width) ) / float(int32_t(m_viewState.m_height) ); + const float camNear = 0.1f; + const float camFar = 2000.0f; + const float projHeight = 1.0f/bx::ftan(bx::toRad(camFovy)*0.5f); + const float projWidth = projHeight * camAspect; + bx::mtxProj(m_viewState.m_proj, camFovy, camAspect, camNear, camFar, caps->homogeneousDepth); + cameraGetViewMtx(m_viewState.m_view); + + float currentShadowMapSizef = float(int16_t(m_currentShadowMapSize) ); + s_uniforms.m_shadowMapTexelSize = 1.0f / currentShadowMapSizef; - s_uniforms.submitPerFrameUniforms(); - - // Time. - int64_t now = bx::getHPCounter(); - static int64_t last = now; - const int64_t frameTime = now - last; - last = now; - const double freq = double(bx::getHPFrequency() ); - const double toMs = 1000.0/freq; - const float deltaTime = float(frameTime/freq); - - // Use debug font to print information about this example. - bgfx::dbgTextClear(); - bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/16-shadowmaps"); - bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Shadow maps example."); - bgfx::dbgTextPrintf(0, 3, 0x0f, "Frame: % 7.3f[ms]", double(frameTime)*toMs); - - // Update camera. - cameraUpdate(deltaTime, mouseState); - - // Update view mtx. - cameraGetViewMtx(viewState.m_view); - - // Update lights. - pointLight.computeViewSpaceComponents(viewState.m_view); - directionalLight.computeViewSpaceComponents(viewState.m_view); - - // Update time accumulators. - if (settings.m_updateLights) { timeAccumulatorLight += deltaTime; } - if (settings.m_updateScene) { timeAccumulatorScene += deltaTime; } - - // Setup lights. - pointLight.m_position.m_x = bx::fcos(timeAccumulatorLight) * 20.0f; - pointLight.m_position.m_y = 26.0f; - pointLight.m_position.m_z = bx::fsin(timeAccumulatorLight) * 20.0f; - pointLight.m_spotDirectionInner.m_x = -pointLight.m_position.m_x; - pointLight.m_spotDirectionInner.m_y = -pointLight.m_position.m_y; - pointLight.m_spotDirectionInner.m_z = -pointLight.m_position.m_z; - - directionalLight.m_position.m_x = -bx::fcos(timeAccumulatorLight); - directionalLight.m_position.m_y = -1.0f; - directionalLight.m_position.m_z = -bx::fsin(timeAccumulatorLight); - - // Setup instance matrices. - float mtxFloor[16]; - const float floorScale = 550.0f; - bx::mtxSRT(mtxFloor - , floorScale //scaleX - , floorScale //scaleY - , floorScale //scaleZ - , 0.0f //rotX - , 0.0f //rotY - , 0.0f //rotZ - , 0.0f //translateX - , 0.0f //translateY - , 0.0f //translateZ - ); - - float mtxBunny[16]; - bx::mtxSRT(mtxBunny - , 5.0f - , 5.0f - , 5.0f - , 0.0f - , 1.56f - timeAccumulatorScene - , 0.0f - , 15.0f - , 5.0f - , 0.0f - ); + s_uniforms.submitConstUniforms(); - float mtxHollowcube[16]; - bx::mtxSRT(mtxHollowcube - , 2.5f - , 2.5f - , 2.5f - , 0.0f - , 1.56f - timeAccumulatorScene - , 0.0f - , 0.0f - , 10.0f - , 0.0f - ); + // s_uniforms.submitConstUniforms(); - float mtxCube[16]; - bx::mtxSRT(mtxCube - , 2.5f - , 2.5f - , 2.5f - , 0.0f - , 1.56f - timeAccumulatorScene - , 0.0f - , -15.0f - , 5.0f - , 0.0f - ); + // Imgui. + imguiBeginFrame(m_mouseState.m_mx + , m_mouseState.m_my + , (m_mouseState.m_buttons[entry::MouseButton::Left ] ? IMGUI_MBUT_LEFT : 0) + | (m_mouseState.m_buttons[entry::MouseButton::Right ] ? IMGUI_MBUT_RIGHT : 0) + | (m_mouseState.m_buttons[entry::MouseButton::Middle] ? IMGUI_MBUT_MIDDLE : 0) + , m_mouseState.m_mz + , m_viewState.m_width + , m_viewState.m_height + ); - const uint8_t numTrees = 10; - float mtxTrees[numTrees][16]; - for (uint8_t ii = 0; ii < numTrees; ++ii) - { - bx::mtxSRT(mtxTrees[ii] - , 2.0f - , 2.0f - , 2.0f - , 0.0f - , float(ii) - , 0.0f - , bx::fsin(float(ii)*2.0f*bx::pi/float(numTrees) ) * 60.0f - , 0.0f - , bx::fcos(float(ii)*2.0f*bx::pi/float(numTrees) ) * 60.0f + showExampleDialog(this); + + ImGui::SetNextWindowPos( + ImVec2(m_viewState.m_width - m_viewState.m_width / 5.0f - 10.0f, 10.0f) + , ImGuiSetCond_FirstUseEver ); - } + ImGui::Begin("Settings" + , NULL + , ImVec2(m_viewState.m_width / 5.0f, m_viewState.m_height - 20.0f) + , ImGuiWindowFlags_AlwaysAutoResize + ); + +#define IMGUI_FLOAT_SLIDER(_name, _val) \ + ImGui::SliderFloat(_name \ + , &_val \ + , *( ((float*)&_val)+1) \ + , *( ((float*)&_val)+2) \ + ) + +#define IMGUI_RADIO_BUTTON(_name, _var, _val) \ + if (ImGui::RadioButton(_name, _var == _val) ) \ + { \ + _var = _val; \ + } - // Compute transform matrices. - const uint8_t shadowMapPasses = ShadowMapRenderTargets::Count; - float lightView[shadowMapPasses][16]; - float lightProj[shadowMapPasses][16]; - float mtxYpr[TetrahedronFaces::Count][16]; + ImGui::Checkbox("Update lights", &m_settings.m_updateLights); + ImGui::Checkbox("Update scene", &m_settings.m_updateScene); - float screenProj[16]; - float screenView[16]; - bx::mtxIdentity(screenView); - bx::mtxOrtho(screenProj, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 100.0f); + ImGui::Separator(); + ImGui::Text("Shadow map depth:"); + IMGUI_RADIO_BUTTON("InvZ", m_settings.m_depthImpl, DepthImpl::InvZ); + IMGUI_RADIO_BUTTON("Linear", m_settings.m_depthImpl, DepthImpl::Linear); - if (LightType::SpotLight == settings.m_lightType) - { - const float fovy = settings.m_coverageSpotL; - const float aspect = 1.0f; - bx::mtxProj(lightProj[ProjType::Horizontal], fovy, aspect, currentSmSettings->m_near, currentSmSettings->m_far); + ShadowMapSettings* currentSmSettings = &m_smSettings[m_settings.m_lightType][m_settings.m_depthImpl][m_settings.m_smImpl]; - //For linear depth, prevent depth division by variable w-component in shaders and divide here by far plane - if (DepthImpl::Linear == settings.m_depthImpl) + ImGui::Separator(); + ImGui::Checkbox("Draw depth buffer", &m_settings.m_drawDepthBuffer); + if (m_settings.m_drawDepthBuffer) { - lightProj[ProjType::Horizontal][10] /= currentSmSettings->m_far; - lightProj[ProjType::Horizontal][14] /= currentSmSettings->m_far; + IMGUI_FLOAT_SLIDER("Depth value pow", currentSmSettings->m_depthValuePow); } - float at[3]; - bx::vec3Add(at, pointLight.m_position.m_v, pointLight.m_spotDirectionInner.m_v); - bx::mtxLookAt(lightView[TetrahedronFaces::Green], pointLight.m_position.m_v, at); - } - else if (LightType::PointLight == settings.m_lightType) - { - float ypr[TetrahedronFaces::Count][3] = + ImGui::Separator(); + ImGui::Text("Shadow Map implementation"); + IMGUI_RADIO_BUTTON("Hard", m_settings.m_smImpl, SmImpl::Hard); + IMGUI_RADIO_BUTTON("PCF", m_settings.m_smImpl, SmImpl::PCF); + IMGUI_RADIO_BUTTON("VSM", m_settings.m_smImpl, SmImpl::VSM); + IMGUI_RADIO_BUTTON("ESM", m_settings.m_smImpl, SmImpl::ESM); + currentSmSettings = &m_smSettings[m_settings.m_lightType][m_settings.m_depthImpl][m_settings.m_smImpl]; + + ImGui::Separator(); + IMGUI_FLOAT_SLIDER("Bias", currentSmSettings->m_bias); + IMGUI_FLOAT_SLIDER("Normal offset", currentSmSettings->m_normalOffset); + ImGui::Separator(); + if (LightType::DirectionalLight != m_settings.m_lightType) { - { bx::toRad( 0.0f), bx::toRad( 27.36780516f), bx::toRad(0.0f) }, - { bx::toRad(180.0f), bx::toRad( 27.36780516f), bx::toRad(0.0f) }, - { bx::toRad(-90.0f), bx::toRad(-27.36780516f), bx::toRad(0.0f) }, - { bx::toRad( 90.0f), bx::toRad(-27.36780516f), bx::toRad(0.0f) }, - }; - + IMGUI_FLOAT_SLIDER("Near plane", currentSmSettings->m_near); + } + IMGUI_FLOAT_SLIDER("Far plane", currentSmSettings->m_far); - if (settings.m_stencilPack) + ImGui::Separator(); + switch(m_settings.m_smImpl) { - const float fovx = 143.98570868f + 3.51f + settings.m_fovXAdjust; - const float fovy = 125.26438968f + 9.85f + settings.m_fovYAdjust; - const float aspect = bx::ftan(bx::toRad(fovx*0.5f) )/bx::ftan(bx::toRad(fovy*0.5f) ); - - bx::mtxProj(lightProj[ProjType::Vertical] - , fovx - , aspect - , currentSmSettings->m_near - , currentSmSettings->m_far - ); - - //For linear depth, prevent depth division by variable w-component in shaders and divide here by far plane - if (DepthImpl::Linear == settings.m_depthImpl) - { - lightProj[ProjType::Vertical][10] /= currentSmSettings->m_far; - lightProj[ProjType::Vertical][14] /= currentSmSettings->m_far; - } + case SmImpl::Hard: + //ImGui::Text("Hard"); + break; + + case SmImpl::PCF: + ImGui::Text("PCF"); + IMGUI_FLOAT_SLIDER("X Offset", currentSmSettings->m_xOffset); + IMGUI_FLOAT_SLIDER("Y Offset", currentSmSettings->m_yOffset); + break; + + case SmImpl::VSM: + ImGui::Text("VSM"); + IMGUI_FLOAT_SLIDER("Min variance", currentSmSettings->m_customParam0); + IMGUI_FLOAT_SLIDER("Depth multiplier", currentSmSettings->m_customParam1); + ImGui::Checkbox("Blur shadow map", ¤tSmSettings->m_doBlur); + if (currentSmSettings->m_doBlur) + { + IMGUI_FLOAT_SLIDER("Blur X Offset", currentSmSettings->m_xOffset); + IMGUI_FLOAT_SLIDER("Blur Y Offset", currentSmSettings->m_yOffset); + } + break; + + case SmImpl::ESM: + ImGui::Text("ESM"); + IMGUI_FLOAT_SLIDER("ESM Hardness", currentSmSettings->m_customParam0); + IMGUI_FLOAT_SLIDER("Depth multiplier", currentSmSettings->m_customParam1); + ImGui::Checkbox("Blur shadow map", ¤tSmSettings->m_doBlur); + if (currentSmSettings->m_doBlur) + { + IMGUI_FLOAT_SLIDER("Blur X Offset", currentSmSettings->m_xOffset); + IMGUI_FLOAT_SLIDER("Blur Y Offset", currentSmSettings->m_yOffset); + } + break; - ypr[TetrahedronFaces::Green ][2] = bx::toRad(180.0f); - ypr[TetrahedronFaces::Yellow][2] = bx::toRad( 0.0f); - ypr[TetrahedronFaces::Blue ][2] = bx::toRad( 90.0f); - ypr[TetrahedronFaces::Red ][2] = bx::toRad(-90.0f); - } + default: + break; + }; - const float fovx = 143.98570868f + 7.8f + settings.m_fovXAdjust; - const float fovy = 125.26438968f + 3.0f + settings.m_fovYAdjust; - const float aspect = bx::ftan(bx::toRad(fovx*0.5f) )/bx::ftan(bx::toRad(fovy*0.5f) ); + ImGui::End(); +#undef IMGUI_RADIO_BUTTON - bx::mtxProj(lightProj[ProjType::Horizontal], fovy, aspect, currentSmSettings->m_near, currentSmSettings->m_far); + ImGui::SetNextWindowPos( + ImVec2(10.0f, 260.0f) + , ImGuiSetCond_FirstUseEver + ); + ImGui::Begin("Light" + , NULL + , ImVec2(m_viewState.m_width / 5.0f, 350.0f) + , ImGuiWindowFlags_AlwaysAutoResize + ); + ImGui::PushItemWidth(185.0f); - //For linear depth, prevent depth division by variable w component in shaders and divide here by far plane - if (DepthImpl::Linear == settings.m_depthImpl) + bool bLtChanged = false; + if ( ImGui::RadioButton("Spot light", m_settings.m_lightType == LightType::SpotLight )) + { + m_settings.m_lightType = LightType::SpotLight; bLtChanged = true; + } + if ( ImGui::RadioButton("Point light", m_settings.m_lightType == LightType::PointLight )) { - lightProj[ProjType::Horizontal][10] /= currentSmSettings->m_far; - lightProj[ProjType::Horizontal][14] /= currentSmSettings->m_far; + m_settings.m_lightType = LightType::PointLight; bLtChanged = true; + } + if ( ImGui::RadioButton("Directional light", m_settings.m_lightType == LightType::DirectionalLight )) + { + m_settings.m_lightType = LightType::DirectionalLight; bLtChanged = true; } + ImGui::Separator(); + ImGui::Checkbox("Show shadow map coverage.", &m_settings.m_showSmCoverage); - for (uint8_t ii = 0; ii < TetrahedronFaces::Count; ++ii) - { - float mtxTmp[16]; - mtxYawPitchRoll(mtxTmp, ypr[ii][0], ypr[ii][1], ypr[ii][2]); + ImGui::Separator(); + ImGui::Text("Shadow map resolution: %ux%u", m_currentShadowMapSize, m_currentShadowMapSize); + ImGui::SliderFloat("##SizePwrTwo", ¤tSmSettings->m_sizePwrTwo, + currentSmSettings->m_sizePwrTwoMin, + currentSmSettings->m_sizePwrTwoMax, "%.0f"); - float tmp[3] = - { - -bx::vec3Dot(pointLight.m_position.m_v, &mtxTmp[0]), - -bx::vec3Dot(pointLight.m_position.m_v, &mtxTmp[4]), - -bx::vec3Dot(pointLight.m_position.m_v, &mtxTmp[8]), - }; + ImGui::Separator(); + if (LightType::SpotLight == m_settings.m_lightType) + { + ImGui::Text("Spot light"); + ImGui::SliderFloat("Shadow map area", &m_settings.m_coverageSpotL, 45.0f, 120.0f); - bx::mtxTranspose(mtxYpr[ii], mtxTmp); + ImGui::Separator(); + ImGui::SliderFloat("Spot outer cone", &m_settings.m_spotOuterAngle, 0.0f, 91.0f); + ImGui::SliderFloat("Spot inner cone", &m_settings.m_spotInnerAngle, 0.0f, 90.0f); + } + else if (LightType::PointLight == m_settings.m_lightType) + { + ImGui::Text("Point light"); + ImGui::Checkbox("Stencil pack", &m_settings.m_stencilPack); - bx::memCopy(lightView[ii], mtxYpr[ii], 12*sizeof(float) ); - lightView[ii][12] = tmp[0]; - lightView[ii][13] = tmp[1]; - lightView[ii][14] = tmp[2]; - lightView[ii][15] = 1.0f; + ImGui::SliderFloat("Fov X adjust", &m_settings.m_fovXAdjust, -20.0f, 20.0f); + ImGui::SliderFloat("Fov Y adjust", &m_settings.m_fovYAdjust, -20.0f, 20.0f); } - } - else // LightType::DirectionalLight == settings.m_lightType - { - // Setup light view mtx. - float eye[3] = + else if (LightType::DirectionalLight == m_settings.m_lightType) { - -directionalLight.m_position.m_x - , -directionalLight.m_position.m_y - , -directionalLight.m_position.m_z - }; - float at[3] = { 0.0f, 0.0f, 0.0f }; - bx::mtxLookAt(lightView[0], eye, at); + ImGui::Text("Directional light"); + ImGui::Checkbox("Stabilize cascades", &m_settings.m_stabilize); + ImGui::SliderInt("Cascade splits", &m_settings.m_numSplits, 1, 4); + ImGui::SliderFloat("Cascade distribution", &m_settings.m_splitDistribution, 0.0f, 1.0f); + } - // Compute camera inverse view mtx. - float mtxViewInv[16]; - bx::mtxInverse(mtxViewInv, viewState.m_view); +#undef IMGUI_FLOAT_SLIDER - // Compute split distances. - const uint8_t maxNumSplits = 4; - BX_CHECK(maxNumSplits >= settings.m_numSplits, "Error! Max num splits."); + ImGui::End(); - float splitSlices[maxNumSplits*2]; - splitFrustum(splitSlices, settings.m_numSplits, currentSmSettings->m_near, currentSmSettings->m_far, settings.m_splitDistribution); + imguiEndFrame(); // Update uniforms. - for (uint8_t ii = 0, ff = 1; ii < settings.m_numSplits; ++ii, ff+=2) + s_uniforms.m_shadowMapBias = currentSmSettings->m_bias; + s_uniforms.m_shadowMapOffset = currentSmSettings->m_normalOffset; + s_uniforms.m_shadowMapParam0 = currentSmSettings->m_customParam0; + s_uniforms.m_shadowMapParam1 = currentSmSettings->m_customParam1; + s_uniforms.m_depthValuePow = currentSmSettings->m_depthValuePow; + s_uniforms.m_XNum = currentSmSettings->m_xNum; + s_uniforms.m_YNum = currentSmSettings->m_yNum; + s_uniforms.m_XOffset = currentSmSettings->m_xOffset; + s_uniforms.m_YOffset = currentSmSettings->m_yOffset; + s_uniforms.m_showSmCoverage = float(m_settings.m_showSmCoverage); + s_uniforms.m_lightPtr = (LightType::DirectionalLight == m_settings.m_lightType) ? &m_directionalLight : &m_pointLight; + + if (LightType::SpotLight == m_settings.m_lightType) { - // This lags for 1 frame, but it's not a problem. - s_uniforms.m_csmFarDistances[ii] = splitSlices[ff]; + m_pointLight.m_attenuationSpotOuter.m_outer = m_settings.m_spotOuterAngle; + m_pointLight.m_spotDirectionInner.m_inner = m_settings.m_spotInnerAngle; + } + else + { + m_pointLight.m_attenuationSpotOuter.m_outer = 91.0f; //above 90.0f means point light } - float mtxProj[16]; - bx::mtxOrtho(mtxProj, 1.0f, -1.0f, 1.0f, -1.0f, -currentSmSettings->m_far, currentSmSettings->m_far); - - const uint8_t numCorners = 8; - float frustumCorners[maxNumSplits][numCorners][3]; - for (uint8_t ii = 0, nn = 0, ff = 1; ii < settings.m_numSplits; ++ii, nn+=2, ff+=2) + s_uniforms.submitPerFrameUniforms(); + + // Time. + int64_t now = bx::getHPCounter(); + static int64_t last = now; + const int64_t frameTime = now - last; + last = now; + const double freq = double(bx::getHPFrequency() ); + const float deltaTime = float(frameTime/freq); + + // Update camera. + cameraUpdate(deltaTime, m_mouseState); + + // Update view mtx. + cameraGetViewMtx(m_viewState.m_view); + + // Update lights. + m_pointLight.computeViewSpaceComponents(m_viewState.m_view); + m_directionalLight.computeViewSpaceComponents(m_viewState.m_view); + + // Update time accumulators. + if (m_settings.m_updateLights) { m_timeAccumulatorLight += deltaTime; } + if (m_settings.m_updateScene) { m_timeAccumulatorScene += deltaTime; } + + // Setup lights. + m_pointLight.m_position.m_x = bx::fcos(m_timeAccumulatorLight) * 20.0f; + m_pointLight.m_position.m_y = 26.0f; + m_pointLight.m_position.m_z = bx::fsin(m_timeAccumulatorLight) * 20.0f; + m_pointLight.m_spotDirectionInner.m_x = -m_pointLight.m_position.m_x; + m_pointLight.m_spotDirectionInner.m_y = -m_pointLight.m_position.m_y; + m_pointLight.m_spotDirectionInner.m_z = -m_pointLight.m_position.m_z; + + m_directionalLight.m_position.m_x = -bx::fcos(m_timeAccumulatorLight); + m_directionalLight.m_position.m_y = -1.0f; + m_directionalLight.m_position.m_z = -bx::fsin(m_timeAccumulatorLight); + + // Setup instance matrices. + float mtxFloor[16]; + const float floorScale = 550.0f; + bx::mtxSRT(mtxFloor + , floorScale //scaleX + , floorScale //scaleY + , floorScale //scaleZ + , 0.0f //rotX + , 0.0f //rotY + , 0.0f //rotZ + , 0.0f //translateX + , 0.0f //translateY + , 0.0f //translateZ + ); + + float mtxBunny[16]; + bx::mtxSRT(mtxBunny + , 5.0f + , 5.0f + , 5.0f + , 0.0f + , 1.56f - m_timeAccumulatorScene + , 0.0f + , 15.0f + , 5.0f + , 0.0f + ); + + float mtxHollowcube[16]; + bx::mtxSRT(mtxHollowcube + , 2.5f + , 2.5f + , 2.5f + , 0.0f + , 1.56f - m_timeAccumulatorScene + , 0.0f + , 0.0f + , 10.0f + , 0.0f + ); + + float mtxCube[16]; + bx::mtxSRT(mtxCube + , 2.5f + , 2.5f + , 2.5f + , 0.0f + , 1.56f - m_timeAccumulatorScene + , 0.0f + , -15.0f + , 5.0f + , 0.0f + ); + + const uint8_t numTrees = 10; + float mtxTrees[numTrees][16]; + for (uint8_t ii = 0; ii < numTrees; ++ii) { - // Compute frustum corners for one split in world space. - worldSpaceFrustumCorners( (float*)frustumCorners[ii], splitSlices[nn], splitSlices[ff], projWidth, projHeight, mtxViewInv); + bx::mtxSRT(mtxTrees[ii] + , 2.0f + , 2.0f + , 2.0f + , 0.0f + , float(ii) + , 0.0f + , bx::fsin(float(ii)*2.0f*bx::kPi/float(numTrees) ) * 60.0f + , 0.0f + , bx::fcos(float(ii)*2.0f*bx::kPi/float(numTrees) ) * 60.0f + ); + } - float min[3] = { 9000.0f, 9000.0f, 9000.0f }; - float max[3] = { -9000.0f, -9000.0f, -9000.0f }; + // Compute transform matrices. + const uint8_t shadowMapPasses = ShadowMapRenderTargets::Count; + float lightView[shadowMapPasses][16]; + float lightProj[shadowMapPasses][16]; + float mtxYpr[TetrahedronFaces::Count][16]; + + float screenProj[16]; + float screenView[16]; + bx::mtxIdentity(screenView); + + bx::mtxOrtho( + screenProj + , 0.0f + , 1.0f + , 1.0f + , 0.0f + , 0.0f + , 100.0f + , 0.0f + , caps->homogeneousDepth + ); + + if (LightType::SpotLight == m_settings.m_lightType) + { + const float fovy = m_settings.m_coverageSpotL; + const float aspect = 1.0f; + bx::mtxProj( + lightProj[ProjType::Horizontal] + , fovy + , aspect + , currentSmSettings->m_near + , currentSmSettings->m_far + , false + ); - for (uint8_t jj = 0; jj < numCorners; ++jj) + //For linear depth, prevent depth division by variable w-component in shaders and divide here by far plane + if (DepthImpl::Linear == m_settings.m_depthImpl) { - // Transform to light space. - float lightSpaceFrustumCorner[3]; - bx::vec3MulMtx(lightSpaceFrustumCorner, frustumCorners[ii][jj], lightView[0]); - - // Update bounding box. - min[0] = bx::fmin(min[0], lightSpaceFrustumCorner[0]); - max[0] = bx::fmax(max[0], lightSpaceFrustumCorner[0]); - min[1] = bx::fmin(min[1], lightSpaceFrustumCorner[1]); - max[1] = bx::fmax(max[1], lightSpaceFrustumCorner[1]); - min[2] = bx::fmin(min[2], lightSpaceFrustumCorner[2]); - max[2] = bx::fmax(max[2], lightSpaceFrustumCorner[2]); + lightProj[ProjType::Horizontal][10] /= currentSmSettings->m_far; + lightProj[ProjType::Horizontal][14] /= currentSmSettings->m_far; } - float minproj[3]; - float maxproj[3]; - bx::vec3MulMtxH(minproj, min, mtxProj); - bx::vec3MulMtxH(maxproj, max, mtxProj); - - float offsetx, offsety; - float scalex, scaley; + float at[3]; + bx::vec3Add(at, m_pointLight.m_position.m_v, m_pointLight.m_spotDirectionInner.m_v); + bx::mtxLookAt(lightView[TetrahedronFaces::Green], m_pointLight.m_position.m_v, at); + } + else if (LightType::PointLight == m_settings.m_lightType) + { + float ypr[TetrahedronFaces::Count][3] = + { + { bx::toRad( 0.0f), bx::toRad( 27.36780516f), bx::toRad(0.0f) }, + { bx::toRad(180.0f), bx::toRad( 27.36780516f), bx::toRad(0.0f) }, + { bx::toRad(-90.0f), bx::toRad(-27.36780516f), bx::toRad(0.0f) }, + { bx::toRad( 90.0f), bx::toRad(-27.36780516f), bx::toRad(0.0f) }, + }; - scalex = 2.0f / (maxproj[0] - minproj[0]); - scaley = 2.0f / (maxproj[1] - minproj[1]); - if (settings.m_stabilize) + if (m_settings.m_stencilPack) { - const float quantizer = 64.0f; - scalex = quantizer / bx::fceil(quantizer / scalex); - scaley = quantizer / bx::fceil(quantizer / scaley); + const float fovx = 143.98570868f + 3.51f + m_settings.m_fovXAdjust; + const float fovy = 125.26438968f + 9.85f + m_settings.m_fovYAdjust; + const float aspect = bx::ftan(bx::toRad(fovx*0.5f) )/bx::ftan(bx::toRad(fovy*0.5f) ); + + bx::mtxProj( + lightProj[ProjType::Vertical] + , fovx + , aspect + , currentSmSettings->m_near + , currentSmSettings->m_far + , false + ); + + //For linear depth, prevent depth division by variable w-component in shaders and divide here by far plane + if (DepthImpl::Linear == m_settings.m_depthImpl) + { + lightProj[ProjType::Vertical][10] /= currentSmSettings->m_far; + lightProj[ProjType::Vertical][14] /= currentSmSettings->m_far; + } + + ypr[TetrahedronFaces::Green ][2] = bx::toRad(180.0f); + ypr[TetrahedronFaces::Yellow][2] = bx::toRad( 0.0f); + ypr[TetrahedronFaces::Blue ][2] = bx::toRad( 90.0f); + ypr[TetrahedronFaces::Red ][2] = bx::toRad(-90.0f); } - offsetx = 0.5f * (maxproj[0] + minproj[0]) * scalex; - offsety = 0.5f * (maxproj[1] + minproj[1]) * scaley; + const float fovx = 143.98570868f + 7.8f + m_settings.m_fovXAdjust; + const float fovy = 125.26438968f + 3.0f + m_settings.m_fovYAdjust; + const float aspect = bx::ftan(bx::toRad(fovx*0.5f) )/bx::ftan(bx::toRad(fovy*0.5f) ); - if (settings.m_stabilize) + bx::mtxProj( + lightProj[ProjType::Horizontal] + , fovy + , aspect + , currentSmSettings->m_near + , currentSmSettings->m_far + , caps->homogeneousDepth + ); + + //For linear depth, prevent depth division by variable w component in shaders and divide here by far plane + if (DepthImpl::Linear == m_settings.m_depthImpl) { - const float halfSize = currentShadowMapSizef * 0.5f; - offsetx = bx::fceil(offsetx * halfSize) / halfSize; - offsety = bx::fceil(offsety * halfSize) / halfSize; + lightProj[ProjType::Horizontal][10] /= currentSmSettings->m_far; + lightProj[ProjType::Horizontal][14] /= currentSmSettings->m_far; } - float mtxCrop[16]; - bx::mtxIdentity(mtxCrop); - mtxCrop[ 0] = scalex; - mtxCrop[ 5] = scaley; - mtxCrop[12] = offsetx; - mtxCrop[13] = offsety; - - bx::mtxMul(lightProj[ii], mtxCrop, mtxProj); - } - } - // Reset render targets. - const bgfx::FrameBufferHandle invalidRt = BGFX_INVALID_HANDLE; - for (uint8_t ii = 0; ii < RENDERVIEW_DRAWDEPTH_3_ID+1; ++ii) - { - bgfx::setViewFrameBuffer(ii, invalidRt); - } + for (uint8_t ii = 0; ii < TetrahedronFaces::Count; ++ii) + { + float mtxTmp[16]; + mtxYawPitchRoll(mtxTmp, ypr[ii][0], ypr[ii][1], ypr[ii][2]); - // Determine on-screen rectangle size where depth buffer will be drawn. - uint16_t depthRectHeight = uint16_t(float(viewState.m_height) / 2.5f); - uint16_t depthRectWidth = depthRectHeight; - uint16_t depthRectX = 0; - uint16_t depthRectY = viewState.m_height - depthRectHeight; + float tmp[3] = + { + -bx::vec3Dot(m_pointLight.m_position.m_v, &mtxTmp[0]), + -bx::vec3Dot(m_pointLight.m_position.m_v, &mtxTmp[4]), + -bx::vec3Dot(m_pointLight.m_position.m_v, &mtxTmp[8]), + }; - // Setup views and render targets. - bgfx::setViewRect(0, 0, 0, viewState.m_width, viewState.m_height); - bgfx::setViewTransform(0, viewState.m_view, viewState.m_proj); + bx::mtxTranspose(mtxYpr[ii], mtxTmp); - if (LightType::SpotLight == settings.m_lightType) - { - /** - * RENDERVIEW_SHADOWMAP_0_ID - Clear shadow map. (used as convenience, otherwise render_pass_1 could be cleared) - * RENDERVIEW_SHADOWMAP_1_ID - Craft shadow map. - * RENDERVIEW_VBLUR_0_ID - Vertical blur. - * RENDERVIEW_HBLUR_0_ID - Horizontal blur. - * RENDERVIEW_DRAWSCENE_0_ID - Draw scene. - * RENDERVIEW_DRAWSCENE_1_ID - Draw floor bottom. - * RENDERVIEW_DRAWDEPTH_0_ID - Draw depth buffer. - */ - - bgfx::setViewRect(RENDERVIEW_SHADOWMAP_0_ID, 0, 0, currentShadowMapSize, currentShadowMapSize); - bgfx::setViewRect(RENDERVIEW_SHADOWMAP_1_ID, 0, 0, currentShadowMapSize, currentShadowMapSize); - bgfx::setViewRect(RENDERVIEW_VBLUR_0_ID, 0, 0, currentShadowMapSize, currentShadowMapSize); - bgfx::setViewRect(RENDERVIEW_HBLUR_0_ID, 0, 0, currentShadowMapSize, currentShadowMapSize); - bgfx::setViewRect(RENDERVIEW_DRAWSCENE_0_ID, 0, 0, viewState.m_width, viewState.m_height); - bgfx::setViewRect(RENDERVIEW_DRAWSCENE_1_ID, 0, 0, viewState.m_width, viewState.m_height); - bgfx::setViewRect(RENDERVIEW_DRAWDEPTH_0_ID, depthRectX, depthRectY, depthRectWidth, depthRectHeight); - - bgfx::setViewTransform(RENDERVIEW_SHADOWMAP_0_ID, screenView, screenProj); - bgfx::setViewTransform(RENDERVIEW_SHADOWMAP_1_ID, lightView[0], lightProj[ProjType::Horizontal]); - bgfx::setViewTransform(RENDERVIEW_VBLUR_0_ID, screenView, screenProj); - bgfx::setViewTransform(RENDERVIEW_HBLUR_0_ID, screenView, screenProj); - bgfx::setViewTransform(RENDERVIEW_DRAWSCENE_0_ID, viewState.m_view, viewState.m_proj); - bgfx::setViewTransform(RENDERVIEW_DRAWSCENE_1_ID, viewState.m_view, viewState.m_proj); - bgfx::setViewTransform(RENDERVIEW_DRAWDEPTH_0_ID, screenView, screenProj); - - bgfx::setViewFrameBuffer(RENDERVIEW_SHADOWMAP_0_ID, s_rtShadowMap[0]); - bgfx::setViewFrameBuffer(RENDERVIEW_SHADOWMAP_1_ID, s_rtShadowMap[0]); - bgfx::setViewFrameBuffer(RENDERVIEW_VBLUR_0_ID, s_rtBlur); - bgfx::setViewFrameBuffer(RENDERVIEW_HBLUR_0_ID, s_rtShadowMap[0]); - } - else if (LightType::PointLight == settings.m_lightType) - { - /** - * RENDERVIEW_SHADOWMAP_0_ID - Clear entire shadow map. - * RENDERVIEW_SHADOWMAP_1_ID - Craft green tetrahedron shadow face. - * RENDERVIEW_SHADOWMAP_2_ID - Craft yellow tetrahedron shadow face. - * RENDERVIEW_SHADOWMAP_3_ID - Craft blue tetrahedron shadow face. - * RENDERVIEW_SHADOWMAP_4_ID - Craft red tetrahedron shadow face. - * RENDERVIEW_VBLUR_0_ID - Vertical blur. - * RENDERVIEW_HBLUR_0_ID - Horizontal blur. - * RENDERVIEW_DRAWSCENE_0_ID - Draw scene. - * RENDERVIEW_DRAWSCENE_1_ID - Draw floor bottom. - * RENDERVIEW_DRAWDEPTH_0_ID - Draw depth buffer. - */ - - bgfx::setViewRect(RENDERVIEW_SHADOWMAP_0_ID, 0, 0, currentShadowMapSize, currentShadowMapSize); - if (settings.m_stencilPack) - { - const uint16_t f = currentShadowMapSize; //full size - const uint16_t h = currentShadowMapSize/2; //half size - bgfx::setViewRect(RENDERVIEW_SHADOWMAP_1_ID, 0, 0, f, h); - bgfx::setViewRect(RENDERVIEW_SHADOWMAP_2_ID, 0, h, f, h); - bgfx::setViewRect(RENDERVIEW_SHADOWMAP_3_ID, 0, 0, h, f); - bgfx::setViewRect(RENDERVIEW_SHADOWMAP_4_ID, h, 0, h, f); - } - else - { - const uint16_t h = currentShadowMapSize/2; //half size - bgfx::setViewRect(RENDERVIEW_SHADOWMAP_1_ID, 0, 0, h, h); - bgfx::setViewRect(RENDERVIEW_SHADOWMAP_2_ID, h, 0, h, h); - bgfx::setViewRect(RENDERVIEW_SHADOWMAP_3_ID, 0, h, h, h); - bgfx::setViewRect(RENDERVIEW_SHADOWMAP_4_ID, h, h, h, h); - } - bgfx::setViewRect(RENDERVIEW_VBLUR_0_ID, 0, 0, currentShadowMapSize, currentShadowMapSize); - bgfx::setViewRect(RENDERVIEW_HBLUR_0_ID, 0, 0, currentShadowMapSize, currentShadowMapSize); - bgfx::setViewRect(RENDERVIEW_DRAWSCENE_0_ID, 0, 0, viewState.m_width, viewState.m_height); - bgfx::setViewRect(RENDERVIEW_DRAWSCENE_1_ID, 0, 0, viewState.m_width, viewState.m_height); - bgfx::setViewRect(RENDERVIEW_DRAWDEPTH_0_ID, depthRectX, depthRectY, depthRectWidth, depthRectHeight); - - bgfx::setViewTransform(RENDERVIEW_SHADOWMAP_0_ID, screenView, screenProj); - bgfx::setViewTransform(RENDERVIEW_SHADOWMAP_1_ID, lightView[TetrahedronFaces::Green], lightProj[ProjType::Horizontal]); - bgfx::setViewTransform(RENDERVIEW_SHADOWMAP_2_ID, lightView[TetrahedronFaces::Yellow], lightProj[ProjType::Horizontal]); - if(settings.m_stencilPack) - { - bgfx::setViewTransform(RENDERVIEW_SHADOWMAP_3_ID, lightView[TetrahedronFaces::Blue], lightProj[ProjType::Vertical]); - bgfx::setViewTransform(RENDERVIEW_SHADOWMAP_4_ID, lightView[TetrahedronFaces::Red], lightProj[ProjType::Vertical]); + bx::memCopy(lightView[ii], mtxYpr[ii], 12*sizeof(float) ); + lightView[ii][12] = tmp[0]; + lightView[ii][13] = tmp[1]; + lightView[ii][14] = tmp[2]; + lightView[ii][15] = 1.0f; + } } - else + else // LightType::DirectionalLight == settings.m_lightType { - bgfx::setViewTransform(RENDERVIEW_SHADOWMAP_3_ID, lightView[TetrahedronFaces::Blue], lightProj[ProjType::Horizontal]); - bgfx::setViewTransform(RENDERVIEW_SHADOWMAP_4_ID, lightView[TetrahedronFaces::Red], lightProj[ProjType::Horizontal]); - } - bgfx::setViewTransform(RENDERVIEW_VBLUR_0_ID, screenView, screenProj); - bgfx::setViewTransform(RENDERVIEW_HBLUR_0_ID, screenView, screenProj); - bgfx::setViewTransform(RENDERVIEW_DRAWSCENE_0_ID, viewState.m_view, viewState.m_proj); - bgfx::setViewTransform(RENDERVIEW_DRAWSCENE_1_ID, viewState.m_view, viewState.m_proj); - bgfx::setViewTransform(RENDERVIEW_DRAWDEPTH_0_ID, screenView, screenProj); - - bgfx::setViewFrameBuffer(RENDERVIEW_SHADOWMAP_0_ID, s_rtShadowMap[0]); - bgfx::setViewFrameBuffer(RENDERVIEW_SHADOWMAP_1_ID, s_rtShadowMap[0]); - bgfx::setViewFrameBuffer(RENDERVIEW_SHADOWMAP_2_ID, s_rtShadowMap[0]); - bgfx::setViewFrameBuffer(RENDERVIEW_SHADOWMAP_3_ID, s_rtShadowMap[0]); - bgfx::setViewFrameBuffer(RENDERVIEW_SHADOWMAP_4_ID, s_rtShadowMap[0]); - bgfx::setViewFrameBuffer(RENDERVIEW_VBLUR_0_ID, s_rtBlur); - bgfx::setViewFrameBuffer(RENDERVIEW_HBLUR_0_ID, s_rtShadowMap[0]); - } - else // LightType::DirectionalLight == settings.m_lightType - { - /** - * RENDERVIEW_SHADOWMAP_1_ID - Craft shadow map for first split. - * RENDERVIEW_SHADOWMAP_2_ID - Craft shadow map for second split. - * RENDERVIEW_SHADOWMAP_3_ID - Craft shadow map for third split. - * RENDERVIEW_SHADOWMAP_4_ID - Craft shadow map for fourth split. - * RENDERVIEW_VBLUR_0_ID - Vertical blur for first split. - * RENDERVIEW_HBLUR_0_ID - Horizontal blur for first split. - * RENDERVIEW_VBLUR_1_ID - Vertical blur for second split. - * RENDERVIEW_HBLUR_1_ID - Horizontal blur for second split. - * RENDERVIEW_VBLUR_2_ID - Vertical blur for third split. - * RENDERVIEW_HBLUR_2_ID - Horizontal blur for third split. - * RENDERVIEW_VBLUR_3_ID - Vertical blur for fourth split. - * RENDERVIEW_HBLUR_3_ID - Horizontal blur for fourth split. - * RENDERVIEW_DRAWSCENE_0_ID - Draw scene. - * RENDERVIEW_DRAWSCENE_1_ID - Draw floor bottom. - * RENDERVIEW_DRAWDEPTH_0_ID - Draw depth buffer for first split. - * RENDERVIEW_DRAWDEPTH_1_ID - Draw depth buffer for second split. - * RENDERVIEW_DRAWDEPTH_2_ID - Draw depth buffer for third split. - * RENDERVIEW_DRAWDEPTH_3_ID - Draw depth buffer for fourth split. - */ - - depthRectHeight = viewState.m_height / 3; - depthRectWidth = depthRectHeight; - depthRectX = 0; - depthRectY = viewState.m_height - depthRectHeight; - - bgfx::setViewRect(RENDERVIEW_SHADOWMAP_1_ID, 0, 0, currentShadowMapSize, currentShadowMapSize); - bgfx::setViewRect(RENDERVIEW_SHADOWMAP_2_ID, 0, 0, currentShadowMapSize, currentShadowMapSize); - bgfx::setViewRect(RENDERVIEW_SHADOWMAP_3_ID, 0, 0, currentShadowMapSize, currentShadowMapSize); - bgfx::setViewRect(RENDERVIEW_SHADOWMAP_4_ID, 0, 0, currentShadowMapSize, currentShadowMapSize); - bgfx::setViewRect(RENDERVIEW_VBLUR_0_ID, 0, 0, currentShadowMapSize, currentShadowMapSize); - bgfx::setViewRect(RENDERVIEW_HBLUR_0_ID, 0, 0, currentShadowMapSize, currentShadowMapSize); - bgfx::setViewRect(RENDERVIEW_VBLUR_1_ID, 0, 0, currentShadowMapSize, currentShadowMapSize); - bgfx::setViewRect(RENDERVIEW_HBLUR_1_ID, 0, 0, currentShadowMapSize, currentShadowMapSize); - bgfx::setViewRect(RENDERVIEW_VBLUR_2_ID, 0, 0, currentShadowMapSize, currentShadowMapSize); - bgfx::setViewRect(RENDERVIEW_HBLUR_2_ID, 0, 0, currentShadowMapSize, currentShadowMapSize); - bgfx::setViewRect(RENDERVIEW_VBLUR_3_ID, 0, 0, currentShadowMapSize, currentShadowMapSize); - bgfx::setViewRect(RENDERVIEW_HBLUR_3_ID, 0, 0, currentShadowMapSize, currentShadowMapSize); - bgfx::setViewRect(RENDERVIEW_DRAWSCENE_0_ID, 0, 0, viewState.m_width, viewState.m_height); - bgfx::setViewRect(RENDERVIEW_DRAWSCENE_1_ID, 0, 0, viewState.m_width, viewState.m_height); - bgfx::setViewRect(RENDERVIEW_DRAWDEPTH_0_ID, depthRectX+(0*depthRectWidth), depthRectY, depthRectWidth, depthRectHeight); - bgfx::setViewRect(RENDERVIEW_DRAWDEPTH_1_ID, depthRectX+(1*depthRectWidth), depthRectY, depthRectWidth, depthRectHeight); - bgfx::setViewRect(RENDERVIEW_DRAWDEPTH_2_ID, depthRectX+(2*depthRectWidth), depthRectY, depthRectWidth, depthRectHeight); - bgfx::setViewRect(RENDERVIEW_DRAWDEPTH_3_ID, depthRectX+(3*depthRectWidth), depthRectY, depthRectWidth, depthRectHeight); - - bgfx::setViewTransform(RENDERVIEW_SHADOWMAP_1_ID, lightView[0], lightProj[0]); - bgfx::setViewTransform(RENDERVIEW_SHADOWMAP_2_ID, lightView[0], lightProj[1]); - bgfx::setViewTransform(RENDERVIEW_SHADOWMAP_3_ID, lightView[0], lightProj[2]); - bgfx::setViewTransform(RENDERVIEW_SHADOWMAP_4_ID, lightView[0], lightProj[3]); - bgfx::setViewTransform(RENDERVIEW_VBLUR_0_ID, screenView, screenProj); - bgfx::setViewTransform(RENDERVIEW_HBLUR_0_ID, screenView, screenProj); - bgfx::setViewTransform(RENDERVIEW_VBLUR_1_ID, screenView, screenProj); - bgfx::setViewTransform(RENDERVIEW_HBLUR_1_ID, screenView, screenProj); - bgfx::setViewTransform(RENDERVIEW_VBLUR_2_ID, screenView, screenProj); - bgfx::setViewTransform(RENDERVIEW_HBLUR_2_ID, screenView, screenProj); - bgfx::setViewTransform(RENDERVIEW_VBLUR_3_ID, screenView, screenProj); - bgfx::setViewTransform(RENDERVIEW_HBLUR_3_ID, screenView, screenProj); - bgfx::setViewTransform(RENDERVIEW_DRAWSCENE_0_ID, viewState.m_view, viewState.m_proj); - bgfx::setViewTransform(RENDERVIEW_DRAWSCENE_1_ID, viewState.m_view, viewState.m_proj); - bgfx::setViewTransform(RENDERVIEW_DRAWDEPTH_0_ID, screenView, screenProj); - bgfx::setViewTransform(RENDERVIEW_DRAWDEPTH_1_ID, screenView, screenProj); - bgfx::setViewTransform(RENDERVIEW_DRAWDEPTH_2_ID, screenView, screenProj); - bgfx::setViewTransform(RENDERVIEW_DRAWDEPTH_3_ID, screenView, screenProj); - - bgfx::setViewFrameBuffer(RENDERVIEW_SHADOWMAP_1_ID, s_rtShadowMap[0]); - bgfx::setViewFrameBuffer(RENDERVIEW_SHADOWMAP_2_ID, s_rtShadowMap[1]); - bgfx::setViewFrameBuffer(RENDERVIEW_SHADOWMAP_3_ID, s_rtShadowMap[2]); - bgfx::setViewFrameBuffer(RENDERVIEW_SHADOWMAP_4_ID, s_rtShadowMap[3]); - bgfx::setViewFrameBuffer(RENDERVIEW_VBLUR_0_ID, s_rtBlur); //vblur - bgfx::setViewFrameBuffer(RENDERVIEW_HBLUR_0_ID, s_rtShadowMap[0]); //hblur - bgfx::setViewFrameBuffer(RENDERVIEW_VBLUR_1_ID, s_rtBlur); //vblur - bgfx::setViewFrameBuffer(RENDERVIEW_HBLUR_1_ID, s_rtShadowMap[1]); //hblur - bgfx::setViewFrameBuffer(RENDERVIEW_VBLUR_2_ID, s_rtBlur); //vblur - bgfx::setViewFrameBuffer(RENDERVIEW_HBLUR_2_ID, s_rtShadowMap[2]); //hblur - bgfx::setViewFrameBuffer(RENDERVIEW_VBLUR_3_ID, s_rtBlur); //vblur - bgfx::setViewFrameBuffer(RENDERVIEW_HBLUR_3_ID, s_rtShadowMap[3]); //hblur - } + // Setup light view mtx. + float eye[3] = + { + -m_directionalLight.m_position.m_x + , -m_directionalLight.m_position.m_y + , -m_directionalLight.m_position.m_z + }; + float at[3] = { 0.0f, 0.0f, 0.0f }; + bx::mtxLookAt(lightView[0], eye, at); + + // Compute camera inverse view mtx. + float mtxViewInv[16]; + bx::mtxInverse(mtxViewInv, m_viewState.m_view); + + // Compute split distances. + const uint8_t maxNumSplits = 4; + BX_CHECK(maxNumSplits >= settings.m_numSplits, "Error! Max num splits."); + + float splitSlices[maxNumSplits*2]; + splitFrustum(splitSlices + , uint8_t(m_settings.m_numSplits) + , currentSmSettings->m_near + , currentSmSettings->m_far + , m_settings.m_splitDistribution + ); - // Clear backbuffer at beginning. - bgfx::setViewClear(0 - , BGFX_CLEAR_COLOR - | BGFX_CLEAR_DEPTH - , clearValues.m_clearRgba - , clearValues.m_clearDepth - , clearValues.m_clearStencil - ); - bgfx::touch(0); - - // Clear shadowmap rendertarget at beginning. - const uint8_t flags0 = (LightType::DirectionalLight == settings.m_lightType) - ? 0 - : BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH | BGFX_CLEAR_STENCIL - ; - - bgfx::setViewClear(RENDERVIEW_SHADOWMAP_0_ID - , flags0 - , 0xfefefefe //blur fails on completely white regions - , clearValues.m_clearDepth - , clearValues.m_clearStencil - ); - bgfx::touch(RENDERVIEW_SHADOWMAP_0_ID); + // Update uniforms. + for (uint8_t ii = 0, ff = 1; ii < m_settings.m_numSplits; ++ii, ff+=2) + { + // This lags for 1 frame, but it's not a problem. + s_uniforms.m_csmFarDistances[ii] = splitSlices[ff]; + } - const uint8_t flags1 = (LightType::DirectionalLight == settings.m_lightType) - ? BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH - : 0 - ; + float mtxProj[16]; + bx::mtxOrtho( + mtxProj + , 1.0f + , -1.0f + , 1.0f + , -1.0f + , -currentSmSettings->m_far + , currentSmSettings->m_far + , 0.0f + , caps->homogeneousDepth + ); + + const uint8_t numCorners = 8; + float frustumCorners[maxNumSplits][numCorners][3]; + for (uint8_t ii = 0, nn = 0, ff = 1; ii < m_settings.m_numSplits; ++ii, nn+=2, ff+=2) + { + // Compute frustum corners for one split in world space. + worldSpaceFrustumCorners( (float*)frustumCorners[ii], splitSlices[nn], splitSlices[ff], projWidth, projHeight, mtxViewInv); - for (uint8_t ii = 0; ii < 4; ++ii) - { - bgfx::setViewClear(RENDERVIEW_SHADOWMAP_1_ID+ii - , flags1 - , 0xfefefefe //blur fails on completely white regions - , clearValues.m_clearDepth - , clearValues.m_clearStencil - ); - bgfx::touch(RENDERVIEW_SHADOWMAP_1_ID+ii); - } + float min[3] = { 9000.0f, 9000.0f, 9000.0f }; + float max[3] = { -9000.0f, -9000.0f, -9000.0f }; + + for (uint8_t jj = 0; jj < numCorners; ++jj) + { + // Transform to light space. + float lightSpaceFrustumCorner[3]; + bx::vec3MulMtx(lightSpaceFrustumCorner, frustumCorners[ii][jj], lightView[0]); + + // Update bounding box. + min[0] = bx::fmin(min[0], lightSpaceFrustumCorner[0]); + max[0] = bx::fmax(max[0], lightSpaceFrustumCorner[0]); + min[1] = bx::fmin(min[1], lightSpaceFrustumCorner[1]); + max[1] = bx::fmax(max[1], lightSpaceFrustumCorner[1]); + min[2] = bx::fmin(min[2], lightSpaceFrustumCorner[2]); + max[2] = bx::fmax(max[2], lightSpaceFrustumCorner[2]); + } - // Render. + float minproj[3]; + float maxproj[3]; + bx::vec3MulMtxH(minproj, min, mtxProj); + bx::vec3MulMtxH(maxproj, max, mtxProj); - // Craft shadow map. - { - // Craft stencil mask for point light shadow map packing. - if(LightType::PointLight == settings.m_lightType && settings.m_stencilPack) - { - if (6 == bgfx::getAvailTransientVertexBuffer(6, posDecl) ) - { - struct Pos + float offsetx, offsety; + float scalex, scaley; + + scalex = 2.0f / (maxproj[0] - minproj[0]); + scaley = 2.0f / (maxproj[1] - minproj[1]); + + if (m_settings.m_stabilize) { - float m_x, m_y, m_z; - }; + const float quantizer = 64.0f; + scalex = quantizer / bx::fceil(quantizer / scalex); + scaley = quantizer / bx::fceil(quantizer / scaley); + } - bgfx::TransientVertexBuffer vb; - bgfx::allocTransientVertexBuffer(&vb, 6, posDecl); - Pos* vertex = (Pos*)vb.data; - - const float min = 0.0f; - const float max = 1.0f; - const float center = 0.5f; - const float zz = 0.0f; - - vertex[0].m_x = min; - vertex[0].m_y = min; - vertex[0].m_z = zz; - - vertex[1].m_x = max; - vertex[1].m_y = min; - vertex[1].m_z = zz; - - vertex[2].m_x = center; - vertex[2].m_y = center; - vertex[2].m_z = zz; - - vertex[3].m_x = center; - vertex[3].m_y = center; - vertex[3].m_z = zz; - - vertex[4].m_x = max; - vertex[4].m_y = max; - vertex[4].m_z = zz; - - vertex[5].m_x = min; - vertex[5].m_y = max; - vertex[5].m_z = zz; - - bgfx::setState(0); - bgfx::setStencil(BGFX_STENCIL_TEST_ALWAYS - | BGFX_STENCIL_FUNC_REF(1) - | BGFX_STENCIL_FUNC_RMASK(0xff) - | BGFX_STENCIL_OP_FAIL_S_REPLACE - | BGFX_STENCIL_OP_FAIL_Z_REPLACE - | BGFX_STENCIL_OP_PASS_Z_REPLACE - ); - bgfx::setVertexBuffer(&vb); - bgfx::submit(RENDERVIEW_SHADOWMAP_0_ID, s_programs.m_black); + offsetx = 0.5f * (maxproj[0] + minproj[0]) * scalex; + offsety = 0.5f * (maxproj[1] + minproj[1]) * scaley; + + if (m_settings.m_stabilize) + { + const float halfSize = currentShadowMapSizef * 0.5f; + offsetx = bx::fceil(offsetx * halfSize) / halfSize; + offsety = bx::fceil(offsety * halfSize) / halfSize; + } + + float mtxCrop[16]; + bx::mtxIdentity(mtxCrop); + mtxCrop[ 0] = scalex; + mtxCrop[ 5] = scaley; + mtxCrop[12] = offsetx; + mtxCrop[13] = offsety; + + bx::mtxMul(lightProj[ii], mtxCrop, mtxProj); } } - // Draw scene into shadowmap. - uint8_t drawNum; - if (LightType::SpotLight == settings.m_lightType) + // Reset render targets. + const bgfx::FrameBufferHandle invalidRt = BGFX_INVALID_HANDLE; + for (uint8_t ii = 0; ii < RENDERVIEW_DRAWDEPTH_3_ID+1; ++ii) { - drawNum = 1; + bgfx::setViewFrameBuffer(ii, invalidRt); } - else if (LightType::PointLight == settings.m_lightType) + + // Determine on-screen rectangle size where depth buffer will be drawn. + uint16_t depthRectHeight = uint16_t(float(m_viewState.m_height) / 2.5f); + uint16_t depthRectWidth = depthRectHeight; + uint16_t depthRectX = 0; + uint16_t depthRectY = m_viewState.m_height - depthRectHeight; + + // Setup views and render targets. + bgfx::setViewRect(0, 0, 0, m_viewState.m_width, m_viewState.m_height); + bgfx::setViewTransform(0, m_viewState.m_view, m_viewState.m_proj); + + if (LightType::SpotLight == m_settings.m_lightType) { - drawNum = 4; + /** + * RENDERVIEW_SHADOWMAP_0_ID - Clear shadow map. (used as convenience, otherwise render_pass_1 could be cleared) + * RENDERVIEW_SHADOWMAP_1_ID - Craft shadow map. + * RENDERVIEW_VBLUR_0_ID - Vertical blur. + * RENDERVIEW_HBLUR_0_ID - Horizontal blur. + * RENDERVIEW_DRAWSCENE_0_ID - Draw scene. + * RENDERVIEW_DRAWSCENE_1_ID - Draw floor bottom. + * RENDERVIEW_DRAWDEPTH_0_ID - Draw depth buffer. + */ + + bgfx::setViewRect(RENDERVIEW_SHADOWMAP_0_ID, 0, 0, m_currentShadowMapSize, m_currentShadowMapSize); + bgfx::setViewRect(RENDERVIEW_SHADOWMAP_1_ID, 0, 0, m_currentShadowMapSize, m_currentShadowMapSize); + bgfx::setViewRect(RENDERVIEW_VBLUR_0_ID, 0, 0, m_currentShadowMapSize, m_currentShadowMapSize); + bgfx::setViewRect(RENDERVIEW_HBLUR_0_ID, 0, 0, m_currentShadowMapSize, m_currentShadowMapSize); + bgfx::setViewRect(RENDERVIEW_DRAWSCENE_0_ID, 0, 0, m_viewState.m_width, m_viewState.m_height); + bgfx::setViewRect(RENDERVIEW_DRAWSCENE_1_ID, 0, 0, m_viewState.m_width, m_viewState.m_height); + bgfx::setViewRect(RENDERVIEW_DRAWDEPTH_0_ID, depthRectX, depthRectY, depthRectWidth, depthRectHeight); + + bgfx::setViewTransform(RENDERVIEW_SHADOWMAP_0_ID, screenView, screenProj); + bgfx::setViewTransform(RENDERVIEW_SHADOWMAP_1_ID, lightView[0], lightProj[ProjType::Horizontal]); + bgfx::setViewTransform(RENDERVIEW_VBLUR_0_ID, screenView, screenProj); + bgfx::setViewTransform(RENDERVIEW_HBLUR_0_ID, screenView, screenProj); + bgfx::setViewTransform(RENDERVIEW_DRAWSCENE_0_ID, m_viewState.m_view, m_viewState.m_proj); + bgfx::setViewTransform(RENDERVIEW_DRAWSCENE_1_ID, m_viewState.m_view, m_viewState.m_proj); + bgfx::setViewTransform(RENDERVIEW_DRAWDEPTH_0_ID, screenView, screenProj); + + bgfx::setViewFrameBuffer(RENDERVIEW_SHADOWMAP_0_ID, s_rtShadowMap[0]); + bgfx::setViewFrameBuffer(RENDERVIEW_SHADOWMAP_1_ID, s_rtShadowMap[0]); + bgfx::setViewFrameBuffer(RENDERVIEW_VBLUR_0_ID, s_rtBlur); + bgfx::setViewFrameBuffer(RENDERVIEW_HBLUR_0_ID, s_rtShadowMap[0]); + } + else if (LightType::PointLight == m_settings.m_lightType) + { + /** + * RENDERVIEW_SHADOWMAP_0_ID - Clear entire shadow map. + * RENDERVIEW_SHADOWMAP_1_ID - Craft green tetrahedron shadow face. + * RENDERVIEW_SHADOWMAP_2_ID - Craft yellow tetrahedron shadow face. + * RENDERVIEW_SHADOWMAP_3_ID - Craft blue tetrahedron shadow face. + * RENDERVIEW_SHADOWMAP_4_ID - Craft red tetrahedron shadow face. + * RENDERVIEW_VBLUR_0_ID - Vertical blur. + * RENDERVIEW_HBLUR_0_ID - Horizontal blur. + * RENDERVIEW_DRAWSCENE_0_ID - Draw scene. + * RENDERVIEW_DRAWSCENE_1_ID - Draw floor bottom. + * RENDERVIEW_DRAWDEPTH_0_ID - Draw depth buffer. + */ + + bgfx::setViewRect(RENDERVIEW_SHADOWMAP_0_ID, 0, 0, m_currentShadowMapSize, m_currentShadowMapSize); + if (m_settings.m_stencilPack) + { + const uint16_t f = m_currentShadowMapSize; //full size + const uint16_t h = m_currentShadowMapSize/2; //half size + bgfx::setViewRect(RENDERVIEW_SHADOWMAP_1_ID, 0, 0, f, h); + bgfx::setViewRect(RENDERVIEW_SHADOWMAP_2_ID, 0, h, f, h); + bgfx::setViewRect(RENDERVIEW_SHADOWMAP_3_ID, 0, 0, h, f); + bgfx::setViewRect(RENDERVIEW_SHADOWMAP_4_ID, h, 0, h, f); + } + else + { + const uint16_t h = m_currentShadowMapSize/2; //half size + bgfx::setViewRect(RENDERVIEW_SHADOWMAP_1_ID, 0, 0, h, h); + bgfx::setViewRect(RENDERVIEW_SHADOWMAP_2_ID, h, 0, h, h); + bgfx::setViewRect(RENDERVIEW_SHADOWMAP_3_ID, 0, h, h, h); + bgfx::setViewRect(RENDERVIEW_SHADOWMAP_4_ID, h, h, h, h); + } + bgfx::setViewRect(RENDERVIEW_VBLUR_0_ID, 0, 0, m_currentShadowMapSize, m_currentShadowMapSize); + bgfx::setViewRect(RENDERVIEW_HBLUR_0_ID, 0, 0, m_currentShadowMapSize, m_currentShadowMapSize); + bgfx::setViewRect(RENDERVIEW_DRAWSCENE_0_ID, 0, 0, m_viewState.m_width, m_viewState.m_height); + bgfx::setViewRect(RENDERVIEW_DRAWSCENE_1_ID, 0, 0, m_viewState.m_width, m_viewState.m_height); + bgfx::setViewRect(RENDERVIEW_DRAWDEPTH_0_ID, depthRectX, depthRectY, depthRectWidth, depthRectHeight); + + bgfx::setViewTransform(RENDERVIEW_SHADOWMAP_0_ID, screenView, screenProj); + bgfx::setViewTransform(RENDERVIEW_SHADOWMAP_1_ID, lightView[TetrahedronFaces::Green], lightProj[ProjType::Horizontal]); + bgfx::setViewTransform(RENDERVIEW_SHADOWMAP_2_ID, lightView[TetrahedronFaces::Yellow], lightProj[ProjType::Horizontal]); + if(m_settings.m_stencilPack) + { + bgfx::setViewTransform(RENDERVIEW_SHADOWMAP_3_ID, lightView[TetrahedronFaces::Blue], lightProj[ProjType::Vertical]); + bgfx::setViewTransform(RENDERVIEW_SHADOWMAP_4_ID, lightView[TetrahedronFaces::Red], lightProj[ProjType::Vertical]); + } + else + { + bgfx::setViewTransform(RENDERVIEW_SHADOWMAP_3_ID, lightView[TetrahedronFaces::Blue], lightProj[ProjType::Horizontal]); + bgfx::setViewTransform(RENDERVIEW_SHADOWMAP_4_ID, lightView[TetrahedronFaces::Red], lightProj[ProjType::Horizontal]); + } + bgfx::setViewTransform(RENDERVIEW_VBLUR_0_ID, screenView, screenProj); + bgfx::setViewTransform(RENDERVIEW_HBLUR_0_ID, screenView, screenProj); + bgfx::setViewTransform(RENDERVIEW_DRAWSCENE_0_ID, m_viewState.m_view, m_viewState.m_proj); + bgfx::setViewTransform(RENDERVIEW_DRAWSCENE_1_ID, m_viewState.m_view, m_viewState.m_proj); + bgfx::setViewTransform(RENDERVIEW_DRAWDEPTH_0_ID, screenView, screenProj); + + bgfx::setViewFrameBuffer(RENDERVIEW_SHADOWMAP_0_ID, s_rtShadowMap[0]); + bgfx::setViewFrameBuffer(RENDERVIEW_SHADOWMAP_1_ID, s_rtShadowMap[0]); + bgfx::setViewFrameBuffer(RENDERVIEW_SHADOWMAP_2_ID, s_rtShadowMap[0]); + bgfx::setViewFrameBuffer(RENDERVIEW_SHADOWMAP_3_ID, s_rtShadowMap[0]); + bgfx::setViewFrameBuffer(RENDERVIEW_SHADOWMAP_4_ID, s_rtShadowMap[0]); + bgfx::setViewFrameBuffer(RENDERVIEW_VBLUR_0_ID, s_rtBlur); + bgfx::setViewFrameBuffer(RENDERVIEW_HBLUR_0_ID, s_rtShadowMap[0]); } - else //LightType::DirectionalLight == settings.m_lightType) + else // LightType::DirectionalLight == settings.m_lightType { - drawNum = settings.m_numSplits; + /** + * RENDERVIEW_SHADOWMAP_1_ID - Craft shadow map for first split. + * RENDERVIEW_SHADOWMAP_2_ID - Craft shadow map for second split. + * RENDERVIEW_SHADOWMAP_3_ID - Craft shadow map for third split. + * RENDERVIEW_SHADOWMAP_4_ID - Craft shadow map for fourth split. + * RENDERVIEW_VBLUR_0_ID - Vertical blur for first split. + * RENDERVIEW_HBLUR_0_ID - Horizontal blur for first split. + * RENDERVIEW_VBLUR_1_ID - Vertical blur for second split. + * RENDERVIEW_HBLUR_1_ID - Horizontal blur for second split. + * RENDERVIEW_VBLUR_2_ID - Vertical blur for third split. + * RENDERVIEW_HBLUR_2_ID - Horizontal blur for third split. + * RENDERVIEW_VBLUR_3_ID - Vertical blur for fourth split. + * RENDERVIEW_HBLUR_3_ID - Horizontal blur for fourth split. + * RENDERVIEW_DRAWSCENE_0_ID - Draw scene. + * RENDERVIEW_DRAWSCENE_1_ID - Draw floor bottom. + * RENDERVIEW_DRAWDEPTH_0_ID - Draw depth buffer for first split. + * RENDERVIEW_DRAWDEPTH_1_ID - Draw depth buffer for second split. + * RENDERVIEW_DRAWDEPTH_2_ID - Draw depth buffer for third split. + * RENDERVIEW_DRAWDEPTH_3_ID - Draw depth buffer for fourth split. + */ + + depthRectHeight = m_viewState.m_height / 3; + depthRectWidth = depthRectHeight; + depthRectX = 0; + depthRectY = m_viewState.m_height - depthRectHeight; + + bgfx::setViewRect(RENDERVIEW_SHADOWMAP_1_ID, 0, 0, m_currentShadowMapSize, m_currentShadowMapSize); + bgfx::setViewRect(RENDERVIEW_SHADOWMAP_2_ID, 0, 0, m_currentShadowMapSize, m_currentShadowMapSize); + bgfx::setViewRect(RENDERVIEW_SHADOWMAP_3_ID, 0, 0, m_currentShadowMapSize, m_currentShadowMapSize); + bgfx::setViewRect(RENDERVIEW_SHADOWMAP_4_ID, 0, 0, m_currentShadowMapSize, m_currentShadowMapSize); + bgfx::setViewRect(RENDERVIEW_VBLUR_0_ID, 0, 0, m_currentShadowMapSize, m_currentShadowMapSize); + bgfx::setViewRect(RENDERVIEW_HBLUR_0_ID, 0, 0, m_currentShadowMapSize, m_currentShadowMapSize); + bgfx::setViewRect(RENDERVIEW_VBLUR_1_ID, 0, 0, m_currentShadowMapSize, m_currentShadowMapSize); + bgfx::setViewRect(RENDERVIEW_HBLUR_1_ID, 0, 0, m_currentShadowMapSize, m_currentShadowMapSize); + bgfx::setViewRect(RENDERVIEW_VBLUR_2_ID, 0, 0, m_currentShadowMapSize, m_currentShadowMapSize); + bgfx::setViewRect(RENDERVIEW_HBLUR_2_ID, 0, 0, m_currentShadowMapSize, m_currentShadowMapSize); + bgfx::setViewRect(RENDERVIEW_VBLUR_3_ID, 0, 0, m_currentShadowMapSize, m_currentShadowMapSize); + bgfx::setViewRect(RENDERVIEW_HBLUR_3_ID, 0, 0, m_currentShadowMapSize, m_currentShadowMapSize); + bgfx::setViewRect(RENDERVIEW_DRAWSCENE_0_ID, 0, 0, m_viewState.m_width, m_viewState.m_height); + bgfx::setViewRect(RENDERVIEW_DRAWSCENE_1_ID, 0, 0, m_viewState.m_width, m_viewState.m_height); + bgfx::setViewRect(RENDERVIEW_DRAWDEPTH_0_ID, depthRectX+(0*depthRectWidth), depthRectY, depthRectWidth, depthRectHeight); + bgfx::setViewRect(RENDERVIEW_DRAWDEPTH_1_ID, depthRectX+(1*depthRectWidth), depthRectY, depthRectWidth, depthRectHeight); + bgfx::setViewRect(RENDERVIEW_DRAWDEPTH_2_ID, depthRectX+(2*depthRectWidth), depthRectY, depthRectWidth, depthRectHeight); + bgfx::setViewRect(RENDERVIEW_DRAWDEPTH_3_ID, depthRectX+(3*depthRectWidth), depthRectY, depthRectWidth, depthRectHeight); + + bgfx::setViewTransform(RENDERVIEW_SHADOWMAP_1_ID, lightView[0], lightProj[0]); + bgfx::setViewTransform(RENDERVIEW_SHADOWMAP_2_ID, lightView[0], lightProj[1]); + bgfx::setViewTransform(RENDERVIEW_SHADOWMAP_3_ID, lightView[0], lightProj[2]); + bgfx::setViewTransform(RENDERVIEW_SHADOWMAP_4_ID, lightView[0], lightProj[3]); + bgfx::setViewTransform(RENDERVIEW_VBLUR_0_ID, screenView, screenProj); + bgfx::setViewTransform(RENDERVIEW_HBLUR_0_ID, screenView, screenProj); + bgfx::setViewTransform(RENDERVIEW_VBLUR_1_ID, screenView, screenProj); + bgfx::setViewTransform(RENDERVIEW_HBLUR_1_ID, screenView, screenProj); + bgfx::setViewTransform(RENDERVIEW_VBLUR_2_ID, screenView, screenProj); + bgfx::setViewTransform(RENDERVIEW_HBLUR_2_ID, screenView, screenProj); + bgfx::setViewTransform(RENDERVIEW_VBLUR_3_ID, screenView, screenProj); + bgfx::setViewTransform(RENDERVIEW_HBLUR_3_ID, screenView, screenProj); + bgfx::setViewTransform(RENDERVIEW_DRAWSCENE_0_ID, m_viewState.m_view, m_viewState.m_proj); + bgfx::setViewTransform(RENDERVIEW_DRAWSCENE_1_ID, m_viewState.m_view, m_viewState.m_proj); + bgfx::setViewTransform(RENDERVIEW_DRAWDEPTH_0_ID, screenView, screenProj); + bgfx::setViewTransform(RENDERVIEW_DRAWDEPTH_1_ID, screenView, screenProj); + bgfx::setViewTransform(RENDERVIEW_DRAWDEPTH_2_ID, screenView, screenProj); + bgfx::setViewTransform(RENDERVIEW_DRAWDEPTH_3_ID, screenView, screenProj); + + bgfx::setViewFrameBuffer(RENDERVIEW_SHADOWMAP_1_ID, s_rtShadowMap[0]); + bgfx::setViewFrameBuffer(RENDERVIEW_SHADOWMAP_2_ID, s_rtShadowMap[1]); + bgfx::setViewFrameBuffer(RENDERVIEW_SHADOWMAP_3_ID, s_rtShadowMap[2]); + bgfx::setViewFrameBuffer(RENDERVIEW_SHADOWMAP_4_ID, s_rtShadowMap[3]); + bgfx::setViewFrameBuffer(RENDERVIEW_VBLUR_0_ID, s_rtBlur); //vblur + bgfx::setViewFrameBuffer(RENDERVIEW_HBLUR_0_ID, s_rtShadowMap[0]); //hblur + bgfx::setViewFrameBuffer(RENDERVIEW_VBLUR_1_ID, s_rtBlur); //vblur + bgfx::setViewFrameBuffer(RENDERVIEW_HBLUR_1_ID, s_rtShadowMap[1]); //hblur + bgfx::setViewFrameBuffer(RENDERVIEW_VBLUR_2_ID, s_rtBlur); //vblur + bgfx::setViewFrameBuffer(RENDERVIEW_HBLUR_2_ID, s_rtShadowMap[2]); //hblur + bgfx::setViewFrameBuffer(RENDERVIEW_VBLUR_3_ID, s_rtBlur); //vblur + bgfx::setViewFrameBuffer(RENDERVIEW_HBLUR_3_ID, s_rtShadowMap[3]); //hblur } - for (uint8_t ii = 0; ii < drawNum; ++ii) + // Clear backbuffer at beginning. + bgfx::setViewClear(0 + , BGFX_CLEAR_COLOR + | BGFX_CLEAR_DEPTH + , m_clearValues.m_clearRgba + , m_clearValues.m_clearDepth + , m_clearValues.m_clearStencil + ); + bgfx::touch(0); + + // Clear shadowmap rendertarget at beginning. + const uint8_t flags0 = (LightType::DirectionalLight == m_settings.m_lightType) + ? 0 + : BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH | BGFX_CLEAR_STENCIL + ; + + bgfx::setViewClear(RENDERVIEW_SHADOWMAP_0_ID + , flags0 + , 0xfefefefe //blur fails on completely white regions + , m_clearValues.m_clearDepth + , m_clearValues.m_clearStencil + ); + bgfx::touch(RENDERVIEW_SHADOWMAP_0_ID); + + const uint8_t flags1 = (LightType::DirectionalLight == m_settings.m_lightType) + ? BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH + : 0 + ; + + for (uint8_t ii = 0; ii < 4; ++ii) { - const uint8_t viewId = RENDERVIEW_SHADOWMAP_1_ID + ii; + bgfx::setViewClear(RENDERVIEW_SHADOWMAP_1_ID+ii + , flags1 + , 0xfefefefe //blur fails on completely white regions + , m_clearValues.m_clearDepth + , m_clearValues.m_clearStencil + ); + bgfx::touch(RENDERVIEW_SHADOWMAP_1_ID+ii); + } - uint8_t renderStateIndex = RenderState::ShadowMap_PackDepth; - if(LightType::PointLight == settings.m_lightType && settings.m_stencilPack) + // Render. + + // Craft shadow map. + { + // Craft stencil mask for point light shadow map packing. + if(LightType::PointLight == m_settings.m_lightType && m_settings.m_stencilPack) { - renderStateIndex = uint8_t( (ii < 2) ? RenderState::ShadowMap_PackDepthHoriz : RenderState::ShadowMap_PackDepthVert); - } + if (6 == bgfx::getAvailTransientVertexBuffer(6, m_posDecl) ) + { + struct Pos + { + float m_x, m_y, m_z; + }; - // Floor. - hplaneMesh.submit(viewId - , mtxFloor - , *currentSmSettings->m_progPack - , s_renderStates[renderStateIndex] - ); + bgfx::TransientVertexBuffer vb; + bgfx::allocTransientVertexBuffer(&vb, 6, m_posDecl); + Pos* vertex = (Pos*)vb.data; + + const float min = 0.0f; + const float max = 1.0f; + const float center = 0.5f; + const float zz = 0.0f; + + vertex[0].m_x = min; + vertex[0].m_y = min; + vertex[0].m_z = zz; + + vertex[1].m_x = max; + vertex[1].m_y = min; + vertex[1].m_z = zz; + + vertex[2].m_x = center; + vertex[2].m_y = center; + vertex[2].m_z = zz; + + vertex[3].m_x = center; + vertex[3].m_y = center; + vertex[3].m_z = zz; + + vertex[4].m_x = max; + vertex[4].m_y = max; + vertex[4].m_z = zz; + + vertex[5].m_x = min; + vertex[5].m_y = max; + vertex[5].m_z = zz; + + bgfx::setState(0); + bgfx::setStencil(BGFX_STENCIL_TEST_ALWAYS + | BGFX_STENCIL_FUNC_REF(1) + | BGFX_STENCIL_FUNC_RMASK(0xff) + | BGFX_STENCIL_OP_FAIL_S_REPLACE + | BGFX_STENCIL_OP_FAIL_Z_REPLACE + | BGFX_STENCIL_OP_PASS_Z_REPLACE + ); + bgfx::setVertexBuffer(0, &vb); + bgfx::submit(RENDERVIEW_SHADOWMAP_0_ID, s_programs.m_black); + } + } - // Bunny. - bunnyMesh.submit(viewId - , mtxBunny - , *currentSmSettings->m_progPack - , s_renderStates[renderStateIndex] - ); + // Draw scene into shadowmap. + uint8_t drawNum; + if (LightType::SpotLight == m_settings.m_lightType) + { + drawNum = 1; + } + else if (LightType::PointLight == m_settings.m_lightType) + { + drawNum = 4; + } + else //LightType::DirectionalLight == settings.m_lightType) + { + drawNum = uint8_t(m_settings.m_numSplits); + } - // Hollow cube. - hollowcubeMesh.submit(viewId - , mtxHollowcube - , *currentSmSettings->m_progPack - , s_renderStates[renderStateIndex] - ); + for (uint8_t ii = 0; ii < drawNum; ++ii) + { + const uint8_t viewId = RENDERVIEW_SHADOWMAP_1_ID + ii; - // Cube. - cubeMesh.submit(viewId - , mtxCube - , *currentSmSettings->m_progPack - , s_renderStates[renderStateIndex] - ); + uint8_t renderStateIndex = RenderState::ShadowMap_PackDepth; + if(LightType::PointLight == m_settings.m_lightType && m_settings.m_stencilPack) + { + renderStateIndex = uint8_t( (ii < 2) ? RenderState::ShadowMap_PackDepthHoriz : RenderState::ShadowMap_PackDepthVert); + } - // Trees. - for (uint8_t jj = 0; jj < numTrees; ++jj) - { - treeMesh.submit(viewId - , mtxTrees[jj] - , *currentSmSettings->m_progPack - , s_renderStates[renderStateIndex] - ); + // Floor. + m_hplaneMesh.submit(viewId + , mtxFloor + , *currentSmSettings->m_progPack + , s_renderStates[renderStateIndex] + ); + + // Bunny. + m_bunnyMesh.submit(viewId + , mtxBunny + , *currentSmSettings->m_progPack + , s_renderStates[renderStateIndex] + ); + + // Hollow cube. + m_hollowcubeMesh.submit(viewId + , mtxHollowcube + , *currentSmSettings->m_progPack + , s_renderStates[renderStateIndex] + ); + + // Cube. + m_cubeMesh.submit(viewId + , mtxCube + , *currentSmSettings->m_progPack + , s_renderStates[renderStateIndex] + ); + + // Trees. + for (uint8_t jj = 0; jj < numTrees; ++jj) + { + m_treeMesh.submit(viewId + , mtxTrees[jj] + , *currentSmSettings->m_progPack + , s_renderStates[renderStateIndex] + ); + } } } - } - PackDepth::Enum depthType = (SmImpl::VSM == settings.m_smImpl) ? PackDepth::VSM : PackDepth::RGBA; - bool bVsmOrEsm = (SmImpl::VSM == settings.m_smImpl) || (SmImpl::ESM == settings.m_smImpl); + PackDepth::Enum depthType = (SmImpl::VSM == m_settings.m_smImpl) ? PackDepth::VSM : PackDepth::RGBA; + bool bVsmOrEsm = (SmImpl::VSM == m_settings.m_smImpl) || (SmImpl::ESM == m_settings.m_smImpl); - // Blur shadow map. - if (bVsmOrEsm - && currentSmSettings->m_doBlur) - { - bgfx::setTexture(4, s_shadowMap[0], bgfx::getTexture(s_rtShadowMap[0]) ); - bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE); - screenSpaceQuad(currentShadowMapSizef, currentShadowMapSizef, s_flipV); - bgfx::submit(RENDERVIEW_VBLUR_0_ID, s_programs.m_vBlur[depthType]); + // Blur shadow map. + if (bVsmOrEsm + && currentSmSettings->m_doBlur) + { + bgfx::setTexture(4, s_shadowMap[0], bgfx::getTexture(s_rtShadowMap[0]) ); + bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE); + screenSpaceQuad(currentShadowMapSizef, currentShadowMapSizef, s_flipV); + bgfx::submit(RENDERVIEW_VBLUR_0_ID, s_programs.m_vBlur[depthType]); - bgfx::setTexture(4, s_shadowMap[0], bgfx::getTexture(s_rtBlur) ); - bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE); - screenSpaceQuad(currentShadowMapSizef, currentShadowMapSizef, s_flipV); - bgfx::submit(RENDERVIEW_HBLUR_0_ID, s_programs.m_hBlur[depthType]); + bgfx::setTexture(4, s_shadowMap[0], bgfx::getTexture(s_rtBlur) ); + bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE); + screenSpaceQuad(currentShadowMapSizef, currentShadowMapSizef, s_flipV); + bgfx::submit(RENDERVIEW_HBLUR_0_ID, s_programs.m_hBlur[depthType]); - if (LightType::DirectionalLight == settings.m_lightType) - { - for (uint8_t ii = 1, jj = 2; ii < settings.m_numSplits; ++ii, jj+=2) + if (LightType::DirectionalLight == m_settings.m_lightType) { - const uint8_t viewId = RENDERVIEW_VBLUR_0_ID + jj; + for (uint8_t ii = 1, jj = 2; ii < m_settings.m_numSplits; ++ii, jj+=2) + { + const uint8_t viewId = RENDERVIEW_VBLUR_0_ID + jj; - bgfx::setTexture(4, s_shadowMap[0], bgfx::getTexture(s_rtShadowMap[ii]) ); - bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE); - screenSpaceQuad(currentShadowMapSizef, currentShadowMapSizef, s_flipV); - bgfx::submit(viewId, s_programs.m_vBlur[depthType]); + bgfx::setTexture(4, s_shadowMap[0], bgfx::getTexture(s_rtShadowMap[ii]) ); + bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE); + screenSpaceQuad(currentShadowMapSizef, currentShadowMapSizef, s_flipV); + bgfx::submit(viewId, s_programs.m_vBlur[depthType]); - bgfx::setTexture(4, s_shadowMap[0], bgfx::getTexture(s_rtBlur) ); - bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE); - screenSpaceQuad(currentShadowMapSizef, currentShadowMapSizef, s_flipV); - bgfx::submit(viewId+1, s_programs.m_hBlur[depthType]); + bgfx::setTexture(4, s_shadowMap[0], bgfx::getTexture(s_rtBlur) ); + bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE); + screenSpaceQuad(currentShadowMapSizef, currentShadowMapSizef, s_flipV); + bgfx::submit(viewId+1, s_programs.m_hBlur[depthType]); + } } } - } - - // Draw scene. - { - // Setup shadow mtx. - float mtxShadow[16]; - - const float ymul = (s_flipV) ? 0.5f : -0.5f; - float zadd = (DepthImpl::Linear == settings.m_depthImpl) ? 0.0f : 0.5f; - const float mtxBias[16] = + // Draw scene. { - 0.5f, 0.0f, 0.0f, 0.0f, - 0.0f, ymul, 0.0f, 0.0f, - 0.0f, 0.0f, 0.5f, 0.0f, - 0.5f, 0.5f, zadd, 1.0f, - }; + // Setup shadow mtx. + float mtxShadow[16]; - if (LightType::SpotLight == settings.m_lightType) - { - float mtxTmp[16]; - bx::mtxMul(mtxTmp, lightProj[ProjType::Horizontal], mtxBias); - bx::mtxMul(mtxShadow, lightView[0], mtxTmp); //lightViewProjBias - } - else if (LightType::PointLight == settings.m_lightType) - { - const float s = (s_flipV) ? 1.0f : -1.0f; //sign - zadd = (DepthImpl::Linear == settings.m_depthImpl) ? 0.0f : 0.5f; + const float ymul = (s_flipV) ? 0.5f : -0.5f; + float zadd = (DepthImpl::Linear == m_settings.m_depthImpl) ? 0.0f : 0.5f; - const float mtxCropBias[2][TetrahedronFaces::Count][16] = + const float mtxBias[16] = { - { // settings.m_stencilPack == false + 0.5f, 0.0f, 0.0f, 0.0f, + 0.0f, ymul, 0.0f, 0.0f, + 0.0f, 0.0f, 0.5f, 0.0f, + 0.5f, 0.5f, zadd, 1.0f, + }; - { // D3D: Green, OGL: Blue - 0.25f, 0.0f, 0.0f, 0.0f, + if (LightType::SpotLight == m_settings.m_lightType) + { + float mtxTmp[16]; + bx::mtxMul(mtxTmp, lightProj[ProjType::Horizontal], mtxBias); + bx::mtxMul(mtxShadow, lightView[0], mtxTmp); //lightViewProjBias + } + else if (LightType::PointLight == m_settings.m_lightType) + { + const float s = (s_flipV) ? 1.0f : -1.0f; //sign + zadd = (DepthImpl::Linear == m_settings.m_depthImpl) ? 0.0f : 0.5f; + + const float mtxCropBias[2][TetrahedronFaces::Count][16] = + { + { // settings.m_stencilPack == false + + { // D3D: Green, OGL: Blue + 0.25f, 0.0f, 0.0f, 0.0f, 0.0f, s*0.25f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, - 0.25f, 0.25f, zadd, 1.0f, - }, - { // D3D: Yellow, OGL: Red - 0.25f, 0.0f, 0.0f, 0.0f, + 0.25f, 0.25f, zadd, 1.0f, + }, + { // D3D: Yellow, OGL: Red + 0.25f, 0.0f, 0.0f, 0.0f, 0.0f, s*0.25f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, - 0.75f, 0.25f, zadd, 1.0f, - }, - { // D3D: Blue, OGL: Green - 0.25f, 0.0f, 0.0f, 0.0f, + 0.75f, 0.25f, zadd, 1.0f, + }, + { // D3D: Blue, OGL: Green + 0.25f, 0.0f, 0.0f, 0.0f, 0.0f, s*0.25f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, - 0.25f, 0.75f, zadd, 1.0f, - }, - { // D3D: Red, OGL: Yellow - 0.25f, 0.0f, 0.0f, 0.0f, + 0.25f, 0.75f, zadd, 1.0f, + }, + { // D3D: Red, OGL: Yellow + 0.25f, 0.0f, 0.0f, 0.0f, 0.0f, s*0.25f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, - 0.75f, 0.75f, zadd, 1.0f, + 0.75f, 0.75f, zadd, 1.0f, + }, }, - }, - { // settings.m_stencilPack == true + { // settings.m_stencilPack == true - { // D3D: Red, OGL: Blue - 0.25f, 0.0f, 0.0f, 0.0f, + { // D3D: Red, OGL: Blue + 0.25f, 0.0f, 0.0f, 0.0f, 0.0f, s*0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, - 0.25f, 0.5f, zadd, 1.0f, - }, - { // D3D: Blue, OGL: Red - 0.25f, 0.0f, 0.0f, 0.0f, + 0.25f, 0.5f, zadd, 1.0f, + }, + { // D3D: Blue, OGL: Red + 0.25f, 0.0f, 0.0f, 0.0f, 0.0f, s*0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, - 0.75f, 0.5f, zadd, 1.0f, - }, - { // D3D: Green, OGL: Green - 0.5f, 0.0f, 0.0f, 0.0f, - 0.0f, s*0.25f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.5f, 0.0f, - 0.5f, 0.75f, zadd, 1.0f, + 0.75f, 0.5f, zadd, 1.0f, + }, + { // D3D: Green, OGL: Green + 0.5f, 0.0f, 0.0f, 0.0f, + 0.0f, s*0.25f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.5f, 0.0f, + 0.5f, 0.75f, zadd, 1.0f, + }, + { // D3D: Yellow, OGL: Yellow + 0.5f, 0.0f, 0.0f, 0.0f, + 0.0f, s*0.25f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.5f, 0.0f, + 0.5f, 0.25f, zadd, 1.0f, + }, + } + }; + + //Use as: [stencilPack][flipV][tetrahedronFace] + static const uint8_t cropBiasIndices[2][2][4] = + { + { // settings.m_stencilPack == false + { 0, 1, 2, 3 }, //flipV == false + { 2, 3, 0, 1 }, //flipV == true }, - { // D3D: Yellow, OGL: Yellow - 0.5f, 0.0f, 0.0f, 0.0f, - 0.0f, s*0.25f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.5f, 0.0f, - 0.5f, 0.25f, zadd, 1.0f, + { // settings.m_stencilPack == true + { 3, 2, 0, 1 }, //flipV == false + { 2, 3, 0, 1 }, //flipV == true }, - } - }; + }; - //Use as: [stencilPack][flipV][tetrahedronFace] - static const uint8_t cropBiasIndices[2][2][4] = - { - { // settings.m_stencilPack == false - { 0, 1, 2, 3 }, //flipV == false - { 2, 3, 0, 1 }, //flipV == true - }, - { // settings.m_stencilPack == true - { 3, 2, 0, 1 }, //flipV == false - { 2, 3, 0, 1 }, //flipV == true - }, - }; + for (uint8_t ii = 0; ii < TetrahedronFaces::Count; ++ii) + { + ProjType::Enum projType = (m_settings.m_stencilPack) ? ProjType::Enum(ii>1) : ProjType::Horizontal; + uint8_t biasIndex = cropBiasIndices[m_settings.m_stencilPack][uint8_t(s_flipV)][ii]; - for (uint8_t ii = 0; ii < TetrahedronFaces::Count; ++ii) + float mtxTmp[16]; + bx::mtxMul(mtxTmp, mtxYpr[ii], lightProj[projType]); + bx::mtxMul(m_shadowMapMtx[ii], mtxTmp, mtxCropBias[m_settings.m_stencilPack][biasIndex]); //mtxYprProjBias + } + + bx::mtxTranslate(mtxShadow //lightInvTranslate + , -m_pointLight.m_position.m_v[0] + , -m_pointLight.m_position.m_v[1] + , -m_pointLight.m_position.m_v[2] + ); + } + else //LightType::DirectionalLight == settings.m_lightType { - ProjType::Enum projType = (settings.m_stencilPack) ? ProjType::Enum(ii>1) : ProjType::Horizontal; - uint8_t biasIndex = cropBiasIndices[settings.m_stencilPack][uint8_t(s_flipV)][ii]; + for (uint8_t ii = 0; ii < m_settings.m_numSplits; ++ii) + { + float mtxTmp[16]; - float mtxTmp[16]; - bx::mtxMul(mtxTmp, mtxYpr[ii], lightProj[projType]); - bx::mtxMul(shadowMapMtx[ii], mtxTmp, mtxCropBias[settings.m_stencilPack][biasIndex]); //mtxYprProjBias + bx::mtxMul(mtxTmp, lightProj[ii], mtxBias); + bx::mtxMul(m_shadowMapMtx[ii], lightView[0], mtxTmp); //lViewProjCropBias + } } - bx::mtxTranslate(mtxShadow //lightInvTranslate - , -pointLight.m_position.m_v[0] - , -pointLight.m_position.m_v[1] - , -pointLight.m_position.m_v[2] - ); - } - else //LightType::DirectionalLight == settings.m_lightType - { - for (uint8_t ii = 0; ii < settings.m_numSplits; ++ii) + // Floor. + if (LightType::DirectionalLight != m_settings.m_lightType) { - float mtxTmp[16]; - - bx::mtxMul(mtxTmp, lightProj[ii], mtxBias); - bx::mtxMul(shadowMapMtx[ii], lightView[0], mtxTmp); //lViewProjCropBias + bx::mtxMul(m_lightMtx, mtxFloor, mtxShadow); //not needed for directional light } - } + m_hplaneMesh.submit(RENDERVIEW_DRAWSCENE_0_ID + , mtxFloor + , *currentSmSettings->m_progDraw + , s_renderStates[RenderState::Default] + , true + ); - // Floor. - if (LightType::DirectionalLight != settings.m_lightType) - { - bx::mtxMul(lightMtx, mtxFloor, mtxShadow); //not needed for directional light - } - hplaneMesh.submit(RENDERVIEW_DRAWSCENE_0_ID - , mtxFloor - , *currentSmSettings->m_progDraw - , s_renderStates[RenderState::Default] - , true - ); + // Bunny. + if (LightType::DirectionalLight != m_settings.m_lightType) + { + bx::mtxMul(m_lightMtx, mtxBunny, mtxShadow); + } + m_bunnyMesh.submit(RENDERVIEW_DRAWSCENE_0_ID + , mtxBunny + , *currentSmSettings->m_progDraw + , s_renderStates[RenderState::Default] + , true + ); - // Bunny. - if (LightType::DirectionalLight != settings.m_lightType) - { - bx::mtxMul(lightMtx, mtxBunny, mtxShadow); - } - bunnyMesh.submit(RENDERVIEW_DRAWSCENE_0_ID - , mtxBunny - , *currentSmSettings->m_progDraw - , s_renderStates[RenderState::Default] - , true - ); + // Hollow cube. + if (LightType::DirectionalLight != m_settings.m_lightType) + { + bx::mtxMul(m_lightMtx, mtxHollowcube, mtxShadow); + } + m_hollowcubeMesh.submit(RENDERVIEW_DRAWSCENE_0_ID + , mtxHollowcube + , *currentSmSettings->m_progDraw + , s_renderStates[RenderState::Default] + , true + ); - // Hollow cube. - if (LightType::DirectionalLight != settings.m_lightType) - { - bx::mtxMul(lightMtx, mtxHollowcube, mtxShadow); - } - hollowcubeMesh.submit(RENDERVIEW_DRAWSCENE_0_ID - , mtxHollowcube - , *currentSmSettings->m_progDraw - , s_renderStates[RenderState::Default] - , true - ); + // Cube. + if (LightType::DirectionalLight != m_settings.m_lightType) + { + bx::mtxMul(m_lightMtx, mtxCube, mtxShadow); + } + m_cubeMesh.submit(RENDERVIEW_DRAWSCENE_0_ID + , mtxCube + , *currentSmSettings->m_progDraw + , s_renderStates[RenderState::Default] + , true + ); - // Cube. - if (LightType::DirectionalLight != settings.m_lightType) - { - bx::mtxMul(lightMtx, mtxCube, mtxShadow); - } - cubeMesh.submit(RENDERVIEW_DRAWSCENE_0_ID - , mtxCube - , *currentSmSettings->m_progDraw - , s_renderStates[RenderState::Default] - , true - ); + // Trees. + for (uint8_t ii = 0; ii < numTrees; ++ii) + { + if (LightType::DirectionalLight != m_settings.m_lightType) + { + bx::mtxMul(m_lightMtx, mtxTrees[ii], mtxShadow); + } + m_treeMesh.submit(RENDERVIEW_DRAWSCENE_0_ID + , mtxTrees[ii] + , *currentSmSettings->m_progDraw + , s_renderStates[RenderState::Default] + , true + ); + } - // Trees. - for (uint8_t ii = 0; ii < numTrees; ++ii) - { - if (LightType::DirectionalLight != settings.m_lightType) + // Lights. + if (LightType::SpotLight == m_settings.m_lightType || LightType::PointLight == m_settings.m_lightType) { - bx::mtxMul(lightMtx, mtxTrees[ii], mtxShadow); + const float lightScale[3] = { 1.5f, 1.5f, 1.5f }; + float mtx[16]; + mtxBillboard(mtx, m_viewState.m_view, m_pointLight.m_position.m_v, lightScale); + m_vplaneMesh.submit(RENDERVIEW_DRAWSCENE_0_ID + , mtx + , s_programs.m_colorTexture + , s_renderStates[RenderState::Custom_BlendLightTexture] + , m_texFlare + ); } - treeMesh.submit(RENDERVIEW_DRAWSCENE_0_ID - , mtxTrees[ii] - , *currentSmSettings->m_progDraw - , s_renderStates[RenderState::Default] - , true - ); - } - // Lights. - if (LightType::SpotLight == settings.m_lightType || LightType::PointLight == settings.m_lightType) - { - const float lightScale[3] = { 1.5f, 1.5f, 1.5f }; - float mtx[16]; - mtxBillboard(mtx, viewState.m_view, pointLight.m_position.m_v, lightScale); - vplaneMesh.submit(RENDERVIEW_DRAWSCENE_0_ID - , mtx - , s_programs.m_colorTexture - , s_renderStates[RenderState::Custom_BlendLightTexture] - , texFlare - ); + // Draw floor bottom. + float floorBottomMtx[16]; + bx::mtxSRT(floorBottomMtx + , floorScale //scaleX + , floorScale //scaleY + , floorScale //scaleZ + , 0.0f //rotX + , 0.0f //rotY + , 0.0f //rotZ + , 0.0f //translateX + , -0.1f //translateY + , 0.0f //translateZ + ); + + m_hplaneMesh.submit(RENDERVIEW_DRAWSCENE_1_ID + , floorBottomMtx + , s_programs.m_texture + , s_renderStates[RenderState::Custom_DrawPlaneBottom] + , m_texFigure + ); } - // Draw floor bottom. - float floorBottomMtx[16]; - bx::mtxSRT(floorBottomMtx - , floorScale //scaleX - , floorScale //scaleY - , floorScale //scaleZ - , 0.0f //rotX - , 0.0f //rotY - , 0.0f //rotZ - , 0.0f //translateX - , -0.1f //translateY - , 0.0f //translateZ - ); - - hplaneMesh.submit(RENDERVIEW_DRAWSCENE_1_ID - , floorBottomMtx - , s_programs.m_texture - , s_renderStates[RenderState::Custom_DrawPlaneBottom] - , texFigure - ); - } - - // Draw depth rect. - if (settings.m_drawDepthBuffer) - { - bgfx::setTexture(4, s_shadowMap[0], bgfx::getTexture(s_rtShadowMap[0]) ); - bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE); - screenSpaceQuad(currentShadowMapSizef, currentShadowMapSizef, s_flipV); - bgfx::submit(RENDERVIEW_DRAWDEPTH_0_ID, s_programs.m_drawDepth[depthType]); - - if (LightType::DirectionalLight == settings.m_lightType) + // Draw depth rect. + if (m_settings.m_drawDepthBuffer) { - for (uint8_t ii = 1; ii < settings.m_numSplits; ++ii) + bgfx::setTexture(4, s_shadowMap[0], bgfx::getTexture(s_rtShadowMap[0]) ); + bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE); + screenSpaceQuad(currentShadowMapSizef, currentShadowMapSizef, s_flipV); + bgfx::submit(RENDERVIEW_DRAWDEPTH_0_ID, s_programs.m_drawDepth[depthType]); + + if (LightType::DirectionalLight == m_settings.m_lightType) { - bgfx::setTexture(4, s_shadowMap[0], bgfx::getTexture(s_rtShadowMap[ii]) ); - bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE); - screenSpaceQuad(currentShadowMapSizef, currentShadowMapSizef, s_flipV); - bgfx::submit(RENDERVIEW_DRAWDEPTH_0_ID+ii, s_programs.m_drawDepth[depthType]); + for (uint8_t ii = 1; ii < m_settings.m_numSplits; ++ii) + { + bgfx::setTexture(4, s_shadowMap[0], bgfx::getTexture(s_rtShadowMap[ii]) ); + bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE); + screenSpaceQuad(currentShadowMapSizef, currentShadowMapSizef, s_flipV); + bgfx::submit(RENDERVIEW_DRAWDEPTH_0_ID+ii, s_programs.m_drawDepth[depthType]); + } } } - } - - // Update render target size. - shadowMapSize = 1 << uint32_t(currentSmSettings->m_sizePwrTwo); - if (bLtChanged || currentShadowMapSize != shadowMapSize) - { - currentShadowMapSize = shadowMapSize; - currentShadowMapSizef = float(int16_t(currentShadowMapSize) ); - s_uniforms.m_shadowMapTexelSize = 1.0f / currentShadowMapSizef; + // Update render target size. + uint16_t shadowMapSize = 1 << uint32_t(currentSmSettings->m_sizePwrTwo); + if (bLtChanged || m_currentShadowMapSize != shadowMapSize) { - bgfx::destroyFrameBuffer(s_rtShadowMap[0]); + m_currentShadowMapSize = shadowMapSize; + s_uniforms.m_shadowMapTexelSize = 1.0f / currentShadowMapSizef; - bgfx::TextureHandle fbtextures[] = { - bgfx::createTexture2D(currentShadowMapSize, currentShadowMapSize, false, 1, bgfx::TextureFormat::BGRA8, BGFX_TEXTURE_RT), - bgfx::createTexture2D(currentShadowMapSize, currentShadowMapSize, false, 1, bgfx::TextureFormat::D24S8, BGFX_TEXTURE_RT), - }; - s_rtShadowMap[0] = bgfx::createFrameBuffer(BX_COUNTOF(fbtextures), fbtextures, true); - } + bgfx::destroy(s_rtShadowMap[0]); - if (LightType::DirectionalLight == settings.m_lightType) - { - for (uint8_t ii = 1; ii < ShadowMapRenderTargets::Count; ++ii) - { + bgfx::TextureHandle fbtextures[] = { - bgfx::destroyFrameBuffer(s_rtShadowMap[ii]); + bgfx::createTexture2D(m_currentShadowMapSize, m_currentShadowMapSize, false, 1, bgfx::TextureFormat::BGRA8, BGFX_TEXTURE_RT), + bgfx::createTexture2D(m_currentShadowMapSize, m_currentShadowMapSize, false, 1, bgfx::TextureFormat::D24S8, BGFX_TEXTURE_RT), + }; + s_rtShadowMap[0] = bgfx::createFrameBuffer(BX_COUNTOF(fbtextures), fbtextures, true); + } - bgfx::TextureHandle fbtextures[] = + if (LightType::DirectionalLight == m_settings.m_lightType) + { + for (uint8_t ii = 1; ii < ShadowMapRenderTargets::Count; ++ii) + { { - bgfx::createTexture2D(currentShadowMapSize, currentShadowMapSize, false, 1, bgfx::TextureFormat::BGRA8, BGFX_TEXTURE_RT), - bgfx::createTexture2D(currentShadowMapSize, currentShadowMapSize, false, 1, bgfx::TextureFormat::D24S8, BGFX_TEXTURE_RT), - }; - s_rtShadowMap[ii] = bgfx::createFrameBuffer(BX_COUNTOF(fbtextures), fbtextures, true); + bgfx::destroy(s_rtShadowMap[ii]); + + bgfx::TextureHandle fbtextures[] = + { + bgfx::createTexture2D(m_currentShadowMapSize, m_currentShadowMapSize, false, 1, bgfx::TextureFormat::BGRA8, BGFX_TEXTURE_RT), + bgfx::createTexture2D(m_currentShadowMapSize, m_currentShadowMapSize, false, 1, bgfx::TextureFormat::D24S8, BGFX_TEXTURE_RT), + }; + s_rtShadowMap[ii] = bgfx::createFrameBuffer(BX_COUNTOF(fbtextures), fbtextures, true); + } } } + + bgfx::destroy(s_rtBlur); + s_rtBlur = bgfx::createFrameBuffer(m_currentShadowMapSize, m_currentShadowMapSize, bgfx::TextureFormat::BGRA8); } - bgfx::destroyFrameBuffer(s_rtBlur); - s_rtBlur = bgfx::createFrameBuffer(currentShadowMapSize, currentShadowMapSize, bgfx::TextureFormat::BGRA8); - } + // Advance to next frame. Rendering thread will be kicked to + // process submitted rendering primitives. + bgfx::frame(); - // Advance to next frame. Rendering thread will be kicked to - // process submitted rendering primitives. - bgfx::frame(); + return true; + } + return false; } - bunnyMesh.unload(); - treeMesh.unload(); - cubeMesh.unload(); - hollowcubeMesh.unload(); - hplaneMesh.unload(); - vplaneMesh.unload(); + entry::MouseState m_mouseState; + uint32_t m_width; + uint32_t m_height; + uint32_t m_debug; + uint32_t m_reset; - bgfx::destroyTexture(texFigure); - bgfx::destroyTexture(texFieldstone); - bgfx::destroyTexture(texFlare); + ViewState m_viewState; + ClearValues m_clearValues; - for (uint8_t ii = 0; ii < ShadowMapRenderTargets::Count; ++ii) - { - bgfx::destroyFrameBuffer(s_rtShadowMap[ii]); - } - bgfx::destroyFrameBuffer(s_rtBlur); + bgfx::VertexDecl m_posDecl; - s_programs.destroy(); + bgfx::TextureHandle m_texFigure; + bgfx::TextureHandle m_texFlare; + bgfx::TextureHandle m_texFieldstone; - bgfx::destroyUniform(s_texColor); - bgfx::destroyUniform(s_shadowMap[3]); - bgfx::destroyUniform(s_shadowMap[2]); - bgfx::destroyUniform(s_shadowMap[1]); - bgfx::destroyUniform(s_shadowMap[0]); + Mesh m_bunnyMesh; + Mesh m_treeMesh; + Mesh m_cubeMesh; + Mesh m_hollowcubeMesh; + Mesh m_hplaneMesh; + Mesh m_vplaneMesh; - s_uniforms.destroy(); + float m_color[4]; + Material m_defaultMaterial; + Light m_pointLight; + Light m_directionalLight; - cameraDestroy(); - imguiDestroy(); + float m_lightMtx[16]; + float m_shadowMapMtx[ShadowMapRenderTargets::Count][16]; - // Shutdown bgfx. - bgfx::shutdown(); + ShadowMapSettings m_smSettings[LightType::Count][DepthImpl::Count][SmImpl::Count]; + SceneSettings m_settings; - return 0; -} + uint16_t m_currentShadowMapSize; + + float m_timeAccumulatorLight; + float m_timeAccumulatorScene; +}; + +} // namespace + +ENTRY_IMPLEMENT_MAIN(ExampleShadowmaps, "16-shadowmaps", "Shadow maps example."); |