From 6deffa62fbd1e91873afa663630b788b9ffabee3 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sat, 14 Sep 2019 00:37:42 -0300 Subject: [PATCH] Several fixes to 3D rendering, and multimesh implementation. --- core/io/resource_loader.cpp | 1 + drivers/vulkan/rendering_device_vulkan.cpp | 4 +- editor/doc/doc_data.cpp | 2 + editor/import/resource_importer_texture.cpp | 17 +- editor/plugins/multimesh_editor_plugin.cpp | 2 +- modules/gridmap/grid_map.cpp | 2 +- scene/2d/cpu_particles_2d.cpp | 4 +- scene/3d/cpu_particles.cpp | 4 +- scene/3d/vehicle_body.cpp | 3 +- scene/3d/voxel_light_baker.cpp | 2 +- scene/main/viewport.cpp | 2 +- scene/resources/environment.cpp | 14 + scene/resources/environment.h | 3 + scene/resources/mesh.cpp | 117 +++- scene/resources/multimesh.cpp | 95 +-- scene/resources/multimesh.h | 33 +- scene/resources/texture.cpp | 76 +- scene/resources/texture.h | 4 +- servers/visual/rasterizer.h | 6 +- .../rasterizer_rd/rasterizer_canvas_rd.cpp | 2 +- .../rasterizer_scene_forward_rd.cpp | 92 ++- .../rasterizer_scene_forward_rd.h | 12 + .../rasterizer_rd/rasterizer_scene_rd.cpp | 3 +- .../rasterizer_rd/rasterizer_storage_rd.cpp | 655 +++++++++++++++++- .../rasterizer_rd/rasterizer_storage_rd.h | 125 +++- .../rasterizer_rd/shader_compiler_rd.cpp | 3 +- .../rasterizer_rd/shaders/scene_forward.glsl | 58 +- .../shaders/scene_forward_inc.glsl | 16 +- .../visual/rasterizer_rd/shaders/tonemap.glsl | 4 +- servers/visual/shader_language.cpp | 18 + servers/visual/shader_language.h | 12 + servers/visual/visual_server_raster.h | 5 +- servers/visual/visual_server_scene.cpp | 1 - servers/visual/visual_server_wrap_mt.h | 5 +- servers/visual_server.cpp | 11 +- servers/visual_server.h | 21 +- 36 files changed, 1212 insertions(+), 222 deletions(-) diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index 0e1ada9475..b6e75dd0e7 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -404,6 +404,7 @@ RES ResourceLoader::load(const String &p_path, const String &p_type_hint, bool p if (!p_no_cache) { _remove_from_loading_map(local_path); } + print_verbose("Failed loading resource: " + path); return RES(); } if (!p_no_cache) diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp index 8cc07c59b1..09b0f7113e 100644 --- a/drivers/vulkan/rendering_device_vulkan.cpp +++ b/drivers/vulkan/rendering_device_vulkan.cpp @@ -3969,7 +3969,7 @@ RID RenderingDeviceVulkan::storage_buffer_create(uint32_t p_size_bytes, const Po ERR_FAIL_COND_V(p_data.size() && (uint32_t)p_data.size() != p_size_bytes, RID()); Buffer buffer; - Error err = _buffer_allocate(&buffer, p_size_bytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY); + Error err = _buffer_allocate(&buffer, p_size_bytes, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY); ERR_FAIL_COND_V(err != OK, RID()); if (p_data.size()) { @@ -4600,6 +4600,8 @@ PoolVector RenderingDeviceVulkan::buffer_get_data(RID p_buffer) { buffer = index_buffer_owner.getornull(p_buffer); } else if (texture_buffer_owner.owns(p_buffer)) { buffer = &texture_buffer_owner.getornull(p_buffer)->buffer; + } else if (storage_buffer_owner.owns(p_buffer)) { + buffer = storage_buffer_owner.getornull(p_buffer); } else { ERR_FAIL_V_MSG(PoolVector(), "Buffer is either invalid or this type of buffer can't be retrieved. Only Index and Vertex buffers allow retrieving."); } diff --git a/editor/doc/doc_data.cpp b/editor/doc/doc_data.cpp index 0d9e53c71c..c128ca4321 100644 --- a/editor/doc/doc_data.cpp +++ b/editor/doc/doc_data.cpp @@ -304,6 +304,8 @@ void DocData::generate(bool p_basic_types) { } } + //used to track uninitialized values using valgrind + //print_line("getting default value for " + String(name) + "." + String(E->get().name)); if (default_value_valid && default_value.get_type() != Variant::OBJECT) { prop.default_value = default_value.get_construct_string().replace("\n", ""); } diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp index 1c373fbcf2..32bf9c6f40 100644 --- a/editor/import/resource_importer_texture.cpp +++ b/editor/import/resource_importer_texture.cpp @@ -115,8 +115,8 @@ void ResourceImporterTexture::update_imports() { changed = true; } - if (E->get().flags & MAKE_3D_FLAG && bool(cf->get_value("params", "detect_3d"))) { - cf->set_value("params", "detect_3d", false); + if (E->get().flags & MAKE_3D_FLAG && bool(cf->get_value("params", "usage/detect_3d"))) { + cf->set_value("params", "usage/detect_3d", false); cf->set_value("params", "compress/mode", 2); cf->set_value("params", "format/mipmaps", true); changed = true; @@ -214,9 +214,10 @@ void ResourceImporterTexture::get_import_options(List *r_options, r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "process/premult_alpha"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "process/invert_color"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "process/HDR_as_SRGB"), false)); - r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "stream"), false)); - r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "size_limit", PROPERTY_HINT_RANGE, "0,4096,1"), 0)); - r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "detect_3d"), p_preset == PRESET_DETECT)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "process/size_limit", PROPERTY_HINT_RANGE, "0,4096,1"), 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "process/mipmap_limit", PROPERTY_HINT_RANGE, "0,999,1"), 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "usage/stream"), false)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "usage/detect_3d"), p_preset == PRESET_DETECT)); r_options->push_back(ImportOption(PropertyInfo(Variant::REAL, "svg/scale", PROPERTY_HINT_RANGE, "0.001,100,0.001"), 1.0)); } @@ -385,8 +386,8 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String bool fix_alpha_border = p_options["process/fix_alpha_border"]; bool premult_alpha = p_options["process/premult_alpha"]; bool invert_color = p_options["process/invert_color"]; - bool stream = p_options["stream"]; - int size_limit = p_options["size_limit"]; + bool stream = p_options["usage/stream"]; + int size_limit = p_options["process/size_limit"]; bool hdr_as_srgb = p_options["process/HDR_as_SRGB"]; int normal = p_options["compress/normal_map"]; float scale = p_options["svg/scale"]; @@ -443,7 +444,7 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String image->unlock(); } - bool detect_3d = p_options["detect_3d"]; + bool detect_3d = p_options["usage/detect_3d"]; bool detect_roughness = roughness == 0; bool detect_normal = normal == 0; bool force_normal = normal == 1; diff --git a/editor/plugins/multimesh_editor_plugin.cpp b/editor/plugins/multimesh_editor_plugin.cpp index 5dc222f84c..ddd27b5e97 100644 --- a/editor/plugins/multimesh_editor_plugin.cpp +++ b/editor/plugins/multimesh_editor_plugin.cpp @@ -172,7 +172,7 @@ void MultiMeshEditor::_populate() { int instance_count = populate_amount->get_value(); multimesh->set_transform_format(MultiMesh::TRANSFORM_3D); - multimesh->set_color_format(MultiMesh::COLOR_NONE); + multimesh->set_use_colors(false); multimesh->set_instance_count(instance_count); float _tilt_random = populate_tilt_random->get_value(); diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp index 1e73a715db..7fe58f8ce7 100644 --- a/modules/gridmap/grid_map.cpp +++ b/modules/gridmap/grid_map.cpp @@ -514,7 +514,7 @@ bool GridMap::_octant_update(const OctantKey &p_key) { Octant::MultimeshInstance mmi; RID mm = VS::get_singleton()->multimesh_create(); - VS::get_singleton()->multimesh_allocate(mm, E->get().size(), VS::MULTIMESH_TRANSFORM_3D, VS::MULTIMESH_COLOR_NONE); + VS::get_singleton()->multimesh_allocate(mm, E->get().size(), VS::MULTIMESH_TRANSFORM_3D); VS::get_singleton()->multimesh_set_mesh(mm, mesh_library->get_item_mesh(E->key())->get_rid()); int idx = 0; diff --git a/scene/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp index 0e5c1b8c02..b4d1052c04 100644 --- a/scene/2d/cpu_particles_2d.cpp +++ b/scene/2d/cpu_particles_2d.cpp @@ -59,7 +59,7 @@ void CPUParticles2D::set_amount(int p_amount) { } particle_data.resize((8 + 4 + 1) * p_amount); - VS::get_singleton()->multimesh_allocate(multimesh, p_amount, VS::MULTIMESH_TRANSFORM_2D, VS::MULTIMESH_COLOR_8BIT, VS::MULTIMESH_CUSTOM_DATA_FLOAT); + VS::get_singleton()->multimesh_allocate(multimesh, p_amount, VS::MULTIMESH_TRANSFORM_2D, true, true); particle_order.resize(p_amount); } @@ -1077,7 +1077,7 @@ void CPUParticles2D::_update_render_thread() { update_mutex->lock(); #endif - VS::get_singleton()->multimesh_set_as_bulk_array(multimesh, particle_data); + VS::get_singleton()->multimesh_set_buffer(multimesh, particle_data); #ifndef NO_THREADS update_mutex->unlock(); diff --git a/scene/3d/cpu_particles.cpp b/scene/3d/cpu_particles.cpp index aa7a413548..e8760983e9 100644 --- a/scene/3d/cpu_particles.cpp +++ b/scene/3d/cpu_particles.cpp @@ -73,7 +73,7 @@ void CPUParticles::set_amount(int p_amount) { } particle_data.resize((12 + 4 + 1) * p_amount); - VS::get_singleton()->multimesh_allocate(multimesh, p_amount, VS::MULTIMESH_TRANSFORM_3D, VS::MULTIMESH_COLOR_8BIT, VS::MULTIMESH_CUSTOM_DATA_FLOAT); + VS::get_singleton()->multimesh_allocate(multimesh, p_amount, VS::MULTIMESH_TRANSFORM_3D, true, true); particle_order.resize(p_amount); } @@ -1144,7 +1144,7 @@ void CPUParticles::_update_render_thread() { update_mutex->lock(); #endif if (can_update) { - VS::get_singleton()->multimesh_set_as_bulk_array(multimesh, particle_data); + VS::get_singleton()->multimesh_set_buffer(multimesh, particle_data); can_update = false; //wait for next time } diff --git a/scene/3d/vehicle_body.cpp b/scene/3d/vehicle_body.cpp index 92b17d5056..52e50aa84e 100644 --- a/scene/3d/vehicle_body.cpp +++ b/scene/3d/vehicle_body.cpp @@ -364,9 +364,8 @@ VehicleWheel::VehicleWheel() { steers = false; engine_traction = false; - m_steering = real_t(0.); - //m_engineForce = real_t(0.); + m_engineForce = real_t(0.); m_rotation = real_t(0.); m_deltaRotation = real_t(0.); m_brake = real_t(0.); diff --git a/scene/3d/voxel_light_baker.cpp b/scene/3d/voxel_light_baker.cpp index 1b6e328342..db8d7f0851 100644 --- a/scene/3d/voxel_light_baker.cpp +++ b/scene/3d/voxel_light_baker.cpp @@ -2339,7 +2339,7 @@ Ref VoxelLightBaker::create_debug_multimesh(DebugMode p_mode) { mm.instance(); mm->set_transform_format(MultiMesh::TRANSFORM_3D); - mm->set_color_format(MultiMesh::COLOR_8BIT); + mm->set_use_colors(true); mm->set_instance_count(leaf_voxel_count); Ref mesh; diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 976c66ad0c..19edf556fb 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -300,7 +300,7 @@ void Viewport::_notification(int p_what) { //3D PhysicsServer::get_singleton()->space_set_debug_contacts(find_world()->get_space(), get_tree()->get_collision_debug_contact_count()); contact_3d_debug_multimesh = VisualServer::get_singleton()->multimesh_create(); - VisualServer::get_singleton()->multimesh_allocate(contact_3d_debug_multimesh, get_tree()->get_collision_debug_contact_count(), VS::MULTIMESH_TRANSFORM_3D, VS::MULTIMESH_COLOR_8BIT); + VisualServer::get_singleton()->multimesh_allocate(contact_3d_debug_multimesh, get_tree()->get_collision_debug_contact_count(), VS::MULTIMESH_TRANSFORM_3D, true); VisualServer::get_singleton()->multimesh_set_visible_instances(contact_3d_debug_multimesh, 0); VisualServer::get_singleton()->multimesh_set_mesh(contact_3d_debug_multimesh, get_tree()->get_debug_contact_mesh()->get_rid()); contact_3d_debug_instance = VisualServer::get_singleton()->instance_create(); diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp index 5e18e73b5b..4ee8962702 100644 --- a/scene/resources/environment.cpp +++ b/scene/resources/environment.cpp @@ -937,6 +937,20 @@ float Environment::get_fog_height_curve() const { return fog_height_curve; } +#ifndef DISABLE_DEPRECATED +bool Environment::_set(const StringName &p_name, const Variant &p_value) { + if (p_name == "background_sky") { + set_sky(p_value); + return true; + } else if (p_name == "background_sky_custom_fov") { + set_sky_custom_fov(p_value); + return true; + } else { + return false; + } +} +#endif + void Environment::_bind_methods() { ClassDB::bind_method(D_METHOD("set_background", "mode"), &Environment::set_background); diff --git a/scene/resources/environment.h b/scene/resources/environment.h index 30f96e97fd..69f18c3424 100644 --- a/scene/resources/environment.h +++ b/scene/resources/environment.h @@ -194,6 +194,9 @@ private: protected: static void _bind_methods(); virtual void _validate_property(PropertyInfo &property) const; +#ifndef DISABLE_DEPRECATED + bool _set(const StringName &p_name, const Variant &p_value); +#endif public: void set_background(BGMode p_bg); diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index 96c609174f..e102d944e8 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -590,6 +590,89 @@ Vector > Mesh::convex_decompose() const { Mesh::Mesh() { } +static PoolVector _fix_array_compatibility(const PoolVector &p_src, uint32_t p_format, uint32_t p_elements) { + + bool vertex_16bit = p_format & ((1 << (Mesh::ARRAY_VERTEX + Mesh::ARRAY_COMPRESS_BASE))); + bool bone_32_bits = (p_format & Mesh::ARRAY_FORMAT_BONES) && !(p_format & (Mesh::ARRAY_COMPRESS_INDEX << 2)); + + print_line("convert vertex16: " + itos(vertex_16bit) + " bone 32 " + itos(bone_32_bits)); + if (!vertex_16bit && !bone_32_bits) { + return p_src; + } + + bool vertex_2d = (p_format & (Mesh::ARRAY_COMPRESS_INDEX << 1)); + + uint32_t src_stride = p_src.size() / p_elements; + uint32_t dst_stride = src_stride + (vertex_16bit ? 4 : 0) - (bone_32_bits ? 16 : 0); + + PoolVector ret; + ret.resize(dst_stride * p_elements); + { + PoolVector::Write w = ret.write(); + PoolVector::Read r = p_src.read(); + + for (uint32_t i = 0; i < p_elements; i++) { + + uint32_t remaining = src_stride; + const uint8_t *src = (const uint8_t *)(r.ptr() + src_stride * i); + uint8_t *dst = (uint8_t *)(w.ptr() + dst_stride * i); + + if (!vertex_2d) { //3D + if (vertex_16bit) { + float *dstw = (float *)dst; + const uint16_t *srcr = (const uint16_t *)src; + dstw[0] = Math::half_to_float(srcr[0]); + dstw[1] = Math::half_to_float(srcr[1]); + dstw[2] = Math::half_to_float(srcr[2]); + remaining -= 8; + src += 8; + } else { + src += 12; + remaining -= 12; + } + dst += 12; + } else { + if (vertex_16bit) { + float *dstw = (float *)dst; + const uint16_t *srcr = (const uint16_t *)src; + dstw[0] = Math::half_to_float(srcr[0]); + dstw[1] = Math::half_to_float(srcr[1]); + remaining -= 4; + src += 4; + } else { + src += 8; + remaining -= 8; + } + dst += 8; + } + + if (bone_32_bits) { + + const uint32_t *src_bones = (const uint32_t *)&src[remaining - 32]; + const float *src_weights = (const float *)&src[remaining - 16]; + uint16_t *dstw = (uint16_t *)&dst[remaining - 32]; + + dstw[0] = src_bones[0]; + dstw[1] = src_bones[1]; + dstw[2] = src_bones[2]; + dstw[3] = src_bones[3]; + dstw[4] = CLAMP(src_weights[0] * 65535, 0, 65535); //16bits unorm + dstw[5] = CLAMP(src_weights[1] * 65535, 0, 65535); + dstw[6] = CLAMP(src_weights[2] * 65535, 0, 65535); + dstw[7] = CLAMP(src_weights[3] * 65535, 0, 65535); + + remaining -= 32; + } + + for (uint32_t j = 0; j < remaining; j++) { + dst[j] = src[j]; + } + } + } + + return ret; +} + bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) { String sname = p_name; @@ -624,11 +707,11 @@ bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) { return true; } -#ifdef ENABLE_DEPRECATED +#ifndef DISABLE_DEPRECATED if (!sname.begins_with("surfaces")) return false; - WARN_DEPRECATED("Mesh uses old surface format, which is deprecated (and loads slower). Consider re-importing or re-saving the scene."); + WARN_DEPRECATED_MSG("Mesh uses old surface format, which is deprecated (and loads slower). Consider re-importing or re-saving the scene."); int idx = sname.get_slicec('/', 1).to_int(); String what = sname.get_slicec('/', 2); @@ -640,12 +723,13 @@ bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) { ERR_FAIL_COND_V(!d.has("primitive"), false); if (d.has("arrays")) { - //old format + //oldest format (2.x) ERR_FAIL_COND_V(!d.has("morph_arrays"), false); add_surface_from_arrays(PrimitiveType(int(d["primitive"])), d["arrays"], d["morph_arrays"]); } else if (d.has("array_data")) { - + print_line("array data (old style"); + //older format (3.x) PoolVector array_data = d["array_data"]; PoolVector array_index_data; if (d.has("array_index_data")) @@ -655,16 +739,24 @@ bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) { uint32_t format = d["format"]; uint32_t primitive = d["primitive"]; - if (primitive > PRIMITIVE_LINE_STRIP) { - primitive--; //line loop was deprecated, so it's not supported and indices go down by one - } - if (primitive > PRIMITIVE_TRIANGLE_STRIP) { - primitive = PRIMITIVE_TRIANGLE_STRIP; //fan is no longer supported - } + + uint32_t primitive_remap[7] = { + PRIMITIVE_POINTS, + PRIMITIVE_LINES, + PRIMITIVE_LINE_STRIP, + PRIMITIVE_LINES, + PRIMITIVE_TRIANGLES, + PRIMITIVE_TRIANGLE_STRIP, + PRIMITIVE_TRIANGLE_STRIP + }; + + primitive = primitive_remap[primitive]; //compatibility ERR_FAIL_COND_V(!d.has("vertex_count"), false); int vertex_count = d["vertex_count"]; + array_data = _fix_array_compatibility(array_data, format, vertex_count); + int index_count = 0; if (d.has("index_count")) index_count = d["index_count"]; @@ -675,10 +767,15 @@ bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) { Array blend_shape_data = d["blend_shape_data"]; for (int i = 0; i < blend_shape_data.size(); i++) { PoolVector shape = blend_shape_data[i]; + shape = _fix_array_compatibility(shape, format, vertex_count); + blend_shapes.push_back(shape); } } + //clear unused flags + format &= ~((1 << (ARRAY_VERTEX + ARRAY_COMPRESS_BASE)) | (ARRAY_COMPRESS_INDEX << 2)); + ERR_FAIL_COND_V(!d.has("aabb"), false); AABB aabb = d["aabb"]; diff --git a/scene/resources/multimesh.cpp b/scene/resources/multimesh.cpp index ee831f36f5..946511c766 100644 --- a/scene/resources/multimesh.cpp +++ b/scene/resources/multimesh.cpp @@ -31,6 +31,8 @@ #include "multimesh.h" #include "servers/visual_server.h" +#ifndef DISABLE_DEPRECATED + void MultiMesh::_set_transform_array(const PoolVector &p_array) { if (transform_format != TRANSFORM_3D) return; @@ -146,7 +148,7 @@ void MultiMesh::_set_color_array(const PoolVector &p_array) { PoolVector MultiMesh::_get_color_array() const { - if (instance_count == 0 || color_format == COLOR_NONE) + if (instance_count == 0 || !use_colors) return PoolVector(); PoolVector colors; @@ -178,7 +180,7 @@ void MultiMesh::_set_custom_data_array(const PoolVector &p_array) { PoolVector MultiMesh::_get_custom_data_array() const { - if (instance_count == 0 || custom_data_format == CUSTOM_DATA_NONE) + if (instance_count == 0 || !use_custom_data) return PoolVector(); PoolVector custom_datas; @@ -191,6 +193,16 @@ PoolVector MultiMesh::_get_custom_data_array() const { return custom_datas; } + +#endif +void MultiMesh::set_buffer(const PoolVector &p_buffer) { + VS::get_singleton()->multimesh_set_buffer(multimesh, p_buffer); +} + +PoolVector MultiMesh::get_buffer() const { + return VS::get_singleton()->multimesh_get_buffer(multimesh); +} + void MultiMesh::set_mesh(const Ref &p_mesh) { mesh = p_mesh; @@ -207,7 +219,7 @@ Ref MultiMesh::get_mesh() const { void MultiMesh::set_instance_count(int p_count) { ERR_FAIL_COND(p_count < 0); - VisualServer::get_singleton()->multimesh_allocate(multimesh, p_count, VS::MultimeshTransformFormat(transform_format), VS::MultimeshColorFormat(color_format), VS::MultimeshCustomDataFormat(custom_data_format)); + VisualServer::get_singleton()->multimesh_allocate(multimesh, p_count, VS::MultimeshTransformFormat(transform_format), use_colors, use_custom_data); instance_count = p_count; } int MultiMesh::get_instance_count() const { @@ -217,6 +229,7 @@ int MultiMesh::get_instance_count() const { void MultiMesh::set_visible_instance_count(int p_count) { ERR_FAIL_COND(p_count < -1); + ERR_FAIL_COND(p_count > instance_count); VisualServer::get_singleton()->multimesh_set_visible_instances(multimesh, p_count); visible_instance_count = p_count; } @@ -263,11 +276,6 @@ Color MultiMesh::get_instance_custom_data(int p_instance) const { return VisualServer::get_singleton()->multimesh_instance_get_custom_data(multimesh, p_instance); } -void MultiMesh::set_as_bulk_array(const PoolVector &p_array) { - - VisualServer::get_singleton()->multimesh_set_as_bulk_array(multimesh, p_array); -} - AABB MultiMesh::get_aabb() const { return VisualServer::get_singleton()->multimesh_get_aabb(multimesh); @@ -278,26 +286,22 @@ RID MultiMesh::get_rid() const { return multimesh; } -void MultiMesh::set_color_format(ColorFormat p_color_format) { - +void MultiMesh::set_use_colors(bool p_enable) { ERR_FAIL_COND(instance_count > 0); - color_format = p_color_format; + use_colors = p_enable; } -MultiMesh::ColorFormat MultiMesh::get_color_format() const { - - return color_format; +bool MultiMesh::is_using_colors() const { + return use_colors; } -void MultiMesh::set_custom_data_format(CustomDataFormat p_custom_data_format) { - +void MultiMesh::set_use_custom_data(bool p_enable) { ERR_FAIL_COND(instance_count > 0); - custom_data_format = p_custom_data_format; + use_custom_data = p_enable; } -MultiMesh::CustomDataFormat MultiMesh::get_custom_data_format() const { - - return custom_data_format; +bool MultiMesh::is_using_custom_data() const { + return use_custom_data; } void MultiMesh::set_transform_format(TransformFormat p_transform_format) { @@ -314,10 +318,10 @@ void MultiMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("set_mesh", "mesh"), &MultiMesh::set_mesh); ClassDB::bind_method(D_METHOD("get_mesh"), &MultiMesh::get_mesh); - ClassDB::bind_method(D_METHOD("set_color_format", "format"), &MultiMesh::set_color_format); - ClassDB::bind_method(D_METHOD("get_color_format"), &MultiMesh::get_color_format); - ClassDB::bind_method(D_METHOD("set_custom_data_format", "format"), &MultiMesh::set_custom_data_format); - ClassDB::bind_method(D_METHOD("get_custom_data_format"), &MultiMesh::get_custom_data_format); + ClassDB::bind_method(D_METHOD("set_use_colors", "enable"), &MultiMesh::set_use_colors); + ClassDB::bind_method(D_METHOD("is_using_colors"), &MultiMesh::is_using_colors); + ClassDB::bind_method(D_METHOD("set_use_custom_data", "enable"), &MultiMesh::set_use_custom_data); + ClassDB::bind_method(D_METHOD("is_using_custom_data"), &MultiMesh::is_using_custom_data); ClassDB::bind_method(D_METHOD("set_transform_format", "format"), &MultiMesh::set_transform_format); ClassDB::bind_method(D_METHOD("get_transform_format"), &MultiMesh::get_transform_format); @@ -333,9 +337,22 @@ void MultiMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("get_instance_color", "instance"), &MultiMesh::get_instance_color); ClassDB::bind_method(D_METHOD("set_instance_custom_data", "instance", "custom_data"), &MultiMesh::set_instance_custom_data); ClassDB::bind_method(D_METHOD("get_instance_custom_data", "instance"), &MultiMesh::get_instance_custom_data); - ClassDB::bind_method(D_METHOD("set_as_bulk_array", "array"), &MultiMesh::set_as_bulk_array); ClassDB::bind_method(D_METHOD("get_aabb"), &MultiMesh::get_aabb); + ClassDB::bind_method(D_METHOD("get_buffer"), &MultiMesh::get_buffer); + ClassDB::bind_method(D_METHOD("set_buffer", "buffer"), &MultiMesh::set_buffer); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "transform_format", PROPERTY_HINT_ENUM, "2D,3D"), "set_transform_format", "get_transform_format"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_colors"), "set_use_colors", "is_using_colors"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_custom_data"), "set_use_custom_data", "is_using_custom_data"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "instance_count", PROPERTY_HINT_RANGE, "0,16384,1,or_greater"), "set_instance_count", "get_instance_count"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_instance_count", PROPERTY_HINT_RANGE, "-1,16384,1,or_greater"), "set_visible_instance_count", "get_visible_instance_count"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_mesh", "get_mesh"); + ADD_PROPERTY(PropertyInfo(Variant::POOL_REAL_ARRAY, "buffer", PROPERTY_HINT_NONE), "set_buffer", "get_buffer"); + +#ifndef DISABLE_DEPRECATED + //kept for compatibility + ClassDB::bind_method(D_METHOD("_set_transform_array"), &MultiMesh::_set_transform_array); ClassDB::bind_method(D_METHOD("_get_transform_array"), &MultiMesh::_get_transform_array); ClassDB::bind_method(D_METHOD("_set_transform_2d_array"), &MultiMesh::_set_transform_2d_array); @@ -345,34 +362,20 @@ void MultiMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_custom_data_array"), &MultiMesh::_set_custom_data_array); ClassDB::bind_method(D_METHOD("_get_custom_data_array"), &MultiMesh::_get_custom_data_array); - ADD_PROPERTY(PropertyInfo(Variant::INT, "color_format", PROPERTY_HINT_ENUM, "None,Byte,Float"), "set_color_format", "get_color_format"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "transform_format", PROPERTY_HINT_ENUM, "2D,3D"), "set_transform_format", "get_transform_format"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "custom_data_format", PROPERTY_HINT_ENUM, "None,Byte,Float"), "set_custom_data_format", "get_custom_data_format"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "instance_count", PROPERTY_HINT_RANGE, "0,16384,1,or_greater"), "set_instance_count", "get_instance_count"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_instance_count", PROPERTY_HINT_RANGE, "-1,16384,1,or_greater"), "set_visible_instance_count", "get_visible_instance_count"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_mesh", "get_mesh"); - ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR3_ARRAY, "transform_array", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_transform_array", "_get_transform_array"); - ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "transform_2d_array", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_transform_2d_array", "_get_transform_2d_array"); - ADD_PROPERTY(PropertyInfo(Variant::POOL_COLOR_ARRAY, "color_array", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_color_array", "_get_color_array"); - ADD_PROPERTY(PropertyInfo(Variant::POOL_COLOR_ARRAY, "custom_data_array", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_custom_data_array", "_get_custom_data_array"); - + ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR3_ARRAY, "transform_array", PROPERTY_HINT_NONE, "", 0), "_set_transform_array", "_get_transform_array"); + ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "transform_2d_array", PROPERTY_HINT_NONE, "", 0), "_set_transform_2d_array", "_get_transform_2d_array"); + ADD_PROPERTY(PropertyInfo(Variant::POOL_COLOR_ARRAY, "color_array", PROPERTY_HINT_NONE, "", 0), "_set_color_array", "_get_color_array"); + ADD_PROPERTY(PropertyInfo(Variant::POOL_COLOR_ARRAY, "custom_data_array", PROPERTY_HINT_NONE, "", 0), "_set_custom_data_array", "_get_custom_data_array"); +#endif BIND_ENUM_CONSTANT(TRANSFORM_2D); BIND_ENUM_CONSTANT(TRANSFORM_3D); - - BIND_ENUM_CONSTANT(COLOR_NONE); - BIND_ENUM_CONSTANT(COLOR_8BIT); - BIND_ENUM_CONSTANT(COLOR_FLOAT); - - BIND_ENUM_CONSTANT(CUSTOM_DATA_NONE); - BIND_ENUM_CONSTANT(CUSTOM_DATA_8BIT); - BIND_ENUM_CONSTANT(CUSTOM_DATA_FLOAT); } MultiMesh::MultiMesh() { multimesh = VisualServer::get_singleton()->multimesh_create(); - color_format = COLOR_NONE; - custom_data_format = CUSTOM_DATA_NONE; + use_colors = false; + use_custom_data = false; transform_format = TRANSFORM_2D; visible_instance_count = -1; instance_count = 0; diff --git a/scene/resources/multimesh.h b/scene/resources/multimesh.h index 9394737799..e7d62d0993 100644 --- a/scene/resources/multimesh.h +++ b/scene/resources/multimesh.h @@ -45,30 +45,20 @@ public: TRANSFORM_3D = VS::MULTIMESH_TRANSFORM_3D }; - enum ColorFormat { - COLOR_NONE = VS::MULTIMESH_COLOR_NONE, - COLOR_8BIT = VS::MULTIMESH_COLOR_8BIT, - COLOR_FLOAT = VS::MULTIMESH_COLOR_FLOAT, - }; - - enum CustomDataFormat { - CUSTOM_DATA_NONE, - CUSTOM_DATA_8BIT, - CUSTOM_DATA_FLOAT, - }; - private: Ref mesh; RID multimesh; TransformFormat transform_format; - ColorFormat color_format; - CustomDataFormat custom_data_format; + bool use_colors; + bool use_custom_data; int instance_count; int visible_instance_count; protected: static void _bind_methods(); +#ifndef DISABLE_DEPRECATED + void _set_transform_array(const PoolVector &p_array); PoolVector _get_transform_array() const; @@ -80,16 +70,19 @@ protected: void _set_custom_data_array(const PoolVector &p_array); PoolVector _get_custom_data_array() const; +#endif + void set_buffer(const PoolVector &p_buffer); + PoolVector get_buffer() const; public: void set_mesh(const Ref &p_mesh); Ref get_mesh() const; - void set_color_format(ColorFormat p_color_format); - ColorFormat get_color_format() const; + void set_use_colors(bool p_enable); + bool is_using_colors() const; - void set_custom_data_format(CustomDataFormat p_custom_data_format); - CustomDataFormat get_custom_data_format() const; + void set_use_custom_data(bool p_enable); + bool is_using_custom_data() const; void set_transform_format(TransformFormat p_transform_format); TransformFormat get_transform_format() const; @@ -111,8 +104,6 @@ public: void set_instance_custom_data(int p_instance, const Color &p_custom_data); Color get_instance_custom_data(int p_instance) const; - void set_as_bulk_array(const PoolVector &p_array); - virtual AABB get_aabb() const; virtual RID get_rid() const; @@ -122,7 +113,5 @@ public: }; VARIANT_ENUM_CAST(MultiMesh::TransformFormat); -VARIANT_ENUM_CAST(MultiMesh::ColorFormat); -VARIANT_ENUM_CAST(MultiMesh::CustomDataFormat); #endif // MULTI_MESH_H diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index 7085171043..c0311aca3a 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -394,7 +394,7 @@ Image::Format StreamTexture::get_format() const { return format; } -Error StreamTexture::_load_data(const String &p_path, int &tw, int &th, int &tw_custom, int &th_custom, Ref &image, int p_size_limit) { +Error StreamTexture::_load_data(const String &p_path, int &tw, int &th, int &tw_custom, int &th_custom, Ref &image, bool &r_request_3d, bool &r_request_normal, bool &r_request_roughness, int p_size_limit) { alpha_cache.unref(); @@ -420,29 +420,16 @@ Error StreamTexture::_load_data(const String &p_path, int &tw, int &th, int &tw_ #ifdef TOOLS_ENABLED - if (request_3d_callback && df & FORMAT_BIT_DETECT_3D) { - //print_line("request detect 3D at " + p_path); - VS::get_singleton()->texture_set_detect_3d_callback(texture, _requested_3d, this); - } else { - //print_line("not requesting detect 3D at " + p_path); - VS::get_singleton()->texture_set_detect_3d_callback(texture, NULL, NULL); - } + r_request_3d = request_3d_callback && df & FORMAT_BIT_DETECT_3D; + r_request_roughness = request_roughness_callback && df & FORMAT_BIT_DETECT_ROUGNESS; + r_request_normal = request_normal_callback && df & FORMAT_BIT_DETECT_NORMAL; - if (request_roughness_callback && df & FORMAT_BIT_DETECT_ROUGNESS) { - //print_line("request detect srgb at " + p_path); - VS::get_singleton()->texture_set_detect_roughness_callback(texture, _requested_roughness, this); - } else { - //print_line("not requesting detect srgb at " + p_path); - VS::get_singleton()->texture_set_detect_roughness_callback(texture, NULL, NULL); - } +#else + + r_request_3d = false; + r_request_roughness = false; + r_request_normal = false; - if (request_normal_callback && df & FORMAT_BIT_DETECT_NORMAL) { - //print_line("request detect srgb at " + p_path); - VS::get_singleton()->texture_set_detect_normal_callback(texture, _requested_normal, this); - } else { - //print_line("not requesting detect normal at " + p_path); - VS::get_singleton()->texture_set_detect_normal_callback(texture, NULL, NULL); - } #endif if (!(df & FORMAT_BIT_STREAM)) { p_size_limit = 0; @@ -607,7 +594,7 @@ Error StreamTexture::_load_data(const String &p_path, int &tw, int &th, int &tw_ } } - return ERR_BUG; //unreachable + ERR_FAIL_V(ERR_BUG); //unreachable } Error StreamTexture::load(const String &p_path) { @@ -615,14 +602,15 @@ Error StreamTexture::load(const String &p_path) { int lw, lh, lwc, lhc; Ref image; image.instance(); - Error err = _load_data(p_path, lw, lh, lwc, lhc, image); + + bool request_3d; + bool request_normal; + bool request_roughness; + + Error err = _load_data(p_path, lw, lh, lwc, lhc, image, request_3d, request_normal, request_roughness); if (err) return err; - if (get_path() == String()) { - //temporarily set path if no path set for resource, helps find errors - VisualServer::get_singleton()->texture_set_path(texture, p_path); - } if (texture.is_valid()) { RID new_texture = VS::get_singleton()->texture_2d_create(image); VS::get_singleton()->texture_replace(texture, new_texture); @@ -638,6 +626,38 @@ Error StreamTexture::load(const String &p_path) { path_to_file = p_path; format = image->get_format(); + if (get_path() == String()) { + //temporarily set path if no path set for resource, helps find errors + VisualServer::get_singleton()->texture_set_path(texture, p_path); + } + +#ifdef TOOLS_ENABLED + + if (request_3d) { + //print_line("request detect 3D at " + p_path); + VS::get_singleton()->texture_set_detect_3d_callback(texture, _requested_3d, this); + } else { + //print_line("not requesting detect 3D at " + p_path); + VS::get_singleton()->texture_set_detect_3d_callback(texture, NULL, NULL); + } + + if (request_roughness) { + //print_line("request detect srgb at " + p_path); + VS::get_singleton()->texture_set_detect_roughness_callback(texture, _requested_roughness, this); + } else { + //print_line("not requesting detect srgb at " + p_path); + VS::get_singleton()->texture_set_detect_roughness_callback(texture, NULL, NULL); + } + + if (request_normal) { + //print_line("request detect srgb at " + p_path); + VS::get_singleton()->texture_set_detect_normal_callback(texture, _requested_normal, this); + } else { + //print_line("not requesting detect normal at " + p_path); + VS::get_singleton()->texture_set_detect_normal_callback(texture, NULL, NULL); + } + +#endif _change_notify(); emit_changed(); return OK; diff --git a/scene/resources/texture.h b/scene/resources/texture.h index c18368fb85..173556da72 100644 --- a/scene/resources/texture.h +++ b/scene/resources/texture.h @@ -155,7 +155,7 @@ public: }; private: - Error _load_data(const String &p_path, int &tw, int &th, int &tw_custom, int &th_custom, Ref &image, int p_size_limit = 0); + Error _load_data(const String &p_path, int &tw, int &th, int &tw_custom, int &th_custom, Ref &image, bool &r_request_3d, bool &r_request_normal, bool &r_request_roughness, int p_size_limit = 0); String path_to_file; mutable RID texture; Image::Format format; @@ -390,6 +390,7 @@ public: class Cubemap : public TextureLayered { GDCLASS(Cubemap, TextureLayered); + public: Cubemap() : TextureLayered(VS::TEXTURE_LAYERED_CUBEMAP) {} @@ -398,6 +399,7 @@ public: class CubemapArray : public TextureLayered { GDCLASS(CubemapArray, TextureLayered); + public: CubemapArray() : TextureLayered(VS::TEXTURE_LAYERED_CUBEMAP_ARRAY) {} diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index fe682618a4..f5ce604b04 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -358,7 +358,8 @@ public: virtual RID multimesh_create() = 0; - virtual void multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, VS::MultimeshColorFormat p_color_format, VS::MultimeshCustomDataFormat p_data = VS::MULTIMESH_CUSTOM_DATA_NONE) = 0; + virtual void multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) = 0; + virtual int multimesh_get_instance_count(RID p_multimesh) const = 0; virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) = 0; @@ -374,7 +375,8 @@ public: virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const = 0; virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const = 0; - virtual void multimesh_set_as_bulk_array(RID p_multimesh, const PoolVector &p_array) = 0; + virtual void multimesh_set_buffer(RID p_multimesh, const PoolVector &p_buffer) = 0; + virtual PoolVector multimesh_get_buffer(RID p_multimesh) const = 0; virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) = 0; virtual int multimesh_get_visible_instances(RID p_multimesh) const = 0; diff --git a/servers/visual/rasterizer_rd/rasterizer_canvas_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_canvas_rd.cpp index 1dc0503027..1a94f11334 100644 --- a/servers/visual/rasterizer_rd/rasterizer_canvas_rd.cpp +++ b/servers/visual/rasterizer_rd/rasterizer_canvas_rd.cpp @@ -2107,7 +2107,7 @@ void RasterizerCanvasRD::MaterialData::update_parameters(const Mapdefault_texture_params, shader_data->texture_uniforms, texture_cache.ptrw()); + update_textures(p_parameters, shader_data->default_texture_params, shader_data->texture_uniforms, texture_cache.ptrw(), false); } if (shader_data->ubo_size == 0 && !shader_data->uses_material_samplers) { diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp index be5b8f1845..bf4d7e4fc8 100644 --- a/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp +++ b/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp @@ -465,7 +465,7 @@ void RasterizerSceneForwardRD::MaterialData::update_parameters(const Mapdefault_texture_params, shader_data->texture_uniforms, texture_cache.ptrw()); + update_textures(p_parameters, shader_data->default_texture_params, shader_data->texture_uniforms, texture_cache.ptrw(), true); } if (shader_data->ubo_size == 0 && shader_data->texture_uniforms.size() == 0) { @@ -607,6 +607,26 @@ void RasterizerSceneForwardRD::_fill_instances(RenderList::Element **p_elements, id.flags = 0; id.mask = e->instance->layer_mask; + if (e->instance->base_type == VS::INSTANCE_MULTIMESH) { + id.flags |= INSTANCE_DATA_FLAG_MULTIMESH; + uint32_t stride; + if (storage->multimesh_get_transform_format(e->instance->base) == VS::MULTIMESH_TRANSFORM_2D) { + id.flags |= INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D; + stride = 2; + } else { + stride = 3; + } + if (storage->multimesh_uses_colors(e->instance->base)) { + id.flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR; + stride += 1; + } + if (storage->multimesh_uses_custom_data(e->instance->base)) { + id.flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA; + stride += 1; + } + + id.flags |= (stride << INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_SHIFT); + } //forward uint32_t reflection_count = 0; @@ -632,7 +652,7 @@ void RasterizerSceneForwardRD::_fill_instances(RenderList::Element **p_elements, } if (reflection_count < 8) { - id.omni_light_indices[omni_count] = reflection_probe_instance_get_render_index(rpi_ptrs[j]); + id.reflection_probe_indices[reflection_count] = reflection_probe_instance_get_render_index(rpi_ptrs[j]); reflection_count++; } } @@ -661,7 +681,7 @@ void RasterizerSceneForwardRD::_fill_instances(RenderList::Element **p_elements, } } else { if (spot_count < 8) { - id.omni_light_indices[spot_count] = light_instance_get_index(light_ptrs[j]); + id.spot_light_indices[spot_count] = light_instance_get_index(light_ptrs[j]); spot_count++; } } @@ -686,6 +706,7 @@ void RasterizerSceneForwardRD::_render_list(RenderingDevice::DrawListID p_draw_l //global scope bindings RD::get_singleton()->draw_list_bind_uniform_set(draw_list, render_base_uniform_set, 0); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, default_vec4_xform_uniform_set, 1); MaterialData *prev_material = nullptr; // ShaderData *prev_shader = nullptr; @@ -693,6 +714,7 @@ void RasterizerSceneForwardRD::_render_list(RenderingDevice::DrawListID p_draw_l RID prev_vertex_array_rd; RID prev_index_array_rd; RID prev_pipeline_rd; + RID prev_xforms_uniform_set; PushConstant push_constant; zeromem(&push_constant, sizeof(PushConstant)); @@ -703,6 +725,7 @@ void RasterizerSceneForwardRD::_render_list(RenderingDevice::DrawListID p_draw_l MaterialData *material = e->material; ShaderData *shader = material->shader_data; + RID xforms_uniform_set; //find cull variant ShaderData::CullVariant cull_variant; @@ -725,7 +748,12 @@ void RasterizerSceneForwardRD::_render_list(RenderingDevice::DrawListID p_draw_l primitive = storage->mesh_surface_get_primitive(e->instance->base, e->surface_index); } break; case VS::INSTANCE_MULTIMESH: { - ERR_CONTINUE(true); //should be a bug + 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); + + xforms_uniform_set = storage->multimesh_get_3d_uniform_set(e->instance->base, default_shader_rd, 1); + } break; case VS::INSTANCE_IMMEDIATE: { ERR_CONTINUE(true); //should be a bug @@ -790,7 +818,9 @@ void RasterizerSceneForwardRD::_render_list(RenderingDevice::DrawListID p_draw_l 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); } break; case VS::INSTANCE_MULTIMESH: { - ERR_CONTINUE(true); //should be a bug + 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 VS::INSTANCE_IMMEDIATE: { ERR_CONTINUE(true); //should be a bug @@ -824,6 +854,11 @@ void RasterizerSceneForwardRD::_render_list(RenderingDevice::DrawListID p_draw_l prev_pipeline_rd = pipeline_rd; } + if (xforms_uniform_set.is_valid() && prev_xforms_uniform_set != xforms_uniform_set) { + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, material->uniform_set, 1); + prev_xforms_uniform_set = xforms_uniform_set; + } + if (material != prev_material) { //update uniform set if (material->uniform_set.is_valid()) { @@ -841,7 +876,8 @@ void RasterizerSceneForwardRD::_render_list(RenderingDevice::DrawListID p_draw_l RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid()); } break; case VS::INSTANCE_MULTIMESH: { - + uint32_t instances = storage->multimesh_get_instances_to_draw(e->instance->base); + RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid(), instances); } break; case VS::INSTANCE_IMMEDIATE: { @@ -1223,28 +1259,35 @@ void RasterizerSceneForwardRD::_fill_render_list(InstanceBase **p_cull_result, i //mesh->last_pass=frame; } break; -#if 0 + case VS::INSTANCE_MULTIMESH: { - RasterizerStorageGLES3::MultiMesh *multi_mesh = storage->multimesh_owner.getornull(inst->base); - ERR_CONTINUE(!multi_mesh); - - if (multi_mesh->size == 0 || multi_mesh->visible_instances == 0) + if (storage->multimesh_get_instances_to_draw(inst->base) == 0) { + //not visible, 0 instances continue; + } - RasterizerStorageGLES3::Mesh *mesh = storage->mesh_owner.getornull(multi_mesh->mesh); - if (!mesh) - continue; //mesh not assigned + RID mesh = storage->multimesh_get_mesh(inst->base); + if (!mesh.is_valid()) { + continue; + } - int ssize = mesh->surfaces.size(); + const RID *materials = NULL; + uint32_t surface_count; - for (int j = 0; j < ssize; j++) { + materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count); + if (!materials) { + continue; //nothing to do + } - RasterizerStorageGLES3::Surface *s = mesh->surfaces[j]; - _add_geometry(s, inst, multi_mesh, -1, p_depth_pass, p_shadow_pass); + for (uint32_t j = 0; j < surface_count; j++) { + + uint32_t surface_index = storage->mesh_surface_get_multimesh_render_pass_index(inst->base, j, render_pass, &geometry_index); + _add_geometry(inst, j, materials[j], p_pass_mode, surface_index); } } break; +#if 0 case VS::INSTANCE_IMMEDIATE: { RasterizerStorageGLES3::Immediate *immediate = storage->immediate_owner.getornull(inst->base); @@ -2589,7 +2632,7 @@ RasterizerSceneForwardRD::RasterizerSceneForwardRD(RasterizerStorageRD *p_storag actions.renames["POINT_COORD"] = "gl_PointCoord"; actions.renames["INSTANCE_CUSTOM"] = "instance_custom"; actions.renames["SCREEN_UV"] = "screen_uv"; - actions.renames["SCREEN_TEXTURE"] = "screen_texture"; + actions.renames["SCREEN_TEXTURE"] = "color_buffer"; actions.renames["DEPTH_TEXTURE"] = "depth_buffer"; actions.renames["NORMAL_TEXTURE"] = "normal_buffer"; actions.renames["DEPTH"] = "gl_FragDepth"; @@ -2697,6 +2740,17 @@ RasterizerSceneForwardRD::RasterizerSceneForwardRD(RasterizerStorageRD *p_storag default_shader_rd = shader.scene_shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS); } + { + default_vec4_xform_buffer = RD::get_singleton()->storage_buffer_create(256); + Vector uniforms; + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.ids.push_back(default_vec4_xform_buffer); + u.binding = 0; + uniforms.push_back(u); + + default_vec4_xform_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, 1); + } { RD::SamplerState sampler; diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h b/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h index c8166c3f88..912d62b1d8 100644 --- a/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h +++ b/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h @@ -247,6 +247,15 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD { float shadow_matrices[4][16]; }; + enum { + INSTANCE_DATA_FLAG_MULTIMESH = 1 << 12, + INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D = 1 << 13, + INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR = 1 << 14, + INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA = 1 << 15, + INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_SHIFT = 16, + INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_MASK = 0x7, + }; + struct InstanceData { float transform[16]; float normal_transform[16]; @@ -471,6 +480,9 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD { RID default_material; RID default_shader_rd; + RID default_vec4_xform_buffer; + RID default_vec4_xform_uniform_set; + enum PassMode { PASS_MODE_COLOR, PASS_MODE_COLOR_SPECULAR, diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp index 63b65a8a15..7bb615eda9 100644 --- a/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp +++ b/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp @@ -428,6 +428,7 @@ VS::EnvironmentReflectionSource RasterizerSceneRD::environment_get_reflection_so void RasterizerSceneRD::environment_set_tonemap(RID p_env, VS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) { Environent *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); + env->exposure = p_exposure; env->tone_mapper = p_tone_mapper; env->auto_exposure = p_auto_exposure; env->white = p_white; @@ -1414,7 +1415,7 @@ bool RasterizerSceneRD::free(RID p_rid) { reflection_atlas_owner.free(p_rid); } else if (reflection_probe_instance_owner.owns(p_rid)) { //not much to delete, just free it - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_rid); + //ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_rid); reflection_probe_release_atlas_index(p_rid); reflection_probe_instance_owner.free(p_rid); } else if (sky_owner.owns(p_rid)) { diff --git a/servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp index e80f5f54b9..7cf93a82e0 100644 --- a/servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp +++ b/servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp @@ -199,7 +199,7 @@ Ref RasterizerStorageRD::_validate_texture_format(const Ref &p_ima case Image::FORMAT_DXT1: { if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { r_format.format = RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK; - r_format.format_srgb = RD::DATA_FORMAT_BC1_RGBA_SRGB_BLOCK; + r_format.format_srgb = RD::DATA_FORMAT_BC1_RGB_SRGB_BLOCK; } else { //not supported, reconvert r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; @@ -788,16 +788,31 @@ void RasterizerStorageRD::texture_set_size_override(RID p_texture, int p_width, } void RasterizerStorageRD::texture_set_path(RID p_texture, const String &p_path) { + Texture *tex = texture_owner.getornull(p_texture); + ERR_FAIL_COND(!tex); + tex->path = p_path; } String RasterizerStorageRD::texture_get_path(RID p_texture) const { return String(); } void RasterizerStorageRD::texture_set_detect_3d_callback(RID p_texture, VS::TextureDetectCallback p_callback, void *p_userdata) { + Texture *tex = texture_owner.getornull(p_texture); + ERR_FAIL_COND(!tex); + tex->detect_3d_callback_ud = p_userdata; + tex->detect_3d_callback = p_callback; } void RasterizerStorageRD::texture_set_detect_normal_callback(RID p_texture, VS::TextureDetectCallback p_callback, void *p_userdata) { + Texture *tex = texture_owner.getornull(p_texture); + ERR_FAIL_COND(!tex); + tex->detect_normal_callback_ud = p_userdata; + tex->detect_normal_callback = p_callback; } void RasterizerStorageRD::texture_set_detect_roughness_callback(RID p_texture, VS::TextureDetectRoughnessCallback p_callback, void *p_userdata) { + Texture *tex = texture_owner.getornull(p_texture); + ERR_FAIL_COND(!tex); + tex->detect_roughness_callback_ud = p_userdata; + tex->detect_roughness_callback = p_callback; } void RasterizerStorageRD::texture_debug_usage(List *r_info) { } @@ -1611,9 +1626,14 @@ void RasterizerStorageRD::MaterialData::update_uniform_buffer(const Map &p_parameters, const Map &p_default_textures, const Vector &p_texture_uniforms, RID *p_textures) { +void RasterizerStorageRD::MaterialData::update_textures(const Map &p_parameters, const Map &p_default_textures, const Vector &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) { RasterizerStorageRD *singleton = (RasterizerStorageRD *)RasterizerStorage::base_singleton; +#ifdef TOOLS_ENABLED + Texture *roughness_detect_texture = nullptr; + VS::TextureDetectRoughnessChannel roughness_channel; + Texture *normal_detect_texture = nullptr; +#endif for (int i = 0; i < p_texture_uniforms.size(); i++) { @@ -1653,8 +1673,31 @@ void RasterizerStorageRD::MaterialData::update_textures(const Maptexture_get_rd_texture(texture, srgb); + bool srgb = p_use_linear_color && p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ALBEDO || p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO; + + Texture *tex = singleton->texture_owner.getornull(texture); + + if (tex) { + rd_texture = (srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture; +#ifdef TOOLS_ENABLED + if (tex->detect_3d_callback && p_use_linear_color) { + tex->detect_3d_callback(tex->detect_3d_callback_ud); + } + if (tex->detect_normal_callback && (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL || p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL)) { + if (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL) { + normal_detect_texture = tex; + } + tex->detect_normal_callback(tex->detect_normal_callback_ud); + } + if (tex->detect_roughness_callback && (p_texture_uniforms[i].hint >= ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_R || p_texture_uniforms[i].hint <= ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_GRAY)) { + //find the normal texture + roughness_detect_texture = tex; + roughness_channel = VS::TextureDetectRoughnessChannel(p_texture_uniforms[i].hint - ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_R); + } + +#endif + } + if (rd_texture.is_null()) { //wtf rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE); @@ -1663,6 +1706,11 @@ void RasterizerStorageRD::MaterialData::update_textures(const Mappath != String()) { + roughness_detect_texture->detect_roughness_callback(roughness_detect_texture->detect_roughness_callback_ud, normal_detect_texture->path, roughness_channel); + } +#endif } void RasterizerStorageRD::material_force_update_textures(RID p_material, ShaderType p_shader_type) { @@ -2087,6 +2135,568 @@ void RasterizerStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Su v.vertex_array = RD::get_singleton()->vertex_array_create(s->vertex_count, v.vertex_format, buffers); } +////////////////// MULTIMESH + +RID RasterizerStorageRD::multimesh_create() { + + return multimesh_owner.make_rid(MultiMesh()); +} + +void RasterizerStorageRD::multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, bool p_use_colors, bool p_use_custom_data) { + + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND(!multimesh); + + if (multimesh->instances == p_instances && multimesh->xform_format == p_transform_format && multimesh->uses_colors == p_use_colors && multimesh->uses_custom_data == p_use_custom_data) { + return; + } + + if (multimesh->buffer.is_valid()) { + RD::get_singleton()->free(multimesh->buffer); + multimesh->buffer = RID(); + multimesh->uniform_set_3d = RID(); //cleared by dependency + } + + if (multimesh->data_cache_dirty_regions) { + memdelete_arr(multimesh->data_cache_dirty_regions); + multimesh->data_cache_dirty_regions = nullptr; + multimesh->data_cache_used_dirty_regions = 0; + } + + multimesh->instances = p_instances; + multimesh->xform_format = p_transform_format; + multimesh->uses_colors = p_use_colors; + multimesh->color_offset_cache = p_transform_format == VS::MULTIMESH_TRANSFORM_2D ? 8 : 12; + multimesh->uses_custom_data = p_use_custom_data; + multimesh->custom_data_offset_cache = multimesh->color_offset_cache + (p_use_colors ? 4 : 0); + multimesh->stride_cache = multimesh->custom_data_offset_cache + (p_use_custom_data ? 4 : 0); + multimesh->buffer_set = false; + + print_line("allocate, elements: " + itos(p_instances) + " 2D: " + itos(p_transform_format == VS::MULTIMESH_TRANSFORM_2D) + " colors " + itos(multimesh->uses_colors) + " data " + itos(multimesh->uses_custom_data) + " stride " + itos(multimesh->stride_cache) + " total size " + itos(multimesh->stride_cache * multimesh->instances)); + multimesh->data_cache = PoolVector(); + multimesh->aabb = AABB(); + multimesh->aabb_dirty = false; + multimesh->visible_instances = MIN(multimesh->visible_instances, multimesh->instances); + + if (multimesh->instances) { + + multimesh->buffer = RD::get_singleton()->storage_buffer_create(multimesh->instances * multimesh->stride_cache); + } +} + +int RasterizerStorageRD::multimesh_get_instance_count(RID p_multimesh) const { + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND_V(!multimesh, 0); + return multimesh->instances; +} + +void RasterizerStorageRD::multimesh_set_mesh(RID p_multimesh, RID p_mesh) { + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND(!multimesh); + if (multimesh->mesh == p_mesh) { + return; + } + multimesh->mesh = p_mesh; + + if (multimesh->instances == 0) { + return; + } + + if (multimesh->data_cache.size()) { + //we have a data cache, just mark it dirt + _multimesh_mark_all_dirty(multimesh, false, true); + } else if (multimesh->instances) { + //need to re-create AABB unfortunately, calling this has a penalty + { + PoolVector buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer); + PoolVector::Read r = buffer.read(); + const float *data = (const float *)r.ptr(); + _multimesh_re_create_aabb(multimesh, data, multimesh->instances); + } + } + + multimesh->instance_dependency.instance_notify_changed(true, true); +} + +#define MULTIMESH_DIRTY_REGION_SIZE 512 + +void RasterizerStorageRD::_multimesh_make_local(MultiMesh *multimesh) const { + if (multimesh->data_cache.size() > 0) { + return; //already local + } + ERR_FAIL_COND(multimesh->data_cache.size() > 0); + // this means that the user wants to load/save individual elements, + // for this, the data must reside on CPU, so just copy it there. + multimesh->data_cache.resize(multimesh->instances * multimesh->stride_cache); + { + PoolVector::Write w = multimesh->data_cache.write(); + + if (multimesh->buffer_set) { + PoolVector buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer); + { + + PoolVector::Read r = buffer.read(); + copymem(w.ptr(), r.ptr(), buffer.size()); + } + } else { + zeromem(w.ptr(), multimesh->instances * multimesh->stride_cache * sizeof(float)); + } + } + uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; + multimesh->data_cache_dirty_regions = memnew_arr(bool, data_cache_dirty_region_count); + for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) { + multimesh->data_cache_dirty_regions[i] = 0; + } + multimesh->data_cache_used_dirty_regions = 0; +} + +void RasterizerStorageRD::_multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb) { + + uint32_t region_index = p_index / MULTIMESH_DIRTY_REGION_SIZE; +#ifdef DEBUG_ENABLED + uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; + ERR_FAIL_INDEX(region_index, data_cache_dirty_region_count); //bug +#endif + if (!multimesh->data_cache_dirty_regions[region_index]) { + multimesh->data_cache_dirty_regions[p_index] = true; + multimesh->data_cache_used_dirty_regions++; + } + + if (p_aabb) { + multimesh->aabb_dirty = true; + } + + if (!multimesh->dirty) { + multimesh->dirty_list = multimesh_dirty_list; + multimesh_dirty_list = multimesh; + multimesh->dirty = true; + } +} + +void RasterizerStorageRD::_multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb) { + if (p_data) { + uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; + + for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) { + if (!multimesh->data_cache_dirty_regions[i]) { + multimesh->data_cache_dirty_regions[i] = true; + multimesh->data_cache_used_dirty_regions++; + } + } + } + + if (p_aabb) { + multimesh->aabb_dirty = true; + } + + if (!multimesh->dirty) { + multimesh->dirty_list = multimesh_dirty_list; + multimesh_dirty_list = multimesh; + multimesh->dirty = true; + } +} + +void RasterizerStorageRD::_multimesh_re_create_aabb(MultiMesh *multimesh, const float *p_data, int p_instances) { + + ERR_FAIL_COND(multimesh->mesh.is_null()); + AABB aabb; + AABB mesh_aabb = mesh_get_aabb(multimesh->mesh); + for (int i = 0; i < p_instances; i++) { + const float *data = p_data + multimesh->stride_cache * i; + Transform t; + + if (multimesh->xform_format == VS::MULTIMESH_TRANSFORM_3D) { + t.basis[0].x = data[0]; + t.basis[0].y = data[1]; + t.basis[0].z = data[2]; + t.basis[1].x = data[3]; + t.basis[1].y = data[4]; + t.basis[1].z = data[5]; + t.basis[2].x = data[6]; + t.basis[2].y = data[7]; + t.basis[2].z = data[8]; + t.origin.x = data[9]; + t.origin.y = data[10]; + t.origin.z = data[11]; + + } else { + + t.basis.elements[0].x = data[0]; + t.basis.elements[1].x = data[1]; + t.origin.x = data[3]; + + t.basis.elements[0].y = data[4]; + t.basis.elements[1].y = data[5]; + t.origin.y = data[7]; + } + + if (i == 0) { + aabb = t.xform(mesh_aabb); + } else { + aabb.merge_with(t.xform(mesh_aabb)); + } + } + + multimesh->aabb = aabb; +} + +void RasterizerStorageRD::multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform) { + + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND(!multimesh); + ERR_FAIL_INDEX(p_index, multimesh->instances); + ERR_FAIL_COND(multimesh->xform_format != VS::MULTIMESH_TRANSFORM_3D); + + _multimesh_make_local(multimesh); + + { + PoolVector::Write w = multimesh->data_cache.write(); + + float *dataptr = w.ptr() + p_index * multimesh->stride_cache; + + dataptr[0] = p_transform.basis[0].x; + dataptr[1] = p_transform.basis[0].y; + dataptr[2] = p_transform.basis[0].z; + dataptr[3] = p_transform.basis[1].x; + dataptr[4] = p_transform.basis[1].y; + dataptr[5] = p_transform.basis[1].z; + dataptr[6] = p_transform.basis[2].x; + dataptr[7] = p_transform.basis[2].y; + dataptr[8] = p_transform.basis[2].z; + dataptr[9] = p_transform.origin.x; + dataptr[10] = p_transform.origin.y; + dataptr[11] = p_transform.origin.z; + } + + _multimesh_mark_dirty(multimesh, p_index, true); +} + +void RasterizerStorageRD::multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) { + + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND(!multimesh); + ERR_FAIL_INDEX(p_index, multimesh->instances); + ERR_FAIL_COND(multimesh->xform_format != VS::MULTIMESH_TRANSFORM_2D); + + _multimesh_make_local(multimesh); + + { + PoolVector::Write w = multimesh->data_cache.write(); + + float *dataptr = w.ptr() + p_index * multimesh->stride_cache; + + dataptr[0] = p_transform.elements[0].x; + dataptr[1] = p_transform.elements[1].x; + dataptr[2] = 0; + dataptr[3] = p_transform.elements[2].x; + dataptr[4] = p_transform.elements[0].y; + dataptr[5] = p_transform.elements[1].y; + dataptr[6] = 0; + dataptr[7] = p_transform.elements[2].y; + } + + _multimesh_mark_dirty(multimesh, p_index, true); +} +void RasterizerStorageRD::multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) { + + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND(!multimesh); + ERR_FAIL_INDEX(p_index, multimesh->instances); + ERR_FAIL_INDEX(p_index, !multimesh->uses_colors); + + _multimesh_make_local(multimesh); + + { + PoolVector::Write w = multimesh->data_cache.write(); + + float *dataptr = w.ptr() + p_index * multimesh->stride_cache + multimesh->color_offset_cache; + + dataptr[0] = p_color.r; + dataptr[1] = p_color.g; + dataptr[2] = p_color.b; + dataptr[3] = p_color.a; + } + + _multimesh_mark_dirty(multimesh, p_index, false); +} +void RasterizerStorageRD::multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) { + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND(!multimesh); + ERR_FAIL_INDEX(p_index, multimesh->instances); + ERR_FAIL_INDEX(p_index, !multimesh->uses_custom_data); + + _multimesh_make_local(multimesh); + + { + PoolVector::Write w = multimesh->data_cache.write(); + + float *dataptr = w.ptr() + p_index * multimesh->stride_cache + multimesh->custom_data_offset_cache; + + dataptr[0] = p_color.r; + dataptr[1] = p_color.g; + dataptr[2] = p_color.b; + dataptr[3] = p_color.a; + } + + _multimesh_mark_dirty(multimesh, p_index, false); +} + +RID RasterizerStorageRD::multimesh_get_mesh(RID p_multimesh) const { + + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND_V(!multimesh, RID()); + + return multimesh->mesh; +} + +Transform RasterizerStorageRD::multimesh_instance_get_transform(RID p_multimesh, int p_index) const { + + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND_V(!multimesh, Transform()); + ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform()); + ERR_FAIL_COND_V(multimesh->xform_format != VS::MULTIMESH_TRANSFORM_3D, Transform()); + + _multimesh_make_local(multimesh); + + Transform t; + { + PoolVector::Read r = multimesh->data_cache.read(); + + const float *dataptr = r.ptr() + p_index * multimesh->stride_cache; + + t.basis[0].x = dataptr[0]; + t.basis[0].y = dataptr[1]; + t.basis[0].z = dataptr[2]; + t.basis[1].x = dataptr[3]; + t.basis[1].y = dataptr[4]; + t.basis[1].z = dataptr[5]; + t.basis[2].x = dataptr[6]; + t.basis[2].y = dataptr[7]; + t.basis[2].z = dataptr[8]; + t.origin.x = dataptr[9]; + t.origin.y = dataptr[10]; + t.origin.z = dataptr[11]; + } + + return t; +} +Transform2D RasterizerStorageRD::multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const { + + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND_V(!multimesh, Transform2D()); + ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform2D()); + ERR_FAIL_COND_V(multimesh->xform_format != VS::MULTIMESH_TRANSFORM_2D, Transform2D()); + + _multimesh_make_local(multimesh); + + Transform2D t; + { + PoolVector::Read r = multimesh->data_cache.read(); + + const float *dataptr = r.ptr() + p_index * multimesh->stride_cache; + + t.elements[0].x = dataptr[0]; + t.elements[1].x = dataptr[1]; + t.elements[2].x = dataptr[3]; + + t.elements[0].y = dataptr[4]; + t.elements[1].y = dataptr[5]; + t.elements[2].y = dataptr[7]; + } + + return t; +} +Color RasterizerStorageRD::multimesh_instance_get_color(RID p_multimesh, int p_index) const { + + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND_V(!multimesh, Color()); + ERR_FAIL_INDEX_V(p_index, multimesh->instances, Color()); + ERR_FAIL_INDEX_V(p_index, !multimesh->uses_colors, Color()); + + _multimesh_make_local(multimesh); + + Color c; + { + PoolVector::Read r = multimesh->data_cache.read(); + + const float *dataptr = r.ptr() + p_index * multimesh->stride_cache + multimesh->color_offset_cache; + + c.r = dataptr[0]; + c.g = dataptr[1]; + c.b = dataptr[2]; + c.a = dataptr[3]; + } + + return c; +} +Color RasterizerStorageRD::multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const { + + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND_V(!multimesh, Color()); + ERR_FAIL_INDEX_V(p_index, multimesh->instances, Color()); + ERR_FAIL_INDEX_V(p_index, !multimesh->uses_custom_data, Color()); + + _multimesh_make_local(multimesh); + + Color c; + { + PoolVector::Read r = multimesh->data_cache.read(); + + const float *dataptr = r.ptr() + p_index * multimesh->stride_cache + multimesh->custom_data_offset_cache; + + c.r = dataptr[0]; + c.g = dataptr[1]; + c.b = dataptr[2]; + c.a = dataptr[3]; + } + + return c; +} + +void RasterizerStorageRD::multimesh_set_buffer(RID p_multimesh, const PoolVector &p_buffer) { + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND(!multimesh); + ERR_FAIL_COND(p_buffer.size() != (multimesh->instances * (int)multimesh->stride_cache)); + + { + PoolVector::Read r = p_buffer.read(); + RD::get_singleton()->buffer_update(multimesh->buffer, 0, p_buffer.size() * sizeof(float), r.ptr(), false); + multimesh->buffer_set = true; + } + + if (multimesh->data_cache.size()) { + //if we have a data cache, just update it + multimesh->data_cache = p_buffer; + { + //clear dirty since nothing will be dirty anymore + uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; + for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) { + multimesh->data_cache_dirty_regions[i] = false; + } + multimesh->data_cache_used_dirty_regions = 0; + } + + _multimesh_mark_all_dirty(multimesh, false, true); //update AABB + } else if (multimesh->mesh.is_valid()) { + //if we have a mesh set, we need to re-generate the AABB from the new data + PoolVector::Read r = p_buffer.read(); + const float *data = r.ptr(); + _multimesh_re_create_aabb(multimesh, data, multimesh->instances); + multimesh->instance_dependency.instance_notify_changed(true, false); + } +} + +PoolVector RasterizerStorageRD::multimesh_get_buffer(RID p_multimesh) const { + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND_V(!multimesh, PoolVector()); + if (multimesh->buffer.is_null()) { + return PoolVector(); + } else if (multimesh->data_cache.size()) { + return multimesh->data_cache; + } else { + //get from memory + + PoolVector buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer); + PoolVector ret; + ret.resize(multimesh->instances); + { + PoolVector::Write w = multimesh->data_cache.write(); + PoolVector::Read r = buffer.read(); + copymem(w.ptr(), r.ptr(), buffer.size()); + } + + return ret; + } +} + +void RasterizerStorageRD::multimesh_set_visible_instances(RID p_multimesh, int p_visible) { + + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND(!multimesh); + ERR_FAIL_COND(p_visible < -1 || p_visible > multimesh->instances); + if (multimesh->visible_instances == p_visible) { + return; + } + + if (multimesh->data_cache.size()) { + //there is a data cache.. + _multimesh_mark_all_dirty(multimesh, false, true); + } + + multimesh->visible_instances = p_visible; +} +int RasterizerStorageRD::multimesh_get_visible_instances(RID p_multimesh) const { + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND_V(!multimesh, 0); + return multimesh->visible_instances; +} + +AABB RasterizerStorageRD::multimesh_get_aabb(RID p_multimesh) const { + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND_V(!multimesh, AABB()); + if (multimesh->aabb_dirty) { + const_cast(this)->_update_dirty_multimeshes(); + } + return multimesh->aabb; +} + +void RasterizerStorageRD::_update_dirty_multimeshes() { + + while (multimesh_dirty_list) { + + MultiMesh *multimesh = multimesh_dirty_list; + + if (multimesh->data_cache.size()) { //may have been cleared, so only process if it exists + PoolVector::Read r = multimesh->data_cache.read(); + const float *data = r.ptr(); + + uint32_t visible_instances = multimesh->visible_instances >= 0 ? multimesh->visible_instances : multimesh->instances; + + if (multimesh->data_cache_used_dirty_regions) { + + uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; + uint32_t visible_region_count = (visible_instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; + + uint32_t region_size = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * sizeof(float); + + if (multimesh->data_cache_used_dirty_regions > 32 || multimesh->data_cache_used_dirty_regions > visible_region_count / 2) { + //if there too many dirty regions, or represent the majority of regions, just copy all, else transfer cost piles up too much + RD::get_singleton()->buffer_update(multimesh->buffer, 0, MIN(visible_region_count * region_size, multimesh->instances * multimesh->stride_cache), data, false); + } else { + //not that many regions? update them all + for (uint32_t i = 0; i < visible_region_count; i++) { + if (multimesh->data_cache_dirty_regions[i]) { + uint64_t offset = i * region_size; + uint64_t size = multimesh->stride_cache * multimesh->instances; + RD::get_singleton()->buffer_update(multimesh->buffer, offset, MIN(region_size, size - offset), &data[i * region_size], false); + } + } + } + + for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) { + multimesh->data_cache_dirty_regions[i] = false; + } + + multimesh->data_cache_used_dirty_regions = 0; + } + + if (multimesh->aabb_dirty) { + //aabb is dirty.. + _multimesh_re_create_aabb(multimesh, data, visible_instances); + multimesh->aabb_dirty = false; + multimesh->instance_dependency.instance_notify_changed(true, false); + } + } + + multimesh_dirty_list = multimesh->dirty_list; + + multimesh->dirty_list = nullptr; + multimesh->dirty = false; + } + + multimesh_dirty_list = nullptr; +} + /* LIGHT */ RID RasterizerStorageRD::light_create(VS::LightType p_type) { @@ -2889,6 +3499,13 @@ void RasterizerStorageRD::base_update_dependency(RID p_base, RasterizerScene::In if (mesh_owner.owns(p_base)) { Mesh *mesh = mesh_owner.getornull(p_base); p_instance->update_dependency(&mesh->instance_dependency); + } else if (multimesh_owner.owns(p_base)) { + + MultiMesh *multimesh = multimesh_owner.getornull(p_base); + p_instance->update_dependency(&multimesh->instance_dependency); + if (multimesh->mesh.is_valid()) { + base_update_dependency(multimesh->mesh, p_instance); + } } else if (reflection_probe_owner.owns(p_base)) { ReflectionProbe *rp = reflection_probe_owner.getornull(p_base); p_instance->update_dependency(&rp->instance_dependency); @@ -2903,6 +3520,9 @@ VS::InstanceType RasterizerStorageRD::get_base_type(RID p_rid) const { if (mesh_owner.owns(p_rid)) { return VS::INSTANCE_MESH; } + if (multimesh_owner.owns(p_rid)) { + return VS::INSTANCE_MULTIMESH; + } if (reflection_probe_owner.owns(p_rid)) { return VS::INSTANCE_REFLECTION_PROBE; } @@ -2914,8 +3534,29 @@ VS::InstanceType RasterizerStorageRD::get_base_type(RID p_rid) const { } void RasterizerStorageRD::update_dirty_resources() { _update_queued_materials(); + _update_dirty_multimeshes(); } +bool RasterizerStorageRD::has_os_feature(const String &p_feature) const { + + if (p_feature == "s3tc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) { + return true; + } + + if (p_feature == "bptc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC7_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) { + return true; + } + + if ((p_feature == "etc" || p_feature == "etc2") && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) { + return true; + } + + if (p_feature == "pvrtc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG, RD::TEXTURE_USAGE_SAMPLING_BIT)) { + return true; + } + + return false; +} bool RasterizerStorageRD::free(RID p_rid) { if (texture_owner.owns(p_rid)) { @@ -2972,6 +3613,12 @@ bool RasterizerStorageRD::free(RID p_rid) { Mesh *mesh = mesh_owner.getornull(p_rid); mesh->instance_dependency.instance_notify_deleted(p_rid); mesh_owner.free(p_rid); + } else if (multimesh_owner.owns(p_rid)) { + _update_dirty_multimeshes(); + multimesh_allocate(p_rid, 0, VS::MULTIMESH_TRANSFORM_2D); + MultiMesh *multimesh = multimesh_owner.getornull(p_rid); + multimesh->instance_dependency.instance_notify_deleted(p_rid); + multimesh_owner.free(p_rid); } else if (reflection_probe_owner.owns(p_rid)) { ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_rid); reflection_probe->instance_dependency.instance_notify_deleted(p_rid); diff --git a/servers/visual/rasterizer_rd/rasterizer_storage_rd.h b/servers/visual/rasterizer_rd/rasterizer_storage_rd.h index 3cfd5601e8..ef22a6689b 100644 --- a/servers/visual/rasterizer_rd/rasterizer_storage_rd.h +++ b/servers/visual/rasterizer_rd/rasterizer_storage_rd.h @@ -62,7 +62,7 @@ public: struct MaterialData { void update_uniform_buffer(const Map &p_uniforms, const uint32_t *p_uniform_offsets, const Map &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color); - void update_textures(const Map &p_parameters, const Map &p_default_textures, const Vector &p_texture_uniforms, RID *p_textures); + void update_textures(const Map &p_parameters, const Map &p_default_textures, const Vector &p_texture_uniforms, RID *p_textures, bool p_use_linear_color); virtual void set_render_priority(int p_priority) = 0; virtual void set_next_pass(RID p_pass) = 0; @@ -135,6 +135,15 @@ private: RID proxy_to; Vector proxies; + + VS::TextureDetectCallback detect_3d_callback = nullptr; + void *detect_3d_callback_ud = nullptr; + + VS::TextureDetectCallback detect_normal_callback = nullptr; + void *detect_normal_callback_ud = nullptr; + + VS::TextureDetectRoughnessCallback detect_roughness_callback = nullptr; + void *detect_roughness_callback_ud = nullptr; }; struct TextureToRDFormat { @@ -281,6 +290,43 @@ private: RID mesh_default_rd_buffers[DEFAULT_RD_BUFFER_MAX]; + /* MultiMesh */ + struct MultiMesh { + RID mesh; + int instances = 0; + VS::MultimeshTransformFormat xform_format = VS::MULTIMESH_TRANSFORM_3D; + bool uses_colors = false; + bool uses_custom_data = false; + int visible_instances = -1; + AABB aabb; + bool aabb_dirty = false; + bool buffer_set = false; + uint32_t stride_cache = 0; + uint32_t color_offset_cache = 0; + uint32_t custom_data_offset_cache = 0; + + PoolVector data_cache; //used if individual setting is used + bool *data_cache_dirty_regions = nullptr; + uint32_t data_cache_used_dirty_regions = 0; + + RID buffer; //storage buffer + RID uniform_set_3d; + + bool dirty = false; + MultiMesh *dirty_list = nullptr; + + RasterizerScene::InstanceDependency instance_dependency; + }; + + mutable RID_Owner multimesh_owner; + + MultiMesh *multimesh_dirty_list = nullptr; + + _FORCE_INLINE_ void _multimesh_make_local(MultiMesh *multimesh) const; + _FORCE_INLINE_ void _multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb); + _FORCE_INLINE_ void _multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb); + _FORCE_INLINE_ void _multimesh_re_create_aabb(MultiMesh *multimesh, const float *p_data, int p_instances); + void _update_dirty_multimeshes(); /* LIGHT */ struct Light { @@ -485,7 +531,7 @@ public: _FORCE_INLINE_ MaterialData *material_get_data(RID p_material, ShaderType p_shader_type) { Material *material = material_owner.getornull(p_material); - if (material->shader_type != p_shader_type) { + if (!material || material->shader_type != p_shader_type) { return NULL; } else { return material->data; @@ -612,30 +658,69 @@ public: /* MULTIMESH API */ - virtual RID multimesh_create() { return RID(); } + RID multimesh_create(); - void multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, VS::MultimeshColorFormat p_color_format, VS::MultimeshCustomDataFormat p_data = VS::MULTIMESH_CUSTOM_DATA_NONE) {} - int multimesh_get_instance_count(RID p_multimesh) const { return 0; } + void multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false); + int multimesh_get_instance_count(RID p_multimesh) const; - void multimesh_set_mesh(RID p_multimesh, RID p_mesh) {} - void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform) {} - void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) {} - void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) {} - void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) {} + void multimesh_set_mesh(RID p_multimesh, RID p_mesh); + void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform); + void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform); + void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color); + void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color); - RID multimesh_get_mesh(RID p_multimesh) const { return RID(); } + RID multimesh_get_mesh(RID p_multimesh) const; - Transform multimesh_instance_get_transform(RID p_multimesh, int p_index) const { return Transform(); } - Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const { return Transform2D(); } - Color multimesh_instance_get_color(RID p_multimesh, int p_index) const { return Color(); } - Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const { return Color(); } + Transform multimesh_instance_get_transform(RID p_multimesh, int p_index) const; + Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const; + Color multimesh_instance_get_color(RID p_multimesh, int p_index) const; + Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const; - void multimesh_set_as_bulk_array(RID p_multimesh, const PoolVector &p_array) {} + void multimesh_set_buffer(RID p_multimesh, const PoolVector &p_buffer); + PoolVector multimesh_get_buffer(RID p_multimesh) const; - void multimesh_set_visible_instances(RID p_multimesh, int p_visible) {} - int multimesh_get_visible_instances(RID p_multimesh) const { return 0; } + void multimesh_set_visible_instances(RID p_multimesh, int p_visible); + int multimesh_get_visible_instances(RID p_multimesh) const; - AABB multimesh_get_aabb(RID p_multimesh) const { return AABB(); } + AABB multimesh_get_aabb(RID p_multimesh) const; + + _FORCE_INLINE_ VS::MultimeshTransformFormat multimesh_get_transform_format(RID p_multimesh) const { + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + return multimesh->xform_format; + } + + _FORCE_INLINE_ bool multimesh_uses_colors(RID p_multimesh) const { + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + return multimesh->uses_colors; + } + + _FORCE_INLINE_ bool multimesh_uses_custom_data(RID p_multimesh) const { + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + return multimesh->uses_custom_data; + } + + _FORCE_INLINE_ uint32_t multimesh_get_instances_to_draw(RID p_multimesh) const { + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + if (multimesh->visible_instances >= 0) { + return multimesh->visible_instances; + } + return multimesh->instances; + } + + _FORCE_INLINE_ RID multimesh_get_3d_uniform_set(RID p_multimesh, RID p_shader, uint32_t p_set) const { + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + if (!multimesh->uniform_set_3d.is_valid()) { + Vector uniforms; + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 0; + u.ids.push_back(multimesh->buffer); + uniforms.push_back(u); + multimesh->uniform_set_3d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set); + } + + return multimesh->uniform_set_3d; + } /* IMMEDIATE API */ @@ -919,7 +1004,7 @@ public: bool free(RID p_rid); - bool has_os_feature(const String &p_feature) const { return false; } + bool has_os_feature(const String &p_feature) const; void update_dirty_resources(); diff --git a/servers/visual/rasterizer_rd/shader_compiler_rd.cpp b/servers/visual/rasterizer_rd/shader_compiler_rd.cpp index 3908fbec3f..1aa48a82fc 100644 --- a/servers/visual/rasterizer_rd/shader_compiler_rd.cpp +++ b/servers/visual/rasterizer_rd/shader_compiler_rd.cpp @@ -482,8 +482,10 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge //code for functions for (int i = 0; i < pnode->functions.size(); i++) { SL::FunctionNode *fnode = pnode->functions[i].function; + function = fnode; current_func_name = fnode->name; function_code[fnode->name] = _dump_node_code(fnode->body, p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); + function = NULL; } //place functions in actual code @@ -763,7 +765,6 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge sampler_name = actions.custom_samplers[texture_uniform]; } else { if (shader->uniforms.has(texture_uniform)) { - print_line("shader from texture uniform " + itos(shader->uniforms[texture_uniform].filter) + ", " + itos(shader->uniforms[texture_uniform].repeat)); sampler_name = _get_sampler_name(shader->uniforms[texture_uniform].filter, shader->uniforms[texture_uniform].repeat); } else { bool found = false; diff --git a/servers/visual/rasterizer_rd/shaders/scene_forward.glsl b/servers/visual/rasterizer_rd/shaders/scene_forward.glsl index d64276a2bf..1bd11c4288 100644 --- a/servers/visual/rasterizer_rd/shaders/scene_forward.glsl +++ b/servers/visual/rasterizer_rd/shaders/scene_forward.glsl @@ -86,16 +86,50 @@ layout(location =8) out float dp_clip; void main() { instance_index = draw_call.instance_index; - - /*if (draw_call.instance_increment) { - instance_index += gl_InstanceIndex; - }*/ - - vec3 vertex = vertex_attrib; + vec4 instance_custom = vec4(0.0); +#if defined(COLOR_USED) + color_interp = color_attrib; +#endif mat4 world_matrix = instances.data[instance_index].transform; mat3 world_normal_matrix= mat3(instances.data[instance_index].normal_transform); + if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH)) { + //multimesh, instances are for it + uint offset = (instances.data[instance_index].flags>>INSTANCE_FLAGS_MULTIMESH_STRIDE_SHIFT)&INSTANCE_FLAGS_MULTIMESH_STRIDE_MASK; + offset*=gl_InstanceIndex; + + + mat4 matrix; + if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) { + mat4 matrix = mat4(transforms.data[offset+0],transforms.data[offset+1],vec4(0.0,0.0,1.0,0.0),vec4(0.0,0.0,0.0,1.0)); + offset+=2; + } else { + mat4 matrix = mat4(transforms.data[offset+0],transforms.data[offset+1],transforms.data[offset+2],vec4(0.0,0.0,0.0,1.0)); + offset+=3; + } + + if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_COLOR)) { +#ifdef COLOR_USED + color_interp *= transforms.data[offset]; +#endif + offset+=1; + } + + if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA)) { + instance_custom = transforms.data[offset]; + } + + //transposed, so multiply in opposite order + world_matrix = matrix * world_matrix; + world_normal_matrix = mat3(matrix) * world_normal_matrix; + + } else { + //not a multimesh, instances are for multiple draw calls + instance_index += gl_InstanceIndex; + } + + vec3 vertex = vertex_attrib; vec3 normal = normal_attrib; #if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED) @@ -103,10 +137,6 @@ void main() { float binormalf = tangent_attrib.a; #endif -#if defined(COLOR_USED) - color_interp = color_attrib; -#endif - #if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED) vec3 binormal = normalize(cross(normal, tangent) * binormalf); @@ -124,7 +154,7 @@ void main() { vec4 position; #endif - vec4 instance_custom = vec4(0.0); + mat4 projection_matrix = scene_data.projection_matrix; @@ -768,7 +798,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a transmission, #endif #ifdef LIGHT_RIM_USED - rim * omni_attenuation, rim_tint, + rim * spot_attenuation, rim_tint, #endif #ifdef LIGHT_CLEARCOAT_USED clearcoat, clearcoat_gloss, @@ -932,7 +962,7 @@ void main() { float normaldepth = 1.0; #if defined(SCREEN_UV_USED) - vec2 screen_uv = gl_FragCoord.xy * screen_pixel_size; + vec2 screen_uv = gl_FragCoord.xy * scene_data.screen_pixel_size; #endif float sss_strength = 0.0; @@ -1182,7 +1212,7 @@ FRAGMENT_SHADER_CODE transmission, #endif #ifdef LIGHT_RIM_USED - rim * omni_attenuation, rim_tint, + rim, rim_tint, #endif #ifdef LIGHT_CLEARCOAT_USED clearcoat, clearcoat_gloss, diff --git a/servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl b/servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl index d6b6aa4301..4d1a1c9495 100644 --- a/servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl +++ b/servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl @@ -118,11 +118,20 @@ layout(set=0,binding=8,std140) uniform SceneData { #endif } scene_data; -#define INSTANCE_FLAGS_FORWARD_MASK 3 +#define INSTANCE_FLAGS_FORWARD_MASK 0x7 #define INSTANCE_FLAGS_FORWARD_OMNI_LIGHT_SHIFT 3 #define INSTANCE_FLAGS_FORWARD_SPOT_LIGHT_SHIFT 6 #define INSTANCE_FLAGS_FORWARD_DECAL_SHIFT 9 +#define INSTANCE_FLAGS_MULTIMESH (1 << 12) +#define INSTANCE_FLAGS_MULTIMESH_FORMAT_2D (1 << 13) +#define INSTANCE_FLAGS_MULTIMESH_HAS_COLOR (1 << 14) +#define INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA (1 << 15) +#define INSTANCE_FLAGS_MULTIMESH_STRIDE_SHIFT 16 +//3 bits of stride +#define INSTANCE_FLAGS_MULTIMESH_STRIDE_MASK 0x7 + + struct InstanceData { mat4 transform; @@ -217,6 +226,11 @@ layout(set=0,binding=15,std430) buffer Skeletons { //layout(set = 1, binding = 0) uniform textureBuffer multimesh_transforms; +layout(set=1,binding=0,std430) buffer Transforms { + vec4 data[]; +} transforms; + + /* Set 2 Instancing (Multimesh) data */ #if 0 diff --git a/servers/visual/rasterizer_rd/shaders/tonemap.glsl b/servers/visual/rasterizer_rd/shaders/tonemap.glsl index 6797ff9f77..f54c938e24 100644 --- a/servers/visual/rasterizer_rd/shaders/tonemap.glsl +++ b/servers/visual/rasterizer_rd/shaders/tonemap.glsl @@ -145,7 +145,7 @@ vec3 tonemap_filmic(vec3 color, float white) { vec3 color_tonemapped = ((color * (A * color + C * B) + D * E) / (color * (A * color + B) + D * F)) - E / F; float white_tonemapped = ((white * (A * white + C * B) + D * E) / (white * (A * white + B) + D * F)) - E / F; - return color_tonemapped / white_tonemapped, vec3(0.0f), vec3(1.0f); + return color_tonemapped / white_tonemapped; } vec3 tonemap_aces(vec3 color, float white) { @@ -159,7 +159,7 @@ vec3 tonemap_aces(vec3 color, float white) { vec3 color_tonemapped = (color * (A * color + B)) / (color * (C * color + D) + E); float white_tonemapped = (white * (A * white + B)) / (white * (C * white + D) + E); - return color_tonemapped / white_tonemapped, vec3(0.0f), vec3(1.0f); + return color_tonemapped / white_tonemapped; } vec3 tonemap_reinhard(vec3 color, float white) { diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index c343e23881..5ef51e3e1a 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -307,6 +307,12 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = { { TK_HINT_WHITE_TEXTURE, "hint_white" }, { TK_HINT_BLACK_TEXTURE, "hint_black" }, { TK_HINT_NORMAL_TEXTURE, "hint_normal" }, + { TK_HINT_ROUGHNESS_NORMAL_TEXTURE, "hint_roughness_normal" }, + { TK_HINT_ROUGHNESS_R, "hint_roughness_r" }, + { TK_HINT_ROUGHNESS_G, "hint_roughness_g" }, + { TK_HINT_ROUGHNESS_B, "hint_roughness_b" }, + { TK_HINT_ROUGHNESS_A, "hint_roughness_a" }, + { TK_HINT_ROUGHNESS_GRAY, "hint_roughness_gray" }, { TK_HINT_ANISO_TEXTURE, "hint_aniso" }, { TK_HINT_ALBEDO_TEXTURE, "hint_albedo" }, { TK_HINT_BLACK_ALBEDO_TEXTURE, "hint_black_albedo" }, @@ -5171,6 +5177,18 @@ Error ShaderLanguage::_parse_shader(const Map &p_funct uniform2.hint = ShaderNode::Uniform::HINT_BLACK; } else if (tk.type == TK_HINT_NORMAL_TEXTURE) { uniform2.hint = ShaderNode::Uniform::HINT_NORMAL; + } else if (tk.type == TK_HINT_ROUGHNESS_NORMAL_TEXTURE) { + uniform2.hint = ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL; + } else if (tk.type == TK_HINT_ROUGHNESS_R) { + uniform2.hint = ShaderNode::Uniform::HINT_ROUGHNESS_R; + } else if (tk.type == TK_HINT_ROUGHNESS_G) { + uniform2.hint = ShaderNode::Uniform::HINT_ROUGHNESS_G; + } else if (tk.type == TK_HINT_ROUGHNESS_B) { + uniform2.hint = ShaderNode::Uniform::HINT_ROUGHNESS_B; + } else if (tk.type == TK_HINT_ROUGHNESS_A) { + uniform2.hint = ShaderNode::Uniform::HINT_ROUGHNESS_A; + } else if (tk.type == TK_HINT_ROUGHNESS_GRAY) { + uniform2.hint = ShaderNode::Uniform::HINT_ROUGHNESS_GRAY; } else if (tk.type == TK_HINT_ANISO_TEXTURE) { uniform2.hint = ShaderNode::Uniform::HINT_ANISO; } else if (tk.type == TK_HINT_ALBEDO_TEXTURE) { diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h index 3a1ded0547..da5b0600ff 100644 --- a/servers/visual/shader_language.h +++ b/servers/visual/shader_language.h @@ -150,6 +150,12 @@ public: TK_HINT_WHITE_TEXTURE, TK_HINT_BLACK_TEXTURE, TK_HINT_NORMAL_TEXTURE, + TK_HINT_ROUGHNESS_NORMAL_TEXTURE, + TK_HINT_ROUGHNESS_R, + TK_HINT_ROUGHNESS_G, + TK_HINT_ROUGHNESS_B, + TK_HINT_ROUGHNESS_A, + TK_HINT_ROUGHNESS_GRAY, TK_HINT_ANISO_TEXTURE, TK_HINT_ALBEDO_TEXTURE, TK_HINT_BLACK_ALBEDO_TEXTURE, @@ -576,6 +582,12 @@ public: HINT_ALBEDO, HINT_BLACK_ALBEDO, HINT_NORMAL, + HINT_ROUGHNESS_NORMAL, + HINT_ROUGHNESS_R, + HINT_ROUGHNESS_G, + HINT_ROUGHNESS_B, + HINT_ROUGHNESS_A, + HINT_ROUGHNESS_GRAY, HINT_BLACK, HINT_WHITE, HINT_ANISO, diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index be19a935e9..8543289083 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -248,7 +248,7 @@ public: BIND0R(RID, multimesh_create) - BIND5(multimesh_allocate, RID, int, MultimeshTransformFormat, MultimeshColorFormat, MultimeshCustomDataFormat) + BIND5(multimesh_allocate, RID, int, MultimeshTransformFormat, bool, bool) BIND1RC(int, multimesh_get_instance_count, RID) BIND2(multimesh_set_mesh, RID, RID) @@ -265,7 +265,8 @@ public: BIND2RC(Color, multimesh_instance_get_color, RID, int) BIND2RC(Color, multimesh_instance_get_custom_data, RID, int) - BIND2(multimesh_set_as_bulk_array, RID, const PoolVector &) + BIND2(multimesh_set_buffer, RID, const PoolVector &) + BIND1RC(PoolVector, multimesh_get_buffer, RID) BIND2(multimesh_set_visible_instances, RID, int) BIND1RC(int, multimesh_get_visible_instances, RID) diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp index 3f33ec945c..96831d1cc2 100644 --- a/servers/visual/visual_server_scene.cpp +++ b/servers/visual/visual_server_scene.cpp @@ -1863,7 +1863,6 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca bool keep = false; if ((camera_layer_mask & ins->layer_mask) == 0) { - //failure } else if (ins->base_type == VS::INSTANCE_LIGHT && ins->visible) { diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index d8cd6771c1..a58d36f279 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -175,7 +175,7 @@ public: FUNCRID(multimesh) - FUNC5(multimesh_allocate, RID, int, MultimeshTransformFormat, MultimeshColorFormat, MultimeshCustomDataFormat) + FUNC5(multimesh_allocate, RID, int, MultimeshTransformFormat, bool, bool) FUNC1RC(int, multimesh_get_instance_count, RID) FUNC2(multimesh_set_mesh, RID, RID) @@ -192,7 +192,8 @@ public: FUNC2RC(Color, multimesh_instance_get_color, RID, int) FUNC2RC(Color, multimesh_instance_get_custom_data, RID, int) - FUNC2(multimesh_set_as_bulk_array, RID, const PoolVector &) + FUNC2(multimesh_set_buffer, RID, const PoolVector &) + FUNC1RC(PoolVector, multimesh_get_buffer, RID) FUNC2(multimesh_set_visible_instances, RID, int) FUNC1RC(int, multimesh_get_visible_instances, RID) diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index 66e0d67938..0c72a09a91 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -1638,7 +1638,7 @@ void VisualServer::_bind_methods() { ClassDB::bind_method(D_METHOD("mesh_clear", "mesh"), &VisualServer::mesh_clear); ClassDB::bind_method(D_METHOD("multimesh_create"), &VisualServer::multimesh_create); - ClassDB::bind_method(D_METHOD("multimesh_allocate", "multimesh", "instances", "transform_format", "color_format", "custom_data_format"), &VisualServer::multimesh_allocate, DEFVAL(MULTIMESH_CUSTOM_DATA_NONE)); + ClassDB::bind_method(D_METHOD("multimesh_allocate", "multimesh", "instances", "transform_format", "color_format", "custom_data_format"), &VisualServer::multimesh_allocate, DEFVAL(false), DEFVAL(false)); ClassDB::bind_method(D_METHOD("multimesh_get_instance_count", "multimesh"), &VisualServer::multimesh_get_instance_count); ClassDB::bind_method(D_METHOD("multimesh_set_mesh", "multimesh", "mesh"), &VisualServer::multimesh_set_mesh); ClassDB::bind_method(D_METHOD("multimesh_instance_set_transform", "multimesh", "index", "transform"), &VisualServer::multimesh_instance_set_transform); @@ -1653,7 +1653,8 @@ void VisualServer::_bind_methods() { ClassDB::bind_method(D_METHOD("multimesh_instance_get_custom_data", "multimesh", "index"), &VisualServer::multimesh_instance_get_custom_data); ClassDB::bind_method(D_METHOD("multimesh_set_visible_instances", "multimesh", "visible"), &VisualServer::multimesh_set_visible_instances); ClassDB::bind_method(D_METHOD("multimesh_get_visible_instances", "multimesh"), &VisualServer::multimesh_get_visible_instances); - ClassDB::bind_method(D_METHOD("multimesh_set_as_bulk_array", "multimesh", "array"), &VisualServer::multimesh_set_as_bulk_array); + ClassDB::bind_method(D_METHOD("multimesh_set_buffer", "multimesh", "buffer"), &VisualServer::multimesh_set_buffer); + ClassDB::bind_method(D_METHOD("multimesh_get_buffer", "multimesh"), &VisualServer::multimesh_get_buffer); #ifndef _3D_DISABLED ClassDB::bind_method(D_METHOD("immediate_create"), &VisualServer::immediate_create); ClassDB::bind_method(D_METHOD("immediate_begin", "immediate", "primitive", "texture"), &VisualServer::immediate_begin, DEFVAL(RID())); @@ -2151,12 +2152,6 @@ void VisualServer::_bind_methods() { BIND_ENUM_CONSTANT(MULTIMESH_TRANSFORM_2D); BIND_ENUM_CONSTANT(MULTIMESH_TRANSFORM_3D); - BIND_ENUM_CONSTANT(MULTIMESH_COLOR_NONE); - BIND_ENUM_CONSTANT(MULTIMESH_COLOR_8BIT); - BIND_ENUM_CONSTANT(MULTIMESH_COLOR_FLOAT); - BIND_ENUM_CONSTANT(MULTIMESH_CUSTOM_DATA_NONE); - BIND_ENUM_CONSTANT(MULTIMESH_CUSTOM_DATA_8BIT); - BIND_ENUM_CONSTANT(MULTIMESH_CUSTOM_DATA_FLOAT); BIND_ENUM_CONSTANT(REFLECTION_PROBE_UPDATE_ONCE); BIND_ENUM_CONSTANT(REFLECTION_PROBE_UPDATE_ALWAYS); diff --git a/servers/visual_server.h b/servers/visual_server.h index 2ab521c7c0..06dba99860 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -319,21 +319,7 @@ public: MULTIMESH_TRANSFORM_3D, }; - enum MultimeshColorFormat { - MULTIMESH_COLOR_NONE, - MULTIMESH_COLOR_8BIT, - MULTIMESH_COLOR_FLOAT, - MULTIMESH_COLOR_MAX, - }; - - enum MultimeshCustomDataFormat { - MULTIMESH_CUSTOM_DATA_NONE, - MULTIMESH_CUSTOM_DATA_8BIT, - MULTIMESH_CUSTOM_DATA_FLOAT, - MULTIMESH_CUSTOM_DATA_MAX, - }; - - virtual void multimesh_allocate(RID p_multimesh, int p_instances, MultimeshTransformFormat p_transform_format, MultimeshColorFormat p_color_format, MultimeshCustomDataFormat p_data_format = MULTIMESH_CUSTOM_DATA_NONE) = 0; + virtual void multimesh_allocate(RID p_multimesh, int p_instances, MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) = 0; virtual int multimesh_get_instance_count(RID p_multimesh) const = 0; virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) = 0; @@ -350,7 +336,8 @@ public: virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const = 0; virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const = 0; - virtual void multimesh_set_as_bulk_array(RID p_multimesh, const PoolVector &p_array) = 0; + virtual void multimesh_set_buffer(RID p_multimesh, const PoolVector &p_buffer) = 0; + virtual PoolVector multimesh_get_buffer(RID p_multimesh) const = 0; virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) = 0; virtual int multimesh_get_visible_instances(RID p_multimesh) const = 0; @@ -1100,8 +1087,6 @@ VARIANT_ENUM_CAST(VisualServer::CanvasOccluderPolygonCullMode); VARIANT_ENUM_CAST(VisualServer::RenderInfo); VARIANT_ENUM_CAST(VisualServer::Features); VARIANT_ENUM_CAST(VisualServer::MultimeshTransformFormat); -VARIANT_ENUM_CAST(VisualServer::MultimeshColorFormat); -VARIANT_ENUM_CAST(VisualServer::MultimeshCustomDataFormat); VARIANT_ENUM_CAST(VisualServer::LightOmniShadowMode); VARIANT_ENUM_CAST(VisualServer::LightDirectionalShadowMode); VARIANT_ENUM_CAST(VisualServer::LightDirectionalShadowDepthRangeMode);