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:
@@ -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"
|
||||||
|
|||||||
9
PyInt.h
9
PyInt.h
@@ -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"
|
||||||
|
|
||||||
|
|||||||
@@ -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];
|
||||||
|
|||||||
@@ -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);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
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();
|
||||||
|
};
|
||||||
|
}
|
||||||
76
renderer.cpp
76
renderer.cpp
@@ -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()
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user