Skip to content

Commit

Permalink
Merge pull request #85621 from daustria/opengl-compatibility-wireframe
Browse files Browse the repository at this point in the history
Add wireframe for compatibility mode
  • Loading branch information
YuriSizov committed Dec 8, 2023
2 parents b0339b6 + bae6f86 commit c2151bb
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 8 deletions.
34 changes: 28 additions & 6 deletions drivers/gles3/rasterizer_scene_gles3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2916,6 +2916,15 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
prev_index_array_gl = 0;
}

bool use_wireframe = false;
if (p_params->force_wireframe) {
GLuint wireframe_index_array_gl = mesh_storage->mesh_surface_get_index_buffer_wireframe(mesh_surface);
if (wireframe_index_array_gl) {
index_array_gl = wireframe_index_array_gl;
use_wireframe = true;
}
}

bool use_index_buffer = index_array_gl != 0;
if (prev_index_array_gl != index_array_gl) {
if (index_array_gl != 0) {
Expand Down Expand Up @@ -3166,6 +3175,11 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
count = mesh_storage->mesh_surface_get_vertices_drawn_count(mesh_surface);
}

if (use_wireframe) {
// In this case we are using index count, and we need double the indices for the wireframe mesh.
count = count * 2;
}

if constexpr (p_pass_mode != PASS_MODE_DEPTH) {
// Don't count draw calls during depth pre-pass to match the RD renderers.
if (p_render_data->render_info) {
Expand Down Expand Up @@ -3220,17 +3234,25 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
glVertexAttribI4ui(15, default_color, default_color, default_custom, default_custom);
}

if (use_index_buffer) {
glDrawElementsInstanced(primitive_gl, count, mesh_storage->mesh_surface_get_index_type(mesh_surface), 0, inst->instance_count);
if (use_wireframe) {
glDrawElementsInstanced(GL_LINES, count, GL_UNSIGNED_INT, 0, inst->instance_count);
} else {
glDrawArraysInstanced(primitive_gl, 0, count, inst->instance_count);
if (use_index_buffer) {
glDrawElementsInstanced(primitive_gl, count, mesh_storage->mesh_surface_get_index_type(mesh_surface), 0, inst->instance_count);
} else {
glDrawArraysInstanced(primitive_gl, 0, count, inst->instance_count);
}
}
} else {
// Using regular Mesh.
if (use_index_buffer) {
glDrawElements(primitive_gl, count, mesh_storage->mesh_surface_get_index_type(mesh_surface), 0);
if (use_wireframe) {
glDrawElements(GL_LINES, count, GL_UNSIGNED_INT, 0);
} else {
glDrawArrays(primitive_gl, 0, count);
if (use_index_buffer) {
glDrawElements(primitive_gl, count, mesh_storage->mesh_surface_get_index_type(mesh_surface), 0);
} else {
glDrawArrays(primitive_gl, 0, count);
}
}
}

Expand Down
3 changes: 1 addition & 2 deletions drivers/gles3/storage/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,7 @@ class Config {
int64_t max_renderable_lights = 0;
int64_t max_lights_per_object = 0;

// TODO implement wireframe in OpenGL
// bool generate_wireframes;
bool generate_wireframes = false;

HashSet<String> extensions;

Expand Down
69 changes: 69 additions & 0 deletions drivers/gles3/storage/mesh_storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#ifdef GLES3_ENABLED

#include "mesh_storage.h"
#include "config.h"
#include "material_storage.h"
#include "utilities.h"

Expand Down Expand Up @@ -285,6 +286,69 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)

ERR_FAIL_COND_MSG(!new_surface.index_count && !new_surface.vertex_count, "Meshes must contain a vertex array, an index array, or both");

if (GLES3::Config::get_singleton()->generate_wireframes && s->primitive == RS::PRIMITIVE_TRIANGLES) {
// Generate wireframes. This is mostly used by the editor.
s->wireframe = memnew(Mesh::Surface::Wireframe);
Vector<uint32_t> wf_indices;
uint32_t &wf_index_count = s->wireframe->index_count;
uint32_t *wr = nullptr;

if (new_surface.format & RS::ARRAY_FORMAT_INDEX) {
wf_index_count = s->index_count * 2;
wf_indices.resize(wf_index_count);

Vector<uint8_t> ir = new_surface.index_data;
wr = wf_indices.ptrw();

if (new_surface.vertex_count < (1 << 16)) {
// Read 16 bit indices.
const uint16_t *src_idx = (const uint16_t *)ir.ptr();
for (uint32_t i = 0; i + 5 < wf_index_count; i += 6) {
// We use GL_LINES instead of GL_TRIANGLES for drawing these primitives later,
// so we need double the indices for each triangle.
wr[i + 0] = src_idx[i / 2];
wr[i + 1] = src_idx[i / 2 + 1];
wr[i + 2] = src_idx[i / 2 + 1];
wr[i + 3] = src_idx[i / 2 + 2];
wr[i + 4] = src_idx[i / 2 + 2];
wr[i + 5] = src_idx[i / 2];
}

} else {
// Read 32 bit indices.
const uint32_t *src_idx = (const uint32_t *)ir.ptr();
for (uint32_t i = 0; i + 5 < wf_index_count; i += 6) {
wr[i + 0] = src_idx[i / 2];
wr[i + 1] = src_idx[i / 2 + 1];
wr[i + 2] = src_idx[i / 2 + 1];
wr[i + 3] = src_idx[i / 2 + 2];
wr[i + 4] = src_idx[i / 2 + 2];
wr[i + 5] = src_idx[i / 2];
}
}
} else {
// Not using indices.
wf_index_count = s->vertex_count * 2;
wf_indices.resize(wf_index_count);
wr = wf_indices.ptrw();

for (uint32_t i = 0; i + 5 < wf_index_count; i += 6) {
wr[i + 0] = i / 2;
wr[i + 1] = i / 2 + 1;
wr[i + 2] = i / 2 + 1;
wr[i + 3] = i / 2 + 2;
wr[i + 4] = i / 2 + 2;
wr[i + 5] = i / 2;
}
}

s->wireframe->index_buffer_size = wf_index_count * sizeof(uint32_t);
glGenBuffers(1, &s->wireframe->index_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s->wireframe->index_buffer);
GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ELEMENT_ARRAY_BUFFER, s->wireframe->index_buffer, s->wireframe->index_buffer_size, wr, GL_STATIC_DRAW, "Mesh wireframe index buffer");
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); // unbind
}

s->aabb = new_surface.aabb;
s->bone_aabbs = new_surface.bone_aabbs; //only really useful for returning them.

Expand Down Expand Up @@ -712,6 +776,11 @@ void MeshStorage::mesh_clear(RID p_mesh) {
memfree(s.versions); //reallocs, so free with memfree.
}

if (s.wireframe) {
GLES3::Utilities::get_singleton()->buffer_free_data(s.wireframe->index_buffer);
memdelete(s.wireframe);
}

if (s.lod_count) {
for (uint32_t j = 0; j < s.lod_count; j++) {
if (s.lods[j].index_buffer != 0) {
Expand Down
18 changes: 18 additions & 0 deletions drivers/gles3/storage/mesh_storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,14 @@ struct Mesh {
uint32_t index_count = 0;
uint32_t index_buffer_size = 0;

struct Wireframe {
GLuint index_buffer = 0;
uint32_t index_count = 0;
uint32_t index_buffer_size = 0;
};

Wireframe *wireframe = nullptr;

struct LOD {
float edge_length = 0.0;
uint32_t index_count = 0;
Expand Down Expand Up @@ -376,6 +384,16 @@ class MeshStorage : public RendererMeshStorage {
}
}

_FORCE_INLINE_ GLuint mesh_surface_get_index_buffer_wireframe(void *p_surface) const {
Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);

if (s->wireframe) {
return s->wireframe->index_buffer;
}

return 0;
}

_FORCE_INLINE_ GLenum mesh_surface_get_index_type(void *p_surface) const {
Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);

Expand Down
2 changes: 2 additions & 0 deletions drivers/gles3/storage/utilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,8 @@ void Utilities::update_dirty_resources() {
}

void Utilities::set_debug_generate_wireframes(bool p_generate) {
Config *config = Config::get_singleton();
config->generate_wireframes = p_generate;
}

bool Utilities::has_os_feature(const String &p_feature) const {
Expand Down

0 comments on commit c2151bb

Please sign in to comment.