lightpreview: preliminary vis culling
- q2 only - not handling bmodels properly
This commit is contained in:
parent
07020ceeae
commit
edb664f200
|
|
@ -79,6 +79,7 @@ GLView::~GLView()
|
|||
|
||||
placeholder_texture.reset();
|
||||
lightmap_texture.reset();
|
||||
face_visibility_texture.reset();
|
||||
m_drawcalls.clear();
|
||||
|
||||
doneCurrent();
|
||||
|
|
@ -121,10 +122,24 @@ static const char *s_vertShader_Wireframe = R"(
|
|||
#version 330 core
|
||||
|
||||
layout (location = 0) in vec3 position;
|
||||
layout (location = 6) in int face_index;
|
||||
|
||||
uniform mat4 MVP;
|
||||
uniform usampler1D face_visibility_sampler;
|
||||
|
||||
bool is_culled() {
|
||||
int byte_index = face_index;
|
||||
|
||||
uint sampled = texelFetch(face_visibility_sampler, byte_index, 0).r;
|
||||
|
||||
return sampled != 16u;
|
||||
}
|
||||
|
||||
void main() {
|
||||
if (is_culled()) {
|
||||
gl_Position = vec4(0.0);
|
||||
return;
|
||||
}
|
||||
gl_Position = MVP * vec4(position, 1.0);
|
||||
}
|
||||
)";
|
||||
|
|
@ -193,6 +208,7 @@ layout (location = 2) in vec2 vertex_lightmap_uv;
|
|||
layout (location = 3) in vec3 vertex_normal;
|
||||
layout (location = 4) in vec3 vertex_flat_color;
|
||||
layout (location = 5) in uint vertex_styles;
|
||||
layout (location = 6) in int face_index;
|
||||
|
||||
out vec2 uv;
|
||||
out vec2 lightmap_uv;
|
||||
|
|
@ -201,8 +217,22 @@ flat out vec3 flat_color;
|
|||
flat out uint styles;
|
||||
|
||||
uniform mat4 MVP;
|
||||
uniform usampler1D face_visibility_sampler;
|
||||
|
||||
bool is_culled() {
|
||||
int byte_index = face_index;
|
||||
|
||||
uint sampled = texelFetch(face_visibility_sampler, byte_index, 0).r;
|
||||
|
||||
return sampled != 16u;
|
||||
}
|
||||
|
||||
void main() {
|
||||
if (is_culled()) {
|
||||
gl_Position = vec4(0.0);
|
||||
return;
|
||||
}
|
||||
|
||||
gl_Position = MVP * vec4(position.x, position.y, position.z, 1.0);
|
||||
|
||||
uv = vertex_uv;
|
||||
|
|
@ -277,6 +307,7 @@ layout (location = 2) in vec2 vertex_lightmap_uv;
|
|||
layout (location = 3) in vec3 vertex_normal;
|
||||
layout (location = 4) in vec3 vertex_flat_color;
|
||||
layout (location = 5) in uint vertex_styles;
|
||||
layout (location = 6) in int face_index;
|
||||
|
||||
out vec3 fragment_world_pos;
|
||||
out vec2 lightmap_uv;
|
||||
|
|
@ -286,8 +317,22 @@ flat out uint styles;
|
|||
|
||||
uniform mat4 MVP;
|
||||
uniform vec3 eye_origin;
|
||||
uniform usampler1D face_visibility_sampler;
|
||||
|
||||
bool is_culled() {
|
||||
int byte_index = face_index;
|
||||
|
||||
uint sampled = texelFetch(face_visibility_sampler, byte_index, 0).r;
|
||||
|
||||
return sampled != 16u;
|
||||
}
|
||||
|
||||
void main() {
|
||||
if (is_culled()) {
|
||||
gl_Position = vec4(0.0);
|
||||
return;
|
||||
}
|
||||
|
||||
gl_Position = MVP * vec4(position, 1.0);
|
||||
fragment_world_pos = position;
|
||||
|
||||
|
|
@ -298,6 +343,72 @@ void main() {
|
|||
}
|
||||
)";
|
||||
|
||||
void GLView::updateFaceVisibility()
|
||||
{
|
||||
if (!m_bsp)
|
||||
return;
|
||||
|
||||
const mbsp_t &bsp = *m_bsp;
|
||||
const auto &world = bsp.dmodels.at(0);
|
||||
|
||||
auto *leaf = BSP_FindLeafAtPoint(&bsp, &world, qvec3d{m_cameraOrigin.x(), m_cameraOrigin.y(), m_cameraOrigin.z()});
|
||||
|
||||
int leafnum = leaf - bsp.dleafs.data();
|
||||
int clusternum = leaf->cluster;
|
||||
|
||||
if (m_lastLeaf == clusternum) {
|
||||
qDebug() << "reusing last frame visdata for leaf " << leafnum << " cluster " << clusternum;
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "looking up pvs for clusternum " << clusternum;
|
||||
|
||||
auto it = m_decompressedVis.find(clusternum);
|
||||
if (it == m_decompressedVis.end()) {
|
||||
qDebug() << "no visdata, must be in void";
|
||||
|
||||
m_lastLeaf = clusternum;
|
||||
setFaceVisibilityToAllVisible();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Q_assert(it != m_decompressedVis.end());
|
||||
|
||||
const auto &pvs = it->second;
|
||||
qDebug() << "found bitvec of size " << pvs.size();
|
||||
|
||||
// check leaf visibility
|
||||
|
||||
auto leaf_sees = [&](const mleaf_t *b) -> bool {
|
||||
if (b->cluster < 0)
|
||||
return true;
|
||||
|
||||
return !!(pvs[b->cluster >> 3] & (1 << (b->cluster & 7)));
|
||||
};
|
||||
|
||||
const int face_visibility_width = m_bsp->dfaces.size();
|
||||
|
||||
std::vector<uint8_t> face_flags;
|
||||
face_flags.resize(face_visibility_width, 0);
|
||||
|
||||
// check all leafs
|
||||
// FIXME: only world?
|
||||
|
||||
for (auto &leaf : bsp.dleafs) {
|
||||
if (leaf_sees(&leaf)) {
|
||||
for (int ms = 0; ms < leaf.nummarksurfaces; ++ms) {
|
||||
int fnum = bsp.dleaffaces[leaf.firstmarksurface + ms];
|
||||
face_flags[fnum] = 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setFaceVisibilityArray(face_flags.data());
|
||||
|
||||
m_lastLeaf = clusternum;
|
||||
}
|
||||
|
||||
bool GLView::shouldLiveUpdate() const
|
||||
{
|
||||
if (m_keysPressed)
|
||||
|
|
@ -357,6 +468,7 @@ void GLView::initializeGL()
|
|||
m_program_mvp_location = m_program->uniformLocation("MVP");
|
||||
m_program_texture_sampler_location = m_program->uniformLocation("texture_sampler");
|
||||
m_program_lightmap_sampler_location = m_program->uniformLocation("lightmap_sampler");
|
||||
m_program_face_visibility_sampler_location = m_program->uniformLocation("face_visibility_sampler");
|
||||
m_program_opacity_location = m_program->uniformLocation("opacity");
|
||||
m_program_alpha_test_location = m_program->uniformLocation("alpha_test");
|
||||
m_program_lightmap_only_location = m_program->uniformLocation("lightmap_only");
|
||||
|
|
@ -371,6 +483,7 @@ void GLView::initializeGL()
|
|||
m_skybox_program_eye_direction_location = m_skybox_program->uniformLocation("eye_origin");
|
||||
m_skybox_program_texture_sampler_location = m_skybox_program->uniformLocation("texture_sampler");
|
||||
m_skybox_program_lightmap_sampler_location = m_skybox_program->uniformLocation("lightmap_sampler");
|
||||
m_skybox_program_face_visibility_sampler_location = m_skybox_program->uniformLocation("face_visibility_sampler");
|
||||
m_skybox_program_opacity_location = m_skybox_program->uniformLocation("opacity");
|
||||
m_skybox_program_lightmap_only_location = m_skybox_program->uniformLocation("lightmap_only");
|
||||
m_skybox_program_fullbright_location = m_skybox_program->uniformLocation("fullbright");
|
||||
|
|
@ -381,6 +494,8 @@ void GLView::initializeGL()
|
|||
|
||||
m_program_wireframe->bind();
|
||||
m_program_wireframe_mvp_location = m_program_wireframe->uniformLocation("MVP");
|
||||
m_program_wireframe_face_visibility_sampler_location =
|
||||
m_program_wireframe->uniformLocation("face_visibility_sampler");
|
||||
m_program_wireframe->release();
|
||||
|
||||
m_program_simple->bind();
|
||||
|
|
@ -415,6 +530,9 @@ void GLView::paintGL()
|
|||
applyMouseMotion();
|
||||
applyFlyMovement(duration_seconds);
|
||||
|
||||
// update vis culling if needed
|
||||
updateFaceVisibility();
|
||||
|
||||
// draw
|
||||
glClearColor(0.1, 0.1, 0.1, 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
|
@ -433,6 +551,7 @@ void GLView::paintGL()
|
|||
m_program->setUniformValue(m_program_mvp_location, MVP);
|
||||
m_program->setUniformValue(m_program_texture_sampler_location, 0 /* texture unit */);
|
||||
m_program->setUniformValue(m_program_lightmap_sampler_location, 1 /* texture unit */);
|
||||
m_program->setUniformValue(m_program_face_visibility_sampler_location, 2 /* texture unit */);
|
||||
m_program->setUniformValue(m_program_opacity_location, 1.0f);
|
||||
m_program->setUniformValue(m_program_alpha_test_location, false);
|
||||
m_program->setUniformValue(m_program_lightmap_only_location, m_lighmapOnly);
|
||||
|
|
@ -445,6 +564,7 @@ void GLView::paintGL()
|
|||
m_skybox_program->setUniformValue(m_skybox_program_eye_direction_location, m_cameraOrigin);
|
||||
m_skybox_program->setUniformValue(m_skybox_program_texture_sampler_location, 0 /* texture unit */);
|
||||
m_skybox_program->setUniformValue(m_skybox_program_lightmap_sampler_location, 1 /* texture unit */);
|
||||
m_skybox_program->setUniformValue(m_skybox_program_face_visibility_sampler_location, 2 /* texture unit */);
|
||||
m_skybox_program->setUniformValue(m_skybox_program_opacity_location, 1.0f);
|
||||
m_skybox_program->setUniformValue(m_skybox_program_lightmap_only_location, m_lighmapOnly);
|
||||
m_skybox_program->setUniformValue(m_skybox_program_fullbright_location, m_fullbright);
|
||||
|
|
@ -469,6 +589,9 @@ void GLView::paintGL()
|
|||
|
||||
draw.texture->bind(0 /* texture unit */);
|
||||
lightmap_texture->bind(1 /* texture unit */);
|
||||
if (face_visibility_texture) {
|
||||
face_visibility_texture->bind(2 /* texture unit */);
|
||||
}
|
||||
|
||||
QOpenGLVertexArrayObject::Binder vaoBinder(&m_vao);
|
||||
|
||||
|
|
@ -498,6 +621,9 @@ void GLView::paintGL()
|
|||
|
||||
draw.texture->bind(0 /* texture unit */);
|
||||
lightmap_texture->bind(1 /* texture unit */);
|
||||
if (face_visibility_texture) {
|
||||
face_visibility_texture->bind(2 /* texture unit */);
|
||||
}
|
||||
|
||||
if (active_program == m_program) {
|
||||
m_program->setUniformValue(m_program_opacity_location, draw.key.opacity);
|
||||
|
|
@ -520,6 +646,12 @@ void GLView::paintGL()
|
|||
if (m_showTris || m_showTrisSeeThrough) {
|
||||
m_program_wireframe->bind();
|
||||
m_program_wireframe->setUniformValue(m_program_wireframe_mvp_location, MVP);
|
||||
m_program_wireframe->setUniformValue(
|
||||
m_program_wireframe_face_visibility_sampler_location, 2 /* texture unit */);
|
||||
|
||||
if (face_visibility_texture) {
|
||||
face_visibility_texture->bind(2 /* texture unit */);
|
||||
}
|
||||
|
||||
if (m_showTrisSeeThrough)
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
|
@ -705,10 +837,55 @@ void GLView::takeScreenshot(QString destPath, int w, int h)
|
|||
update();
|
||||
}
|
||||
|
||||
void GLView::setFaceVisibilityArray(uint8_t *data)
|
||||
{
|
||||
// one byte per face
|
||||
int face_visibility_width = m_bsp->dfaces.size();
|
||||
|
||||
face_visibility_texture.reset();
|
||||
|
||||
face_visibility_texture = std::make_shared<QOpenGLTexture>(QOpenGLTexture::Target1D);
|
||||
face_visibility_texture->setSize(face_visibility_width);
|
||||
face_visibility_texture->setFormat(QOpenGLTexture::R8U);
|
||||
face_visibility_texture->setMagnificationFilter(QOpenGLTexture::Nearest);
|
||||
face_visibility_texture->setMinificationFilter(QOpenGLTexture::Nearest);
|
||||
face_visibility_texture->allocateStorage();
|
||||
|
||||
face_visibility_texture->setData(
|
||||
0, QOpenGLTexture::Red_Integer, QOpenGLTexture::UInt8, reinterpret_cast<const void *>(data));
|
||||
|
||||
logging::print("uploaded {} bytes face visibility texture", face_visibility_width);
|
||||
}
|
||||
|
||||
void GLView::setFaceVisibilityToAllVisible()
|
||||
{
|
||||
// one byte per face
|
||||
int face_visibility_width = m_bsp->dfaces.size();
|
||||
|
||||
uint8_t *data = new uint8_t[face_visibility_width];
|
||||
for (int x = 0; x < face_visibility_width; ++x) {
|
||||
data[x] = 16;
|
||||
}
|
||||
|
||||
setFaceVisibilityArray(data);
|
||||
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
void GLView::renderBSP(const QString &file, const mbsp_t &bsp, const bspxentries_t &bspx,
|
||||
const std::vector<entdict_t> &entities, const full_atlas_t &lightmap, const settings::common_settings &settings,
|
||||
bool use_bspx_normals)
|
||||
{
|
||||
// copy the bsp for later use (FIXME: just store a pointer to MainWindow's?)
|
||||
m_bsp = bsp;
|
||||
if (bsp.dvis.bits.empty()) {
|
||||
logging::print("no visdata\n");
|
||||
m_decompressedVis.clear();
|
||||
} else {
|
||||
logging::print("decompressing visdata...\n");
|
||||
m_decompressedVis = DecompressAllVis(&bsp, true);
|
||||
}
|
||||
|
||||
img::load_textures(&bsp, settings);
|
||||
|
||||
std::optional<bspxfacenormals> facenormals;
|
||||
|
|
@ -723,6 +900,7 @@ void GLView::renderBSP(const QString &file, const mbsp_t &bsp, const bspxentries
|
|||
// clear old data
|
||||
placeholder_texture.reset();
|
||||
lightmap_texture.reset();
|
||||
face_visibility_texture.reset();
|
||||
m_drawcalls.clear();
|
||||
m_vbo.bind();
|
||||
m_vbo.allocate(0);
|
||||
|
|
@ -736,6 +914,7 @@ void GLView::renderBSP(const QString &file, const mbsp_t &bsp, const bspxentries
|
|||
m_portalIndexBuffer.allocate(0);
|
||||
num_leak_points = 0;
|
||||
num_portal_indices = 0;
|
||||
m_lastLeaf = -1;
|
||||
|
||||
int32_t highest_depth = 0;
|
||||
|
||||
|
|
@ -795,6 +974,11 @@ void GLView::renderBSP(const QString &file, const mbsp_t &bsp, const bspxentries
|
|||
delete[] data;
|
||||
}
|
||||
|
||||
// upload face visibility
|
||||
if (!bsp.dfaces.empty()) {
|
||||
setFaceVisibilityToAllVisible();
|
||||
}
|
||||
|
||||
struct face_payload
|
||||
{
|
||||
const mface_t *face;
|
||||
|
|
@ -983,6 +1167,7 @@ void GLView::renderBSP(const QString &file, const mbsp_t &bsp, const bspxentries
|
|||
qvec3f normal;
|
||||
qvec3f flat_color;
|
||||
uint32_t styles;
|
||||
int32_t face_index;
|
||||
};
|
||||
std::vector<vertex_t> verts;
|
||||
std::vector<uint32_t> indexBuffer;
|
||||
|
|
@ -1047,7 +1232,8 @@ void GLView::renderBSP(const QString &file, const mbsp_t &bsp, const bspxentries
|
|||
.normal = vertex_normal,
|
||||
.flat_color = flat_color,
|
||||
.styles = (uint32_t)(f->styles[0]) | (uint32_t)(f->styles[1] << 8) |
|
||||
(uint32_t)(f->styles[2] << 16) | (uint32_t)(f->styles[3] << 24)});
|
||||
(uint32_t)(f->styles[2] << 16) | (uint32_t)(f->styles[3] << 24),
|
||||
.face_index = fnum});
|
||||
}
|
||||
|
||||
// output the vertex indices for this face
|
||||
|
|
@ -1123,6 +1309,10 @@ void GLView::renderBSP(const QString &file, const mbsp_t &bsp, const bspxentries
|
|||
glEnableVertexAttribArray(5 /* attrib */);
|
||||
glVertexAttribIPointer(
|
||||
5 /* attrib */, 1, GL_UNSIGNED_INT, sizeof(vertex_t), (void *)offsetof(vertex_t, styles));
|
||||
|
||||
// face indices
|
||||
glEnableVertexAttribArray(6 /* attrib */);
|
||||
glVertexAttribIPointer(6 /* attrib */, 1, GL_INT, sizeof(vertex_t), (void *)offsetof(vertex_t, face_index));
|
||||
}
|
||||
|
||||
// initialize style values
|
||||
|
|
|
|||
|
|
@ -56,6 +56,9 @@ class GLView : public QOpenGLWidget, protected QOpenGLFunctions_3_3_Core
|
|||
Q_OBJECT
|
||||
|
||||
private:
|
||||
std::optional<mbsp_t> m_bsp;
|
||||
std::unordered_map<int, std::vector<uint8_t>> m_decompressedVis;
|
||||
|
||||
uint32_t m_keysPressed;
|
||||
std::optional<time_point> m_lastFrame;
|
||||
std::optional<QPoint> m_lastMouseDownPos;
|
||||
|
|
@ -64,6 +67,12 @@ private:
|
|||
*/
|
||||
float m_moveSpeed;
|
||||
|
||||
// vis culling stuff
|
||||
/**
|
||||
* -1 indicates solid leaf or no visdata (render all)
|
||||
*/
|
||||
int m_lastLeaf = -1;
|
||||
|
||||
// camera stuff
|
||||
float m_displayAspect;
|
||||
QVector3D m_cameraOrigin;
|
||||
|
|
@ -113,6 +122,14 @@ private:
|
|||
|
||||
std::shared_ptr<QOpenGLTexture> placeholder_texture;
|
||||
std::shared_ptr<QOpenGLTexture> lightmap_texture;
|
||||
/**
|
||||
* 1D texture, one uint8 per face.
|
||||
*
|
||||
* 0 = render normally
|
||||
* 1 = skip face
|
||||
*/
|
||||
std::shared_ptr<QOpenGLTexture> face_visibility_texture;
|
||||
|
||||
struct drawcall_t
|
||||
{
|
||||
material_key key;
|
||||
|
|
@ -128,10 +145,11 @@ private:
|
|||
QOpenGLShaderProgram *m_program_wireframe = nullptr;
|
||||
QOpenGLShaderProgram *m_program_simple = nullptr;
|
||||
|
||||
// uniform locations
|
||||
// uniform locations (default program)
|
||||
int m_program_mvp_location = 0;
|
||||
int m_program_texture_sampler_location = 0;
|
||||
int m_program_lightmap_sampler_location = 0;
|
||||
int m_program_face_visibility_sampler_location = 0;
|
||||
int m_program_opacity_location = 0;
|
||||
int m_program_alpha_test_location = 0;
|
||||
int m_program_lightmap_only_location = 0;
|
||||
|
|
@ -140,11 +158,12 @@ private:
|
|||
int m_program_drawflat_location = 0;
|
||||
int m_program_style_scalars_location = 0;
|
||||
|
||||
// uniform locations
|
||||
// uniform locations (skybox program)
|
||||
int m_skybox_program_mvp_location = 0;
|
||||
int m_skybox_program_eye_direction_location = 0;
|
||||
int m_skybox_program_texture_sampler_location = 0;
|
||||
int m_skybox_program_lightmap_sampler_location = 0;
|
||||
int m_skybox_program_face_visibility_sampler_location = 0;
|
||||
int m_skybox_program_opacity_location = 0;
|
||||
int m_skybox_program_lightmap_only_location = 0;
|
||||
int m_skybox_program_fullbright_location = 0;
|
||||
|
|
@ -154,8 +173,9 @@ private:
|
|||
|
||||
// uniform locations (wireframe program)
|
||||
int m_program_wireframe_mvp_location = 0;
|
||||
int m_program_wireframe_face_visibility_sampler_location = 0;
|
||||
|
||||
// uniform locations
|
||||
// uniform locations (simple program)
|
||||
int m_program_simple_mvp_location = 0;
|
||||
int m_program_simple_color_location = 0;
|
||||
|
||||
|
|
@ -163,6 +183,11 @@ public:
|
|||
GLView(QWidget *parent = nullptr);
|
||||
~GLView();
|
||||
|
||||
private:
|
||||
void setFaceVisibilityArray(uint8_t *data);
|
||||
void setFaceVisibilityToAllVisible();
|
||||
|
||||
public:
|
||||
void renderBSP(const QString &file, const mbsp_t &bsp, const bspxentries_t &bspx,
|
||||
const std::vector<entdict_t> &entities, const full_atlas_t &lightmap, const settings::common_settings &settings,
|
||||
bool use_bspx_normals);
|
||||
|
|
@ -189,6 +214,7 @@ protected:
|
|||
void resizeGL(int width, int height) override;
|
||||
|
||||
private:
|
||||
void updateFaceVisibility();
|
||||
bool shouldLiveUpdate() const;
|
||||
void handleLoggedMessage(const QOpenGLDebugMessage &debugMessage);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue