mirror of
https://github.com/bkaradzic/bgfx.git
synced 2026-10-24 18:00:54 +00:00
310 lines
7.8 KiB
C++
310 lines
7.8 KiB
C++
/*
|
|
* Copyright 2011-2026 Branimir Karadzic. All rights reserved.
|
|
* License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE
|
|
*/
|
|
|
|
#include "common.h"
|
|
#include "bgfx_utils.h"
|
|
#include "imgui/imgui.h"
|
|
|
|
#include <bx/math.h>
|
|
|
|
namespace
|
|
{
|
|
|
|
constexpr uint32_t kSwapChainFlags = 0
|
|
| BGFX_SWAP_CHAIN_FULLSCREEN_MASK
|
|
| BGFX_SWAP_CHAIN_MSAA_MASK
|
|
| BGFX_SWAP_CHAIN_SRGB_BACKBUFFER
|
|
| BGFX_SWAP_CHAIN_HDR10
|
|
| BGFX_SWAP_CHAIN_HIDPI
|
|
| BGFX_SWAP_CHAIN_TRANSPARENT_BACKBUFFER
|
|
;
|
|
|
|
constexpr uint32_t kNumGray = 7;
|
|
constexpr uint32_t kNumBars = 6;
|
|
|
|
constexpr float kGrayNits[kNumGray] = { 0.0f, 100.0f, 203.0f, 400.0f, 1000.0f, 4000.0f, 10000.0f };
|
|
constexpr float kGrayScale[kNumGray] = { 0.0f, 0.5f, 1.0f, 2.0f, 4.0f, 8.0f, 16.0f };
|
|
constexpr float kBarNits = 203.0f;
|
|
|
|
constexpr float kBarColor[kNumBars][3] =
|
|
{
|
|
{ 1.0f, 0.0f, 0.0f },
|
|
{ 0.0f, 1.0f, 0.0f },
|
|
{ 0.0f, 0.0f, 1.0f },
|
|
{ 0.0f, 1.0f, 1.0f },
|
|
{ 1.0f, 0.0f, 1.0f },
|
|
{ 1.0f, 1.0f, 0.0f },
|
|
};
|
|
|
|
constexpr const char* kBarName[kNumBars] = { "R", "G", "B", "C", "M", "Y" };
|
|
|
|
float encodePq(float _nits)
|
|
{
|
|
constexpr float m1 = 2610.0f/16384.0f;
|
|
constexpr float m2 = 2523.0f/4096.0f*128.0f;
|
|
constexpr float c1 = 3424.0f/4096.0f;
|
|
constexpr float c2 = 2413.0f/4096.0f*32.0f;
|
|
constexpr float c3 = 2392.0f/4096.0f*32.0f;
|
|
|
|
const float yy = bx::pow(bx::clamp(_nits/10000.0f, 0.0f, 1.0f), m1);
|
|
|
|
return bx::pow( (c1 + c2*yy) / (1.0f + c3*yy), m2);
|
|
}
|
|
|
|
class ExampleHdr10 : public entry::AppI
|
|
{
|
|
public:
|
|
ExampleHdr10(const char* _name, const char* _description, const char* _url)
|
|
: entry::AppI(_name, _description, _url)
|
|
{
|
|
}
|
|
|
|
void init(int32_t _argc, const char* const* _argv, uint32_t _width, uint32_t _height) override
|
|
{
|
|
Args args(_argc, _argv);
|
|
|
|
m_width = _width;
|
|
m_height = _height;
|
|
m_debug = BGFX_DEBUG_NONE;
|
|
m_reset = BGFX_RESET_VSYNC|BGFX_RESET_HDR10;
|
|
m_pq = true;
|
|
|
|
bgfx::Init init;
|
|
init.type = args.m_type;
|
|
init.vendorId = args.m_pciId;
|
|
init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle);
|
|
init.swapChain.ndt = entry::getNativeDisplayHandle();
|
|
init.platformData.type = entry::getNativeWindowHandleType();
|
|
init.swapChain.width = m_width;
|
|
init.swapChain.height = m_height;
|
|
init.swapChain.formatColor = getFormat();
|
|
init.reset = m_reset;
|
|
bgfx::init(init);
|
|
|
|
bgfx::setDebug(m_debug);
|
|
|
|
m_appliedWidth = m_width;
|
|
m_appliedHeight = m_height;
|
|
m_appliedReset = m_reset;
|
|
m_appliedPq = m_pq;
|
|
|
|
imguiCreate();
|
|
}
|
|
|
|
int shutdown() override
|
|
{
|
|
imguiDestroy();
|
|
|
|
bgfx::shutdown();
|
|
|
|
return 0;
|
|
}
|
|
|
|
bgfx::TextureFormat::Enum getFormat() const
|
|
{
|
|
return m_pq
|
|
? bgfx::TextureFormat::RGB10A2
|
|
: bgfx::TextureFormat::RGBA16F
|
|
;
|
|
}
|
|
|
|
void setPatch(uint8_t _index, float _red, float _green, float _blue)
|
|
{
|
|
const float rgba[4] = { _red, _green, _blue, 1.0f };
|
|
bgfx::setPaletteColor(_index, rgba);
|
|
}
|
|
|
|
float encode(float _nits, float _scale) const
|
|
{
|
|
return m_pq ? encodePq(_nits) : _scale;
|
|
}
|
|
|
|
void imguiLabel(float _x, float _y, const char* _id, const char* _text)
|
|
{
|
|
ImGui::SetNextWindowPos(ImVec2(_x, _y), 0, ImVec2(0.5f, 1.0f) );
|
|
ImGui::SetNextWindowBgAlpha(0.5f);
|
|
|
|
ImGui::Begin(_id, NULL, 0
|
|
| ImGuiWindowFlags_NoInputs
|
|
| ImGuiWindowFlags_NoTitleBar
|
|
| ImGuiWindowFlags_NoMove
|
|
| ImGuiWindowFlags_NoResize
|
|
| ImGuiWindowFlags_NoSavedSettings
|
|
| ImGuiWindowFlags_AlwaysAutoResize
|
|
);
|
|
ImGui::Text("%s", _text);
|
|
ImGui::End();
|
|
}
|
|
|
|
void submitPatch(bgfx::ViewId _view, uint8_t _index, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height)
|
|
{
|
|
bgfx::setViewRect(_view, _x, _y, _width, _height);
|
|
bgfx::setViewClear(_view, BGFX_CLEAR_COLOR, 1.0f, 0, _index);
|
|
bgfx::touch(_view);
|
|
}
|
|
|
|
bool update() override
|
|
{
|
|
if (entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
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)
|
|
);
|
|
|
|
showExampleDialog(this);
|
|
|
|
bool hdr10 = 0 != (m_reset & BGFX_RESET_HDR10);
|
|
|
|
ImGui::SetNextWindowPos(ImVec2(m_width - m_width / 5.0f - 10.0f, 10.0f), ImGuiCond_FirstUseEver);
|
|
ImGui::SetNextWindowSize(ImVec2(m_width / 5.0f, m_height / 6.0f), ImGuiCond_FirstUseEver);
|
|
ImGui::Begin("Settings", NULL, 0);
|
|
|
|
if (ImGui::RadioButton("PQ, RGB10A2", m_pq) )
|
|
{
|
|
m_pq = true;
|
|
}
|
|
|
|
if (ImGui::RadioButton("Linear, RGBA16F", !m_pq) )
|
|
{
|
|
m_pq = false;
|
|
}
|
|
|
|
ImGui::Checkbox("HDR10", &hdr10);
|
|
|
|
ImGui::End();
|
|
|
|
const float labelRowHeight = float(m_height*2/5);
|
|
|
|
char id[32];
|
|
char text[128];
|
|
|
|
for (uint32_t ii = 0; ii < kNumGray; ++ii)
|
|
{
|
|
if (m_pq)
|
|
{
|
|
bx::snprintf(text, BX_COUNTOF(text), "%.0f nits", kGrayNits[ii]);
|
|
}
|
|
else
|
|
{
|
|
bx::snprintf(text, BX_COUNTOF(text), "%.1fx white", kGrayScale[ii]);
|
|
}
|
|
|
|
bx::snprintf(id, BX_COUNTOF(id), "gray%d", ii);
|
|
imguiLabel(m_width*(ii + 0.5f)/kNumGray, labelRowHeight - 10.0f, id, text);
|
|
}
|
|
|
|
for (uint32_t ii = 0; ii < kNumBars; ++ii)
|
|
{
|
|
if (m_pq)
|
|
{
|
|
bx::snprintf(text, BX_COUNTOF(text), "%s %.0f nits", kBarName[ii], kBarNits);
|
|
}
|
|
else
|
|
{
|
|
bx::snprintf(text, BX_COUNTOF(text), "%s 1.0x white", kBarName[ii]);
|
|
}
|
|
|
|
bx::snprintf(id, BX_COUNTOF(id), "bar%d", ii);
|
|
imguiLabel(m_width*(ii + 0.5f)/kNumBars, 2.0f*labelRowHeight - 10.0f, id, text);
|
|
}
|
|
|
|
const bgfx::Caps* caps = bgfx::getCaps();
|
|
|
|
bx::snprintf(text, BX_COUNTOF(text), "BGFX_CAPS_HDR10: %s, back buffer: %s"
|
|
, 0 != (caps->supported & BGFX_CAPS_HDR10) ? "supported" : "not supported"
|
|
, m_pq ? "RGB10A2, PQ BT.2020" : "RGBA16F, extended linear sRGB"
|
|
);
|
|
imguiLabel(m_width*0.5f, m_height - 10.0f, "status", text);
|
|
|
|
imguiEndFrame();
|
|
|
|
m_reset = (m_reset & ~BGFX_RESET_HDR10) | (hdr10 ? BGFX_RESET_HDR10 : 0);
|
|
|
|
if (m_width != m_appliedWidth
|
|
|| m_height != m_appliedHeight
|
|
|| m_reset != m_appliedReset
|
|
|| m_pq != m_appliedPq)
|
|
{
|
|
m_appliedWidth = m_width;
|
|
m_appliedHeight = m_height;
|
|
m_appliedReset = m_reset;
|
|
m_appliedPq = m_pq;
|
|
|
|
bgfx::SwapChain swapChain;
|
|
swapChain.width = m_width;
|
|
swapChain.height = m_height;
|
|
swapChain.flags = m_reset & kSwapChainFlags;
|
|
swapChain.formatColor = getFormat();
|
|
|
|
bgfx::reset(m_reset & ~kSwapChainFlags, &swapChain);
|
|
}
|
|
|
|
bgfx::setViewRect(0, 0, 0, uint16_t(m_width), uint16_t(m_height) );
|
|
bgfx::setViewClear(0, BGFX_CLEAR_COLOR, 0x000000ff, 1.0f, 0);
|
|
bgfx::touch(0);
|
|
|
|
const uint16_t rowHeight = uint16_t(m_height*2/5);
|
|
|
|
for (uint32_t ii = 0; ii < kNumGray; ++ii)
|
|
{
|
|
const float value = encode(kGrayNits[ii], kGrayScale[ii]);
|
|
setPatch(uint8_t(ii), value, value, value);
|
|
|
|
const uint16_t x0 = uint16_t(m_width* ii /kNumGray);
|
|
const uint16_t x1 = uint16_t(m_width*(ii + 1)/kNumGray);
|
|
submitPatch(bgfx::ViewId(1 + ii), uint8_t(ii), x0, 0, x1 - x0, rowHeight);
|
|
}
|
|
|
|
for (uint32_t ii = 0; ii < kNumBars; ++ii)
|
|
{
|
|
const float on = encode(kBarNits, 1.0f);
|
|
setPatch(uint8_t(kNumGray + ii)
|
|
, kBarColor[ii][0]*on
|
|
, kBarColor[ii][1]*on
|
|
, kBarColor[ii][2]*on
|
|
);
|
|
|
|
const uint16_t x0 = uint16_t(m_width* ii /kNumBars);
|
|
const uint16_t x1 = uint16_t(m_width*(ii + 1)/kNumBars);
|
|
submitPatch(bgfx::ViewId(1 + kNumGray + ii), uint8_t(kNumGray + ii), x0, rowHeight, x1 - x0, rowHeight);
|
|
}
|
|
|
|
bgfx::frame();
|
|
|
|
return true;
|
|
}
|
|
|
|
entry::MouseState m_mouseState;
|
|
|
|
uint32_t m_width;
|
|
uint32_t m_height;
|
|
uint32_t m_debug;
|
|
uint32_t m_reset;
|
|
bool m_pq;
|
|
|
|
uint32_t m_appliedWidth;
|
|
uint32_t m_appliedHeight;
|
|
uint32_t m_appliedReset;
|
|
bool m_appliedPq;
|
|
};
|
|
|
|
} // namespace
|
|
|
|
ENTRY_IMPLEMENT_MAIN(
|
|
ExampleHdr10
|
|
, "55-hdr10"
|
|
, "HDR10 test pattern."
|
|
, "https://bkaradzic.github.io/bgfx/examples.html#hdr10"
|
|
);
|