summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/bgfx/examples/30-picking/picking.cpp
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/bgfx/examples/30-picking/picking.cpp')
-rw-r--r--3rdparty/bgfx/examples/30-picking/picking.cpp381
1 files changed, 199 insertions, 182 deletions
diff --git a/3rdparty/bgfx/examples/30-picking/picking.cpp b/3rdparty/bgfx/examples/30-picking/picking.cpp
index 563e44bf684..22e4af9bb00 100644
--- a/3rdparty/bgfx/examples/30-picking/picking.cpp
+++ b/3rdparty/bgfx/examples/30-picking/picking.cpp
@@ -9,6 +9,9 @@
#include <bx/rng.h>
#include <map>
+namespace
+{
+
#define RENDER_PASS_SHADING 0 // Default forward rendered geo with simple shading
#define RENDER_PASS_ID 1 // ID buffer for picking
#define RENDER_PASS_BLIT 2 // Blit GPU render target to CPU texture
@@ -17,13 +20,19 @@
class ExamplePicking : public entry::AppI
{
- void init(int _argc, char** _argv) BX_OVERRIDE
+public:
+ ExamplePicking(const char* _name, const char* _description)
+ : entry::AppI(_name, _description)
+ {
+ }
+
+ void init(int32_t _argc, const char* const* _argv, uint32_t _width, uint32_t _height) override
{
Args args(_argc, _argv);
- m_width = 1280;
- m_height = 720;
- m_debug = BGFX_DEBUG_TEXT;
+ m_width = _width;
+ m_height = _height;
+ m_debug = BGFX_DEBUG_NONE;
m_reset = BGFX_RESET_VSYNC;
bgfx::init(args.m_type, args.m_pciId);
@@ -144,7 +153,7 @@ class ExamplePicking : public entry::AppI
imguiCreate();
}
- int shutdown() BX_OVERRIDE
+ int shutdown() override
{
for (uint32_t ii = 0; ii < 12; ++ii)
{
@@ -152,16 +161,16 @@ class ExamplePicking : public entry::AppI
}
// Cleanup.
- bgfx::destroyProgram(m_shadingProgram);
- bgfx::destroyProgram(m_idProgram);
+ bgfx::destroy(m_shadingProgram);
+ bgfx::destroy(m_idProgram);
- bgfx::destroyUniform(u_tint);
- bgfx::destroyUniform(u_id);
+ bgfx::destroy(u_tint);
+ bgfx::destroy(u_id);
- bgfx::destroyFrameBuffer(m_pickingFB);
- bgfx::destroyTexture(m_pickingRT);
- bgfx::destroyTexture(m_pickingRTDepth);
- bgfx::destroyTexture(m_blitTex);
+ bgfx::destroy(m_pickingFB);
+ bgfx::destroy(m_pickingRT);
+ bgfx::destroy(m_pickingRTDepth);
+ bgfx::destroy(m_blitTex);
imguiDestroy();
@@ -171,212 +180,218 @@ class ExamplePicking : public entry::AppI
return 0;
}
- bool update() BX_OVERRIDE
+ bool update() override
{
if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
{
- bgfx::setViewFrameBuffer(RENDER_PASS_ID, m_pickingFB);
-
- 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)( (bx::getHPCounter() - m_timeOffset) / double(bx::getHPFrequency() ) );
-
- // Use debug font to print information about this example.
- bgfx::dbgTextClear();
- bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/30-picking");
- bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Mouse picking via GPU texture readback.");
- bgfx::dbgTextPrintf(0, 3, 0x0f, "Frame: % 7.3f[ms]", double(frameTime)*toMs);
-
- // Set up matrices for basic forward renderer
- const float camSpeed = 0.25;
- float cameraSpin = (float)m_cameraSpin;
- float eyeDist = 2.5f;
- float eye[3] =
- {
- -eyeDist * bx::fsin(time*cameraSpin*camSpeed),
- 0.0f,
- -eyeDist * bx::fcos(time*cameraSpin*camSpeed),
- };
- float at[3] = { 0.0f, 0.0f, 0.0f };
+ // Draw UI
+ 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_width)
+ , uint16_t(m_height)
+ );
+
+ const bgfx::Caps* caps = bgfx::getCaps();
+ bool blitSupport = 0 != (caps->supported & BGFX_CAPS_TEXTURE_BLIT);
- float view[16];
- bx::mtxLookAt(view, eye, at);
+ showExampleDialog(this
+ , !blitSupport
+ ? "BGFX_CAPS_TEXTURE_BLIT is not supported."
+ : NULL
+ );
- float proj[16];
- bx::mtxProj(proj, 60.0f, float(m_width) / float(m_height), 0.1f, 100.0f, bgfx::getCaps()->homogeneousDepth);
+ if (blitSupport)
+ {
+ ImGui::SetNextWindowPos(
+ ImVec2(m_width - m_width / 5.0f - 10.0f, 10.0f)
+ , ImGuiSetCond_FirstUseEver
+ );
+ ImGui::Begin("Settings"
+ , NULL
+ , ImVec2(m_width / 5.0f, m_height / 2.0f)
+ , ImGuiWindowFlags_AlwaysAutoResize
+ );
- // Set up view rect and transform for the shaded pass
- bgfx::setViewRect(RENDER_PASS_SHADING, 0, 0, uint16_t(m_width), uint16_t(m_height) );
- bgfx::setViewTransform(RENDER_PASS_SHADING, view, proj);
+ ImGui::Image(m_pickingRT, ImVec2(m_width / 5.0f - 16.0f, m_width / 5.0f - 16.0f) );
+ ImGui::SliderFloat("Field of view", &m_fov, 1.0f, 60.0f);
+ ImGui::Checkbox("Spin Camera", &m_cameraSpin);
- // Set up picking pass
- float viewProj[16];
- bx::mtxMul(viewProj, view, proj);
+ ImGui::End();
- float invViewProj[16];
- bx::mtxInverse(invViewProj, viewProj);
+ bgfx::setViewFrameBuffer(RENDER_PASS_ID, m_pickingFB);
- // Mouse coord in NDC
- float mouseXNDC = ( m_mouseState.m_mx / (float)m_width ) * 2.0f - 1.0f;
- float mouseYNDC = ((m_height - m_mouseState.m_my) / (float)m_height) * 2.0f - 1.0f;
+ float time = (float)( (bx::getHPCounter() - m_timeOffset) / double(bx::getHPFrequency() ) );
- float pickEye[3];
- float mousePosNDC[3] = { mouseXNDC, mouseYNDC, 0.0f };
- bx::vec3MulMtxH(pickEye, mousePosNDC, invViewProj);
+ // Set up matrices for basic forward renderer
+ const float camSpeed = 0.25;
+ float cameraSpin = (float)m_cameraSpin;
+ float eyeDist = 2.5f;
+ float eye[3] =
+ {
+ -eyeDist * bx::fsin(time*cameraSpin*camSpeed),
+ 0.0f,
+ -eyeDist * bx::fcos(time*cameraSpin*camSpeed),
+ };
+ float at[3] = { 0.0f, 0.0f, 0.0f };
- float pickAt[3];
- float mousePosNDCEnd[3] = { mouseXNDC, mouseYNDC, 1.0f };
- bx::vec3MulMtxH(pickAt, mousePosNDCEnd, invViewProj);
+ float view[16];
+ bx::mtxLookAt(view, eye, at);
- // Look at our unprojected point
- float pickView[16];
- bx::mtxLookAt(pickView, pickEye, pickAt);
+ float proj[16];
+ bx::mtxProj(proj, 60.0f, float(m_width) / float(m_height), 0.1f, 100.0f, caps->homogeneousDepth);
- // Tight FOV is best for picking
- float pickProj[16];
- bx::mtxProj(pickProj, m_fov, 1, 0.1f, 100.0f, bgfx::getCaps()->homogeneousDepth);
+ // Set up view rect and transform for the shaded pass
+ bgfx::setViewRect(RENDER_PASS_SHADING, 0, 0, uint16_t(m_width), uint16_t(m_height) );
+ bgfx::setViewTransform(RENDER_PASS_SHADING, view, proj);
- // View rect and transforms for picking pass
- bgfx::setViewRect(RENDER_PASS_ID, 0, 0, ID_DIM, ID_DIM);
- bgfx::setViewTransform(RENDER_PASS_ID, pickView, pickProj);
+ // Set up picking pass
+ float viewProj[16];
+ bx::mtxMul(viewProj, view, proj);
- // Now that our passes are set up, we can finally draw each mesh
+ float invViewProj[16];
+ bx::mtxInverse(invViewProj, viewProj);
- // Picking highlights a mesh so we'll set up this tint color
- const float tintBasic[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
- const float tintHighlighted[4] = { 0.3f, 0.3f, 2.0f, 1.0f };
+ // Mouse coord in NDC
+ float mouseXNDC = ( m_mouseState.m_mx / (float)m_width ) * 2.0f - 1.0f;
+ float mouseYNDC = ((m_height - m_mouseState.m_my) / (float)m_height) * 2.0f - 1.0f;
- for (uint32_t mesh = 0; mesh < 12; ++mesh)
- {
- const float scale = m_meshScale[mesh];
-
- // Set up transform matrix for each mesh
- float mtx[16];
- bx::mtxSRT(mtx
- , scale, scale, scale
- , 0.0f
- , time*0.37f*(mesh % 2 ? 1.0f : -1.0f)
- , 0.0f
- , (mesh % 4) - 1.5f
- , (mesh / 4) - 1.25f
- , 0.0f
- );
+ float pickEye[3];
+ float mousePosNDC[3] = { mouseXNDC, mouseYNDC, 0.0f };
+ bx::vec3MulMtxH(pickEye, mousePosNDC, invViewProj);
- // Submit mesh to both of our render passes
- // Set uniform based on if this is the highlighted mesh
- bgfx::setUniform(u_tint
- , mesh == m_highlighted
- ? tintHighlighted
- : tintBasic
- );
- meshSubmit(m_meshes[mesh], RENDER_PASS_SHADING, m_shadingProgram, mtx);
+ float pickAt[3];
+ float mousePosNDCEnd[3] = { mouseXNDC, mouseYNDC, 1.0f };
+ bx::vec3MulMtxH(pickAt, mousePosNDCEnd, invViewProj);
- // Submit ID pass based on mesh ID
- bgfx::setUniform(u_id, m_idsF[mesh]);
- meshSubmit(m_meshes[mesh], RENDER_PASS_ID, m_idProgram, mtx);
- }
+ // Look at our unprojected point
+ float pickView[16];
+ bx::mtxLookAt(pickView, pickEye, pickAt);
- // If the user previously clicked, and we're done reading data from GPU, look at ID buffer on CPU
- // Whatever mesh has the most pixels in the ID buffer is the one the user clicked on.
- if (m_reading == m_currFrame)
- {
- m_reading = 0;
- std::map<uint32_t, uint32_t> ids; // This contains all the IDs found in the buffer
- uint32_t maxAmount = 0;
- for (uint8_t *x = m_blitData; x < m_blitData + ID_DIM * ID_DIM * 4;)
- {
- uint8_t rr = *x++;
- uint8_t gg = *x++;
- uint8_t bb = *x++;
- uint8_t aa = *x++;
+ // Tight FOV is best for picking
+ float pickProj[16];
+ bx::mtxProj(pickProj, m_fov, 1, 0.1f, 100.0f, caps->homogeneousDepth);
- const bgfx::Caps* caps = bgfx::getCaps();
- if (bgfx::RendererType::Direct3D9 == caps->rendererType)
- {
- // Comes back as BGRA
- uint8_t temp = rr;
- rr = bb;
- bb = temp;
- }
+ // View rect and transforms for picking pass
+ bgfx::setViewRect(RENDER_PASS_ID, 0, 0, ID_DIM, ID_DIM);
+ bgfx::setViewTransform(RENDER_PASS_ID, pickView, pickProj);
- if (0 == (rr|gg|bb) ) // Skip background
- {
- continue;
- }
+ // Now that our passes are set up, we can finally draw each mesh
- uint32_t hashKey = rr + (gg << 8) + (bb << 16) + (aa << 24);
- std::map<uint32_t, uint32_t>::iterator mapIter = ids.find(hashKey);
- uint32_t amount = 1;
- if (mapIter != ids.end() )
- {
- amount = mapIter->second + 1;
- }
+ // Picking highlights a mesh so we'll set up this tint color
+ const float tintBasic[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
+ const float tintHighlighted[4] = { 0.3f, 0.3f, 2.0f, 1.0f };
- ids[hashKey] = amount; // Amount of times this ID (color) has been clicked on in buffer
- maxAmount = maxAmount > amount
- ? maxAmount
- : amount
- ;
+ for (uint32_t mesh = 0; mesh < 12; ++mesh)
+ {
+ const float scale = m_meshScale[mesh];
+
+ // Set up transform matrix for each mesh
+ float mtx[16];
+ bx::mtxSRT(mtx
+ , scale, scale, scale
+ , 0.0f
+ , time*0.37f*(mesh % 2 ? 1.0f : -1.0f)
+ , 0.0f
+ , (mesh % 4) - 1.5f
+ , (mesh / 4) - 1.25f
+ , 0.0f
+ );
+
+ // Submit mesh to both of our render passes
+ // Set uniform based on if this is the highlighted mesh
+ bgfx::setUniform(u_tint
+ , mesh == m_highlighted
+ ? tintHighlighted
+ : tintBasic
+ );
+ meshSubmit(m_meshes[mesh], RENDER_PASS_SHADING, m_shadingProgram, mtx);
+
+ // Submit ID pass based on mesh ID
+ bgfx::setUniform(u_id, m_idsF[mesh]);
+ meshSubmit(m_meshes[mesh], RENDER_PASS_ID, m_idProgram, mtx);
}
- uint32_t idKey = 0;
- m_highlighted = UINT32_MAX;
- if (maxAmount)
+ // If the user previously clicked, and we're done reading data from GPU, look at ID buffer on CPU
+ // Whatever mesh has the most pixels in the ID buffer is the one the user clicked on.
+ if (m_reading == m_currFrame)
{
- for (std::map<uint32_t, uint32_t>::iterator mapIter = ids.begin(); mapIter != ids.end(); mapIter++)
+ m_reading = 0;
+ std::map<uint32_t, uint32_t> ids; // This contains all the IDs found in the buffer
+ uint32_t maxAmount = 0;
+ for (uint8_t *x = m_blitData; x < m_blitData + ID_DIM * ID_DIM * 4;)
{
- if (mapIter->second == maxAmount)
+ uint8_t rr = *x++;
+ uint8_t gg = *x++;
+ uint8_t bb = *x++;
+ uint8_t aa = *x++;
+
+ if (bgfx::RendererType::Direct3D9 == caps->rendererType)
+ {
+ // Comes back as BGRA
+ uint8_t temp = rr;
+ rr = bb;
+ bb = temp;
+ }
+
+ if (0 == (rr|gg|bb) ) // Skip background
{
- idKey = mapIter->first;
- break;
+ continue;
}
+
+ uint32_t hashKey = rr + (gg << 8) + (bb << 16) + (aa << 24);
+ std::map<uint32_t, uint32_t>::iterator mapIter = ids.find(hashKey);
+ uint32_t amount = 1;
+ if (mapIter != ids.end() )
+ {
+ amount = mapIter->second + 1;
+ }
+
+ ids[hashKey] = amount; // Amount of times this ID (color) has been clicked on in buffer
+ maxAmount = maxAmount > amount
+ ? maxAmount
+ : amount
+ ;
}
- for (uint32_t ii = 0; ii < 12; ++ii)
+ uint32_t idKey = 0;
+ m_highlighted = UINT32_MAX;
+ if (maxAmount)
{
- if (m_idsU[ii] == idKey)
+ for (std::map<uint32_t, uint32_t>::iterator mapIter = ids.begin(); mapIter != ids.end(); mapIter++)
{
- m_highlighted = ii;
- break;
+ if (mapIter->second == maxAmount)
+ {
+ idKey = mapIter->first;
+ break;
+ }
+ }
+
+ for (uint32_t ii = 0; ii < 12; ++ii)
+ {
+ if (m_idsU[ii] == idKey)
+ {
+ m_highlighted = ii;
+ break;
+ }
}
}
}
- }
-
- // Start a new readback?
- if (!m_reading
- && m_mouseState.m_buttons[entry::MouseButton::Left])
- {
- // Blit and read
- bgfx::blit(RENDER_PASS_BLIT, m_blitTex, 0, 0, m_pickingRT);
- m_reading = bgfx::readTexture(m_blitTex, m_blitData);
- }
-
- // Draw UI
- 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_width)
- , uint16_t(m_height)
- );
-
- imguiBeginArea("Picking Render Target:", 10, 100, 300, 400);
- imguiImage(m_pickingRT, 1.0f, 1.0f, 1.0f);
- imguiSlider("FOV", m_fov, 1.0f, 60.0f, 1.0f);
- if (imguiCheck("Spin Camera", m_cameraSpin))
- {
- m_cameraSpin = !m_cameraSpin;
+ // Start a new readback?
+ if (!m_reading
+ && m_mouseState.m_buttons[entry::MouseButton::Left])
+ {
+ // Blit and read
+ bgfx::blit(RENDER_PASS_BLIT, m_blitTex, 0, 0, m_pickingRT);
+ m_reading = bgfx::readTexture(m_blitTex, m_blitData);
+ }
}
- imguiEndArea();
imguiEndFrame();
// Advance to next frame. Rendering thread will be kicked to
@@ -389,14 +404,14 @@ class ExamplePicking : public entry::AppI
return false;
}
+ entry::MouseState m_mouseState;
+
uint32_t m_width;
uint32_t m_height;
uint32_t m_debug;
uint32_t m_reset;
int64_t m_timeOffset;
- entry::MouseState m_mouseState;
-
Mesh* m_meshes[12];
float m_meshScale[12];
float m_idsF[12][4];
@@ -422,4 +437,6 @@ class ExamplePicking : public entry::AppI
bool m_cameraSpin;
};
-ENTRY_IMPLEMENT_MAIN(ExamplePicking);
+} // namespace
+
+ENTRY_IMPLEMENT_MAIN(ExamplePicking, "30-picking", "Mouse picking via GPU texture readback.");