summaryrefslogtreecommitdiff
path: root/servers
diff options
context:
space:
mode:
authorJuan Linietsky <reduzio@gmail.com>2019-09-14 00:37:42 -0300
committerJuan Linietsky <reduzio@gmail.com>2020-02-11 12:01:22 +0100
commit6deffa62fbd1e91873afa663630b788b9ffabee3 (patch)
treee77c1a67c8b8ddb64429280131502f64c8cd8e8c /servers
parent9d7b7f931b6924399903e4954a0c32d59c15d4c3 (diff)
Several fixes to 3D rendering, and multimesh implementation.
Diffstat (limited to 'servers')
-rw-r--r--servers/visual/rasterizer.h6
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_canvas_rd.cpp2
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp90
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h12
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp3
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp655
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_storage_rd.h125
-rw-r--r--servers/visual/rasterizer_rd/shader_compiler_rd.cpp3
-rw-r--r--servers/visual/rasterizer_rd/shaders/scene_forward.glsl58
-rw-r--r--servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl16
-rw-r--r--servers/visual/rasterizer_rd/shaders/tonemap.glsl4
-rw-r--r--servers/visual/shader_language.cpp18
-rw-r--r--servers/visual/shader_language.h12
-rw-r--r--servers/visual/visual_server_raster.h5
-rw-r--r--servers/visual/visual_server_scene.cpp1
-rw-r--r--servers/visual/visual_server_wrap_mt.h5
-rw-r--r--servers/visual_server.cpp11
-rw-r--r--servers/visual_server.h21
18 files changed, 952 insertions, 95 deletions
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<float> &p_array) = 0;
+ virtual void multimesh_set_buffer(RID p_multimesh, const PoolVector<float> &p_buffer) = 0;
+ virtual PoolVector<float> 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 Map<StringName, V
if (p_textures_dirty && tex_uniform_count) {
- update_textures(p_parameters, shader_data->default_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 Map<StringN
if (p_textures_dirty && tex_uniform_count) {
- update_textures(p_parameters, shader_data->default_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 (storage->multimesh_get_instances_to_draw(inst->base) == 0) {
+ //not visible, 0 instances
+ continue;
+ }
- if (multi_mesh->size == 0 || multi_mesh->visible_instances == 0)
+ RID mesh = storage->multimesh_get_mesh(inst->base);
+ if (!mesh.is_valid()) {
continue;
+ }
- RasterizerStorageGLES3::Mesh *mesh = storage->mesh_owner.getornull(multi_mesh->mesh);
- if (!mesh)
- continue; //mesh not assigned
+ const RID *materials = NULL;
+ uint32_t surface_count;
- int ssize = mesh->surfaces.size();
+ materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count);
+ if (!materials) {
+ continue; //nothing to do
+ }
- for (int j = 0; j < ssize; j++) {
+ for (uint32_t j = 0; j < surface_count; j++) {
- RasterizerStorageGLES3::Surface *s = mesh->surfaces[j];
- _add_geometry(s, inst, multi_mesh, -1, p_depth_pass, p_shadow_pass);
+ 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";
@@ -2698,6 +2741,17 @@ RasterizerSceneForwardRD::RasterizerSceneForwardRD(RasterizerStorageRD *p_storag
}
{
+ default_vec4_xform_buffer = RD::get_singleton()->storage_buffer_create(256);
+ Vector<RD::Uniform> 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;
sampler.mag_filter = RD::SAMPLER_FILTER_LINEAR;
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<Image> RasterizerStorageRD::_validate_texture_format(const Ref<Image> &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<VS::TextureInfo> *r_info) {
}
@@ -1611,9 +1626,14 @@ void RasterizerStorageRD::MaterialData::update_uniform_buffer(const Map<StringNa
}
}
-void RasterizerStorageRD::MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, RID> &p_default_textures, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures) {
+void RasterizerStorageRD::MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, RID> &p_default_textures, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &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 Map<StringName, Va
} break;
}
} else {
- bool srgb = p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ALBEDO || p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO;
- rd_texture = singleton->texture_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 Map<StringName, Va
p_textures[i] = rd_texture;
}
+#ifdef TOOLS_ENABLED
+ if (roughness_detect_texture && normal_detect_texture && normal_detect_texture->path != 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<float>();
+ 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<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer);
+ PoolVector<uint8_t>::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<float>::Write w = multimesh->data_cache.write();
+
+ if (multimesh->buffer_set) {
+ PoolVector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer);
+ {
+
+ PoolVector<uint8_t>::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<float>::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<float>::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<float>::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<float>::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<float>::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<float>::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<float>::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<float>::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<float> &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<float>::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<float>::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<float> RasterizerStorageRD::multimesh_get_buffer(RID p_multimesh) const {
+ MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
+ ERR_FAIL_COND_V(!multimesh, PoolVector<float>());
+ if (multimesh->buffer.is_null()) {
+ return PoolVector<float>();
+ } else if (multimesh->data_cache.size()) {
+ return multimesh->data_cache;
+ } else {
+ //get from memory
+
+ PoolVector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer);
+ PoolVector<float> ret;
+ ret.resize(multimesh->instances);
+ {
+ PoolVector<float>::Write w = multimesh->data_cache.write();
+ PoolVector<uint8_t>::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<RasterizerStorageRD *>(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<float>::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<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color);
- void update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, RID> &p_default_textures, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures);
+ void update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, RID> &p_default_textures, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &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<RID> 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<float> 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> 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<float> &p_array) {}
+ void multimesh_set_buffer(RID p_multimesh, const PoolVector<float> &p_buffer);
+ PoolVector<float> 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<RD::Uniform> 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<StringName, FunctionInfo> &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<float> &)
+ BIND2(multimesh_set_buffer, RID, const PoolVector<float> &)
+ BIND1RC(PoolVector<float>, 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<float> &)
+ FUNC2(multimesh_set_buffer, RID, const PoolVector<float> &)
+ FUNC1RC(PoolVector<float>, 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<float> &p_array) = 0;
+ virtual void multimesh_set_buffer(RID p_multimesh, const PoolVector<float> &p_buffer) = 0;
+ virtual PoolVector<float> 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);