16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-18 00:49:19 +02:00

use pbo for picking buffers, restore picking for scenery nodes

This commit is contained in:
milek7
2018-10-23 17:04:04 +02:00
parent cdd79e605c
commit 0c460e9e0d
10 changed files with 165 additions and 53 deletions

View File

@@ -5,7 +5,7 @@ include(cotire)
set(DEPS_DIR ${DEPS_DIR} "${CMAKE_SOURCE_DIR}/ref")
project("eu07")
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD 17)
include_directories("." "Console" "McZapkie" "gl" "ref/glad/include")
file(GLOB HEADERS "*.h" "Console/*.h" "McZapkie/*.h" "gl/*.h")
@@ -109,6 +109,7 @@ set(SOURCES
"gl/glsl_common.cpp"
"gl/buffer.cpp"
"gl/fence.cpp"
"gl/pbo.cpp"
"imgui/imgui.cpp"
"imgui/imgui_demo.cpp"

View File

@@ -18,6 +18,10 @@ http://mozilla.org/MPL/2.0/.
#undef _XOPEN_SOURCE
#endif
#ifdef __GNUC__
#pragma GCC diagnostic ignored "-Wregister"
#endif
#ifdef _DEBUG
#undef _DEBUG // bez tego macra Py_DECREF powoduja problemy przy linkowaniu
#include "Python.h"
@@ -25,6 +29,11 @@ http://mozilla.org/MPL/2.0/.
#else
#include "Python.h"
#endif
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#include "Classes.h"
#include "utilities.h"

View File

@@ -64,4 +64,19 @@ void gl::buffer::upload(targets target, const void *data, int offset, int size)
glBufferSubData(glenum_target(target), offset, size, data);
}
void gl::buffer::download(targets target, void *data, int offset, int size)
{
bind(target);
if (GLAD_GL_VERSION_3_3)
{
glGetBufferSubData(glenum_target(target), offset, size, data);
}
else
{
void *glbuf = glMapBufferRange(glenum_target(target), offset, size, GL_MAP_READ_BIT);
memcpy(data, glbuf, size);
glUnmapBuffer(glenum_target(target));
}
}
GLuint gl::buffer::binding_points[13];

View File

@@ -40,5 +40,6 @@ namespace gl
void allocate(targets target, int size, GLenum hint);
void upload(targets target, const void *data, int offset, int size);
void download(targets target, void *data, int offset, int size);
};
}

View File

@@ -12,7 +12,8 @@ gl::fence::~fence()
bool gl::fence::is_signalled()
{
GLsizei len = 0;
GLint val;
glGetSynciv(sync, GL_SYNC_STATUS, 1, &val);
return val == GL_SIGNALED;
glGetSynciv(sync, GL_SYNC_STATUS, 1, &len, &val);
return len == 1 && val == GL_SIGNALED;
}

View File

@@ -11,5 +11,8 @@ namespace gl
~fence();
bool is_signalled();
fence(const fence&) = delete;
fence& operator=(const fence&) = delete;
};
}

51
gl/pbo.cpp Normal file
View File

@@ -0,0 +1,51 @@
#include "pbo.h"
void gl::pbo::request_read(int x, int y, int lx, int ly)
{
int s = lx * ly * 4;
if (s != size)
allocate(PIXEL_PACK_BUFFER, s, GL_STREAM_DRAW);
size = s;
data_ready = false;
sync.reset();
bind(PIXEL_PACK_BUFFER);
glReadPixels(x, y, lx, ly, GL_RGBA, GL_UNSIGNED_BYTE, 0);
unbind(PIXEL_PACK_BUFFER);
sync.emplace();
}
bool gl::pbo::read_data(int lx, int ly, uint8_t *data)
{
is_busy();
if (!data_ready)
return false;
int s = lx * ly * 4;
if (s != size)
return false;
download(PIXEL_PACK_BUFFER, data, 0, s);
unbind(PIXEL_PACK_BUFFER);
data_ready = false;
return true;
}
bool gl::pbo::is_busy()
{
if (!sync)
return false;
if (sync->is_signalled())
{
data_ready = true;
sync.reset();
return false;
}
return true;
}

17
gl/pbo.h Normal file
View File

@@ -0,0 +1,17 @@
#include "buffer.h"
#include "fence.h"
#include <optional>
namespace gl {
class pbo : private buffer
{
std::optional<fence> sync;
int size = 0;
bool data_ready;
public:
void request_read(int x, int y, int lx, int ly);
bool read_data(int lx, int ly, uint8_t *data);
bool is_busy();
};
}

View File

@@ -294,6 +294,10 @@ bool opengl_renderer::Init(GLFWwindow *Window)
WriteLog("envmap enabled");
}
m_picking_pbo = std::make_unique<gl::pbo>();
m_picking_node_pbo = std::make_unique<gl::pbo>();
WriteLog("picking pbos created");
WriteLog("renderer initialization finished!");
return true;
@@ -1784,6 +1788,8 @@ void opengl_renderer::Render(cell_sequence::iterator First, cell_sequence::itera
model_ubs.param[0] = glm::vec4(pick_color(m_picksceneryitems.size() + 1), 1.0f);
Render(path);
}
// post-render cleanup
::glPopMatrix();
break;
}
case rendermode::reflections:
@@ -3347,66 +3353,70 @@ void opengl_renderer::Render_Alpha(TSubModel *Submodel)
// utility methods
TSubModel const *opengl_renderer::Update_Pick_Control()
{
Render_pass(rendermode::pickcontrols);
if (!m_picking_pbo->is_busy())
{
unsigned char pickreadout[4];
if (m_picking_pbo->read_data(1, 1, pickreadout))
{
auto const controlindex = pick_index(glm::ivec3{pickreadout[0], pickreadout[1], pickreadout[2]});
TSubModel const *control{nullptr};
if ((controlindex > 0) && (controlindex <= m_pickcontrolsitems.size()))
{
control = m_pickcontrolsitems[controlindex - 1];
}
// determine point to examine
glm::dvec2 mousepos = Application.get_cursor_pos();
mousepos.y = Global.iWindowHeight - mousepos.y; // cursor coordinates are flipped compared to opengl
glm::ivec2 pickbufferpos;
pickbufferpos = glm::ivec2{mousepos.x * EU07_PICKBUFFERSIZE / std::max(1, Global.iWindowWidth), mousepos.y * EU07_PICKBUFFERSIZE / std::max(1, Global.iWindowHeight)};
unsigned char pickreadout[4];
// m7t: ! replace with PBO and wait frame or two to improve performance
m_pick_fb->bind();
::glReadPixels(pickbufferpos.x, pickbufferpos.y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pickreadout);
m_pick_fb->unbind();
auto const controlindex = pick_index(glm::ivec3{pickreadout[0], pickreadout[1], pickreadout[2]});
TSubModel const *control{nullptr};
if ((controlindex > 0) && (controlindex <= m_pickcontrolsitems.size()))
{
control = m_pickcontrolsitems[controlindex - 1];
}
m_pickcontrolitem = control;
return control;
}
scene::basic_node *opengl_renderer::Update_Pick_Node()
{
// m7t: restore picking
/*
Render_pass(rendermode::pickscenery);
m_pickcontrolitem = control;
}
// determine point to examine
glm::dvec2 mousepos;
glfwGetCursorPos(m_window, &mousepos.x, &mousepos.y);
glm::dvec2 mousepos = Application.get_cursor_pos();
mousepos.y = Global.iWindowHeight - mousepos.y; // cursor coordinates are flipped compared to opengl
glm::ivec2 pickbufferpos;
pickbufferpos = glm::ivec2{mousepos.x * EU07_PICKBUFFERSIZE / std::max(1, Global.iWindowWidth), mousepos.y * EU07_PICKBUFFERSIZE / std::max(1, Global.iWindowHeight)};
pickbufferpos = glm::clamp(pickbufferpos, glm::ivec2(0, 0), glm::ivec2(EU07_PICKBUFFERSIZE - 1, EU07_PICKBUFFERSIZE - 1));
unsigned char pickreadout[3];
// m7t: ! replace with PBO and wait frame or two to improve performance
// (and don't clash with control picking)
Render_pass(rendermode::pickcontrols);
m_pick_fb->bind();
::glReadPixels(pickbufferpos.x, pickbufferpos.y, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, pickreadout);
m_picking_pbo->request_read(pickbufferpos.x, pickbufferpos.y, 1, 1);
m_pick_fb->unbind();
}
auto const nodeindex = pick_index(glm::ivec3{pickreadout[0], pickreadout[1], pickreadout[2]});
scene::basic_node const *node{nullptr};
if ((nodeindex > 0) && (nodeindex <= m_picksceneryitems.size()))
return m_pickcontrolitem;
}
scene::basic_node *opengl_renderer::Update_Pick_Node()
{
if (!m_picking_node_pbo->is_busy())
{
unsigned char pickreadout[4];
if (m_picking_node_pbo->read_data(1, 1, pickreadout))
{
node = m_picksceneryitems[nodeindex - 1];
auto const nodeindex = pick_index(glm::ivec3{pickreadout[0], pickreadout[1], pickreadout[2]});
scene::basic_node *node{nullptr};
if ((nodeindex > 0) && (nodeindex <= m_picksceneryitems.size()))
{
node = m_picksceneryitems[nodeindex - 1];
}
m_picksceneryitem = node;
}
m_picksceneryitem = node;
return node;
*/
return nullptr;
// determine point to examine
glm::dvec2 mousepos = Application.get_cursor_pos();
mousepos.y = Global.iWindowHeight - mousepos.y; // cursor coordinates are flipped compared to opengl
glm::ivec2 pickbufferpos;
pickbufferpos = glm::ivec2{mousepos.x * EU07_PICKBUFFERSIZE / std::max(1, Global.iWindowWidth), mousepos.y * EU07_PICKBUFFERSIZE / std::max(1, Global.iWindowHeight)};
pickbufferpos = glm::clamp(pickbufferpos, glm::ivec2(0, 0), glm::ivec2(EU07_PICKBUFFERSIZE - 1, EU07_PICKBUFFERSIZE - 1));
Render_pass(rendermode::pickscenery);
m_pick_fb->bind();
m_picking_node_pbo->request_read(pickbufferpos.x, pickbufferpos.y, 1, 1);
m_pick_fb->unbind();
}
return m_picksceneryitem;
}
glm::dvec3 opengl_renderer::Update_Mouse_Position()
@@ -3488,7 +3498,7 @@ void opengl_renderer::Update(double const Deltatime)
if ((true == Global.ControlPicking) && (false == FreeFlyModeFlag))
{
Update_Pick_Control();
Update_Pick_Control();
}
else
{
@@ -3497,7 +3507,7 @@ void opengl_renderer::Update(double const Deltatime)
// temporary conditions for testing. eventually will be coupled with editor mode
if ((true == Global.ControlPicking) && (true == DebugModeFlag) && (true == FreeFlyModeFlag))
{
Update_Pick_Node();
Update_Pick_Node();
}
else
{

View File

@@ -26,6 +26,7 @@ http://mozilla.org/MPL/2.0/.
#include "gl/shader.h"
#include "gl/cubemap.h"
#include "gl/glsl_common.h"
#include "gl/pbo.h"
#define EU07_USE_PICKING_FRAMEBUFFER
//#define EU07_USE_DEBUG_SHADOWMAP
@@ -321,8 +322,8 @@ class opengl_renderer
renderpass_config m_cabshadowpass; // parameters of most recent cab shadowmap pass
std::vector<TSubModel const *> m_pickcontrolsitems;
TSubModel const *m_pickcontrolitem{nullptr};
std::vector<scene::basic_node const *> m_picksceneryitems;
scene::basic_node const *m_picksceneryitem{nullptr};
std::vector<scene::basic_node *> m_picksceneryitems;
scene::basic_node *m_picksceneryitem{nullptr};
glm::vec3 m_worldmousecoordinates { 0.f };
#ifdef EU07_USE_DEBUG_CAMERA
renderpass_config m_worldcamera; // debug item
@@ -389,6 +390,9 @@ class opengl_renderer
std::unique_ptr<gl::cubemap> m_empty_cubemap;
std::unique_ptr<gl::pbo> m_picking_pbo;
std::unique_ptr<gl::pbo> m_picking_node_pbo;
material_handle m_invalid_material;
bool m_blendingenabled;