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:
@@ -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"
|
||||
|
||||
9
PyInt.h
9
PyInt.h
@@ -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"
|
||||
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
51
gl/pbo.cpp
Normal 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
17
gl/pbo.h
Normal 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();
|
||||
};
|
||||
}
|
||||
106
renderer.cpp
106
renderer.cpp
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user