Skip to content

Commit

Permalink
initial support for volumetric geometry
Browse files Browse the repository at this point in the history
  • Loading branch information
DmitriySalnikov committed Nov 17, 2023
1 parent 725c92f commit 11888ca
Show file tree
Hide file tree
Showing 17 changed files with 419 additions and 130 deletions.
1 change: 1 addition & 0 deletions examples_dd3d/DebugDrawDemoScene.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ func _on_Button_pressed() -> void:
process_priority = 1
script = ExtResource("1")
custom_font = ExtResource("2_aedbq")
draw_array_of_boxes = true
start_culling_distance = 55.0
text_groups_position = 2
text_groups_default_font_size = 15
Expand Down
60 changes: 44 additions & 16 deletions lib_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,13 +138,21 @@ def get_library_object(env, arguments=None, gen_help=None):


def generate_sources_for_resources(env, src_out):
files = [
"images/icon_3d_32.png"
# Array of (path, is_text)
editor_files = [
("images/icon_3d_32.png", False),
]
generate_resources_cpp_h_files(files, "editor_resources.gen", src_out if "editor" in env["target"] else [])
generate_resources_cpp_h_files(editor_files, "DD3DEditorResources", "editor_resources.gen", src_out if "editor" in env["target"] else [])

shared_files = [
("src/resources/extendable_meshes.gdshader", True),
("src/resources/basic_unshaded.gdshader", True),
("src/resources/billboard_unshaded.gdshader", True),
]
generate_resources_cpp_h_files(shared_files, "DD3DResources", "shared_resources.gen", src_out)


def generate_resources_cpp_h_files(input_files, output_no_ext, src_out):
def generate_resources_cpp_h_files(input_files, namespace, output_no_ext, src_out):
gen_dir = "gen/"
out_dir = src_folder + "/" + gen_dir
Path(out_dir).mkdir(parents=True, exist_ok=True)
Expand All @@ -157,20 +165,40 @@ def generate_resources_cpp_h_files(input_files, output_no_ext, src_out):
with open(out_dir + cpp_name, "w+") as cpp_file, open(out_dir + h_name, "w+") as h_file:
h_file.write("#pragma once\n\n")
h_file.write("#include <array>\n\n")
h_file.write("namespace DD3DEditorResources {\n")
h_file.write(f"namespace {namespace} {{\n")

cpp_file.write(f"#include \"{h_name}\"\n\n")
cpp_file.write("namespace DD3DEditorResources {\n")

for input_file in input_files:
file_name_escaped = input_file.replace(".", "_").replace("/", "_").replace("\\", "_").replace(":", "_")
with open(input_file, "rb") as input_file:
binary_data = input_file.read()

cpp_array = ", ".join([f"{byte}" for byte in binary_data])
cpp_file.write(f"\tconst std::array<unsigned char, {len(binary_data)}> {file_name_escaped} = {{ {cpp_array} }};\n")

h_file.write(f"\textern const std::array<unsigned char, {len(binary_data)}> {file_name_escaped};\n")
cpp_file.write(f"namespace {namespace} {{\n")

for input_file_touple in input_files:
is_text = input_file_touple[1]
input_file_path = input_file_touple[0]
file_name_escaped = input_file_path.replace(".", "_").replace("/", "_").replace("\\", "_").replace(":", "_")

if is_text:
try:
with open(input_file_path, "r") as file:
text_data = file.read()
except UnicodeDecodeError:
try:
with open(input_file_path, "r", encoding="utf-8") as file:
text_data = file.read()
except UnicodeDecodeError as e:
print("Skipping file due to 'UnicodeDecodeError' exception: " +
(input_file_path).resolve().as_posix() + "\nException: " + str(e))
continue

cpp_file.write(f"\tconst char *{file_name_escaped} = R\"({text_data})\";\n\n")

h_file.write(f"\textern const char *{file_name_escaped};\n")
else:
with open(input_file_touple[0], "rb") as input_file:
binary_data = input_file.read()

cpp_array = ", ".join([f"{byte}" for byte in binary_data])
cpp_file.write(f"\tconst std::array<unsigned char, {len(binary_data)}> {file_name_escaped} = {{ {cpp_array} }};\n\n")

h_file.write(f"\textern const std::array<unsigned char, {len(binary_data)}> {file_name_escaped};\n")

h_file.write("}\n")
cpp_file.write("}\n")
56 changes: 55 additions & 1 deletion src/3d/debug_draw_3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
#include "config_3d.h"
#include "debug_draw_manager.h"
#include "debug_geometry_container.h"
#include "gen/shared_resources.gen.h"
#include "geometry_generators.h"
#include "stats_3d.h"
#include "utils/utils.h"

GODOT_WARNING_DISABLE()
#include <godot_cpp/classes/camera3d.hpp>
#include <godot_cpp/classes/standard_material3d.hpp>
GODOT_WARNING_RESTORE()

#include <limits.h>
Expand Down Expand Up @@ -91,6 +91,8 @@ void DebugDraw3D::init(DebugDrawManager *root) {
root_node = root;
set_config(nullptr);

_load_materials();

#ifndef DISABLE_DEBUG_RENDERING
dgc = std::make_unique<DebugGeometryContainer>(this);
#endif
Expand All @@ -101,6 +103,15 @@ DebugDraw3D::~DebugDraw3D() {

#ifndef DISABLE_DEBUG_RENDERING
dgc.reset();

shader_unshaded_mat.unref();
shader_unshaded_code.unref();

shader_billboard_mat.unref();
shader_billboard_code.unref();

shader_extendable_mat.unref();
shader_extendable_code.unref();
#endif

root_node = nullptr;
Expand All @@ -113,6 +124,25 @@ void DebugDraw3D::process(double delta) {
#endif
}

void DebugDraw3D::_load_materials() {
#ifndef DISABLE_DEBUG_RENDERING
shader_unshaded_code.instantiate();
shader_unshaded_code->set_code(DD3DResources::src_resources_basic_unshaded_gdshader);
shader_unshaded_mat.instantiate();
shader_unshaded_mat->set_shader(shader_unshaded_code);

shader_extendable_code.instantiate();
shader_extendable_code->set_code(DD3DResources::src_resources_extendable_meshes_gdshader);
shader_extendable_mat.instantiate();
shader_extendable_mat->set_shader(shader_extendable_code);

shader_billboard_code.instantiate();
shader_billboard_code->set_code(DD3DResources::src_resources_billboard_unshaded_gdshader);
shader_billboard_mat.instantiate();
shader_billboard_mat->set_shader(shader_billboard_code);
#endif
}

void DebugDraw3D::_set_base_world_node(Node *_world_base) {
#ifndef DISABLE_DEBUG_RENDERING
dgc->set_world(_world_base);
Expand All @@ -137,6 +167,30 @@ std::vector<SubViewport *> DebugDraw3D::get_custom_editor_viewports() {
return custom_editor_viewports;
}

Ref<ShaderMaterial> DebugDraw3D::get_basic_unshaded_material() {
#ifndef DISABLE_DEBUG_RENDERING
return shader_unshaded_mat;
#else
return Ref<ShaderMaterial>();
#endif
}

Ref<ShaderMaterial> DebugDraw3D::get_billboard_unshaded_material() {
#ifndef DISABLE_DEBUG_RENDERING
return shader_billboard_mat;
#else
return Ref<ShaderMaterial>();
#endif
}

Ref<ShaderMaterial> DebugDraw3D::get_extendable_material() {
#ifndef DISABLE_DEBUG_RENDERING
return shader_extendable_mat;
#else
return Ref<ShaderMaterial>();
#endif
}

void DebugDraw3D::set_empty_color(const Color &_col) {
}

Expand Down
20 changes: 19 additions & 1 deletion src/3d/debug_draw_3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

GODOT_WARNING_DISABLE()
#include <godot_cpp/classes/ref_counted.hpp>
#include <godot_cpp/classes/shader.hpp>
#include <godot_cpp/classes/shader_material.hpp>
#include <godot_cpp/classes/sub_viewport.hpp>
GODOT_WARNING_RESTORE()

Expand All @@ -21,17 +23,29 @@ class DebugDraw3D : public Object {
GDCLASS(DebugDraw3D, Object)

friend DebugDrawManager;
static DebugDraw3D *singleton;

private:
static DebugDraw3D *singleton;

std::vector<SubViewport *> custom_editor_viewports;
DebugDrawManager *root_node = nullptr;

#ifndef DISABLE_DEBUG_RENDERING
// Meshes
std::unique_ptr<DebugGeometryContainer> dgc;

// Default materials and shaders
Ref<ShaderMaterial> shader_unshaded_mat;
Ref<Shader> shader_unshaded_code;

Ref<ShaderMaterial> shader_billboard_mat;
Ref<Shader> shader_billboard_code;

Ref<ShaderMaterial> shader_extendable_mat;
Ref<Shader> shader_extendable_code;
#endif

void _load_materials();
void _set_base_world_node(Node *world_base);
inline bool _is_enabled_override() const;

Expand Down Expand Up @@ -65,6 +79,10 @@ class DebugDraw3D : public Object {
void set_custom_editor_viewport(std::vector<SubViewport *> _viewports);
std::vector<SubViewport *> get_custom_editor_viewports();

Ref<ShaderMaterial> get_basic_unshaded_material();
Ref<ShaderMaterial> get_billboard_unshaded_material();
Ref<ShaderMaterial> get_extendable_material();

#pragma region Exposed Parameters
void set_empty_color(const Color &_col);
Color get_empty_color() const;
Expand Down
99 changes: 59 additions & 40 deletions src/3d/debug_geometry_container.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,7 @@ DebugGeometryContainer::DebugGeometryContainer(class DebugDraw3D *root) {
rs->instance_geometry_set_flag(_immediate_instance, RenderingServer::INSTANCE_FLAG_USE_DYNAMIC_GI, false);
rs->instance_geometry_set_flag(_immediate_instance, RenderingServer::INSTANCE_FLAG_USE_BAKED_LIGHT, false);

Ref<StandardMaterial3D> mat;
mat.instantiate();
mat->set_shading_mode(BaseMaterial3D::SHADING_MODE_UNSHADED);
mat->set_flag(StandardMaterial3D::Flags::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);

Ref<ShaderMaterial> mat = owner->get_basic_unshaded_material();
rs->instance_geometry_set_material_override(_immediate_instance, mat->get_rid());

immediate_mesh_storage.instance = _immediate_instance;
Expand All @@ -42,14 +38,51 @@ DebugGeometryContainer::DebugGeometryContainer(class DebugDraw3D *root) {

// Create node with material and MultiMesh. Add to tree. Create array of instances
{
CreateMMI(InstanceType::CUBES, NAMEOF(mmi_cubes), CreateMesh(Mesh::PrimitiveType::PRIMITIVE_LINES, GeometryGenerator::CubeVertices, GeometryGenerator::CubeIndices));
CreateMMI(InstanceType::CUBES_CENTERED, NAMEOF(mmi_cubes_centered), CreateMesh(Mesh::PrimitiveType::PRIMITIVE_LINES, GeometryGenerator::CenteredCubeVertices, GeometryGenerator::CubeIndices));
CreateMMI(InstanceType::ARROWHEADS, NAMEOF(mmi_arrowheads), CreateMesh(Mesh::PrimitiveType::PRIMITIVE_LINES, GeometryGenerator::ArrowheadVertices, GeometryGenerator::ArrowheadIndices));
CreateMMI(InstanceType::BILLBOARD_SQUARES, NAMEOF(mmi_billboard_squares), CreateMesh(Mesh::PrimitiveType::PRIMITIVE_TRIANGLES, GeometryGenerator::CenteredSquareVertices, GeometryGenerator::SquareIndices));
CreateMMI(InstanceType::POSITIONS, NAMEOF(mmi_positions), CreateMesh(Mesh::PrimitiveType::PRIMITIVE_LINES, GeometryGenerator::PositionVertices, GeometryGenerator::PositionIndices));
CreateMMI(InstanceType::SPHERES, NAMEOF(mmi_spheres), CreateMesh(Mesh::PrimitiveType::PRIMITIVE_LINES, GeometryGenerator::CreateSphereLines(8, 8, 0.5f, Vector3_ZERO)));
CreateMMI(InstanceType::SPHERES_HD, NAMEOF(mmi_spheres_hd), CreateMesh(Mesh::PrimitiveType::PRIMITIVE_LINES, GeometryGenerator::CreateSphereLines(16, 16, 0.5f, Vector3_ZERO)));
CreateMMI(InstanceType::CYLINDERS, NAMEOF(mmi_cylinders), CreateMesh(Mesh::PrimitiveType::PRIMITIVE_LINES, GeometryGenerator::CreateCylinderLines(52, 1, 1, Vector3_ZERO, 4)));
auto array_mesh_cube = GeometryGenerator::CreateMesh(Mesh::PrimitiveType::PRIMITIVE_LINES, GeometryGenerator::CubeVertices, GeometryGenerator::CubeIndices);
CreateMMI(InstanceType::CUBE_VOLUMETRIC, UsingShaderType::Wireframe, NAMEOF(mmi_cubes), array_mesh_cube);

auto array_mesh_cube_center = GeometryGenerator::CreateMesh(Mesh::PrimitiveType::PRIMITIVE_LINES, GeometryGenerator::CenteredCubeVertices, GeometryGenerator::CubeIndices);
// CreateMMI(InstanceType::CUBES_CENTERED, UsingShaderType::Wireframe, NAMEOF(mmi_cubes_centered), array_mesh_cube_center);

auto array_mesh_arrow_head = GeometryGenerator::CreateMesh(Mesh::PrimitiveType::PRIMITIVE_LINES, GeometryGenerator::ArrowheadVertices, GeometryGenerator::ArrowheadIndices);
//CreateMMI(InstanceType::ARROWHEADS, UsingShaderType::Wireframe, NAMEOF(mmi_arrowheads), array_mesh_arrow_head);

auto array_mesh_billboard = GeometryGenerator::CreateMesh(Mesh::PrimitiveType::PRIMITIVE_TRIANGLES, GeometryGenerator::CenteredSquareVertices, GeometryGenerator::SquareIndices);
CreateMMI(InstanceType::BILLBOARD_SQUARES, UsingShaderType::Billboard, NAMEOF(mmi_billboard_squares), array_mesh_billboard);

auto array_mesh_pos = GeometryGenerator::CreateMesh(Mesh::PrimitiveType::PRIMITIVE_LINES, GeometryGenerator::PositionVertices, GeometryGenerator::PositionIndices);
//CreateMMI(InstanceType::POSITIONS, UsingShaderType::Wireframe, NAMEOF(mmi_positions), array_mesh_pos);

auto array_mesh_sphere = GeometryGenerator::CreateMesh(Mesh::PrimitiveType::PRIMITIVE_LINES, GeometryGenerator::CreateSphereLines(8, 8, 0.5f, Vector3_ZERO));
//CreateMMI(InstanceType::SPHERES, UsingShaderType::Wireframe, NAMEOF(mmi_spheres), array_mesh_sphere);

auto array_mesh_sphere_hd = GeometryGenerator::CreateMesh(Mesh::PrimitiveType::PRIMITIVE_LINES, GeometryGenerator::CreateSphereLines(16, 16, 0.5f, Vector3_ZERO));
//CreateMMI(InstanceType::SPHERES_HD, UsingShaderType::Wireframe, NAMEOF(mmi_spheres_hd), array_mesh_sphere_hd);

auto array_mesh_cylinder = GeometryGenerator::CreateMesh(Mesh::PrimitiveType::PRIMITIVE_LINES, GeometryGenerator::CreateCylinderLines(52, 1, 1, Vector3_ZERO, 4));
//CreateMMI(InstanceType::CYLINDERS, UsingShaderType::Wireframe, NAMEOF(mmi_cylinders), array_mesh_cylinder);


auto array_mesh_cube_volumetric = GeometryGenerator::ConvertWireframeToVolumetric(array_mesh_cube);
CreateMMI(InstanceType::CUBES, UsingShaderType::Expandable, NAMEOF(TEST_CUBE_VOLUMETRIC), array_mesh_cube_volumetric);

auto array_mesh_cube_centered_volumetric = GeometryGenerator::ConvertWireframeToVolumetric(array_mesh_cube_center);
CreateMMI(InstanceType::CUBES_CENTERED, UsingShaderType::Expandable, NAMEOF(TEST_CUBE_VOLUMETRIC), array_mesh_cube_centered_volumetric);

auto array_mesh_sphere_volumetric = GeometryGenerator::ConvertWireframeToVolumetric(array_mesh_sphere);
CreateMMI(InstanceType::SPHERES, UsingShaderType::Expandable, NAMEOF(TEST_CUBE_VOLUMETRIC), array_mesh_sphere_volumetric);

auto array_mesh_arrow_head_volumetric = GeometryGenerator::ConvertWireframeToVolumetric(array_mesh_arrow_head);
CreateMMI(InstanceType::ARROWHEADS, UsingShaderType::Expandable, NAMEOF(TEST_CUBE_VOLUMETRIC), array_mesh_arrow_head_volumetric);

auto array_mesh_pos_volumetric = GeometryGenerator::ConvertWireframeToVolumetric(array_mesh_pos);
CreateMMI(InstanceType::POSITIONS, UsingShaderType::Expandable, NAMEOF(TEST_CUBE_VOLUMETRIC), array_mesh_pos_volumetric);

auto array_mesh_sphere_hd_volumetric = GeometryGenerator::ConvertWireframeToVolumetric(array_mesh_sphere_hd);
CreateMMI(InstanceType::SPHERES_HD, UsingShaderType::Expandable, NAMEOF(TEST_CUBE_VOLUMETRIC), array_mesh_sphere_hd_volumetric);

auto array_mesh_cylinder_volumetric = GeometryGenerator::ConvertWireframeToVolumetric(array_mesh_cylinder);
CreateMMI(InstanceType::CYLINDERS, UsingShaderType::Expandable, NAMEOF(TEST_CUBE_VOLUMETRIC), array_mesh_cylinder_volumetric);

set_render_layer_mask(1);
}
Expand All @@ -62,7 +95,7 @@ DebugGeometryContainer::~DebugGeometryContainer() {
geometry_pool.clear_pool();
}

void DebugGeometryContainer::CreateMMI(InstanceType type, const String &name, Ref<ArrayMesh> mesh) {
void DebugGeometryContainer::CreateMMI(InstanceType type, UsingShaderType shader, const String &name, Ref<ArrayMesh> mesh) {
RenderingServer *rs = RS();

RID mmi = rs->instance_create();
Expand All @@ -79,17 +112,20 @@ void DebugGeometryContainer::CreateMMI(InstanceType type, const String &name, Re

rs->instance_set_base(mmi, new_mm->get_rid());

Ref<StandardMaterial3D> new_mat;
new_mat.instantiate();
new_mat->set_shading_mode(BaseMaterial3D::SHADING_MODE_UNSHADED);
new_mat->set_flag(StandardMaterial3D::Flags::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);

if (type == InstanceType::BILLBOARD_SQUARES) {
new_mat->set_billboard_mode(StandardMaterial3D::BillboardMode::BILLBOARD_ENABLED);
new_mat->set_flag(StandardMaterial3D::Flags::FLAG_BILLBOARD_KEEP_SCALE, true);
Ref<ShaderMaterial> mat;
switch (shader) {
case UsingShaderType::Wireframe:
mat = owner->get_basic_unshaded_material();
break;
case UsingShaderType::Billboard:
mat = owner->get_billboard_unshaded_material();
break;
case UsingShaderType::Expandable:
mat = owner->get_extendable_material();
break;
}

mesh->surface_set_material(0, new_mat);
mesh->surface_set_material(0, mat);

rs->instance_geometry_set_cast_shadows_setting(mmi, RenderingServer::SHADOW_CASTING_SETTING_OFF);
rs->instance_geometry_set_flag(mmi, RenderingServer::INSTANCE_FLAG_USE_DYNAMIC_GI, false);
Expand All @@ -99,23 +135,6 @@ void DebugGeometryContainer::CreateMMI(InstanceType type, const String &name, Re
multi_mesh_storage[type].mesh = new_mm;
}

Ref<ArrayMesh> DebugGeometryContainer::CreateMesh(Mesh::PrimitiveType type, const PackedVector3Array &vertices, const PackedInt32Array &indices, const PackedColorArray &colors) {
Ref<ArrayMesh> mesh;
mesh.instantiate();
Array a;
a.resize((int)ArrayMesh::ArrayType::ARRAY_MAX);

a[(int)ArrayMesh::ArrayType::ARRAY_VERTEX] = vertices;
if (indices.size())
a[(int)ArrayMesh::ArrayType::ARRAY_INDEX] = indices;
if (colors.size())
a[(int)ArrayMesh::ArrayType::ARRAY_COLOR] = colors;

mesh->add_surface_from_arrays(type, a);

return mesh;
}

void DebugGeometryContainer::set_world(Node *new_world) {
scene_world_node = new_world;
RenderingServer *rs = RS();
Expand Down
Loading

0 comments on commit 11888ca

Please sign in to comment.