GPU accelerated selection

This commit is contained in:
sshumakov3
2021-08-31 15:28:32 +03:00
parent 0fa66d6ad6
commit 05368885d1
11 changed files with 208 additions and 117 deletions

View File

@@ -145,8 +145,7 @@ vec4 texture_blend()
vec3 t2 = get_tex_color(vary_texcoord, instances[instanceID].ChunkTextureSamplers.z, instances[instanceID].ChunkTextureArrayIDs.z);
vec3 t3 = get_tex_color(vary_texcoord, instances[instanceID].ChunkTextureSamplers.w, instances[instanceID].ChunkTextureArrayIDs.w);
return mix(vec4 (1.0, 1.0, 1.0, 1.0), vec4 (t0 * (1.0 - (a0 + a1 + a2)) + t1 * a0 + t2 * a1 + t3 * a2, 1.0)
, int(instances[instanceID].ChunkHoles_DrawImpass_TexLayerCount_CantPaint.b > 0));
return vec4 (t0 * (1.0 - (a0 + a1 + a2)) + t1 * a0 + t2 * a1 + t3 * a2, 1.0);
}
float contour_alpha(float unit_size, float pos, float line_width)
@@ -169,7 +168,7 @@ void main()
vec3 fw = fwidth(vary_position.xyz);
out_color = texture_blend();
out_color = mix(vec4(1.0, 1.0, 1.0, 1.0), texture_blend(), int(instances[instanceID].ChunkHoles_DrawImpass_TexLayerCount_CantPaint.b > 0));
out_color.rgb *= vary_mccv;

View File

@@ -373,6 +373,19 @@ bool MapChunk::GetVertex(float x, float z, math::vector_3d *V)
return true;
}
void MapChunk::getVertexInternal(float x, float z, math::vector_3d* v)
{
float xdiff, zdiff;
xdiff = x - xbase;
zdiff = z - zbase;
const int row = static_cast<int>(zdiff / (UNITSIZE * 0.5f) + 0.5f);
const int column = static_cast<int>((xdiff - UNITSIZE * 0.5f * (row % 2)) / UNITSIZE + 0.5f);
*v = mVertices[17 * (row / 2) + ((row % 2) ? 9 : 0) + column];
}
float MapChunk::getHeight(int x, int z)
{
if (x > 9 || z > 9 || x < 0 || z < 0) return 0.0f;
@@ -599,115 +612,130 @@ void MapChunk::updateVerticesData()
update_intersect_points();
}
void MapChunk::recalcNorms (std::function<boost::optional<float> (float, float)> height)
math::vector_3d MapChunk::getNeighborVertex(int i, unsigned dir)
{
// This method assumes tile's heightmap texture is currently bound to the active tex unit
// i - vertex index
// 0 - up_left
// 1 - up_right
// 2 - down_left
// 3 - down_right
auto point
(
[this, height](int i, unsigned dir)
// Returns a neighboring vertex,
// if one does not exist,
// returns a virtual vertex with the height that equals to the height of MapChunks's vertex i.
constexpr float half_unit = UNITSIZE / 2.f;
static constexpr std::array xdiff{-half_unit, half_unit, half_unit, -half_unit};
static constexpr std::array zdiff{-half_unit, -half_unit, half_unit, half_unit};
static constexpr std::array idiff{-9, -8, 9, 8};
if ((i >= 1 && i <= 7 && dir < 2 && !py)
|| (i >= 137 && i <= 143 && (dir == 2 || dir == 3) && py == 15)
|| (!i && (dir < 2 && !py || (!dir || dir == 3) && !px))
|| (i == 8 && ((dir == 1 || dir == 2) && px == 15) || dir < 2 && !py)
|| (i == 136 && ((dir == 3 || dir == 2) && py == 15) || (!dir || dir == 3) && !px)
|| (i == 144 && ((dir == 3 || dir == 2) && py == 15) || ((dir == 1 || dir == 2) && px == 15))
|| (!(i % 17) && (!dir || dir == 3) && !px)
|| (!(i % 25) && (dir == 1 || dir == 2) && px == 15))
{
float vertex_x = mVertices[i].x + xdiff[dir];
float vertex_z = mVertices[i].z + zdiff[dir];
tile_index tile({vertex_x, 0, vertex_z});
if (!mt->_world->mapIndex.tileLoaded(tile))
{
constexpr float half_unit = UNITSIZE / 2.f;
static constexpr std::array xdiff{-half_unit, half_unit, half_unit, -half_unit};
static constexpr std::array zdiff{-half_unit, -half_unit, half_unit, half_unit};
static constexpr std::array idiff{-9, -8, 9, 8};
if ((i >= 1 && i <= 7 && dir < 2 && !py)
|| (i >= 137 && i <= 143 && (dir == 2 || dir == 3) && py == 15)
|| (!i && (dir < 2 && !py || (!dir || dir == 3) && !px))
|| (i == 8 && ((dir == 1 || dir == 2) && px == 15) || dir < 2 && !py)
|| (i == 136 && ((dir == 3 || dir == 2) && py == 15) || (!dir || dir == 3) && !px)
|| (i == 144 && ((dir == 3 || dir == 2) && py == 15) || ((dir == 1 || dir == 2) && px == 15))
|| (!(i % 17) && (!dir || dir == 3) && !px)
|| (!(i % 25) && (dir == 1 || dir == 2) && px == 15))
{
return math::vector_3d
( mVertices[i].x + xdiff[dir]
, height(mVertices[i].x + xdiff[dir], mVertices[i].z + zdiff[dir]).get_value_or(mVertices[i].y)
, mVertices[i].z + zdiff[dir]
);
}
switch (dir)
{
case 0:
{
if (!i)
return mt->getChunk(px - 1, py - 1)->mVertices[135];
else if (i == 136)
return mt->getChunk(px - 1, py)->mVertices[135];
else if (i == 8)
return mt->getChunk(px, py - 1)->mVertices[135];
else if (i >= 1 && i <= 7)
return mt->getChunk(px, py - 1)->mVertices[127 + i];
else if (!(i % 17))
return mt->getChunk(px - 1, py)->mVertices[i - 1];
break;
}
case 1:
{
if (!i)
return mt->getChunk(px, py - 1)->mVertices[128];
else if (i == 144)
return mt->getChunk(px + 1, py)->mVertices[128];
else if (i == 8)
return mt->getChunk(px + 1, py - 1)->mVertices[128];
else if (i >= 1 && i <= 7)
return mt->getChunk(px, py - 1)->mVertices[128 + i];
else if (!(i % 17 % 8) && i % 17 != 16 && i % 17)
return mt->getChunk(px + 1, py)->mVertices[i - 8];
break;
}
case 2:
{
if (i == 136)
return mt->getChunk(px, py + 1)->mVertices[9];
else if (i == 144)
return mt->getChunk(px + 1, py + 1)->mVertices[9];
else if (i == 8)
return mt->getChunk(px + 1, py)->mVertices[9];
else if (!(i % 17 % 8) && i % 17 != 16 && i && i % 17)
return mt->getChunk(px + 1, py)->mVertices[i + 9];
else if (i >= 137 && i <= 143)
return mt->getChunk(px, py + 1)->mVertices[i - 127];
break;
}
case 3:
{
if (!i)
return mt->getChunk(px - 1, py)->mVertices[16];
else if (i == 136)
return mt->getChunk(px - 1, py + 1)->mVertices[16];
else if (i == 144)
return mt->getChunk(px, py + 1)->mVertices[16];
else if (!(i % 17))
return mt->getChunk(px - 1, py)->mVertices[i + 16];
else if (i >= 137 && i <= 143)
return mt->getChunk(px, py + 1)->mVertices[i - 128];
break;
}
}
return mVertices[i + idiff[dir]];
return math::vector_3d( mVertices[i].x + xdiff[dir], mVertices[i].y, mVertices[i].z + zdiff[dir]);
}
);
math::vector_3d vertex{};
mt->_world->mapIndex.getTile(tile)->getVertexInternal(mVertices[i].x + xdiff[dir], mVertices[i].z + zdiff[dir], &vertex);
return math::vector_3d( mVertices[i].x + xdiff[dir], vertex.y, mVertices[i].z + zdiff[dir]);
}
switch (dir)
{
case 0:
{
if (!i)
return mt->getChunk(px - 1, py - 1)->mVertices[135];
else if (i == 136)
return mt->getChunk(px - 1, py)->mVertices[135];
else if (i == 8)
return mt->getChunk(px, py - 1)->mVertices[135];
else if (i >= 1 && i <= 7)
return mt->getChunk(px, py - 1)->mVertices[127 + i];
else if (!(i % 17))
return mt->getChunk(px - 1, py)->mVertices[i - 1];
break;
}
case 1:
{
if (!i)
return mt->getChunk(px, py - 1)->mVertices[128];
else if (i == 144)
return mt->getChunk(px + 1, py)->mVertices[128];
else if (i == 8)
return mt->getChunk(px + 1, py - 1)->mVertices[128];
else if (i >= 1 && i <= 7)
return mt->getChunk(px, py - 1)->mVertices[128 + i];
else if (!(i % 17 % 8) && i % 17 != 16 && i % 17)
return mt->getChunk(px + 1, py)->mVertices[i - 8];
break;
}
case 2:
{
if (i == 136)
return mt->getChunk(px, py + 1)->mVertices[9];
else if (i == 144)
return mt->getChunk(px + 1, py + 1)->mVertices[9];
else if (i == 8)
return mt->getChunk(px + 1, py)->mVertices[9];
else if (!(i % 17 % 8) && i % 17 != 16 && i && i % 17)
return mt->getChunk(px + 1, py)->mVertices[i + 9];
else if (i >= 137 && i <= 143)
return mt->getChunk(px, py + 1)->mVertices[i - 127];
break;
}
case 3:
{
if (!i)
return mt->getChunk(px - 1, py)->mVertices[16];
else if (i == 136)
return mt->getChunk(px - 1, py + 1)->mVertices[16];
else if (i == 144)
return mt->getChunk(px, py + 1)->mVertices[16];
else if (!(i % 17))
return mt->getChunk(px - 1, py)->mVertices[i + 16];
else if (i >= 137 && i <= 143)
return mt->getChunk(px, py + 1)->mVertices[i - 128];
break;
}
}
return mVertices[i + idiff[dir]];
}
void MapChunk::recalcNorms()
{
// 0 - up_left
// 1 - up_right
// 2 - down_left
// 3 - down_right
auto& tile_buffer = mt->getChunkHeightmapBuffer();
int chunk_start = (px * 16 + py) * mapbufsize * 4;
for (int i = 0; i < mapbufsize; ++i)
{
math::vector_3d const P1 (point(i, 0));
math::vector_3d const P2 (point(i, 1));
math::vector_3d const P3 (point(i, 2));
math::vector_3d const P4 (point(i, 3));
math::vector_3d const P1 (getNeighborVertex(i, 0)); // up_left
math::vector_3d const P2 (getNeighborVertex(i, 1)); // up_right
math::vector_3d const P3 (getNeighborVertex(i, 2)); // down_left
math::vector_3d const P4 (getNeighborVertex(i, 3)); // down_right
math::vector_3d const N1 ((P2 - mVertices[i]) % (P1 - mVertices[i]));
math::vector_3d const N2 ((P3 - mVertices[i]) % (P2 - mVertices[i]));

View File

@@ -129,8 +129,9 @@ public:
ChunkWater* liquid_chunk() const;
void updateVerticesData();
void recalcNorms (std::function<boost::optional<float> (float, float)> height);
void recalcNorms();
void updateNormalsData();
math::vector_3d getNeighborVertex(int i, unsigned dir);
//! \todo implement Action stack for these
bool changeTerrain(math::vector_3d const& pos, float change, float radius, int BrushType, float inner_radius);
@@ -168,6 +169,7 @@ public:
void setAreaID(int ID);
bool GetVertex(float x, float z, math::vector_3d *V);
void getVertexInternal(float x, float z, math::vector_3d * v);
float getHeight(int x, int z);
float getMinHeight();
float getMaxHeight() { return vmin.y; };

View File

@@ -445,8 +445,6 @@ void MapTile::draw ( math::frustum const& frustum
if (flags & ChunkUpdateFlags::ALPHAMAP)
{
std::fill(_samplers.begin(), _samplers.end(), -1);
gl.activeTexture(GL_TEXTURE0 + 3);
gl.bindTexture(GL_TEXTURE_2D_ARRAY, _alphamap_tex);
alphamap_bound = true;
@@ -754,6 +752,14 @@ bool MapTile::GetVertex(float x, float z, math::vector_3d *V)
return xcol >= 0 && xcol <= 15 && ycol >= 0 && ycol <= 15 && mChunks[ycol][xcol]->GetVertex(x, z, V);
}
void MapTile::getVertexInternal(float x, float z, math::vector_3d* v)
{
int xcol = (int)((x - xbase) / CHUNKSIZE);
int ycol = (int)((z - zbase) / CHUNKSIZE);
mChunks[ycol][xcol]->getVertexInternal(x, z, v);
}
/// --- Only saving related below this line. --------------------------
void MapTile::saveTile(World* world)

View File

@@ -105,6 +105,7 @@ public:
void drawMFBO (opengl::scoped::use_program&);
bool GetVertex(float x, float z, math::vector_3d *V);
void getVertexInternal(float x, float z, math::vector_3d* v);
void saveTile(World*);
void CropWater();

View File

@@ -44,7 +44,9 @@
#include <external/imguipiemenu/PieMenu.hpp>
#include <external/tracy/Tracy.hpp>
#include <noggit/ui/object_palette.hpp>
#include <external/glm/gtc/type_ptr.hpp>
#include <opengl/types.hpp>
#include <limits>
#include <noggit/ActionManager.hpp>
@@ -2618,6 +2620,11 @@ void MapView::initializeGL()
_world->initShaders();
onSettingsSave();
_buffers.upload();
gl.bufferData<GL_PIXEL_PACK_BUFFER>(_buffers[0], 4, nullptr, GL_DYNAMIC_READ);
gl.bufferData<GL_PIXEL_PACK_BUFFER>(_buffers[1], 4, nullptr, GL_DYNAMIC_READ);
_gl_initialized = true;
}
@@ -2776,6 +2783,12 @@ void MapView::paintGL()
_last_frame_durations.emplace_back (now - _last_update);
makeCurrent();
gl.clear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
draw_map();
if (!saving_minimap)
{
tick (now - _last_update);
@@ -2784,12 +2797,6 @@ void MapView::paintGL()
_last_update = now;
makeCurrent();
gl.clear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
draw_map();
if (saving_minimap)
{
gl.clear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@@ -3875,6 +3882,49 @@ void MapView::doSelection (bool selectTerrainOnly, bool mouseMove)
void MapView::update_cursor_pos()
{
static bool buffer_switch = false;
float mx = _last_mouse_pos.x(), mz = _last_mouse_pos.y();
//gl.readBuffer(GL_FRONT);
gl.bindBuffer(GL_PIXEL_PACK_BUFFER, _buffers[static_cast<unsigned>(buffer_switch)]);
gl.readPixels(mx, height() - mz - 1, 1, 1, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, 0);
gl.bindBuffer(GL_PIXEL_PACK_BUFFER, _buffers[static_cast<unsigned>(!buffer_switch)]);
GLushort* ptr = static_cast<GLushort*>(gl.mapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY));
buffer_switch = !buffer_switch;
if(ptr)
{
glm::vec4 viewport = glm::vec4(0, 0, width(), height());
glm::vec3 wincoord = glm::vec3(mx, height() - mz - 1, static_cast<float>(*ptr) / std::numeric_limits<unsigned short>::max());
math::matrix_4x4 model_view_ = model_view().transposed();
math::matrix_4x4 projection_ = projection().transposed();
glm::vec3 objcoord = glm::unProject(wincoord, glm::make_mat4(reinterpret_cast<float*>(&model_view_)),
glm::make_mat4(reinterpret_cast<float*>(&projection_)), viewport);
tile_index tile({objcoord.x, objcoord.y, objcoord.z});
if (!_world->mapIndex.tileLoaded(tile))
{
gl.unmapBuffer(GL_PIXEL_PACK_BUFFER);
gl.bindBuffer(GL_PIXEL_PACK_BUFFER, 0);
return;
}
_cursor_pos = {objcoord.x, objcoord.y, objcoord.z};
gl.unmapBuffer(GL_PIXEL_PACK_BUFFER);
}
gl.bindBuffer(GL_PIXEL_PACK_BUFFER, 0);
return;
selection_result results (intersect_result (true));
if (!results.empty())
@@ -4938,6 +4988,8 @@ void MapView::unloadOpenglData(bool from_manager)
if (!from_manager)
noggit::Red::ViewportManager::ViewportManager::unloadOpenglData(this);
_buffers.unload();
disconnect(_gl_guard_connection);
_gl_initialized = false;

View File

@@ -23,6 +23,7 @@
#include <external/qtimgui/QtImGui.h>
#include <external/QtAdvancedDockingSystem/src/DockManager.h>
#include <opengl/texture.hpp>
#include <opengl/scoped.hpp>
#include <boost/optional.hpp>
@@ -393,6 +394,8 @@ private:
bool _destroying = false;
bool _needs_redraw = false;
opengl::scoped::deferred_upload_buffers<2> _buffers;
public:
private:

View File

@@ -125,6 +125,9 @@ void PreviewRenderer::resetCamera(float x, float y, float z, float roll, float y
void PreviewRenderer::draw()
{
return;
float culldistance = 10000000;
math::matrix_4x4 const mvp(model_view().transposed() * projection().transposed());

View File

@@ -1511,6 +1511,7 @@ selection_result World::intersect ( math::matrix_4x4 const& model_view
if (draw_terrain)
{
ZoneScopedN("World::intersect() : intersect terrain");
for (auto&& tile : mapIndex.loaded_tiles())
{
if (tile->intersect(ray, &results))
@@ -1647,7 +1648,7 @@ bool World::GetVertex(float x, float z, math::vector_3d *V) const
MapTile* adt = mapIndex.getTile(tile);
return adt->finishedLoading() && adt->GetVertex(x, z, V);
return adt->GetVertex(x, z, V);
}
@@ -1830,15 +1831,9 @@ void World::blurTerrain(math::vector_3d const& pos, float remain, float radius,
}
void World::recalc_norms (MapChunk* chunk) const
{
{
ZoneScoped;
chunk->recalcNorms ( [this] (float x, float z) -> boost::optional<float>
{
math::vector_3d vec;
auto res (GetVertex (x, z, &vec));
return boost::make_optional (res, vec.y);
}
);
chunk->recalcNorms();
}
bool World::paintTexture(math::vector_3d const& pos, Brush* brush, float strength, float pressure, scoped_blp_texture_reference texture)

View File

@@ -274,7 +274,8 @@ Noggit::Noggit(int argc, char *argv[])
format.setSwapBehavior(QSurfaceFormat::TripleBuffer);
format.setSwapInterval(settings.value ("vsync", 0).toInt());
format.setRenderableType(QSurfaceFormat::OpenGL);
format.setDepthBufferSize(16);
format.setSamples(0);
if (doAntiAliasing)
{

View File

@@ -953,6 +953,7 @@ void opengl::context::bufferData (GLuint buffer, GLsizeiptr size, GLvoid const*
gl.bindBuffer (target, old);
}
template void opengl::context::bufferData<GL_ARRAY_BUFFER> (GLuint buffer, GLsizeiptr size, GLvoid const* data, GLenum usage);
template void opengl::context::bufferData<GL_PIXEL_PACK_BUFFER> (GLuint buffer, GLsizeiptr size, GLvoid const* data, GLenum usage);
template void opengl::context::bufferData<GL_ELEMENT_ARRAY_BUFFER> (GLuint buffer, GLsizeiptr size, GLvoid const* data, GLenum usage);
template<GLenum target, typename T>