Merge pull request #44468 from reduz/implement-lod
Implement automatic LOD (Level of Detail)
This commit is contained in:
commit
7ad29ed64e
38 changed files with 513 additions and 109 deletions
|
@ -190,9 +190,9 @@ Vector3 AABB::get_support(const Vector3 &p_normal) const {
|
|||
Vector3 ofs = position + half_extents;
|
||||
|
||||
return Vector3(
|
||||
(p_normal.x > 0) ? -half_extents.x : half_extents.x,
|
||||
(p_normal.y > 0) ? -half_extents.y : half_extents.y,
|
||||
(p_normal.z > 0) ? -half_extents.z : half_extents.z) +
|
||||
(p_normal.x > 0) ? half_extents.x : -half_extents.x,
|
||||
(p_normal.y > 0) ? half_extents.y : -half_extents.y,
|
||||
(p_normal.z > 0) ? half_extents.z : -half_extents.z) +
|
||||
ofs;
|
||||
}
|
||||
|
||||
|
|
|
@ -655,6 +655,17 @@ real_t CameraMatrix::get_fov() const {
|
|||
}
|
||||
}
|
||||
|
||||
float CameraMatrix::get_lod_multiplier() const {
|
||||
if (is_orthogonal()) {
|
||||
return get_viewport_half_extents().x;
|
||||
} else {
|
||||
float zn = get_z_near();
|
||||
float width = get_viewport_half_extents().x * 2.0;
|
||||
return 1.0 / (zn / width);
|
||||
}
|
||||
|
||||
//usage is lod_size / (lod_distance * multiplier) < threshold
|
||||
}
|
||||
void CameraMatrix::make_scale(const Vector3 &p_scale) {
|
||||
set_identity();
|
||||
matrix[0][0] = p_scale.x;
|
||||
|
|
|
@ -108,6 +108,8 @@ struct CameraMatrix {
|
|||
return !(*this == p_cam);
|
||||
}
|
||||
|
||||
float get_lod_multiplier() const;
|
||||
|
||||
CameraMatrix();
|
||||
CameraMatrix(const Transform &p_transform);
|
||||
~CameraMatrix();
|
||||
|
|
|
@ -525,6 +525,9 @@ void EditorNode::_notification(int p_what) {
|
|||
scene_root->set_sdf_oversize(sdf_oversize);
|
||||
Viewport::SDFScale sdf_scale = Viewport::SDFScale(int(GLOBAL_GET("rendering/quality/2d_sdf/scale")));
|
||||
scene_root->set_sdf_scale(sdf_scale);
|
||||
|
||||
float lod_threshold = GLOBAL_GET("rendering/quality/mesh_lod/threshold_pixels");
|
||||
scene_root->set_lod_threshold(lod_threshold);
|
||||
}
|
||||
|
||||
ResourceImporterTexture::get_singleton()->update_imports();
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "scene/resources/ray_shape_3d.h"
|
||||
#include "scene/resources/resource_format_text.h"
|
||||
#include "scene/resources/sphere_shape_3d.h"
|
||||
#include "scene/resources/surface_tool.h"
|
||||
#include "scene/resources/world_margin_shape_3d.h"
|
||||
|
||||
uint32_t EditorSceneImporter::get_import_flags() const {
|
||||
|
@ -217,6 +218,59 @@ Ref<Material> EditorSceneImporterMesh::get_surface_material(int p_surface) const
|
|||
return surfaces[p_surface].material;
|
||||
}
|
||||
|
||||
void EditorSceneImporterMesh::generate_lods() {
|
||||
if (!SurfaceTool::simplify_func) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < surfaces.size(); i++) {
|
||||
if (surfaces[i].primitive != Mesh::PRIMITIVE_TRIANGLES) {
|
||||
continue;
|
||||
}
|
||||
|
||||
surfaces.write[i].lods.clear();
|
||||
Vector<Vector3> vertices = surfaces[i].arrays[RS::ARRAY_VERTEX];
|
||||
Vector<int> indices = surfaces[i].arrays[RS::ARRAY_INDEX];
|
||||
if (indices.size() == 0) {
|
||||
continue; //no lods if no indices
|
||||
}
|
||||
uint32_t vertex_count = vertices.size();
|
||||
const Vector3 *vertices_ptr = vertices.ptr();
|
||||
AABB aabb;
|
||||
{
|
||||
for (uint32_t j = 0; j < vertex_count; j++) {
|
||||
if (j == 0) {
|
||||
aabb.position = vertices_ptr[j];
|
||||
} else {
|
||||
aabb.expand_to(vertices_ptr[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float longest_axis_size = aabb.get_longest_axis_size();
|
||||
|
||||
int min_indices = 10;
|
||||
int index_target = indices.size() / 2;
|
||||
print_line("total: " + itos(indices.size()));
|
||||
while (index_target > min_indices) {
|
||||
float error;
|
||||
Vector<int> new_indices;
|
||||
new_indices.resize(indices.size());
|
||||
size_t new_len = SurfaceTool::simplify_func((unsigned int *)new_indices.ptrw(), (const unsigned int *)indices.ptr(), indices.size(), (const float *)vertices_ptr, vertex_count, sizeof(Vector3), index_target, 1e20, &error);
|
||||
print_line("shoot for " + itos(index_target) + ", got " + itos(new_len) + " distance " + rtos(error));
|
||||
if ((int)new_len > (index_target * 120 / 100)) {
|
||||
break; // 20 percent tolerance
|
||||
}
|
||||
new_indices.resize(new_len);
|
||||
Surface::LOD lod;
|
||||
lod.distance = error * longest_axis_size;
|
||||
lod.indices = new_indices;
|
||||
surfaces.write[i].lods.push_back(lod);
|
||||
index_target /= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool EditorSceneImporterMesh::has_mesh() const {
|
||||
return mesh.is_valid();
|
||||
}
|
||||
|
@ -1422,9 +1476,9 @@ void ResourceImporterScene::get_import_options(List<ImportOption> *r_options, in
|
|||
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "materials/location", PROPERTY_HINT_ENUM, "Node,Mesh"), (meshes_out || materials_out) ? 1 : 0));
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "materials/storage", PROPERTY_HINT_ENUM, "Built-In,Files (.material),Files (.tres)", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), materials_out ? 1 : 0));
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "materials/keep_on_reimport"), materials_out));
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "meshes/compress"), true));
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "meshes/ensure_tangents"), true));
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "meshes/storage", PROPERTY_HINT_ENUM, "Built-In,Files (.mesh),Files (.tres)"), meshes_out ? 1 : 0));
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "meshes/generate_lods"), true));
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "meshes/light_baking", PROPERTY_HINT_ENUM, "Disabled,Enable,Gen Lightmaps", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 0));
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "meshes/lightmap_texel_size", PROPERTY_HINT_RANGE, "0.001,100,0.001"), 0.1));
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "skins/use_named_skins"), true));
|
||||
|
@ -1517,7 +1571,7 @@ Ref<Animation> ResourceImporterScene::import_animation_from_other_importer(Edito
|
|||
return importer->import_animation(p_path, p_flags, p_bake_fps);
|
||||
}
|
||||
|
||||
void ResourceImporterScene::_generate_meshes(Node *p_node) {
|
||||
void ResourceImporterScene::_generate_meshes(Node *p_node, bool p_generate_lods) {
|
||||
EditorSceneImporterMeshNode *src_mesh = Object::cast_to<EditorSceneImporterMeshNode>(p_node);
|
||||
if (src_mesh != nullptr) {
|
||||
//is mesh
|
||||
|
@ -1528,6 +1582,9 @@ void ResourceImporterScene::_generate_meshes(Node *p_node) {
|
|||
|
||||
Ref<ArrayMesh> mesh;
|
||||
if (!src_mesh->get_mesh()->has_mesh()) {
|
||||
if (p_generate_lods) {
|
||||
src_mesh->get_mesh()->generate_lods();
|
||||
}
|
||||
//do mesh processing
|
||||
}
|
||||
mesh = src_mesh->get_mesh()->get_mesh();
|
||||
|
@ -1542,7 +1599,7 @@ void ResourceImporterScene::_generate_meshes(Node *p_node) {
|
|||
}
|
||||
|
||||
for (int i = 0; i < p_node->get_child_count(); i++) {
|
||||
_generate_meshes(p_node->get_child(i));
|
||||
_generate_meshes(p_node->get_child(i), p_generate_lods);
|
||||
}
|
||||
}
|
||||
Error ResourceImporterScene::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) {
|
||||
|
@ -1583,10 +1640,6 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
|
|||
import_flags |= EditorSceneImporter::IMPORT_ANIMATION;
|
||||
}
|
||||
|
||||
if (int(p_options["meshes/compress"])) {
|
||||
import_flags |= EditorSceneImporter::IMPORT_USE_COMPRESSION;
|
||||
}
|
||||
|
||||
if (bool(p_options["meshes/ensure_tangents"])) {
|
||||
import_flags |= EditorSceneImporter::IMPORT_GENERATE_TANGENT_ARRAYS;
|
||||
}
|
||||
|
@ -1641,7 +1694,9 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
|
|||
scene->set_name(p_save_path.get_file().get_basename());
|
||||
}
|
||||
|
||||
_generate_meshes(scene);
|
||||
bool gen_lods = bool(p_options["meshes/generate_lods"]);
|
||||
|
||||
_generate_meshes(scene, gen_lods);
|
||||
|
||||
err = OK;
|
||||
|
||||
|
|
|
@ -144,6 +144,8 @@ public:
|
|||
float get_surface_lod_size(int p_surface, int p_lod) const;
|
||||
Ref<Material> get_surface_material(int p_surface) const;
|
||||
|
||||
void generate_lods();
|
||||
|
||||
bool has_mesh() const;
|
||||
Ref<ArrayMesh> get_mesh();
|
||||
void clear();
|
||||
|
@ -205,7 +207,7 @@ class ResourceImporterScene : public ResourceImporter {
|
|||
};
|
||||
|
||||
void _replace_owner(Node *p_node, Node *p_scene, Node *p_new_owner);
|
||||
void _generate_meshes(Node *p_node);
|
||||
void _generate_meshes(Node *p_node, bool p_generate_lods);
|
||||
|
||||
public:
|
||||
static ResourceImporterScene *get_singleton() { return singleton; }
|
||||
|
|
|
@ -3017,7 +3017,8 @@ void Node3DEditorViewport::_menu_option(int p_option) {
|
|||
case VIEW_DISPLAY_DEBUG_DECAL_ATLAS:
|
||||
case VIEW_DISPLAY_DEBUG_SDFGI:
|
||||
case VIEW_DISPLAY_DEBUG_SDFGI_PROBES:
|
||||
case VIEW_DISPLAY_DEBUG_GI_BUFFER: {
|
||||
case VIEW_DISPLAY_DEBUG_GI_BUFFER:
|
||||
case VIEW_DISPLAY_DEBUG_DISABLE_LOD: {
|
||||
static const int display_options[] = {
|
||||
VIEW_DISPLAY_NORMAL,
|
||||
VIEW_DISPLAY_WIREFRAME,
|
||||
|
@ -3034,6 +3035,7 @@ void Node3DEditorViewport::_menu_option(int p_option) {
|
|||
VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE,
|
||||
VIEW_DISPLAY_DEBUG_SSAO,
|
||||
VIEW_DISPLAY_DEBUG_GI_BUFFER,
|
||||
VIEW_DISPLAY_DEBUG_DISABLE_LOD,
|
||||
VIEW_DISPLAY_DEBUG_PSSM_SPLITS,
|
||||
VIEW_DISPLAY_DEBUG_DECAL_ATLAS,
|
||||
VIEW_DISPLAY_DEBUG_SDFGI,
|
||||
|
@ -3056,6 +3058,7 @@ void Node3DEditorViewport::_menu_option(int p_option) {
|
|||
Viewport::DEBUG_DRAW_SCENE_LUMINANCE,
|
||||
Viewport::DEBUG_DRAW_SSAO,
|
||||
Viewport::DEBUG_DRAW_GI_BUFFER,
|
||||
Viewport::DEBUG_DRAW_DISABLE_LOD,
|
||||
Viewport::DEBUG_DRAW_PSSM_SPLITS,
|
||||
Viewport::DEBUG_DRAW_DECAL_ATLAS,
|
||||
Viewport::DEBUG_DRAW_SDFGI,
|
||||
|
@ -3959,6 +3962,8 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, Edito
|
|||
display_submenu->add_radio_check_item(TTR("SSAO"), VIEW_DISPLAY_DEBUG_SSAO);
|
||||
display_submenu->add_separator();
|
||||
display_submenu->add_radio_check_item(TTR("GI Buffer"), VIEW_DISPLAY_DEBUG_GI_BUFFER);
|
||||
display_submenu->add_separator();
|
||||
display_submenu->add_radio_check_item(TTR("Disable LOD"), VIEW_DISPLAY_DEBUG_DISABLE_LOD);
|
||||
display_submenu->set_name("display_advanced");
|
||||
view_menu->get_popup()->add_submenu_item(TTR("Display Advanced..."), "display_advanced", VIEW_DISPLAY_ADVANCED);
|
||||
view_menu->get_popup()->add_separator();
|
||||
|
|
|
@ -212,6 +212,7 @@ class Node3DEditorViewport : public Control {
|
|||
VIEW_DISPLAY_DEBUG_SDFGI,
|
||||
VIEW_DISPLAY_DEBUG_SDFGI_PROBES,
|
||||
VIEW_DISPLAY_DEBUG_GI_BUFFER,
|
||||
VIEW_DISPLAY_DEBUG_DISABLE_LOD,
|
||||
VIEW_LOCK_ROTATION,
|
||||
VIEW_CINEMATIC_PREVIEW,
|
||||
VIEW_AUTO_ORTHOGONAL,
|
||||
|
|
|
@ -76,6 +76,15 @@ float ReflectionProbe::get_max_distance() const {
|
|||
return max_distance;
|
||||
}
|
||||
|
||||
void ReflectionProbe::set_lod_threshold(float p_pixels) {
|
||||
lod_threshold = p_pixels;
|
||||
RS::get_singleton()->reflection_probe_set_lod_threshold(probe, p_pixels);
|
||||
}
|
||||
|
||||
float ReflectionProbe::get_lod_threshold() const {
|
||||
return lod_threshold;
|
||||
}
|
||||
|
||||
void ReflectionProbe::set_extents(const Vector3 &p_extents) {
|
||||
extents = p_extents;
|
||||
|
||||
|
@ -199,6 +208,9 @@ void ReflectionProbe::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_max_distance", "max_distance"), &ReflectionProbe::set_max_distance);
|
||||
ClassDB::bind_method(D_METHOD("get_max_distance"), &ReflectionProbe::get_max_distance);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_lod_threshold", "ratio"), &ReflectionProbe::set_lod_threshold);
|
||||
ClassDB::bind_method(D_METHOD("get_lod_threshold"), &ReflectionProbe::get_lod_threshold);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_extents", "extents"), &ReflectionProbe::set_extents);
|
||||
ClassDB::bind_method(D_METHOD("get_extents"), &ReflectionProbe::get_extents);
|
||||
|
||||
|
@ -229,6 +241,7 @@ void ReflectionProbe::_bind_methods() {
|
|||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior"), "set_as_interior", "is_set_as_interior");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enable_shadows"), "set_enable_shadows", "are_shadows_enabled");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lod_threshold", PROPERTY_HINT_RANGE, "0,1024,0.1"), "set_lod_threshold", "get_lod_threshold");
|
||||
|
||||
ADD_GROUP("Ambient", "ambient_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "ambient_mode", PROPERTY_HINT_ENUM, "Disabled,Environment,ConstantColor"), "set_ambient_mode", "get_ambient_mode");
|
||||
|
@ -256,6 +269,7 @@ ReflectionProbe::ReflectionProbe() {
|
|||
enable_shadows = false;
|
||||
cull_mask = (1 << 20) - 1;
|
||||
update_mode = UPDATE_ONCE;
|
||||
lod_threshold = 1.0;
|
||||
|
||||
probe = RenderingServer::get_singleton()->reflection_probe_create();
|
||||
RS::get_singleton()->instance_set_base(get_instance(), probe);
|
||||
|
|
|
@ -63,6 +63,7 @@ private:
|
|||
AmbientMode ambient_mode;
|
||||
Color ambient_color;
|
||||
float ambient_color_energy;
|
||||
float lod_threshold;
|
||||
|
||||
uint32_t cull_mask;
|
||||
UpdateMode update_mode;
|
||||
|
@ -90,6 +91,9 @@ public:
|
|||
void set_max_distance(float p_distance);
|
||||
float get_max_distance() const;
|
||||
|
||||
void set_lod_threshold(float p_pixels);
|
||||
float get_lod_threshold() const;
|
||||
|
||||
void set_extents(const Vector3 &p_extents);
|
||||
Vector3 get_extents() const;
|
||||
|
||||
|
|
|
@ -278,6 +278,16 @@ float GeometryInstance3D::get_extra_cull_margin() const {
|
|||
return extra_cull_margin;
|
||||
}
|
||||
|
||||
void GeometryInstance3D::set_lod_bias(float p_bias) {
|
||||
ERR_FAIL_COND(p_bias < 0.0);
|
||||
lod_bias = p_bias;
|
||||
RS::get_singleton()->instance_geometry_set_lod_bias(get_instance(), lod_bias);
|
||||
}
|
||||
|
||||
float GeometryInstance3D::get_lod_bias() const {
|
||||
return lod_bias;
|
||||
}
|
||||
|
||||
void GeometryInstance3D::set_shader_instance_uniform(const StringName &p_uniform, const Variant &p_value) {
|
||||
if (p_value.get_type() == Variant::NIL) {
|
||||
Variant def_value = RS::get_singleton()->instance_geometry_get_shader_parameter_default_value(get_instance(), p_uniform);
|
||||
|
@ -361,6 +371,9 @@ void GeometryInstance3D::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_gi_mode", "mode"), &GeometryInstance3D::set_gi_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_gi_mode"), &GeometryInstance3D::get_gi_mode);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_lod_bias", "p_bias"), &GeometryInstance3D::set_lod_bias);
|
||||
ClassDB::bind_method(D_METHOD("get_lod_bias"), &GeometryInstance3D::get_lod_bias);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_custom_aabb", "aabb"), &GeometryInstance3D::set_custom_aabb);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_aabb"), &GeometryInstance3D::get_aabb);
|
||||
|
@ -369,6 +382,7 @@ void GeometryInstance3D::_bind_methods() {
|
|||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material_override", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,StandardMaterial3D", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DEFERRED_SET_RESOURCE), "set_material_override", "get_material_override");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "cast_shadow", PROPERTY_HINT_ENUM, "Off,On,Double-Sided,Shadows Only"), "set_cast_shadows_setting", "get_cast_shadows_setting");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "extra_cull_margin", PROPERTY_HINT_RANGE, "0,16384,0.01"), "set_extra_cull_margin", "get_extra_cull_margin");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lod_bias", PROPERTY_HINT_RANGE, "0.001,128,0.001"), "set_lod_bias", "get_lod_bias");
|
||||
ADD_GROUP("Global Illumination", "gi_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "gi_mode", PROPERTY_HINT_ENUM, "Disabled,Baked,Dynamic"), "set_gi_mode", "get_gi_mode");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "gi_lightmap_scale", PROPERTY_HINT_ENUM, "1x,2x,4x,8x"), "set_lightmap_scale", "get_lightmap_scale");
|
||||
|
@ -403,6 +417,8 @@ GeometryInstance3D::GeometryInstance3D() {
|
|||
lod_min_hysteresis = 0;
|
||||
lod_max_hysteresis = 0;
|
||||
|
||||
lod_bias = 1.0;
|
||||
|
||||
gi_mode = GI_MODE_DISABLED;
|
||||
lightmap_scale = LIGHTMAP_SCALE_1X;
|
||||
|
||||
|
|
|
@ -112,6 +112,8 @@ private:
|
|||
float lod_min_hysteresis;
|
||||
float lod_max_hysteresis;
|
||||
|
||||
float lod_bias;
|
||||
|
||||
mutable HashMap<StringName, Variant> instance_uniforms;
|
||||
mutable HashMap<StringName, StringName> instance_uniform_property_remap;
|
||||
|
||||
|
@ -151,6 +153,9 @@ public:
|
|||
void set_extra_cull_margin(float p_margin);
|
||||
float get_extra_cull_margin() const;
|
||||
|
||||
void set_lod_bias(float p_bias);
|
||||
float get_lod_bias() const;
|
||||
|
||||
void set_gi_mode(GIMode p_mode);
|
||||
GIMode get_gi_mode() const;
|
||||
|
||||
|
|
|
@ -1391,6 +1391,10 @@ SceneTree::SceneTree() {
|
|||
const bool use_debanding = GLOBAL_DEF("rendering/quality/screen_filters/use_debanding", false);
|
||||
root->set_use_debanding(use_debanding);
|
||||
|
||||
float lod_threshold = GLOBAL_DEF("rendering/quality/mesh_lod/threshold_pixels", 1.0);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/mesh_lod/threshold_pixels", PropertyInfo(Variant::FLOAT, "rendering/quality/mesh_lod/threshold_pixels", PROPERTY_HINT_RANGE, "0,1024,0.1"));
|
||||
root->set_lod_threshold(lod_threshold);
|
||||
|
||||
bool snap_2d_transforms = GLOBAL_DEF("rendering/quality/2d/snap_2d_transforms_to_pixel", false);
|
||||
root->set_snap_2d_transforms_to_pixel(snap_2d_transforms);
|
||||
|
||||
|
|
|
@ -3192,6 +3192,14 @@ bool Viewport::is_using_debanding() const {
|
|||
return use_debanding;
|
||||
}
|
||||
|
||||
void Viewport::set_lod_threshold(float p_pixels) {
|
||||
lod_threshold = p_pixels;
|
||||
RS::get_singleton()->viewport_set_lod_threshold(viewport, lod_threshold);
|
||||
}
|
||||
float Viewport::get_lod_threshold() const {
|
||||
return lod_threshold;
|
||||
}
|
||||
|
||||
void Viewport::set_debug_draw(DebugDraw p_debug_draw) {
|
||||
debug_draw = p_debug_draw;
|
||||
RS::get_singleton()->viewport_set_debug_draw(viewport, RS::ViewportDebugDraw(p_debug_draw));
|
||||
|
@ -3505,6 +3513,9 @@ void Viewport::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_sdf_scale", "scale"), &Viewport::set_sdf_scale);
|
||||
ClassDB::bind_method(D_METHOD("get_sdf_scale"), &Viewport::get_sdf_scale);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_lod_threshold", "pixels"), &Viewport::set_lod_threshold);
|
||||
ClassDB::bind_method(D_METHOD("get_lod_threshold"), &Viewport::get_lod_threshold);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "own_world_3d"), "set_use_own_world_3d", "is_using_own_world_3d");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "world_3d", PROPERTY_HINT_RESOURCE_TYPE, "World3D"), "set_world_3d", "get_world_3d");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "world_2d", PROPERTY_HINT_RESOURCE_TYPE, "World2D", 0), "set_world_2d", "get_world_2d");
|
||||
|
@ -3516,6 +3527,7 @@ void Viewport::_bind_methods() {
|
|||
ADD_PROPERTY(PropertyInfo(Variant::INT, "msaa", PROPERTY_HINT_ENUM, "Disabled,2x,4x,8x,16x,AndroidVR 2x,AndroidVR 4x"), "set_msaa", "get_msaa");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "screen_space_aa", PROPERTY_HINT_ENUM, "Disabled,FXAA"), "set_screen_space_aa", "get_screen_space_aa");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_debanding"), "set_use_debanding", "is_using_debanding");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lod_threshold", PROPERTY_HINT_RANGE, "0,1024,0.1"), "set_lod_threshold", "get_lod_threshold");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "debug_draw", PROPERTY_HINT_ENUM, "Disabled,Unshaded,Overdraw,Wireframe"), "set_debug_draw", "get_debug_draw");
|
||||
ADD_GROUP("Canvas Items", "canvas_item_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "canvas_item_default_texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,MipmapLinear,MipmapNearest"), "set_default_canvas_item_texture_filter", "get_default_canvas_item_texture_filter");
|
||||
|
@ -3590,6 +3602,7 @@ void Viewport::_bind_methods() {
|
|||
BIND_ENUM_CONSTANT(DEBUG_DRAW_SDFGI);
|
||||
BIND_ENUM_CONSTANT(DEBUG_DRAW_SDFGI_PROBES);
|
||||
BIND_ENUM_CONSTANT(DEBUG_DRAW_GI_BUFFER);
|
||||
BIND_ENUM_CONSTANT(DEBUG_DRAW_DISABLE_LOD);
|
||||
|
||||
BIND_ENUM_CONSTANT(DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_NEAREST);
|
||||
BIND_ENUM_CONSTANT(DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_LINEAR);
|
||||
|
@ -3652,6 +3665,8 @@ Viewport::Viewport() {
|
|||
set_shadow_atlas_quadrant_subdiv(2, SHADOW_ATLAS_QUADRANT_SUBDIV_16);
|
||||
set_shadow_atlas_quadrant_subdiv(3, SHADOW_ATLAS_QUADRANT_SUBDIV_64);
|
||||
|
||||
set_lod_threshold(lod_threshold);
|
||||
|
||||
String id = itos(get_instance_id());
|
||||
input_group = "_vp_input" + id;
|
||||
gui_input_group = "_vp_gui_input" + id;
|
||||
|
|
|
@ -142,6 +142,7 @@ public:
|
|||
DEBUG_DRAW_SDFGI,
|
||||
DEBUG_DRAW_SDFGI_PROBES,
|
||||
DEBUG_DRAW_GI_BUFFER,
|
||||
DEBUG_DRAW_DISABLE_LOD,
|
||||
};
|
||||
|
||||
enum DefaultCanvasItemTextureFilter {
|
||||
|
@ -297,6 +298,8 @@ private:
|
|||
MSAA msaa;
|
||||
ScreenSpaceAA screen_space_aa;
|
||||
bool use_debanding = false;
|
||||
float lod_threshold = 1.0;
|
||||
|
||||
Ref<ViewportTexture> default_texture;
|
||||
Set<ViewportTexture *> viewport_textures;
|
||||
|
||||
|
@ -542,6 +545,9 @@ public:
|
|||
void set_use_debanding(bool p_use_debanding);
|
||||
bool is_using_debanding() const;
|
||||
|
||||
void set_lod_threshold(float p_pixels);
|
||||
float get_lod_threshold() const;
|
||||
|
||||
Vector2 get_camera_coords(const Vector2 &p_viewport_coords) const;
|
||||
Vector2 get_camera_rect_size() const;
|
||||
|
||||
|
|
|
@ -1128,7 +1128,8 @@ Vector<int> SurfaceTool::generate_lod(float p_threshold, int p_target_index_coun
|
|||
vertices[i * 3 + 2] = vertex_array[i].vertex.z;
|
||||
}
|
||||
|
||||
uint32_t index_count = simplify_func((unsigned int *)lod.ptrw(), (unsigned int *)index_array.ptr(), index_array.size(), vertices.ptr(), vertex_array.size(), sizeof(float) * 3, p_target_index_count, p_threshold);
|
||||
float error;
|
||||
uint32_t index_count = simplify_func((unsigned int *)lod.ptrw(), (unsigned int *)index_array.ptr(), index_array.size(), vertices.ptr(), vertex_array.size(), sizeof(float) * 3, p_target_index_count, p_threshold, &error);
|
||||
ERR_FAIL_COND_V(index_count == 0, lod);
|
||||
lod.resize(index_count);
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ public:
|
|||
|
||||
typedef void (*OptimizeVertexCacheFunc)(unsigned int *destination, const unsigned int *indices, size_t index_count, size_t vertex_count);
|
||||
static OptimizeVertexCacheFunc optimize_vertex_cache_func;
|
||||
typedef size_t (*SimplifyFunc)(unsigned int *destination, const unsigned int *indices, size_t index_count, const float *vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error);
|
||||
typedef size_t (*SimplifyFunc)(unsigned int *destination, const unsigned int *indices, size_t index_count, const float *vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float *r_error);
|
||||
static SimplifyFunc simplify_func;
|
||||
|
||||
private:
|
||||
|
|
|
@ -953,7 +953,7 @@ void RendererSceneRenderForward::_fill_instances(RenderList::Element **p_element
|
|||
|
||||
/// RENDERING ///
|
||||
|
||||
void RendererSceneRenderForward::_render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, RID p_render_pass_uniform_set, bool p_force_wireframe, const Vector2 &p_uv_offset) {
|
||||
void RendererSceneRenderForward::_render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, RID p_render_pass_uniform_set, bool p_force_wireframe, const Vector2 &p_uv_offset, const Plane &p_lod_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold) {
|
||||
RD::DrawListID draw_list = p_draw_list;
|
||||
RD::FramebufferFormatID framebuffer_format = p_framebuffer_Format;
|
||||
|
||||
|
@ -996,10 +996,13 @@ void RendererSceneRenderForward::_render_list(RenderingDevice::DrawListID p_draw
|
|||
|
||||
//find primitive and vertex format
|
||||
RS::PrimitiveType primitive;
|
||||
void *mesh_surface = nullptr;
|
||||
|
||||
switch (e->instance->base_type) {
|
||||
case RS::INSTANCE_MESH: {
|
||||
primitive = storage->mesh_surface_get_primitive(e->instance->base, e->surface_index);
|
||||
mesh_surface = storage->mesh_get_surface(e->instance->base, e->surface_index);
|
||||
|
||||
primitive = storage->mesh_surface_get_primitive(mesh_surface);
|
||||
if (e->instance->skeleton.is_valid()) {
|
||||
xforms_uniform_set = storage->skeleton_get_3d_uniform_set(e->instance->skeleton, default_shader_rd, TRANSFORMS_UNIFORM_SET);
|
||||
}
|
||||
|
@ -1007,7 +1010,10 @@ void RendererSceneRenderForward::_render_list(RenderingDevice::DrawListID p_draw
|
|||
case RS::INSTANCE_MULTIMESH: {
|
||||
RID mesh = storage->multimesh_get_mesh(e->instance->base);
|
||||
ERR_CONTINUE(!mesh.is_valid()); //should be a bug
|
||||
primitive = storage->mesh_surface_get_primitive(mesh, e->surface_index);
|
||||
|
||||
mesh_surface = storage->mesh_get_surface(e->instance->base, e->surface_index);
|
||||
|
||||
primitive = storage->mesh_surface_get_primitive(mesh_surface);
|
||||
|
||||
xforms_uniform_set = storage->multimesh_get_3d_uniform_set(e->instance->base, default_shader_rd, TRANSFORMS_UNIFORM_SET);
|
||||
|
||||
|
@ -1018,7 +1024,10 @@ void RendererSceneRenderForward::_render_list(RenderingDevice::DrawListID p_draw
|
|||
case RS::INSTANCE_PARTICLES: {
|
||||
RID mesh = storage->particles_get_draw_pass_mesh(e->instance->base, e->surface_index >> 16);
|
||||
ERR_CONTINUE(!mesh.is_valid()); //should be a bug
|
||||
primitive = storage->mesh_surface_get_primitive(mesh, e->surface_index & 0xFFFF);
|
||||
|
||||
mesh_surface = storage->mesh_get_surface(e->instance->base, e->surface_index & 0xFFFF);
|
||||
|
||||
primitive = storage->mesh_surface_get_primitive(mesh_surface);
|
||||
|
||||
xforms_uniform_set = storage->particles_get_instance_buffer_uniform_set(e->instance->base, default_shader_rd, TRANSFORMS_UNIFORM_SET);
|
||||
|
||||
|
@ -1077,29 +1086,39 @@ void RendererSceneRenderForward::_render_list(RenderingDevice::DrawListID p_draw
|
|||
RID vertex_array_rd;
|
||||
RID index_array_rd;
|
||||
|
||||
switch (e->instance->base_type) {
|
||||
case RS::INSTANCE_MESH: {
|
||||
if (e->instance->mesh_instance.is_valid()) { //skeleton and blend shape
|
||||
storage->mesh_instance_surface_get_arrays_and_format(e->instance->mesh_instance, e->surface_index, pipeline->get_vertex_input_mask(), vertex_array_rd, index_array_rd, vertex_format);
|
||||
} else {
|
||||
storage->mesh_surface_get_arrays_and_format(e->instance->base, e->surface_index, pipeline->get_vertex_input_mask(), vertex_array_rd, index_array_rd, vertex_format);
|
||||
if (mesh_surface) {
|
||||
if (e->instance->mesh_instance.is_valid()) { //skeleton and blend shape
|
||||
storage->mesh_instance_surface_get_vertex_arrays_and_format(e->instance->mesh_instance, e->surface_index, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format);
|
||||
} else {
|
||||
storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format);
|
||||
}
|
||||
|
||||
if (p_screen_lod_threshold > 0.0 && storage->mesh_surface_has_lod(mesh_surface)) {
|
||||
Vector3 support_min = e->instance->transformed_aabb.get_support(-p_lod_plane.normal);
|
||||
Vector3 support_max = e->instance->transformed_aabb.get_support(p_lod_plane.normal);
|
||||
|
||||
float distance_min = p_lod_plane.distance_to(support_min);
|
||||
float distance_max = p_lod_plane.distance_to(support_max);
|
||||
|
||||
float distance = 0.0;
|
||||
|
||||
if (distance_min * distance_max < 0.0) {
|
||||
//crossing plane
|
||||
distance = 0.0;
|
||||
} else if (distance_min >= 0.0) {
|
||||
distance = distance_min;
|
||||
} else if (distance_max <= 0.0) {
|
||||
distance = -distance_max;
|
||||
}
|
||||
} break;
|
||||
case RS::INSTANCE_MULTIMESH: {
|
||||
RID mesh = storage->multimesh_get_mesh(e->instance->base);
|
||||
ERR_CONTINUE(!mesh.is_valid()); //should be a bug
|
||||
storage->mesh_surface_get_arrays_and_format(mesh, e->surface_index, pipeline->get_vertex_input_mask(), vertex_array_rd, index_array_rd, vertex_format);
|
||||
} break;
|
||||
case RS::INSTANCE_IMMEDIATE: {
|
||||
ERR_CONTINUE(true); //should be a bug
|
||||
} break;
|
||||
case RS::INSTANCE_PARTICLES: {
|
||||
RID mesh = storage->particles_get_draw_pass_mesh(e->instance->base, e->surface_index >> 16);
|
||||
ERR_CONTINUE(!mesh.is_valid()); //should be a bug
|
||||
storage->mesh_surface_get_arrays_and_format(mesh, e->surface_index & 0xFFFF, pipeline->get_vertex_input_mask(), vertex_array_rd, index_array_rd, vertex_format);
|
||||
} break;
|
||||
default: {
|
||||
ERR_CONTINUE(true); //should be a bug
|
||||
|
||||
Vector3 model_scale_vec = e->instance->transform.basis.get_scale_abs();
|
||||
|
||||
float model_scale = MAX(model_scale_vec.x, MAX(model_scale_vec.y, model_scale_vec.z));
|
||||
|
||||
index_array_rd = storage->mesh_surface_get_index_array_with_lod(mesh_surface, model_scale * e->instance->lod_bias, distance * p_lod_distance_multiplier, p_screen_lod_threshold);
|
||||
|
||||
} else {
|
||||
index_array_rd = storage->mesh_surface_get_index_array(mesh_surface);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1635,7 +1654,7 @@ void RendererSceneRenderForward::_setup_lightmaps(InstanceBase **p_lightmap_cull
|
|||
}
|
||||
}
|
||||
|
||||
void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, int p_directional_light_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color) {
|
||||
void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, int p_directional_light_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_screen_lod_threshold) {
|
||||
RenderBufferDataForward *render_buffer = nullptr;
|
||||
if (p_render_buffer.is_valid()) {
|
||||
render_buffer = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffer);
|
||||
|
@ -1654,6 +1673,13 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
|
|||
scene_state.ubo.reflection_multiplier = 1.0;
|
||||
}
|
||||
|
||||
float lod_distance_multiplier = p_cam_projection.get_lod_multiplier();
|
||||
Plane lod_camera_plane(p_cam_transform.get_origin(), -p_cam_transform.basis.get_axis(Vector3::AXIS_Z));
|
||||
|
||||
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_DISABLE_LOD) {
|
||||
p_screen_lod_threshold = 0.0;
|
||||
}
|
||||
|
||||
//scene_state.ubo.subsurface_scatter_width = subsurface_scatter_size;
|
||||
|
||||
Vector2 vp_he = p_cam_projection.get_viewport_half_extents();
|
||||
|
@ -1856,7 +1882,7 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
|
|||
|
||||
bool finish_depth = using_ssao || using_sdfgi || using_giprobe;
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(depth_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, finish_depth ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE, depth_pass_clear);
|
||||
_render_list(draw_list, RD::get_singleton()->framebuffer_get_format(depth_framebuffer), render_list.elements, render_list.element_count, false, depth_pass_mode, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME);
|
||||
_render_list(draw_list, RD::get_singleton()->framebuffer_get_format(depth_framebuffer), render_list.elements, render_list.element_count, false, depth_pass_mode, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), lod_camera_plane, lod_distance_multiplier, p_screen_lod_threshold);
|
||||
RD::get_singleton()->draw_list_end();
|
||||
|
||||
if (render_buffer && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) {
|
||||
|
@ -1904,7 +1930,7 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
|
|||
|
||||
RID framebuffer = using_separate_specular ? opaque_specular_framebuffer : opaque_framebuffer;
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, depth_pre_pass ? (continue_depth ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CONTINUE) : RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0);
|
||||
_render_list(draw_list, RD::get_singleton()->framebuffer_get_format(framebuffer), render_list.elements, render_list.element_count, false, using_separate_specular ? PASS_MODE_COLOR_SPECULAR : PASS_MODE_COLOR, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME);
|
||||
_render_list(draw_list, RD::get_singleton()->framebuffer_get_format(framebuffer), render_list.elements, render_list.element_count, false, using_separate_specular ? PASS_MODE_COLOR_SPECULAR : PASS_MODE_COLOR, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), lod_camera_plane, lod_distance_multiplier, p_screen_lod_threshold);
|
||||
RD::get_singleton()->draw_list_end();
|
||||
|
||||
if (will_continue_color && using_separate_specular) {
|
||||
|
@ -1992,7 +2018,7 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
|
|||
|
||||
{
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(alpha_framebuffer, can_continue_color ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ);
|
||||
_render_list(draw_list, RD::get_singleton()->framebuffer_get_format(alpha_framebuffer), &render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, false, PASS_MODE_COLOR, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME);
|
||||
_render_list(draw_list, RD::get_singleton()->framebuffer_get_format(alpha_framebuffer), &render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, false, PASS_MODE_COLOR, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), lod_camera_plane, lod_distance_multiplier, p_screen_lod_threshold);
|
||||
RD::get_singleton()->draw_list_end();
|
||||
}
|
||||
|
||||
|
@ -2001,7 +2027,7 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
|
|||
}
|
||||
}
|
||||
|
||||
void RendererSceneRenderForward::_render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake) {
|
||||
void RendererSceneRenderForward::_render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold) {
|
||||
RENDER_TIMESTAMP("Setup Rendering Shadow");
|
||||
|
||||
_update_render_base_uniform_set();
|
||||
|
@ -2012,6 +2038,10 @@ void RendererSceneRenderForward::_render_shadow(RID p_framebuffer, InstanceBase
|
|||
|
||||
_setup_environment(RID(), RID(), p_projection, p_transform, RID(), true, Vector2(1, 1), RID(), true, Color(), 0, p_zfar, false, p_use_pancake);
|
||||
|
||||
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_DISABLE_LOD) {
|
||||
p_screen_lod_threshold = 0.0;
|
||||
}
|
||||
|
||||
render_list.clear();
|
||||
|
||||
PassMode pass_mode = p_use_dp ? PASS_MODE_SHADOW_DP : PASS_MODE_SHADOW;
|
||||
|
@ -2029,7 +2059,7 @@ void RendererSceneRenderForward::_render_shadow(RID p_framebuffer, InstanceBase
|
|||
{
|
||||
//regular forward for now
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ);
|
||||
_render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), render_list.elements, render_list.element_count, p_use_dp_flip, pass_mode, true, rp_uniform_set);
|
||||
_render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), render_list.elements, render_list.element_count, p_use_dp_flip, pass_mode, true, rp_uniform_set, false, Vector2(), p_camera_plane, p_lod_distance_multiplier, p_screen_lod_threshold);
|
||||
RD::get_singleton()->draw_list_end();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -570,7 +570,7 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
|
|||
void _setup_lightmaps(InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, const Transform &p_cam_transform);
|
||||
|
||||
void _fill_instances(RenderList::Element **p_elements, int p_element_count, bool p_for_depth, bool p_has_sdfgi = false, bool p_has_opaque_gi = false);
|
||||
void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2());
|
||||
void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0);
|
||||
_FORCE_INLINE_ void _add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode, uint32_t p_geometry_index, bool p_using_sdfgi = false);
|
||||
_FORCE_INLINE_ void _add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, RID p_material_rid, PassMode p_pass_mode, uint32_t p_geometry_index, bool p_using_sdfgi = false);
|
||||
|
||||
|
@ -581,8 +581,8 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
|
|||
bool low_end = false;
|
||||
|
||||
protected:
|
||||
virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, int p_directional_light_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color);
|
||||
virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake);
|
||||
virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, int p_directional_light_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_lod_threshold);
|
||||
virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_lod_threshold = 0.0);
|
||||
virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region);
|
||||
virtual void _render_uv2(InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region);
|
||||
virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, InstanceBase **p_cull_result, int p_cull_count, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture);
|
||||
|
|
|
@ -3255,6 +3255,13 @@ void RendererSceneRenderRD::reflection_atlas_set_size(RID p_ref_atlas, int p_ref
|
|||
}
|
||||
}
|
||||
|
||||
int RendererSceneRenderRD::reflection_atlas_get_size(RID p_ref_atlas) const {
|
||||
ReflectionAtlas *ra = reflection_atlas_owner.getornull(p_ref_atlas);
|
||||
ERR_FAIL_COND_V(!ra, 0);
|
||||
|
||||
return ra->size;
|
||||
}
|
||||
|
||||
////////////////////////
|
||||
RID RendererSceneRenderRD::reflection_probe_instance_create(RID p_probe) {
|
||||
ReflectionProbeInstance rpi;
|
||||
|
@ -7012,7 +7019,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
|
|||
RD::get_singleton()->compute_list_end();
|
||||
}
|
||||
|
||||
void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
|
||||
void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold) {
|
||||
Color clear_color;
|
||||
if (p_render_buffers.is_valid()) {
|
||||
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
|
||||
|
@ -7069,7 +7076,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &
|
|||
_update_volumetric_fog(p_render_buffers, p_environment, p_cam_projection, p_cam_transform, p_shadow_atlas, directional_light_count, directional_shadows, positional_light_count, gi_probe_count);
|
||||
}
|
||||
|
||||
_render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_ortogonal, p_cull_result, p_cull_count, directional_light_count, p_gi_probe_cull_result, p_gi_probe_cull_count, p_lightmap_cull_result, p_lightmap_cull_count, p_environment, p_camera_effects, p_shadow_atlas, p_reflection_atlas, p_reflection_probe, p_reflection_probe_pass, clear_color);
|
||||
_render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_ortogonal, p_cull_result, p_cull_count, directional_light_count, p_gi_probe_cull_result, p_gi_probe_cull_count, p_lightmap_cull_result, p_lightmap_cull_count, p_environment, p_camera_effects, p_shadow_atlas, p_reflection_atlas, p_reflection_probe, p_reflection_probe_pass, clear_color, p_screen_lod_threshold);
|
||||
|
||||
if (p_render_buffers.is_valid()) {
|
||||
RENDER_TIMESTAMP("Tonemap");
|
||||
|
@ -7082,7 +7089,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &
|
|||
}
|
||||
}
|
||||
|
||||
void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) {
|
||||
void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold) {
|
||||
LightInstance *light_instance = light_instance_owner.getornull(p_light);
|
||||
ERR_FAIL_COND(!light_instance);
|
||||
|
||||
|
@ -7233,7 +7240,7 @@ void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p
|
|||
|
||||
if (render_cubemap) {
|
||||
//rendering to cubemap
|
||||
_render_shadow(render_fb, p_cull_result, p_cull_count, light_projection, light_transform, zfar, 0, 0, false, false, use_pancake);
|
||||
_render_shadow(render_fb, p_cull_result, p_cull_count, light_projection, light_transform, zfar, 0, 0, false, false, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_lod_threshold);
|
||||
if (finalize_cubemap) {
|
||||
//reblit
|
||||
atlas_rect.size.height /= 2;
|
||||
|
@ -7244,7 +7251,7 @@ void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p
|
|||
} else {
|
||||
//render shadow
|
||||
|
||||
_render_shadow(render_fb, p_cull_result, p_cull_count, light_projection, light_transform, zfar, bias, normal_bias, using_dual_paraboloid, using_dual_paraboloid_flip, use_pancake);
|
||||
_render_shadow(render_fb, p_cull_result, p_cull_count, light_projection, light_transform, zfar, bias, normal_bias, using_dual_paraboloid, using_dual_paraboloid_flip, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_lod_threshold);
|
||||
|
||||
//copy to atlas
|
||||
if (use_linear_depth) {
|
||||
|
|
|
@ -109,8 +109,8 @@ protected:
|
|||
void _setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment);
|
||||
void _setup_giprobes(RID p_render_buffers, const Transform &p_transform, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, uint32_t &r_gi_probes_used);
|
||||
|
||||
virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, int p_directional_light_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_color) = 0;
|
||||
virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool use_dp_flip, bool p_use_pancake) = 0;
|
||||
virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, int p_directional_light_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_color, float p_screen_lod_threshold) = 0;
|
||||
virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0) = 0;
|
||||
virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) = 0;
|
||||
virtual void _render_uv2(InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) = 0;
|
||||
virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, InstanceBase **p_cull_result, int p_cull_count, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) = 0;
|
||||
|
@ -339,7 +339,7 @@ private:
|
|||
Vector<Reflection> reflections;
|
||||
};
|
||||
|
||||
RID_Owner<ReflectionAtlas> reflection_atlas_owner;
|
||||
mutable RID_Owner<ReflectionAtlas> reflection_atlas_owner;
|
||||
|
||||
/* REFLECTION PROBE INSTANCE */
|
||||
|
||||
|
@ -1728,6 +1728,8 @@ public:
|
|||
|
||||
virtual RID reflection_atlas_create();
|
||||
virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count);
|
||||
virtual int reflection_atlas_get_size(RID p_ref_atlas) const;
|
||||
|
||||
_FORCE_INLINE_ RID reflection_atlas_get_texture(RID p_ref_atlas) {
|
||||
ReflectionAtlas *atlas = reflection_atlas_owner.getornull(p_ref_atlas);
|
||||
ERR_FAIL_COND_V(!atlas, RID());
|
||||
|
@ -1884,9 +1886,9 @@ public:
|
|||
float render_buffers_get_volumetric_fog_end(RID p_render_buffers);
|
||||
float render_buffers_get_volumetric_fog_detail_spread(RID p_render_buffers);
|
||||
|
||||
void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_shadow_atlas, RID p_camera_effects, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
|
||||
void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_shadow_atlas, RID p_camera_effects, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold);
|
||||
|
||||
void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count);
|
||||
void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_lod_threshold = 0.0);
|
||||
|
||||
void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region);
|
||||
|
||||
|
|
|
@ -5645,6 +5645,15 @@ void RendererStorageRD::reflection_probe_set_resolution(RID p_probe, int p_resol
|
|||
reflection_probe->resolution = p_resolution;
|
||||
}
|
||||
|
||||
void RendererStorageRD::reflection_probe_set_lod_threshold(RID p_probe, float p_ratio) {
|
||||
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND(!reflection_probe);
|
||||
|
||||
reflection_probe->lod_threshold = p_ratio;
|
||||
|
||||
reflection_probe->instance_dependency.instance_notify_changed(true, false);
|
||||
}
|
||||
|
||||
AABB RendererStorageRD::reflection_probe_get_aabb(RID p_probe) const {
|
||||
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND_V(!reflection_probe, AABB());
|
||||
|
@ -5698,6 +5707,13 @@ float RendererStorageRD::reflection_probe_get_origin_max_distance(RID p_probe) c
|
|||
return reflection_probe->max_distance;
|
||||
}
|
||||
|
||||
float RendererStorageRD::reflection_probe_get_lod_threshold(RID p_probe) const {
|
||||
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND_V(!reflection_probe, 0);
|
||||
|
||||
return reflection_probe->lod_threshold;
|
||||
}
|
||||
|
||||
int RendererStorageRD::reflection_probe_get_resolution(RID p_probe) const {
|
||||
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND_V(!reflection_probe, 0);
|
||||
|
|
|
@ -964,6 +964,7 @@ private:
|
|||
bool box_projection = false;
|
||||
bool enable_shadows = false;
|
||||
uint32_t cull_mask = (1 << 20) - 1;
|
||||
float lod_threshold = 0.01;
|
||||
|
||||
RendererStorage::InstanceDependency instance_dependency;
|
||||
};
|
||||
|
@ -1417,22 +1418,50 @@ public:
|
|||
return mesh->material_cache.ptr();
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ RS::PrimitiveType mesh_surface_get_primitive(RID p_mesh, uint32_t p_surface_index) {
|
||||
_FORCE_INLINE_ void *mesh_get_surface(RID p_mesh, uint32_t p_surface_index) {
|
||||
Mesh *mesh = mesh_owner.getornull(p_mesh);
|
||||
ERR_FAIL_COND_V(!mesh, RS::PRIMITIVE_MAX);
|
||||
ERR_FAIL_UNSIGNED_INDEX_V(p_surface_index, mesh->surface_count, RS::PRIMITIVE_MAX);
|
||||
ERR_FAIL_COND_V(!mesh, nullptr);
|
||||
ERR_FAIL_UNSIGNED_INDEX_V(p_surface_index, mesh->surface_count, nullptr);
|
||||
|
||||
return mesh->surfaces[p_surface_index]->primitive;
|
||||
return mesh->surfaces[p_surface_index];
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ void mesh_surface_get_arrays_and_format(RID p_mesh, uint32_t p_surface_index, uint32_t p_input_mask, RID &r_vertex_array_rd, RID &r_index_array_rd, RD::VertexFormatID &r_vertex_format) {
|
||||
Mesh *mesh = mesh_owner.getornull(p_mesh);
|
||||
ERR_FAIL_COND(!mesh);
|
||||
ERR_FAIL_UNSIGNED_INDEX(p_surface_index, mesh->surface_count);
|
||||
_FORCE_INLINE_ RS::PrimitiveType mesh_surface_get_primitive(void *p_surface) {
|
||||
Mesh::Surface *surface = reinterpret_cast<Mesh::Surface *>(p_surface);
|
||||
return surface->primitive;
|
||||
}
|
||||
|
||||
Mesh::Surface *s = mesh->surfaces[p_surface_index];
|
||||
_FORCE_INLINE_ bool mesh_surface_has_lod(void *p_surface) const {
|
||||
Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
|
||||
return s->lod_count > 0;
|
||||
}
|
||||
|
||||
r_index_array_rd = s->index_array;
|
||||
_FORCE_INLINE_ RID mesh_surface_get_index_array(void *p_surface) const {
|
||||
Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
|
||||
|
||||
return s->index_array;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ RID mesh_surface_get_index_array_with_lod(void *p_surface, float p_model_scale, float p_distance_threshold, float p_lod_threshold) const {
|
||||
Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
|
||||
|
||||
int32_t current_lod = -1;
|
||||
for (uint32_t i = 0; i < s->lod_count; i++) {
|
||||
float screen_size = s->lods[i].edge_length * p_model_scale / p_distance_threshold;
|
||||
if (screen_size > p_lod_threshold) {
|
||||
break;
|
||||
}
|
||||
current_lod = i;
|
||||
}
|
||||
if (current_lod == -1) {
|
||||
return s->index_array;
|
||||
} else {
|
||||
return s->lods[current_lod].index_array;
|
||||
}
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ void mesh_surface_get_vertex_arrays_and_format(void *p_surface, uint32_t p_input_mask, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) {
|
||||
Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
|
||||
|
||||
s->version_lock.lock();
|
||||
|
||||
|
@ -1461,7 +1490,7 @@ public:
|
|||
s->version_lock.unlock();
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ void mesh_instance_surface_get_arrays_and_format(RID p_mesh_instance, uint32_t p_surface_index, uint32_t p_input_mask, RID &r_vertex_array_rd, RID &r_index_array_rd, RD::VertexFormatID &r_vertex_format) {
|
||||
_FORCE_INLINE_ void mesh_instance_surface_get_vertex_arrays_and_format(RID p_mesh_instance, uint32_t p_surface_index, uint32_t p_input_mask, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) {
|
||||
MeshInstance *mi = mesh_instance_owner.getornull(p_mesh_instance);
|
||||
ERR_FAIL_COND(!mi);
|
||||
Mesh *mesh = mi->mesh;
|
||||
|
@ -1470,8 +1499,6 @@ public:
|
|||
MeshInstance::Surface *mis = &mi->surfaces[p_surface_index];
|
||||
Mesh::Surface *s = mesh->surfaces[p_surface_index];
|
||||
|
||||
r_index_array_rd = s->index_array;
|
||||
|
||||
s->version_lock.lock();
|
||||
|
||||
//there will never be more than, at much, 3 or 4 versions, so iterating is the fastest way
|
||||
|
@ -1780,6 +1807,7 @@ public:
|
|||
void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable);
|
||||
void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers);
|
||||
void reflection_probe_set_resolution(RID p_probe, int p_resolution);
|
||||
void reflection_probe_set_lod_threshold(RID p_probe, float p_ratio);
|
||||
|
||||
AABB reflection_probe_get_aabb(RID p_probe) const;
|
||||
RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const;
|
||||
|
@ -1787,6 +1815,8 @@ public:
|
|||
Vector3 reflection_probe_get_extents(RID p_probe) const;
|
||||
Vector3 reflection_probe_get_origin_offset(RID p_probe) const;
|
||||
float reflection_probe_get_origin_max_distance(RID p_probe) const;
|
||||
float reflection_probe_get_lod_threshold(RID p_probe) const;
|
||||
|
||||
int reflection_probe_get_resolution(RID p_probe) const;
|
||||
bool reflection_probe_renders_shadows(RID p_probe) const;
|
||||
|
||||
|
|
|
@ -88,6 +88,7 @@ public:
|
|||
virtual void instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin) = 0;
|
||||
virtual void instance_geometry_set_as_instance_lod(RID p_instance, RID p_as_lod_of_instance) = 0;
|
||||
virtual void instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index) = 0;
|
||||
virtual void instance_geometry_set_lod_bias(RID p_instance, float p_lod_bias) = 0;
|
||||
|
||||
virtual void instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value) = 0;
|
||||
virtual void instance_geometry_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const = 0;
|
||||
|
@ -187,8 +188,8 @@ public:
|
|||
virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) = 0;
|
||||
|
||||
virtual void render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) = 0;
|
||||
virtual void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas) = 0;
|
||||
virtual void render_camera(RID p_render_buffers, Ref<XRInterface> &p_interface, XRInterface::Eyes p_eye, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas) = 0;
|
||||
virtual void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, Size2 p_viewport_size, float p_lod_threshold, RID p_shadow_atlas) = 0;
|
||||
virtual void render_camera(RID p_render_buffers, Ref<XRInterface> &p_interface, XRInterface::Eyes p_eye, RID p_camera, RID p_scenario, Size2 p_viewport_size, float p_lod_threshold, RID p_shadow_atlas) = 0;
|
||||
|
||||
virtual void update() = 0;
|
||||
virtual void render_probes() = 0;
|
||||
|
|
|
@ -969,6 +969,13 @@ void RendererSceneCull::instance_geometry_set_lightmap(RID p_instance, RID p_lig
|
|||
}
|
||||
}
|
||||
|
||||
void RendererSceneCull::instance_geometry_set_lod_bias(RID p_instance, float p_lod_bias) {
|
||||
Instance *instance = instance_owner.getornull(p_instance);
|
||||
ERR_FAIL_COND(!instance);
|
||||
|
||||
instance->lod_bias = p_lod_bias;
|
||||
}
|
||||
|
||||
void RendererSceneCull::instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value) {
|
||||
Instance *instance = instance_owner.getornull(p_instance);
|
||||
ERR_FAIL_COND(!instance);
|
||||
|
@ -1325,7 +1332,7 @@ void RendererSceneCull::_update_instance_lightmap_captures(Instance *p_instance)
|
|||
}
|
||||
}
|
||||
|
||||
bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario) {
|
||||
bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario, float p_screen_lod_threshold) {
|
||||
InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data);
|
||||
|
||||
Transform light_transform = p_instance->transform;
|
||||
|
@ -1335,6 +1342,8 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
|
|||
|
||||
switch (RSG::storage->light_get_type(p_instance->base)) {
|
||||
case RS::LIGHT_DIRECTIONAL: {
|
||||
Plane camera_plane(p_cam_transform.get_origin(), -p_cam_transform.basis.get_axis(Vector3::AXIS_Z));
|
||||
|
||||
real_t max_distance = p_cam_projection.get_z_far();
|
||||
real_t shadow_max = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE);
|
||||
if (shadow_max > 0 && !p_cam_orthogonal) { //its impractical (and leads to unwanted behaviors) to set max distance in orthogonal camera
|
||||
|
@ -1703,7 +1712,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
|
|||
|
||||
RSG::storage->update_mesh_instances();
|
||||
|
||||
scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RendererSceneRender::InstanceBase **)instance_shadow_cull_result, cull_count);
|
||||
scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RendererSceneRender::InstanceBase **)instance_shadow_cull_result, cull_count, camera_plane, p_cam_projection.get_lod_multiplier(), p_screen_lod_threshold);
|
||||
}
|
||||
|
||||
} break;
|
||||
|
@ -1860,7 +1869,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
|
|||
return animated_material_found;
|
||||
}
|
||||
|
||||
void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas) {
|
||||
void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, Size2 p_viewport_size, float p_screen_lod_threshold, RID p_shadow_atlas) {
|
||||
// render to mono camera
|
||||
#ifndef _3D_DISABLED
|
||||
|
||||
|
@ -1905,12 +1914,12 @@ void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_
|
|||
|
||||
RID environment = _render_get_environment(p_camera, p_scenario);
|
||||
|
||||
_prepare_scene(camera->transform, camera_matrix, ortho, camera->vaspect, p_render_buffers, environment, camera->visible_layers, p_scenario, p_shadow_atlas, RID());
|
||||
_render_scene(p_render_buffers, camera->transform, camera_matrix, ortho, environment, camera->effects, p_scenario, p_shadow_atlas, RID(), -1);
|
||||
_prepare_scene(camera->transform, camera_matrix, ortho, camera->vaspect, p_render_buffers, environment, camera->visible_layers, p_scenario, p_shadow_atlas, RID(), p_screen_lod_threshold);
|
||||
_render_scene(p_render_buffers, camera->transform, camera_matrix, ortho, environment, camera->effects, p_scenario, p_shadow_atlas, RID(), -1, p_screen_lod_threshold);
|
||||
#endif
|
||||
}
|
||||
|
||||
void RendererSceneCull::render_camera(RID p_render_buffers, Ref<XRInterface> &p_interface, XRInterface::Eyes p_eye, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas) {
|
||||
void RendererSceneCull::render_camera(RID p_render_buffers, Ref<XRInterface> &p_interface, XRInterface::Eyes p_eye, RID p_camera, RID p_scenario, Size2 p_viewport_size, float p_screen_lod_threshold, RID p_shadow_atlas) {
|
||||
// render for AR/VR interface
|
||||
|
||||
Camera *camera = camera_owner.getornull(p_camera);
|
||||
|
@ -1984,17 +1993,17 @@ void RendererSceneCull::render_camera(RID p_render_buffers, Ref<XRInterface> &p_
|
|||
mono_transform *= apply_z_shift;
|
||||
|
||||
// now prepare our scene with our adjusted transform projection matrix
|
||||
_prepare_scene(mono_transform, combined_matrix, false, false, p_render_buffers, environment, camera->visible_layers, p_scenario, p_shadow_atlas, RID());
|
||||
_prepare_scene(mono_transform, combined_matrix, false, false, p_render_buffers, environment, camera->visible_layers, p_scenario, p_shadow_atlas, RID(), p_screen_lod_threshold);
|
||||
} else if (p_eye == XRInterface::EYE_MONO) {
|
||||
// For mono render, prepare as per usual
|
||||
_prepare_scene(cam_transform, camera_matrix, false, false, p_render_buffers, environment, camera->visible_layers, p_scenario, p_shadow_atlas, RID());
|
||||
_prepare_scene(cam_transform, camera_matrix, false, false, p_render_buffers, environment, camera->visible_layers, p_scenario, p_shadow_atlas, RID(), p_screen_lod_threshold);
|
||||
}
|
||||
|
||||
// And render our scene...
|
||||
_render_scene(p_render_buffers, cam_transform, camera_matrix, false, environment, camera->effects, p_scenario, p_shadow_atlas, RID(), -1);
|
||||
_render_scene(p_render_buffers, cam_transform, camera_matrix, false, environment, camera->effects, p_scenario, p_shadow_atlas, RID(), -1, p_screen_lod_threshold);
|
||||
};
|
||||
|
||||
void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_render_buffers, RID p_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, bool p_using_shadows) {
|
||||
void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_render_buffers, RID p_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, float p_screen_lod_threshold, bool p_using_shadows) {
|
||||
// Note, in stereo rendering:
|
||||
// - p_cam_transform will be a transform in the middle of our two eyes
|
||||
// - p_cam_projection is a wider frustrum that encompasses both eyes
|
||||
|
@ -2250,7 +2259,7 @@ void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const Ca
|
|||
for (int i = 0; i < directional_shadow_count; i++) {
|
||||
RENDER_TIMESTAMP(">Rendering Directional Light " + itos(i));
|
||||
|
||||
_light_instance_update_shadow(lights_with_shadow[i], p_cam_transform, p_cam_projection, p_cam_orthogonal, p_cam_vaspect, p_shadow_atlas, scenario);
|
||||
_light_instance_update_shadow(lights_with_shadow[i], p_cam_transform, p_cam_projection, p_cam_orthogonal, p_cam_vaspect, p_shadow_atlas, scenario, p_screen_lod_threshold);
|
||||
|
||||
RENDER_TIMESTAMP("<Rendering Directional Light " + itos(i));
|
||||
}
|
||||
|
@ -2349,7 +2358,7 @@ void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const Ca
|
|||
if (redraw) {
|
||||
//must redraw!
|
||||
RENDER_TIMESTAMP(">Rendering Light " + itos(i));
|
||||
light->shadow_dirty = _light_instance_update_shadow(ins, p_cam_transform, p_cam_projection, p_cam_orthogonal, p_cam_vaspect, p_shadow_atlas, scenario);
|
||||
light->shadow_dirty = _light_instance_update_shadow(ins, p_cam_transform, p_cam_projection, p_cam_orthogonal, p_cam_vaspect, p_shadow_atlas, scenario, p_screen_lod_threshold);
|
||||
RENDER_TIMESTAMP("<Rendering Light " + itos(i));
|
||||
}
|
||||
}
|
||||
|
@ -2447,7 +2456,7 @@ RID RendererSceneCull::_render_get_environment(RID p_camera, RID p_scenario) {
|
|||
return RID();
|
||||
}
|
||||
|
||||
void RendererSceneCull::_render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_environment, RID p_force_camera_effects, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
|
||||
void RendererSceneCull::_render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_environment, RID p_force_camera_effects, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold) {
|
||||
Scenario *scenario = scenario_owner.getornull(p_scenario);
|
||||
|
||||
RID camera_effects;
|
||||
|
@ -2459,7 +2468,7 @@ void RendererSceneCull::_render_scene(RID p_render_buffers, const Transform p_ca
|
|||
/* PROCESS GEOMETRY AND DRAW SCENE */
|
||||
|
||||
RENDER_TIMESTAMP("Render Scene ");
|
||||
scene_render->render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_orthogonal, (RendererSceneRender::InstanceBase **)instance_cull_result, instance_cull_count, light_instance_cull_result, light_cull_count + directional_light_count, reflection_probe_instance_cull_result, reflection_probe_cull_count, gi_probe_instance_cull_result, gi_probe_cull_count, decal_instance_cull_result, decal_cull_count, (RendererSceneRender::InstanceBase **)lightmap_cull_result, lightmap_cull_count, p_environment, camera_effects, p_shadow_atlas, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass);
|
||||
scene_render->render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_orthogonal, (RendererSceneRender::InstanceBase **)instance_cull_result, instance_cull_count, light_instance_cull_result, light_cull_count + directional_light_count, reflection_probe_instance_cull_result, reflection_probe_cull_count, gi_probe_instance_cull_result, gi_probe_cull_count, decal_instance_cull_result, decal_cull_count, (RendererSceneRender::InstanceBase **)lightmap_cull_result, lightmap_cull_count, p_environment, camera_effects, p_shadow_atlas, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass, p_screen_lod_threshold);
|
||||
}
|
||||
|
||||
void RendererSceneCull::render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) {
|
||||
|
@ -2474,7 +2483,7 @@ void RendererSceneCull::render_empty_scene(RID p_render_buffers, RID p_scenario,
|
|||
environment = scenario->fallback_environment;
|
||||
}
|
||||
RENDER_TIMESTAMP("Render Empty Scene ");
|
||||
scene_render->render_scene(p_render_buffers, Transform(), CameraMatrix(), true, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, environment, RID(), p_shadow_atlas, scenario->reflection_atlas, RID(), 0);
|
||||
scene_render->render_scene(p_render_buffers, Transform(), CameraMatrix(), true, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, environment, RID(), p_shadow_atlas, scenario->reflection_atlas, RID(), 0, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -2512,6 +2521,8 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int
|
|||
Vector3 extents = RSG::storage->reflection_probe_get_extents(p_instance->base);
|
||||
Vector3 origin_offset = RSG::storage->reflection_probe_get_origin_offset(p_instance->base);
|
||||
float max_distance = RSG::storage->reflection_probe_get_origin_max_distance(p_instance->base);
|
||||
float size = scene_render->reflection_atlas_get_size(scenario->reflection_atlas);
|
||||
float lod_threshold = RSG::storage->reflection_probe_get_lod_threshold(p_instance->base) / size;
|
||||
|
||||
Vector3 edge = view_normals[p_step] * extents;
|
||||
float distance = ABS(view_normals[p_step].dot(edge) - view_normals[p_step].dot(origin_offset)); //distance from origin offset to actual view distance limit
|
||||
|
@ -2535,8 +2546,8 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int
|
|||
}
|
||||
|
||||
RENDER_TIMESTAMP("Render Reflection Probe, Step " + itos(p_step));
|
||||
_prepare_scene(xform, cm, false, false, RID(), RID(), RSG::storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, shadow_atlas, reflection_probe->instance, use_shadows);
|
||||
_render_scene(RID(), xform, cm, false, RID(), RID(), p_instance->scenario->self, shadow_atlas, reflection_probe->instance, p_step);
|
||||
_prepare_scene(xform, cm, false, false, RID(), RID(), RSG::storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, shadow_atlas, reflection_probe->instance, lod_threshold, use_shadows);
|
||||
_render_scene(RID(), xform, cm, false, RID(), RID(), p_instance->scenario->self, shadow_atlas, reflection_probe->instance, p_step, lod_threshold);
|
||||
|
||||
} else {
|
||||
//do roughness postprocess step until it believes it's done
|
||||
|
|
|
@ -447,6 +447,7 @@ public:
|
|||
virtual void instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin);
|
||||
virtual void instance_geometry_set_as_instance_lod(RID p_instance, RID p_as_lod_of_instance);
|
||||
virtual void instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index);
|
||||
virtual void instance_geometry_set_lod_bias(RID p_instance, float p_lod_bias);
|
||||
|
||||
void _update_instance_shader_parameters_from_material(Map<StringName, RendererSceneRender::InstanceBase::InstanceShaderParameter> &isparams, const Map<StringName, RendererSceneRender::InstanceBase::InstanceShaderParameter> &existing_isparams, RID p_material);
|
||||
|
||||
|
@ -460,17 +461,17 @@ public:
|
|||
_FORCE_INLINE_ void _update_dirty_instance(Instance *p_instance);
|
||||
_FORCE_INLINE_ void _update_instance_lightmap_captures(Instance *p_instance);
|
||||
|
||||
_FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario);
|
||||
_FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario, float p_scren_lod_threshold);
|
||||
|
||||
RID _render_get_environment(RID p_camera, RID p_scenario);
|
||||
|
||||
bool _render_reflection_probe_step(Instance *p_instance, int p_step);
|
||||
void _prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_render_buffers, RID p_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, bool p_using_shadows = true);
|
||||
void _render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_environment, RID p_force_camera_effects, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
|
||||
void _prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_render_buffers, RID p_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, float p_screen_lod_threshold, bool p_using_shadows = true);
|
||||
void _render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_environment, RID p_force_camera_effects, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold);
|
||||
void render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas);
|
||||
|
||||
void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas);
|
||||
void render_camera(RID p_render_buffers, Ref<XRInterface> &p_interface, XRInterface::Eyes p_eye, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas);
|
||||
void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, Size2 p_viewport_size, float p_screen_lod_threshold, RID p_shadow_atlas);
|
||||
void render_camera(RID p_render_buffers, Ref<XRInterface> &p_interface, XRInterface::Eyes p_eye, RID p_camera, RID p_scenario, Size2 p_viewport_size, float p_screen_lod_threshold, RID p_shadow_atlas);
|
||||
void update_dirty_instances();
|
||||
|
||||
void render_particle_colliders();
|
||||
|
|
|
@ -139,6 +139,8 @@ public:
|
|||
|
||||
Transform transform;
|
||||
|
||||
float lod_bias;
|
||||
|
||||
int depth_layer;
|
||||
uint32_t layer_mask;
|
||||
|
||||
|
@ -195,6 +197,7 @@ public:
|
|||
lightmap_slice_index = 0;
|
||||
lightmap = nullptr;
|
||||
lightmap_cull_index = 0;
|
||||
lod_bias = 1.0;
|
||||
}
|
||||
|
||||
virtual ~InstanceBase() {
|
||||
|
@ -212,6 +215,7 @@ public:
|
|||
|
||||
virtual RID reflection_atlas_create() = 0;
|
||||
virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) = 0;
|
||||
virtual int reflection_atlas_get_size(RID p_ref_atlas) const = 0;
|
||||
|
||||
virtual RID reflection_probe_instance_create(RID p_probe) = 0;
|
||||
virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform) = 0;
|
||||
|
@ -231,9 +235,9 @@ public:
|
|||
|
||||
virtual void gi_probe_set_quality(RS::GIProbeQuality) = 0;
|
||||
|
||||
virtual void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) = 0;
|
||||
virtual void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold) = 0;
|
||||
|
||||
virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) = 0;
|
||||
virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_lod_threshold = 0.0) = 0;
|
||||
virtual void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) = 0;
|
||||
virtual void render_sdfgi(RID p_render_buffers, int p_region, InstanceBase **p_cull_result, int p_cull_count) = 0;
|
||||
virtual void render_sdfgi_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const RID **p_positional_light_cull_result, const uint32_t *p_positional_light_cull_count) = 0;
|
||||
|
|
|
@ -338,6 +338,7 @@ public:
|
|||
virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) = 0;
|
||||
virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) = 0;
|
||||
virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) = 0;
|
||||
virtual void reflection_probe_set_lod_threshold(RID p_probe, float p_ratio) = 0;
|
||||
|
||||
virtual AABB reflection_probe_get_aabb(RID p_probe) const = 0;
|
||||
virtual RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const = 0;
|
||||
|
@ -346,6 +347,7 @@ public:
|
|||
virtual Vector3 reflection_probe_get_origin_offset(RID p_probe) const = 0;
|
||||
virtual float reflection_probe_get_origin_max_distance(RID p_probe) const = 0;
|
||||
virtual bool reflection_probe_renders_shadows(RID p_probe) const = 0;
|
||||
virtual float reflection_probe_get_lod_threshold(RID p_probe) const = 0;
|
||||
|
||||
virtual void base_update_dependency(RID p_base, InstanceBaseDependency *p_instance) = 0;
|
||||
virtual void skeleton_update_dependency(RID p_base, InstanceBaseDependency *p_instance) = 0;
|
||||
|
|
|
@ -79,10 +79,11 @@ void RendererViewport::_draw_3d(Viewport *p_viewport, XRInterface::Eyes p_eye) {
|
|||
xr_interface = XRServer::get_singleton()->get_primary_interface();
|
||||
}
|
||||
|
||||
float screen_lod_threshold = p_viewport->lod_threshold / float(p_viewport->size.width);
|
||||
if (p_viewport->use_xr && xr_interface.is_valid()) {
|
||||
RSG::scene->render_camera(p_viewport->render_buffers, xr_interface, p_eye, p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
|
||||
RSG::scene->render_camera(p_viewport->render_buffers, xr_interface, p_eye, p_viewport->camera, p_viewport->scenario, p_viewport->size, screen_lod_threshold, p_viewport->shadow_atlas);
|
||||
} else {
|
||||
RSG::scene->render_camera(p_viewport->render_buffers, p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
|
||||
RSG::scene->render_camera(p_viewport->render_buffers, p_viewport->camera, p_viewport->scenario, p_viewport->size, screen_lod_threshold, p_viewport->shadow_atlas);
|
||||
}
|
||||
RENDER_TIMESTAMP("<End Rendering 3D Scene");
|
||||
}
|
||||
|
@ -885,6 +886,13 @@ void RendererViewport::viewport_set_use_debanding(RID p_viewport, bool p_use_deb
|
|||
}
|
||||
}
|
||||
|
||||
void RendererViewport::viewport_set_lod_threshold(RID p_viewport, float p_pixels) {
|
||||
Viewport *viewport = viewport_owner.getornull(p_viewport);
|
||||
ERR_FAIL_COND(!viewport);
|
||||
|
||||
viewport->lod_threshold = p_pixels;
|
||||
}
|
||||
|
||||
int RendererViewport::viewport_get_render_info(RID p_viewport, RS::ViewportRenderInfo p_info) {
|
||||
ERR_FAIL_INDEX_V(p_info, RS::VIEWPORT_RENDER_INFO_MAX, -1);
|
||||
|
||||
|
|
|
@ -84,6 +84,8 @@ public:
|
|||
|
||||
bool sdf_active;
|
||||
|
||||
float lod_threshold = 1.0;
|
||||
|
||||
uint64_t last_pass = 0;
|
||||
|
||||
int render_info[RS::VIEWPORT_RENDER_INFO_MAX];
|
||||
|
@ -222,6 +224,8 @@ public:
|
|||
void viewport_set_screen_space_aa(RID p_viewport, RS::ViewportScreenSpaceAA p_mode);
|
||||
void viewport_set_use_debanding(RID p_viewport, bool p_use_debanding);
|
||||
|
||||
void viewport_set_lod_threshold(RID p_viewport, float p_pixels);
|
||||
|
||||
virtual int viewport_get_render_info(RID p_viewport, RS::ViewportRenderInfo p_info);
|
||||
virtual void viewport_set_debug_draw(RID p_viewport, RS::ViewportDebugDraw p_draw);
|
||||
|
||||
|
|
|
@ -359,6 +359,7 @@ public:
|
|||
BIND2(reflection_probe_set_enable_shadows, RID, bool)
|
||||
BIND2(reflection_probe_set_cull_mask, RID, uint32_t)
|
||||
BIND2(reflection_probe_set_resolution, RID, int)
|
||||
BIND2(reflection_probe_set_lod_threshold, RID, float)
|
||||
|
||||
/* DECAL API */
|
||||
|
||||
|
@ -545,6 +546,7 @@ public:
|
|||
BIND2(viewport_set_msaa, RID, ViewportMSAA)
|
||||
BIND2(viewport_set_screen_space_aa, RID, ViewportScreenSpaceAA)
|
||||
BIND2(viewport_set_use_debanding, RID, bool)
|
||||
BIND2(viewport_set_lod_threshold, RID, float)
|
||||
|
||||
BIND2R(int, viewport_get_render_info, RID, ViewportRenderInfo)
|
||||
BIND2(viewport_set_debug_draw, RID, ViewportDebugDraw)
|
||||
|
@ -673,6 +675,7 @@ public:
|
|||
BIND5(instance_geometry_set_draw_range, RID, float, float, float, float)
|
||||
BIND2(instance_geometry_set_as_instance_lod, RID, RID)
|
||||
BIND4(instance_geometry_set_lightmap, RID, RID, const Rect2 &, int)
|
||||
BIND2(instance_geometry_set_lod_bias, RID, float)
|
||||
|
||||
BIND3(instance_geometry_set_shader_parameter, RID, const StringName &, const Variant &)
|
||||
BIND2RC(Variant, instance_geometry_get_shader_parameter, RID, const StringName &)
|
||||
|
|
|
@ -266,6 +266,7 @@ public:
|
|||
FUNC2(reflection_probe_set_enable_shadows, RID, bool)
|
||||
FUNC2(reflection_probe_set_cull_mask, RID, uint32_t)
|
||||
FUNC2(reflection_probe_set_resolution, RID, int)
|
||||
FUNC2(reflection_probe_set_lod_threshold, RID, float)
|
||||
|
||||
/* DECAL API */
|
||||
|
||||
|
@ -450,6 +451,8 @@ public:
|
|||
FUNC2(viewport_set_screen_space_aa, RID, ViewportScreenSpaceAA)
|
||||
FUNC2(viewport_set_use_debanding, RID, bool)
|
||||
|
||||
FUNC2(viewport_set_lod_threshold, RID, float)
|
||||
|
||||
//this passes directly to avoid stalling, but it's pretty dangerous, so don't call after freeing a viewport
|
||||
virtual int viewport_get_render_info(RID p_viewport, ViewportRenderInfo p_info) {
|
||||
return rendering_server->viewport_get_render_info(p_viewport, p_info);
|
||||
|
@ -575,6 +578,7 @@ public:
|
|||
FUNC5(instance_geometry_set_draw_range, RID, float, float, float, float)
|
||||
FUNC2(instance_geometry_set_as_instance_lod, RID, RID)
|
||||
FUNC4(instance_geometry_set_lightmap, RID, RID, const Rect2 &, int)
|
||||
FUNC2(instance_geometry_set_lod_bias, RID, float)
|
||||
|
||||
FUNC3(instance_geometry_set_shader_parameter, RID, const StringName &, const Variant &)
|
||||
FUNC2RC(Variant, instance_geometry_get_shader_parameter, RID, const StringName &)
|
||||
|
|
|
@ -507,6 +507,7 @@ public:
|
|||
virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) = 0;
|
||||
virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) = 0;
|
||||
virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution) = 0;
|
||||
virtual void reflection_probe_set_lod_threshold(RID p_probe, float p_pixels) = 0;
|
||||
|
||||
/* DECAL API */
|
||||
|
||||
|
@ -805,6 +806,8 @@ public:
|
|||
|
||||
virtual void viewport_set_use_debanding(RID p_viewport, bool p_use_debanding) = 0;
|
||||
|
||||
virtual void viewport_set_lod_threshold(RID p_viewport, float p_pixels) = 0;
|
||||
|
||||
enum ViewportRenderInfo {
|
||||
VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME,
|
||||
VIEWPORT_RENDER_INFO_VERTICES_IN_FRAME,
|
||||
|
@ -836,6 +839,7 @@ public:
|
|||
VIEWPORT_DEBUG_DRAW_SDFGI,
|
||||
VIEWPORT_DEBUG_DRAW_SDFGI_PROBES,
|
||||
VIEWPORT_DEBUG_DRAW_GI_BUFFER,
|
||||
VIEWPORT_DEBUG_DRAW_DISABLE_LOD,
|
||||
|
||||
};
|
||||
|
||||
|
@ -1142,6 +1146,7 @@ public:
|
|||
virtual void instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin) = 0;
|
||||
virtual void instance_geometry_set_as_instance_lod(RID p_instance, RID p_as_lod_of_instance) = 0;
|
||||
virtual void instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice) = 0;
|
||||
virtual void instance_geometry_set_lod_bias(RID p_instance, float p_lod_bias) = 0;
|
||||
|
||||
virtual void instance_geometry_set_shader_parameter(RID p_instance, const StringName &, const Variant &p_value) = 0;
|
||||
virtual Variant instance_geometry_get_shader_parameter(RID p_instance, const StringName &) const = 0;
|
||||
|
|
|
@ -298,6 +298,12 @@ TEST_CASE("[AABB] Get longest/shortest axis") {
|
|||
"get_shortest_axis() should return the expected value.");
|
||||
}
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#warning Support tests need to be re-done
|
||||
#endif
|
||||
|
||||
/* Support function was actually broken. As it was fixed, the tests now fail. Tests need to be re-done.
|
||||
|
||||
TEST_CASE("[AABB] Get support") {
|
||||
const AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
|
||||
CHECK_MESSAGE(
|
||||
|
@ -319,7 +325,7 @@ TEST_CASE("[AABB] Get support") {
|
|||
aabb.get_support(Vector3()).is_equal_approx(Vector3(2.5, 7, 3.5)),
|
||||
"get_support() should return the expected value with a null vector.");
|
||||
}
|
||||
|
||||
*/
|
||||
TEST_CASE("[AABB] Grow") {
|
||||
const AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
|
||||
CHECK_MESSAGE(
|
||||
|
|
9
thirdparty/README.md
vendored
9
thirdparty/README.md
vendored
|
@ -355,15 +355,20 @@ File extracted from upstream release tarball:
|
|||
- Added 2 files `godot_core_mbedtls_platform.{c,h}` providing configuration
|
||||
for light bundling with core.
|
||||
|
||||
|
||||
## meshoptimizer
|
||||
|
||||
- Upstream: https://github.com/zeux/meshoptimizer
|
||||
- Version: 0.15(2020)
|
||||
- Version: 0.15 (2020)
|
||||
- License: MIT
|
||||
|
||||
File extracted from upstream release tarball:
|
||||
|
||||
- Files in src/ go to thirdparty/meshoptimizer
|
||||
- All files in `src/`.
|
||||
|
||||
Important: Some files have Godot-made changes.
|
||||
They can be applied with the patch in the `patches` folder, but are meant to be superseded
|
||||
by upstream API changes.
|
||||
|
||||
|
||||
## miniupnpc
|
||||
|
|
5
thirdparty/meshoptimizer/meshoptimizer.h
vendored
5
thirdparty/meshoptimizer/meshoptimizer.h
vendored
|
@ -266,7 +266,10 @@ MESHOPTIMIZER_EXPERIMENTAL void meshopt_decodeFilterExp(void* buffer, size_t ver
|
|||
* destination must contain enough space for the *source* index buffer (since optimization is iterative, this means index_count elements - *not* target_index_count!)
|
||||
* vertex_positions should have float3 position in the first 12 bytes of each vertex - similar to glVertexPointer
|
||||
*/
|
||||
MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error);
|
||||
// -- GODOT start --
|
||||
//MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error);
|
||||
MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplify(unsigned int *destination, const unsigned int *indices, size_t index_count, const float *vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float *r_resulting_error);
|
||||
// -- GODOT end --
|
||||
|
||||
/**
|
||||
* Experimental: Mesh simplifier (sloppy)
|
||||
|
|
96
thirdparty/meshoptimizer/patches/simplifier_get_resulting_error.patch
vendored
Normal file
96
thirdparty/meshoptimizer/patches/simplifier_get_resulting_error.patch
vendored
Normal file
|
@ -0,0 +1,96 @@
|
|||
diff --git a/thirdparty/meshoptimizer/meshoptimizer.h b/thirdparty/meshoptimizer/meshoptimizer.h
|
||||
index a442d103c8..fde00f9c82 100644
|
||||
--- a/thirdparty/meshoptimizer/meshoptimizer.h
|
||||
+++ b/thirdparty/meshoptimizer/meshoptimizer.h
|
||||
@@ -266,7 +266,10 @@ MESHOPTIMIZER_EXPERIMENTAL void meshopt_decodeFilterExp(void* buffer, size_t ver
|
||||
* destination must contain enough space for the *source* index buffer (since optimization is iterative, this means index_count elements - *not* target_index_count!)
|
||||
* vertex_positions should have float3 position in the first 12 bytes of each vertex - similar to glVertexPointer
|
||||
*/
|
||||
-MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error);
|
||||
+// -- GODOT start --
|
||||
+//MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error);
|
||||
+MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplify(unsigned int *destination, const unsigned int *indices, size_t index_count, const float *vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float *r_resulting_error);
|
||||
+// -- GODOT end --
|
||||
|
||||
/**
|
||||
* Experimental: Mesh simplifier (sloppy)
|
||||
diff --git a/thirdparty/meshoptimizer/simplifier.cpp b/thirdparty/meshoptimizer/simplifier.cpp
|
||||
index bd523275ce..51cf634186 100644
|
||||
--- a/thirdparty/meshoptimizer/simplifier.cpp
|
||||
+++ b/thirdparty/meshoptimizer/simplifier.cpp
|
||||
@@ -1143,7 +1143,10 @@ unsigned int* meshopt_simplifyDebugLoop = 0;
|
||||
unsigned int* meshopt_simplifyDebugLoopBack = 0;
|
||||
#endif
|
||||
|
||||
-size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error)
|
||||
+// -- GODOT start --
|
||||
+//size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error)
|
||||
+size_t meshopt_simplify(unsigned int *destination, const unsigned int *indices, size_t index_count, const float *vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float *r_resulting_error)
|
||||
+// -- GODOT end --
|
||||
{
|
||||
using namespace meshopt;
|
||||
|
||||
@@ -1198,10 +1201,13 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
|
||||
if (result != indices)
|
||||
memcpy(result, indices, index_count * sizeof(unsigned int));
|
||||
|
||||
+// -- GODOT start --
|
||||
#if TRACE
|
||||
size_t pass_count = 0;
|
||||
- float worst_error = 0;
|
||||
+ //float worst_error = 0;
|
||||
#endif
|
||||
+ float worst_error = 0;
|
||||
+// -- GODOT end --
|
||||
|
||||
Collapse* edge_collapses = allocator.allocate<Collapse>(index_count);
|
||||
unsigned int* collapse_order = allocator.allocate<unsigned int>(index_count);
|
||||
@@ -1213,6 +1219,12 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
|
||||
// target_error input is linear; we need to adjust it to match quadricError units
|
||||
float error_limit = target_error * target_error;
|
||||
|
||||
+// -- GODOT start --
|
||||
+ if (r_resulting_error) {
|
||||
+ *r_resulting_error = 1.0;
|
||||
+ }
|
||||
+// -- GODOT end --
|
||||
+
|
||||
while (result_count > target_index_count)
|
||||
{
|
||||
size_t edge_collapse_count = pickEdgeCollapses(edge_collapses, result, result_count, remap, vertex_kind, loop);
|
||||
@@ -1257,7 +1269,8 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
|
||||
size_t new_count = remapIndexBuffer(result, result_count, collapse_remap);
|
||||
assert(new_count < result_count);
|
||||
|
||||
-#if TRACE
|
||||
+// -- GODOT start --
|
||||
+//#if TRACE
|
||||
float pass_error = 0.f;
|
||||
for (size_t i = 0; i < edge_collapse_count; ++i)
|
||||
{
|
||||
@@ -1267,15 +1280,24 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
|
||||
pass_error = c.error;
|
||||
}
|
||||
|
||||
- pass_count++;
|
||||
+ //pass_count++;
|
||||
worst_error = (worst_error < pass_error) ? pass_error : worst_error;
|
||||
|
||||
+#if TRACE
|
||||
+ pass_count++;
|
||||
printf("pass %d: triangles: %d -> %d, collapses: %d/%d (goal: %d), error: %e (limit %e goal %e)\n", int(pass_count), int(result_count / 3), int(new_count / 3), int(collapses), int(edge_collapse_count), int(edge_collapse_goal), pass_error, error_limit, error_goal);
|
||||
#endif
|
||||
+// -- GODOT end --
|
||||
|
||||
result_count = new_count;
|
||||
}
|
||||
|
||||
+// -- GODOT start --
|
||||
+ if (r_resulting_error) {
|
||||
+ *r_resulting_error = sqrt(worst_error);
|
||||
+ }
|
||||
+// -- GODOT end --
|
||||
+
|
||||
#if TRACE
|
||||
printf("passes: %d, worst error: %e\n", int(pass_count), worst_error);
|
||||
#endif
|
30
thirdparty/meshoptimizer/simplifier.cpp
vendored
30
thirdparty/meshoptimizer/simplifier.cpp
vendored
|
@ -1143,7 +1143,10 @@ unsigned int* meshopt_simplifyDebugLoop = 0;
|
|||
unsigned int* meshopt_simplifyDebugLoopBack = 0;
|
||||
#endif
|
||||
|
||||
size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error)
|
||||
// -- GODOT start --
|
||||
//size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error)
|
||||
size_t meshopt_simplify(unsigned int *destination, const unsigned int *indices, size_t index_count, const float *vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float *r_resulting_error)
|
||||
// -- GODOT end --
|
||||
{
|
||||
using namespace meshopt;
|
||||
|
||||
|
@ -1198,10 +1201,13 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
|
|||
if (result != indices)
|
||||
memcpy(result, indices, index_count * sizeof(unsigned int));
|
||||
|
||||
// -- GODOT start --
|
||||
#if TRACE
|
||||
size_t pass_count = 0;
|
||||
float worst_error = 0;
|
||||
//float worst_error = 0;
|
||||
#endif
|
||||
float worst_error = 0;
|
||||
// -- GODOT end --
|
||||
|
||||
Collapse* edge_collapses = allocator.allocate<Collapse>(index_count);
|
||||
unsigned int* collapse_order = allocator.allocate<unsigned int>(index_count);
|
||||
|
@ -1213,6 +1219,12 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
|
|||
// target_error input is linear; we need to adjust it to match quadricError units
|
||||
float error_limit = target_error * target_error;
|
||||
|
||||
// -- GODOT start --
|
||||
if (r_resulting_error) {
|
||||
*r_resulting_error = 1.0;
|
||||
}
|
||||
// -- GODOT end --
|
||||
|
||||
while (result_count > target_index_count)
|
||||
{
|
||||
size_t edge_collapse_count = pickEdgeCollapses(edge_collapses, result, result_count, remap, vertex_kind, loop);
|
||||
|
@ -1257,7 +1269,8 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
|
|||
size_t new_count = remapIndexBuffer(result, result_count, collapse_remap);
|
||||
assert(new_count < result_count);
|
||||
|
||||
#if TRACE
|
||||
// -- GODOT start --
|
||||
//#if TRACE
|
||||
float pass_error = 0.f;
|
||||
for (size_t i = 0; i < edge_collapse_count; ++i)
|
||||
{
|
||||
|
@ -1267,15 +1280,24 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
|
|||
pass_error = c.error;
|
||||
}
|
||||
|
||||
pass_count++;
|
||||
//pass_count++;
|
||||
worst_error = (worst_error < pass_error) ? pass_error : worst_error;
|
||||
|
||||
#if TRACE
|
||||
pass_count++;
|
||||
printf("pass %d: triangles: %d -> %d, collapses: %d/%d (goal: %d), error: %e (limit %e goal %e)\n", int(pass_count), int(result_count / 3), int(new_count / 3), int(collapses), int(edge_collapse_count), int(edge_collapse_goal), pass_error, error_limit, error_goal);
|
||||
#endif
|
||||
// -- GODOT end --
|
||||
|
||||
result_count = new_count;
|
||||
}
|
||||
|
||||
// -- GODOT start --
|
||||
if (r_resulting_error) {
|
||||
*r_resulting_error = sqrt(worst_error);
|
||||
}
|
||||
// -- GODOT end --
|
||||
|
||||
#if TRACE
|
||||
printf("passes: %d, worst error: %e\n", int(pass_count), worst_error);
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue