16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-22 17:29:18 +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") set(DEPS_DIR ${DEPS_DIR} "${CMAKE_SOURCE_DIR}/ref")
project("eu07") project("eu07")
set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD 17)
include_directories("." "Console" "McZapkie" "gl" "ref/glad/include") include_directories("." "Console" "McZapkie" "gl" "ref/glad/include")
file(GLOB HEADERS "*.h" "Console/*.h" "McZapkie/*.h" "gl/*.h") file(GLOB HEADERS "*.h" "Console/*.h" "McZapkie/*.h" "gl/*.h")
@@ -109,6 +109,7 @@ set(SOURCES
"gl/glsl_common.cpp" "gl/glsl_common.cpp"
"gl/buffer.cpp" "gl/buffer.cpp"
"gl/fence.cpp" "gl/fence.cpp"
"gl/pbo.cpp"
"imgui/imgui.cpp" "imgui/imgui.cpp"
"imgui/imgui_demo.cpp" "imgui/imgui_demo.cpp"

View File

@@ -18,6 +18,10 @@ http://mozilla.org/MPL/2.0/.
#undef _XOPEN_SOURCE #undef _XOPEN_SOURCE
#endif #endif
#ifdef __GNUC__
#pragma GCC diagnostic ignored "-Wregister"
#endif
#ifdef _DEBUG #ifdef _DEBUG
#undef _DEBUG // bez tego macra Py_DECREF powoduja problemy przy linkowaniu #undef _DEBUG // bez tego macra Py_DECREF powoduja problemy przy linkowaniu
#include "Python.h" #include "Python.h"
@@ -25,6 +29,11 @@ http://mozilla.org/MPL/2.0/.
#else #else
#include "Python.h" #include "Python.h"
#endif #endif
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#include "Classes.h" #include "Classes.h"
#include "utilities.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); 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]; GLuint gl::buffer::binding_points[13];

View File

@@ -40,5 +40,6 @@ namespace gl
void allocate(targets target, int size, GLenum hint); void allocate(targets target, int size, GLenum hint);
void upload(targets target, const void *data, int offset, int size); 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() bool gl::fence::is_signalled()
{ {
GLsizei len = 0;
GLint val; GLint val;
glGetSynciv(sync, GL_SYNC_STATUS, 1, &val); glGetSynciv(sync, GL_SYNC_STATUS, 1, &len, &val);
return val == GL_SIGNALED; return len == 1 && val == GL_SIGNALED;
} }

View File

@@ -11,5 +11,8 @@ namespace gl
~fence(); ~fence();
bool is_signalled(); 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"); 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!"); WriteLog("renderer initialization finished!");
return true; 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); model_ubs.param[0] = glm::vec4(pick_color(m_picksceneryitems.size() + 1), 1.0f);
Render(path); Render(path);
} }
// post-render cleanup
::glPopMatrix();
break; break;
} }
case rendermode::reflections: case rendermode::reflections:
@@ -3347,22 +3353,11 @@ void opengl_renderer::Render_Alpha(TSubModel *Submodel)
// utility methods // utility methods
TSubModel const *opengl_renderer::Update_Pick_Control() TSubModel const *opengl_renderer::Update_Pick_Control()
{ {
Render_pass(rendermode::pickcontrols); if (!m_picking_pbo->is_busy())
{
// 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]; unsigned char pickreadout[4];
if (m_picking_pbo->read_data(1, 1, pickreadout))
// 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]}); auto const controlindex = pick_index(glm::ivec3{pickreadout[0], pickreadout[1], pickreadout[2]});
TSubModel const *control{nullptr}; TSubModel const *control{nullptr};
if ((controlindex > 0) && (controlindex <= m_pickcontrolsitems.size())) if ((controlindex > 0) && (controlindex <= m_pickcontrolsitems.size()))
@@ -3371,42 +3366,57 @@ TSubModel const *opengl_renderer::Update_Pick_Control()
} }
m_pickcontrolitem = control; m_pickcontrolitem = control;
return control;
} }
scene::basic_node *opengl_renderer::Update_Pick_Node()
{
// m7t: restore picking
/*
Render_pass(rendermode::pickscenery);
// determine point to examine // determine point to examine
glm::dvec2 mousepos; glm::dvec2 mousepos = Application.get_cursor_pos();
glfwGetCursorPos(m_window, &mousepos.x, &mousepos.y);
mousepos.y = Global.iWindowHeight - mousepos.y; // cursor coordinates are flipped compared to opengl mousepos.y = Global.iWindowHeight - mousepos.y; // cursor coordinates are flipped compared to opengl
glm::ivec2 pickbufferpos; 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::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]; Render_pass(rendermode::pickcontrols);
// m7t: ! replace with PBO and wait frame or two to improve performance
// (and don't clash with control picking)
m_pick_fb->bind(); 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(); m_pick_fb->unbind();
}
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))
{
auto const nodeindex = pick_index(glm::ivec3{pickreadout[0], pickreadout[1], pickreadout[2]}); auto const nodeindex = pick_index(glm::ivec3{pickreadout[0], pickreadout[1], pickreadout[2]});
scene::basic_node const *node{nullptr}; scene::basic_node *node{nullptr};
if ((nodeindex > 0) && (nodeindex <= m_picksceneryitems.size())) if ((nodeindex > 0) && (nodeindex <= m_picksceneryitems.size()))
{ {
node = m_picksceneryitems[nodeindex - 1]; 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() glm::dvec3 opengl_renderer::Update_Mouse_Position()

View File

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