|
|
@@ -1819,1016 +1819,1095 @@ bool clipTest(const float* _planes, uint8_t _planeNum, const Mesh& _mesh, const
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
-int _main_(int _argc, char** _argv)
|
|
|
+struct ShadowVolumeProgramType
|
|
|
{
|
|
|
- Args args(_argc, _argv);
|
|
|
-
|
|
|
- ViewState viewState(1280, 720);
|
|
|
- ClearValues clearValues = {0x00000000, 1.0f, 0};
|
|
|
-
|
|
|
- uint32_t debug = BGFX_DEBUG_TEXT;
|
|
|
- uint32_t reset = BGFX_RESET_VSYNC;
|
|
|
-
|
|
|
- bgfx::init(args.m_type, args.m_pciId);
|
|
|
- bgfx::reset(viewState.m_width, viewState.m_height, reset);
|
|
|
-
|
|
|
- // Enable debug text.
|
|
|
- bgfx::setDebug(debug);
|
|
|
-
|
|
|
- const bgfx::Caps* caps = bgfx::getCaps();
|
|
|
- s_oglNdc = caps->homogeneousDepth;
|
|
|
- s_texelHalf = bgfx::RendererType::Direct3D9 == caps->rendererType ? 0.5f : 0.0f;
|
|
|
-
|
|
|
- // Imgui
|
|
|
- imguiCreate();
|
|
|
-
|
|
|
- PosNormalTexcoordVertex::init();
|
|
|
-
|
|
|
- s_uniforms.init();
|
|
|
- s_uniforms.submitConstUniforms();
|
|
|
-
|
|
|
- bgfx::TextureHandle figureTex = loadTexture("textures/figure-rgba.dds");
|
|
|
- bgfx::TextureHandle flareTex = loadTexture("textures/flare.dds");
|
|
|
- bgfx::TextureHandle fieldstoneTex = loadTexture("textures/fieldstone-rgba.dds");
|
|
|
-
|
|
|
- bgfx::TextureHandle fbtextures[] =
|
|
|
- {
|
|
|
- bgfx::createTexture2D(uint16_t(viewState.m_width), uint16_t(viewState.m_height), false, 1, bgfx::TextureFormat::BGRA8, BGFX_TEXTURE_U_CLAMP | BGFX_TEXTURE_V_CLAMP | BGFX_TEXTURE_RT),
|
|
|
- bgfx::createTexture2D(uint16_t(viewState.m_width), uint16_t(viewState.m_height), false, 1, bgfx::TextureFormat::D16, BGFX_TEXTURE_RT_WRITE_ONLY),
|
|
|
- };
|
|
|
- s_stencilFb = bgfx::createFrameBuffer(BX_COUNTOF(fbtextures), fbtextures, true);
|
|
|
-
|
|
|
- s_texColor = bgfx::createUniform("s_texColor", bgfx::UniformType::Int1);
|
|
|
- s_texStencil = bgfx::createUniform("s_texStencil", bgfx::UniformType::Int1);
|
|
|
-
|
|
|
- bgfx::ProgramHandle programTextureLighting = loadProgram("vs_shadowvolume_texture_lighting", "fs_shadowvolume_texture_lighting");
|
|
|
- bgfx::ProgramHandle programColorLighting = loadProgram("vs_shadowvolume_color_lighting", "fs_shadowvolume_color_lighting" );
|
|
|
- bgfx::ProgramHandle programColorTexture = loadProgram("vs_shadowvolume_color_texture", "fs_shadowvolume_color_texture" );
|
|
|
- bgfx::ProgramHandle programTexture = loadProgram("vs_shadowvolume_texture", "fs_shadowvolume_texture" );
|
|
|
-
|
|
|
- bgfx::ProgramHandle programBackBlank = loadProgram("vs_shadowvolume_svback", "fs_shadowvolume_svbackblank" );
|
|
|
- bgfx::ProgramHandle programSideBlank = loadProgram("vs_shadowvolume_svside", "fs_shadowvolume_svsideblank" );
|
|
|
- bgfx::ProgramHandle programFrontBlank = loadProgram("vs_shadowvolume_svfront", "fs_shadowvolume_svfrontblank");
|
|
|
-
|
|
|
- bgfx::ProgramHandle programBackColor = loadProgram("vs_shadowvolume_svback", "fs_shadowvolume_svbackcolor" );
|
|
|
- bgfx::ProgramHandle programSideColor = loadProgram("vs_shadowvolume_svside", "fs_shadowvolume_svsidecolor" );
|
|
|
- bgfx::ProgramHandle programFrontColor = loadProgram("vs_shadowvolume_svfront", "fs_shadowvolume_svfrontcolor");
|
|
|
-
|
|
|
- bgfx::ProgramHandle programSideTex = loadProgram("vs_shadowvolume_svside", "fs_shadowvolume_svsidetex" );
|
|
|
- bgfx::ProgramHandle programBackTex1 = loadProgram("vs_shadowvolume_svback", "fs_shadowvolume_svbacktex1" );
|
|
|
- bgfx::ProgramHandle programBackTex2 = loadProgram("vs_shadowvolume_svback", "fs_shadowvolume_svbacktex2" );
|
|
|
- bgfx::ProgramHandle programFrontTex1 = loadProgram("vs_shadowvolume_svfront", "fs_shadowvolume_svfronttex1" );
|
|
|
- bgfx::ProgramHandle programFrontTex2 = loadProgram("vs_shadowvolume_svfront", "fs_shadowvolume_svfronttex2" );
|
|
|
-
|
|
|
- struct ShadowVolumeProgramType
|
|
|
- {
|
|
|
- enum Enum
|
|
|
- {
|
|
|
- Blank = 0,
|
|
|
- Color,
|
|
|
- Tex1,
|
|
|
- Tex2,
|
|
|
-
|
|
|
- Count
|
|
|
- };
|
|
|
- };
|
|
|
-
|
|
|
- struct ShadowVolumePart
|
|
|
- {
|
|
|
- enum Enum
|
|
|
- {
|
|
|
- Back = 0,
|
|
|
- Side,
|
|
|
- Front,
|
|
|
-
|
|
|
- Count
|
|
|
- };
|
|
|
- };
|
|
|
-
|
|
|
- bgfx::ProgramHandle svProgs[ShadowVolumeProgramType::Count][ShadowVolumePart::Count] =
|
|
|
- {
|
|
|
- { programBackBlank, programSideBlank, programFrontBlank }, // Blank
|
|
|
- { programBackColor, programSideColor, programFrontColor }, // Color
|
|
|
- { programBackTex1, programSideTex, programFrontTex1 }, // Tex1
|
|
|
- { programBackTex2, programSideTex, programFrontTex2 }, // Tex2
|
|
|
- };
|
|
|
-
|
|
|
- Model bunnyLowPolyModel;
|
|
|
- Model bunnyHighPolyModel;
|
|
|
- Model columnModel;
|
|
|
- Model platformModel;
|
|
|
- Model cubeModel;
|
|
|
- Model hplaneFieldModel;
|
|
|
- Model hplaneFigureModel;
|
|
|
- Model vplaneModel;
|
|
|
-
|
|
|
- bunnyHighPolyModel.load("meshes/bunny_patched.bin");
|
|
|
- bunnyHighPolyModel.m_program = programColorLighting;
|
|
|
-
|
|
|
- bunnyLowPolyModel.load("meshes/bunny_decimated.bin");
|
|
|
- bunnyLowPolyModel.m_program = programColorLighting;
|
|
|
-
|
|
|
- columnModel.load("meshes/column.bin");
|
|
|
- columnModel.m_program = programColorLighting;
|
|
|
-
|
|
|
- platformModel.load("meshes/platform.bin");
|
|
|
- platformModel.m_program = programTextureLighting;
|
|
|
- platformModel.m_texture = figureTex;
|
|
|
-
|
|
|
- cubeModel.load("meshes/cube.bin");
|
|
|
- cubeModel.m_program = programTextureLighting;
|
|
|
- cubeModel.m_texture = figureTex;
|
|
|
-
|
|
|
- hplaneFieldModel.load(s_hplaneVertices, BX_COUNTOF(s_hplaneVertices), PosNormalTexcoordVertex::ms_decl, s_planeIndices, BX_COUNTOF(s_planeIndices) );
|
|
|
- hplaneFieldModel.m_program = programTextureLighting;
|
|
|
- hplaneFieldModel.m_texture = fieldstoneTex;
|
|
|
-
|
|
|
- hplaneFigureModel.load(s_hplaneVertices, BX_COUNTOF(s_hplaneVertices), PosNormalTexcoordVertex::ms_decl, s_planeIndices, BX_COUNTOF(s_planeIndices) );
|
|
|
- hplaneFigureModel.m_program = programTextureLighting;
|
|
|
- hplaneFigureModel.m_texture = figureTex;
|
|
|
-
|
|
|
- vplaneModel.load(s_vplaneVertices, BX_COUNTOF(s_vplaneVertices), PosNormalTexcoordVertex::ms_decl, s_planeIndices, BX_COUNTOF(s_planeIndices) );
|
|
|
- vplaneModel.m_program = programColorTexture;
|
|
|
- vplaneModel.m_texture = flareTex;
|
|
|
-
|
|
|
- // Setup lights.
|
|
|
- const float rgbInnerR[MAX_LIGHTS_COUNT][4] =
|
|
|
- {
|
|
|
- { 1.0f, 0.7f, 0.2f, 0.0f }, //yellow
|
|
|
- { 0.7f, 0.2f, 1.0f, 0.0f }, //purple
|
|
|
- { 0.2f, 1.0f, 0.7f, 0.0f }, //cyan
|
|
|
- { 1.0f, 0.4f, 0.2f, 0.0f }, //orange
|
|
|
- { 0.7f, 0.7f, 0.7f, 0.0f }, //white
|
|
|
- };
|
|
|
-
|
|
|
- float lightRgbInnerR[MAX_LIGHTS_COUNT][4];
|
|
|
- for (uint8_t ii = 0, jj = 0; ii < MAX_LIGHTS_COUNT; ++ii, ++jj)
|
|
|
- {
|
|
|
- const uint8_t index = jj%MAX_LIGHTS_COUNT;
|
|
|
- lightRgbInnerR[ii][0] = rgbInnerR[index][0];
|
|
|
- lightRgbInnerR[ii][1] = rgbInnerR[index][1];
|
|
|
- lightRgbInnerR[ii][2] = rgbInnerR[index][2];
|
|
|
- lightRgbInnerR[ii][3] = rgbInnerR[index][3];
|
|
|
- }
|
|
|
-
|
|
|
- int64_t profTime = 0;
|
|
|
- int64_t timeOffset = bx::getHPCounter();
|
|
|
-
|
|
|
- uint32_t numShadowVolumeVertices = 0;
|
|
|
- uint32_t numShadowVolumeIndices = 0;
|
|
|
-
|
|
|
- uint32_t oldWidth = 0;
|
|
|
- uint32_t oldHeight = 0;
|
|
|
-
|
|
|
- // Imgui.
|
|
|
- bool settings_showHelp = false;
|
|
|
- bool settings_updateLights = true;
|
|
|
- bool settings_updateScene = true;
|
|
|
- bool settings_mixedSvImpl = true;
|
|
|
- bool settings_useStencilTexture = false;
|
|
|
- bool settings_drawShadowVolumes = false;
|
|
|
- float settings_numLights = 1.0f;
|
|
|
- float settings_instanceCount = 9.0f;
|
|
|
- ShadowVolumeImpl::Enum settings_shadowVolumeImpl = ShadowVolumeImpl::DepthFail;
|
|
|
- ShadowVolumeAlgorithm::Enum settings_shadowVolumeAlgorithm = ShadowVolumeAlgorithm::EdgeBased;
|
|
|
- int32_t scrollAreaRight = 0;
|
|
|
-
|
|
|
- const char* titles[2] =
|
|
|
- {
|
|
|
- "Scene 0",
|
|
|
- "Scene 1",
|
|
|
- };
|
|
|
-
|
|
|
- enum LightPattern
|
|
|
- {
|
|
|
- LightPattern0 = 0,
|
|
|
- LightPattern1
|
|
|
- };
|
|
|
-
|
|
|
- enum MeshChoice
|
|
|
+ enum Enum
|
|
|
{
|
|
|
- BunnyHighPoly = 0,
|
|
|
- BunnyLowPoly
|
|
|
+ Blank = 0,
|
|
|
+ Color,
|
|
|
+ Tex1,
|
|
|
+ Tex2,
|
|
|
+
|
|
|
+ Count
|
|
|
};
|
|
|
+};
|
|
|
|
|
|
- enum Scene
|
|
|
+struct ShadowVolumePart
|
|
|
+{
|
|
|
+ enum Enum
|
|
|
{
|
|
|
- Scene0 = 0,
|
|
|
- Scene1,
|
|
|
-
|
|
|
- SceneCount
|
|
|
+ Back = 0,
|
|
|
+ Side,
|
|
|
+ Front,
|
|
|
+
|
|
|
+ Count
|
|
|
};
|
|
|
+};
|
|
|
|
|
|
- LightPattern lightPattern = LightPattern0;
|
|
|
- MeshChoice currentMesh = BunnyLowPoly;
|
|
|
- Scene currentScene = Scene0;
|
|
|
+enum LightPattern
|
|
|
+{
|
|
|
+ LightPattern0 = 0,
|
|
|
+ LightPattern1
|
|
|
+};
|
|
|
|
|
|
- // Set view and projection matrices.
|
|
|
- const float fov = 60.0f;
|
|
|
- const float aspect = float(viewState.m_width)/float(viewState.m_height);
|
|
|
- const float nearPlane = 1.0f;
|
|
|
- const float farPlane = 1000.0f;
|
|
|
+enum MeshChoice
|
|
|
+{
|
|
|
+ BunnyHighPoly = 0,
|
|
|
+ BunnyLowPoly
|
|
|
+};
|
|
|
|
|
|
- float initialPos[3] = { 3.0f, 20.0f, -58.0f };
|
|
|
- cameraCreate();
|
|
|
- cameraSetPosition(initialPos);
|
|
|
- cameraSetVerticalAngle(-0.25f);
|
|
|
- cameraGetViewMtx(viewState.m_view);
|
|
|
+enum Scene
|
|
|
+{
|
|
|
+ Scene0 = 0,
|
|
|
+ Scene1,
|
|
|
+
|
|
|
+ SceneCount
|
|
|
+};
|
|
|
|
|
|
- entry::MouseState mouseState;
|
|
|
- while (!entry::processEvents(viewState.m_width, viewState.m_height, debug, reset, &mouseState) )
|
|
|
+class ExampleShadowVolumes : public entry::AppI
|
|
|
+{
|
|
|
+ void init(int _argc, char** _argv) BX_OVERRIDE
|
|
|
{
|
|
|
- // Respond properly on resize.
|
|
|
- if (oldWidth != viewState.m_width
|
|
|
- || oldHeight != viewState.m_height)
|
|
|
- {
|
|
|
- oldWidth = viewState.m_width;
|
|
|
- oldHeight = viewState.m_height;
|
|
|
-
|
|
|
- bgfx::destroyFrameBuffer(s_stencilFb);
|
|
|
-
|
|
|
- fbtextures[0] = bgfx::createTexture2D(uint16_t(viewState.m_width), uint16_t(viewState.m_height), false, 1, bgfx::TextureFormat::BGRA8, BGFX_TEXTURE_U_CLAMP|BGFX_TEXTURE_V_CLAMP|BGFX_TEXTURE_RT);
|
|
|
- fbtextures[1] = bgfx::createTexture2D(uint16_t(viewState.m_width), uint16_t(viewState.m_height), false, 1, bgfx::TextureFormat::D16, BGFX_TEXTURE_RT_WRITE_ONLY);
|
|
|
- s_stencilFb = bgfx::createFrameBuffer(BX_COUNTOF(fbtextures), fbtextures, true);
|
|
|
- }
|
|
|
-
|
|
|
- // 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;
|
|
|
- float time = (float)( (now - timeOffset)/double(bx::getHPFrequency() ) );
|
|
|
- const float deltaTime = float(frameTime/freq);
|
|
|
- s_uniforms.m_time = time;
|
|
|
-
|
|
|
- // Update camera.
|
|
|
- cameraUpdate(deltaTime, mouseState);
|
|
|
-
|
|
|
- // Set view and projection matrix for view 0.
|
|
|
- const bgfx::HMD* hmd = bgfx::getHMD();
|
|
|
- if (NULL != hmd && 0 != (hmd->flags & BGFX_HMD_RENDERING) )
|
|
|
- {
|
|
|
- float eye[3];
|
|
|
- cameraGetPosition(eye);
|
|
|
-
|
|
|
- bx::mtxQuatTranslationHMD(viewState.m_view, hmd->eye[0].rotation, eye);
|
|
|
- bx::mtxProj(viewState.m_proj, hmd->eye[0].fov, nearPlane, farPlane, s_oglNdc);
|
|
|
-
|
|
|
- viewState.m_width = hmd->width;
|
|
|
- viewState.m_height = hmd->height;
|
|
|
- }
|
|
|
- else
|
|
|
+
|
|
|
+ Args args(_argc, _argv);
|
|
|
+
|
|
|
+ m_viewState = ViewState(1280, 720);
|
|
|
+ m_clearValues = {0x00000000, 1.0f, 0};
|
|
|
+
|
|
|
+ m_debug = BGFX_DEBUG_TEXT;
|
|
|
+ m_reset = BGFX_RESET_VSYNC;
|
|
|
+
|
|
|
+ bgfx::init(args.m_type, args.m_pciId);
|
|
|
+ bgfx::reset(m_viewState.m_width, m_viewState.m_height, m_reset);
|
|
|
+
|
|
|
+ // Enable debug text.
|
|
|
+ bgfx::setDebug(m_debug);
|
|
|
+
|
|
|
+ const bgfx::Caps* caps = bgfx::getCaps();
|
|
|
+ s_oglNdc = caps->homogeneousDepth;
|
|
|
+ s_texelHalf = bgfx::RendererType::Direct3D9 == caps->rendererType ? 0.5f : 0.0f;
|
|
|
+
|
|
|
+ // Imgui
|
|
|
+ imguiCreate();
|
|
|
+
|
|
|
+ PosNormalTexcoordVertex::init();
|
|
|
+
|
|
|
+ s_uniforms.init();
|
|
|
+
|
|
|
+ m_figureTex = loadTexture("textures/figure-rgba.dds");
|
|
|
+ m_flareTex = loadTexture("textures/flare.dds");
|
|
|
+ m_fieldstoneTex = loadTexture("textures/fieldstone-rgba.dds");
|
|
|
+
|
|
|
+ bgfx::TextureHandle fbtextures[] =
|
|
|
{
|
|
|
- cameraGetViewMtx(viewState.m_view);
|
|
|
- bx::mtxProj(viewState.m_proj, fov, aspect, nearPlane, farPlane, s_oglNdc);
|
|
|
- }
|
|
|
-
|
|
|
- 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
|
|
|
- , uint16_t(viewState.m_width)
|
|
|
- , uint16_t(viewState.m_height)
|
|
|
- );
|
|
|
-
|
|
|
- imguiBeginScrollArea("Settings", viewState.m_width - 256 - 10, 10, 256, 700, &scrollAreaRight);
|
|
|
-
|
|
|
- if (imguiCheck(titles[Scene0], Scene0 == currentScene) )
|
|
|
- {
|
|
|
- currentScene = Scene0;
|
|
|
- }
|
|
|
-
|
|
|
- if (imguiCheck(titles[Scene1], Scene1 == currentScene) )
|
|
|
- {
|
|
|
- currentScene = Scene1;
|
|
|
- }
|
|
|
-
|
|
|
- imguiSlider("Lights", settings_numLights, 1.0f, float(MAX_LIGHTS_COUNT), 1.0f);
|
|
|
-
|
|
|
- if (imguiCheck("Update lights", settings_updateLights) )
|
|
|
- {
|
|
|
- settings_updateLights = !settings_updateLights;
|
|
|
- }
|
|
|
-
|
|
|
- imguiIndent();
|
|
|
-
|
|
|
- if (imguiCheck("Light pattern 0", LightPattern0 == lightPattern, settings_updateLights) )
|
|
|
+ bgfx::createTexture2D(uint16_t(m_viewState.m_width), uint16_t(m_viewState.m_height), false, 1, bgfx::TextureFormat::BGRA8, BGFX_TEXTURE_U_CLAMP | BGFX_TEXTURE_V_CLAMP | BGFX_TEXTURE_RT),
|
|
|
+ bgfx::createTexture2D(uint16_t(m_viewState.m_width), uint16_t(m_viewState.m_height), false, 1, bgfx::TextureFormat::D16, BGFX_TEXTURE_RT_WRITE_ONLY),
|
|
|
+ };
|
|
|
+
|
|
|
+ s_stencilFb = bgfx::createFrameBuffer(BX_COUNTOF(fbtextures), fbtextures, true);
|
|
|
+
|
|
|
+ s_texColor = bgfx::createUniform("s_texColor", bgfx::UniformType::Int1);
|
|
|
+ s_texStencil = bgfx::createUniform("s_texStencil", bgfx::UniformType::Int1);
|
|
|
+
|
|
|
+ m_programTextureLighting = loadProgram("vs_shadowvolume_texture_lighting", "fs_shadowvolume_texture_lighting");
|
|
|
+ m_programColorLighting = loadProgram("vs_shadowvolume_color_lighting", "fs_shadowvolume_color_lighting" );
|
|
|
+ m_programColorTexture = loadProgram("vs_shadowvolume_color_texture", "fs_shadowvolume_color_texture" );
|
|
|
+ m_programTexture = loadProgram("vs_shadowvolume_texture", "fs_shadowvolume_texture" );
|
|
|
+
|
|
|
+ m_programBackBlank = loadProgram("vs_shadowvolume_svback", "fs_shadowvolume_svbackblank" );
|
|
|
+ m_programSideBlank = loadProgram("vs_shadowvolume_svside", "fs_shadowvolume_svsideblank" );
|
|
|
+ m_programFrontBlank = loadProgram("vs_shadowvolume_svfront", "fs_shadowvolume_svfrontblank");
|
|
|
+
|
|
|
+ m_programBackColor = loadProgram("vs_shadowvolume_svback", "fs_shadowvolume_svbackcolor" );
|
|
|
+ m_programSideColor = loadProgram("vs_shadowvolume_svside", "fs_shadowvolume_svsidecolor" );
|
|
|
+ m_programFrontColor = loadProgram("vs_shadowvolume_svfront", "fs_shadowvolume_svfrontcolor");
|
|
|
+
|
|
|
+ m_programSideTex = loadProgram("vs_shadowvolume_svside", "fs_shadowvolume_svsidetex" );
|
|
|
+ m_programBackTex1 = loadProgram("vs_shadowvolume_svback", "fs_shadowvolume_svbacktex1" );
|
|
|
+ m_programBackTex2 = loadProgram("vs_shadowvolume_svback", "fs_shadowvolume_svbacktex2" );
|
|
|
+ m_programFrontTex1 = loadProgram("vs_shadowvolume_svfront", "fs_shadowvolume_svfronttex1" );
|
|
|
+ m_programFrontTex2 = loadProgram("vs_shadowvolume_svfront", "fs_shadowvolume_svfronttex2" );
|
|
|
+
|
|
|
+ bgfx::ProgramHandle svProgs[ShadowVolumeProgramType::Count][ShadowVolumePart::Count] =
|
|
|
{
|
|
|
- lightPattern = LightPattern0;
|
|
|
- }
|
|
|
-
|
|
|
- if (imguiCheck("Light pattern 1", LightPattern1 == lightPattern, settings_updateLights) )
|
|
|
+ { m_programBackBlank, m_programSideBlank, m_programFrontBlank }, // Blank
|
|
|
+ { m_programBackColor, m_programSideColor, m_programFrontColor }, // Color
|
|
|
+ { m_programBackTex1, m_programSideTex, m_programFrontTex1 }, // Tex1
|
|
|
+ { m_programBackTex2, m_programSideTex, m_programFrontTex2 }, // Tex2
|
|
|
+ };
|
|
|
+ bx::memCopy(m_svProgs, svProgs, sizeof(svProgs));
|
|
|
+
|
|
|
+ m_bunnyHighPolyModel.load("meshes/bunny_patched.bin");
|
|
|
+ m_bunnyHighPolyModel.m_program = m_programColorLighting;
|
|
|
+
|
|
|
+ m_bunnyLowPolyModel.load("meshes/bunny_decimated.bin");
|
|
|
+ m_bunnyLowPolyModel.m_program = m_programColorLighting;
|
|
|
+
|
|
|
+ m_columnModel.load("meshes/column.bin");
|
|
|
+ m_columnModel.m_program = m_programColorLighting;
|
|
|
+
|
|
|
+ m_platformModel.load("meshes/platform.bin");
|
|
|
+ m_platformModel.m_program = m_programTextureLighting;
|
|
|
+ m_platformModel.m_texture = m_figureTex;
|
|
|
+
|
|
|
+ m_cubeModel.load("meshes/cube.bin");
|
|
|
+ m_cubeModel.m_program = m_programTextureLighting;
|
|
|
+ m_cubeModel.m_texture = m_figureTex;
|
|
|
+
|
|
|
+ m_hplaneFieldModel.load(s_hplaneVertices, BX_COUNTOF(s_hplaneVertices), PosNormalTexcoordVertex::ms_decl, s_planeIndices, BX_COUNTOF(s_planeIndices) );
|
|
|
+ m_hplaneFieldModel.m_program = m_programTextureLighting;
|
|
|
+ m_hplaneFieldModel.m_texture = m_fieldstoneTex;
|
|
|
+
|
|
|
+ m_hplaneFigureModel.load(s_hplaneVertices, BX_COUNTOF(s_hplaneVertices), PosNormalTexcoordVertex::ms_decl, s_planeIndices, BX_COUNTOF(s_planeIndices) );
|
|
|
+ m_hplaneFigureModel.m_program = m_programTextureLighting;
|
|
|
+ m_hplaneFigureModel.m_texture = m_figureTex;
|
|
|
+
|
|
|
+ m_vplaneModel.load(s_vplaneVertices, BX_COUNTOF(s_vplaneVertices), PosNormalTexcoordVertex::ms_decl, s_planeIndices, BX_COUNTOF(s_planeIndices) );
|
|
|
+ m_vplaneModel.m_program = m_programColorTexture;
|
|
|
+ m_vplaneModel.m_texture = m_flareTex;
|
|
|
+
|
|
|
+ // Setup lights.
|
|
|
+ const float rgbInnerR[MAX_LIGHTS_COUNT][4] =
|
|
|
{
|
|
|
- lightPattern = LightPattern1;
|
|
|
- }
|
|
|
-
|
|
|
- imguiUnindent();
|
|
|
-
|
|
|
- if (imguiCheck("Update scene", settings_updateScene, Scene0 == currentScene) )
|
|
|
+ { 1.0f, 0.7f, 0.2f, 0.0f }, //yellow
|
|
|
+ { 0.7f, 0.2f, 1.0f, 0.0f }, //purple
|
|
|
+ { 0.2f, 1.0f, 0.7f, 0.0f }, //cyan
|
|
|
+ { 1.0f, 0.4f, 0.2f, 0.0f }, //orange
|
|
|
+ { 0.7f, 0.7f, 0.7f, 0.0f }, //white
|
|
|
+ };
|
|
|
+
|
|
|
+ for (uint8_t ii = 0, jj = 0; ii < MAX_LIGHTS_COUNT; ++ii, ++jj)
|
|
|
{
|
|
|
- settings_updateScene = !settings_updateScene;
|
|
|
+ const uint8_t index = jj%MAX_LIGHTS_COUNT;
|
|
|
+ m_lightRgbInnerR[ii][0] = rgbInnerR[index][0];
|
|
|
+ m_lightRgbInnerR[ii][1] = rgbInnerR[index][1];
|
|
|
+ m_lightRgbInnerR[ii][2] = rgbInnerR[index][2];
|
|
|
+ m_lightRgbInnerR[ii][3] = rgbInnerR[index][3];
|
|
|
}
|
|
|
+
|
|
|
+ m_profTime = 0;
|
|
|
+ m_timeOffset = bx::getHPCounter();
|
|
|
+
|
|
|
+ m_numShadowVolumeVertices = 0;
|
|
|
+ m_numShadowVolumeIndices = 0;
|
|
|
+
|
|
|
+ m_oldWidth = 0;
|
|
|
+ m_oldHeight = 0;
|
|
|
+
|
|
|
+ // Imgui.
|
|
|
+ m_settings_showHelp = false;
|
|
|
+ m_settings_updateLights = true;
|
|
|
+ m_settings_updateScene = true;
|
|
|
+ m_settings_mixedSvImpl = true;
|
|
|
+ m_settings_useStencilTexture = false;
|
|
|
+ m_settings_drawShadowVolumes = false;
|
|
|
+ m_settings_numLights = 1.0f;
|
|
|
+ m_settings_instanceCount = 9.0f;
|
|
|
+ m_settings_shadowVolumeImpl = ShadowVolumeImpl::DepthFail;
|
|
|
+ m_settings_shadowVolumeAlgorithm = ShadowVolumeAlgorithm::EdgeBased;
|
|
|
+ m_scrollAreaRight = 0;
|
|
|
+
|
|
|
+ m_lightPattern = LightPattern0;
|
|
|
+ m_currentMesh = BunnyLowPoly;
|
|
|
+ m_currentScene = Scene0;
|
|
|
+
|
|
|
+ // Set view matrix
|
|
|
+ float initialPos[3] = { 3.0f, 20.0f, -58.0f };
|
|
|
+ cameraCreate();
|
|
|
+ cameraSetPosition(initialPos);
|
|
|
+ cameraSetVerticalAngle(-0.25f);
|
|
|
+ cameraGetViewMtx(m_viewState.m_view);
|
|
|
+ }
|
|
|
+
|
|
|
+ virtual int shutdown() BX_OVERRIDE
|
|
|
+ {
|
|
|
+ // Cleanup
|
|
|
+ m_bunnyLowPolyModel.unload();
|
|
|
+ m_bunnyHighPolyModel.unload();
|
|
|
+ m_columnModel.unload();
|
|
|
+ m_cubeModel.unload();
|
|
|
+ m_platformModel.unload();
|
|
|
+ m_hplaneFieldModel.unload();
|
|
|
+ m_hplaneFigureModel.unload();
|
|
|
+ m_vplaneModel.unload();
|
|
|
+
|
|
|
+ s_uniforms.destroy();
|
|
|
+
|
|
|
+ bgfx::destroyUniform(s_texColor);
|
|
|
+ bgfx::destroyUniform(s_texStencil);
|
|
|
+ bgfx::destroyFrameBuffer(s_stencilFb);
|
|
|
+
|
|
|
+ bgfx::destroyTexture(m_figureTex);
|
|
|
+ bgfx::destroyTexture(m_fieldstoneTex);
|
|
|
+ bgfx::destroyTexture(m_flareTex);
|
|
|
+
|
|
|
+ bgfx::destroyProgram(m_programTextureLighting);
|
|
|
+ bgfx::destroyProgram(m_programColorLighting);
|
|
|
+ bgfx::destroyProgram(m_programColorTexture);
|
|
|
+ bgfx::destroyProgram(m_programTexture);
|
|
|
+
|
|
|
+ bgfx::destroyProgram(m_programBackBlank);
|
|
|
+ bgfx::destroyProgram(m_programSideBlank);
|
|
|
+ bgfx::destroyProgram(m_programFrontBlank);
|
|
|
+ bgfx::destroyProgram(m_programBackColor);
|
|
|
+ bgfx::destroyProgram(m_programSideColor);
|
|
|
+ bgfx::destroyProgram(m_programFrontColor);
|
|
|
+ bgfx::destroyProgram(m_programSideTex);
|
|
|
+ bgfx::destroyProgram(m_programBackTex1);
|
|
|
+ bgfx::destroyProgram(m_programBackTex2);
|
|
|
+ bgfx::destroyProgram(m_programFrontTex1);
|
|
|
+ bgfx::destroyProgram(m_programFrontTex2);
|
|
|
+
|
|
|
+ cameraDestroy();
|
|
|
+ imguiDestroy();
|
|
|
+
|
|
|
+ // Shutdown bgfx.
|
|
|
+ bgfx::shutdown();
|
|
|
+
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
|
|
|
- imguiSeparatorLine();
|
|
|
- imguiLabel("Stencil buffer implementation:");
|
|
|
- settings_shadowVolumeImpl = (imguiCheck("Depth fail", ShadowVolumeImpl::DepthFail == settings_shadowVolumeImpl, !settings_mixedSvImpl) ? ShadowVolumeImpl::DepthFail : settings_shadowVolumeImpl);
|
|
|
- settings_shadowVolumeImpl = (imguiCheck("Depth pass", ShadowVolumeImpl::DepthPass == settings_shadowVolumeImpl, !settings_mixedSvImpl) ? ShadowVolumeImpl::DepthPass : settings_shadowVolumeImpl);
|
|
|
- settings_mixedSvImpl = (imguiCheck("Mixed", settings_mixedSvImpl) ? !settings_mixedSvImpl : settings_mixedSvImpl);
|
|
|
-
|
|
|
- imguiLabel("Shadow volume implementation:");
|
|
|
- settings_shadowVolumeAlgorithm = (imguiCheck("Face based impl.", ShadowVolumeAlgorithm::FaceBased == settings_shadowVolumeAlgorithm) ? ShadowVolumeAlgorithm::FaceBased : settings_shadowVolumeAlgorithm);
|
|
|
- settings_shadowVolumeAlgorithm = (imguiCheck("Edge based impl.", ShadowVolumeAlgorithm::EdgeBased == settings_shadowVolumeAlgorithm) ? ShadowVolumeAlgorithm::EdgeBased : settings_shadowVolumeAlgorithm);
|
|
|
-
|
|
|
- imguiLabel("Stencil:");
|
|
|
- if (imguiCheck("Use stencil buffer", !settings_useStencilTexture) )
|
|
|
+ bool update() BX_OVERRIDE
|
|
|
+ {
|
|
|
+ if (!entry::processEvents(m_viewState.m_width, m_viewState.m_height, m_debug, m_reset, &m_mouseState) )
|
|
|
{
|
|
|
- if (settings_useStencilTexture)
|
|
|
+ s_uniforms.submitConstUniforms();
|
|
|
+
|
|
|
+ // Set projection matrices.
|
|
|
+ const float fov = 60.0f;
|
|
|
+ const float aspect = float(m_viewState.m_width)/float(m_viewState.m_height);
|
|
|
+ const float nearPlane = 1.0f;
|
|
|
+ const float farPlane = 1000.0f;
|
|
|
+
|
|
|
+ // Respond properly on resize.
|
|
|
+ if (m_oldWidth != m_viewState.m_width
|
|
|
+ || m_oldHeight != m_viewState.m_height)
|
|
|
{
|
|
|
- settings_useStencilTexture = false;
|
|
|
+ m_oldWidth = m_viewState.m_width;
|
|
|
+ m_oldHeight = m_viewState.m_height;
|
|
|
+
|
|
|
+ bgfx::destroyFrameBuffer(s_stencilFb);
|
|
|
+
|
|
|
+ bgfx::TextureHandle fbtextures[] =
|
|
|
+ {
|
|
|
+ bgfx::createTexture2D(uint16_t(m_viewState.m_width), uint16_t(m_viewState.m_height), false, 1, bgfx::TextureFormat::BGRA8, BGFX_TEXTURE_U_CLAMP|BGFX_TEXTURE_V_CLAMP|BGFX_TEXTURE_RT),
|
|
|
+ bgfx::createTexture2D(uint16_t(m_viewState.m_width), uint16_t(m_viewState.m_height), false, 1, bgfx::TextureFormat::D16, BGFX_TEXTURE_RT_WRITE_ONLY)
|
|
|
+ };
|
|
|
+ s_stencilFb = bgfx::createFrameBuffer(BX_COUNTOF(fbtextures), fbtextures, true);
|
|
|
}
|
|
|
- }
|
|
|
- if (imguiCheck("Use texture as stencil", settings_useStencilTexture) )
|
|
|
- {
|
|
|
- if (!settings_useStencilTexture)
|
|
|
+
|
|
|
+ // 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;
|
|
|
+ float time = (float)( (now - m_timeOffset)/double(bx::getHPFrequency() ) );
|
|
|
+ const float deltaTime = float(frameTime/freq);
|
|
|
+ s_uniforms.m_time = time;
|
|
|
+
|
|
|
+ // Update camera.
|
|
|
+ cameraUpdate(deltaTime, m_mouseState);
|
|
|
+
|
|
|
+ // Set view and projection matrix for view 0.
|
|
|
+ const bgfx::HMD* hmd = bgfx::getHMD();
|
|
|
+ if (NULL != hmd && 0 != (hmd->flags & BGFX_HMD_RENDERING) )
|
|
|
{
|
|
|
- settings_useStencilTexture = true;
|
|
|
+ float eye[3];
|
|
|
+ cameraGetPosition(eye);
|
|
|
+
|
|
|
+ bx::mtxQuatTranslationHMD(m_viewState.m_view, hmd->eye[0].rotation, eye);
|
|
|
+ bx::mtxProj(m_viewState.m_proj, hmd->eye[0].fov, nearPlane, farPlane, s_oglNdc);
|
|
|
+
|
|
|
+ m_viewState.m_width = hmd->width;
|
|
|
+ m_viewState.m_height = hmd->height;
|
|
|
}
|
|
|
- }
|
|
|
-
|
|
|
- imguiSeparatorLine();
|
|
|
- imguiLabel("Mesh:");
|
|
|
- if (imguiCheck("Bunny - high poly", BunnyHighPoly == currentMesh) )
|
|
|
- {
|
|
|
- currentMesh = BunnyHighPoly;
|
|
|
- }
|
|
|
-
|
|
|
- if (imguiCheck("Bunny - low poly", BunnyLowPoly == currentMesh) )
|
|
|
- {
|
|
|
- currentMesh = BunnyLowPoly;
|
|
|
- }
|
|
|
-
|
|
|
- if (Scene1 == currentScene)
|
|
|
- {
|
|
|
- imguiSlider("Instance count", settings_instanceCount, 1.0f, float(MAX_INSTANCE_COUNT), 1.0f);
|
|
|
- }
|
|
|
-
|
|
|
- imguiLabel("CPU Time: %7.1f [ms]", double(profTime)*toMs);
|
|
|
- imguiLabel("Volume Vertices: %5.uk", numShadowVolumeVertices/1000);
|
|
|
- imguiLabel("Volume Indices: %6.uk", numShadowVolumeIndices/1000);
|
|
|
- numShadowVolumeVertices = 0;
|
|
|
- numShadowVolumeIndices = 0;
|
|
|
-
|
|
|
- imguiSeparatorLine();
|
|
|
- settings_drawShadowVolumes = imguiCheck("Draw Shadow Volumes", settings_drawShadowVolumes)
|
|
|
- ? !settings_drawShadowVolumes
|
|
|
- : settings_drawShadowVolumes
|
|
|
+ else
|
|
|
+ {
|
|
|
+ cameraGetViewMtx(m_viewState.m_view);
|
|
|
+ bx::mtxProj(m_viewState.m_proj, fov, aspect, nearPlane, farPlane, s_oglNdc);
|
|
|
+ }
|
|
|
+
|
|
|
+ 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
|
|
|
+ , uint16_t(m_viewState.m_width)
|
|
|
+ , uint16_t(m_viewState.m_height)
|
|
|
+ );
|
|
|
+
|
|
|
+ imguiBeginScrollArea("Settings", m_viewState.m_width - 256 - 10, 10, 256, 700, &m_scrollAreaRight);
|
|
|
+
|
|
|
+ const char* titles[2] =
|
|
|
+ {
|
|
|
+ "Scene 0",
|
|
|
+ "Scene 1",
|
|
|
+ };
|
|
|
+
|
|
|
+ if (imguiCheck(titles[Scene0], Scene0 == m_currentScene) )
|
|
|
+ {
|
|
|
+ m_currentScene = Scene0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (imguiCheck(titles[Scene1], Scene1 == m_currentScene) )
|
|
|
+ {
|
|
|
+ m_currentScene = Scene1;
|
|
|
+ }
|
|
|
+
|
|
|
+ imguiSlider("Lights", m_settings_numLights, 1.0f, float(MAX_LIGHTS_COUNT), 1.0f);
|
|
|
+
|
|
|
+ if (imguiCheck("Update lights", m_settings_updateLights) )
|
|
|
+ {
|
|
|
+ m_settings_updateLights = !m_settings_updateLights;
|
|
|
+ }
|
|
|
+
|
|
|
+ imguiIndent();
|
|
|
+
|
|
|
+ if (imguiCheck("Light pattern 0", LightPattern0 == m_lightPattern, m_settings_updateLights) )
|
|
|
+ {
|
|
|
+ m_lightPattern = LightPattern0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (imguiCheck("Light pattern 1", LightPattern1 == m_lightPattern, m_settings_updateLights) )
|
|
|
+ {
|
|
|
+ m_lightPattern = LightPattern1;
|
|
|
+ }
|
|
|
+
|
|
|
+ imguiUnindent();
|
|
|
+
|
|
|
+ if (imguiCheck("Update scene", m_settings_updateScene, Scene0 == m_currentScene) )
|
|
|
+ {
|
|
|
+ m_settings_updateScene = !m_settings_updateScene;
|
|
|
+ }
|
|
|
+
|
|
|
+ imguiSeparatorLine();
|
|
|
+ imguiLabel("Stencil buffer implementation:");
|
|
|
+ m_settings_shadowVolumeImpl = (imguiCheck("Depth fail", ShadowVolumeImpl::DepthFail == m_settings_shadowVolumeImpl, !m_settings_mixedSvImpl) ? ShadowVolumeImpl::DepthFail : m_settings_shadowVolumeImpl);
|
|
|
+ m_settings_shadowVolumeImpl = (imguiCheck("Depth pass", ShadowVolumeImpl::DepthPass == m_settings_shadowVolumeImpl, !m_settings_mixedSvImpl) ? ShadowVolumeImpl::DepthPass : m_settings_shadowVolumeImpl);
|
|
|
+ m_settings_mixedSvImpl = (imguiCheck("Mixed", m_settings_mixedSvImpl) ? !m_settings_mixedSvImpl : m_settings_mixedSvImpl);
|
|
|
+
|
|
|
+ imguiLabel("Shadow volume implementation:");
|
|
|
+ m_settings_shadowVolumeAlgorithm = (imguiCheck("Face based impl.", ShadowVolumeAlgorithm::FaceBased == m_settings_shadowVolumeAlgorithm) ? ShadowVolumeAlgorithm::FaceBased : m_settings_shadowVolumeAlgorithm);
|
|
|
+ m_settings_shadowVolumeAlgorithm = (imguiCheck("Edge based impl.", ShadowVolumeAlgorithm::EdgeBased == m_settings_shadowVolumeAlgorithm) ? ShadowVolumeAlgorithm::EdgeBased : m_settings_shadowVolumeAlgorithm);
|
|
|
+
|
|
|
+ imguiLabel("Stencil:");
|
|
|
+ if (imguiCheck("Use stencil buffer", !m_settings_useStencilTexture) )
|
|
|
+ {
|
|
|
+ if (m_settings_useStencilTexture)
|
|
|
+ {
|
|
|
+ m_settings_useStencilTexture = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (imguiCheck("Use texture as stencil", m_settings_useStencilTexture) )
|
|
|
+ {
|
|
|
+ if (!m_settings_useStencilTexture)
|
|
|
+ {
|
|
|
+ m_settings_useStencilTexture = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ imguiSeparatorLine();
|
|
|
+ imguiLabel("Mesh:");
|
|
|
+ if (imguiCheck("Bunny - high poly", BunnyHighPoly == m_currentMesh) )
|
|
|
+ {
|
|
|
+ m_currentMesh = BunnyHighPoly;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (imguiCheck("Bunny - low poly", BunnyLowPoly == m_currentMesh) )
|
|
|
+ {
|
|
|
+ m_currentMesh = BunnyLowPoly;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (Scene1 == m_currentScene)
|
|
|
+ {
|
|
|
+ imguiSlider("Instance count", m_settings_instanceCount, 1.0f, float(MAX_INSTANCE_COUNT), 1.0f);
|
|
|
+ }
|
|
|
+
|
|
|
+ imguiLabel("CPU Time: %7.1f [ms]", double(m_profTime)*toMs);
|
|
|
+ imguiLabel("Volume Vertices: %5.uk", m_numShadowVolumeVertices/1000);
|
|
|
+ imguiLabel("Volume Indices: %6.uk", m_numShadowVolumeIndices/1000);
|
|
|
+ m_numShadowVolumeVertices = 0;
|
|
|
+ m_numShadowVolumeIndices = 0;
|
|
|
+
|
|
|
+ imguiSeparatorLine();
|
|
|
+ m_settings_drawShadowVolumes = imguiCheck("Draw Shadow Volumes", m_settings_drawShadowVolumes)
|
|
|
+ ? !m_settings_drawShadowVolumes
|
|
|
+ : m_settings_drawShadowVolumes
|
|
|
;
|
|
|
- imguiIndent();
|
|
|
- imguiUnindent();
|
|
|
-
|
|
|
- imguiEndScrollArea();
|
|
|
-
|
|
|
- static int32_t scrollAreaLeft = 0;
|
|
|
- imguiBeginScrollArea("Show help:", 10, viewState.m_height - 77 - 10, 120, 77, &scrollAreaLeft);
|
|
|
- settings_showHelp = imguiButton(settings_showHelp ? "ON" : "OFF")
|
|
|
- ? !settings_showHelp
|
|
|
- : settings_showHelp
|
|
|
+ imguiIndent();
|
|
|
+ imguiUnindent();
|
|
|
+
|
|
|
+ imguiEndScrollArea();
|
|
|
+
|
|
|
+ static int32_t scrollAreaLeft = 0;
|
|
|
+ imguiBeginScrollArea("Show help:", 10, m_viewState.m_height - 77 - 10, 120, 77, &scrollAreaLeft);
|
|
|
+ m_settings_showHelp = imguiButton(m_settings_showHelp ? "ON" : "OFF")
|
|
|
+ ? !m_settings_showHelp
|
|
|
+ : m_settings_showHelp
|
|
|
;
|
|
|
-
|
|
|
- imguiEndScrollArea();
|
|
|
-
|
|
|
- imguiEndFrame();
|
|
|
-
|
|
|
- //update settings
|
|
|
- s_uniforms.m_params.m_ambientPass = 1.0f;
|
|
|
- s_uniforms.m_params.m_lightingPass = 1.0f;
|
|
|
- s_uniforms.m_params.m_texelHalf = s_texelHalf;
|
|
|
- s_uniforms.m_svparams.m_useStencilTex = float(settings_useStencilTexture);
|
|
|
-
|
|
|
- //set picked bunny model
|
|
|
- Model* bunnyModel = BunnyLowPoly == currentMesh ? &bunnyLowPolyModel : &bunnyHighPolyModel;
|
|
|
-
|
|
|
- //update time accumulators
|
|
|
- static float sceneTimeAccumulator = 0.0f;
|
|
|
- if (settings_updateScene)
|
|
|
- {
|
|
|
- sceneTimeAccumulator += deltaTime;
|
|
|
- }
|
|
|
-
|
|
|
- static float lightTimeAccumulator = 0.0f;
|
|
|
- if (settings_updateLights)
|
|
|
- {
|
|
|
- lightTimeAccumulator += deltaTime;
|
|
|
- }
|
|
|
-
|
|
|
- //setup light positions
|
|
|
- float lightPosRadius[MAX_LIGHTS_COUNT][4];
|
|
|
- if (LightPattern0 == lightPattern)
|
|
|
- {
|
|
|
- for (uint8_t ii = 0; ii < settings_numLights; ++ii)
|
|
|
+
|
|
|
+ imguiEndScrollArea();
|
|
|
+
|
|
|
+ imguiEndFrame();
|
|
|
+
|
|
|
+ //update settings
|
|
|
+ s_uniforms.m_params.m_ambientPass = 1.0f;
|
|
|
+ s_uniforms.m_params.m_lightingPass = 1.0f;
|
|
|
+ s_uniforms.m_params.m_texelHalf = s_texelHalf;
|
|
|
+ s_uniforms.m_svparams.m_useStencilTex = float(m_settings_useStencilTexture);
|
|
|
+
|
|
|
+ //set picked bunny model
|
|
|
+ Model* bunnyModel = BunnyLowPoly == m_currentMesh ? &m_bunnyLowPolyModel : &m_bunnyHighPolyModel;
|
|
|
+
|
|
|
+ //update time accumulators
|
|
|
+ static float sceneTimeAccumulator = 0.0f;
|
|
|
+ if (m_settings_updateScene)
|
|
|
{
|
|
|
- lightPosRadius[ii][0] = bx::fcos(2.0f*bx::kPi/settings_numLights * float(ii) + lightTimeAccumulator * 1.1f + 3.0f) * 20.0f;
|
|
|
- lightPosRadius[ii][1] = 20.0f;
|
|
|
- lightPosRadius[ii][2] = bx::fsin(2.0f*bx::kPi/settings_numLights * float(ii) + lightTimeAccumulator * 1.1f + 3.0f) * 20.0f;
|
|
|
- lightPosRadius[ii][3] = 20.0f;
|
|
|
+ sceneTimeAccumulator += deltaTime;
|
|
|
}
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- for (uint8_t ii = 0; ii < settings_numLights; ++ii)
|
|
|
+
|
|
|
+ static float lightTimeAccumulator = 0.0f;
|
|
|
+ if (m_settings_updateLights)
|
|
|
{
|
|
|
- lightPosRadius[ii][0] = bx::fcos(float(ii) * 2.0f/settings_numLights + lightTimeAccumulator * 1.3f + bx::kPi) * 40.0f;
|
|
|
- lightPosRadius[ii][1] = 20.0f;
|
|
|
- lightPosRadius[ii][2] = bx::fsin(float(ii) * 2.0f/settings_numLights + lightTimeAccumulator * 1.3f + bx::kPi) * 40.0f;
|
|
|
- lightPosRadius[ii][3] = 20.0f;
|
|
|
+ lightTimeAccumulator += deltaTime;
|
|
|
}
|
|
|
- }
|
|
|
-
|
|
|
- //use debug font to print information about this example.
|
|
|
- bgfx::dbgTextClear();
|
|
|
- bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/14-shadowvolumes");
|
|
|
- bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Shadow volumes.");
|
|
|
- bgfx::dbgTextPrintf(0, 3, 0x0f, "Frame: % 7.3f[ms]", double(frameTime)*toMs);
|
|
|
-
|
|
|
- if (settings_showHelp)
|
|
|
- {
|
|
|
- uint8_t row = 5;
|
|
|
- bgfx::dbgTextPrintf(3, row++, 0x0f, "Stencil buffer implementation:");
|
|
|
- bgfx::dbgTextPrintf(8, row++, 0x0f, "Depth fail - Robust, but slower than 'Depth pass'. Requires computing and drawing of shadow volume caps.");
|
|
|
- bgfx::dbgTextPrintf(8, row++, 0x0f, "Depth pass - Faster, but not stable. Shadows are wrong when camera is in the shadow.");
|
|
|
- bgfx::dbgTextPrintf(8, row++, 0x0f, "Mixed - 'Depth pass' where possible, 'Depth fail' where necessary. Best of both words.");
|
|
|
-
|
|
|
- row++;
|
|
|
- bgfx::dbgTextPrintf(3, row++, 0x0f, "Shadow volume implementation:");
|
|
|
- bgfx::dbgTextPrintf(8, row++, 0x0f, "Face Based - Slower. Works fine with either stencil buffer or texture as stencil.");
|
|
|
- bgfx::dbgTextPrintf(8, row++, 0x0f, "Edge Based - Faster, but requires +2 incr/decr on stencil buffer. To avoid massive redraw, use RGBA texture as stencil.");
|
|
|
-
|
|
|
- row++;
|
|
|
- bgfx::dbgTextPrintf(3, row++, 0x0f, "Stencil:");
|
|
|
- bgfx::dbgTextPrintf(8, row++, 0x0f, "Stencil buffer - Faster, but capable only of +1 incr.");
|
|
|
- bgfx::dbgTextPrintf(8, row++, 0x0f, "Texture as stencil - Slower, but capable of +2 incr.");
|
|
|
- }
|
|
|
-
|
|
|
- // Setup instances
|
|
|
- Instance shadowCasters[SceneCount][60];
|
|
|
- uint16_t shadowCastersCount[SceneCount];
|
|
|
- for (uint8_t ii = 0; ii < SceneCount; ++ii)
|
|
|
- {
|
|
|
- shadowCastersCount[ii] = 0;
|
|
|
- }
|
|
|
-
|
|
|
- Instance shadowReceivers[SceneCount][10];
|
|
|
- uint16_t shadowReceiversCount[SceneCount];
|
|
|
- for (uint8_t ii = 0; ii < SceneCount; ++ii)
|
|
|
- {
|
|
|
- shadowReceiversCount[ii] = 0;
|
|
|
- }
|
|
|
-
|
|
|
- // Scene 0 - shadow casters - Bunny
|
|
|
- {
|
|
|
- Instance& inst = shadowCasters[Scene0][shadowCastersCount[Scene0]++];
|
|
|
- inst.m_scale[0] = 5.0f;
|
|
|
- inst.m_scale[1] = 5.0f;
|
|
|
- inst.m_scale[2] = 5.0f;
|
|
|
- inst.m_rotation[0] = 0.0f;
|
|
|
- inst.m_rotation[1] = float(4.0f - sceneTimeAccumulator * 0.7f);
|
|
|
- inst.m_rotation[2] = 0.0f;
|
|
|
- inst.m_pos[0] = 0.0f;
|
|
|
- inst.m_pos[1] = 10.0f;
|
|
|
- inst.m_pos[2] = 0.0f;
|
|
|
- inst.m_color[0] = 0.68f;
|
|
|
- inst.m_color[1] = 0.65f;
|
|
|
- inst.m_color[2] = 0.60f;
|
|
|
- inst.m_model = bunnyModel;
|
|
|
- }
|
|
|
-
|
|
|
- // Scene 0 - shadow casters - Cubes top.
|
|
|
- const uint8_t numCubesTop = 9;
|
|
|
- for (uint16_t ii = 0; ii < numCubesTop; ++ii)
|
|
|
- {
|
|
|
- Instance& inst = shadowCasters[Scene0][shadowCastersCount[Scene0]++];
|
|
|
- inst.m_scale[0] = 1.0f;
|
|
|
- inst.m_scale[1] = 1.0f;
|
|
|
- inst.m_scale[2] = 1.0f;
|
|
|
- inst.m_rotation[0] = 0.0f;
|
|
|
- inst.m_rotation[1] = 0.0f;
|
|
|
- inst.m_rotation[2] = 0.0f;
|
|
|
- inst.m_pos[0] = bx::fsin(ii * 2.0f + 13.0f + sceneTimeAccumulator * 1.1f) * 13.0f;
|
|
|
- inst.m_pos[1] = 6.0f;
|
|
|
- inst.m_pos[2] = bx::fcos(ii * 2.0f + 13.0f + sceneTimeAccumulator * 1.1f) * 13.0f;
|
|
|
- inst.m_model = &cubeModel;
|
|
|
- }
|
|
|
-
|
|
|
- // Scene 0 - shadow casters - Cubes bottom.
|
|
|
- const uint8_t numCubesBottom = 9;
|
|
|
- for (uint16_t ii = 0; ii < numCubesBottom; ++ii)
|
|
|
- {
|
|
|
- Instance& inst = shadowCasters[Scene0][shadowCastersCount[Scene0]++];
|
|
|
- inst.m_scale[0] = 1.0f;
|
|
|
- inst.m_scale[1] = 1.0f;
|
|
|
- inst.m_scale[2] = 1.0f;
|
|
|
- inst.m_rotation[0] = 0.0f;
|
|
|
- inst.m_rotation[1] = 0.0f;
|
|
|
- inst.m_rotation[2] = 0.0f;
|
|
|
- inst.m_pos[0] = bx::fsin(ii * 2.0f + 13.0f + sceneTimeAccumulator * 1.1f) * 13.0f;
|
|
|
- inst.m_pos[1] = 22.0f;
|
|
|
- inst.m_pos[2] = bx::fcos(ii * 2.0f + 13.0f + sceneTimeAccumulator * 1.1f) * 13.0f;
|
|
|
- inst.m_model = &cubeModel;
|
|
|
- }
|
|
|
-
|
|
|
- // Scene 0 - shadow casters - Columns.
|
|
|
- const float dist = 16.0f;
|
|
|
- const float columnPositions[][3] =
|
|
|
- {
|
|
|
- { dist, 3.3f, dist },
|
|
|
- { -dist, 3.3f, dist },
|
|
|
- { dist, 3.3f, -dist },
|
|
|
- { -dist, 3.3f, -dist },
|
|
|
- };
|
|
|
-
|
|
|
- for (uint8_t ii = 0; ii < 4; ++ii)
|
|
|
- {
|
|
|
- Instance& inst = shadowCasters[Scene0][shadowCastersCount[Scene0]++];
|
|
|
- inst.m_scale[0] = 1.5f;
|
|
|
- inst.m_scale[1] = 1.5f;
|
|
|
- inst.m_scale[2] = 1.5f;
|
|
|
- inst.m_rotation[0] = 0.0f;
|
|
|
- inst.m_rotation[1] = 1.57f;
|
|
|
- inst.m_rotation[2] = 0.0f;
|
|
|
- inst.m_pos[0] = columnPositions[ii][0];
|
|
|
- inst.m_pos[1] = columnPositions[ii][1];
|
|
|
- inst.m_pos[2] = columnPositions[ii][2];
|
|
|
- inst.m_color[0] = 0.25f;
|
|
|
- inst.m_color[1] = 0.25f;
|
|
|
- inst.m_color[2] = 0.25f;
|
|
|
- inst.m_model = &columnModel;
|
|
|
- }
|
|
|
-
|
|
|
- // Scene 0 - shadow casters - Ceiling.
|
|
|
- {
|
|
|
- Instance& inst = shadowCasters[Scene0][shadowCastersCount[Scene0]++];
|
|
|
- inst.m_scale[0] = 21.0f;
|
|
|
- inst.m_scale[1] = 21.0f;
|
|
|
- inst.m_scale[2] = 21.0f;
|
|
|
- inst.m_rotation[0] = bx::kPi;
|
|
|
- inst.m_rotation[1] = 0.0f;
|
|
|
- inst.m_rotation[2] = 0.0f;
|
|
|
- inst.m_pos[0] = 0.0f;
|
|
|
- inst.m_pos[1] = 28.2f;
|
|
|
- inst.m_pos[2] = 0.0f;
|
|
|
- inst.m_model = &platformModel;
|
|
|
- inst.m_svExtrusionDistance = 2.0f; //prevent culling on tight view frustum
|
|
|
- }
|
|
|
-
|
|
|
- // Scene 0 - shadow casters - Platform.
|
|
|
- {
|
|
|
- Instance& inst = shadowCasters[Scene0][shadowCastersCount[Scene0]++];
|
|
|
- inst.m_scale[0] = 24.0f;
|
|
|
- inst.m_scale[1] = 24.0f;
|
|
|
- inst.m_scale[2] = 24.0f;
|
|
|
- inst.m_rotation[0] = 0.0f;
|
|
|
- inst.m_rotation[1] = 0.0f;
|
|
|
- inst.m_rotation[2] = 0.0f;
|
|
|
- inst.m_pos[0] = 0.0f;
|
|
|
- inst.m_pos[1] = 0.0f;
|
|
|
- inst.m_pos[2] = 0.0f;
|
|
|
- inst.m_model = &platformModel;
|
|
|
- inst.m_svExtrusionDistance = 2.0f; //prevent culling on tight view frustum
|
|
|
- }
|
|
|
-
|
|
|
- // Scene 0 - shadow receivers - Floor.
|
|
|
- {
|
|
|
- Instance& inst = shadowReceivers[Scene0][shadowReceiversCount[Scene0]++];
|
|
|
- inst.m_scale[0] = 500.0f;
|
|
|
- inst.m_scale[1] = 500.0f;
|
|
|
- inst.m_scale[2] = 500.0f;
|
|
|
- inst.m_rotation[0] = 0.0f;
|
|
|
- inst.m_rotation[1] = 0.0f;
|
|
|
- inst.m_rotation[2] = 0.0f;
|
|
|
- inst.m_pos[0] = 0.0f;
|
|
|
- inst.m_pos[1] = 0.0f;
|
|
|
- inst.m_pos[2] = 0.0f;
|
|
|
- inst.m_model = &hplaneFieldModel;
|
|
|
- }
|
|
|
-
|
|
|
- // Scene 1 - shadow casters - Bunny instances
|
|
|
- {
|
|
|
- enum Direction
|
|
|
+
|
|
|
+ //setup light positions
|
|
|
+ float lightPosRadius[MAX_LIGHTS_COUNT][4];
|
|
|
+ if (LightPattern0 == m_lightPattern)
|
|
|
{
|
|
|
- Left = 0x0,
|
|
|
- Down = 0x1,
|
|
|
- Right = 0x2,
|
|
|
- Up = 0x3,
|
|
|
- };
|
|
|
- const uint8_t directionMask = 0x3;
|
|
|
-
|
|
|
- uint8_t currentDirection = Left;
|
|
|
- float currX = 0.0f;
|
|
|
- float currY = 0.0f;
|
|
|
- const float stepX = 20.0f;
|
|
|
- const float stepY = 20.0f;
|
|
|
- uint8_t stateStep = 0;
|
|
|
- uint8_t stateChange = 1;
|
|
|
-
|
|
|
- for (uint8_t ii = 0; ii < settings_instanceCount; ++ii)
|
|
|
+ for (uint8_t ii = 0; ii < m_settings_numLights; ++ii)
|
|
|
+ {
|
|
|
+ lightPosRadius[ii][0] = bx::fcos(2.0f*bx::kPi/m_settings_numLights * float(ii) + lightTimeAccumulator * 1.1f + 3.0f) * 20.0f;
|
|
|
+ lightPosRadius[ii][1] = 20.0f;
|
|
|
+ lightPosRadius[ii][2] = bx::fsin(2.0f*bx::kPi/m_settings_numLights * float(ii) + lightTimeAccumulator * 1.1f + 3.0f) * 20.0f;
|
|
|
+ lightPosRadius[ii][3] = 20.0f;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ for (uint8_t ii = 0; ii < m_settings_numLights; ++ii)
|
|
|
+ {
|
|
|
+ lightPosRadius[ii][0] = bx::fcos(float(ii) * 2.0f/m_settings_numLights + lightTimeAccumulator * 1.3f + bx::kPi) * 40.0f;
|
|
|
+ lightPosRadius[ii][1] = 20.0f;
|
|
|
+ lightPosRadius[ii][2] = bx::fsin(float(ii) * 2.0f/m_settings_numLights + lightTimeAccumulator * 1.3f + bx::kPi) * 40.0f;
|
|
|
+ lightPosRadius[ii][3] = 20.0f;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //use debug font to print information about this example.
|
|
|
+ bgfx::dbgTextClear();
|
|
|
+ bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/14-shadowvolumes");
|
|
|
+ bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Shadow volumes.");
|
|
|
+ bgfx::dbgTextPrintf(0, 3, 0x0f, "Frame: % 7.3f[ms]", double(frameTime)*toMs);
|
|
|
+
|
|
|
+ if (m_settings_showHelp)
|
|
|
{
|
|
|
- Instance& inst = shadowCasters[Scene1][shadowCastersCount[Scene1]++];
|
|
|
+ uint8_t row = 5;
|
|
|
+ bgfx::dbgTextPrintf(3, row++, 0x0f, "Stencil buffer implementation:");
|
|
|
+ bgfx::dbgTextPrintf(8, row++, 0x0f, "Depth fail - Robust, but slower than 'Depth pass'. Requires computing and drawing of shadow volume caps.");
|
|
|
+ bgfx::dbgTextPrintf(8, row++, 0x0f, "Depth pass - Faster, but not stable. Shadows are wrong when camera is in the shadow.");
|
|
|
+ bgfx::dbgTextPrintf(8, row++, 0x0f, "Mixed - 'Depth pass' where possible, 'Depth fail' where necessary. Best of both words.");
|
|
|
+
|
|
|
+ row++;
|
|
|
+ bgfx::dbgTextPrintf(3, row++, 0x0f, "Shadow volume implementation:");
|
|
|
+ bgfx::dbgTextPrintf(8, row++, 0x0f, "Face Based - Slower. Works fine with either stencil buffer or texture as stencil.");
|
|
|
+ bgfx::dbgTextPrintf(8, row++, 0x0f, "Edge Based - Faster, but requires +2 incr/decr on stencil buffer. To avoid massive redraw, use RGBA texture as stencil.");
|
|
|
+
|
|
|
+ row++;
|
|
|
+ bgfx::dbgTextPrintf(3, row++, 0x0f, "Stencil:");
|
|
|
+ bgfx::dbgTextPrintf(8, row++, 0x0f, "Stencil buffer - Faster, but capable only of +1 incr.");
|
|
|
+ bgfx::dbgTextPrintf(8, row++, 0x0f, "Texture as stencil - Slower, but capable of +2 incr.");
|
|
|
+ }
|
|
|
+
|
|
|
+ // Setup instances
|
|
|
+ Instance shadowCasters[SceneCount][60];
|
|
|
+ uint16_t shadowCastersCount[SceneCount];
|
|
|
+ for (uint8_t ii = 0; ii < SceneCount; ++ii)
|
|
|
+ {
|
|
|
+ shadowCastersCount[ii] = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ Instance shadowReceivers[SceneCount][10];
|
|
|
+ uint16_t shadowReceiversCount[SceneCount];
|
|
|
+ for (uint8_t ii = 0; ii < SceneCount; ++ii)
|
|
|
+ {
|
|
|
+ shadowReceiversCount[ii] = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Scene 0 - shadow casters - Bunny
|
|
|
+ {
|
|
|
+ Instance& inst = shadowCasters[Scene0][shadowCastersCount[Scene0]++];
|
|
|
inst.m_scale[0] = 5.0f;
|
|
|
inst.m_scale[1] = 5.0f;
|
|
|
inst.m_scale[2] = 5.0f;
|
|
|
inst.m_rotation[0] = 0.0f;
|
|
|
- inst.m_rotation[1] = bx::kPi;
|
|
|
+ inst.m_rotation[1] = float(4.0f - sceneTimeAccumulator * 0.7f);
|
|
|
inst.m_rotation[2] = 0.0f;
|
|
|
- inst.m_pos[0] = currX;
|
|
|
- inst.m_pos[1] = 0.0f;
|
|
|
- inst.m_pos[2] = currY;
|
|
|
+ inst.m_pos[0] = 0.0f;
|
|
|
+ inst.m_pos[1] = 10.0f;
|
|
|
+ inst.m_pos[2] = 0.0f;
|
|
|
+ inst.m_color[0] = 0.68f;
|
|
|
+ inst.m_color[1] = 0.65f;
|
|
|
+ inst.m_color[2] = 0.60f;
|
|
|
inst.m_model = bunnyModel;
|
|
|
-
|
|
|
- ++stateStep;
|
|
|
- if (stateStep >= ( (stateChange & ~0x1) >> 1) )
|
|
|
+ }
|
|
|
+
|
|
|
+ // Scene 0 - shadow casters - Cubes top.
|
|
|
+ const uint8_t numCubesTop = 9;
|
|
|
+ for (uint16_t ii = 0; ii < numCubesTop; ++ii)
|
|
|
+ {
|
|
|
+ Instance& inst = shadowCasters[Scene0][shadowCastersCount[Scene0]++];
|
|
|
+ inst.m_scale[0] = 1.0f;
|
|
|
+ inst.m_scale[1] = 1.0f;
|
|
|
+ inst.m_scale[2] = 1.0f;
|
|
|
+ inst.m_rotation[0] = 0.0f;
|
|
|
+ inst.m_rotation[1] = 0.0f;
|
|
|
+ inst.m_rotation[2] = 0.0f;
|
|
|
+ inst.m_pos[0] = bx::fsin(ii * 2.0f + 13.0f + sceneTimeAccumulator * 1.1f) * 13.0f;
|
|
|
+ inst.m_pos[1] = 6.0f;
|
|
|
+ inst.m_pos[2] = bx::fcos(ii * 2.0f + 13.0f + sceneTimeAccumulator * 1.1f) * 13.0f;
|
|
|
+ inst.m_model = &m_cubeModel;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Scene 0 - shadow casters - Cubes bottom.
|
|
|
+ const uint8_t numCubesBottom = 9;
|
|
|
+ for (uint16_t ii = 0; ii < numCubesBottom; ++ii)
|
|
|
+ {
|
|
|
+ Instance& inst = shadowCasters[Scene0][shadowCastersCount[Scene0]++];
|
|
|
+ inst.m_scale[0] = 1.0f;
|
|
|
+ inst.m_scale[1] = 1.0f;
|
|
|
+ inst.m_scale[2] = 1.0f;
|
|
|
+ inst.m_rotation[0] = 0.0f;
|
|
|
+ inst.m_rotation[1] = 0.0f;
|
|
|
+ inst.m_rotation[2] = 0.0f;
|
|
|
+ inst.m_pos[0] = bx::fsin(ii * 2.0f + 13.0f + sceneTimeAccumulator * 1.1f) * 13.0f;
|
|
|
+ inst.m_pos[1] = 22.0f;
|
|
|
+ inst.m_pos[2] = bx::fcos(ii * 2.0f + 13.0f + sceneTimeAccumulator * 1.1f) * 13.0f;
|
|
|
+ inst.m_model = &m_cubeModel;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Scene 0 - shadow casters - Columns.
|
|
|
+ const float dist = 16.0f;
|
|
|
+ const float columnPositions[][3] =
|
|
|
+ {
|
|
|
+ { dist, 3.3f, dist },
|
|
|
+ { -dist, 3.3f, dist },
|
|
|
+ { dist, 3.3f, -dist },
|
|
|
+ { -dist, 3.3f, -dist },
|
|
|
+ };
|
|
|
+
|
|
|
+ for (uint8_t ii = 0; ii < 4; ++ii)
|
|
|
+ {
|
|
|
+ Instance& inst = shadowCasters[Scene0][shadowCastersCount[Scene0]++];
|
|
|
+ inst.m_scale[0] = 1.5f;
|
|
|
+ inst.m_scale[1] = 1.5f;
|
|
|
+ inst.m_scale[2] = 1.5f;
|
|
|
+ inst.m_rotation[0] = 0.0f;
|
|
|
+ inst.m_rotation[1] = 1.57f;
|
|
|
+ inst.m_rotation[2] = 0.0f;
|
|
|
+ inst.m_pos[0] = columnPositions[ii][0];
|
|
|
+ inst.m_pos[1] = columnPositions[ii][1];
|
|
|
+ inst.m_pos[2] = columnPositions[ii][2];
|
|
|
+ inst.m_color[0] = 0.25f;
|
|
|
+ inst.m_color[1] = 0.25f;
|
|
|
+ inst.m_color[2] = 0.25f;
|
|
|
+ inst.m_model = &m_columnModel;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Scene 0 - shadow casters - Ceiling.
|
|
|
+ {
|
|
|
+ Instance& inst = shadowCasters[Scene0][shadowCastersCount[Scene0]++];
|
|
|
+ inst.m_scale[0] = 21.0f;
|
|
|
+ inst.m_scale[1] = 21.0f;
|
|
|
+ inst.m_scale[2] = 21.0f;
|
|
|
+ inst.m_rotation[0] = bx::kPi;
|
|
|
+ inst.m_rotation[1] = 0.0f;
|
|
|
+ inst.m_rotation[2] = 0.0f;
|
|
|
+ inst.m_pos[0] = 0.0f;
|
|
|
+ inst.m_pos[1] = 28.2f;
|
|
|
+ inst.m_pos[2] = 0.0f;
|
|
|
+ inst.m_model = &m_platformModel;
|
|
|
+ inst.m_svExtrusionDistance = 2.0f; //prevent culling on tight view frustum
|
|
|
+ }
|
|
|
+
|
|
|
+ // Scene 0 - shadow casters - Platform.
|
|
|
+ {
|
|
|
+ Instance& inst = shadowCasters[Scene0][shadowCastersCount[Scene0]++];
|
|
|
+ inst.m_scale[0] = 24.0f;
|
|
|
+ inst.m_scale[1] = 24.0f;
|
|
|
+ inst.m_scale[2] = 24.0f;
|
|
|
+ inst.m_rotation[0] = 0.0f;
|
|
|
+ inst.m_rotation[1] = 0.0f;
|
|
|
+ inst.m_rotation[2] = 0.0f;
|
|
|
+ inst.m_pos[0] = 0.0f;
|
|
|
+ inst.m_pos[1] = 0.0f;
|
|
|
+ inst.m_pos[2] = 0.0f;
|
|
|
+ inst.m_model = &m_platformModel;
|
|
|
+ inst.m_svExtrusionDistance = 2.0f; //prevent culling on tight view frustum
|
|
|
+ }
|
|
|
+
|
|
|
+ // Scene 0 - shadow receivers - Floor.
|
|
|
+ {
|
|
|
+ Instance& inst = shadowReceivers[Scene0][shadowReceiversCount[Scene0]++];
|
|
|
+ inst.m_scale[0] = 500.0f;
|
|
|
+ inst.m_scale[1] = 500.0f;
|
|
|
+ inst.m_scale[2] = 500.0f;
|
|
|
+ inst.m_rotation[0] = 0.0f;
|
|
|
+ inst.m_rotation[1] = 0.0f;
|
|
|
+ inst.m_rotation[2] = 0.0f;
|
|
|
+ inst.m_pos[0] = 0.0f;
|
|
|
+ inst.m_pos[1] = 0.0f;
|
|
|
+ inst.m_pos[2] = 0.0f;
|
|
|
+ inst.m_model = &m_hplaneFieldModel;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Scene 1 - shadow casters - Bunny instances
|
|
|
+ {
|
|
|
+ enum Direction
|
|
|
{
|
|
|
- currentDirection = (currentDirection + 1) & directionMask;
|
|
|
- stateStep = 0;
|
|
|
- ++stateChange;
|
|
|
- }
|
|
|
-
|
|
|
- switch (currentDirection)
|
|
|
+ Left = 0x0,
|
|
|
+ Down = 0x1,
|
|
|
+ Right = 0x2,
|
|
|
+ Up = 0x3,
|
|
|
+ };
|
|
|
+ const uint8_t directionMask = 0x3;
|
|
|
+
|
|
|
+ uint8_t currentDirection = Left;
|
|
|
+ float currX = 0.0f;
|
|
|
+ float currY = 0.0f;
|
|
|
+ const float stepX = 20.0f;
|
|
|
+ const float stepY = 20.0f;
|
|
|
+ uint8_t stateStep = 0;
|
|
|
+ uint8_t stateChange = 1;
|
|
|
+
|
|
|
+ for (uint8_t ii = 0; ii < m_settings_instanceCount; ++ii)
|
|
|
{
|
|
|
- case Left: currX -= stepX; break;
|
|
|
- case Down: currY -= stepY; break;
|
|
|
- case Right: currX += stepX; break;
|
|
|
- case Up: currY += stepY; break;
|
|
|
+ Instance& inst = shadowCasters[Scene1][shadowCastersCount[Scene1]++];
|
|
|
+ inst.m_scale[0] = 5.0f;
|
|
|
+ inst.m_scale[1] = 5.0f;
|
|
|
+ inst.m_scale[2] = 5.0f;
|
|
|
+ inst.m_rotation[0] = 0.0f;
|
|
|
+ inst.m_rotation[1] = bx::kPi;
|
|
|
+ inst.m_rotation[2] = 0.0f;
|
|
|
+ inst.m_pos[0] = currX;
|
|
|
+ inst.m_pos[1] = 0.0f;
|
|
|
+ inst.m_pos[2] = currY;
|
|
|
+ inst.m_model = bunnyModel;
|
|
|
+
|
|
|
+ ++stateStep;
|
|
|
+ if (stateStep >= ( (stateChange & ~0x1) >> 1) )
|
|
|
+ {
|
|
|
+ currentDirection = (currentDirection + 1) & directionMask;
|
|
|
+ stateStep = 0;
|
|
|
+ ++stateChange;
|
|
|
+ }
|
|
|
+
|
|
|
+ switch (currentDirection)
|
|
|
+ {
|
|
|
+ case Left: currX -= stepX; break;
|
|
|
+ case Down: currY -= stepY; break;
|
|
|
+ case Right: currX += stepX; break;
|
|
|
+ case Up: currY += stepY; break;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
- }
|
|
|
-
|
|
|
- // Scene 1 - shadow receivers - Floor.
|
|
|
- {
|
|
|
- Instance& inst = shadowReceivers[Scene1][shadowReceiversCount[Scene1]++];
|
|
|
- inst.m_scale[0] = 500.0f;
|
|
|
- inst.m_scale[1] = 500.0f;
|
|
|
- inst.m_scale[2] = 500.0f;
|
|
|
- inst.m_rotation[0] = 0.0f;
|
|
|
- inst.m_rotation[1] = 0.0f;
|
|
|
- inst.m_rotation[2] = 0.0f;
|
|
|
- inst.m_pos[0] = 0.0f;
|
|
|
- inst.m_pos[1] = 0.0f;
|
|
|
- inst.m_pos[2] = 0.0f;
|
|
|
- inst.m_model = &hplaneFigureModel;
|
|
|
- }
|
|
|
-
|
|
|
- // Make sure at the beginning everything gets cleared.
|
|
|
- bgfx::setViewClear(0
|
|
|
- , BGFX_CLEAR_COLOR
|
|
|
- | BGFX_CLEAR_DEPTH
|
|
|
- | BGFX_CLEAR_STENCIL
|
|
|
- , clearValues.m_clearRgba
|
|
|
- , clearValues.m_clearDepth
|
|
|
- , clearValues.m_clearStencil
|
|
|
- );
|
|
|
-
|
|
|
- ::touch(0);
|
|
|
-
|
|
|
- // Draw ambient only.
|
|
|
- s_uniforms.m_params.m_ambientPass = 1.0f;
|
|
|
- s_uniforms.m_params.m_lightingPass = 0.0f;
|
|
|
-
|
|
|
- s_uniforms.m_color[0] = 1.0f;
|
|
|
- s_uniforms.m_color[1] = 1.0f;
|
|
|
- s_uniforms.m_color[2] = 1.0f;
|
|
|
-
|
|
|
- const RenderState& drawAmbient = (settings_useStencilTexture ?
|
|
|
- s_renderStates[RenderState::ShadowVolume_UsingStencilTexture_DrawAmbient]:
|
|
|
- s_renderStates[RenderState::ShadowVolume_UsingStencilBuffer_DrawAmbient]);
|
|
|
-
|
|
|
- // Draw shadow casters.
|
|
|
- for (uint8_t ii = 0; ii < shadowCastersCount[currentScene]; ++ii)
|
|
|
- {
|
|
|
- shadowCasters[currentScene][ii].submit(VIEWID_RANGE1_PASS0, drawAmbient);
|
|
|
- }
|
|
|
-
|
|
|
- // Draw shadow receivers.
|
|
|
- for (uint8_t ii = 0; ii < shadowReceiversCount[currentScene]; ++ii)
|
|
|
- {
|
|
|
- shadowReceivers[currentScene][ii].submit(VIEWID_RANGE1_PASS0, drawAmbient);
|
|
|
- }
|
|
|
-
|
|
|
- // Using stencil texture requires rendering to separate render target. first pass is building depth buffer.
|
|
|
- if (settings_useStencilTexture)
|
|
|
- {
|
|
|
- bgfx::setViewClear(VIEWID_RANGE1_RT_PASS1, BGFX_CLEAR_DEPTH, 0x00000000, 1.0f, 0);
|
|
|
- bgfx::setViewFrameBuffer(VIEWID_RANGE1_RT_PASS1, s_stencilFb);
|
|
|
-
|
|
|
- const RenderState& renderState = s_renderStates[RenderState::ShadowVolume_UsingStencilTexture_BuildDepth];
|
|
|
-
|
|
|
- for (uint8_t ii = 0; ii < shadowCastersCount[currentScene]; ++ii)
|
|
|
- {
|
|
|
- shadowCasters[currentScene][ii].submit(VIEWID_RANGE1_RT_PASS1, renderState);
|
|
|
- }
|
|
|
-
|
|
|
- for (uint8_t ii = 0; ii < shadowReceiversCount[currentScene]; ++ii)
|
|
|
+
|
|
|
+ // Scene 1 - shadow receivers - Floor.
|
|
|
{
|
|
|
- shadowReceivers[currentScene][ii].submit(VIEWID_RANGE1_RT_PASS1, renderState);
|
|
|
+ Instance& inst = shadowReceivers[Scene1][shadowReceiversCount[Scene1]++];
|
|
|
+ inst.m_scale[0] = 500.0f;
|
|
|
+ inst.m_scale[1] = 500.0f;
|
|
|
+ inst.m_scale[2] = 500.0f;
|
|
|
+ inst.m_rotation[0] = 0.0f;
|
|
|
+ inst.m_rotation[1] = 0.0f;
|
|
|
+ inst.m_rotation[2] = 0.0f;
|
|
|
+ inst.m_pos[0] = 0.0f;
|
|
|
+ inst.m_pos[1] = 0.0f;
|
|
|
+ inst.m_pos[2] = 0.0f;
|
|
|
+ inst.m_model = &m_hplaneFigureModel;
|
|
|
}
|
|
|
- }
|
|
|
-
|
|
|
- profTime = bx::getHPCounter();
|
|
|
-
|
|
|
- /**
|
|
|
- * For each light:
|
|
|
- * 1. Compute and draw shadow volume to stencil buffer
|
|
|
- * 2. Draw diffuse with stencil test
|
|
|
- */
|
|
|
- for (uint8_t ii = 0, viewId = VIEWID_RANGE15_PASS2; ii < settings_numLights; ++ii, ++viewId)
|
|
|
- {
|
|
|
- const float* lightPos = lightPosRadius[ii];
|
|
|
-
|
|
|
- bx::memCopy(s_uniforms.m_lightPosRadius, lightPosRadius[ii], 4*sizeof(float) );
|
|
|
- bx::memCopy(s_uniforms.m_lightRgbInnerR, lightRgbInnerR[ii], 3*sizeof(float) );
|
|
|
- bx::memCopy(s_uniforms.m_color, lightRgbInnerR[ii], 3*sizeof(float) );
|
|
|
-
|
|
|
- if (settings_useStencilTexture)
|
|
|
+
|
|
|
+ // Make sure at the beginning everything gets cleared.
|
|
|
+ bgfx::setViewClear(0
|
|
|
+ , BGFX_CLEAR_COLOR
|
|
|
+ | BGFX_CLEAR_DEPTH
|
|
|
+ | BGFX_CLEAR_STENCIL
|
|
|
+ , m_clearValues.m_clearRgba
|
|
|
+ , m_clearValues.m_clearDepth
|
|
|
+ , m_clearValues.m_clearStencil
|
|
|
+ );
|
|
|
+
|
|
|
+ ::touch(0);
|
|
|
+
|
|
|
+ // Draw ambient only.
|
|
|
+ s_uniforms.m_params.m_ambientPass = 1.0f;
|
|
|
+ s_uniforms.m_params.m_lightingPass = 0.0f;
|
|
|
+
|
|
|
+ s_uniforms.m_color[0] = 1.0f;
|
|
|
+ s_uniforms.m_color[1] = 1.0f;
|
|
|
+ s_uniforms.m_color[2] = 1.0f;
|
|
|
+
|
|
|
+ const RenderState& drawAmbient = (m_settings_useStencilTexture ?
|
|
|
+ s_renderStates[RenderState::ShadowVolume_UsingStencilTexture_DrawAmbient]:
|
|
|
+ s_renderStates[RenderState::ShadowVolume_UsingStencilBuffer_DrawAmbient]);
|
|
|
+
|
|
|
+ // Draw shadow casters.
|
|
|
+ for (uint8_t ii = 0; ii < shadowCastersCount[m_currentScene]; ++ii)
|
|
|
{
|
|
|
- bgfx::setViewFrameBuffer(viewId, s_stencilFb);
|
|
|
-
|
|
|
- bgfx::setViewClear(viewId
|
|
|
- , BGFX_CLEAR_COLOR
|
|
|
- , 0x00000000
|
|
|
- , 1.0f
|
|
|
- , 0
|
|
|
- );
|
|
|
+ shadowCasters[m_currentScene][ii].submit(VIEWID_RANGE1_PASS0, drawAmbient);
|
|
|
}
|
|
|
- else
|
|
|
+
|
|
|
+ // Draw shadow receivers.
|
|
|
+ for (uint8_t ii = 0; ii < shadowReceiversCount[m_currentScene]; ++ii)
|
|
|
{
|
|
|
- const bgfx::FrameBufferHandle invalid = BGFX_INVALID_HANDLE;
|
|
|
- bgfx::setViewFrameBuffer(viewId, invalid);
|
|
|
-
|
|
|
- bgfx::setViewClear(viewId
|
|
|
- , BGFX_CLEAR_STENCIL
|
|
|
- , clearValues.m_clearRgba
|
|
|
- , clearValues.m_clearDepth
|
|
|
- , clearValues.m_clearStencil
|
|
|
- );
|
|
|
+ shadowReceivers[m_currentScene][ii].submit(VIEWID_RANGE1_PASS0, drawAmbient);
|
|
|
}
|
|
|
-
|
|
|
- // Create near clip volume for current light.
|
|
|
- float nearClipVolume[6 * 4] = {};
|
|
|
- float pointLight[4];
|
|
|
- if (settings_mixedSvImpl)
|
|
|
+
|
|
|
+ // Using stencil texture requires rendering to separate render target. first pass is building depth buffer.
|
|
|
+ if (m_settings_useStencilTexture)
|
|
|
{
|
|
|
- pointLight[0] = lightPos[0];
|
|
|
- pointLight[1] = lightPos[1];
|
|
|
- pointLight[2] = lightPos[2];
|
|
|
- pointLight[3] = 1.0f;
|
|
|
- createNearClipVolume(nearClipVolume, pointLight, viewState.m_view, fov, aspect, nearPlane);
|
|
|
+ bgfx::setViewClear(VIEWID_RANGE1_RT_PASS1, BGFX_CLEAR_DEPTH, 0x00000000, 1.0f, 0);
|
|
|
+ bgfx::setViewFrameBuffer(VIEWID_RANGE1_RT_PASS1, s_stencilFb);
|
|
|
+
|
|
|
+ const RenderState& renderState = s_renderStates[RenderState::ShadowVolume_UsingStencilTexture_BuildDepth];
|
|
|
+
|
|
|
+ for (uint8_t ii = 0; ii < shadowCastersCount[m_currentScene]; ++ii)
|
|
|
+ {
|
|
|
+ shadowCasters[m_currentScene][ii].submit(VIEWID_RANGE1_RT_PASS1, renderState);
|
|
|
+ }
|
|
|
+
|
|
|
+ for (uint8_t ii = 0; ii < shadowReceiversCount[m_currentScene]; ++ii)
|
|
|
+ {
|
|
|
+ shadowReceivers[m_currentScene][ii].submit(VIEWID_RANGE1_RT_PASS1, renderState);
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
- for (uint8_t jj = 0; jj < shadowCastersCount[currentScene]; ++jj)
|
|
|
+
|
|
|
+ m_profTime = bx::getHPCounter();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * For each light:
|
|
|
+ * 1. Compute and draw shadow volume to stencil buffer
|
|
|
+ * 2. Draw diffuse with stencil test
|
|
|
+ */
|
|
|
+ for (uint8_t ii = 0, viewId = VIEWID_RANGE15_PASS2; ii < m_settings_numLights; ++ii, ++viewId)
|
|
|
{
|
|
|
- const Instance& instance = shadowCasters[currentScene][jj];
|
|
|
- Model* model = instance.m_model;
|
|
|
-
|
|
|
- ShadowVolumeImpl::Enum shadowVolumeImpl = settings_shadowVolumeImpl;
|
|
|
- if (settings_mixedSvImpl)
|
|
|
+ const float* lightPos = lightPosRadius[ii];
|
|
|
+
|
|
|
+ bx::memCopy(s_uniforms.m_lightPosRadius, lightPosRadius[ii], 4*sizeof(float) );
|
|
|
+ bx::memCopy(s_uniforms.m_lightRgbInnerR, m_lightRgbInnerR[ii], 3*sizeof(float) );
|
|
|
+ bx::memCopy(s_uniforms.m_color, m_lightRgbInnerR[ii], 3*sizeof(float) );
|
|
|
+
|
|
|
+ if (m_settings_useStencilTexture)
|
|
|
+ {
|
|
|
+ bgfx::setViewFrameBuffer(viewId, s_stencilFb);
|
|
|
+
|
|
|
+ bgfx::setViewClear(viewId
|
|
|
+ , BGFX_CLEAR_COLOR
|
|
|
+ , 0x00000000
|
|
|
+ , 1.0f
|
|
|
+ , 0
|
|
|
+ );
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ const bgfx::FrameBufferHandle invalid = BGFX_INVALID_HANDLE;
|
|
|
+ bgfx::setViewFrameBuffer(viewId, invalid);
|
|
|
+
|
|
|
+ bgfx::setViewClear(viewId
|
|
|
+ , BGFX_CLEAR_STENCIL
|
|
|
+ , m_clearValues.m_clearRgba
|
|
|
+ , m_clearValues.m_clearDepth
|
|
|
+ , m_clearValues.m_clearStencil
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ // Create near clip volume for current light.
|
|
|
+ float nearClipVolume[6 * 4] = {};
|
|
|
+ float pointLight[4];
|
|
|
+ if (m_settings_mixedSvImpl)
|
|
|
{
|
|
|
- // If instance is inside near clip volume, depth fail must be used, else depth pass is fine.
|
|
|
- bool isInsideVolume = clipTest(nearClipVolume, 6, model->m_mesh, instance.m_scale, instance.m_pos);
|
|
|
- shadowVolumeImpl = (isInsideVolume ? ShadowVolumeImpl::DepthFail : ShadowVolumeImpl::DepthPass);
|
|
|
+ pointLight[0] = lightPos[0];
|
|
|
+ pointLight[1] = lightPos[1];
|
|
|
+ pointLight[2] = lightPos[2];
|
|
|
+ pointLight[3] = 1.0f;
|
|
|
+ createNearClipVolume(nearClipVolume, pointLight, m_viewState.m_view, fov, aspect, nearPlane);
|
|
|
}
|
|
|
- s_uniforms.m_svparams.m_dfail = float(ShadowVolumeImpl::DepthFail == shadowVolumeImpl);
|
|
|
-
|
|
|
- // Compute virtual light position for shadow volume generation.
|
|
|
- float transformedLightPos[3];
|
|
|
- shadowVolumeLightTransform(transformedLightPos
|
|
|
- , instance.m_scale
|
|
|
- , instance.m_rotation
|
|
|
- , instance.m_pos
|
|
|
- , lightPos
|
|
|
- );
|
|
|
-
|
|
|
- // Set virtual light pos.
|
|
|
- bx::memCopy(s_uniforms.m_virtualLightPos_extrusionDist, transformedLightPos, 3*sizeof(float) );
|
|
|
- s_uniforms.m_virtualLightPos_extrusionDist[3] = instance.m_svExtrusionDistance;
|
|
|
-
|
|
|
- // Compute transform for shadow volume.
|
|
|
- float shadowVolumeMtx[16];
|
|
|
- bx::mtxSRT(shadowVolumeMtx
|
|
|
- , instance.m_scale[0]
|
|
|
- , instance.m_scale[1]
|
|
|
- , instance.m_scale[2]
|
|
|
- , instance.m_rotation[0]
|
|
|
- , instance.m_rotation[1]
|
|
|
- , instance.m_rotation[2]
|
|
|
- , instance.m_pos[0]
|
|
|
- , instance.m_pos[1]
|
|
|
- , instance.m_pos[2]
|
|
|
- );
|
|
|
-
|
|
|
- GroupArray& groups = model->m_mesh.m_groups;
|
|
|
- const uint16_t stride = model->m_mesh.m_decl.getStride();
|
|
|
- for (GroupArray::iterator it = groups.begin(), itEnd = groups.end(); it != itEnd; ++it)
|
|
|
+
|
|
|
+ for (uint8_t jj = 0; jj < shadowCastersCount[m_currentScene]; ++jj)
|
|
|
{
|
|
|
- Group& group = *it;
|
|
|
-
|
|
|
- // Create shadow volume.
|
|
|
- ShadowVolume shadowVolume;
|
|
|
- shadowVolumeCreate(shadowVolume
|
|
|
- , group
|
|
|
- , stride
|
|
|
- , shadowVolumeMtx
|
|
|
- , transformedLightPos
|
|
|
- , shadowVolumeImpl
|
|
|
- , settings_shadowVolumeAlgorithm
|
|
|
- , settings_useStencilTexture
|
|
|
- );
|
|
|
-
|
|
|
- numShadowVolumeVertices += shadowVolume.m_numVertices;
|
|
|
- numShadowVolumeIndices += shadowVolume.m_numIndices;
|
|
|
-
|
|
|
- ShadowVolumeProgramType::Enum programIndex = ShadowVolumeProgramType::Blank;
|
|
|
- RenderState::Enum renderStateIndex;
|
|
|
- if (settings_useStencilTexture)
|
|
|
+ const Instance& instance = shadowCasters[m_currentScene][jj];
|
|
|
+ Model* model = instance.m_model;
|
|
|
+
|
|
|
+ ShadowVolumeImpl::Enum shadowVolumeImpl = m_settings_shadowVolumeImpl;
|
|
|
+ if (m_settings_mixedSvImpl)
|
|
|
+ {
|
|
|
+ // If instance is inside near clip volume, depth fail must be used, else depth pass is fine.
|
|
|
+ bool isInsideVolume = clipTest(nearClipVolume, 6, model->m_mesh, instance.m_scale, instance.m_pos);
|
|
|
+ shadowVolumeImpl = (isInsideVolume ? ShadowVolumeImpl::DepthFail : ShadowVolumeImpl::DepthPass);
|
|
|
+ }
|
|
|
+ s_uniforms.m_svparams.m_dfail = float(ShadowVolumeImpl::DepthFail == shadowVolumeImpl);
|
|
|
+
|
|
|
+ // Compute virtual light position for shadow volume generation.
|
|
|
+ float transformedLightPos[3];
|
|
|
+ shadowVolumeLightTransform(transformedLightPos
|
|
|
+ , instance.m_scale
|
|
|
+ , instance.m_rotation
|
|
|
+ , instance.m_pos
|
|
|
+ , lightPos
|
|
|
+ );
|
|
|
+
|
|
|
+ // Set virtual light pos.
|
|
|
+ bx::memCopy(s_uniforms.m_virtualLightPos_extrusionDist, transformedLightPos, 3*sizeof(float) );
|
|
|
+ s_uniforms.m_virtualLightPos_extrusionDist[3] = instance.m_svExtrusionDistance;
|
|
|
+
|
|
|
+ // Compute transform for shadow volume.
|
|
|
+ float shadowVolumeMtx[16];
|
|
|
+ bx::mtxSRT(shadowVolumeMtx
|
|
|
+ , instance.m_scale[0]
|
|
|
+ , instance.m_scale[1]
|
|
|
+ , instance.m_scale[2]
|
|
|
+ , instance.m_rotation[0]
|
|
|
+ , instance.m_rotation[1]
|
|
|
+ , instance.m_rotation[2]
|
|
|
+ , instance.m_pos[0]
|
|
|
+ , instance.m_pos[1]
|
|
|
+ , instance.m_pos[2]
|
|
|
+ );
|
|
|
+
|
|
|
+ GroupArray& groups = model->m_mesh.m_groups;
|
|
|
+ const uint16_t stride = model->m_mesh.m_decl.getStride();
|
|
|
+ for (GroupArray::iterator it = groups.begin(), itEnd = groups.end(); it != itEnd; ++it)
|
|
|
{
|
|
|
- renderStateIndex = ShadowVolumeImpl::DepthFail == shadowVolumeImpl
|
|
|
+ Group& group = *it;
|
|
|
+
|
|
|
+ // Create shadow volume.
|
|
|
+ ShadowVolume shadowVolume;
|
|
|
+ shadowVolumeCreate(shadowVolume
|
|
|
+ , group
|
|
|
+ , stride
|
|
|
+ , shadowVolumeMtx
|
|
|
+ , transformedLightPos
|
|
|
+ , shadowVolumeImpl
|
|
|
+ , m_settings_shadowVolumeAlgorithm
|
|
|
+ , m_settings_useStencilTexture
|
|
|
+ );
|
|
|
+
|
|
|
+ m_numShadowVolumeVertices += shadowVolume.m_numVertices;
|
|
|
+ m_numShadowVolumeIndices += shadowVolume.m_numIndices;
|
|
|
+
|
|
|
+ ShadowVolumeProgramType::Enum programIndex = ShadowVolumeProgramType::Blank;
|
|
|
+ RenderState::Enum renderStateIndex;
|
|
|
+ if (m_settings_useStencilTexture)
|
|
|
+ {
|
|
|
+ renderStateIndex = ShadowVolumeImpl::DepthFail == shadowVolumeImpl
|
|
|
? RenderState::ShadowVolume_UsingStencilTexture_CraftStencil_DepthFail
|
|
|
: RenderState::ShadowVolume_UsingStencilTexture_CraftStencil_DepthPass
|
|
|
;
|
|
|
-
|
|
|
- programIndex = ShadowVolumeAlgorithm::FaceBased == settings_shadowVolumeAlgorithm
|
|
|
+
|
|
|
+ programIndex = ShadowVolumeAlgorithm::FaceBased == m_settings_shadowVolumeAlgorithm
|
|
|
? ShadowVolumeProgramType::Tex1
|
|
|
: ShadowVolumeProgramType::Tex2
|
|
|
;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- renderStateIndex = ShadowVolumeImpl::DepthFail == shadowVolumeImpl
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ renderStateIndex = ShadowVolumeImpl::DepthFail == shadowVolumeImpl
|
|
|
? RenderState::ShadowVolume_UsingStencilBuffer_CraftStencil_DepthFail
|
|
|
: RenderState::ShadowVolume_UsingStencilBuffer_CraftStencil_DepthPass
|
|
|
;
|
|
|
- }
|
|
|
- const RenderState& renderStateCraftStencil = s_renderStates[renderStateIndex];
|
|
|
-
|
|
|
- s_uniforms.submitPerDrawUniforms();
|
|
|
- bgfx::setTransform(shadowVolumeMtx);
|
|
|
- bgfx::setVertexBuffer(0, shadowVolume.m_vbSides);
|
|
|
- bgfx::setIndexBuffer(shadowVolume.m_ibSides);
|
|
|
- setRenderState(renderStateCraftStencil);
|
|
|
- ::submit(viewId, svProgs[programIndex][ShadowVolumePart::Side]);
|
|
|
-
|
|
|
- if (shadowVolume.m_cap)
|
|
|
- {
|
|
|
- s_uniforms.submitPerDrawUniforms();
|
|
|
- bgfx::setTransform(shadowVolumeMtx);
|
|
|
- bgfx::setVertexBuffer(0, group.m_vbh);
|
|
|
- bgfx::setIndexBuffer(shadowVolume.m_ibFrontCap);
|
|
|
- setRenderState(renderStateCraftStencil);
|
|
|
- ::submit(viewId, svProgs[programIndex][ShadowVolumePart::Front]);
|
|
|
-
|
|
|
- s_uniforms.submitPerDrawUniforms();
|
|
|
- bgfx::setTransform(shadowVolumeMtx);
|
|
|
- bgfx::setVertexBuffer(0, group.m_vbh);
|
|
|
- bgfx::setIndexBuffer(shadowVolume.m_ibBackCap);
|
|
|
- ::setRenderState(renderStateCraftStencil);
|
|
|
- ::submit(viewId, svProgs[programIndex][ShadowVolumePart::Back]);
|
|
|
- }
|
|
|
-
|
|
|
- if (settings_drawShadowVolumes)
|
|
|
- {
|
|
|
- const RenderState& renderState = s_renderStates[RenderState::Custom_DrawShadowVolume_Lines];
|
|
|
-
|
|
|
+ }
|
|
|
+ const RenderState& renderStateCraftStencil = s_renderStates[renderStateIndex];
|
|
|
+
|
|
|
s_uniforms.submitPerDrawUniforms();
|
|
|
bgfx::setTransform(shadowVolumeMtx);
|
|
|
bgfx::setVertexBuffer(0, shadowVolume.m_vbSides);
|
|
|
bgfx::setIndexBuffer(shadowVolume.m_ibSides);
|
|
|
- ::setRenderState(renderState);
|
|
|
- ::submit(VIEWID_RANGE1_PASS3, svProgs[ShadowVolumeProgramType::Color][ShadowVolumePart::Side]);
|
|
|
-
|
|
|
+ setRenderState(renderStateCraftStencil);
|
|
|
+ ::submit(viewId, m_svProgs[programIndex][ShadowVolumePart::Side]);
|
|
|
+
|
|
|
if (shadowVolume.m_cap)
|
|
|
{
|
|
|
s_uniforms.submitPerDrawUniforms();
|
|
|
bgfx::setTransform(shadowVolumeMtx);
|
|
|
bgfx::setVertexBuffer(0, group.m_vbh);
|
|
|
bgfx::setIndexBuffer(shadowVolume.m_ibFrontCap);
|
|
|
- ::setRenderState(renderState);
|
|
|
- ::submit(VIEWID_RANGE1_PASS3, svProgs[ShadowVolumeProgramType::Color][ShadowVolumePart::Front]);
|
|
|
-
|
|
|
+ setRenderState(renderStateCraftStencil);
|
|
|
+ ::submit(viewId, m_svProgs[programIndex][ShadowVolumePart::Front]);
|
|
|
+
|
|
|
s_uniforms.submitPerDrawUniforms();
|
|
|
bgfx::setTransform(shadowVolumeMtx);
|
|
|
bgfx::setVertexBuffer(0, group.m_vbh);
|
|
|
bgfx::setIndexBuffer(shadowVolume.m_ibBackCap);
|
|
|
+ ::setRenderState(renderStateCraftStencil);
|
|
|
+ ::submit(viewId, m_svProgs[programIndex][ShadowVolumePart::Back]);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (m_settings_drawShadowVolumes)
|
|
|
+ {
|
|
|
+ const RenderState& renderState = s_renderStates[RenderState::Custom_DrawShadowVolume_Lines];
|
|
|
+
|
|
|
+ s_uniforms.submitPerDrawUniforms();
|
|
|
+ bgfx::setTransform(shadowVolumeMtx);
|
|
|
+ bgfx::setVertexBuffer(0, shadowVolume.m_vbSides);
|
|
|
+ bgfx::setIndexBuffer(shadowVolume.m_ibSides);
|
|
|
::setRenderState(renderState);
|
|
|
- ::submit(VIEWID_RANGE1_PASS3, svProgs[ShadowVolumeProgramType::Color][ShadowVolumePart::Back]);
|
|
|
+ ::submit(VIEWID_RANGE1_PASS3, m_svProgs[ShadowVolumeProgramType::Color][ShadowVolumePart::Side]);
|
|
|
+
|
|
|
+ if (shadowVolume.m_cap)
|
|
|
+ {
|
|
|
+ s_uniforms.submitPerDrawUniforms();
|
|
|
+ bgfx::setTransform(shadowVolumeMtx);
|
|
|
+ bgfx::setVertexBuffer(0, group.m_vbh);
|
|
|
+ bgfx::setIndexBuffer(shadowVolume.m_ibFrontCap);
|
|
|
+ ::setRenderState(renderState);
|
|
|
+ ::submit(VIEWID_RANGE1_PASS3, m_svProgs[ShadowVolumeProgramType::Color][ShadowVolumePart::Front]);
|
|
|
+
|
|
|
+ s_uniforms.submitPerDrawUniforms();
|
|
|
+ bgfx::setTransform(shadowVolumeMtx);
|
|
|
+ bgfx::setVertexBuffer(0, group.m_vbh);
|
|
|
+ bgfx::setIndexBuffer(shadowVolume.m_ibBackCap);
|
|
|
+ ::setRenderState(renderState);
|
|
|
+ ::submit(VIEWID_RANGE1_PASS3, m_svProgs[ShadowVolumeProgramType::Color][ShadowVolumePart::Back]);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- }
|
|
|
-
|
|
|
- // Draw diffuse only.
|
|
|
- s_uniforms.m_params.m_ambientPass = 0.0f;
|
|
|
- s_uniforms.m_params.m_lightingPass = 1.0f;
|
|
|
-
|
|
|
- RenderState& drawDiffuse = settings_useStencilTexture
|
|
|
+
|
|
|
+ // Draw diffuse only.
|
|
|
+ s_uniforms.m_params.m_ambientPass = 0.0f;
|
|
|
+ s_uniforms.m_params.m_lightingPass = 1.0f;
|
|
|
+
|
|
|
+ RenderState& drawDiffuse = m_settings_useStencilTexture
|
|
|
? s_renderStates[RenderState::ShadowVolume_UsingStencilTexture_DrawDiffuse]
|
|
|
: s_renderStates[RenderState::ShadowVolume_UsingStencilBuffer_DrawDiffuse]
|
|
|
;
|
|
|
-
|
|
|
- // If using stencil texture, viewId is set to render target. Incr it to render to default back buffer.
|
|
|
- viewId += uint8_t(settings_useStencilTexture);
|
|
|
-
|
|
|
- // Draw shadow casters.
|
|
|
- for (uint8_t jj = 0; jj < shadowCastersCount[currentScene]; ++jj)
|
|
|
- {
|
|
|
- shadowCasters[currentScene][jj].submit(viewId, drawDiffuse);
|
|
|
+
|
|
|
+ // If using stencil texture, viewId is set to render target. Incr it to render to default back buffer.
|
|
|
+ viewId += uint8_t(m_settings_useStencilTexture);
|
|
|
+
|
|
|
+ // Draw shadow casters.
|
|
|
+ for (uint8_t jj = 0; jj < shadowCastersCount[m_currentScene]; ++jj)
|
|
|
+ {
|
|
|
+ shadowCasters[m_currentScene][jj].submit(viewId, drawDiffuse);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Draw shadow receivers.
|
|
|
+ for (uint8_t jj = 0; jj < shadowReceiversCount[m_currentScene]; ++jj)
|
|
|
+ {
|
|
|
+ shadowReceivers[m_currentScene][jj].submit(viewId, drawDiffuse);
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
- // Draw shadow receivers.
|
|
|
- for (uint8_t jj = 0; jj < shadowReceiversCount[currentScene]; ++jj)
|
|
|
+
|
|
|
+ m_profTime = bx::getHPCounter() - m_profTime;
|
|
|
+
|
|
|
+ // Lights.
|
|
|
+ const float lightScale[3] = { 1.5f, 1.5f, 1.5f };
|
|
|
+ for (uint8_t ii = 0; ii < m_settings_numLights; ++ii)
|
|
|
{
|
|
|
- shadowReceivers[currentScene][jj].submit(viewId, drawDiffuse);
|
|
|
+ bx::memCopy(s_uniforms.m_color, m_lightRgbInnerR[ii], 3*sizeof(float) );
|
|
|
+
|
|
|
+ float lightMtx[16];
|
|
|
+ mtxBillboard(lightMtx, m_viewState.m_view, lightPosRadius[ii], lightScale);
|
|
|
+
|
|
|
+ m_vplaneModel.submit(VIEWID_RANGE1_PASS3, lightMtx, s_renderStates[RenderState::Custom_BlendLightTexture]);
|
|
|
}
|
|
|
+
|
|
|
+ // Setup view rect and transform for all used views.
|
|
|
+ setViewRectMask(s_viewMask, 0, 0, uint16_t(m_viewState.m_width), uint16_t(m_viewState.m_height) );
|
|
|
+ setViewTransformMask(s_viewMask, m_viewState.m_view, m_viewState.m_proj);
|
|
|
+ s_viewMask = 0;
|
|
|
+
|
|
|
+ // Advance to next frame. Rendering thread will be kicked to
|
|
|
+ // process submitted rendering primitives.
|
|
|
+ bgfx::frame();
|
|
|
+
|
|
|
+ // Swap memory pages.
|
|
|
+ s_svAllocator.swap();
|
|
|
+
|
|
|
+ // Reset clear values.
|
|
|
+ setViewClearMask(UINT32_MAX
|
|
|
+ , BGFX_CLEAR_NONE
|
|
|
+ , m_clearValues.m_clearRgba
|
|
|
+ , m_clearValues.m_clearDepth
|
|
|
+ , m_clearValues.m_clearStencil
|
|
|
+ );
|
|
|
+ return true;
|
|
|
}
|
|
|
-
|
|
|
- profTime = bx::getHPCounter() - profTime;
|
|
|
-
|
|
|
- // Lights.
|
|
|
- const float lightScale[3] = { 1.5f, 1.5f, 1.5f };
|
|
|
- for (uint8_t ii = 0; ii < settings_numLights; ++ii)
|
|
|
- {
|
|
|
- bx::memCopy(s_uniforms.m_color, lightRgbInnerR[ii], 3*sizeof(float) );
|
|
|
-
|
|
|
- float lightMtx[16];
|
|
|
- mtxBillboard(lightMtx, viewState.m_view, lightPosRadius[ii], lightScale);
|
|
|
-
|
|
|
- vplaneModel.submit(VIEWID_RANGE1_PASS3, lightMtx, s_renderStates[RenderState::Custom_BlendLightTexture]);
|
|
|
- }
|
|
|
-
|
|
|
- // Setup view rect and transform for all used views.
|
|
|
- setViewRectMask(s_viewMask, 0, 0, uint16_t(viewState.m_width), uint16_t(viewState.m_height) );
|
|
|
- setViewTransformMask(s_viewMask, viewState.m_view, viewState.m_proj);
|
|
|
- s_viewMask = 0;
|
|
|
-
|
|
|
- // Advance to next frame. Rendering thread will be kicked to
|
|
|
- // process submitted rendering primitives.
|
|
|
- bgfx::frame();
|
|
|
-
|
|
|
- // Swap memory pages.
|
|
|
- s_svAllocator.swap();
|
|
|
-
|
|
|
- // Reset clear values.
|
|
|
- setViewClearMask(UINT32_MAX
|
|
|
- , BGFX_CLEAR_NONE
|
|
|
- , clearValues.m_clearRgba
|
|
|
- , clearValues.m_clearDepth
|
|
|
- , clearValues.m_clearStencil
|
|
|
- );
|
|
|
+ return false;
|
|
|
}
|
|
|
+
|
|
|
+ ViewState m_viewState;
|
|
|
+ ClearValues m_clearValues;
|
|
|
+
|
|
|
+ uint32_t m_debug;
|
|
|
+ uint32_t m_reset;
|
|
|
+
|
|
|
+ bgfx::TextureHandle m_figureTex;
|
|
|
+ bgfx::TextureHandle m_flareTex;
|
|
|
+ bgfx::TextureHandle m_fieldstoneTex;
|
|
|
+
|
|
|
+ bgfx::ProgramHandle m_programTextureLighting;
|
|
|
+ bgfx::ProgramHandle m_programColorLighting;
|
|
|
+ bgfx::ProgramHandle m_programColorTexture;
|
|
|
+ bgfx::ProgramHandle m_programTexture;
|
|
|
+
|
|
|
+ bgfx::ProgramHandle m_programBackBlank;
|
|
|
+ bgfx::ProgramHandle m_programSideBlank;
|
|
|
+ bgfx::ProgramHandle m_programFrontBlank;
|
|
|
+
|
|
|
+ bgfx::ProgramHandle m_programBackColor;
|
|
|
+ bgfx::ProgramHandle m_programSideColor;
|
|
|
+ bgfx::ProgramHandle m_programFrontColor;
|
|
|
+
|
|
|
+ bgfx::ProgramHandle m_programSideTex;
|
|
|
+ bgfx::ProgramHandle m_programBackTex1;
|
|
|
+ bgfx::ProgramHandle m_programBackTex2;
|
|
|
+ bgfx::ProgramHandle m_programFrontTex1;
|
|
|
+ bgfx::ProgramHandle m_programFrontTex2;
|
|
|
+
|
|
|
+ bgfx::ProgramHandle m_svProgs[ShadowVolumeProgramType::Count][ShadowVolumePart::Count];
|
|
|
+
|
|
|
+ Model m_bunnyLowPolyModel;
|
|
|
+ Model m_bunnyHighPolyModel;
|
|
|
+ Model m_columnModel;
|
|
|
+ Model m_platformModel;
|
|
|
+ Model m_cubeModel;
|
|
|
+ Model m_hplaneFieldModel;
|
|
|
+ Model m_hplaneFigureModel;
|
|
|
+ Model m_vplaneModel;
|
|
|
+
|
|
|
+ float m_lightRgbInnerR[MAX_LIGHTS_COUNT][4];
|
|
|
+
|
|
|
+ int64_t m_profTime;
|
|
|
+ int64_t m_timeOffset;
|
|
|
+
|
|
|
+ uint32_t m_numShadowVolumeVertices;
|
|
|
+ uint32_t m_numShadowVolumeIndices;
|
|
|
+
|
|
|
+ uint32_t m_oldWidth;
|
|
|
+ uint32_t m_oldHeight;
|
|
|
+
|
|
|
+ bool m_settings_showHelp;
|
|
|
+ bool m_settings_updateLights;
|
|
|
+ bool m_settings_updateScene;
|
|
|
+ bool m_settings_mixedSvImpl;
|
|
|
+ bool m_settings_useStencilTexture;
|
|
|
+ bool m_settings_drawShadowVolumes;
|
|
|
+ float m_settings_numLights;
|
|
|
+ float m_settings_instanceCount;
|
|
|
+ ShadowVolumeImpl::Enum m_settings_shadowVolumeImpl;
|
|
|
+ ShadowVolumeAlgorithm::Enum m_settings_shadowVolumeAlgorithm;
|
|
|
+ int32_t m_scrollAreaRight;
|
|
|
+
|
|
|
+ LightPattern m_lightPattern;
|
|
|
+ MeshChoice m_currentMesh;
|
|
|
+ Scene m_currentScene;
|
|
|
+
|
|
|
+ entry::MouseState m_mouseState;
|
|
|
+};
|
|
|
|
|
|
- // Cleanup
|
|
|
- bunnyLowPolyModel.unload();
|
|
|
- bunnyHighPolyModel.unload();
|
|
|
- columnModel.unload();
|
|
|
- cubeModel.unload();
|
|
|
- platformModel.unload();
|
|
|
- hplaneFieldModel.unload();
|
|
|
- hplaneFigureModel.unload();
|
|
|
- vplaneModel.unload();
|
|
|
-
|
|
|
- s_uniforms.destroy();
|
|
|
-
|
|
|
- bgfx::destroyUniform(s_texColor);
|
|
|
- bgfx::destroyUniform(s_texStencil);
|
|
|
- bgfx::destroyFrameBuffer(s_stencilFb);
|
|
|
-
|
|
|
- bgfx::destroyTexture(figureTex);
|
|
|
- bgfx::destroyTexture(fieldstoneTex);
|
|
|
- bgfx::destroyTexture(flareTex);
|
|
|
-
|
|
|
- bgfx::destroyProgram(programTextureLighting);
|
|
|
- bgfx::destroyProgram(programColorLighting);
|
|
|
- bgfx::destroyProgram(programColorTexture);
|
|
|
- bgfx::destroyProgram(programTexture);
|
|
|
-
|
|
|
- bgfx::destroyProgram(programBackBlank);
|
|
|
- bgfx::destroyProgram(programSideBlank);
|
|
|
- bgfx::destroyProgram(programFrontBlank);
|
|
|
- bgfx::destroyProgram(programBackColor);
|
|
|
- bgfx::destroyProgram(programSideColor);
|
|
|
- bgfx::destroyProgram(programFrontColor);
|
|
|
- bgfx::destroyProgram(programSideTex);
|
|
|
- bgfx::destroyProgram(programBackTex1);
|
|
|
- bgfx::destroyProgram(programBackTex2);
|
|
|
- bgfx::destroyProgram(programFrontTex1);
|
|
|
- bgfx::destroyProgram(programFrontTex2);
|
|
|
-
|
|
|
- cameraDestroy();
|
|
|
- imguiDestroy();
|
|
|
-
|
|
|
- // Shutdown bgfx.
|
|
|
- bgfx::shutdown();
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
+ENTRY_IMPLEMENT_MAIN(ExampleShadowVolumes);
|