summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/vulkan/rendering_device_vulkan.cpp99
-rw-r--r--drivers/vulkan/rendering_device_vulkan.h5
-rw-r--r--editor/editor_node.cpp3
-rw-r--r--editor/editor_plugin.cpp1
-rw-r--r--editor/import/editor_import_collada.cpp2
-rw-r--r--editor/import/editor_scene_importer_gltf.cpp9
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp3
-rw-r--r--editor/plugins/collision_polygon_editor_plugin.cpp4
-rw-r--r--editor/plugins/editor_preview_plugins.cpp3
-rw-r--r--editor/plugins/spatial_editor_plugin.cpp3
-rw-r--r--editor/plugins/sprite_editor_plugin.cpp2
-rw-r--r--main/main.cpp4
-rw-r--r--modules/gridmap/grid_map_editor_plugin.cpp3
-rw-r--r--scene/3d/ray_cast.cpp3
-rw-r--r--scene/3d/soft_body.cpp11
-rw-r--r--scene/main/scene_tree.cpp6
-rw-r--r--scene/main/viewport.cpp86
-rw-r--r--scene/main/viewport.h30
-rw-r--r--scene/resources/mesh.cpp397
-rw-r--r--scene/resources/mesh.h30
-rw-r--r--scene/resources/primitive_meshes.cpp27
-rw-r--r--scene/resources/primitive_meshes.h4
-rw-r--r--scene/resources/surface_tool.cpp2
-rw-r--r--servers/visual/rasterizer.h53
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_canvas_rd.cpp72
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_canvas_rd.h6
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp (renamed from servers/visual/rasterizer_rd/effects_rd.cpp)12
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_effects_rd.h (renamed from servers/visual/rasterizer_rd/effects_rd.h)10
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_rd.cpp3
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp2002
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h451
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp41
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_scene_rd.h105
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp524
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_storage_rd.h278
-rw-r--r--servers/visual/rasterizer_rd/render_pipeline_vertex_format_cache_rd.cpp5
-rw-r--r--servers/visual/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h5
-rw-r--r--servers/visual/rasterizer_rd/shaders/SCsub2
-rw-r--r--servers/visual/rasterizer_rd/shaders/scene_forward.glsl762
-rw-r--r--servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl141
-rw-r--r--servers/visual/rendering_device.h3
-rw-r--r--servers/visual/shader_types.cpp12
-rw-r--r--servers/visual/visual_server_raster.h29
-rw-r--r--servers/visual/visual_server_scene.cpp45
-rw-r--r--servers/visual/visual_server_scene.h8
-rw-r--r--servers/visual/visual_server_viewport.cpp105
-rw-r--r--servers/visual/visual_server_viewport.h11
-rw-r--r--servers/visual/visual_server_wrap_mt.h26
-rw-r--r--servers/visual_server.cpp375
-rw-r--r--servers/visual_server.h75
50 files changed, 4879 insertions, 1019 deletions
diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp
index 265dfc69d4..82ab8d6c2f 100644
--- a/drivers/vulkan/rendering_device_vulkan.cpp
+++ b/drivers/vulkan/rendering_device_vulkan.cpp
@@ -3041,7 +3041,7 @@ RID RenderingDeviceVulkan::vertex_buffer_create(uint32_t p_size_bytes, const Poo
ERR_FAIL_COND_V(p_data.size() && (uint32_t)p_data.size() != p_size_bytes, RID());
Buffer buffer;
- _buffer_allocate(&buffer, p_size_bytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
+ _buffer_allocate(&buffer, p_size_bytes, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
if (p_data.size()) {
uint64_t data_size = p_data.size();
PoolVector<uint8_t>::Read r = p_data.read();
@@ -3202,7 +3202,7 @@ RID RenderingDeviceVulkan::index_buffer_create(uint32_t p_index_count, IndexBuff
#else
index_buffer.max_index = 0xFFFFFFFF;
#endif
- _buffer_allocate(&index_buffer, size_bytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
+ _buffer_allocate(&index_buffer, size_bytes, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
if (p_data.size()) {
uint64_t data_size = p_data.size();
PoolVector<uint8_t>::Read r = p_data.read();
@@ -3485,8 +3485,9 @@ RID RenderingDeviceVulkan::shader_create(const Vector<ShaderStageData> &p_stages
push_constant.push_constant_size = 0;
push_constant.push_constants_vk_stage = 0;
- Vector<int> vertex_input_locations;
- int fragment_outputs = 0;
+ uint32_t vertex_input_mask = 0;
+
+ uint32_t fragment_outputs = 0;
uint32_t stages_processed = 0;
@@ -3660,6 +3661,29 @@ RID RenderingDeviceVulkan::shader_create(const Vector<ShaderStageData> &p_stages
}
}
+ if (stage == SHADER_STAGE_VERTEX) {
+
+ uint32_t iv_count = 0;
+ result = spvReflectEnumerateInputVariables(&module, &iv_count, NULL);
+ ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, RID(),
+ "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_stages[i].shader_stage]) + "' failed enumerating input variables.");
+
+ if (iv_count) {
+ Vector<SpvReflectInterfaceVariable *> input_vars;
+ input_vars.resize(iv_count);
+
+ result = spvReflectEnumerateOutputVariables(&module, &iv_count, input_vars.ptrw());
+ ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, RID(),
+ "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_stages[i].shader_stage]) + "' failed obtaining input variables.");
+
+ for (uint32_t j = 0; j < iv_count; j++) {
+ if (input_vars[j]) {
+ vertex_input_mask |= (1 << uint32_t(input_vars[j]->location));
+ }
+ }
+ }
+ }
+
if (stage == SHADER_STAGE_FRAGMENT) {
uint32_t ov_count = 0;
@@ -3726,7 +3750,7 @@ RID RenderingDeviceVulkan::shader_create(const Vector<ShaderStageData> &p_stages
Shader shader;
- shader.vertex_input_locations = vertex_input_locations;
+ shader.vertex_input_mask = vertex_input_mask;
shader.fragment_outputs = fragment_outputs;
shader.push_constant = push_constant;
@@ -3871,10 +3895,10 @@ RID RenderingDeviceVulkan::shader_create(const Vector<ShaderStageData> &p_stages
return shader_owner.make_rid(shader);
}
-Vector<int> RenderingDeviceVulkan::shader_get_vertex_input_locations_used(RID p_shader) {
+uint32_t RenderingDeviceVulkan::shader_get_vertex_input_attribute_mask(RID p_shader) {
const Shader *shader = shader_owner.getornull(p_shader);
- ERR_FAIL_COND_V(!shader, Vector<int>());
- return shader->vertex_input_locations;
+ ERR_FAIL_COND_V(!shader, 0);
+ return shader->vertex_input_mask;
}
/******************/
@@ -3929,7 +3953,7 @@ RID RenderingDeviceVulkan::texture_buffer_create(uint32_t p_size_elements, DataF
ERR_FAIL_COND_V(p_data.size() && (uint32_t)p_data.size() != size_bytes, RID());
TextureBuffer texture_buffer;
- Error err = _buffer_allocate(&texture_buffer.buffer, size_bytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
+ Error err = _buffer_allocate(&texture_buffer.buffer, size_bytes, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
ERR_FAIL_COND_V(err != OK, RID());
if (p_data.size()) {
@@ -4488,6 +4512,49 @@ Error RenderingDeviceVulkan::buffer_update(RID p_buffer, uint32_t p_offset, uint
return err;
}
+PoolVector<uint8_t> RenderingDeviceVulkan::buffer_get_data(RID p_buffer) {
+
+ Buffer *buffer = NULL;
+ if (vertex_buffer_owner.owns(p_buffer)) {
+ buffer = vertex_buffer_owner.getornull(p_buffer);
+ } else if (index_buffer_owner.owns(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 {
+ ERR_FAIL_V_MSG(PoolVector<uint8_t>(), "Buffer is either invalid or this type of buffer can't be retrieved. Only Index and Vertex buffers allow retrieving.");
+ }
+
+ VkCommandBuffer command_buffer = frames[frame].setup_command_buffer;
+ Buffer tmp_buffer;
+ _buffer_allocate(&tmp_buffer, buffer->size, VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
+ VkBufferCopy region;
+ region.srcOffset = 0;
+ region.dstOffset = 0;
+ region.size = buffer->size;
+ vkCmdCopyBuffer(command_buffer, buffer->buffer, tmp_buffer.buffer, 1, &region); //dst buffer is in CPU, but I wonder if src buffer needs a barrier for this..
+ //flush everything so memory can be safely mapped
+ _flush(true, false);
+
+ void *buffer_mem;
+ VkResult vkerr = vmaMapMemory(allocator, tmp_buffer.allocation, &buffer_mem);
+ if (vkerr) {
+ ERR_FAIL_V(PoolVector<uint8_t>());
+ }
+
+ PoolVector<uint8_t> buffer_data;
+ {
+
+ buffer_data.resize(buffer->size);
+ PoolVector<uint8_t>::Write w = buffer_data.write();
+ copymem(w.ptr(), buffer_mem, buffer->size);
+ }
+
+ _buffer_free(&tmp_buffer);
+
+ return buffer_data;
+}
+
/*************************/
/**** RENDER PIPELINE ****/
/*************************/
@@ -4523,17 +4590,19 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma
pipeline_vertex_input_state_create_info = vd.create_info;
//validate with inputs
- for (int i = 0; i < shader->vertex_input_locations.size(); i++) {
- uint32_t location = shader->vertex_input_locations[i];
+ for (uint32_t i = 0; i < 32; i++) {
+ if (!(shader->vertex_input_mask & (1 << i))) {
+ continue;
+ }
bool found = false;
for (int j = 0; j < vd.vertex_formats.size(); j++) {
- if (vd.vertex_formats[j].location == location) {
+ if (vd.vertex_formats[j].location == i) {
found = true;
}
}
ERR_FAIL_COND_V_MSG(!found, RID(),
- "Shader vertex input location (" + itos(location) + ") not provided in vertex input description for pipeline creation.");
+ "Shader vertex input location (" + itos(i) + ") not provided in vertex input description for pipeline creation.");
}
} else {
@@ -4546,8 +4615,8 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma
pipeline_vertex_input_state_create_info.vertexAttributeDescriptionCount = 0;
pipeline_vertex_input_state_create_info.pVertexAttributeDescriptions = NULL;
- ERR_FAIL_COND_V_MSG(shader->vertex_input_locations.size(), RID(),
- "Shader contains vertex inputs (" + itos(shader->vertex_input_locations.size()) + ") but no vertex input description was provided for pipeline creation.");
+ ERR_FAIL_COND_V_MSG(shader->vertex_input_mask != 0, RID(),
+ "Shader contains vertex inputs, but no vertex input description was provided for pipeline creation.");
}
//input assembly
diff --git a/drivers/vulkan/rendering_device_vulkan.h b/drivers/vulkan/rendering_device_vulkan.h
index af144a7f6b..2cd72fbac4 100644
--- a/drivers/vulkan/rendering_device_vulkan.h
+++ b/drivers/vulkan/rendering_device_vulkan.h
@@ -506,7 +506,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
VkDescriptorSetLayout descriptor_set_layout;
};
- Vector<int> vertex_input_locations; //inputs used, this is mostly for validation
+ uint32_t vertex_input_mask; //inputs used, this is mostly for validation
int fragment_outputs;
struct PushConstant {
@@ -894,7 +894,7 @@ public:
/****************/
virtual RID shader_create(const Vector<ShaderStageData> &p_stages);
- virtual Vector<int> shader_get_vertex_input_locations_used(RID p_shader);
+ virtual uint32_t shader_get_vertex_input_attribute_mask(RID p_shader);
/*****************/
/**** UNIFORM ****/
@@ -908,6 +908,7 @@ public:
virtual bool uniform_set_is_valid(RID p_uniform_set);
virtual Error buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const void *p_data, bool p_sync_with_draw = false); //works for any buffer
+ virtual PoolVector<uint8_t> buffer_get_data(RID p_buffer);
/*************************/
/**** RENDER PIPELINE ****/
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 856bfe5f44..f4749da309 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -363,8 +363,6 @@ void EditorNode::_notification(int p_what) {
Engine::get_singleton()->set_editor_hint(true);
OS::get_singleton()->set_low_processor_usage_mode_sleep_usec(int(EDITOR_GET("interface/editor/low_processor_mode_sleep_usec")));
- get_tree()->get_root()->set_usage(Viewport::USAGE_2D_NO_SAMPLING); //reduce memory usage
- get_tree()->get_root()->set_disable_3d(true);
get_tree()->get_root()->set_as_audio_listener(false);
get_tree()->get_root()->set_as_audio_listener_2d(false);
get_tree()->set_auto_accept_quit(false);
@@ -6059,7 +6057,6 @@ EditorNode::EditorNode() {
scene_root = memnew(Viewport);
//scene_root->set_usage(Viewport::USAGE_2D); canvas BG mode prevents usage of this as 2D
- scene_root->set_disable_3d(true);
VisualServer::get_singleton()->viewport_set_hide_scenario(scene_root->get_viewport_rid(), true);
scene_root->set_disable_input(true);
diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp
index 69a2344bc0..ce847d02eb 100644
--- a/editor/editor_plugin.cpp
+++ b/editor/editor_plugin.cpp
@@ -68,7 +68,6 @@ Vector<Ref<Texture2D> > EditorInterface::make_mesh_previews(const Vector<Ref<Mes
RID viewport = VS::get_singleton()->viewport_create();
VS::get_singleton()->viewport_set_update_mode(viewport, VS::VIEWPORT_UPDATE_ALWAYS);
- VS::get_singleton()->viewport_set_vflip(viewport, true);
VS::get_singleton()->viewport_set_scenario(viewport, scenario);
VS::get_singleton()->viewport_set_size(viewport, size, size);
VS::get_singleton()->viewport_set_transparent_background(viewport, true);
diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp
index bf293c3a5e..f1e54739b3 100644
--- a/editor/import/editor_import_collada.cpp
+++ b/editor/import/editor_import_collada.cpp
@@ -984,7 +984,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_me
mr.push_back(a);
}
- p_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, d, mr, p_use_compression ? Mesh::ARRAY_COMPRESS_DEFAULT : 0);
+ p_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, d, mr, Dictionary(), p_use_compression ? Mesh::ARRAY_COMPRESS_DEFAULT : 0);
if (material.is_valid()) {
if (p_use_mesh_material) {
diff --git a/editor/import/editor_scene_importer_gltf.cpp b/editor/import/editor_scene_importer_gltf.cpp
index 3239cadbe4..7d5fd9be75 100644
--- a/editor/import/editor_scene_importer_gltf.cpp
+++ b/editor/import/editor_scene_importer_gltf.cpp
@@ -984,14 +984,15 @@ Error EditorSceneImporterGLTF::_parse_meshes(GLTFState &state) {
static const Mesh::PrimitiveType primitives2[7] = {
Mesh::PRIMITIVE_POINTS,
Mesh::PRIMITIVE_LINES,
+ Mesh::PRIMITIVE_LINES, //loop not supported, should ce converted
Mesh::PRIMITIVE_LINES,
- Mesh::PRIMITIVE_LINES,
- Mesh::PRIMITIVE_TRIANGLES,
- Mesh::PRIMITIVE_TRIANGLES,
Mesh::PRIMITIVE_TRIANGLES,
+ Mesh::PRIMITIVE_TRIANGLE_STRIP,
+ Mesh::PRIMITIVE_TRIANGLES, //fan not supported, should be converted
#ifndef _MSC_VER
-#warning these will have to be decomposed into proper primitive now that lineloop/strip,etc no longer supported
+#warning line loop and triangle fan are not supported and need to be converted to lines and triangles
#endif
+
};
primitive = primitives2[mode];
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index 5e69ce4e69..d8bbac9c49 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -1322,11 +1322,10 @@ void AnimationPlayerEditor::_allocate_onion_layers() {
// Each capture is a viewport with a canvas item attached that renders a full-size rect with the contents of the main viewport.
onion.captures.write[i] = VS::get_singleton()->viewport_create();
- VS::get_singleton()->viewport_set_usage(onion.captures[i], VS::VIEWPORT_USAGE_2D);
+
VS::get_singleton()->viewport_set_size(onion.captures[i], capture_size.width, capture_size.height);
VS::get_singleton()->viewport_set_update_mode(onion.captures[i], VS::VIEWPORT_UPDATE_ALWAYS);
VS::get_singleton()->viewport_set_transparent_background(onion.captures[i], !is_present);
- VS::get_singleton()->viewport_set_vflip(onion.captures[i], true);
VS::get_singleton()->viewport_attach_canvas(onion.captures[i], onion.capture.canvas);
}
diff --git a/editor/plugins/collision_polygon_editor_plugin.cpp b/editor/plugins/collision_polygon_editor_plugin.cpp
index 612b21204d..32075e82be 100644
--- a/editor/plugins/collision_polygon_editor_plugin.cpp
+++ b/editor/plugins/collision_polygon_editor_plugin.cpp
@@ -463,9 +463,7 @@ void Polygon3DEditor::_polygon_draw() {
imgeom->end();
- while (m->get_surface_count()) {
- m->surface_remove(0);
- }
+ m->clear_surfaces();
if (poly.size() == 0)
return;
diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp
index 2037c17b89..6e8aef0aea 100644
--- a/editor/plugins/editor_preview_plugins.cpp
+++ b/editor/plugins/editor_preview_plugins.cpp
@@ -370,7 +370,6 @@ EditorMaterialPreviewPlugin::EditorMaterialPreviewPlugin() {
VS::get_singleton()->viewport_set_size(viewport, 128, 128);
VS::get_singleton()->viewport_set_transparent_background(viewport, true);
VS::get_singleton()->viewport_set_active(viewport, true);
- VS::get_singleton()->viewport_set_vflip(viewport, true);
viewport_texture = VS::get_singleton()->viewport_get_texture(viewport);
camera = VS::get_singleton()->camera_create();
@@ -773,7 +772,6 @@ EditorMeshPreviewPlugin::EditorMeshPreviewPlugin() {
viewport = VS::get_singleton()->viewport_create();
VS::get_singleton()->viewport_set_update_mode(viewport, VS::VIEWPORT_UPDATE_DISABLED);
- VS::get_singleton()->viewport_set_vflip(viewport, true);
VS::get_singleton()->viewport_set_scenario(viewport, scenario);
VS::get_singleton()->viewport_set_size(viewport, 128, 128);
VS::get_singleton()->viewport_set_transparent_background(viewport, true);
@@ -904,7 +902,6 @@ EditorFontPreviewPlugin::EditorFontPreviewPlugin() {
viewport = VS::get_singleton()->viewport_create();
VS::get_singleton()->viewport_set_update_mode(viewport, VS::VIEWPORT_UPDATE_DISABLED);
- VS::get_singleton()->viewport_set_vflip(viewport, true);
VS::get_singleton()->viewport_set_size(viewport, 128, 128);
VS::get_singleton()->viewport_set_active(viewport, true);
viewport_texture = VS::get_singleton()->viewport_get_texture(viewport);
diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp
index c07983b647..e062246665 100644
--- a/editor/plugins/spatial_editor_plugin.cpp
+++ b/editor/plugins/spatial_editor_plugin.cpp
@@ -2272,9 +2272,6 @@ void SpatialEditorViewport::_notification(int p_what) {
int msaa_mode = ProjectSettings::get_singleton()->get("rendering/quality/filters/msaa");
viewport->set_msaa(Viewport::MSAA(msaa_mode));
- bool hdr = ProjectSettings::get_singleton()->get("rendering/quality/depth/hdr");
- viewport->set_hdr(hdr);
-
bool show_info = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_INFORMATION));
info_label->set_visible(show_info);
diff --git a/editor/plugins/sprite_editor_plugin.cpp b/editor/plugins/sprite_editor_plugin.cpp
index 9fd9fefee6..2736bbfd3a 100644
--- a/editor/plugins/sprite_editor_plugin.cpp
+++ b/editor/plugins/sprite_editor_plugin.cpp
@@ -330,7 +330,7 @@ void SpriteEditor::_convert_to_mesh_2d_node() {
a[Mesh::ARRAY_TEX_UV] = computed_uv;
a[Mesh::ARRAY_INDEX] = computed_indices;
- mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, a, Array(), Mesh::ARRAY_FLAG_USE_2D_VERTICES);
+ mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, a, Array(), Dictionary(), Mesh::ARRAY_FLAG_USE_2D_VERTICES);
MeshInstance2D *mesh_instance = memnew(MeshInstance2D);
mesh_instance->set_mesh(mesh);
diff --git a/main/main.cpp b/main/main.cpp
index 9aebc17a65..fff652edc8 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -1795,8 +1795,6 @@ bool Main::start() {
sml->get_root()->set_shadow_atlas_quadrant_subdiv(1, Viewport::ShadowAtlasQuadrantSubdiv(shadow_atlas_q1_subdiv));
sml->get_root()->set_shadow_atlas_quadrant_subdiv(2, Viewport::ShadowAtlasQuadrantSubdiv(shadow_atlas_q2_subdiv));
sml->get_root()->set_shadow_atlas_quadrant_subdiv(3, Viewport::ShadowAtlasQuadrantSubdiv(shadow_atlas_q3_subdiv));
- Viewport::Usage usage = Viewport::Usage(int(GLOBAL_GET("rendering/quality/intended_usage/framebuffer_allocation")));
- sml->get_root()->set_usage(usage);
bool snap_controls = GLOBAL_DEF("gui/common/snap_controls_to_pixels", true);
sml->get_root()->set_snap_controls_to_pixels(snap_controls);
@@ -1929,8 +1927,6 @@ bool Main::start() {
ProgressDialog *progress_dialog = memnew(ProgressDialog);
pmanager->add_child(progress_dialog);
sml->get_root()->add_child(pmanager);
- // Speed up rendering slightly by disabling 3D features while in the project manager.
- sml->get_root()->set_usage(Viewport::USAGE_2D_NO_SAMPLING);
OS::get_singleton()->set_context(OS::CONTEXT_PROJECTMAN);
project_manager = true;
}
diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp
index e1e0044cea..7b846569dc 100644
--- a/modules/gridmap/grid_map_editor_plugin.cpp
+++ b/modules/gridmap/grid_map_editor_plugin.cpp
@@ -1022,8 +1022,7 @@ void GridMapEditor::_draw_grids(const Vector3 &cell_size) {
Vector3 edited_floor = node->has_meta("_editor_floor_") ? node->get_meta("_editor_floor_") : Variant();
for (int i = 0; i < 3; i++) {
- if (VS::get_singleton()->mesh_get_surface_count(grid[i]) > 0)
- VS::get_singleton()->mesh_remove_surface(grid[i], 0);
+ VS::get_singleton()->mesh_clear(grid[i]);
edit_floor[i] = edited_floor[i];
}
diff --git a/scene/3d/ray_cast.cpp b/scene/3d/ray_cast.cpp
index 7f764a737a..616ab7cf40 100644
--- a/scene/3d/ray_cast.cpp
+++ b/scene/3d/ray_cast.cpp
@@ -362,8 +362,7 @@ void RayCast::_update_debug_shape() {
return;
Ref<ArrayMesh> mesh = mi->get_mesh();
- if (mesh->get_surface_count() > 0)
- mesh->surface_remove(0);
+ mesh->clear_surfaces();
Array a;
a.resize(Mesh::ARRAY_MAX);
diff --git a/scene/3d/soft_body.cpp b/scene/3d/soft_body.cpp
index 435bef7247..931e786455 100644
--- a/scene/3d/soft_body.cpp
+++ b/scene/3d/soft_body.cpp
@@ -47,7 +47,10 @@ void SoftBodyVisualServerHandler::prepare(RID p_mesh, int p_surface) {
mesh = p_mesh;
surface = p_surface;
-
+#ifndef _MSC_VER
+#warning Softbody is not working, needs to be redone considering that these functions no longer exist
+#endif
+#if 0
const uint32_t surface_format = VS::get_singleton()->mesh_surface_get_format(mesh, surface);
const int surface_vertex_len = VS::get_singleton()->mesh_surface_get_array_len(mesh, p_surface);
const int surface_index_len = VS::get_singleton()->mesh_surface_get_array_index_len(mesh, p_surface);
@@ -57,6 +60,7 @@ void SoftBodyVisualServerHandler::prepare(RID p_mesh, int p_surface) {
stride = VS::get_singleton()->mesh_surface_make_offsets_from_format(surface_format, surface_vertex_len, surface_index_len, surface_offsets);
offset_vertices = surface_offsets[VS::ARRAY_VERTEX];
offset_normal = surface_offsets[VS::ARRAY_NORMAL];
+#endif
}
void SoftBodyVisualServerHandler::clear() {
@@ -485,14 +489,15 @@ void SoftBody::become_mesh_owner() {
// Get current mesh array and create new mesh array with necessary flag for softbody
Array surface_arrays = mesh->surface_get_arrays(0);
Array surface_blend_arrays = mesh->surface_get_blend_shape_arrays(0);
+ Dictionary surface_lods = mesh->surface_get_lods(0);
uint32_t surface_format = mesh->surface_get_format(0);
- surface_format &= ~(Mesh::ARRAY_COMPRESS_VERTEX | Mesh::ARRAY_COMPRESS_NORMAL);
+ surface_format &= ~(Mesh::ARRAY_COMPRESS_NORMAL);
surface_format |= Mesh::ARRAY_FLAG_USE_DYNAMIC_UPDATE;
Ref<ArrayMesh> soft_mesh;
soft_mesh.instance();
- soft_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, surface_arrays, surface_blend_arrays, surface_format);
+ soft_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, surface_arrays, surface_blend_arrays, surface_lods, surface_format);
soft_mesh->surface_set_material(0, mesh->surface_get_material(0));
set_mesh(soft_mesh);
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index 15d21859ea..67a39a6b22 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -2081,12 +2081,6 @@ SceneTree::SceneTree() {
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/filters/msaa", PropertyInfo(Variant::INT, "rendering/quality/filters/msaa", PROPERTY_HINT_ENUM, "Disabled,2x,4x,8x,16x,AndroidVR 2x,AndroidVR 4x"));
root->set_msaa(Viewport::MSAA(msaa_mode));
- GLOBAL_DEF("rendering/quality/depth/hdr", true);
- GLOBAL_DEF("rendering/quality/depth/hdr.mobile", false);
-
- bool hdr = GLOBAL_GET("rendering/quality/depth/hdr");
- root->set_hdr(hdr);
-
VS::get_singleton()->scenario_set_reflection_atlas_size(root->get_world()->get_scenario(), ref_atlas_size, ref_atlas_subdiv);
{ //load default fallback environment
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index e4343d3982..976c66ad0c 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -1330,17 +1330,6 @@ Ref<ViewportTexture> Viewport::get_texture() const {
return default_texture;
}
-void Viewport::set_vflip(bool p_enable) {
-
- vflip = p_enable;
- VisualServer::get_singleton()->viewport_set_vflip(viewport, p_enable);
-}
-
-bool Viewport::get_vflip() const {
-
- return vflip;
-}
-
void Viewport::set_clear_mode(ClearMode p_mode) {
clear_mode = p_mode;
@@ -2948,26 +2937,6 @@ bool Viewport::is_input_disabled() const {
return disable_input;
}
-void Viewport::set_disable_3d(bool p_disable) {
- disable_3d = p_disable;
- VS::get_singleton()->viewport_set_disable_3d(viewport, p_disable);
-}
-
-bool Viewport::is_3d_disabled() const {
-
- return disable_3d;
-}
-
-void Viewport::set_keep_3d_linear(bool p_keep_3d_linear) {
- keep_3d_linear = p_keep_3d_linear;
- VS::get_singleton()->viewport_set_keep_3d_linear(viewport, keep_3d_linear);
-}
-
-bool Viewport::get_keep_3d_linear() const {
-
- return keep_3d_linear;
-}
-
Variant Viewport::gui_get_drag_data() const {
return gui.drag_data;
}
@@ -3008,30 +2977,6 @@ Viewport::MSAA Viewport::get_msaa() const {
return msaa;
}
-void Viewport::set_hdr(bool p_hdr) {
-
- if (hdr == p_hdr)
- return;
-
- hdr = p_hdr;
- VS::get_singleton()->viewport_set_hdr(viewport, p_hdr);
-}
-
-bool Viewport::get_hdr() const {
-
- return hdr;
-}
-
-void Viewport::set_usage(Usage p_usage) {
-
- usage = p_usage;
- VS::get_singleton()->viewport_set_usage(viewport, VS::ViewportUsage(p_usage));
-}
-
-Viewport::Usage Viewport::get_usage() const {
- return usage;
-}
-
void Viewport::set_debug_draw(DebugDraw p_debug_draw) {
debug_draw = p_debug_draw;
@@ -3090,10 +3035,6 @@ bool Viewport::is_handling_input_locally() const {
}
void Viewport::_validate_property(PropertyInfo &property) const {
-
- if (VisualServer::get_singleton()->is_low_end() && property.name == "hdr") {
- property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL;
- }
}
void Viewport::set_default_canvas_item_texture_filter(DefaultCanvasItemTextureFilter p_filter) {
@@ -3176,9 +3117,6 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_size_override_stretch", "enabled"), &Viewport::set_size_override_stretch);
ClassDB::bind_method(D_METHOD("is_size_override_stretch_enabled"), &Viewport::is_size_override_stretch_enabled);
- ClassDB::bind_method(D_METHOD("set_vflip", "enable"), &Viewport::set_vflip);
- ClassDB::bind_method(D_METHOD("get_vflip"), &Viewport::get_vflip);
-
ClassDB::bind_method(D_METHOD("set_clear_mode", "mode"), &Viewport::set_clear_mode);
ClassDB::bind_method(D_METHOD("get_clear_mode"), &Viewport::get_clear_mode);
@@ -3188,12 +3126,6 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_msaa", "msaa"), &Viewport::set_msaa);
ClassDB::bind_method(D_METHOD("get_msaa"), &Viewport::get_msaa);
- ClassDB::bind_method(D_METHOD("set_hdr", "enable"), &Viewport::set_hdr);
- ClassDB::bind_method(D_METHOD("get_hdr"), &Viewport::get_hdr);
-
- ClassDB::bind_method(D_METHOD("set_usage", "usage"), &Viewport::set_usage);
- ClassDB::bind_method(D_METHOD("get_usage"), &Viewport::get_usage);
-
ClassDB::bind_method(D_METHOD("set_debug_draw", "debug_draw"), &Viewport::set_debug_draw);
ClassDB::bind_method(D_METHOD("get_debug_draw"), &Viewport::get_debug_draw);
@@ -3236,12 +3168,6 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_disable_input", "disable"), &Viewport::set_disable_input);
ClassDB::bind_method(D_METHOD("is_input_disabled"), &Viewport::is_input_disabled);
- ClassDB::bind_method(D_METHOD("set_disable_3d", "disable"), &Viewport::set_disable_3d);
- ClassDB::bind_method(D_METHOD("is_3d_disabled"), &Viewport::is_3d_disabled);
-
- ClassDB::bind_method(D_METHOD("set_keep_3d_linear", "keep_3d_linear"), &Viewport::set_keep_3d_linear);
- ClassDB::bind_method(D_METHOD("get_keep_3d_linear"), &Viewport::get_keep_3d_linear);
-
ClassDB::bind_method(D_METHOD("_gui_show_tooltip"), &Viewport::_gui_show_tooltip);
ClassDB::bind_method(D_METHOD("_gui_remove_focus"), &Viewport::_gui_remove_focus);
ClassDB::bind_method(D_METHOD("_post_gui_grab_click_focus"), &Viewport::_post_gui_grab_click_focus);
@@ -3289,7 +3215,6 @@ void Viewport::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "render_direct_to_screen"), "set_use_render_direct_to_screen", "is_using_render_direct_to_screen");
ADD_PROPERTY(PropertyInfo(Variant::INT, "debug_draw", PROPERTY_HINT_ENUM, "Disabled,Unshaded,Overdraw,Wireframe"), "set_debug_draw", "get_debug_draw");
ADD_GROUP("Render Target", "render_target_");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "render_target_v_flip"), "set_vflip", "get_vflip");
ADD_PROPERTY(PropertyInfo(Variant::INT, "render_target_clear_mode", PROPERTY_HINT_ENUM, "Always,Never,Next Frame"), "set_clear_mode", "get_clear_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "render_target_update_mode", PROPERTY_HINT_ENUM, "Disabled,Once,When Visible,Always"), "set_update_mode", "get_update_mode");
ADD_GROUP("Canvas Items", "canvas_item_");
@@ -3348,11 +3273,6 @@ void Viewport::_bind_methods() {
BIND_ENUM_CONSTANT(MSAA_8X);
BIND_ENUM_CONSTANT(MSAA_16X);
- BIND_ENUM_CONSTANT(USAGE_2D);
- BIND_ENUM_CONSTANT(USAGE_2D_NO_SAMPLING);
- BIND_ENUM_CONSTANT(USAGE_3D);
- BIND_ENUM_CONSTANT(USAGE_3D_NO_EFFECTS);
-
BIND_ENUM_CONSTANT(CLEAR_MODE_ALWAYS);
BIND_ENUM_CONSTANT(CLEAR_MODE_NEVER);
BIND_ENUM_CONSTANT(CLEAR_MODE_ONLY_NEXT_FRAME);
@@ -3406,8 +3326,6 @@ Viewport::Viewport() {
size_override_size = Size2(1, 1);
gen_mipmaps = false;
- vflip = false;
-
//clear=true;
update_mode = UPDATE_WHEN_VISIBLE;
@@ -3433,8 +3351,6 @@ Viewport::Viewport() {
unhandled_key_input_group = "_vp_unhandled_key_input" + id;
disable_input = false;
- disable_3d = false;
- keep_3d_linear = false;
//window tooltip
gui.tooltip_timer = -1;
@@ -3453,9 +3369,7 @@ Viewport::Viewport() {
gui.last_mouse_focus = NULL;
msaa = MSAA_DISABLED;
- hdr = true;
- usage = USAGE_3D;
debug_draw = DEBUG_DRAW_DISABLED;
clear_mode = CLEAR_MODE_ALWAYS;
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index a70d812eda..469665676c 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -115,13 +115,6 @@ public:
MSAA_16X,
};
- enum Usage {
- USAGE_2D,
- USAGE_2D_NO_SAMPLING,
- USAGE_3D,
- USAGE_3D_NO_EFFECTS,
- };
-
enum RenderInfo {
RENDER_INFO_OBJECTS_IN_FRAME,
@@ -226,7 +219,6 @@ private:
Rect2 last_vp_rect;
bool transparent_bg;
- bool vflip;
ClearMode clear_mode;
bool filter;
bool gen_mipmaps;
@@ -278,21 +270,15 @@ private:
void _update_stretch_transform();
void _update_global_transform();
- bool disable_3d;
- bool keep_3d_linear;
UpdateMode update_mode;
RID texture_rid;
DebugDraw debug_draw;
- Usage usage;
-
int shadow_atlas_size;
ShadowAtlasQuadrantSubdiv shadow_atlas_quadrant_subdiv[4];
MSAA msaa;
- bool hdr;
-
Ref<ViewportTexture> default_texture;
Set<ViewportTexture *> viewport_textures;
@@ -491,9 +477,6 @@ public:
void set_size_override_stretch(bool p_enable);
bool is_size_override_stretch_enabled() const;
- void set_vflip(bool p_enable);
- bool get_vflip() const;
-
void set_clear_mode(ClearMode p_mode);
ClearMode get_clear_mode() const;
@@ -510,9 +493,6 @@ public:
void set_msaa(MSAA p_msaa);
MSAA get_msaa() const;
- void set_hdr(bool p_hdr);
- bool get_hdr() const;
-
Vector2 get_camera_coords(const Vector2 &p_viewport_coords) const;
Vector2 get_camera_rect_size() const;
@@ -525,12 +505,6 @@ public:
void set_disable_input(bool p_disable);
bool is_input_disabled() const;
- void set_disable_3d(bool p_disable);
- bool is_3d_disabled() const;
-
- void set_keep_3d_linear(bool p_keep_3d_linear);
- bool get_keep_3d_linear() const;
-
void set_attach_to_screen_rect(const Rect2 &p_rect);
Rect2 get_attach_to_screen_rect() const;
@@ -553,9 +527,6 @@ public:
virtual String get_configuration_warning() const;
- void set_usage(Usage p_usage);
- Usage get_usage() const;
-
void set_debug_draw(DebugDraw p_debug_draw);
DebugDraw get_debug_draw() const;
@@ -587,7 +558,6 @@ public:
VARIANT_ENUM_CAST(Viewport::UpdateMode);
VARIANT_ENUM_CAST(Viewport::ShadowAtlasQuadrantSubdiv);
VARIANT_ENUM_CAST(Viewport::MSAA);
-VARIANT_ENUM_CAST(Viewport::Usage);
VARIANT_ENUM_CAST(Viewport::DebugDraw);
VARIANT_ENUM_CAST(Viewport::ClearMode);
VARIANT_ENUM_CAST(Viewport::RenderInfo);
diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp
index 8955838f62..96c609174f 100644
--- a/scene/resources/mesh.cpp
+++ b/scene/resources/mesh.cpp
@@ -159,7 +159,7 @@ void Mesh::generate_debug_mesh_indices(Vector<Vector3> &r_points) {
bool Mesh::surface_is_softbody_friendly(int p_idx) const {
const uint32_t surface_format = surface_get_format(p_idx);
- return (surface_format & Mesh::ARRAY_FLAG_USE_DYNAMIC_UPDATE && (!(surface_format & Mesh::ARRAY_COMPRESS_VERTEX)) && (!(surface_format & Mesh::ARRAY_COMPRESS_NORMAL)));
+ return (surface_format & Mesh::ARRAY_FLAG_USE_DYNAMIC_UPDATE && (!(surface_format & Mesh::ARRAY_COMPRESS_NORMAL)));
}
PoolVector<Face3> Mesh::get_faces() const {
@@ -499,7 +499,9 @@ void Mesh::_bind_methods() {
BIND_ENUM_CONSTANT(PRIMITIVE_POINTS);
BIND_ENUM_CONSTANT(PRIMITIVE_LINES);
+ BIND_ENUM_CONSTANT(PRIMITIVE_LINE_STRIP);
BIND_ENUM_CONSTANT(PRIMITIVE_TRIANGLES);
+ BIND_ENUM_CONSTANT(PRIMITIVE_TRIANGLE_STRIP);
BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_NORMALIZED);
BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_RELATIVE);
@@ -514,18 +516,14 @@ void Mesh::_bind_methods() {
BIND_ENUM_CONSTANT(ARRAY_FORMAT_WEIGHTS);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_INDEX);
- BIND_ENUM_CONSTANT(ARRAY_COMPRESS_VERTEX);
BIND_ENUM_CONSTANT(ARRAY_COMPRESS_NORMAL);
BIND_ENUM_CONSTANT(ARRAY_COMPRESS_TANGENT);
BIND_ENUM_CONSTANT(ARRAY_COMPRESS_COLOR);
BIND_ENUM_CONSTANT(ARRAY_COMPRESS_TEX_UV);
BIND_ENUM_CONSTANT(ARRAY_COMPRESS_TEX_UV2);
- BIND_ENUM_CONSTANT(ARRAY_COMPRESS_BONES);
- BIND_ENUM_CONSTANT(ARRAY_COMPRESS_WEIGHTS);
BIND_ENUM_CONSTANT(ARRAY_COMPRESS_INDEX);
BIND_ENUM_CONSTANT(ARRAY_FLAG_USE_2D_VERTICES);
- BIND_ENUM_CONSTANT(ARRAY_FLAG_USE_16_BIT_BONES);
BIND_ENUM_CONSTANT(ARRAY_COMPRESS_DEFAULT);
@@ -626,9 +624,12 @@ bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) {
return true;
}
+#ifdef ENABLE_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.");
+
int idx = sname.get_slicec('/', 1).to_int();
String what = sname.get_slicec('/', 2);
@@ -654,6 +655,12 @@ 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
+ }
ERR_FAIL_COND_V(!d.has("vertex_count"), false);
int vertex_count = d["vertex_count"];
@@ -701,9 +708,191 @@ bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) {
return true;
}
+#endif
+
return false;
}
+Array ArrayMesh::_get_surfaces() const {
+
+ if (mesh.is_null()) {
+ return Array();
+ }
+
+ Array ret;
+ for (int i = 0; i < surfaces.size(); i++) {
+ VisualServer::SurfaceData surface = VS::get_singleton()->mesh_get_surface(mesh, i);
+ Dictionary data;
+ data["format"] = surface.format;
+ data["primitive"] = surface.primitive;
+ data["vertex_data"] = surface.vertex_data;
+ data["vertex_count"] = surface.vertex_count;
+ data["aabb"] = surface.aabb;
+ if (surface.index_count) {
+ data["index_data"] = surface.index_data;
+ data["index_count"] = surface.index_count;
+ };
+
+ Array lods;
+ for (int j = 0; j < surface.lods.size(); j++) {
+ lods.push_back(surface.lods[j].edge_length);
+ lods.push_back(surface.lods[j].index_data);
+ }
+
+ if (lods.size()) {
+ data["lods"] = lods;
+ }
+
+ Array bone_aabbs;
+ for (int j = 0; j < surface.bone_aabbs.size(); j++) {
+ bone_aabbs.push_back(surface.bone_aabbs[j]);
+ }
+ if (bone_aabbs.size()) {
+ data["bone_aabbs"] = bone_aabbs;
+ }
+
+ Array blend_shapes;
+ for (int j = 0; j < surface.blend_shapes.size(); j++) {
+ blend_shapes.push_back(surface.blend_shapes[j]);
+ }
+
+ if (surfaces[i].material.is_valid()) {
+ data["material"] = surfaces[i].material;
+ }
+
+ if (surfaces[i].name != String()) {
+ data["name"] = surfaces[i].name;
+ }
+
+ if (surfaces[i].is_2d) {
+ data["2d"] = true;
+ }
+
+ ret.push_back(data);
+ }
+ return ret;
+}
+
+void ArrayMesh::_create_if_empty() const {
+ if (!mesh.is_valid()) {
+ mesh = VS::get_singleton()->mesh_create();
+ }
+}
+
+void ArrayMesh::_set_surfaces(const Array &p_surfaces) {
+
+ Vector<VS::SurfaceData> surface_data;
+ Vector<Ref<Material> > surface_materials;
+ Vector<String> surface_names;
+ Vector<bool> surface_2d;
+
+ for (int i = 0; i < p_surfaces.size(); i++) {
+ VS::SurfaceData surface;
+ Dictionary d = p_surfaces[i];
+ ERR_FAIL_COND(!d.has("format"));
+ ERR_FAIL_COND(!d.has("primitive"));
+ ERR_FAIL_COND(!d.has("vertex_data"));
+ ERR_FAIL_COND(!d.has("vertex_count"));
+ ERR_FAIL_COND(!d.has("aabb"));
+ surface.format = d["format"];
+ surface.primitive = VS::PrimitiveType(int(d["primitive"]));
+ surface.vertex_data = d["vertex_data"];
+ surface.vertex_count = d["vertex_count"];
+ surface.aabb = d["aabb"];
+
+ if (d.has("index_data")) {
+ ERR_FAIL_COND(!d.has("index_count"));
+ surface.index_data = d["index_data"];
+ surface.index_count = d["index_count"];
+ }
+
+ if (d.has("lods")) {
+ Array lods = d["lods"];
+ ERR_FAIL_COND(lods.size() & 1); //must be even
+ for (int j = 0; j < lods.size(); j += 2) {
+ VS::SurfaceData::LOD lod;
+ lod.edge_length = lods[j + 0];
+ lod.index_data = lods[j + 1];
+ surface.lods.push_back(lod);
+ }
+ }
+
+ if (d.has("bone_aabbs")) {
+ Array bone_aabbs = d["bone_aabbs"];
+ for (int j = 0; j < bone_aabbs.size(); j++) {
+ surface.bone_aabbs.push_back(bone_aabbs[j]);
+ }
+ }
+
+ if (d.has("blend_shapes")) {
+ Array blend_shapes;
+ for (int j = 0; j < blend_shapes.size(); j++) {
+ surface.blend_shapes.push_back(blend_shapes[j]);
+ }
+ }
+
+ Ref<Material> material;
+ if (d.has("material")) {
+ material = d["material"];
+ if (material.is_valid()) {
+ surface.material = material->get_rid();
+ }
+ }
+
+ String name;
+ if (d.has("name")) {
+ name = d["name"];
+ }
+
+ bool _2d = false;
+ if (d.has("2d")) {
+ _2d = d["2d"];
+ }
+
+ surface_data.push_back(surface);
+ surface_materials.push_back(material);
+ surface_names.push_back(name);
+ surface_2d.push_back(_2d);
+ }
+
+ if (mesh.is_valid()) {
+ //if mesh exists, it needs to be updated
+ VS::get_singleton()->mesh_clear(mesh);
+ for (int i = 0; i < surface_data.size(); i++) {
+ VS::get_singleton()->mesh_add_surface(mesh, surface_data[i]);
+ }
+ } else {
+ // if mesh does not exist (first time this is loaded, most likely),
+ // we can create it with a single call, which is a lot more efficient and thread friendly
+ mesh = VS::get_singleton()->mesh_create_from_surfaces(surface_data);
+ }
+
+ surfaces.clear();
+
+ aabb = AABB();
+ for (int i = 0; i < surface_data.size(); i++) {
+ Surface s;
+ s.aabb = surface_data[i].aabb;
+ if (i == 0) {
+ aabb = s.aabb;
+ blend_shapes.resize(surface_data[i].blend_shapes.size());
+ } else {
+ aabb.merge_with(s.aabb);
+ }
+
+ s.material = surface_materials[i];
+ s.is_2d = surface_2d[i];
+ s.name = surface_names[i];
+
+ s.format = surface_data[i].format;
+ s.primitive = PrimitiveType(surface_data[i].primitive);
+ s.array_length = surface_data[i].vertex_count;
+ s.index_array_length = surface_data[i].index_count;
+
+ surfaces.push_back(s);
+ }
+}
+
bool ArrayMesh::_get(const StringName &p_name, Variant &r_ret) const {
if (_is_generated())
@@ -734,47 +923,7 @@ bool ArrayMesh::_get(const StringName &p_name, Variant &r_ret) const {
else if (what == "name")
r_ret = surface_get_name(idx);
return true;
- } else if (!sname.begins_with("surfaces"))
- return false;
-
- int idx = sname.get_slicec('/', 1).to_int();
- ERR_FAIL_INDEX_V(idx, surfaces.size(), false);
-
- Dictionary d;
-
- d["array_data"] = VS::get_singleton()->mesh_surface_get_array(mesh, idx);
- d["vertex_count"] = VS::get_singleton()->mesh_surface_get_array_len(mesh, idx);
- d["array_index_data"] = VS::get_singleton()->mesh_surface_get_index_array(mesh, idx);
- d["index_count"] = VS::get_singleton()->mesh_surface_get_array_index_len(mesh, idx);
- d["primitive"] = VS::get_singleton()->mesh_surface_get_primitive_type(mesh, idx);
- d["format"] = VS::get_singleton()->mesh_surface_get_format(mesh, idx);
- d["aabb"] = VS::get_singleton()->mesh_surface_get_aabb(mesh, idx);
-
- Vector<AABB> skel_aabb = VS::get_singleton()->mesh_surface_get_skeleton_aabb(mesh, idx);
- Array arr;
- arr.resize(skel_aabb.size());
- for (int i = 0; i < skel_aabb.size(); i++) {
- arr[i] = skel_aabb[i];
}
- d["skeleton_aabb"] = arr;
-
- Vector<PoolVector<uint8_t> > blend_shape_data = VS::get_singleton()->mesh_surface_get_blend_shapes(mesh, idx);
-
- Array md;
- for (int i = 0; i < blend_shape_data.size(); i++) {
- md.push_back(blend_shape_data[i]);
- }
-
- d["blend_shape_data"] = md;
-
- Ref<Material> m = surface_get_material(idx);
- if (m.is_valid())
- d["material"] = m;
- String n = surface_get_name(idx);
- if (n != "")
- d["name"] = n;
-
- r_ret = d;
return true;
}
@@ -791,7 +940,6 @@ void ArrayMesh::_get_property_list(List<PropertyInfo> *p_list) const {
for (int i = 0; i < surfaces.size(); i++) {
- p_list->push_back(PropertyInfo(Variant::DICTIONARY, "surfaces/" + itos(i), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
p_list->push_back(PropertyInfo(Variant::STRING, "surface_" + itos(i + 1) + "/name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
if (surfaces[i].is_2d) {
p_list->push_back(PropertyInfo(Variant::OBJECT, "surface_" + itos(i + 1) + "/material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,CanvasItemMaterial", PROPERTY_USAGE_EDITOR));
@@ -814,55 +962,53 @@ void ArrayMesh::_recompute_aabb() {
aabb.merge_with(surfaces[i].aabb);
}
}
+#ifndef _MSC_VER
+#warning need to add binding to add_surface using future MeshSurfaceData object
+#endif
+void ArrayMesh::add_surface(uint32_t p_format, PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<PoolVector<uint8_t> > &p_blend_shapes, const Vector<AABB> &p_bone_aabb, const Vector<VS::SurfaceData::LOD> &p_lods) {
-void ArrayMesh::add_surface(uint32_t p_format, PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<PoolVector<uint8_t> > &p_blend_shapes, const Vector<AABB> &p_bone_aabbs) {
+ _create_if_empty();
Surface s;
s.aabb = p_aabb;
s.is_2d = p_format & ARRAY_FLAG_USE_2D_VERTICES;
+ s.primitive = p_primitive;
+ s.array_length = p_vertex_count;
+ s.index_array_length = p_index_count;
+ s.format = p_format;
+
surfaces.push_back(s);
_recompute_aabb();
- VisualServer::get_singleton()->mesh_add_surface(mesh, p_format, (VS::PrimitiveType)p_primitive, p_array, p_vertex_count, p_index_array, p_index_count, p_aabb, p_blend_shapes, p_bone_aabbs);
-}
-
-void ArrayMesh::add_surface_from_arrays(PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes, uint32_t p_flags) {
-
- ERR_FAIL_COND(p_arrays.size() != ARRAY_MAX);
-
- Surface s;
-
- VisualServer::get_singleton()->mesh_add_surface_from_arrays(mesh, (VisualServer::PrimitiveType)p_primitive, p_arrays, p_blend_shapes, p_flags);
+ VS::SurfaceData sd;
+ sd.format = p_format;
+ sd.primitive = VS::PrimitiveType(p_primitive);
+ sd.aabb = p_aabb;
+ sd.vertex_count = p_vertex_count;
+ sd.vertex_data = p_array;
+ sd.index_count = p_index_count;
+ sd.index_data = p_index_array;
+ sd.blend_shapes = p_blend_shapes;
+ sd.bone_aabbs = p_bone_aabb;
+ sd.lods = p_lods;
- /* make aABB? */ {
+ VisualServer::get_singleton()->mesh_add_surface(mesh, sd);
- Variant arr = p_arrays[ARRAY_VERTEX];
- PoolVector<Vector3> vertices = arr;
- int len = vertices.size();
- ERR_FAIL_COND(len == 0);
- PoolVector<Vector3>::Read r = vertices.read();
- const Vector3 *vtx = r.ptr();
+ clear_cache();
+ _change_notify();
+ emit_changed();
+}
- // check AABB
- AABB aabb;
- for (int i = 0; i < len; i++) {
+void ArrayMesh::add_surface_from_arrays(PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes, const Dictionary &p_lods, uint32_t p_flags) {
- if (i == 0)
- aabb.position = vtx[i];
- else
- aabb.expand_to(vtx[i]);
- }
+ ERR_FAIL_COND(p_arrays.size() != ARRAY_MAX);
- s.aabb = aabb;
- s.is_2d = arr.get_type() == Variant::POOL_VECTOR2_ARRAY;
- surfaces.push_back(s);
+ VS::SurfaceData surface;
- _recompute_aabb();
- }
+ Error err = VS::get_singleton()->mesh_create_surface_data_from_arrays(&surface, (VisualServer::PrimitiveType)p_primitive, p_arrays, p_blend_shapes, p_lods, p_flags);
+ ERR_FAIL_COND(err != OK);
- clear_cache();
- _change_notify();
- emit_changed();
+ add_surface(surface.format, PrimitiveType(surface.primitive), surface.vertex_data, surface.vertex_count, surface.index_data, surface.index_count, surface.aabb, surface.blend_shapes, surface.bone_aabbs, surface.lods);
}
Array ArrayMesh::surface_get_arrays(int p_surface) const {
@@ -875,6 +1021,10 @@ Array ArrayMesh::surface_get_blend_shape_arrays(int p_surface) const {
ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Array());
return VisualServer::get_singleton()->mesh_surface_get_blend_shape_arrays(mesh, p_surface);
}
+Dictionary ArrayMesh::surface_get_lods(int p_surface) const {
+ ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Dictionary());
+ return VisualServer::get_singleton()->mesh_surface_get_lods(mesh, p_surface);
+}
int ArrayMesh::get_surface_count() const {
@@ -898,7 +1048,7 @@ void ArrayMesh::add_blend_shape(const StringName &p_name) {
}
blend_shapes.push_back(name);
- VS::get_singleton()->mesh_set_blend_shape_count(mesh, blend_shapes.size());
+ //VS::get_singleton()->mesh_set_blend_shape_count(mesh, blend_shapes.size());
}
int ArrayMesh::get_blend_shape_count() const {
@@ -927,40 +1077,28 @@ ArrayMesh::BlendShapeMode ArrayMesh::get_blend_shape_mode() const {
return blend_shape_mode;
}
-void ArrayMesh::surface_remove(int p_idx) {
-
- ERR_FAIL_INDEX(p_idx, surfaces.size());
- VisualServer::get_singleton()->mesh_remove_surface(mesh, p_idx);
- surfaces.remove(p_idx);
-
- clear_cache();
- _recompute_aabb();
- _change_notify();
- emit_changed();
-}
-
int ArrayMesh::surface_get_array_len(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, surfaces.size(), -1);
- return VisualServer::get_singleton()->mesh_surface_get_array_len(mesh, p_idx);
+ return surfaces[p_idx].array_length;
}
int ArrayMesh::surface_get_array_index_len(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, surfaces.size(), -1);
- return VisualServer::get_singleton()->mesh_surface_get_array_index_len(mesh, p_idx);
+ return surfaces[p_idx].index_array_length;
}
uint32_t ArrayMesh::surface_get_format(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, surfaces.size(), 0);
- return VisualServer::get_singleton()->mesh_surface_get_format(mesh, p_idx);
+ return surfaces[p_idx].format;
}
ArrayMesh::PrimitiveType ArrayMesh::surface_get_primitive_type(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, surfaces.size(), PRIMITIVE_LINES);
- return (PrimitiveType)VisualServer::get_singleton()->mesh_surface_get_primitive_type(mesh, p_idx);
+ return surfaces[p_idx].primitive;
}
void ArrayMesh::surface_set_material(int p_idx, const Ref<Material> &p_material) {
@@ -981,7 +1119,6 @@ int ArrayMesh::surface_find_by_name(const String &p_name) const {
return i;
}
}
-
return -1;
}
@@ -1020,35 +1157,9 @@ Ref<Material> ArrayMesh::surface_get_material(int p_idx) const {
return surfaces[p_idx].material;
}
-void ArrayMesh::add_surface_from_mesh_data(const Geometry::MeshData &p_mesh_data) {
-
- VisualServer::get_singleton()->mesh_add_surface_from_mesh_data(mesh, p_mesh_data);
- AABB aabb;
- for (int i = 0; i < p_mesh_data.vertices.size(); i++) {
-
- if (i == 0)
- aabb.position = p_mesh_data.vertices[i];
- else
- aabb.expand_to(p_mesh_data.vertices[i]);
- }
-
- Surface s;
- s.aabb = aabb;
- if (surfaces.size() == 0)
- aabb = s.aabb;
- else
- aabb.merge_with(s.aabb);
-
- clear_cache();
-
- surfaces.push_back(s);
- _change_notify();
-
- emit_changed();
-}
-
RID ArrayMesh::get_rid() const {
+ _create_if_empty();
return mesh;
}
AABB ArrayMesh::get_aabb() const {
@@ -1056,8 +1167,18 @@ AABB ArrayMesh::get_aabb() const {
return aabb;
}
+void ArrayMesh::clear_surfaces() {
+ if (!mesh.is_valid()) {
+ return;
+ }
+ VS::get_singleton()->mesh_clear(mesh);
+ surfaces.clear();
+ aabb = AABB();
+}
+
void ArrayMesh::set_custom_aabb(const AABB &p_custom) {
+ _create_if_empty();
custom_aabb = p_custom;
VS::get_singleton()->mesh_set_custom_aabb(mesh, custom_aabb);
emit_changed();
@@ -1070,6 +1191,9 @@ AABB ArrayMesh::get_custom_aabb() const {
void ArrayMesh::regen_normalmaps() {
+ if (surfaces.size() == 0) {
+ return;
+ }
Vector<Ref<SurfaceTool> > surfs;
for (int i = 0; i < get_surface_count(); i++) {
@@ -1078,9 +1202,7 @@ void ArrayMesh::regen_normalmaps() {
surfs.push_back(st);
}
- while (get_surface_count()) {
- surface_remove(0);
- }
+ clear_surfaces();
for (int i = 0; i < surfs.size(); i++) {
@@ -1200,9 +1322,7 @@ Error ArrayMesh::lightmap_unwrap(const Transform &p_base_transform, float p_texe
}
//remove surfaces
- while (get_surface_count()) {
- surface_remove(0);
- }
+ clear_surfaces();
//create surfacetools for each surface..
Vector<Ref<SurfaceTool> > surfaces_tools;
@@ -1286,8 +1406,8 @@ void ArrayMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_blend_shape_mode", "mode"), &ArrayMesh::set_blend_shape_mode);
ClassDB::bind_method(D_METHOD("get_blend_shape_mode"), &ArrayMesh::get_blend_shape_mode);
- ClassDB::bind_method(D_METHOD("add_surface_from_arrays", "primitive", "arrays", "blend_shapes", "compress_flags"), &ArrayMesh::add_surface_from_arrays, DEFVAL(Array()), DEFVAL(ARRAY_COMPRESS_DEFAULT));
- ClassDB::bind_method(D_METHOD("surface_remove", "surf_idx"), &ArrayMesh::surface_remove);
+ ClassDB::bind_method(D_METHOD("add_surface_from_arrays", "primitive", "arrays", "blend_shapes", "lods", "compress_flags"), &ArrayMesh::add_surface_from_arrays, DEFVAL(Array()), DEFVAL(Dictionary()), DEFVAL(ARRAY_COMPRESS_DEFAULT));
+ ClassDB::bind_method(D_METHOD("clear_surfaces"), &ArrayMesh::clear_surfaces);
ClassDB::bind_method(D_METHOD("surface_update_region", "surf_idx", "offset", "data"), &ArrayMesh::surface_update_region);
ClassDB::bind_method(D_METHOD("surface_get_array_len", "surf_idx"), &ArrayMesh::surface_get_array_len);
ClassDB::bind_method(D_METHOD("surface_get_array_index_len", "surf_idx"), &ArrayMesh::surface_get_array_index_len);
@@ -1309,6 +1429,10 @@ void ArrayMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_custom_aabb", "aabb"), &ArrayMesh::set_custom_aabb);
ClassDB::bind_method(D_METHOD("get_custom_aabb"), &ArrayMesh::get_custom_aabb);
+ ClassDB::bind_method(D_METHOD("_set_surfaces", "surfaces"), &ArrayMesh::_set_surfaces);
+ ClassDB::bind_method(D_METHOD("_get_surfaces"), &ArrayMesh::_get_surfaces);
+
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "_surfaces", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_INTERNAL), "_set_surfaces", "_get_surfaces");
ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_shape_mode", PROPERTY_HINT_ENUM, "Normalized,Relative", PROPERTY_USAGE_NOEDITOR), "set_blend_shape_mode", "get_blend_shape_mode");
ADD_PROPERTY(PropertyInfo(Variant::AABB, "custom_aabb", PROPERTY_HINT_NONE, ""), "set_custom_aabb", "get_custom_aabb");
@@ -1350,11 +1474,14 @@ void ArrayMesh::reload_from_file() {
ArrayMesh::ArrayMesh() {
- mesh = VisualServer::get_singleton()->mesh_create();
+ //mesh is now created on demand
+ //mesh = VisualServer::get_singleton()->mesh_create();
blend_shape_mode = BLEND_SHAPE_MODE_RELATIVE;
}
ArrayMesh::~ArrayMesh() {
- VisualServer::get_singleton()->free(mesh);
+ if (mesh.is_valid()) {
+ VisualServer::get_singleton()->free(mesh);
+ }
}
diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h
index 6ead37a7bb..b8f3702bbe 100644
--- a/scene/resources/mesh.h
+++ b/scene/resources/mesh.h
@@ -83,28 +83,26 @@ public:
ARRAY_FORMAT_INDEX = 1 << ARRAY_INDEX,
ARRAY_COMPRESS_BASE = (ARRAY_INDEX + 1),
- ARRAY_COMPRESS_VERTEX = 1 << (ARRAY_VERTEX + ARRAY_COMPRESS_BASE), // mandatory
ARRAY_COMPRESS_NORMAL = 1 << (ARRAY_NORMAL + ARRAY_COMPRESS_BASE),
ARRAY_COMPRESS_TANGENT = 1 << (ARRAY_TANGENT + ARRAY_COMPRESS_BASE),
ARRAY_COMPRESS_COLOR = 1 << (ARRAY_COLOR + ARRAY_COMPRESS_BASE),
ARRAY_COMPRESS_TEX_UV = 1 << (ARRAY_TEX_UV + ARRAY_COMPRESS_BASE),
ARRAY_COMPRESS_TEX_UV2 = 1 << (ARRAY_TEX_UV2 + ARRAY_COMPRESS_BASE),
- ARRAY_COMPRESS_BONES = 1 << (ARRAY_BONES + ARRAY_COMPRESS_BASE),
- ARRAY_COMPRESS_WEIGHTS = 1 << (ARRAY_WEIGHTS + ARRAY_COMPRESS_BASE),
ARRAY_COMPRESS_INDEX = 1 << (ARRAY_INDEX + ARRAY_COMPRESS_BASE),
ARRAY_FLAG_USE_2D_VERTICES = ARRAY_COMPRESS_INDEX << 1,
- ARRAY_FLAG_USE_16_BIT_BONES = ARRAY_COMPRESS_INDEX << 2,
ARRAY_FLAG_USE_DYNAMIC_UPDATE = ARRAY_COMPRESS_INDEX << 3,
- ARRAY_COMPRESS_DEFAULT = ARRAY_COMPRESS_NORMAL | ARRAY_COMPRESS_TANGENT | ARRAY_COMPRESS_COLOR | ARRAY_COMPRESS_TEX_UV | ARRAY_COMPRESS_TEX_UV2 | ARRAY_COMPRESS_WEIGHTS
+ ARRAY_COMPRESS_DEFAULT = ARRAY_COMPRESS_NORMAL | ARRAY_COMPRESS_TANGENT | ARRAY_COMPRESS_COLOR | ARRAY_COMPRESS_TEX_UV | ARRAY_COMPRESS_TEX_UV2
};
enum PrimitiveType {
PRIMITIVE_POINTS = VisualServer::PRIMITIVE_POINTS,
PRIMITIVE_LINES = VisualServer::PRIMITIVE_LINES,
+ PRIMITIVE_LINE_STRIP = VisualServer::PRIMITIVE_LINE_STRIP,
PRIMITIVE_TRIANGLES = VisualServer::PRIMITIVE_TRIANGLES,
+ PRIMITIVE_TRIANGLE_STRIP = VisualServer::PRIMITIVE_TRIANGLE_STRIP,
PRIMITIVE_MAX = VisualServer::PRIMITIVE_MAX,
};
@@ -120,6 +118,7 @@ public:
virtual bool surface_is_softbody_friendly(int p_idx) const;
virtual Array surface_get_arrays(int p_surface) const = 0;
virtual Array surface_get_blend_shape_arrays(int p_surface) const = 0;
+ virtual Dictionary surface_get_lods(int p_surface) const = 0;
virtual uint32_t surface_get_format(int p_idx) const = 0;
virtual PrimitiveType surface_get_primitive_type(int p_idx) const = 0;
virtual void surface_set_material(int p_idx, const Ref<Material> &p_material) = 0;
@@ -157,20 +156,29 @@ class ArrayMesh : public Mesh {
GDCLASS(ArrayMesh, Mesh);
RES_BASE_EXTENSION("mesh");
+ Array _get_surfaces() const;
+ void _set_surfaces(const Array &p_data);
+
private:
struct Surface {
+ uint32_t format;
+ int array_length;
+ int index_array_length;
+ PrimitiveType primitive;
+
String name;
AABB aabb;
Ref<Material> material;
bool is_2d;
};
Vector<Surface> surfaces;
- RID mesh;
+ mutable RID mesh;
AABB aabb;
BlendShapeMode blend_shape_mode;
Vector<StringName> blend_shapes;
AABB custom_aabb;
+ _FORCE_INLINE_ void _create_if_empty() const;
void _recompute_aabb();
protected:
@@ -183,11 +191,13 @@ protected:
static void _bind_methods();
public:
- void add_surface_from_arrays(PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), uint32_t p_flags = ARRAY_COMPRESS_DEFAULT);
- void add_surface(uint32_t p_format, PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<PoolVector<uint8_t> > &p_blend_shapes = Vector<PoolVector<uint8_t> >(), const Vector<AABB> &p_bone_aabbs = Vector<AABB>());
+ void add_surface_from_arrays(PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), const Dictionary &p_lods = Dictionary(), uint32_t p_flags = ARRAY_COMPRESS_DEFAULT);
+
+ void add_surface(uint32_t p_format, PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<PoolVector<uint8_t> > &p_blend_shapes = Vector<PoolVector<uint8_t> >(), const Vector<AABB> &p_bone_aabbs = Vector<AABB>(), const Vector<VS::SurfaceData::LOD> &p_lods = Vector<VS::SurfaceData::LOD>());
Array surface_get_arrays(int p_surface) const;
Array surface_get_blend_shape_arrays(int p_surface) const;
+ Dictionary surface_get_lods(int p_surface) const;
void add_blend_shape(const StringName &p_name);
int get_blend_shape_count() const;
@@ -202,6 +212,8 @@ public:
int get_surface_count() const;
void surface_remove(int p_idx);
+ void clear_surfaces();
+
void surface_set_custom_aabb(int p_idx, const AABB &p_aabb); //only recognized by driver
int surface_get_array_len(int p_idx) const;
@@ -217,8 +229,6 @@ public:
void surface_set_name(int p_idx, const String &p_name);
String surface_get_name(int p_idx) const;
- void add_surface_from_mesh_data(const Geometry::MeshData &p_mesh_data);
-
void set_custom_aabb(const AABB &p_custom);
AABB get_custom_aabb() const;
diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp
index 74df72619a..79d030b8ab 100644
--- a/scene/resources/primitive_meshes.cpp
+++ b/scene/resources/primitive_meshes.cpp
@@ -57,9 +57,11 @@ void PrimitiveMesh::_update() const {
}
}
+ PoolVector<int> indices = arr[VS::ARRAY_INDEX];
+
if (flip_faces) {
PoolVector<Vector3> normals = arr[VS::ARRAY_NORMAL];
- PoolVector<int> indices = arr[VS::ARRAY_INDEX];
+
if (normals.size() && indices.size()) {
{
@@ -82,6 +84,8 @@ void PrimitiveMesh::_update() const {
}
}
+ array_len = pc;
+ index_array_len = indices.size();
// in with the new
VisualServer::get_singleton()->mesh_clear(mesh);
VisualServer::get_singleton()->mesh_add_surface_from_arrays(mesh, (VisualServer::PrimitiveType)primitive_type, arr);
@@ -114,7 +118,7 @@ int PrimitiveMesh::surface_get_array_len(int p_idx) const {
_update();
}
- return VisualServer::get_singleton()->mesh_surface_get_array_len(mesh, 0);
+ return array_len;
}
int PrimitiveMesh::surface_get_array_index_len(int p_idx) const {
@@ -123,7 +127,7 @@ int PrimitiveMesh::surface_get_array_index_len(int p_idx) const {
_update();
}
- return VisualServer::get_singleton()->mesh_surface_get_array_index_len(mesh, 0);
+ return index_array_len;
}
Array PrimitiveMesh::surface_get_arrays(int p_surface) const {
@@ -135,22 +139,18 @@ Array PrimitiveMesh::surface_get_arrays(int p_surface) const {
return VisualServer::get_singleton()->mesh_surface_get_arrays(mesh, 0);
}
+Dictionary PrimitiveMesh::surface_get_lods(int p_surface) const {
+ return Dictionary(); //not really supported
+}
Array PrimitiveMesh::surface_get_blend_shape_arrays(int p_surface) const {
- ERR_FAIL_INDEX_V(p_surface, 1, Array());
- if (pending_request) {
- _update();
- }
- return Array();
+ return Array(); //not really supported
}
uint32_t PrimitiveMesh::surface_get_format(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, 1, 0);
- if (pending_request) {
- _update();
- }
- return VisualServer::get_singleton()->mesh_surface_get_format(mesh, 0);
+ return VS::ARRAY_COMPRESS_DEFAULT;
}
Mesh::PrimitiveType PrimitiveMesh::surface_get_primitive_type(int p_idx) const {
@@ -261,6 +261,9 @@ PrimitiveMesh::PrimitiveMesh() {
// make sure we do an update after we've finished constructing our object
pending_request = true;
+
+ array_len = 0;
+ index_array_len = 0;
}
PrimitiveMesh::~PrimitiveMesh() {
diff --git a/scene/resources/primitive_meshes.h b/scene/resources/primitive_meshes.h
index 47126f1862..5f17680c9e 100644
--- a/scene/resources/primitive_meshes.h
+++ b/scene/resources/primitive_meshes.h
@@ -50,6 +50,9 @@ private:
mutable AABB aabb;
AABB custom_aabb;
+ mutable int array_len;
+ mutable int index_array_len;
+
Ref<Material> material;
bool flip_faces;
@@ -70,6 +73,7 @@ public:
virtual int surface_get_array_index_len(int p_idx) const;
virtual Array surface_get_arrays(int p_surface) const;
virtual Array surface_get_blend_shape_arrays(int p_surface) const;
+ virtual Dictionary surface_get_lods(int p_surface) const;
virtual uint32_t surface_get_format(int p_idx) const;
virtual Mesh::PrimitiveType surface_get_primitive_type(int p_idx) const;
virtual void surface_set_material(int p_idx, const Ref<Material> &p_material);
diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp
index f921a9695c..a1e6430255 100644
--- a/scene/resources/surface_tool.cpp
+++ b/scene/resources/surface_tool.cpp
@@ -466,7 +466,7 @@ Ref<ArrayMesh> SurfaceTool::commit(const Ref<ArrayMesh> &p_existing, uint32_t p_
Array a = commit_to_arrays();
- mesh->add_surface_from_arrays(primitive, a, Array(), p_flags);
+ mesh->add_surface_from_arrays(primitive, a, Array(), Dictionary(), p_flags);
if (material.is_valid())
mesh->surface_set_material(surface, material);
diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h
index c8b756fb4a..8df43bc695 100644
--- a/servers/visual/rasterizer.h
+++ b/servers/visual/rasterizer.h
@@ -100,14 +100,23 @@ public:
Map<InstanceBase *, uint32_t> instances;
};
+ struct InstanceCustomData {
+
+ virtual ~InstanceCustomData() {}
+ };
+
struct InstanceBase {
VS::InstanceType base_type;
RID base;
+ InstanceCustomData *custom_data;
+
RID skeleton;
RID material_override;
+ RID instance_data;
+
Transform transform;
int depth_layer;
@@ -185,6 +194,7 @@ public:
InstanceBase() :
dependency_item(this) {
+ custom_data = nullptr;
base_type = VS::INSTANCE_NONE;
cast_shadows = VS::SHADOW_CASTING_SETTING_ON;
receive_shadows = true;
@@ -198,6 +208,9 @@ public:
}
virtual ~InstanceBase() {
+ if (custom_data) {
+ memdelete(custom_data);
+ }
clear_dependencies();
}
};
@@ -225,12 +238,24 @@ public:
virtual void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) = 0;
virtual void gi_probe_instance_set_bounds(RID p_probe, const Vector3 &p_bounds) = 0;
- virtual void render_scene(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) = 0;
+ virtual void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) = 0;
virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) = 0;
virtual void set_scene_pass(uint64_t p_pass) = 0;
+ virtual void set_time(double p_time) = 0;
virtual void set_debug_draw_mode(VS::ViewportDebugDraw p_debug_draw) = 0;
+ virtual void instance_create_custom_data(InstanceBase *p_instance) = 0;
+ virtual void instance_free_custom_data(InstanceBase *p_instance) = 0;
+ virtual void instance_custom_data_update_lights(InstanceBase *p_instance) = 0;
+ virtual void instance_custom_data_update_reflection_probes(InstanceBase *p_instance) = 0;
+ virtual void instance_custom_data_update_gi_probes(InstanceBase *p_instance) = 0;
+ virtual void instance_custom_data_update_lightmap(InstanceBase *p_instance) = 0;
+ virtual void instance_custom_data_update_transform(InstanceBase *p_instance) = 0;
+
+ virtual RID render_buffers_create() = 0;
+ virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, VS::ViewportMSAA p_msaa) = 0;
+
virtual bool free(RID p_rid) = 0;
virtual ~RasterizerScene() {}
@@ -317,9 +342,9 @@ public:
virtual RID mesh_create() = 0;
- virtual void mesh_add_surface(RID p_mesh, uint32_t p_format, VS::PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<PoolVector<uint8_t> > &p_blend_shapes = Vector<PoolVector<uint8_t> >(), const Vector<AABB> &p_bone_aabbs = Vector<AABB>()) = 0;
+ /// Returns stride
+ virtual void mesh_add_surface(RID p_mesh, const VS::SurfaceData &p_surface) = 0;
- virtual void mesh_set_blend_shape_count(RID p_mesh, int p_amount) = 0;
virtual int mesh_get_blend_shape_count(RID p_mesh) const = 0;
virtual void mesh_set_blend_shape_mode(RID p_mesh, VS::BlendShapeMode p_mode) = 0;
@@ -330,26 +355,14 @@ public:
virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) = 0;
virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const = 0;
- virtual int mesh_surface_get_array_len(RID p_mesh, int p_surface) const = 0;
- virtual int mesh_surface_get_array_index_len(RID p_mesh, int p_surface) const = 0;
-
- virtual PoolVector<uint8_t> mesh_surface_get_array(RID p_mesh, int p_surface) const = 0;
- virtual PoolVector<uint8_t> mesh_surface_get_index_array(RID p_mesh, int p_surface) const = 0;
-
- virtual uint32_t mesh_surface_get_format(RID p_mesh, int p_surface) const = 0;
- virtual VS::PrimitiveType mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const = 0;
-
- virtual AABB mesh_surface_get_aabb(RID p_mesh, int p_surface) const = 0;
- virtual Vector<PoolVector<uint8_t> > mesh_surface_get_blend_shapes(RID p_mesh, int p_surface) const = 0;
- virtual Vector<AABB> mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const = 0;
+ virtual VS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const = 0;
- virtual void mesh_remove_surface(RID p_mesh, int p_index) = 0;
virtual int mesh_get_surface_count(RID p_mesh) const = 0;
virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) = 0;
virtual AABB mesh_get_custom_aabb(RID p_mesh) const = 0;
- virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton) const = 0;
+ virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) = 0;
virtual void mesh_clear(RID p_mesh) = 0;
@@ -590,13 +603,7 @@ public:
/* RENDER TARGET */
enum RenderTargetFlags {
- RENDER_TARGET_VFLIP,
RENDER_TARGET_TRANSPARENT,
- RENDER_TARGET_NO_3D_EFFECTS,
- RENDER_TARGET_NO_3D,
- RENDER_TARGET_NO_SAMPLING,
- RENDER_TARGET_HDR,
- RENDER_TARGET_KEEP_3D_LINEAR,
RENDER_TARGET_DIRECT_TO_SCREEN,
RENDER_TARGET_FLAG_MAX
};
diff --git a/servers/visual/rasterizer_rd/rasterizer_canvas_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_canvas_rd.cpp
index f0d51f514a..130e0e15b7 100644
--- a/servers/visual/rasterizer_rd/rasterizer_canvas_rd.cpp
+++ b/servers/visual/rasterizer_rd/rasterizer_canvas_rd.cpp
@@ -342,7 +342,7 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int
vd.stride = 0;
descriptions.write[1] = vd;
- buffers.write[1] = polygon_buffers.default_color_buffer;
+ buffers.write[1] = storage->mesh_get_default_rd_buffer(RasterizerStorageRD::DEFAULT_RD_BUFFER_COLOR);
}
//uvs
@@ -370,7 +370,7 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int
vd.stride = 0;
descriptions.write[2] = vd;
- buffers.write[2] = polygon_buffers.default_uv_buffer;
+ buffers.write[2] = storage->mesh_get_default_rd_buffer(RasterizerStorageRD::DEFAULT_RD_BUFFER_TEX_UV);
}
//bones
@@ -401,7 +401,7 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int
vd.stride = 0;
descriptions.write[3] = vd;
- buffers.write[3] = polygon_buffers.default_bone_buffer;
+ buffers.write[3] = storage->mesh_get_default_rd_buffer(RasterizerStorageRD::DEFAULT_RD_BUFFER_BONES);
}
//bones
@@ -432,7 +432,7 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int
vd.stride = 0;
descriptions.write[4] = vd;
- buffers.write[4] = polygon_buffers.default_weight_buffer;
+ buffers.write[4] = storage->mesh_get_default_rd_buffer(RasterizerStorageRD::DEFAULT_RD_BUFFER_WEIGHTS);
}
//check that everything is as it should be
@@ -2278,7 +2278,9 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) {
RD::RENDER_PRIMITIVE_LINES,
RD::RENDER_PRIMITIVE_POINTS,
RD::RENDER_PRIMITIVE_TRIANGLES,
+ RD::RENDER_PRIMITIVE_TRIANGLE_STRIPS,
RD::RENDER_PRIMITIVE_LINES,
+ RD::RENDER_PRIMITIVE_LINESTRIPS,
RD::RENDER_PRIMITIVE_POINTS,
};
ShaderVariant shader_variants[PIPELINE_LIGHT_MODE_MAX][PIPELINE_VARIANT_MAX] = {
@@ -2290,6 +2292,8 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) {
SHADER_VARIANT_PRIMITIVE_POINTS,
SHADER_VARIANT_ATTRIBUTES,
SHADER_VARIANT_ATTRIBUTES,
+ SHADER_VARIANT_ATTRIBUTES,
+ SHADER_VARIANT_ATTRIBUTES,
SHADER_VARIANT_ATTRIBUTES_POINTS },
{ //lit
SHADER_VARIANT_QUAD_LIGHT,
@@ -2299,6 +2303,8 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) {
SHADER_VARIANT_PRIMITIVE_POINTS_LIGHT,
SHADER_VARIANT_ATTRIBUTES_LIGHT,
SHADER_VARIANT_ATTRIBUTES_LIGHT,
+ SHADER_VARIANT_ATTRIBUTES_LIGHT,
+ SHADER_VARIANT_ATTRIBUTES_LIGHT,
SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT },
};
@@ -2435,60 +2441,6 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) {
}
{
- {
- PoolVector<uint8_t> colors;
- colors.resize(sizeof(float) * 4);
- {
- PoolVector<uint8_t>::Write w = colors.write();
- float *fptr = (float *)w.ptr();
- fptr[0] = 1.0;
- fptr[1] = 1.0;
- fptr[2] = 1.0;
- fptr[3] = 1.0;
- }
- polygon_buffers.default_color_buffer = RD::get_singleton()->vertex_buffer_create(colors.size(), colors);
- }
-
- {
- PoolVector<uint8_t> uvs;
- uvs.resize(sizeof(float) * 2);
- {
- PoolVector<uint8_t>::Write w = uvs.write();
- float *fptr = (float *)w.ptr();
- fptr[0] = 0.0;
- fptr[1] = 0.0;
- }
- polygon_buffers.default_uv_buffer = RD::get_singleton()->vertex_buffer_create(uvs.size(), uvs);
- }
-
- {
- PoolVector<uint8_t> bones;
- bones.resize(sizeof(uint32_t) * 4);
- {
- PoolVector<uint8_t>::Write w = bones.write();
- uint32_t *iptr = (uint32_t *)w.ptr();
- iptr[0] = 0;
- iptr[1] = 0;
- iptr[2] = 0;
- iptr[3] = 0;
- }
- polygon_buffers.default_bone_buffer = RD::get_singleton()->vertex_buffer_create(bones.size(), bones);
- }
-
- {
- PoolVector<uint8_t> weights;
- weights.resize(sizeof(float) * 4);
- {
- PoolVector<uint8_t>::Write w = weights.write();
- float *fptr = (float *)w.ptr();
- fptr[0] = 0.0;
- fptr[1] = 0.0;
- fptr[2] = 0.0;
- fptr[3] = 0.0;
- }
- polygon_buffers.default_weight_buffer = RD::get_singleton()->vertex_buffer_create(weights.size(), weights);
- }
-
//polygon buffers
polygon_buffers.last_id = 1;
}
@@ -2606,10 +2558,6 @@ RasterizerCanvasRD::~RasterizerCanvasRD() {
{
RD::get_singleton()->free(shader.quad_index_array);
RD::get_singleton()->free(shader.quad_index_buffer);
- RD::get_singleton()->free(polygon_buffers.default_bone_buffer);
- RD::get_singleton()->free(polygon_buffers.default_weight_buffer);
- RD::get_singleton()->free(polygon_buffers.default_color_buffer);
- RD::get_singleton()->free(polygon_buffers.default_uv_buffer);
//primitives are erase by dependency
}
diff --git a/servers/visual/rasterizer_rd/rasterizer_canvas_rd.h b/servers/visual/rasterizer_rd/rasterizer_canvas_rd.h
index 8c22a4b735..eee1b194fb 100644
--- a/servers/visual/rasterizer_rd/rasterizer_canvas_rd.h
+++ b/servers/visual/rasterizer_rd/rasterizer_canvas_rd.h
@@ -116,7 +116,9 @@ class RasterizerCanvasRD : public RasterizerCanvas {
PIPELINE_VARIANT_PRIMITIVE_LINES,
PIPELINE_VARIANT_PRIMITIVE_POINTS,
PIPELINE_VARIANT_ATTRIBUTE_TRIANGLES,
+ PIPELINE_VARIANT_ATTRIBUTE_TRIANGLE_STRIP,
PIPELINE_VARIANT_ATTRIBUTE_LINES,
+ PIPELINE_VARIANT_ATTRIBUTE_LINES_STRIP,
PIPELINE_VARIANT_ATTRIBUTE_POINTS,
PIPELINE_VARIANT_MAX
};
@@ -290,10 +292,6 @@ class RasterizerCanvasRD : public RasterizerCanvas {
struct {
HashMap<PolygonID, PolygonBuffers> polygons;
PolygonID last_id;
- RID default_color_buffer;
- RID default_uv_buffer;
- RID default_bone_buffer;
- RID default_weight_buffer;
} polygon_buffers;
/********************/
diff --git a/servers/visual/rasterizer_rd/effects_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp
index 90881ae7fd..765e718279 100644
--- a/servers/visual/rasterizer_rd/effects_rd.cpp
+++ b/servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp
@@ -1,6 +1,6 @@
-#include "effects_rd.h"
+#include "rasterizer_effects_rd.h"
-RID EffectsRD::_get_uniform_set_from_texture(RID p_texture) {
+RID RasterizerEffectsRD::_get_uniform_set_from_texture(RID p_texture) {
if (texture_to_uniform_set_cache.has(p_texture)) {
RID uniform_set = texture_to_uniform_set_cache[p_texture];
@@ -24,7 +24,7 @@ RID EffectsRD::_get_uniform_set_from_texture(RID p_texture) {
return uniform_set;
}
-void EffectsRD::copy(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_region) {
+void RasterizerEffectsRD::copy(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_region) {
zeromem(&blur.push_constant, sizeof(BlurPushConstant));
@@ -45,7 +45,7 @@ void EffectsRD::copy(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect
RD::get_singleton()->draw_list_end();
}
-void EffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, const Rect2 &p_region) {
+void RasterizerEffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, const Rect2 &p_region) {
zeromem(&blur.push_constant, sizeof(BlurPushConstant));
@@ -86,7 +86,7 @@ void EffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_framebuffer_half, R
RD::get_singleton()->draw_list_end();
}
-EffectsRD::EffectsRD() {
+RasterizerEffectsRD::RasterizerEffectsRD() {
// Initialize blur
Vector<String> blur_modes;
@@ -138,7 +138,7 @@ EffectsRD::EffectsRD() {
}
}
-EffectsRD::~EffectsRD() {
+RasterizerEffectsRD::~RasterizerEffectsRD() {
RD::get_singleton()->free(default_sampler);
blur.shader.version_free(blur.shader_version);
RD::get_singleton()->free(index_buffer); //array gets freed as dependency
diff --git a/servers/visual/rasterizer_rd/effects_rd.h b/servers/visual/rasterizer_rd/rasterizer_effects_rd.h
index ed1bc288de..a51340b368 100644
--- a/servers/visual/rasterizer_rd/effects_rd.h
+++ b/servers/visual/rasterizer_rd/rasterizer_effects_rd.h
@@ -1,10 +1,10 @@
-#ifndef EFFECTS_RD_H
-#define EFFECTS_RD_H
+#ifndef RASTERIZER_EFFECTS_RD_H
+#define RASTERIZER_EFFECTS_RD_H
#include "render_pipeline_vertex_format_cache_rd.h"
#include "shaders/blur.glsl.gen.h"
-class EffectsRD {
+class RasterizerEffectsRD {
enum BlurMode {
BLUR_MODE_GAUSSIAN_BLUR,
@@ -80,8 +80,8 @@ public:
void copy(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_region);
void gaussian_blur(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, const Rect2 &p_region);
- EffectsRD();
- ~EffectsRD();
+ RasterizerEffectsRD();
+ ~RasterizerEffectsRD();
};
#endif // EFFECTS_RD_H
diff --git a/servers/visual/rasterizer_rd/rasterizer_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_rd.cpp
index 8cc090832b..fc38b90b88 100644
--- a/servers/visual/rasterizer_rd/rasterizer_rd.cpp
+++ b/servers/visual/rasterizer_rd/rasterizer_rd.cpp
@@ -79,6 +79,7 @@ void RasterizerRD::begin_frame(double frame_step) {
frame++;
time += frame_step;
canvas->set_time(time);
+ scene->set_time(time);
}
void RasterizerRD::end_frame(bool p_swap_buffers) {
@@ -176,5 +177,5 @@ RasterizerRD::RasterizerRD() {
storage = memnew(RasterizerStorageRD);
canvas = memnew(RasterizerCanvasRD(storage));
- scene = memnew(RasterizerSceneForwardRD);
+ scene = memnew(RasterizerSceneForwardRD(storage));
}
diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp
index 73c99fa70d..f63ceb9dfa 100644
--- a/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp
+++ b/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp
@@ -29,3 +29,2005 @@
/*************************************************************************/
#include "rasterizer_scene_forward_rd.h"
+#include "core/project_settings.h"
+#include "servers/visual/rendering_device.h"
+#include "servers/visual/visual_server_raster.h"
+
+static _FORCE_INLINE_ void store_transform(const Transform &p_mtx, float *p_array) {
+ p_array[0] = p_mtx.basis.elements[0][0];
+ p_array[1] = p_mtx.basis.elements[1][0];
+ p_array[2] = p_mtx.basis.elements[2][0];
+ p_array[3] = 0;
+ p_array[4] = p_mtx.basis.elements[0][1];
+ p_array[5] = p_mtx.basis.elements[1][1];
+ p_array[6] = p_mtx.basis.elements[2][1];
+ p_array[7] = 0;
+ p_array[8] = p_mtx.basis.elements[0][2];
+ p_array[9] = p_mtx.basis.elements[1][2];
+ p_array[10] = p_mtx.basis.elements[2][2];
+ p_array[11] = 0;
+ p_array[12] = p_mtx.origin.x;
+ p_array[13] = p_mtx.origin.y;
+ p_array[14] = p_mtx.origin.z;
+ p_array[15] = 1;
+}
+
+static _FORCE_INLINE_ void store_transform_3x3(const Transform &p_mtx, float *p_array) {
+ p_array[0] = p_mtx.basis.elements[0][0];
+ p_array[1] = p_mtx.basis.elements[1][0];
+ p_array[2] = p_mtx.basis.elements[2][0];
+ p_array[3] = 0;
+ p_array[4] = p_mtx.basis.elements[0][1];
+ p_array[5] = p_mtx.basis.elements[1][1];
+ p_array[6] = p_mtx.basis.elements[2][1];
+ p_array[7] = 0;
+ p_array[8] = p_mtx.basis.elements[0][2];
+ p_array[9] = p_mtx.basis.elements[1][2];
+ p_array[10] = p_mtx.basis.elements[2][2];
+ p_array[11] = 0;
+}
+
+static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_array) {
+
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+
+ p_array[i * 4 + j] = p_mtx.matrix[i][j];
+ }
+ }
+}
+void RasterizerSceneForwardRD::ShaderData::set_code(const String &p_code) {
+ //compile
+
+ code = p_code;
+ valid = false;
+ ubo_size = 0;
+ uniforms.clear();
+ uses_screen_texture = false;
+
+ if (code == String()) {
+ return; //just invalid, but no error
+ }
+
+ ShaderCompilerRD::GeneratedCode gen_code;
+
+ int blend_mode = BLEND_MODE_MIX;
+ int depth_test = DEPTH_TEST_ENABLED;
+ int cull = CULL_BACK;
+
+ uses_point_size = false;
+ uses_alpha = false;
+ uses_blend_alpha = false;
+ uses_depth_pre_pass = false;
+ uses_discard = false;
+ uses_roughness = false;
+ uses_normal = false;
+ bool wireframe = false;
+
+ unshaded = false;
+ uses_vertex = false;
+ uses_sss = false;
+ uses_screen_texture = false;
+ uses_depth_texture = false;
+ uses_normal_texture = false;
+ uses_time = false;
+ writes_modelview_or_projection = false;
+ uses_world_coordinates = false;
+
+ int depth_drawi = DEPTH_DRAW_OPAQUE;
+
+ ShaderCompilerRD::IdentifierActions actions;
+
+ actions.render_mode_values["blend_add"] = Pair<int *, int>(&blend_mode, BLEND_MODE_ADD);
+ actions.render_mode_values["blend_mix"] = Pair<int *, int>(&blend_mode, BLEND_MODE_MIX);
+ actions.render_mode_values["blend_sub"] = Pair<int *, int>(&blend_mode, BLEND_MODE_SUB);
+ actions.render_mode_values["blend_mul"] = Pair<int *, int>(&blend_mode, BLEND_MODE_MUL);
+
+ actions.render_mode_values["depth_draw_never"] = Pair<int *, int>(&depth_drawi, DEPTH_DRAW_DISABLED);
+ actions.render_mode_values["depth_draw_opaque"] = Pair<int *, int>(&depth_drawi, DEPTH_DRAW_OPAQUE);
+ actions.render_mode_values["depth_draw_always"] = Pair<int *, int>(&depth_drawi, DEPTH_DRAW_ALWAYS);
+
+ actions.render_mode_values["depth_test_disabled"] = Pair<int *, int>(&depth_test, DEPTH_TEST_DISABLED);
+
+ actions.render_mode_values["cull_disabled"] = Pair<int *, int>(&cull, CULL_DISABLED);
+ actions.render_mode_values["cull_front"] = Pair<int *, int>(&cull, CULL_FRONT);
+ actions.render_mode_values["cull_back"] = Pair<int *, int>(&cull, CULL_BACK);
+
+ actions.render_mode_flags["unshaded"] = &unshaded;
+ actions.render_mode_flags["wireframe"] = &wireframe;
+
+ actions.usage_flag_pointers["ALPHA"] = &uses_alpha;
+ actions.render_mode_flags["depth_prepass_alpha"] = &uses_depth_pre_pass;
+
+ actions.usage_flag_pointers["SSS_STRENGTH"] = &uses_sss;
+
+ actions.usage_flag_pointers["SCREEN_TEXTURE"] = &uses_screen_texture;
+ actions.usage_flag_pointers["DEPTH_TEXTURE"] = &uses_depth_texture;
+ actions.usage_flag_pointers["NORMAL_TEXTURE"] = &uses_normal_texture;
+ actions.usage_flag_pointers["DISCARD"] = &uses_discard;
+ actions.usage_flag_pointers["TIME"] = &uses_time;
+ actions.usage_flag_pointers["ROUGHNESS"] = &uses_roughness;
+ actions.usage_flag_pointers["NORMAL"] = &uses_normal;
+ actions.usage_flag_pointers["NORMALMAP"] = &uses_normal;
+
+ actions.usage_flag_pointers["POINT_SIZE"] = &uses_point_size;
+ actions.usage_flag_pointers["POINT_COORD"] = &uses_point_size;
+
+ actions.write_flag_pointers["MODELVIEW_MATRIX"] = &writes_modelview_or_projection;
+ actions.write_flag_pointers["PROJECTION_MATRIX"] = &writes_modelview_or_projection;
+ actions.write_flag_pointers["VERTEX"] = &uses_vertex;
+
+ actions.uniforms = &uniforms;
+
+ RasterizerSceneForwardRD *scene_singleton = (RasterizerSceneForwardRD *)RasterizerSceneForwardRD::singleton;
+
+ Error err = scene_singleton->shader.compiler.compile(VS::SHADER_CANVAS_ITEM, code, &actions, path, gen_code);
+
+ ERR_FAIL_COND(err != OK);
+
+ if (version.is_null()) {
+ version = scene_singleton->shader.scene_shader.version_create();
+ }
+
+ depth_draw = DepthDraw(depth_drawi);
+
+#if 0
+ print_line("**compiling shader:");
+ print_line("**defines:\n");
+ for (int i = 0; i < gen_code.defines.size(); i++) {
+ print_line(gen_code.defines[i]);
+ }
+ print_line("\n**uniforms:\n" + gen_code.uniforms);
+ print_line("\n**vertex_globals:\n" + gen_code.vertex_global);
+ print_line("\n**vertex_code:\n" + gen_code.vertex);
+ print_line("\n**fragment_globals:\n" + gen_code.fragment_global);
+ print_line("\n**fragment_code:\n" + gen_code.fragment);
+ print_line("\n**light_code:\n" + gen_code.light);
+#endif
+ scene_singleton->shader.scene_shader.version_set_code(version, gen_code.uniforms, gen_code.vertex_global, gen_code.vertex, gen_code.fragment_global, gen_code.light, gen_code.fragment, gen_code.defines);
+ ERR_FAIL_COND(!scene_singleton->shader.scene_shader.version_is_valid(version));
+
+ ubo_size = gen_code.uniform_total_size;
+ ubo_offsets = gen_code.uniform_offsets;
+ texture_uniforms = gen_code.texture_uniforms;
+
+ //blend modes
+
+ RD::PipelineColorBlendState::Attachment blend_attachment;
+
+ switch (blend_mode) {
+ case BLEND_MODE_MIX: {
+
+ blend_attachment.enable_blend = true;
+ blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD;
+ blend_attachment.color_blend_op = RD::BLEND_OP_ADD;
+ blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
+ blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
+ blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
+ blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
+
+ } break;
+ case BLEND_MODE_ADD: {
+
+ blend_attachment.enable_blend = true;
+ blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD;
+ blend_attachment.color_blend_op = RD::BLEND_OP_ADD;
+ blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
+ blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE;
+ blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
+ blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
+ uses_blend_alpha = true; //force alpha used because of blend
+
+ } break;
+ case BLEND_MODE_SUB: {
+
+ blend_attachment.enable_blend = true;
+ blend_attachment.alpha_blend_op = RD::BLEND_OP_SUBTRACT;
+ blend_attachment.color_blend_op = RD::BLEND_OP_SUBTRACT;
+ blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
+ blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE;
+ blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
+ blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
+ uses_blend_alpha = true; //force alpha used because of blend
+
+ } break;
+ case BLEND_MODE_MUL: {
+ blend_attachment.enable_blend = true;
+ blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD;
+ blend_attachment.color_blend_op = RD::BLEND_OP_ADD;
+ blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_DST_COLOR;
+ blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ZERO;
+ blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_DST_ALPHA;
+ blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ZERO;
+ uses_blend_alpha = true; //force alpha used because of blend
+ } break;
+ }
+
+ RD::PipelineColorBlendState blend_state_blend;
+ blend_state_blend.attachments.push_back(blend_attachment);
+ RD::PipelineColorBlendState blend_state_opaque = RD::PipelineColorBlendState::create_disabled(1);
+ RD::PipelineColorBlendState blend_state_opaque_specular = RD::PipelineColorBlendState::create_disabled(2);
+
+ //update pipelines
+
+ RD::PipelineDepthStencilState depth_stencil_state;
+
+ if (depth_test != DEPTH_TEST_DISABLED) {
+ depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_LESS_OR_EQUAL;
+ depth_stencil_state.enable_depth_write = depth_draw != DEPTH_DRAW_DISABLED ? true : false;
+ }
+
+ bool first = true;
+
+ for (int i = 0; i < CULL_VARIANT_MAX; i++) {
+
+ RD::PolygonCullMode cull_mode_rd_table[3][CULL_VARIANT_MAX] = {
+ { RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_FRONT, RD::POLYGON_CULL_BACK },
+ { RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_BACK, RD::POLYGON_CULL_FRONT },
+ { RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_DISABLED }
+ };
+
+ RD::PolygonCullMode cull_mode_rd = cull_mode_rd_table[cull][i];
+
+ for (int j = 0; j < VS::PRIMITIVE_MAX; j++) {
+
+ RD::RenderPrimitive primitive_rd_table[VS::PRIMITIVE_MAX] = {
+ RD::RENDER_PRIMITIVE_POINTS,
+ RD::RENDER_PRIMITIVE_LINES,
+ RD::RENDER_PRIMITIVE_LINESTRIPS,
+ RD::RENDER_PRIMITIVE_TRIANGLES,
+ RD::RENDER_PRIMITIVE_TRIANGLE_STRIPS,
+ };
+
+ RD::RenderPrimitive primitive_rd = uses_point_size ? RD::RENDER_PRIMITIVE_POINTS : primitive_rd_table[j];
+
+ for (int k = 0; k < SHADER_VERSION_MAX; k++) {
+
+ RD::PipelineRasterizationState raster_state;
+ raster_state.cull_mode = cull_mode_rd;
+ raster_state.wireframe = wireframe;
+
+ RD::PipelineColorBlendState blend_state;
+ RD::PipelineDepthStencilState depth_stencil = depth_stencil_state;
+
+ if (uses_alpha || uses_blend_alpha) {
+ if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_VCT_COLOR_PASS || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) {
+ blend_state = blend_state_blend;
+ if (depth_draw == DEPTH_DRAW_OPAQUE) {
+ depth_stencil.enable_depth_write = false; //alpha does not draw depth
+ }
+ } else if (uses_depth_pre_pass && (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL || k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS)) {
+ if (k == SHADER_VERSION_DEPTH_PASS) {
+ //none, blend state contains nothing
+ } else {
+ blend_state = blend_state_opaque; //writes to normal and roughness in opaque way
+ }
+ } else {
+ pipelines[i][j][k].clear();
+ continue; // do not use this version (will error if using it is attempted)
+ }
+ } else {
+
+ if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_VCT_COLOR_PASS || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) {
+ blend_state = blend_state_opaque;
+ } else if (k == SHADER_VERSION_DEPTH_PASS) {
+ //none, leave empty
+ } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL || k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS) {
+ blend_state = blend_state_opaque; //writes to normal and roughness in opaque way
+ } else {
+ //specular write
+ blend_state = blend_state_opaque_specular;
+ }
+ }
+
+ RID shader_variant = scene_singleton->shader.scene_shader.version_get_shader(version, k);
+
+ if (first) {
+ //should be the same for all, so..
+ vertex_input_mask = RD::get_singleton()->shader_get_vertex_input_attribute_mask(shader_variant);
+ }
+ pipelines[i][j][k].setup(shader_variant, primitive_rd, raster_state, RD::PipelineMultisampleState(), depth_stencil, blend_state, 0);
+ }
+ }
+ }
+
+ valid = true;
+}
+
+void RasterizerSceneForwardRD::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) {
+ if (!p_texture.is_valid()) {
+ default_texture_params.erase(p_name);
+ } else {
+ default_texture_params[p_name] = p_texture;
+ }
+}
+void RasterizerSceneForwardRD::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+
+ Map<int, StringName> order;
+
+ for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
+
+ if (E->get().texture_order >= 0) {
+ order[E->get().texture_order + 100000] = E->key();
+ } else {
+ order[E->get().order] = E->key();
+ }
+ }
+
+ for (Map<int, StringName>::Element *E = order.front(); E; E = E->next()) {
+
+ PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E->get()]);
+ pi.name = E->get();
+ p_param_list->push_back(pi);
+ }
+}
+
+bool RasterizerSceneForwardRD::ShaderData::is_param_texture(const StringName &p_param) const {
+ if (!uniforms.has(p_param)) {
+ return false;
+ }
+
+ return uniforms[p_param].texture_order >= 0;
+}
+
+bool RasterizerSceneForwardRD::ShaderData::is_animated() const {
+ return false;
+}
+bool RasterizerSceneForwardRD::ShaderData::casts_shadows() const {
+ return false;
+}
+Variant RasterizerSceneForwardRD::ShaderData::get_default_parameter(const StringName &p_parameter) const {
+ if (uniforms.has(p_parameter)) {
+ ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter];
+ Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
+ return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.hint);
+ }
+ return Variant();
+}
+
+RasterizerSceneForwardRD::ShaderData::ShaderData() {
+ valid = false;
+ uses_screen_texture = false;
+}
+
+RasterizerSceneForwardRD::ShaderData::~ShaderData() {
+ RasterizerSceneForwardRD *scene_singleton = (RasterizerSceneForwardRD *)RasterizerSceneForwardRD::singleton;
+ ERR_FAIL_COND(!scene_singleton);
+ //pipeline variants will clear themselves if shader is gone
+ if (version.is_valid()) {
+ scene_singleton->shader.scene_shader.version_free(version);
+ }
+}
+
+RasterizerStorageRD::ShaderData *RasterizerSceneForwardRD::_create_shader_func() {
+ ShaderData *shader_data = memnew(ShaderData);
+ return shader_data;
+}
+
+void RasterizerSceneForwardRD::MaterialData::set_render_priority(int p_priority) {
+ priority = p_priority - VS::MATERIAL_RENDER_PRIORITY_MIN; //8 bits
+}
+
+void RasterizerSceneForwardRD::MaterialData::set_next_pass(RID p_pass) {
+ next_pass = p_pass;
+}
+
+void RasterizerSceneForwardRD::MaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
+
+ RasterizerSceneForwardRD *scene_singleton = (RasterizerSceneForwardRD *)RasterizerSceneForwardRD::singleton;
+
+ if ((uint32_t)ubo_data.size() != shader_data->ubo_size) {
+ p_uniform_dirty = true;
+ if (uniform_buffer.is_valid()) {
+ RD::get_singleton()->free(uniform_buffer);
+ uniform_buffer = RID();
+ }
+
+ ubo_data.resize(shader_data->ubo_size);
+ if (ubo_data.size()) {
+ uniform_buffer = RD::get_singleton()->uniform_buffer_create(ubo_data.size());
+ memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear
+ }
+
+ //clear previous uniform set
+ if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
+ RD::get_singleton()->free(uniform_set);
+ uniform_set = RID();
+ }
+ }
+
+ //check whether buffer changed
+ if (p_uniform_dirty && ubo_data.size()) {
+
+ update_uniform_buffer(shader_data->uniforms, shader_data->ubo_offsets.ptr(), p_parameters, ubo_data.ptrw(), ubo_data.size(), false);
+ RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw());
+ }
+
+ uint32_t tex_uniform_count = shader_data->texture_uniforms.size();
+
+ if ((uint32_t)texture_cache.size() != tex_uniform_count) {
+ texture_cache.resize(tex_uniform_count);
+ p_textures_dirty = true;
+
+ //clear previous uniform set
+ if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
+ RD::get_singleton()->free(uniform_set);
+ uniform_set = RID();
+ }
+ }
+
+ if (p_textures_dirty && tex_uniform_count) {
+
+ update_textures(p_parameters, shader_data->default_texture_params, shader_data->texture_uniforms, texture_cache.ptrw());
+ }
+
+ if (shader_data->ubo_size == 0 && shader_data->texture_uniforms.size() == 0) {
+ // This material does not require an uniform set, so don't create it.
+ return;
+ }
+
+ if (!p_textures_dirty && uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
+ //no reason to update uniform set, only UBO (or nothing) was needed to update
+ return;
+ }
+
+ Vector<RD::Uniform> uniforms;
+
+ {
+
+ if (shader_data->ubo_size) {
+ RD::Uniform u;
+ u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 0;
+ u.ids.push_back(uniform_buffer);
+ uniforms.push_back(u);
+ }
+
+ const RID *textures = texture_cache.ptrw();
+ for (uint32_t i = 0; i < tex_uniform_count; i++) {
+ RD::Uniform u;
+ u.type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 1 + i;
+ u.ids.push_back(textures[i]);
+ uniforms.push_back(u);
+ }
+ }
+
+ uniform_set = RD::get_singleton()->uniform_set_create(uniforms, scene_singleton->shader.scene_shader.version_get_shader(shader_data->version, 0), 3);
+}
+RasterizerSceneForwardRD::MaterialData::~MaterialData() {
+ if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
+ RD::get_singleton()->free(uniform_set);
+ }
+
+ if (uniform_buffer.is_valid()) {
+ RD::get_singleton()->free(uniform_buffer);
+ }
+}
+
+RasterizerStorageRD::MaterialData *RasterizerSceneForwardRD::_create_material_func(ShaderData *p_shader) {
+ MaterialData *material_data = memnew(MaterialData);
+ material_data->shader_data = p_shader;
+ material_data->last_frame = false;
+ //update will happen later anyway so do nothing.
+ return material_data;
+}
+
+RasterizerSceneForwardRD::RenderBufferDataForward::~RenderBufferDataForward() {
+ clear();
+}
+
+void RasterizerSceneForwardRD::RenderBufferDataForward::clear() {
+
+ if (color_fb.is_valid()) {
+ RD::get_singleton()->free(color_fb);
+ color_fb = RID();
+ }
+
+ if (color.is_valid()) {
+ RD::get_singleton()->free(color);
+ color = RID();
+ }
+
+ if (depth.is_valid()) {
+ RD::get_singleton()->free(depth);
+ depth = RID();
+ }
+}
+
+void RasterizerSceneForwardRD::RenderBufferDataForward::configure(RID p_render_target, int p_width, int p_height, VS::ViewportMSAA p_msaa) {
+ clear();
+
+ width = p_width;
+ height = p_height;
+
+ render_target = p_render_target;
+
+ {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ tf.width = p_width;
+ tf.height = p_height;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+
+ color = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ }
+ {
+ RD::TextureFormat tf;
+ tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT;
+ tf.width = p_width;
+ tf.height = p_height;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
+
+ depth = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ }
+
+ {
+ Vector<RID> fb;
+ fb.push_back(color);
+ fb.push_back(depth);
+
+ color_fb = RD::get_singleton()->framebuffer_create(fb);
+ }
+}
+
+RasterizerSceneRD::RenderBufferData *RasterizerSceneForwardRD::_create_render_buffer_data() {
+ return memnew(RenderBufferDataForward);
+}
+
+bool RasterizerSceneForwardRD::free(RID p_rid) {
+ if (RasterizerSceneRD::free(p_rid)) {
+ return true;
+ }
+ return false;
+}
+/// INSTANCE DATA ///
+
+void RasterizerSceneForwardRD::instance_create_custom_data(InstanceBase *p_instance) {
+ InstanceGeometryData *geom_data = memnew(InstanceGeometryData);
+ geom_data->ubo = RD::get_singleton()->uniform_buffer_create(sizeof(InstanceGeometryData::UBO));
+}
+
+void RasterizerSceneForwardRD::instance_free_custom_data(InstanceBase *p_instance) {
+ InstanceGeometryData *geom_data = (InstanceGeometryData *)p_instance->custom_data;
+ ERR_FAIL_COND(!geom_data);
+ RD::get_singleton()->free(geom_data->ubo);
+ //uniform sets are freed as dependencies
+ memdelete(geom_data);
+ p_instance->custom_data = nullptr;
+}
+
+void RasterizerSceneForwardRD::instance_custom_data_update_lights(InstanceBase *p_instance) {
+ //unused
+}
+
+void RasterizerSceneForwardRD::instance_custom_data_update_reflection_probes(InstanceBase *p_instance) {
+ //unused
+}
+void RasterizerSceneForwardRD::instance_custom_data_update_lightmap(InstanceBase *p_instance) {
+ InstanceGeometryData *geom_data = (InstanceGeometryData *)p_instance->custom_data;
+ ERR_FAIL_COND(!geom_data);
+
+ geom_data->using_lightmap_gi = p_instance->lightmap.is_valid();
+
+ if (geom_data->uniform_set_gi.is_valid() && RD::get_singleton()->uniform_set_is_valid(geom_data->uniform_set_gi)) {
+ RD::get_singleton()->free(geom_data->uniform_set_gi);
+ }
+ geom_data->uniform_set_gi = RID();
+}
+
+void RasterizerSceneForwardRD::instance_custom_data_update_gi_probes(InstanceBase *p_instance) {
+ InstanceGeometryData *geom_data = (InstanceGeometryData *)p_instance->custom_data;
+ ERR_FAIL_COND(!geom_data);
+
+ geom_data->using_vct_gi = p_instance->gi_probe_instances.size();
+
+ if (geom_data->uniform_set_gi.is_valid() && RD::get_singleton()->uniform_set_is_valid(geom_data->uniform_set_gi)) {
+ RD::get_singleton()->free(geom_data->uniform_set_gi);
+ }
+ geom_data->uniform_set_gi = RID();
+}
+
+void RasterizerSceneForwardRD::instance_custom_data_update_transform(InstanceBase *p_instance) {
+ InstanceGeometryData *geom_data = (InstanceGeometryData *)p_instance->custom_data;
+ ERR_FAIL_COND(!geom_data);
+
+ geom_data->ubo_dirty = true;
+}
+
+/// RENDERING ///
+
+void RasterizerSceneForwardRD::_render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, RID p_screen_uniform_set, bool p_no_gi) {
+
+ RD::DrawListID draw_list = p_draw_list;
+ RD::FramebufferFormatID framebuffer_format = p_framebuffer_Format;
+
+ //global scope bindings
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_screen_uniform_set, 0);
+
+ MaterialData *prev_material = nullptr;
+ // ShaderData *prev_shader = nullptr;
+
+ RID prev_vertex_array_rd;
+ RID prev_index_array_rd;
+
+ for (int i = 0; i < p_element_count; i++) {
+
+ const RenderList::Element *e = p_elements[i];
+
+ MaterialData *material = e->material;
+ ShaderData *shader = material->shader_data;
+
+ //find cull variant
+ ShaderData::CullVariant cull_variant;
+
+ if (p_pass_mode == PASS_MODE_SHADOW && e->instance->cast_shadows == VS::SHADOW_CASTING_SETTING_DOUBLE_SIDED) {
+ cull_variant = ShaderData::CULL_VARIANT_DOUBLE_SIDED;
+ } else {
+ bool mirror = e->instance->mirror;
+ if (p_reverse_cull) {
+ mirror = !mirror;
+ }
+ cull_variant = mirror ? ShaderData::CULL_VARIANT_REVERSED : ShaderData::CULL_VARIANT_NORMAL;
+ }
+
+ //find primitive and vertex format
+ VS::PrimitiveType primitive;
+ RD::VertexFormatID vertex_format;
+ RID vertex_array_rd;
+ RID index_array_rd;
+ RID prev_pipeline_rd;
+
+ switch (e->instance->base_type) {
+ case VS::INSTANCE_MESH: {
+ storage->mesh_get_arrays_primitive_and_format(e->instance->base, e->surface_index, shader->vertex_input_mask, primitive, vertex_array_rd, index_array_rd, vertex_format);
+ } break;
+ case VS::INSTANCE_MULTIMESH: {
+
+ } break;
+ case VS::INSTANCE_IMMEDIATE: {
+
+ } break;
+ case VS::INSTANCE_PARTICLES: {
+
+ } break;
+ default: {
+ ERR_CONTINUE(true); //should be a bug
+ }
+ }
+
+ if (prev_vertex_array_rd != vertex_array_rd) {
+ RD::get_singleton()->draw_list_bind_vertex_array(draw_list, vertex_array_rd);
+ prev_vertex_array_rd = vertex_array_rd;
+ }
+ if (prev_index_array_rd != index_array_rd) {
+ if (index_array_rd.is_valid()) {
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array_rd);
+ }
+ prev_index_array_rd = index_array_rd;
+ }
+
+ InstanceGeometryData *geom_data = (InstanceGeometryData *)e->instance->custom_data;
+
+ ShaderVersion shader_version;
+ RID instance_uniform_set;
+
+ switch (p_pass_mode) {
+ case PASS_MODE_COLOR:
+ case PASS_MODE_COLOR_TRANSPARENT: {
+
+ if (p_no_gi) {
+ instance_uniform_set = geom_data->uniform_set_base;
+ shader_version = SHADER_VERSION_COLOR_PASS;
+ } else if (geom_data->using_lightmap_gi) {
+ instance_uniform_set = geom_data->uniform_set_gi;
+ shader_version = SHADER_VERSION_LIGHTMAP_COLOR_PASS;
+ } else if (geom_data->using_vct_gi) {
+ instance_uniform_set = geom_data->uniform_set_gi;
+ shader_version = SHADER_VERSION_VCT_COLOR_PASS;
+ } else {
+ instance_uniform_set = geom_data->uniform_set_base;
+ shader_version = SHADER_VERSION_COLOR_PASS;
+ }
+ } break;
+ case PASS_MODE_COLOR_SPECULAR: {
+ if (p_no_gi) {
+ instance_uniform_set = geom_data->uniform_set_base;
+ shader_version = SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR;
+ } else if (geom_data->using_lightmap_gi) {
+ instance_uniform_set = geom_data->uniform_set_gi;
+ shader_version = SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR;
+ } else if (geom_data->using_vct_gi) {
+ instance_uniform_set = geom_data->uniform_set_gi;
+ shader_version = SHADER_VERSION_VCT_COLOR_PASS_WITH_SEPARATE_SPECULAR;
+ } else {
+ instance_uniform_set = geom_data->uniform_set_base;
+ shader_version = SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR;
+ }
+ } break;
+ case PASS_MODE_SHADOW: {
+ shader_version = SHADER_VERSION_DEPTH_PASS;
+ instance_uniform_set = geom_data->uniform_set_base;
+ } break;
+ case PASS_MODE_DEPTH: {
+ shader_version = SHADER_VERSION_DEPTH_PASS;
+ instance_uniform_set = geom_data->uniform_set_base;
+ } break;
+ case PASS_MODE_DEPTH_NORMAL: {
+ shader_version = SHADER_VERSION_DEPTH_PASS_WITH_NORMAL;
+ instance_uniform_set = geom_data->uniform_set_base;
+ } break;
+ case PASS_MODE_DEPTH_NORMAL_ROUGHNESS: {
+ shader_version = SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS;
+ instance_uniform_set = geom_data->uniform_set_base;
+ } break;
+ }
+
+ RenderPipelineVertexFormatCacheRD *pipeline = nullptr;
+
+ pipeline = &shader->pipelines[cull_variant][primitive][shader_version];
+
+ RID pipeline_rd = pipeline->get_render_pipeline(vertex_format, framebuffer_format);
+
+ if (pipeline_rd != prev_pipeline_rd) {
+ // checking with prev shader does not make so much sense, as
+ // the pipeline may still be different.
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, pipeline_rd);
+ prev_pipeline_rd = pipeline_rd;
+ }
+
+ if (material != prev_material) {
+ //update uniform set
+ if (material->uniform_set.is_valid()) {
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, material->uniform_set, 2);
+ }
+
+ prev_material = material;
+ }
+
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, instance_uniform_set, 3);
+
+ switch (e->instance->base_type) {
+ case VS::INSTANCE_MESH: {
+ RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid());
+ } break;
+ case VS::INSTANCE_MULTIMESH: {
+
+ } break;
+ case VS::INSTANCE_IMMEDIATE: {
+
+ } break;
+ case VS::INSTANCE_PARTICLES: {
+
+ } break;
+ default: {
+ ERR_CONTINUE(true); //should be a bug
+ }
+ }
+ }
+}
+
+void RasterizerSceneForwardRD::_setup_environment(RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_no_fog) {
+ Transform sky_orientation;
+
+ //store camera into ubo
+ store_camera(p_cam_projection, scene_state.ubo.projection_matrix);
+ store_camera(p_cam_projection.inverse(), scene_state.ubo.inv_projection_matrix);
+ store_transform(p_cam_transform, scene_state.ubo.camera_matrix);
+ store_transform(p_cam_transform.affine_inverse(), scene_state.ubo.inv_camera_matrix);
+
+ //time global variables
+ scene_state.ubo.time = time;
+
+ RD::get_singleton()->buffer_update(scene_state.uniform_buffer, 0, sizeof(SceneState::UBO), &scene_state.ubo, true);
+
+#if 0
+ //bg and ambient
+ if (p_environment.is_valid()) {
+
+ state.ubo_data.bg_energy = env->bg_energy;
+ state.ubo_data.ambient_energy = env->ambient_energy;
+ Color linear_ambient_color = env->ambient_color.to_linear();
+ state.ubo_data.ambient_light_color[0] = linear_ambient_color.r;
+ state.ubo_data.ambient_light_color[1] = linear_ambient_color.g;
+ state.ubo_data.ambient_light_color[2] = linear_ambient_color.b;
+ state.ubo_data.ambient_light_color[3] = linear_ambient_color.a;
+
+ Color bg_color;
+
+ switch (env->bg_mode) {
+ case VS::ENV_BG_CLEAR_COLOR: {
+ bg_color = storage->frame.clear_request_color.to_linear();
+ } break;
+ case VS::ENV_BG_COLOR: {
+ bg_color = env->bg_color.to_linear();
+ } break;
+ default: {
+ bg_color = Color(0, 0, 0, 1);
+ } break;
+ }
+
+ state.ubo_data.bg_color[0] = bg_color.r;
+ state.ubo_data.bg_color[1] = bg_color.g;
+ state.ubo_data.bg_color[2] = bg_color.b;
+ state.ubo_data.bg_color[3] = bg_color.a;
+
+ //use the inverse of our sky_orientation, we may need to skip this if we're using a reflection probe?
+ sky_orientation = Transform(env->sky_orientation, Vector3(0.0, 0.0, 0.0)).affine_inverse();
+
+ state.env_radiance_data.ambient_contribution = env->ambient_sky_contribution;
+ state.ubo_data.ambient_occlusion_affect_light = env->ssao_light_affect;
+ state.ubo_data.ambient_occlusion_affect_ssao = env->ssao_ao_channel_affect;
+
+ //fog
+
+ Color linear_fog = env->fog_color.to_linear();
+ state.ubo_data.fog_color_enabled[0] = linear_fog.r;
+ state.ubo_data.fog_color_enabled[1] = linear_fog.g;
+ state.ubo_data.fog_color_enabled[2] = linear_fog.b;
+ state.ubo_data.fog_color_enabled[3] = (!p_no_fog && env->fog_enabled) ? 1.0 : 0.0;
+ state.ubo_data.fog_density = linear_fog.a;
+
+ Color linear_sun = env->fog_sun_color.to_linear();
+ state.ubo_data.fog_sun_color_amount[0] = linear_sun.r;
+ state.ubo_data.fog_sun_color_amount[1] = linear_sun.g;
+ state.ubo_data.fog_sun_color_amount[2] = linear_sun.b;
+ state.ubo_data.fog_sun_color_amount[3] = env->fog_sun_amount;
+ state.ubo_data.fog_depth_enabled = env->fog_depth_enabled;
+ state.ubo_data.fog_depth_begin = env->fog_depth_begin;
+ state.ubo_data.fog_depth_end = env->fog_depth_end;
+ state.ubo_data.fog_depth_curve = env->fog_depth_curve;
+ state.ubo_data.fog_transmit_enabled = env->fog_transmit_enabled;
+ state.ubo_data.fog_transmit_curve = env->fog_transmit_curve;
+ state.ubo_data.fog_height_enabled = env->fog_height_enabled;
+ state.ubo_data.fog_height_min = env->fog_height_min;
+ state.ubo_data.fog_height_max = env->fog_height_max;
+ state.ubo_data.fog_height_curve = env->fog_height_curve;
+
+ } else {
+ state.ubo_data.bg_energy = 1.0;
+ state.ubo_data.ambient_energy = 1.0;
+ //use from clear color instead, since there is no ambient
+ Color linear_ambient_color = storage->frame.clear_request_color.to_linear();
+ state.ubo_data.ambient_light_color[0] = linear_ambient_color.r;
+ state.ubo_data.ambient_light_color[1] = linear_ambient_color.g;
+ state.ubo_data.ambient_light_color[2] = linear_ambient_color.b;
+ state.ubo_data.ambient_light_color[3] = linear_ambient_color.a;
+
+ state.ubo_data.bg_color[0] = linear_ambient_color.r;
+ state.ubo_data.bg_color[1] = linear_ambient_color.g;
+ state.ubo_data.bg_color[2] = linear_ambient_color.b;
+ state.ubo_data.bg_color[3] = linear_ambient_color.a;
+
+ state.env_radiance_data.ambient_contribution = 0;
+ state.ubo_data.ambient_occlusion_affect_light = 0;
+
+ state.ubo_data.fog_color_enabled[3] = 0.0;
+ }
+
+ {
+ //directional shadow
+
+ state.ubo_data.shadow_directional_pixel_size[0] = 1.0 / directional_shadow.size;
+ state.ubo_data.shadow_directional_pixel_size[1] = 1.0 / directional_shadow.size;
+
+ glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4);
+ glBindTexture(GL_TEXTURE_2D, directional_shadow.depth);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LESS);
+ }
+
+ glBindBuffer(GL_UNIFORM_BUFFER, state.scene_ubo);
+ glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(State::SceneDataUBO), &state.ubo_data);
+ glBindBuffer(GL_UNIFORM_BUFFER, 0);
+
+ //fill up environment
+
+ store_transform(sky_orientation * p_cam_transform, state.env_radiance_data.transform);
+
+ glBindBuffer(GL_UNIFORM_BUFFER, state.env_radiance_ubo);
+ glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(State::EnvironmentRadianceUBO), &state.env_radiance_data);
+ glBindBuffer(GL_UNIFORM_BUFFER, 0);
+#endif
+}
+
+void RasterizerSceneForwardRD::_add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode) {
+
+ RID m_src = p_instance->material_override.is_valid() ? p_instance->material_override : p_material;
+
+ /*if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_OVERDRAW) {
+ m_src = default_overdraw_material;
+ }*/
+
+ MaterialData *material = NULL;
+
+ if (m_src.is_valid()) {
+ material = (MaterialData *)storage->material_get_data(m_src, RasterizerStorageRD::SHADER_TYPE_3D);
+ if (!material || !material->shader_data->valid) {
+ material = NULL;
+ }
+ }
+
+ if (!material) {
+ material = (MaterialData *)storage->material_get_data(default_material, RasterizerStorageRD::SHADER_TYPE_3D);
+ }
+
+ ERR_FAIL_COND(!material);
+
+ _add_geometry_with_material(p_instance, p_surface, material, p_pass_mode);
+
+ while (material->next_pass.is_valid()) {
+
+ material = (MaterialData *)storage->material_get_data(material->next_pass, RasterizerStorageRD::SHADER_TYPE_3D);
+ if (!material || !material->shader_data->valid)
+ break;
+ _add_geometry_with_material(p_instance, p_surface, material, p_pass_mode);
+ }
+}
+
+void RasterizerSceneForwardRD::_add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, PassMode p_pass_mode) {
+
+ bool has_read_screen_alpha = p_material->shader_data->uses_screen_texture || p_material->shader_data->uses_depth_texture || p_material->shader_data->uses_normal_texture;
+ bool has_base_alpha = (p_material->shader_data->uses_alpha || has_read_screen_alpha);
+ bool has_blend_alpha = p_material->shader_data->uses_blend_alpha;
+ bool has_alpha = has_base_alpha || has_blend_alpha;
+
+ if (p_material->shader_data->uses_sss) {
+ scene_state.used_sss = true;
+ }
+
+ if (p_material->shader_data->uses_screen_texture) {
+ scene_state.used_screen_texture = true;
+ }
+
+ if (p_material->shader_data->uses_depth_texture) {
+ scene_state.used_depth_texture = true;
+ }
+
+ if (p_material->shader_data->uses_normal_texture) {
+ scene_state.used_normal_texture = true;
+ }
+
+ if (p_pass_mode != PASS_MODE_COLOR && p_pass_mode != PASS_MODE_COLOR_SPECULAR) {
+
+ if (has_blend_alpha || has_read_screen_alpha || (has_base_alpha && !p_material->shader_data->uses_depth_pre_pass) || p_material->shader_data->depth_draw == ShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == ShaderData::DEPTH_TEST_DISABLED || p_instance->cast_shadows == VS::SHADOW_CASTING_SETTING_OFF) {
+ //conditions in which no depth pass should be processed
+ return;
+ }
+
+ if (!p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass) {
+ //shader does not use discard and does not write a vertex position, use generic material
+ if (p_pass_mode == PASS_MODE_SHADOW || p_pass_mode == PASS_MODE_DEPTH) {
+ p_material = (MaterialData *)storage->material_get_data(default_material, RasterizerStorageRD::SHADER_TYPE_3D);
+ } else if (p_pass_mode == PASS_MODE_DEPTH_NORMAL && !p_material->shader_data->uses_normal) {
+ p_material = (MaterialData *)storage->material_get_data(default_material, RasterizerStorageRD::SHADER_TYPE_3D);
+ } else if (p_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS && !p_material->shader_data->uses_normal && !p_material->shader_data->uses_roughness) {
+ p_material = (MaterialData *)storage->material_get_data(default_material, RasterizerStorageRD::SHADER_TYPE_3D);
+ }
+ }
+
+ has_alpha = false;
+ }
+
+ RenderList::Element *e = (has_alpha || p_material->shader_data->depth_test == ShaderData::DEPTH_TEST_DISABLED) ? render_list.add_alpha_element() : render_list.add_element();
+
+ if (!e)
+ return;
+
+ e->instance = p_instance;
+ e->material = p_material;
+ e->surface_index = p_surface;
+ e->sort_key = 0;
+
+ if (e->material->last_pass != render_pass) {
+ e->material->last_pass = render_pass;
+ e->material->index = scene_state.current_material_index++;
+ if (e->material->shader_data->last_pass != render_pass) {
+ e->material->shader_data->last_pass = scene_state.current_material_index++;
+ e->material->shader_data->index = scene_state.current_shader_index++;
+ }
+ }
+
+ e->material_index = e->material->index;
+ e->shader_index = e->shader_index;
+ e->depth_layer = e->instance->depth_layer;
+ e->priority = p_material->priority;
+
+ if (p_material->shader_data->uses_time) {
+ VisualServerRaster::redraw_request();
+ }
+}
+
+void RasterizerSceneForwardRD::_fill_render_list(InstanceBase **p_cull_result, int p_cull_count, PassMode p_pass_mode, bool p_no_gi) {
+
+ scene_state.current_shader_index = 0;
+ scene_state.current_material_index = 0;
+ scene_state.used_sss = false;
+ scene_state.used_screen_texture = false;
+ scene_state.used_normal_texture = false;
+ scene_state.used_depth_texture = false;
+
+ //fill list
+
+ for (int i = 0; i < p_cull_count; i++) {
+
+ InstanceBase *inst = p_cull_result[i];
+
+ InstanceGeometryData *geom_data = (InstanceGeometryData *)inst->custom_data;
+
+ ERR_CONTINUE(!geom_data);
+
+ if (geom_data->ubo_dirty) {
+ //ubo marked dirty, must be updated
+ InstanceGeometryData::UBO ubo;
+ store_transform(inst->transform, ubo.transform);
+ store_transform_3x3(inst->transform.basis.inverse().transposed(), ubo.normal_transform);
+ ubo.flags = 0;
+ ubo.pad[0];
+ ubo.pad[1];
+ ubo.pad[2];
+ RD::get_singleton()->buffer_update(geom_data->ubo, 0, sizeof(InstanceGeometryData::UBO), &ubo, true);
+ }
+
+ if (p_no_gi) {
+ if (geom_data->uniform_set_base.is_null() || !RD::get_singleton()->uniform_set_is_valid(geom_data->uniform_set_base)) {
+
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 0;
+ u.ids.push_back(geom_data->ubo);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.type = RD::UNIFORM_TYPE_TEXTURE_BUFFER;
+ u.binding = 1;
+ u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER));
+ uniforms.push_back(u);
+ }
+
+ geom_data->uniform_set_base = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, 3);
+ }
+ } else {
+ if (geom_data->uniform_set_gi.is_null() || !RD::get_singleton()->uniform_set_is_valid(geom_data->uniform_set_gi)) {
+
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 0;
+ u.ids.push_back(geom_data->ubo);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.type = RD::UNIFORM_TYPE_TEXTURE_BUFFER;
+ u.binding = 1;
+ u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER));
+ uniforms.push_back(u);
+ }
+
+ if (geom_data->using_lightmap_gi) {
+ {
+ RD::Uniform u;
+ u.type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 2;
+#ifndef _MSC_VER
+#warning Need to put actual lightmap or lightmap capture texture if exists
+#endif
+ u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE));
+ uniforms.push_back(u);
+ }
+ } else if (geom_data->using_vct_gi) {
+#ifndef _MSC_VER
+#warning Need to put actual vct textures here
+#endif
+ }
+
+ geom_data->uniform_set_gi = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, 3);
+ }
+ }
+
+ //add geometry for drawing
+ switch (inst->base_type) {
+
+ case VS::INSTANCE_MESH: {
+
+ const RID *materials = NULL;
+ uint32_t surface_count;
+
+ materials = storage->mesh_get_surface_count_and_materials(inst->base, surface_count);
+ if (!materials) {
+ continue; //nothing to do
+ }
+
+ const RID *inst_materials = inst->materials.ptr();
+
+ for (uint32_t j = 0; j < surface_count; j++) {
+
+ RID material = inst_materials[j].is_valid() ? inst_materials[j] : materials[j];
+
+ _add_geometry(inst, j, material, p_pass_mode);
+ }
+
+ //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)
+ continue;
+
+ RasterizerStorageGLES3::Mesh *mesh = storage->mesh_owner.getornull(multi_mesh->mesh);
+ if (!mesh)
+ continue; //mesh not assigned
+
+ int ssize = mesh->surfaces.size();
+
+ for (int j = 0; j < ssize; j++) {
+
+ RasterizerStorageGLES3::Surface *s = mesh->surfaces[j];
+ _add_geometry(s, inst, multi_mesh, -1, p_depth_pass, p_shadow_pass);
+ }
+
+ } break;
+ case VS::INSTANCE_IMMEDIATE: {
+
+ RasterizerStorageGLES3::Immediate *immediate = storage->immediate_owner.getornull(inst->base);
+ ERR_CONTINUE(!immediate);
+
+ _add_geometry(immediate, inst, NULL, -1, p_depth_pass, p_shadow_pass);
+
+ } break;
+ case VS::INSTANCE_PARTICLES: {
+
+ RasterizerStorageGLES3::Particles *particles = storage->particles_owner.getornull(inst->base);
+ ERR_CONTINUE(!particles);
+
+ for (int j = 0; j < particles->draw_passes.size(); j++) {
+
+ RID pmesh = particles->draw_passes[j];
+ if (!pmesh.is_valid())
+ continue;
+ RasterizerStorageGLES3::Mesh *mesh = storage->mesh_owner.getornull(pmesh);
+ if (!mesh)
+ continue; //mesh not assigned
+
+ int ssize = mesh->surfaces.size();
+
+ for (int k = 0; k < ssize; k++) {
+
+ RasterizerStorageGLES3::Surface *s = mesh->surfaces[k];
+ _add_geometry(s, inst, particles, -1, p_depth_pass, p_shadow_pass);
+ }
+ }
+
+ } break;
+#endif
+ default: {
+ }
+ }
+ }
+}
+
+void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
+
+ RenderBufferDataForward *render_buffer = (RenderBufferDataForward *)p_buffer_data;
+
+ ERR_FAIL_COND(!render_buffer); //bug out for now
+
+ //first of all, make a new render pass
+ render_pass++;
+
+ //fill up ubo
+#if 0
+ storage->info.render.object_count += p_cull_count;
+
+ Environment *env = environment_owner.getornull(p_environment);
+ ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
+ ReflectionAtlas *reflection_atlas = reflection_atlas_owner.getornull(p_reflection_atlas);
+
+ if (shadow_atlas && shadow_atlas->size) {
+ glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 5);
+ glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LESS);
+ scene_state.ubo.shadow_atlas_pixel_size[0] = 1.0 / shadow_atlas->size;
+ scene_state.ubo.shadow_atlas_pixel_size[1] = 1.0 / shadow_atlas->size;
+ }
+
+ if (reflection_atlas && reflection_atlas->size) {
+ glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3);
+ glBindTexture(GL_TEXTURE_2D, reflection_atlas->color);
+ }
+#endif
+ if (p_reflection_probe.is_valid()) {
+ scene_state.ubo.reflection_multiplier = 0.0;
+ } else {
+ scene_state.ubo.reflection_multiplier = 1.0;
+ }
+
+ //scene_state.ubo.subsurface_scatter_width = subsurface_scatter_size;
+
+ scene_state.ubo.shadow_z_offset = 0;
+ scene_state.ubo.shadow_z_slope_scale = 0;
+
+ Vector2 vp_he = p_cam_projection.get_viewport_half_extents();
+ scene_state.ubo.viewport_size[0] = vp_he.x;
+ scene_state.ubo.viewport_size[1] = vp_he.y;
+
+ if (render_buffer) {
+ scene_state.ubo.screen_pixel_size[0] = 1.0 / render_buffer->width;
+ scene_state.ubo.screen_pixel_size[1] = 1.0 / render_buffer->height;
+ }
+
+ _setup_environment(p_environment, p_cam_projection, p_cam_transform, p_reflection_probe.is_valid());
+#if 0
+ for (int i = 0; i < p_light_cull_count; i++) {
+
+ ERR_BREAK(i >= RenderList::MAX_LIGHTS);
+
+ LightInstance *li = light_instance_owner.getornull(p_light_cull_result[i]);
+ if (li->light_ptr->param[VS::LIGHT_PARAM_CONTACT_SHADOW_SIZE] > CMP_EPSILON) {
+ state.used_contact_shadows = true;
+ }
+ }
+#endif
+#if 0
+ // Do depth prepass if it's explicitly enabled
+ bool use_depth_prepass = storage->config.use_depth_prepass;
+
+ // If contact shadows are used then we need to do depth prepass even if it's otherwise disabled
+ use_depth_prepass = use_depth_prepass || state.used_contact_shadows;
+
+ // Never do depth prepass if effects are disabled or if we render overdraws
+ use_depth_prepass = use_depth_prepass && storage->frame.current_rt && !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_NO_3D_EFFECTS];
+ use_depth_prepass = use_depth_prepass && state.debug_draw != VS::VIEWPORT_DEBUG_DRAW_OVERDRAW;
+
+ if (use_depth_prepass) {
+ //pre z pass
+
+ glDisable(GL_BLEND);
+ glDepthMask(GL_TRUE);
+ glEnable(GL_DEPTH_TEST);
+ glDisable(GL_SCISSOR_TEST);
+ glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo);
+ glDrawBuffers(0, NULL);
+
+ glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height);
+
+ glColorMask(0, 0, 0, 0);
+ glClearDepth(1.0f);
+ glClear(GL_DEPTH_BUFFER_BIT);
+
+ render_list.clear();
+ _fill_render_list(p_cull_result, p_cull_count, true, false);
+ render_list.sort_by_key(false);
+ state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_DEPTH, true);
+ _render_list(render_list.elements, render_list.element_count, p_cam_transform, p_cam_projection, 0, false, false, true, false, false);
+ state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_DEPTH, false);
+
+ glColorMask(1, 1, 1, 1);
+
+ if (state.used_contact_shadows) {
+
+ _prepare_depth_texture();
+ _bind_depth_texture();
+ }
+
+ fb_cleared = true;
+ render_pass++;
+ state.used_depth_prepass = true;
+ } else {
+ state.used_depth_prepass = false;
+ }
+
+ _setup_lights(p_light_cull_result, p_light_cull_count, p_cam_transform.affine_inverse(), p_cam_projection, p_shadow_atlas);
+ _setup_reflections(p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_cam_transform.affine_inverse(), p_cam_projection, p_reflection_atlas, env);
+
+ bool use_mrt = false;
+#endif
+ render_list.clear();
+ _fill_render_list(p_cull_result, p_cull_count, PASS_MODE_COLOR, render_buffer == nullptr);
+#if 0
+ //
+
+ glEnable(GL_BLEND);
+ glDepthMask(GL_TRUE);
+ glEnable(GL_DEPTH_TEST);
+ glDisable(GL_SCISSOR_TEST);
+
+ //rendering to a probe cubemap side
+ ReflectionProbeInstance *probe = reflection_probe_instance_owner.getornull(p_reflection_probe);
+ GLuint current_fbo;
+
+ if (probe) {
+
+ ReflectionAtlas *ref_atlas = reflection_atlas_owner.getornull(probe->atlas);
+ ERR_FAIL_COND(!ref_atlas);
+
+ int target_size = ref_atlas->size / ref_atlas->subdiv;
+
+ int cubemap_index = reflection_cubemaps.size() - 1;
+
+ for (int i = reflection_cubemaps.size() - 1; i >= 0; i--) {
+ //find appropriate cubemap to render to
+ if (reflection_cubemaps[i].size > target_size * 2)
+ break;
+
+ cubemap_index = i;
+ }
+
+ current_fbo = reflection_cubemaps[cubemap_index].fbo_id[p_reflection_probe_pass];
+ use_mrt = false;
+ state.scene_shader.set_conditional(SceneShaderGLES3::USE_MULTIPLE_RENDER_TARGETS, false);
+
+ glViewport(0, 0, reflection_cubemaps[cubemap_index].size, reflection_cubemaps[cubemap_index].size);
+ glBindFramebuffer(GL_FRAMEBUFFER, current_fbo);
+
+ } else {
+
+ use_mrt = env && (state.used_sss || env->ssao_enabled || env->ssr_enabled || env->dof_blur_far_enabled || env->dof_blur_near_enabled); //only enable MRT rendering if any of these is enabled
+ //effects disabled and transparency also prevent using MRTs
+ use_mrt = use_mrt && !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT];
+ use_mrt = use_mrt && !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_NO_3D_EFFECTS];
+ use_mrt = use_mrt && state.debug_draw != VS::VIEWPORT_DEBUG_DRAW_OVERDRAW;
+ use_mrt = use_mrt && (env->bg_mode != VS::ENV_BG_KEEP && env->bg_mode != VS::ENV_BG_CANVAS);
+
+ glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height);
+
+ if (use_mrt) {
+
+ current_fbo = storage->frame.current_rt->buffers.fbo;
+
+ glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo);
+ state.scene_shader.set_conditional(SceneShaderGLES3::USE_MULTIPLE_RENDER_TARGETS, true);
+
+ Vector<GLenum> draw_buffers;
+ draw_buffers.push_back(GL_COLOR_ATTACHMENT0);
+ draw_buffers.push_back(GL_COLOR_ATTACHMENT1);
+ draw_buffers.push_back(GL_COLOR_ATTACHMENT2);
+ if (state.used_sss) {
+ draw_buffers.push_back(GL_COLOR_ATTACHMENT3);
+ }
+ glDrawBuffers(draw_buffers.size(), draw_buffers.ptr());
+
+ Color black(0, 0, 0, 0);
+ glClearBufferfv(GL_COLOR, 1, black.components); // specular
+ glClearBufferfv(GL_COLOR, 2, black.components); // normal metal rough
+ if (state.used_sss) {
+ glClearBufferfv(GL_COLOR, 3, black.components); // normal metal rough
+ }
+
+ } else {
+
+ if (storage->frame.current_rt->buffers.active) {
+ current_fbo = storage->frame.current_rt->buffers.fbo;
+ } else {
+ current_fbo = storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo;
+ }
+
+ glBindFramebuffer(GL_FRAMEBUFFER, current_fbo);
+ state.scene_shader.set_conditional(SceneShaderGLES3::USE_MULTIPLE_RENDER_TARGETS, false);
+
+ Vector<GLenum> draw_buffers;
+ draw_buffers.push_back(GL_COLOR_ATTACHMENT0);
+ glDrawBuffers(draw_buffers.size(), draw_buffers.ptr());
+ }
+ }
+
+ if (!fb_cleared) {
+ glClearDepth(1.0f);
+ glClear(GL_DEPTH_BUFFER_BIT);
+ }
+
+ Color clear_color(0, 0, 0, 0);
+
+ RasterizerStorageGLES3::Sky *sky = NULL;
+ Ref<CameraFeed> feed;
+ GLuint env_radiance_tex = 0;
+
+ if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_OVERDRAW) {
+ clear_color = Color(0, 0, 0, 0);
+ storage->frame.clear_request = false;
+ } else if (!probe && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
+ clear_color = Color(0, 0, 0, 0);
+ storage->frame.clear_request = false;
+
+ } else if (!env || env->bg_mode == VS::ENV_BG_CLEAR_COLOR) {
+
+ if (storage->frame.clear_request) {
+
+ clear_color = storage->frame.clear_request_color.to_linear();
+ storage->frame.clear_request = false;
+ }
+
+ } else if (env->bg_mode == VS::ENV_BG_CANVAS) {
+
+ clear_color = env->bg_color.to_linear();
+ storage->frame.clear_request = false;
+ } else if (env->bg_mode == VS::ENV_BG_COLOR) {
+
+ clear_color = env->bg_color.to_linear();
+ storage->frame.clear_request = false;
+ } else if (env->bg_mode == VS::ENV_BG_SKY) {
+
+ storage->frame.clear_request = false;
+
+ } else if (env->bg_mode == VS::ENV_BG_COLOR_SKY) {
+
+ clear_color = env->bg_color.to_linear();
+ storage->frame.clear_request = false;
+
+ } else if (env->bg_mode == VS::ENV_BG_CAMERA_FEED) {
+ feed = CameraServer::get_singleton()->get_feed_by_id(env->camera_feed_id);
+ storage->frame.clear_request = false;
+ } else {
+ storage->frame.clear_request = false;
+ }
+
+ if (!env || env->bg_mode != VS::ENV_BG_KEEP) {
+ glClearBufferfv(GL_COLOR, 0, clear_color.components); // specular
+ }
+
+ VS::EnvironmentBG bg_mode = (!env || (probe && env->bg_mode == VS::ENV_BG_CANVAS)) ? VS::ENV_BG_CLEAR_COLOR : env->bg_mode; //if no environment, or canvas while rendering a probe (invalid use case), use color.
+
+ if (env) {
+ switch (bg_mode) {
+ case VS::ENV_BG_COLOR_SKY:
+ case VS::ENV_BG_SKY:
+
+ sky = storage->sky_owner.getornull(env->sky);
+
+ if (sky) {
+ env_radiance_tex = sky->radiance;
+ }
+ break;
+ case VS::ENV_BG_CANVAS:
+ //copy canvas to 3d buffer and convert it to linear
+
+ glDisable(GL_BLEND);
+ glDepthMask(GL_FALSE);
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_CULL_FACE);
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color);
+
+ storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, true);
+
+ storage->shaders.copy.set_conditional(CopyShaderGLES3::SRGB_TO_LINEAR, true);
+
+ storage->shaders.copy.bind();
+
+ _copy_screen(true, true);
+
+ //turn off everything used
+ storage->shaders.copy.set_conditional(CopyShaderGLES3::SRGB_TO_LINEAR, false);
+ storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, false);
+
+ //restore
+ glEnable(GL_BLEND);
+ glDepthMask(GL_TRUE);
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_CULL_FACE);
+ break;
+ case VS::ENV_BG_CAMERA_FEED:
+ if (feed.is_valid() && (feed->get_base_width() > 0) && (feed->get_base_height() > 0)) {
+ // copy our camera feed to our background
+
+ glDisable(GL_BLEND);
+ glDepthMask(GL_FALSE);
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_CULL_FACE);
+
+ storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_DISPLAY_TRANSFORM, true);
+ storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, true);
+ storage->shaders.copy.set_conditional(CopyShaderGLES3::SRGB_TO_LINEAR, true);
+
+ if (feed->get_datatype() == CameraFeed::FEED_RGB) {
+ RID camera_RGBA = feed->get_texture(CameraServer::FEED_RGBA_IMAGE);
+
+ VS::get_singleton()->texture_bind(camera_RGBA, 0);
+ } else if (feed->get_datatype() == CameraFeed::FEED_YCBCR) {
+ RID camera_YCbCr = feed->get_texture(CameraServer::FEED_YCBCR_IMAGE);
+
+ VS::get_singleton()->texture_bind(camera_YCbCr, 0);
+
+ storage->shaders.copy.set_conditional(CopyShaderGLES3::YCBCR_TO_SRGB, true);
+
+ } else if (feed->get_datatype() == CameraFeed::FEED_YCBCR_SEP) {
+ RID camera_Y = feed->get_texture(CameraServer::FEED_Y_IMAGE);
+ RID camera_CbCr = feed->get_texture(CameraServer::FEED_CBCR_IMAGE);
+
+ VS::get_singleton()->texture_bind(camera_Y, 0);
+ VS::get_singleton()->texture_bind(camera_CbCr, 1);
+
+ storage->shaders.copy.set_conditional(CopyShaderGLES3::SEP_CBCR_TEXTURE, true);
+ storage->shaders.copy.set_conditional(CopyShaderGLES3::YCBCR_TO_SRGB, true);
+ };
+
+ storage->shaders.copy.bind();
+ storage->shaders.copy.set_uniform(CopyShaderGLES3::DISPLAY_TRANSFORM, feed->get_transform());
+
+ _copy_screen(true, true);
+
+ //turn off everything used
+ storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_DISPLAY_TRANSFORM, false);
+ storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, false);
+ storage->shaders.copy.set_conditional(CopyShaderGLES3::SRGB_TO_LINEAR, false);
+ storage->shaders.copy.set_conditional(CopyShaderGLES3::SEP_CBCR_TEXTURE, false);
+ storage->shaders.copy.set_conditional(CopyShaderGLES3::YCBCR_TO_SRGB, false);
+
+ //restore
+ glEnable(GL_BLEND);
+ glDepthMask(GL_TRUE);
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_CULL_FACE);
+ } else {
+ // don't have a feed, just show greenscreen :)
+ clear_color = Color(0.0, 1.0, 0.0, 1.0);
+ }
+ break;
+ default: {
+ }
+ }
+ }
+
+ if (probe && probe->probe_ptr->interior) {
+ env_radiance_tex = 0; //for rendering probe interiors, radiance must not be used.
+ }
+
+ state.texscreen_copied = false;
+
+ glBlendEquation(GL_FUNC_ADD);
+
+ if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ } else {
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glDisable(GL_BLEND);
+ }
+#endif
+
+ render_list.sort_by_key(false);
+
+ {
+ //regular forward for now
+ Vector<Color> c;
+ c.push_back(Color(0, 0, 0, 1));
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(render_buffer->color_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_CONTINUE, c);
+
+ _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(render_buffer->color_fb), render_list.elements, render_list.element_count, false, PASS_MODE_COLOR, default_render_buffer_uniform_set, render_buffer == nullptr);
+ RD::get_singleton()->draw_list_end();
+ }
+
+ //_render_list
+#if 0
+ if (state.directional_light_count == 0) {
+ directional_light = NULL;
+ _render_list(render_list.elements, render_list.element_count, p_cam_transform, p_cam_projection, env_radiance_tex, false, false, false, false, shadow_atlas != NULL);
+ } else {
+ for (int i = 0; i < state.directional_light_count; i++) {
+ directional_light = directional_lights[i];
+ if (i > 0) {
+ glEnable(GL_BLEND);
+ }
+ _setup_directional_light(i, p_cam_transform.affine_inverse(), shadow_atlas != NULL && shadow_atlas->size > 0);
+ _render_list(render_list.elements, render_list.element_count, p_cam_transform, p_cam_projection, env_radiance_tex, false, false, false, i > 0, shadow_atlas != NULL);
+ }
+ }
+
+ state.scene_shader.set_conditional(SceneShaderGLES3::USE_MULTIPLE_RENDER_TARGETS, false);
+
+ if (use_mrt) {
+ GLenum gldb = GL_COLOR_ATTACHMENT0;
+ glDrawBuffers(1, &gldb);
+ }
+
+ if (env && env->bg_mode == VS::ENV_BG_SKY && (!storage->frame.current_rt || (!storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT] && state.debug_draw != VS::VIEWPORT_DEBUG_DRAW_OVERDRAW))) {
+
+ /*
+ if (use_mrt) {
+ glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.fbo); //switch to alpha fbo for sky, only diffuse/ambient matters
+ */
+
+ if (sky && sky->panorama.is_valid())
+ _draw_sky(sky, p_cam_projection, p_cam_transform, false, env->sky_custom_fov, env->bg_energy, env->sky_orientation);
+ }
+
+ //_render_list_forward(&alpha_render_list,camera_transform,camera_transform_inverse,camera_projection,false,fragment_lighting,true);
+ //glColorMask(1,1,1,1);
+
+ //state.scene_shader.set_conditional( SceneShaderGLES3::USE_FOG,false);
+
+ if (use_mrt) {
+
+ _render_mrts(env, p_cam_projection);
+ } else {
+ // Here we have to do the blits/resolves that otherwise are done in the MRT rendering, in particular
+ // - prepare screen texture for any geometry that uses a shader with screen texture
+ // - prepare depth texture for any geometry that uses a shader with depth texture
+
+ bool framebuffer_dirty = false;
+
+ if (storage->frame.current_rt && storage->frame.current_rt->buffers.active && state.used_screen_texture) {
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo);
+ glReadBuffer(GL_COLOR_ATTACHMENT0);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo);
+ glBlitFramebuffer(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, 0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
+ _blur_effect_buffer();
+ framebuffer_dirty = true;
+ }
+
+ if (storage->frame.current_rt && storage->frame.current_rt->buffers.active && state.used_depth_texture) {
+ _prepare_depth_texture();
+ framebuffer_dirty = true;
+ }
+
+ if (framebuffer_dirty) {
+ // Restore framebuffer
+ glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo);
+ glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height);
+ }
+ }
+
+ if (storage->frame.current_rt && state.used_depth_texture && storage->frame.current_rt->buffers.active) {
+ _bind_depth_texture();
+ }
+
+ if (storage->frame.current_rt && state.used_screen_texture && storage->frame.current_rt->buffers.active) {
+ glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 7);
+ glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color);
+ }
+
+ glEnable(GL_BLEND);
+ glDepthMask(GL_TRUE);
+ glEnable(GL_DEPTH_TEST);
+ glDisable(GL_SCISSOR_TEST);
+#endif
+ render_list.sort_by_reverse_depth_and_priority(true);
+
+ {
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(render_buffer->color_fb, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_READ_COLOR_DISCARD_DEPTH);
+ _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(render_buffer->color_fb), render_list.elements, render_list.element_count, false, PASS_MODE_COLOR, default_render_buffer_uniform_set, render_buffer == nullptr);
+ RD::get_singleton()->draw_list_end();
+ }
+
+ //_render_list
+#if 0
+ if (state.directional_light_count == 0) {
+ directional_light = NULL;
+ _render_list(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, p_cam_transform, p_cam_projection, env_radiance_tex, false, true, false, false, shadow_atlas != NULL);
+ } else {
+ for (int i = 0; i < state.directional_light_count; i++) {
+ directional_light = directional_lights[i];
+ _setup_directional_light(i, p_cam_transform.affine_inverse(), shadow_atlas != NULL && shadow_atlas->size > 0);
+ _render_list(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, p_cam_transform, p_cam_projection, env_radiance_tex, false, true, false, i > 0, shadow_atlas != NULL);
+ }
+ }
+#endif
+ if (p_reflection_probe.is_valid()) {
+ //rendering a probe, do no more!
+ return;
+ }
+
+ RasterizerEffectsRD *effects = storage->get_effects();
+ effects->copy(render_buffer->color, storage->render_target_get_rd_framebuffer(render_buffer->render_target), Rect2());
+
+#if 0
+ _post_process(env, p_cam_projection);
+ // Needed only for debugging
+ /* if (shadow_atlas && storage->frame.current_rt) {
+
+ //_copy_texture_to_front_buffer(shadow_atlas->depth);
+ storage->canvas->canvas_begin();
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
+ storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1));
+ }
+
+ if (storage->frame.current_rt) {
+
+ //_copy_texture_to_front_buffer(shadow_atlas->depth);
+ storage->canvas->canvas_begin();
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, exposure_shrink[4].color);
+ //glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->exposure.color);
+ storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 16, storage->frame.current_rt->height / 16), Rect2(0, 0, 1, 1));
+ }
+
+ if (reflection_atlas && storage->frame.current_rt) {
+
+ //_copy_texture_to_front_buffer(shadow_atlas->depth);
+ storage->canvas->canvas_begin();
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, reflection_atlas->color);
+ storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1));
+ }
+
+ if (directional_shadow.fbo) {
+
+ //_copy_texture_to_front_buffer(shadow_atlas->depth);
+ storage->canvas->canvas_begin();
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, directional_shadow.depth);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
+ storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1));
+ }
+
+ if ( env_radiance_tex) {
+
+ //_copy_texture_to_front_buffer(shadow_atlas->depth);
+ storage->canvas->canvas_begin();
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, env_radiance_tex);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1));
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ }*/
+ //disable all stuff
+#endif
+}
+
+RasterizerSceneForwardRD *RasterizerSceneForwardRD::singleton = NULL;
+
+void RasterizerSceneForwardRD::set_scene_pass(uint64_t p_pass) {
+ scene_pass = p_pass;
+}
+
+void RasterizerSceneForwardRD::set_time(double p_time) {
+ time = p_time;
+}
+
+RasterizerSceneForwardRD::RasterizerSceneForwardRD(RasterizerStorageRD *p_storage) {
+ storage = p_storage;
+
+ /* SHADER */
+
+ {
+ String defines;
+
+ Vector<String> shader_versions;
+ shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n");
+ shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define ENABLE_WRITE_NORMAL_BUFFER\n");
+ shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define ENABLE_WRITE_NORMAL_ROUGHNESS_BUFFER\n");
+ shader_versions.push_back("");
+ shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n");
+ shader_versions.push_back("\n#define USE_VOXEL_CONE_TRACING\n");
+ shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n#define USE_VOXEL_CONE_TRACING\n");
+ shader_versions.push_back("\n#define USE_LIGHTMAP\n");
+ shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n#define USE_LIGHTMAP\n");
+ shader.scene_shader.initialize(shader_versions, defines);
+ }
+
+ storage->shader_set_data_request_function(RasterizerStorageRD::SHADER_TYPE_3D, _create_shader_funcs);
+ storage->material_set_data_request_function(RasterizerStorageRD::SHADER_TYPE_3D, _create_material_funcs);
+
+ {
+ //shader compiler
+ ShaderCompilerRD::DefaultIdentifierActions actions;
+
+ actions.renames["WORLD_MATRIX"] = "world_matrix";
+ actions.renames["WORLD_NORMAL_MATRIX"] = "world_normal_matrix";
+ actions.renames["INV_CAMERA_MATRIX"] = "scene_data.camera_inverse_matrix";
+ actions.renames["CAMERA_MATRIX"] = "scene_data.camera_matrix";
+ actions.renames["PROJECTION_MATRIX"] = "projection_matrix";
+ actions.renames["INV_PROJECTION_MATRIX"] = "scene_data.inv_projection_matrix";
+ actions.renames["MODELVIEW_MATRIX"] = "modelview";
+ actions.renames["MODELVIEW_NORMAL_MATRIX"] = "modelview_normal";
+
+ actions.renames["VERTEX"] = "vertex";
+ actions.renames["NORMAL"] = "normal";
+ actions.renames["TANGENT"] = "tangent";
+ actions.renames["BINORMAL"] = "binormal";
+ actions.renames["POSITION"] = "position";
+ actions.renames["UV"] = "uv_interp";
+ actions.renames["UV2"] = "uv2_interp";
+ actions.renames["COLOR"] = "color_interp";
+ actions.renames["POINT_SIZE"] = "gl_PointSize";
+ actions.renames["INSTANCE_ID"] = "gl_InstanceIndex";
+
+ //builtins
+
+ actions.renames["TIME"] = "scene_data.time";
+ actions.renames["VIEWPORT_SIZE"] = "scene_data.viewport_size";
+
+ actions.renames["FRAGCOORD"] = "gl_FragCoord";
+ actions.renames["FRONT_FACING"] = "gl_FrontFacing";
+ actions.renames["NORMALMAP"] = "normalmap";
+ actions.renames["NORMALMAP_DEPTH"] = "normaldepth";
+ actions.renames["ALBEDO"] = "albedo";
+ actions.renames["ALPHA"] = "alpha";
+ actions.renames["METALLIC"] = "metallic";
+ actions.renames["SPECULAR"] = "specular";
+ actions.renames["ROUGHNESS"] = "roughness";
+ actions.renames["RIM"] = "rim";
+ actions.renames["RIM_TINT"] = "rim_tint";
+ actions.renames["CLEARCOAT"] = "clearcoat";
+ actions.renames["CLEARCOAT_GLOSS"] = "clearcoat_gloss";
+ actions.renames["ANISOTROPY"] = "anisotropy";
+ actions.renames["ANISOTROPY_FLOW"] = "anisotropy_flow";
+ actions.renames["SSS_STRENGTH"] = "sss_strength";
+ actions.renames["TRANSMISSION"] = "transmission";
+ actions.renames["AO"] = "ao";
+ actions.renames["AO_LIGHT_AFFECT"] = "ao_light_affect";
+ actions.renames["EMISSION"] = "emission";
+ 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["DEPTH_TEXTURE"] = "depth_buffer";
+ actions.renames["NORMAL_TEXTURE"] = "normal_buffer";
+ actions.renames["DEPTH"] = "gl_FragDepth";
+ actions.renames["OUTPUT_IS_SRGB"] = "true";
+
+ //for light
+ actions.renames["VIEW"] = "view";
+ actions.renames["LIGHT_COLOR"] = "light_color";
+ actions.renames["LIGHT"] = "light";
+ actions.renames["ATTENUATION"] = "attenuation";
+ actions.renames["DIFFUSE_LIGHT"] = "diffuse_light";
+ actions.renames["SPECULAR_LIGHT"] = "specular_light";
+
+ actions.usage_defines["TANGENT"] = "#define ENABLE_TANGENT_INTERP\n";
+ actions.usage_defines["BINORMAL"] = "@TANGENT";
+ actions.usage_defines["RIM"] = "#define LIGHT_USE_RIM\n";
+ actions.usage_defines["RIM_TINT"] = "@RIM";
+ actions.usage_defines["CLEARCOAT"] = "#define LIGHT_USE_CLEARCOAT\n";
+ actions.usage_defines["CLEARCOAT_GLOSS"] = "@CLEARCOAT";
+ actions.usage_defines["ANISOTROPY"] = "#define LIGHT_USE_ANISOTROPY\n";
+ actions.usage_defines["ANISOTROPY_FLOW"] = "@ANISOTROPY";
+ actions.usage_defines["AO"] = "#define ENABLE_AO\n";
+ actions.usage_defines["AO_LIGHT_AFFECT"] = "#define ENABLE_AO\n";
+ actions.usage_defines["UV"] = "#define ENABLE_UV_INTERP\n";
+ actions.usage_defines["UV2"] = "#define ENABLE_UV2_INTERP\n";
+ actions.usage_defines["NORMALMAP"] = "#define ENABLE_NORMALMAP\n";
+ actions.usage_defines["NORMALMAP_DEPTH"] = "@NORMALMAP";
+ actions.usage_defines["COLOR"] = "#define ENABLE_COLOR_INTERP\n";
+ actions.usage_defines["INSTANCE_CUSTOM"] = "#define ENABLE_INSTANCE_CUSTOM\n";
+ actions.usage_defines["POSITION"] = "#define OVERRIDE_POSITION\n";
+
+ actions.usage_defines["SSS_STRENGTH"] = "#define ENABLE_SSS\n";
+ actions.usage_defines["TRANSMISSION"] = "#define TRANSMISSION_USED\n";
+ actions.usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n";
+ actions.usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n";
+
+ actions.usage_defines["DIFFUSE_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n";
+ actions.usage_defines["SPECULAR_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n";
+
+ actions.render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n";
+ actions.render_mode_defines["world_vertex_coords"] = "#define VERTEX_WORLD_COORDS_USED\n";
+ actions.render_mode_defines["ensure_correct_normals"] = "#define ENSURE_CORRECT_NORMALS\n";
+ actions.render_mode_defines["cull_front"] = "#define DO_SIDE_CHECK\n";
+ actions.render_mode_defines["cull_disabled"] = "#define DO_SIDE_CHECK\n";
+
+ bool force_lambert = GLOBAL_GET("rendering/quality/shading/force_lambert_over_burley");
+
+ if (!force_lambert) {
+ actions.render_mode_defines["diffuse_burley"] = "#define DIFFUSE_BURLEY\n";
+ }
+
+ actions.render_mode_defines["diffuse_oren_nayar"] = "#define DIFFUSE_OREN_NAYAR\n";
+ actions.render_mode_defines["diffuse_lambert_wrap"] = "#define DIFFUSE_LAMBERT_WRAP\n";
+ actions.render_mode_defines["diffuse_toon"] = "#define DIFFUSE_TOON\n";
+
+ bool force_blinn = GLOBAL_GET("rendering/quality/shading/force_blinn_over_ggx");
+
+ if (!force_blinn) {
+ actions.render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_SCHLICK_GGX\n";
+ } else {
+ actions.render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_BLINN\n";
+ }
+
+ actions.render_mode_defines["specular_blinn"] = "#define SPECULAR_BLINN\n";
+ actions.render_mode_defines["specular_phong"] = "#define SPECULAR_PHONG\n";
+ actions.render_mode_defines["specular_toon"] = "#define SPECULAR_TOON\n";
+ actions.render_mode_defines["specular_disabled"] = "#define SPECULAR_DISABLED\n";
+ actions.render_mode_defines["shadows_disabled"] = "#define SHADOWS_DISABLED\n";
+ actions.render_mode_defines["ambient_light_disabled"] = "#define AMBIENT_LIGHT_DISABLED\n";
+ actions.render_mode_defines["shadow_to_opacity"] = "#define USE_SHADOW_TO_OPACITY\n";
+
+ actions.sampler_array_name = "material_samplers";
+ actions.base_texture_binding_index = 1;
+ actions.texture_layout_set = 2;
+ actions.base_uniform_string = "material.";
+
+ actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
+ actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
+
+ shader.compiler.initialize(actions);
+ }
+
+ //render list
+ render_list.max_elements = GLOBAL_DEF_RST("rendering/limits/rendering/max_renderable_elements", (int)256000);
+ render_list.init();
+ scene_pass = 0;
+ render_pass = 0;
+
+ {
+ //default material and shader
+ default_shader = storage->shader_create();
+ storage->shader_set_code(default_shader, "shader_type spatial;\n");
+ default_material = storage->material_create();
+ storage->material_set_shader(default_material, default_shader);
+
+ MaterialData *md = (MaterialData *)storage->material_get_data(default_material, RasterizerStorageRD::SHADER_TYPE_3D);
+ default_shader_rd = shader.scene_shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS);
+ }
+
+ //default render buffer and scene state uniform set
+
+ {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.binding = 1;
+ u.type = RD::UNIFORM_TYPE_TEXTURE;
+ u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE));
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 2;
+ u.type = RD::UNIFORM_TYPE_TEXTURE;
+ u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE));
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 3;
+ u.type = RD::UNIFORM_TYPE_TEXTURE;
+ u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE));
+ uniforms.push_back(u);
+ }
+
+ scene_state.uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SceneState::UBO));
+
+ {
+
+ RD::Uniform u;
+ u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 4;
+ u.ids.push_back(scene_state.uniform_buffer);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.type = RD::UNIFORM_TYPE_SAMPLER;
+ u.binding = 5;
+ u.ids.resize(12);
+ RID *ids_ptr = u.ids.ptrw();
+ ids_ptr[0] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[1] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[2] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIMPAMPS, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[3] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[4] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIMPAMPS_ANISOTROPIC, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[5] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[6] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, VS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[7] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, VS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[8] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIMPAMPS, VS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[9] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, VS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[10] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIMPAMPS_ANISOTROPIC, VS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[11] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, VS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ uniforms.push_back(u);
+ }
+
+ default_render_buffer_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, 0);
+ }
+}
+
+RasterizerSceneForwardRD::~RasterizerSceneForwardRD() {
+}
diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h b/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h
index 46a3d898b2..e09e42b1f3 100644
--- a/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h
+++ b/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h
@@ -31,85 +31,418 @@
#ifndef RASTERIZER_SCENE_FORWARD_RD_H
#define RASTERIZER_SCENE_FORWARD_RD_H
-#include "servers/visual/rasterizer.h"
+#include "servers/visual/rasterizer_rd/rasterizer_scene_rd.h"
+#include "servers/visual/rasterizer_rd/rasterizer_storage_rd.h"
+#include "servers/visual/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h"
+#include "servers/visual/rasterizer_rd/shaders/scene_forward.glsl.gen.h"
-class RasterizerSceneForwardRD : public RasterizerScene {
-public:
- /* SHADOW ATLAS API */
+class RasterizerSceneForwardRD : public RasterizerSceneRD {
+
+ /* Shader */
+
+ enum ShaderVersion {
+ SHADER_VERSION_DEPTH_PASS,
+ SHADER_VERSION_DEPTH_PASS_WITH_NORMAL,
+ SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS,
+ SHADER_VERSION_COLOR_PASS,
+ SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR,
+ SHADER_VERSION_VCT_COLOR_PASS,
+ SHADER_VERSION_VCT_COLOR_PASS_WITH_SEPARATE_SPECULAR,
+ SHADER_VERSION_LIGHTMAP_COLOR_PASS,
+ SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR,
+ SHADER_VERSION_MAX
+ };
+
+ struct {
+ SceneForwardShaderRD scene_shader;
+ ShaderCompilerRD compiler;
+ } shader;
+
+ RasterizerStorageRD *storage;
+
+ /* Material */
+
+ struct ShaderData : public RasterizerStorageRD::ShaderData {
+
+ enum BlendMode { //used internally
+ BLEND_MODE_MIX,
+ BLEND_MODE_ADD,
+ BLEND_MODE_SUB,
+ BLEND_MODE_MUL,
+ };
+
+ enum DepthDraw {
+ DEPTH_DRAW_DISABLED,
+ DEPTH_DRAW_OPAQUE,
+ DEPTH_DRAW_ALWAYS
+ };
+
+ enum DepthTest {
+ DEPTH_TEST_DISABLED,
+ DEPTH_TEST_ENABLED
+ };
+
+ enum Cull {
+ CULL_DISABLED,
+ CULL_FRONT,
+ CULL_BACK
+ };
+
+ enum CullVariant {
+ CULL_VARIANT_NORMAL,
+ CULL_VARIANT_REVERSED,
+ CULL_VARIANT_DOUBLE_SIDED,
+ CULL_VARIANT_MAX
+
+ };
+
+ bool valid;
+ RID version;
+ uint32_t vertex_input_mask;
+ RenderPipelineVertexFormatCacheRD pipelines[CULL_VARIANT_MAX][VS::PRIMITIVE_MAX][SHADER_VERSION_MAX];
+
+ String path;
+
+ Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
+ Vector<ShaderCompilerRD::GeneratedCode::Texture> texture_uniforms;
+
+ Vector<uint32_t> ubo_offsets;
+ uint32_t ubo_size;
+
+ String code;
+ Map<StringName, RID> default_texture_params;
+
+ DepthDraw depth_draw;
+ DepthTest depth_test;
+
+ bool uses_point_size;
+ bool uses_alpha;
+ bool uses_blend_alpha;
+ bool uses_depth_pre_pass;
+ bool uses_discard;
+ bool uses_roughness;
+ bool uses_normal;
+
+ bool unshaded;
+ bool uses_vertex;
+ bool uses_sss;
+ bool uses_screen_texture;
+ bool uses_depth_texture;
+ bool uses_normal_texture;
+ bool uses_time;
+ bool writes_modelview_or_projection;
+ bool uses_world_coordinates;
+
+ uint64_t last_pass = 0;
+ uint32_t index = 0;
+
+ virtual void set_code(const String &p_Code);
+ virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
+ virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
+ virtual bool is_param_texture(const StringName &p_param) const;
+ virtual bool is_animated() const;
+ virtual bool casts_shadows() const;
+ virtual Variant get_default_parameter(const StringName &p_parameter) const;
+ ShaderData();
+ virtual ~ShaderData();
+ };
+
+ RasterizerStorageRD::ShaderData *_create_shader_func();
+ static RasterizerStorageRD::ShaderData *_create_shader_funcs() {
+ return static_cast<RasterizerSceneForwardRD *>(singleton)->_create_shader_func();
+ }
+
+ struct MaterialData : public RasterizerStorageRD::MaterialData {
+ uint64_t last_frame;
+ ShaderData *shader_data;
+ RID uniform_buffer;
+ RID uniform_set;
+ Vector<RID> texture_cache;
+ Vector<uint8_t> ubo_data;
+ uint64_t last_pass = 0;
+ uint32_t index = 0;
+ RID next_pass;
+ uint8_t priority;
+ virtual void set_render_priority(int p_priority);
+ virtual void set_next_pass(RID p_pass);
+ virtual void update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
+ virtual ~MaterialData();
+ };
+
+ RasterizerStorageRD::MaterialData *_create_material_func(ShaderData *p_shader);
+ static RasterizerStorageRD::MaterialData *_create_material_funcs(RasterizerStorageRD::ShaderData *p_shader) {
+ return static_cast<RasterizerSceneForwardRD *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader));
+ }
+
+ /* Instance Custom Data */
+
+ struct InstanceGeometryData : public InstanceCustomData {
+
+ struct UBO {
+ float transform[16];
+ float normal_transform[12];
+ uint32_t flags;
+ uint32_t pad[3];
+ };
+
+ RID ubo;
+ RID uniform_set_base;
+ RID uniform_set_gi;
+
+ bool ubo_dirty = true;
+ bool using_lightmap_gi = false;
+ bool using_vct_gi = false;
+ };
+
+ /* Framebuffer */
+
+ struct RenderBufferDataForward : public RenderBufferData {
+ //for rendering, may be MSAAd
+ RID color;
+ RID depth;
+ RID color_fb;
+ int width, height;
+
+ RID render_target;
+
+ RID uniform_set_opaque;
+ RID uniform_set_alpha;
+
+ void clear();
+ virtual void configure(RID p_render_target, int p_width, int p_height, VS::ViewportMSAA p_msaa);
+
+ ~RenderBufferDataForward();
+ };
+
+ virtual RenderBufferData *_create_render_buffer_data();
- RID shadow_atlas_create() { return RID(); }
- void shadow_atlas_set_size(RID p_atlas, int p_size) {}
- void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) {}
- bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) { return false; }
+ RID default_render_buffer_uniform_set;
+ /* Instance Data */
- int get_directional_light_shadow_size(RID p_light_intance) { return 0; }
- void set_directional_shadow_count(int p_count) {}
+ struct InstanceData {
+ struct UBO {
+ };
- /* ENVIRONMENT API */
+ RID state_buffer;
+ RID uniform_set;
+ };
- RID environment_create() { return RID(); }
+ RID_Owner<InstanceData> instance_data_owner;
- void environment_set_background(RID p_env, VS::EnvironmentBG p_bg) {}
- void environment_set_sky(RID p_env, RID p_sky) {}
- void environment_set_sky_custom_fov(RID p_env, float p_scale) {}
- void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) {}
- void environment_set_bg_color(RID p_env, const Color &p_color) {}
- void environment_set_bg_energy(RID p_env, float p_energy) {}
- void environment_set_canvas_max_layer(RID p_env, int p_max_layer) {}
- void environment_set_ambient_light(RID p_env, const Color &p_color, float p_energy = 1.0, float p_sky_contribution = 0.0) {}
+ /* Scene State UBO */
- void environment_set_dof_blur_near(RID p_env, bool p_enable, float p_distance, float p_transition, float p_far_amount, VS::EnvironmentDOFBlurQuality p_quality) {}
- void environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_far_amount, VS::EnvironmentDOFBlurQuality p_quality) {}
- void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_bloom_threshold, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale) {}
+ struct SceneState {
+ struct UBO {
+ float projection_matrix[16];
+ float inv_projection_matrix[16];
- void environment_set_fog(RID p_env, bool p_enable, float p_begin, float p_end, RID p_gradient_texture) {}
+ float camera_matrix[16];
+ float inv_camera_matrix[16];
- void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance, bool p_roughness) {}
- void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect, float p_ao_channel_affect, const Color &p_color, VS::EnvironmentSSAOQuality p_quality, VS::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) {}
+ float viewport_size[2];
+ float screen_pixel_size[2];
- void 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) {}
+ float shadow_z_offset;
+ float shadow_z_slope_scale;
- void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp) {}
+ float time;
+ float reflection_multiplier;
+ };
- void environment_set_fog(RID p_env, bool p_enable, const Color &p_color, const Color &p_sun_color, float p_sun_amount) {}
- void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_end, float p_depth_curve, bool p_transmit, float p_transmit_curve) {}
- void environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve) {}
+ UBO ubo;
- bool is_environment(RID p_env) { return false; }
- VS::EnvironmentBG environment_get_background(RID p_env) { return VS::ENV_BG_KEEP; }
- int environment_get_canvas_max_layer(RID p_env) { return 0; }
+ RID uniform_buffer;
- RID light_instance_create(RID p_light) { return RID(); }
- void light_instance_set_transform(RID p_light_instance, const Transform &p_transform) {}
- void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale = 1.0) {}
- void light_instance_mark_visible(RID p_light_instance) {}
+ bool used_screen_texture = false;
+ bool used_normal_texture = false;
+ bool used_depth_texture = false;
+ bool used_sss = false;
+ uint32_t current_shader_index = 0;
+ uint32_t current_material_index = 0;
+ } scene_state;
- RID reflection_atlas_create() { return RID(); }
- void reflection_atlas_set_size(RID p_ref_atlas, int p_size) {}
- void reflection_atlas_set_subdivision(RID p_ref_atlas, int p_subdiv) {}
+ /* Render List */
- RID reflection_probe_instance_create(RID p_probe) { return RID(); }
- void reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform) {}
- void reflection_probe_release_atlas_index(RID p_instance) {}
- bool reflection_probe_instance_needs_redraw(RID p_instance) { return false; }
- bool reflection_probe_instance_has_reflection(RID p_instance) { return false; }
- bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) { return false; }
- bool reflection_probe_instance_postprocess_step(RID p_instance) { return true; }
+ struct RenderList {
- RID gi_probe_instance_create() { return RID(); }
- void gi_probe_instance_set_light_data(RID p_probe, RID p_base, RID p_data) {}
- void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) {}
- void gi_probe_instance_set_bounds(RID p_probe, const Vector3 &p_bounds) {}
+ int max_elements;
+
+ struct Element {
+ RasterizerScene::InstanceBase *instance;
+ MaterialData *material;
+ union {
+ struct {
+ //from least significant to most significant in sort, TODO: should be endian swapped on big endian
+ uint64_t material_index : 20;
+ uint64_t shader_index : 20;
+ uint64_t priority : 16;
+ uint64_t depth_layer : 8;
+ };
+
+ uint64_t sort_key;
+ };
+ uint32_t surface_index;
+ };
+
+ Element *base_elements;
+ Element **elements;
+
+ int element_count;
+ int alpha_element_count;
+
+ void clear() {
+
+ element_count = 0;
+ alpha_element_count = 0;
+ }
+
+ //should eventually be replaced by radix
+
+ struct SortByKey {
+
+ _FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const {
+ return A->sort_key < B->sort_key;
+ }
+ };
+
+ void sort_by_key(bool p_alpha) {
+
+ SortArray<Element *, SortByKey> sorter;
+ if (p_alpha) {
+ sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count);
+ } else {
+ sorter.sort(elements, element_count);
+ }
+ }
+
+ struct SortByDepth {
+
+ _FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const {
+ return A->instance->depth < B->instance->depth;
+ }
+ };
+
+ void sort_by_depth(bool p_alpha) { //used for shadows
+
+ SortArray<Element *, SortByDepth> sorter;
+ if (p_alpha) {
+ sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count);
+ } else {
+ sorter.sort(elements, element_count);
+ }
+ }
+
+ struct SortByReverseDepthAndPriority {
+
+ _FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const {
+ uint32_t layer_A = uint32_t(A->priority);
+ uint32_t layer_B = uint32_t(B->priority);
+ if (layer_A == layer_B) {
+ return A->instance->depth > B->instance->depth;
+ } else {
+ return layer_A < layer_B;
+ }
+ }
+ };
+
+ void sort_by_reverse_depth_and_priority(bool p_alpha) { //used for alpha
+
+ SortArray<Element *, SortByReverseDepthAndPriority> sorter;
+ if (p_alpha) {
+ sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count);
+ } else {
+ sorter.sort(elements, element_count);
+ }
+ }
+
+ _FORCE_INLINE_ Element *add_element() {
+
+ if (element_count + alpha_element_count >= max_elements)
+ return NULL;
+ elements[element_count] = &base_elements[element_count];
+ return elements[element_count++];
+ }
+
+ _FORCE_INLINE_ Element *add_alpha_element() {
+
+ if (element_count + alpha_element_count >= max_elements)
+ return NULL;
+ int idx = max_elements - alpha_element_count - 1;
+ elements[idx] = &base_elements[idx];
+ alpha_element_count++;
+ return elements[idx];
+ }
+
+ void init() {
+
+ element_count = 0;
+ alpha_element_count = 0;
+ elements = memnew_arr(Element *, max_elements);
+ base_elements = memnew_arr(Element, max_elements);
+ for (int i = 0; i < max_elements; i++)
+ elements[i] = &base_elements[i]; // assign elements
+ }
+
+ RenderList() {
+
+ max_elements = 0;
+ }
+
+ ~RenderList() {
+ memdelete_arr(elements);
+ memdelete_arr(base_elements);
+ }
+ };
+
+ RenderList render_list;
+
+ static RasterizerSceneForwardRD *singleton;
+ uint64_t scene_pass;
+ uint64_t render_pass;
+ double time;
+ RID default_shader;
+ RID default_material;
+ RID default_shader_rd;
+
+ enum PassMode {
+ PASS_MODE_COLOR,
+ PASS_MODE_COLOR_SPECULAR,
+ PASS_MODE_COLOR_TRANSPARENT,
+ PASS_MODE_SHADOW,
+ PASS_MODE_DEPTH,
+ PASS_MODE_DEPTH_NORMAL,
+ PASS_MODE_DEPTH_NORMAL_ROUGHNESS,
+ };
+
+ void _setup_environment(RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_no_fog);
+
+ void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, RID p_screen_uniform_set, bool p_no_gi);
+ _FORCE_INLINE_ void _add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode);
+ _FORCE_INLINE_ void _add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, PassMode p_pass_mode);
+
+ void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, PassMode p_pass_mode, bool p_no_gi);
+
+protected:
+ virtual void _render_scene(RenderBufferData *p_buffer_data, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
+
+public:
+ virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) {}
- void render_scene(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {}
- void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) {}
+ virtual void set_scene_pass(uint64_t p_pass);
+ virtual void set_time(double p_time);
+ virtual void set_debug_draw_mode(VS::ViewportDebugDraw p_debug_draw) {}
- void set_scene_pass(uint64_t p_pass) {}
- void set_debug_draw_mode(VS::ViewportDebugDraw p_debug_draw) {}
+ virtual void instance_create_custom_data(InstanceBase *p_instance);
+ virtual void instance_free_custom_data(InstanceBase *p_instance);
+ virtual void instance_custom_data_update_lights(InstanceBase *p_instance);
+ virtual void instance_custom_data_update_reflection_probes(InstanceBase *p_instance);
+ virtual void instance_custom_data_update_gi_probes(InstanceBase *p_instance);
+ virtual void instance_custom_data_update_lightmap(InstanceBase *p_instance);
+ virtual void instance_custom_data_update_transform(InstanceBase *p_instance);
- bool free(RID p_rid) { return true; }
+ virtual bool free(RID p_rid);
- RasterizerSceneForwardRD() {}
- ~RasterizerSceneForwardRD() {}
+ RasterizerSceneForwardRD(RasterizerStorageRD *p_storage);
+ ~RasterizerSceneForwardRD();
};
#endif // RASTERIZER_SCENE_FORWARD_RD_H
diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp
new file mode 100644
index 0000000000..26598b70a4
--- /dev/null
+++ b/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp
@@ -0,0 +1,41 @@
+#include "rasterizer_scene_rd.h"
+
+RID RasterizerSceneRD::render_buffers_create() {
+ RenderBuffers rb;
+ rb.data = _create_render_buffer_data();
+ return render_buffers_owner.make_rid(rb);
+}
+
+void RasterizerSceneRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, VS::ViewportMSAA p_msaa) {
+
+ RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ rb->width = p_width;
+ rb->height = p_height;
+ rb->render_target = p_render_target;
+ rb->msaa = p_msaa;
+ rb->data->configure(p_render_target, p_width, p_height, p_msaa);
+}
+
+void RasterizerSceneRD::render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
+
+ RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ ERR_FAIL_COND(!rb && p_render_buffers.is_valid());
+
+ _render_scene(rb->data, p_cam_transform, p_cam_projection, p_cam_ortogonal, p_cull_result, p_cull_count, p_light_cull_result, p_light_cull_count, p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_environment, p_shadow_atlas, p_reflection_atlas, p_reflection_probe, p_reflection_probe_pass);
+}
+
+bool RasterizerSceneRD::free(RID p_rid) {
+
+ if (render_buffers_owner.owns(p_rid)) {
+ RenderBuffers *rb = render_buffers_owner.getornull(p_rid);
+ memdelete(rb->data);
+ render_buffers_owner.free(p_rid);
+ } else {
+ return false;
+ }
+
+ return true;
+}
+
+RasterizerSceneRD::RasterizerSceneRD() {
+}
diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_rd.h b/servers/visual/rasterizer_rd/rasterizer_scene_rd.h
new file mode 100644
index 0000000000..2019d4e5a5
--- /dev/null
+++ b/servers/visual/rasterizer_rd/rasterizer_scene_rd.h
@@ -0,0 +1,105 @@
+#ifndef RASTERIZER_SCENE_RD_H
+#define RASTERIZER_SCENE_RD_H
+
+#include "core/rid_owner.h"
+#include "servers/visual/rasterizer.h"
+class RasterizerSceneRD : public RasterizerScene {
+protected:
+ struct RenderBufferData {
+
+ virtual void configure(RID p_render_target, int p_width, int p_height, VS::ViewportMSAA p_msaa) = 0;
+ virtual ~RenderBufferData() {}
+ };
+ virtual RenderBufferData *_create_render_buffer_data() = 0;
+
+ virtual void _render_scene(RenderBufferData *p_buffer_data, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) = 0;
+
+private:
+ struct RenderBuffers {
+
+ RenderBufferData *data = nullptr;
+ int width = 0, height = 0;
+ VS::ViewportMSAA msaa = VS::VIEWPORT_MSAA_DISABLED;
+ RID render_target;
+ };
+
+ RID_Owner<RenderBuffers> render_buffers_owner;
+
+public:
+ /* SHADOW ATLAS API */
+
+ RID shadow_atlas_create() { return RID(); }
+ void shadow_atlas_set_size(RID p_atlas, int p_size) {}
+ void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) {}
+ bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) { return false; }
+
+ int get_directional_light_shadow_size(RID p_light_intance) { return 0; }
+ void set_directional_shadow_count(int p_count) {}
+
+ /* ENVIRONMENT API */
+
+ RID environment_create() { return RID(); }
+
+ void environment_set_background(RID p_env, VS::EnvironmentBG p_bg) {}
+ void environment_set_sky(RID p_env, RID p_sky) {}
+ void environment_set_sky_custom_fov(RID p_env, float p_scale) {}
+ void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) {}
+ void environment_set_bg_color(RID p_env, const Color &p_color) {}
+ void environment_set_bg_energy(RID p_env, float p_energy) {}
+ void environment_set_canvas_max_layer(RID p_env, int p_max_layer) {}
+ void environment_set_ambient_light(RID p_env, const Color &p_color, float p_energy = 1.0, float p_sky_contribution = 0.0) {}
+
+ void environment_set_dof_blur_near(RID p_env, bool p_enable, float p_distance, float p_transition, float p_far_amount, VS::EnvironmentDOFBlurQuality p_quality) {}
+ void environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_far_amount, VS::EnvironmentDOFBlurQuality p_quality) {}
+ void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_bloom_threshold, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale) {}
+
+ void environment_set_fog(RID p_env, bool p_enable, float p_begin, float p_end, RID p_gradient_texture) {}
+
+ void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance, bool p_roughness) {}
+ void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect, float p_ao_channel_affect, const Color &p_color, VS::EnvironmentSSAOQuality p_quality, VS::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) {}
+
+ void 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) {}
+
+ void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp) {}
+
+ void environment_set_fog(RID p_env, bool p_enable, const Color &p_color, const Color &p_sun_color, float p_sun_amount) {}
+ void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_end, float p_depth_curve, bool p_transmit, float p_transmit_curve) {}
+ void environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve) {}
+
+ bool is_environment(RID p_env) { return false; }
+ VS::EnvironmentBG environment_get_background(RID p_env) { return VS::ENV_BG_KEEP; }
+ int environment_get_canvas_max_layer(RID p_env) { return 0; }
+
+ RID light_instance_create(RID p_light) { return RID(); }
+ void light_instance_set_transform(RID p_light_instance, const Transform &p_transform) {}
+ void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale = 1.0) {}
+ void light_instance_mark_visible(RID p_light_instance) {}
+
+ RID reflection_atlas_create() { return RID(); }
+ void reflection_atlas_set_size(RID p_ref_atlas, int p_size) {}
+ void reflection_atlas_set_subdivision(RID p_ref_atlas, int p_subdiv) {}
+
+ RID reflection_probe_instance_create(RID p_probe) { return RID(); }
+ void reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform) {}
+ void reflection_probe_release_atlas_index(RID p_instance) {}
+ bool reflection_probe_instance_needs_redraw(RID p_instance) { return false; }
+ bool reflection_probe_instance_has_reflection(RID p_instance) { return false; }
+ bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) { return false; }
+ bool reflection_probe_instance_postprocess_step(RID p_instance) { return true; }
+
+ RID gi_probe_instance_create() { return RID(); }
+ void gi_probe_instance_set_light_data(RID p_probe, RID p_base, RID p_data) {}
+ void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) {}
+ void gi_probe_instance_set_bounds(RID p_probe, const Vector3 &p_bounds) {}
+
+ RID render_buffers_create();
+ void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, VS::ViewportMSAA p_msaa);
+
+ void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
+
+ virtual bool free(RID p_rid);
+
+ RasterizerSceneRD();
+};
+
+#endif // RASTERIZER_SCENE_RD_H
diff --git a/servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp
index 15503ec38d..5351af7c90 100644
--- a/servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp
+++ b/servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp
@@ -1691,6 +1691,402 @@ void RasterizerStorageRD::_update_queued_materials() {
}
material_update_list = NULL;
}
+/* MESH API */
+
+RID RasterizerStorageRD::mesh_create() {
+
+ return mesh_owner.make_rid(Mesh());
+}
+
+/// Returns stride
+void RasterizerStorageRD::mesh_add_surface(RID p_mesh, const VS::SurfaceData &p_surface) {
+
+ Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND(!mesh);
+
+ //ensure blend shape consistency
+ ERR_FAIL_COND(mesh->blend_shape_count && p_surface.blend_shapes.size() != (int)mesh->blend_shape_count);
+ ERR_FAIL_COND(mesh->blend_shape_count && p_surface.bone_aabbs.size() != mesh->bone_aabbs.size());
+
+ Mesh::Surface *s = memnew(Mesh::Surface);
+
+ s->format = p_surface.format;
+ s->primitive = p_surface.primitive;
+
+ s->vertex_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.vertex_data.size(), p_surface.vertex_data);
+ s->vertex_count = p_surface.vertex_count;
+
+ if (p_surface.index_count) {
+ bool is_index_16 = p_surface.vertex_count <= 65536;
+
+ s->index_buffer = RD::get_singleton()->index_buffer_create(p_surface.index_count, is_index_16 ? RD::INDEX_BUFFER_FORMAT_UINT16 : RD::INDEX_BUFFER_FORMAT_UINT32, p_surface.index_data, false);
+ s->index_count = p_surface.index_count;
+ s->index_array = RD::get_singleton()->index_array_create(s->index_buffer, 0, s->index_count);
+ if (p_surface.lods.size()) {
+ s->lods = memnew_arr(Mesh::Surface::LOD, p_surface.lods.size());
+ s->lod_count = p_surface.lods.size();
+
+ for (int i = 0; i < p_surface.lods.size(); i++) {
+
+ uint32_t indices = p_surface.lods[i].index_data.size() / (is_index_16 ? 2 : 4);
+ s->lods[i].index_buffer = RD::get_singleton()->index_buffer_create(indices, is_index_16 ? RD::INDEX_BUFFER_FORMAT_UINT16 : RD::INDEX_BUFFER_FORMAT_UINT32, p_surface.lods[i].index_data);
+ s->lods[i].index_array = RD::get_singleton()->index_array_create(s->lods[i].index_buffer, 0, indices);
+ s->lods[i].edge_length = p_surface.lods[i].edge_length;
+ }
+ }
+ }
+
+ s->aabb = p_surface.aabb;
+ s->bone_aabbs = p_surface.bone_aabbs; //only really useful for returning them.
+
+ for (int i = 0; i < p_surface.blend_shapes.size(); i++) {
+
+ ERR_FAIL_COND(p_surface.blend_shapes[i].size() != p_surface.vertex_data.size());
+
+ RID vertex_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.blend_shapes[i].size(), p_surface.blend_shapes[i]);
+ s->blend_shapes.push_back(vertex_buffer);
+ }
+
+ mesh->blend_shape_count = p_surface.blend_shapes.size();
+
+ if (mesh->surface_count == 0) {
+ mesh->bone_aabbs = p_surface.bone_aabbs;
+ mesh->aabb = p_surface.aabb;
+ } else {
+ for (int i = 0; i < p_surface.bone_aabbs.size(); i++) {
+ mesh->bone_aabbs.write[i].merge_with(p_surface.bone_aabbs[i]);
+ }
+ mesh->aabb.merge_with(p_surface.aabb);
+ }
+
+ s->material = p_mesh;
+
+ mesh->surfaces = (Mesh::Surface **)memrealloc(mesh->surfaces, sizeof(Mesh::Surface *) * (mesh->surface_count + 1));
+ mesh->surfaces[mesh->surface_count] = s;
+ mesh->surface_count++;
+
+ mesh->instance_dependency.instance_notify_changed(true, true);
+
+ mesh->material_cache.clear();
+}
+
+int RasterizerStorageRD::mesh_get_blend_shape_count(RID p_mesh) const {
+ const Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND_V(!mesh, -1);
+ return mesh->blend_shape_count;
+}
+
+void RasterizerStorageRD::mesh_set_blend_shape_mode(RID p_mesh, VS::BlendShapeMode p_mode) {
+ Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND(!mesh);
+ ERR_FAIL_INDEX(p_mode, 2);
+
+ mesh->blend_shape_mode = p_mode;
+}
+VS::BlendShapeMode RasterizerStorageRD::mesh_get_blend_shape_mode(RID p_mesh) const {
+ Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND_V(!mesh, VS::BLEND_SHAPE_MODE_NORMALIZED);
+ return mesh->blend_shape_mode;
+}
+
+void RasterizerStorageRD::mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const PoolVector<uint8_t> &p_data) {
+ Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND(!mesh);
+ ERR_FAIL_INDEX((uint32_t)p_surface, mesh->surface_count);
+ ERR_FAIL_COND(p_data.size() == 0);
+ uint64_t data_size = p_data.size();
+ PoolVector<uint8_t>::Read r = p_data.read();
+
+ RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->vertex_buffer, p_offset, data_size, r.ptr());
+}
+
+void RasterizerStorageRD::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) {
+ Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND(!mesh);
+ ERR_FAIL_INDEX((uint32_t)p_surface, mesh->surface_count);
+ mesh->surfaces[p_surface]->material = p_material;
+
+ mesh->instance_dependency.instance_notify_changed(false, true);
+ mesh->material_cache.clear();
+}
+RID RasterizerStorageRD::mesh_surface_get_material(RID p_mesh, int p_surface) const {
+ Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND_V(!mesh, RID());
+ ERR_FAIL_INDEX_V((uint32_t)p_surface, mesh->surface_count, RID());
+
+ return mesh->surfaces[p_surface]->material;
+}
+
+VS::SurfaceData RasterizerStorageRD::mesh_get_surface(RID p_mesh, int p_surface) const {
+
+ Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND_V(!mesh, VS::SurfaceData());
+ ERR_FAIL_INDEX_V((uint32_t)p_surface, mesh->surface_count, VS::SurfaceData());
+
+ Mesh::Surface &s = *mesh->surfaces[p_surface];
+
+ VS::SurfaceData sd;
+ sd.format = s.format;
+ sd.vertex_data = RD::get_singleton()->buffer_get_data(s.vertex_buffer);
+ sd.vertex_count = s.vertex_count;
+ sd.index_count = s.index_count;
+ if (sd.index_count) {
+ sd.index_data = RD::get_singleton()->buffer_get_data(s.index_buffer);
+ }
+ sd.aabb = s.aabb;
+ for (uint32_t i = 0; i < s.lod_count; i++) {
+ VS::SurfaceData::LOD lod;
+ lod.edge_length = s.lods[i].edge_length;
+ lod.index_data = RD::get_singleton()->buffer_get_data(s.lods[i].index_buffer);
+ sd.lods.push_back(lod);
+ }
+
+ sd.bone_aabbs = s.bone_aabbs;
+
+ for (int i = 0; i < s.blend_shapes.size(); i++) {
+ PoolVector<uint8_t> bs = RD::get_singleton()->buffer_get_data(s.blend_shapes[i]);
+ sd.blend_shapes.push_back(bs);
+ }
+
+ return sd;
+}
+
+int RasterizerStorageRD::mesh_get_surface_count(RID p_mesh) const {
+ Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND_V(!mesh, 0);
+ return mesh->surface_count;
+}
+
+void RasterizerStorageRD::mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) {
+ Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND(!mesh);
+ mesh->custom_aabb = p_aabb;
+}
+AABB RasterizerStorageRD::mesh_get_custom_aabb(RID p_mesh) const {
+ Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND_V(!mesh, AABB());
+ return mesh->custom_aabb;
+}
+
+AABB RasterizerStorageRD::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
+ Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND_V(!mesh, AABB());
+
+ if (mesh->custom_aabb != AABB()) {
+ return mesh->custom_aabb;
+ }
+
+ if (!p_skeleton.is_valid()) {
+ return mesh->aabb;
+ }
+
+ return mesh->aabb;
+}
+
+void RasterizerStorageRD::mesh_clear(RID p_mesh) {
+
+ Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND(!mesh);
+ for (uint32_t i = 0; i < mesh->surface_count; i++) {
+ Mesh::Surface &s = *mesh->surfaces[i];
+ RD::get_singleton()->free(s.vertex_buffer); //clears arrays as dependency automatically, including all versions
+ if (s.versions) {
+ memfree(s.versions); //reallocs, so free with memfree.
+ }
+
+ if (s.index_buffer.is_valid()) {
+ RD::get_singleton()->free(s.index_buffer);
+ }
+
+ if (s.lod_count) {
+ for (uint32_t j = 0; j < s.lod_count; j++) {
+ RD::get_singleton()->free(s.lods[j].index_buffer);
+ }
+ memdelete_arr(s.lods);
+ }
+
+ for (int32_t j = 0; j < s.blend_shapes.size(); j++) {
+ RD::get_singleton()->free(s.blend_shapes[j]);
+ }
+
+ if (s.blend_shape_base_buffer.is_valid()) {
+ RD::get_singleton()->free(s.blend_shape_base_buffer);
+ }
+
+ memdelete(mesh->surfaces[i]);
+ }
+ if (mesh->surfaces) {
+ memfree(mesh->surfaces);
+ }
+
+ mesh->surfaces = nullptr;
+ mesh->surface_count = 0;
+ mesh->material_cache.clear();
+ mesh->instance_dependency.instance_notify_changed(true, true);
+}
+
+void RasterizerStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Surface *s, uint32_t p_input_mask) {
+ uint32_t version = s->version_count;
+ s->version_count++;
+ s->versions = (Mesh::Surface::Version *)memrealloc(s->versions, sizeof(Mesh::Surface::Version) * s->version_count);
+
+ Mesh::Surface::Version &v = s->versions[version];
+
+ Vector<RD::VertexDescription> attributes;
+ Vector<RID> buffers;
+
+ uint32_t stride = 0;
+
+ for (int i = 0; i < VS::ARRAY_WEIGHTS; i++) {
+
+ if (!(p_input_mask & (1 << i))) {
+ continue; // Shader does not need this, skip it
+ }
+
+ RD::VertexDescription vd;
+ RID buffer;
+ vd.location = i;
+
+ if (!(s->format & (1 << i))) {
+ // Shader needs this, but it's not provided by this surface
+ // Create a default attribue using the default buffers
+ buffer = mesh_default_rd_buffers[i];
+ switch (i) {
+
+ case VS::ARRAY_VERTEX: {
+
+ vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT;
+
+ } break;
+ case VS::ARRAY_NORMAL: {
+ vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT;
+ } break;
+ case VS::ARRAY_TANGENT: {
+
+ vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
+ } break;
+ case VS::ARRAY_COLOR: {
+
+ vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
+
+ } break;
+ case VS::ARRAY_TEX_UV: {
+
+ vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
+
+ } break;
+ case VS::ARRAY_TEX_UV2: {
+
+ vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
+ } break;
+ case VS::ARRAY_BONES: {
+
+ //assumed weights too
+ vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT;
+ } break;
+ }
+ } else {
+ //Shader needs this, and it's also provided
+
+ vd.offset = stride;
+ vd.stride = 1; //mark that it needs a stride set
+ buffer = s->vertex_buffer;
+
+ switch (i) {
+
+ case VS::ARRAY_VERTEX: {
+
+ if (s->format & VS::ARRAY_FLAG_USE_2D_VERTICES) {
+ vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
+ stride += sizeof(float) * 2;
+ } else {
+ vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT;
+ stride += sizeof(float) * 3;
+ }
+
+ } break;
+ case VS::ARRAY_NORMAL: {
+
+ if (s->format & VS::ARRAY_COMPRESS_NORMAL) {
+ vd.format = RD::DATA_FORMAT_R8G8B8A8_SNORM;
+ stride += sizeof(int8_t) * 4;
+ } else {
+ vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
+ stride += sizeof(float) * 4;
+ }
+
+ } break;
+ case VS::ARRAY_TANGENT: {
+
+ if (s->format & VS::ARRAY_COMPRESS_TANGENT) {
+ vd.format = RD::DATA_FORMAT_R8G8B8A8_SNORM;
+ stride += sizeof(int8_t) * 4;
+ } else {
+ vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
+ stride += sizeof(float) * 4;
+ }
+
+ } break;
+ case VS::ARRAY_COLOR: {
+
+ if (s->format & VS::ARRAY_COMPRESS_COLOR) {
+ vd.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ stride += sizeof(int8_t) * 4;
+ } else {
+ vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
+ stride += sizeof(float) * 4;
+ }
+
+ } break;
+ case VS::ARRAY_TEX_UV: {
+
+ if (s->format & VS::ARRAY_COMPRESS_TEX_UV) {
+ vd.format = RD::DATA_FORMAT_R16G16_SFLOAT;
+ stride += sizeof(int16_t) * 2;
+ } else {
+ vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
+ stride += sizeof(float) * 2;
+ }
+
+ } break;
+ case VS::ARRAY_TEX_UV2: {
+
+ if (s->format & VS::ARRAY_COMPRESS_TEX_UV2) {
+ vd.format = RD::DATA_FORMAT_R16G16_SFLOAT;
+ stride += sizeof(int16_t) * 2;
+ } else {
+ vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
+ stride += sizeof(float) * 2;
+ }
+
+ } break;
+ case VS::ARRAY_BONES: {
+ //assumed weights too
+
+ //unique format, internally 16 bits, exposed as single array for 32
+
+ vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT;
+ stride += sizeof(int32_t) * 4;
+
+ } break;
+ }
+ }
+
+ attributes.push_back(vd);
+ buffers.push_back(buffer);
+ }
+
+ //update final stride
+ for (int i = 0; i < attributes.size(); i++) {
+ if (attributes[i].stride == 1) {
+ attributes.write[i].stride = stride;
+ }
+ }
+
+ v.input_mask = p_input_mask;
+ v.vertex_format = RD::get_singleton()->vertex_format_create(attributes);
+ v.vertex_array = RD::get_singleton()->vertex_array_create(s->vertex_count, v.vertex_format, buffers);
+}
/* RENDER TARGET API */
@@ -2033,6 +2429,13 @@ RID RasterizerStorageRD::render_target_get_back_buffer_uniform_set(RID p_render_
return rt->backbuffer_uniform_set;
}
+void RasterizerStorageRD::base_update_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) {
+ if (mesh_owner.owns(p_base)) {
+ Mesh *mesh = mesh_owner.getornull(p_base);
+ p_instance->update_dependency(&mesh->instance_dependency);
+ }
+}
+
void RasterizerStorageRD::update_dirty_resources() {
_update_queued_materials();
}
@@ -2081,6 +2484,11 @@ bool RasterizerStorageRD::free(RID p_rid) {
material_set_shader(p_rid, RID()); //clean up shader
material->instance_dependency.instance_notify_deleted(p_rid);
material_owner.free(p_rid);
+ } else if (mesh_owner.owns(p_rid)) {
+ mesh_clear(p_rid);
+ Mesh *mesh = mesh_owner.getornull(p_rid);
+ mesh->instance_dependency.instance_notify_deleted(p_rid);
+ mesh_owner.free(p_rid);
} else if (render_target_owner.owns(p_rid)) {
RenderTarget *rt = render_target_owner.getornull(p_rid);
@@ -2100,7 +2508,7 @@ bool RasterizerStorageRD::free(RID p_rid) {
return true;
}
-EffectsRD *RasterizerStorageRD::get_effects() {
+RasterizerEffectsRD *RasterizerStorageRD::get_effects() {
return &effects;
}
@@ -2251,6 +2659,115 @@ RasterizerStorageRD::RasterizerStorageRD() {
default_rd_samplers[i][j] = RD::get_singleton()->sampler_create(sampler_state);
}
}
+
+ //default rd buffers
+ {
+
+ { //vertex
+ PoolVector<uint8_t> buffer;
+ buffer.resize(sizeof(float) * 3);
+ {
+ PoolVector<uint8_t>::Write w = buffer.write();
+ float *fptr = (float *)w.ptr();
+ fptr[0] = 0.0;
+ fptr[1] = 0.0;
+ fptr[2] = 0.0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_VERTEX] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
+
+ { //normal
+ PoolVector<uint8_t> buffer;
+ buffer.resize(sizeof(float) * 3);
+ {
+ PoolVector<uint8_t>::Write w = buffer.write();
+ float *fptr = (float *)w.ptr();
+ fptr[0] = 1.0;
+ fptr[1] = 0.0;
+ fptr[2] = 0.0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_NORMAL] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
+
+ { //tangent
+ PoolVector<uint8_t> buffer;
+ buffer.resize(sizeof(float) * 4);
+ {
+ PoolVector<uint8_t>::Write w = buffer.write();
+ float *fptr = (float *)w.ptr();
+ fptr[0] = 1.0;
+ fptr[1] = 0.0;
+ fptr[2] = 0.0;
+ fptr[3] = 0.0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TANGENT] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
+
+ { //color
+ PoolVector<uint8_t> buffer;
+ buffer.resize(sizeof(float) * 4);
+ {
+ PoolVector<uint8_t>::Write w = buffer.write();
+ float *fptr = (float *)w.ptr();
+ fptr[0] = 1.0;
+ fptr[1] = 1.0;
+ fptr[2] = 1.0;
+ fptr[3] = 1.0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_COLOR] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
+
+ { //tex uv 1
+ PoolVector<uint8_t> buffer;
+ buffer.resize(sizeof(float) * 2);
+ {
+ PoolVector<uint8_t>::Write w = buffer.write();
+ float *fptr = (float *)w.ptr();
+ fptr[0] = 0.0;
+ fptr[1] = 0.0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TEX_UV] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
+ { //tex uv 2
+ PoolVector<uint8_t> buffer;
+ buffer.resize(sizeof(float) * 2);
+ {
+ PoolVector<uint8_t>::Write w = buffer.write();
+ float *fptr = (float *)w.ptr();
+ fptr[0] = 0.0;
+ fptr[1] = 0.0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TEX_UV2] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
+
+ { //bones
+ PoolVector<uint8_t> buffer;
+ buffer.resize(sizeof(uint32_t) * 4);
+ {
+ PoolVector<uint8_t>::Write w = buffer.write();
+ uint32_t *fptr = (uint32_t *)w.ptr();
+ fptr[0] = 0;
+ fptr[1] = 0;
+ fptr[2] = 0;
+ fptr[3] = 0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_BONES] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
+
+ { //weights
+ PoolVector<uint8_t> buffer;
+ buffer.resize(sizeof(float) * 4);
+ {
+ PoolVector<uint8_t>::Write w = buffer.write();
+ float *fptr = (float *)w.ptr();
+ fptr[0] = 0.0;
+ fptr[1] = 0.0;
+ fptr[2] = 0.0;
+ fptr[3] = 0.0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_WEIGHTS] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
+ }
}
RasterizerStorageRD::~RasterizerStorageRD() {
@@ -2266,4 +2783,9 @@ RasterizerStorageRD::~RasterizerStorageRD() {
RD::get_singleton()->free(default_rd_samplers[i][j]);
}
}
+
+ //def buffers
+ for (int i = 0; i < DEFAULT_RD_BUFFER_MAX; i++) {
+ RD::get_singleton()->free(mesh_default_rd_buffers[i]);
+ }
}
diff --git a/servers/visual/rasterizer_rd/rasterizer_storage_rd.h b/servers/visual/rasterizer_rd/rasterizer_storage_rd.h
index db1d73e62f..729e8b6556 100644
--- a/servers/visual/rasterizer_rd/rasterizer_storage_rd.h
+++ b/servers/visual/rasterizer_rd/rasterizer_storage_rd.h
@@ -33,7 +33,7 @@
#include "core/rid_owner.h"
#include "servers/visual/rasterizer.h"
-#include "servers/visual/rasterizer_rd/effects_rd.h"
+#include "servers/visual/rasterizer_rd/rasterizer_effects_rd.h"
#include "servers/visual/rasterizer_rd/shader_compiler_rd.h"
#include "servers/visual/rendering_device.h"
@@ -80,6 +80,18 @@ public:
DEFAULT_RD_TEXTURE_MAX
};
+ enum DefaultRDBuffer {
+ DEFAULT_RD_BUFFER_VERTEX,
+ DEFAULT_RD_BUFFER_NORMAL,
+ DEFAULT_RD_BUFFER_TANGENT,
+ DEFAULT_RD_BUFFER_COLOR,
+ DEFAULT_RD_BUFFER_TEX_UV,
+ DEFAULT_RD_BUFFER_TEX_UV2,
+ DEFAULT_RD_BUFFER_BONES,
+ DEFAULT_RD_BUFFER_WEIGHTS,
+ DEFAULT_RD_BUFFER_MAX,
+ };
+
private:
/* TEXTURE API */
struct Texture {
@@ -186,6 +198,80 @@ private:
Material *material_update_list;
void _material_queue_update(Material *material, bool p_uniform, bool p_texture);
void _update_queued_materials();
+
+ /* Mesh */
+
+ struct Mesh {
+
+ struct Surface {
+ VS::PrimitiveType primitive;
+ uint32_t format = 0;
+
+ RID vertex_buffer;
+ uint32_t vertex_count = 0;
+
+ // A different pipeline needs to be allocated
+ // depending on the inputs available in the
+ // material.
+ // There are never that many geometry/material
+ // combinations, so a simple array is the most
+ // cache-efficient structure.
+
+ struct Version {
+ uint32_t input_mask;
+ RD::VertexFormatID vertex_format;
+ RID vertex_array;
+ };
+
+ SpinLock version_lock; //needed to access versions
+ Version *versions = nullptr; //allocated on demand
+ uint32_t version_count = 0;
+
+ RID index_buffer;
+ RID index_array;
+ uint32_t index_count = 0;
+
+ struct LOD {
+ float edge_length;
+ RID index_buffer;
+ RID index_array;
+ };
+
+ LOD *lods = nullptr;
+ uint32_t lod_count = 0;
+
+ AABB aabb;
+
+ Vector<AABB> bone_aabbs;
+
+ Vector<RID> blend_shapes;
+ RID blend_shape_base_buffer; //source buffer goes here when using blend shapes, and main one is uncompressed
+
+ RID material;
+ };
+
+ uint32_t blend_shape_count = 0;
+ VS::BlendShapeMode blend_shape_mode = VS::BLEND_SHAPE_MODE_NORMALIZED;
+
+ Surface **surfaces = nullptr;
+ uint32_t surface_count = 0;
+
+ Vector<AABB> bone_aabbs;
+
+ AABB aabb;
+ AABB custom_aabb;
+
+ Vector<RID> material_cache;
+
+ RasterizerScene::InstanceDependency instance_dependency;
+ };
+
+ mutable RID_Owner<Mesh> mesh_owner;
+
+ void _mesh_surface_generate_version_for_input_mask(Mesh::Surface *s, uint32_t p_input_mask);
+
+ RID mesh_default_rd_buffers[DEFAULT_RD_BUFFER_MAX];
+
/* RENDER TARGET */
struct RenderTarget {
@@ -231,7 +317,7 @@ private:
/* EFFECTS */
- EffectsRD effects;
+ RasterizerEffectsRD effects;
public:
/* TEXTURE API */
@@ -309,26 +395,8 @@ public:
/* SKY API */
- struct RDSurface {
- uint32_t format;
- VS::PrimitiveType primitive;
- PoolVector<uint8_t> array;
- int vertex_count;
- PoolVector<uint8_t> index_array;
- int index_count;
- AABB aabb;
- Vector<PoolVector<uint8_t> > blend_shapes;
- Vector<AABB> bone_aabbs;
- };
-
- struct RDMesh {
- Vector<RDSurface> surfaces;
- int blend_shape_count;
- VS::BlendShapeMode blend_shape_mode;
- };
RID sky_create() { return RID(); }
void sky_set_texture(RID p_sky, RID p_cube_map, int p_radiance_size) {}
- mutable RID_PtrOwner<RDMesh> mesh_owner;
/* SHADER API */
@@ -374,134 +442,87 @@ public:
/* MESH API */
- RID mesh_create() {
- RDMesh *mesh = memnew(RDMesh);
- ERR_FAIL_COND_V(!mesh, RID());
- mesh->blend_shape_count = 0;
- mesh->blend_shape_mode = VS::BLEND_SHAPE_MODE_NORMALIZED;
- return mesh_owner.make_rid(mesh);
- }
+ virtual RID mesh_create();
- void mesh_add_surface(RID p_mesh, uint32_t p_format, VS::PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<PoolVector<uint8_t> > &p_blend_shapes = Vector<PoolVector<uint8_t> >(), const Vector<AABB> &p_bone_aabbs = Vector<AABB>()) {
- RDMesh *m = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND(!m);
-
- m->surfaces.push_back(RDSurface());
- RDSurface *s = &m->surfaces.write[m->surfaces.size() - 1];
- s->format = p_format;
- s->primitive = p_primitive;
- s->array = p_array;
- s->vertex_count = p_vertex_count;
- s->index_array = p_index_array;
- s->index_count = p_index_count;
- s->aabb = p_aabb;
- s->blend_shapes = p_blend_shapes;
- s->bone_aabbs = p_bone_aabbs;
- }
+ /// Return stride
+ virtual void mesh_add_surface(RID p_mesh, const VS::SurfaceData &p_surface);
- void mesh_set_blend_shape_count(RID p_mesh, int p_amount) {
- RDMesh *m = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND(!m);
- m->blend_shape_count = p_amount;
- }
- int mesh_get_blend_shape_count(RID p_mesh) const {
- RDMesh *m = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!m, 0);
- return m->blend_shape_count;
- }
+ virtual int mesh_get_blend_shape_count(RID p_mesh) const;
- void mesh_set_blend_shape_mode(RID p_mesh, VS::BlendShapeMode p_mode) {
- RDMesh *m = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND(!m);
- m->blend_shape_mode = p_mode;
- }
- VS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const {
- RDMesh *m = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!m, VS::BLEND_SHAPE_MODE_NORMALIZED);
- return m->blend_shape_mode;
- }
+ virtual void mesh_set_blend_shape_mode(RID p_mesh, VS::BlendShapeMode p_mode);
+ virtual VS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const;
- void mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const PoolVector<uint8_t> &p_data) {}
+ virtual void mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const PoolVector<uint8_t> &p_data);
- void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) {}
- RID mesh_surface_get_material(RID p_mesh, int p_surface) const { return RID(); }
+ virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material);
+ virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const;
- int mesh_surface_get_array_len(RID p_mesh, int p_surface) const {
- RDMesh *m = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!m, 0);
+ virtual VS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const;
- return m->surfaces[p_surface].vertex_count;
- }
- int mesh_surface_get_array_index_len(RID p_mesh, int p_surface) const {
- RDMesh *m = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!m, 0);
+ virtual int mesh_get_surface_count(RID p_mesh) const;
- return m->surfaces[p_surface].index_count;
- }
+ virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb);
+ virtual AABB mesh_get_custom_aabb(RID p_mesh) const;
- PoolVector<uint8_t> mesh_surface_get_array(RID p_mesh, int p_surface) const {
- RDMesh *m = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!m, PoolVector<uint8_t>());
+ virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID());
- return m->surfaces[p_surface].array;
- }
- PoolVector<uint8_t> mesh_surface_get_index_array(RID p_mesh, int p_surface) const {
- RDMesh *m = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!m, PoolVector<uint8_t>());
+ virtual void mesh_clear(RID p_mesh);
- return m->surfaces[p_surface].index_array;
+ _FORCE_INLINE_ const RID *mesh_get_surface_count_and_materials(RID p_mesh, uint32_t &r_surface_count) {
+ Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND_V(!mesh, NULL);
+ r_surface_count = mesh->surface_count;
+ if (r_surface_count == 0) {
+ return NULL;
+ }
+ if (mesh->material_cache.empty()) {
+ mesh->material_cache.resize(mesh->surface_count);
+ for (uint32_t i = 0; i < r_surface_count; i++) {
+ mesh->material_cache.write[i] = mesh->surfaces[i]->material;
+ }
+ }
+
+ return mesh->material_cache.ptr();
}
- uint32_t mesh_surface_get_format(RID p_mesh, int p_surface) const {
- RDMesh *m = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!m, 0);
+ _FORCE_INLINE_ void mesh_get_arrays_primitive_and_format(RID p_mesh, uint32_t p_surface_index, uint32_t p_input_mask, VS::PrimitiveType &r_primitive, RID &r_vertex_array_rd, RID &r_index_array_rd, RD::VertexFormatID &r_vertex_format) {
+ Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND(!mesh);
+ ERR_FAIL_INDEX(p_surface_index, mesh->surface_count);
- return m->surfaces[p_surface].format;
- }
- VS::PrimitiveType mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const {
- RDMesh *m = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!m, VS::PRIMITIVE_POINTS);
+ Mesh::Surface *s = mesh->surfaces[p_surface_index];
- return m->surfaces[p_surface].primitive;
- }
+ r_index_array_rd = s->index_array;
- AABB mesh_surface_get_aabb(RID p_mesh, int p_surface) const {
- RDMesh *m = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!m, AABB());
+ s->version_lock.lock();
- return m->surfaces[p_surface].aabb;
- }
- Vector<PoolVector<uint8_t> > mesh_surface_get_blend_shapes(RID p_mesh, int p_surface) const {
- RDMesh *m = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!m, Vector<PoolVector<uint8_t> >());
+ //there will never be more than, at much, 3 or 4 versions, so iterating is the fastest way
- return m->surfaces[p_surface].blend_shapes;
- }
- Vector<AABB> mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const {
- RDMesh *m = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!m, Vector<AABB>());
+ for (uint32_t i = 0; i < s->version_count; i++) {
+ if (s->versions[i].input_mask != p_input_mask) {
+ continue;
+ }
+ //we have this version, hooray
+ r_vertex_format = s->versions[i].vertex_format;
+ r_vertex_array_rd = s->versions[i].vertex_array;
+ s->version_lock.unlock();
+ return;
+ }
- return m->surfaces[p_surface].bone_aabbs;
- }
+ uint32_t version = s->version_count; //gets added at the end
- void mesh_remove_surface(RID p_mesh, int p_index) {
- RDMesh *m = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND(!m);
- ERR_FAIL_COND(p_index >= m->surfaces.size());
+ _mesh_surface_generate_version_for_input_mask(s, p_input_mask);
- m->surfaces.remove(p_index);
- }
- int mesh_get_surface_count(RID p_mesh) const {
- RDMesh *m = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!m, 0);
- return m->surfaces.size();
- }
+ r_vertex_format = s->versions[version].vertex_format;
+ r_vertex_array_rd = s->versions[version].vertex_array;
- void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) {}
- AABB mesh_get_custom_aabb(RID p_mesh) const { return AABB(); }
+ s->version_lock.unlock();
+ }
- AABB mesh_get_aabb(RID p_mesh, RID p_skeleton) const { return AABB(); }
- void mesh_clear(RID p_mesh) {}
+ _FORCE_INLINE_ RID mesh_get_default_rd_buffer(DefaultRDBuffer p_buffer) {
+ ERR_FAIL_INDEX_V(p_buffer, DEFAULT_RD_BUFFER_MAX, RID());
+ return mesh_default_rd_buffers[p_buffer];
+ }
/* MULTIMESH API */
@@ -623,7 +644,7 @@ public:
float reflection_probe_get_origin_max_distance(RID p_probe) const { return 0.0; }
bool reflection_probe_renders_shadows(RID p_probe) const { return false; }
- void base_update_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) {}
+ void base_update_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance);
void skeleton_update_dependency(RID p_skeleton, RasterizerScene::InstanceBase *p_instance) {}
/* GI PROBE API */
@@ -752,9 +773,6 @@ public:
RID render_target_get_rd_framebuffer(RID p_render_target);
VS::InstanceType get_base_type(RID p_rid) const {
- if (mesh_owner.owns(p_rid)) {
- return VS::INSTANCE_MESH;
- }
return VS::INSTANCE_NONE;
}
@@ -777,7 +795,7 @@ public:
static RasterizerStorage *base_singleton;
- EffectsRD *get_effects();
+ RasterizerEffectsRD *get_effects();
RasterizerStorageRD();
~RasterizerStorageRD();
diff --git a/servers/visual/rasterizer_rd/render_pipeline_vertex_format_cache_rd.cpp b/servers/visual/rasterizer_rd/render_pipeline_vertex_format_cache_rd.cpp
index 9d4e61c733..b2cb6a1634 100644
--- a/servers/visual/rasterizer_rd/render_pipeline_vertex_format_cache_rd.cpp
+++ b/servers/visual/rasterizer_rd/render_pipeline_vertex_format_cache_rd.cpp
@@ -79,6 +79,11 @@ void RenderPipelineVertexFormatCacheRD::update_shader(RID p_shader) {
setup(p_shader, render_primitive, rasterization_state, multisample_state, depth_stencil_state, blend_state, dynamic_state_flags);
}
+void RenderPipelineVertexFormatCacheRD::clear() {
+ _clear();
+ shader = RID(); //clear shader
+}
+
RenderPipelineVertexFormatCacheRD::RenderPipelineVertexFormatCacheRD() {
version_count = 0;
versions = NULL;
diff --git a/servers/visual/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h b/servers/visual/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h
index 05d9b8db4a..9faa466eae 100644
--- a/servers/visual/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h
+++ b/servers/visual/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h
@@ -63,6 +63,10 @@ public:
void update_shader(RID p_shader);
_FORCE_INLINE_ RID get_render_pipeline(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id) {
+#ifdef DEBUG_ENABLED
+ ERR_FAIL_COND_V_MSG(shader.is_null(), RID(),
+ "Attempted to use an unused shader variant (shader is null),");
+#endif
for (uint32_t i = 0; i < version_count; i++) {
if (versions[i].vertex_id == p_vertex_format_id && versions[i].framebuffer_id == p_framebuffer_format_id) {
return versions[i].pipeline;
@@ -71,6 +75,7 @@ public:
return _generate_version(p_vertex_format_id, p_framebuffer_format_id);
}
+ void clear();
RenderPipelineVertexFormatCacheRD();
~RenderPipelineVertexFormatCacheRD();
};
diff --git a/servers/visual/rasterizer_rd/shaders/SCsub b/servers/visual/rasterizer_rd/shaders/SCsub
index a8e1dafb47..65a40e981d 100644
--- a/servers/visual/rasterizer_rd/shaders/SCsub
+++ b/servers/visual/rasterizer_rd/shaders/SCsub
@@ -6,3 +6,5 @@ if 'RD_GLSL' in env['BUILDERS']:
env.RD_GLSL('canvas.glsl');
env.RD_GLSL('canvas_occlusion.glsl');
env.RD_GLSL('blur.glsl');
+ env.RD_GLSL('scene_forward.glsl');
+ env.RD_GLSL('scene_forward_inc.glsl');
diff --git a/servers/visual/rasterizer_rd/shaders/scene_forward.glsl b/servers/visual/rasterizer_rd/shaders/scene_forward.glsl
new file mode 100644
index 0000000000..c18fead23e
--- /dev/null
+++ b/servers/visual/rasterizer_rd/shaders/scene_forward.glsl
@@ -0,0 +1,762 @@
+/* clang-format off */
+[vertex]
+/* clang-format on */
+
+#version 450
+
+/* clang-format off */
+VERSION_DEFINES
+/* clang-format on */
+
+/* INPUT ATTRIBS */
+
+layout(location = 0) in vec3 vertex_attrib;
+/* clang-format on */
+layout(location = 1) in vec3 normal_attrib;
+#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED)
+layout(location = 2) in vec4 tangent_attrib;
+#endif
+
+#if defined(COLOR_USED)
+layout(location = 3) in vec4 color_attrib;
+#endif
+
+#if defined(UV_USED)
+layout(location = 4) in vec2 uv_attrib;
+#endif
+
+#if defined(UV2_USED) || defined(USE_LIGHTMAP)
+layout(location = 5) in vec2 uv2_attrib;
+#endif
+
+layout(location = 6) in uvec4 bone_attrib; // always bound, even if unused
+
+/* Varyings */
+
+out vec3 vertex_interp;
+out vec3 normal_interp;
+
+#if defined(COLOR_USED)
+out vec4 color_interp;
+#endif
+
+#if defined(UV2_USED) || defined(USE_LIGHTMAP)
+out vec2 uv_interp;
+#endif
+
+//uv2 may be used for lightmapping, so always pass.
+#if !defined(MODE_RENDER_DEPTH)
+out vec2 uv2_interp;
+#endif
+
+#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED)
+out vec3 tangent_interp;
+out vec3 binormal_interp;
+#endif
+
+#ifdef USE_MATERIAL_UNIFORMS
+layout(set = 2, binding = 0, std140) uniform MaterialUniforms {
+/* clang-format off */
+MATERIAL_UNIFORMS
+/* clang-format on */
+} material;
+#endif
+
+
+/* clang-format off */
+
+VERTEX_SHADER_GLOBALS
+
+/* clang-format on */
+
+// FIXME: This triggers a Mesa bug that breaks rendering, so disabled for now.
+// See GH-13450 and https://bugs.freedesktop.org/show_bug.cgi?id=100316
+//invariant gl_Position;
+
+void main() {
+
+ vec3 vertex = vertex_attrib;
+
+ mat4 world_matrix = instance_data.transform;
+ mat3 world_normal_matrix= instance_data.normal_transform;
+
+ vec3 normal = normal_attrib;
+
+#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED)
+ vec3 tangent = tangent_attrib.xyz;
+ 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);
+#endif
+
+#if defined(UV_USED)
+ uv_interp = uv_attrib;
+#endif
+
+#if defined(UV2_USED) || defined(USE_LIGHTMAP)
+ uv2_interp = uv2_attrib;
+#endif
+
+#ifdef USE_OVERRIDE_POSITION
+ vec4 position;
+#endif
+
+ vec4 instance_custom = vec4(0.0);
+
+ mat4 projection_matrix = scene_data.projection_matrix;
+
+//using world coordinates
+#if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED)
+
+ vertex = (world_matrix * vec4(vertex,1.0)).xyz;
+
+ normal = world_normal_matrix * normal;
+
+#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED)
+
+ tangent = world_normal_matrix * tangent;
+ binormal = world_normal_matrix * binormal;
+
+#endif
+#endif
+
+ float roughness = 1.0;
+
+ mat4 modelview = scene_data.inv_camera_matrix * instance_data.transform;
+ mat3 modelview_normal = mat3(scene_data.inv_camera_matrix) * instance_data.normal_transform;
+
+ {
+ /* clang-format off */
+
+VERTEX_SHADER_CODE
+
+ /* clang-format on */
+ }
+
+// using local coordinates (default)
+#if !defined(SKIP_TRANSFORM_USED) && !defined(VERTEX_WORLD_COORDS_USED)
+
+ vertex = (modelview * vec4(vertex,1.0)).xyz;
+ normal = modelview_normal * normal;
+#endif
+
+#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED)
+
+ binormal = modelview_normal * binormal;
+ tangent = modelview_normal * tangent;
+#endif
+#endif
+
+//using world coordinates
+#if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED)
+
+ vertex = (scene_data.inv_camera_matrix * vec4(vertex,1.0)).xyz;
+ normal = mat3(scene_data.inverse_normal_matrix) * normal;
+
+#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED)
+
+ binormal = mat3(scene_data.camera_inverse_binormal_matrix) * binormal;
+ tangent = mat3(scene_data.camera_inverse_tangent_matrix) * tangent;
+#endif
+#endif
+
+ vertex_interp = vertex;
+ normal_interp = normal;
+
+#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED)
+ tangent_interp = tangent;
+ binormal_interp = binormal;
+#endif
+
+#ifdef MODE_RENDER_DEPTH
+
+ float z_ofs = scene_data.z_offset;
+ z_ofs += (1.0 - abs(normal_interp.z)) * scene_data.z_slope_scale;
+ vertex_interp.z -= z_ofs;
+
+#endif //MODE_RENDER_DEPTH
+
+#ifdef USE_OVERRIDE_POSITION
+ gl_Position = position;
+#else
+ gl_Position = projection_matrix * vec4(vertex_interp, 1.0);
+#endif
+
+}
+
+/* clang-format off */
+[fragment]
+/* clang-format on */
+
+#version 450
+
+/* clang-format off */
+VERSION_DEFINES
+/* clang-format on */
+
+
+/* Varyings */
+
+#if defined(COLOR_USED)
+in vec4 color_interp;
+#endif
+
+#if defined(UV_USED)
+in vec2 uv_interp;
+#endif
+
+#if defined(UV2_USED) || defined(USE_LIGHTMAP)
+in vec2 uv2_interp;
+#endif
+
+#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED)
+in vec3 tangent_interp;
+in vec3 binormal_interp;
+#endif
+
+in highp vec3 vertex_interp;
+in vec3 normal_interp;
+
+//defines to keep compatibility with vertex
+
+#define world_matrix instance_data.transform;
+#define world_normal_matrix instance_data.normal_transform;
+#define projection_matrix scene_data.projection_matrix;
+
+#ifdef USE_MATERIAL_UNIFORMS
+layout(set = 2, binding = 0, std140) uniform MaterialUniforms {
+/* clang-format off */
+MATERIAL_UNIFORMS
+/* clang-format on */
+} material;
+#endif
+
+/* clang-format off */
+
+FRAGMENT_SHADER_GLOBALS
+
+/* clang-format on */
+
+#ifdef MODE_MULTIPLE_RENDER_TARGETS
+
+layout(location = 0) out vec4 diffuse_buffer; //diffuse (rgb) and roughness
+layout(location = 1) out vec4 specular_buffer; //specular and SSS (subsurface scatter)
+#else
+
+layout(location = 0) out vec4 frag_color;
+
+#endif
+
+// This returns the G_GGX function divided by 2 cos_theta_m, where in practice cos_theta_m is either N.L or N.V.
+// We're dividing this factor off because the overall term we'll end up looks like
+// (see, for example, the first unnumbered equation in B. Burley, "Physically Based Shading at Disney", SIGGRAPH 2012):
+//
+// F(L.V) D(N.H) G(N.L) G(N.V) / (4 N.L N.V)
+//
+// We're basically regouping this as
+//
+// F(L.V) D(N.H) [G(N.L)/(2 N.L)] [G(N.V) / (2 N.V)]
+//
+// and thus, this function implements the [G(N.m)/(2 N.m)] part with m = L or V.
+//
+// The contents of the D and G (G1) functions (GGX) are taken from
+// E. Heitz, "Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs", J. Comp. Graph. Tech. 3 (2) (2014).
+// Eqns 71-72 and 85-86 (see also Eqns 43 and 80).
+
+float G_GGX_2cos(float cos_theta_m, float alpha) {
+ // Schlick's approximation
+ // C. Schlick, "An Inexpensive BRDF Model for Physically-based Rendering", Computer Graphics Forum. 13 (3): 233 (1994)
+ // Eq. (19), although see Heitz (2014) the about the problems with his derivation.
+ // It nevertheless approximates GGX well with k = alpha/2.
+ float k = 0.5 * alpha;
+ return 0.5 / (cos_theta_m * (1.0 - k) + k);
+
+ // float cos2 = cos_theta_m * cos_theta_m;
+ // float sin2 = (1.0 - cos2);
+ // return 1.0 / (cos_theta_m + sqrt(cos2 + alpha * alpha * sin2));
+}
+
+float D_GGX(float cos_theta_m, float alpha) {
+ float alpha2 = alpha * alpha;
+ float d = 1.0 + (alpha2 - 1.0) * cos_theta_m * cos_theta_m;
+ return alpha2 / (M_PI * d * d);
+}
+
+float G_GGX_anisotropic_2cos(float cos_theta_m, float alpha_x, float alpha_y, float cos_phi, float sin_phi) {
+ float cos2 = cos_theta_m * cos_theta_m;
+ float sin2 = (1.0 - cos2);
+ float s_x = alpha_x * cos_phi;
+ float s_y = alpha_y * sin_phi;
+ return 1.0 / max(cos_theta_m + sqrt(cos2 + (s_x * s_x + s_y * s_y) * sin2), 0.001);
+}
+
+float D_GGX_anisotropic(float cos_theta_m, float alpha_x, float alpha_y, float cos_phi, float sin_phi) {
+ float cos2 = cos_theta_m * cos_theta_m;
+ float sin2 = (1.0 - cos2);
+ float r_x = cos_phi / alpha_x;
+ float r_y = sin_phi / alpha_y;
+ float d = cos2 + sin2 * (r_x * r_x + r_y * r_y);
+ return 1.0 / max(M_PI * alpha_x * alpha_y * d * d, 0.001);
+}
+
+float SchlickFresnel(float u) {
+ float m = 1.0 - u;
+ float m2 = m * m;
+ return m2 * m2 * m; // pow(m,5)
+}
+
+float GTR1(float NdotH, float a) {
+ if (a >= 1.0) return 1.0 / M_PI;
+ float a2 = a * a;
+ float t = 1.0 + (a2 - 1.0) * NdotH * NdotH;
+ return (a2 - 1.0) / (M_PI * log(a2) * t);
+}
+
+vec3 F0(float metallic, float specular, vec3 albedo) {
+ float dielectric = 0.16 * specular * specular;
+ // use albedo * metallic as colored specular reflectance at 0 angle for metallic materials;
+ // see https://google.github.io/filament/Filament.md.html
+ return mix(vec3(dielectric), albedo, vec3(metallic));
+}
+
+void light_compute(vec3 N, vec3 L, vec3 V, vec3 B, vec3 T, vec3 light_color, vec3 attenuation, vec3 diffuse_color, vec3 transmission, float specular_blob_intensity, float roughness, float metallic, float specular, float rim, float rim_tint, float clearcoat, float clearcoat_gloss, float anisotropy, inout vec3 diffuse_light, inout vec3 specular_light, inout float alpha) {
+
+#if defined(USE_LIGHT_SHADER_CODE)
+ // light is written by the light shader
+
+ vec3 normal = N;
+ vec3 albedo = diffuse_color;
+ vec3 light = L;
+ vec3 view = V;
+
+ /* clang-format off */
+
+LIGHT_SHADER_CODE
+
+ /* clang-format on */
+
+#else
+ float NdotL = dot(N, L);
+ float cNdotL = max(NdotL, 0.0); // clamped NdotL
+ float NdotV = dot(N, V);
+ float cNdotV = max(NdotV, 0.0);
+
+#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_BLINN) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_USE_CLEARCOAT)
+ vec3 H = normalize(V + L);
+#endif
+
+#if defined(SPECULAR_BLINN) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_USE_CLEARCOAT)
+ float cNdotH = max(dot(N, H), 0.0);
+#endif
+
+#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_USE_CLEARCOAT)
+ float cLdotH = max(dot(L, H), 0.0);
+#endif
+
+ if (metallic < 1.0) {
+#if defined(DIFFUSE_OREN_NAYAR)
+ vec3 diffuse_brdf_NL;
+#else
+ float diffuse_brdf_NL; // BRDF times N.L for calculating diffuse radiance
+#endif
+
+#if defined(DIFFUSE_LAMBERT_WRAP)
+ // energy conserving lambert wrap shader
+ diffuse_brdf_NL = max(0.0, (NdotL + roughness) / ((1.0 + roughness) * (1.0 + roughness)));
+
+#elif defined(DIFFUSE_OREN_NAYAR)
+
+ {
+ // see http://mimosa-pudica.net/improved-oren-nayar.html
+ float LdotV = dot(L, V);
+
+ float s = LdotV - NdotL * NdotV;
+ float t = mix(1.0, max(NdotL, NdotV), step(0.0, s));
+
+ float sigma2 = roughness * roughness; // TODO: this needs checking
+ vec3 A = 1.0 + sigma2 * (-0.5 / (sigma2 + 0.33) + 0.17 * diffuse_color / (sigma2 + 0.13));
+ float B = 0.45 * sigma2 / (sigma2 + 0.09);
+
+ diffuse_brdf_NL = cNdotL * (A + vec3(B) * s / t) * (1.0 / M_PI);
+ }
+
+#elif defined(DIFFUSE_TOON)
+
+ diffuse_brdf_NL = smoothstep(-roughness, max(roughness, 0.01), NdotL);
+
+#elif defined(DIFFUSE_BURLEY)
+
+ {
+ float FD90_minus_1 = 2.0 * cLdotH * cLdotH * roughness - 0.5;
+ float FdV = 1.0 + FD90_minus_1 * SchlickFresnel(cNdotV);
+ float FdL = 1.0 + FD90_minus_1 * SchlickFresnel(cNdotL);
+ diffuse_brdf_NL = (1.0 / M_PI) * FdV * FdL * cNdotL;
+ /*
+ float energyBias = mix(roughness, 0.0, 0.5);
+ float energyFactor = mix(roughness, 1.0, 1.0 / 1.51);
+ float fd90 = energyBias + 2.0 * VoH * VoH * roughness;
+ float f0 = 1.0;
+ float lightScatter = f0 + (fd90 - f0) * pow(1.0 - cNdotL, 5.0);
+ float viewScatter = f0 + (fd90 - f0) * pow(1.0 - cNdotV, 5.0);
+
+ diffuse_brdf_NL = lightScatter * viewScatter * energyFactor;
+ */
+ }
+#else
+ // lambert
+ diffuse_brdf_NL = cNdotL * (1.0 / M_PI);
+#endif
+
+ diffuse_light += light_color * diffuse_color * diffuse_brdf_NL * attenuation;
+
+#if defined(TRANSMISSION_USED)
+ diffuse_light += light_color * diffuse_color * (vec3(1.0 / M_PI) - diffuse_brdf_NL) * transmission * attenuation;
+#endif
+
+#if defined(LIGHT_USE_RIM)
+ float rim_light = pow(max(0.0, 1.0 - cNdotV), max(0.0, (1.0 - roughness) * 16.0));
+ diffuse_light += rim_light * rim * mix(vec3(1.0), diffuse_color, rim_tint) * light_color;
+#endif
+ }
+
+ if (roughness > 0.0) { // FIXME: roughness == 0 should not disable specular light entirely
+
+ // D
+
+#if defined(SPECULAR_BLINN)
+
+ //normalized blinn
+ float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25;
+ float blinn = pow(cNdotH, shininess);
+ blinn *= (shininess + 8.0) * (1.0 / (8.0 * M_PI));
+ float intensity = (blinn) / max(4.0 * cNdotV * cNdotL, 0.75);
+
+ specular_light += light_color * intensity * specular_blob_intensity * attenuation;
+
+#elif defined(SPECULAR_PHONG)
+
+ vec3 R = normalize(-reflect(L, N));
+ float cRdotV = max(0.0, dot(R, V));
+ float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25;
+ float phong = pow(cRdotV, shininess);
+ phong *= (shininess + 8.0) * (1.0 / (8.0 * M_PI));
+ float intensity = (phong) / max(4.0 * cNdotV * cNdotL, 0.75);
+
+ specular_light += light_color * intensity * specular_blob_intensity * attenuation;
+
+#elif defined(SPECULAR_TOON)
+
+ vec3 R = normalize(-reflect(L, N));
+ float RdotV = dot(R, V);
+ float mid = 1.0 - roughness;
+ mid *= mid;
+ float intensity = smoothstep(mid - roughness * 0.5, mid + roughness * 0.5, RdotV) * mid;
+ diffuse_light += light_color * intensity * specular_blob_intensity * attenuation; // write to diffuse_light, as in toon shading you generally want no reflection
+
+#elif defined(SPECULAR_DISABLED)
+ // none..
+
+#elif defined(SPECULAR_SCHLICK_GGX)
+ // shlick+ggx as default
+
+#if defined(LIGHT_ANISOTROPY_USED)
+
+ float alpha_ggx = roughness * roughness;
+ float aspect = sqrt(1.0 - anisotropy * 0.9);
+ float ax = alpha_ggx / aspect;
+ float ay = alpha_ggx * aspect;
+ float XdotH = dot(T, H);
+ float YdotH = dot(B, H);
+ float D = D_GGX_anisotropic(cNdotH, ax, ay, XdotH, YdotH);
+ float G = G_GGX_anisotropic_2cos(cNdotL, ax, ay, XdotH, YdotH) * G_GGX_anisotropic_2cos(cNdotV, ax, ay, XdotH, YdotH);
+
+#else
+ float alpha_ggx = roughness * roughness;
+ float D = D_GGX(cNdotH, alpha_ggx);
+ float G = G_GGX_2cos(cNdotL, alpha_ggx) * G_GGX_2cos(cNdotV, alpha_ggx);
+#endif
+ // F
+ vec3 f0 = F0(metallic, specular, diffuse_color);
+ float cLdotH5 = SchlickFresnel(cLdotH);
+ vec3 F = mix(vec3(cLdotH5), vec3(1.0), f0);
+
+ vec3 specular_brdf_NL = cNdotL * D * F * G;
+
+ specular_light += specular_brdf_NL * light_color * specular_blob_intensity * attenuation;
+#endif
+
+#if defined(LIGHT_USE_CLEARCOAT)
+
+#if !defined(SPECULAR_SCHLICK_GGX)
+ float cLdotH5 = SchlickFresnel(cLdotH);
+#endif
+ float Dr = GTR1(cNdotH, mix(.1, .001, clearcoat_gloss));
+ float Fr = mix(.04, 1.0, cLdotH5);
+ float Gr = G_GGX_2cos(cNdotL, .25) * G_GGX_2cos(cNdotV, .25);
+
+ float clearcoat_specular_brdf_NL = 0.25 * clearcoat * Gr * Fr * Dr * cNdotL;
+
+ specular_light += clearcoat_specular_brdf_NL * light_color * specular_blob_intensity * attenuation;
+#endif
+ }
+
+#ifdef USE_SHADOW_TO_OPACITY
+ alpha = min(alpha, clamp(1.0 - length(attenuation), 0.0, 1.0));
+#endif
+
+#endif //defined(USE_LIGHT_SHADER_CODE)
+}
+
+
+void main() {
+
+
+ //lay out everything, whathever is unused is optimized away anyway
+ vec3 vertex = vertex_interp;
+ vec3 view = -normalize(vertex_interp);
+ vec3 albedo = vec3(1.0);
+ vec3 transmission = vec3(0.0);
+ float metallic = 0.0;
+ float specular = 0.5;
+ vec3 emission = vec3(0.0);
+ float roughness = 1.0;
+ float rim = 0.0;
+ float rim_tint = 0.0;
+ float clearcoat = 0.0;
+ float clearcoat_gloss = 0.0;
+ float anisotropy = 0.0;
+ vec2 anisotropy_flow = vec2(1.0, 0.0);
+
+#if defined(ENABLE_AO)
+ float ao = 1.0;
+ float ao_light_affect = 0.0;
+#endif
+
+ float alpha = 1.0;
+
+#if defined(ALPHA_SCISSOR_USED)
+ float alpha_scissor = 0.5;
+#endif
+
+#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED)
+ vec3 binormal = normalize(binormal_interp);
+ vec3 tangent = normalize(tangent_interp);
+#else
+ vec3 binormal = vec3(0.0);
+ vec3 tangent = vec3(0.0);
+#endif
+ vec3 normal = normalize(normal_interp);
+
+#if defined(DO_SIDE_CHECK)
+ if (!gl_FrontFacing) {
+ normal = -normal;
+ }
+#endif
+
+#if defined(UV_USED)
+ vec2 uv = uv_interp;
+#endif
+
+#if defined(UV2_USED) || defined(USE_LIGHTMAP)
+ vec2 uv2 = uv2_interp;
+#endif
+
+#if defined(COLOR_USED)
+ vec4 color = color_interp;
+#endif
+
+#if defined(NORMALMAP_USED)
+
+ vec3 normalmap = vec3(0.5);
+#endif
+
+ float normaldepth = 1.0;
+
+#if defined(SCREEN_UV_USED)
+ vec2 screen_uv = gl_FragCoord.xy * screen_pixel_size;
+#endif
+
+#if defined(SSS_USED)
+ float sss_strength = 0.0;
+#endif
+
+#define
+ {
+ /* clang-format off */
+
+FRAGMENT_SHADER_CODE
+
+ /* clang-format on */
+ }
+
+#if !defined(USE_SHADOW_TO_OPACITY)
+
+#if defined(ALPHA_SCISSOR_USED)
+ if (alpha < alpha_scissor) {
+ discard;
+ }
+#endif // ALPHA_SCISSOR_USED
+
+#ifdef USE_OPAQUE_PREPASS
+
+ if (alpha < opaque_prepass_threshold) {
+ discard;
+ }
+
+#endif // USE_OPAQUE_PREPASS
+
+#endif // !USE_SHADOW_TO_OPACITY
+
+#if defined(NORMALMAP_USED)
+
+ normalmap.xy = normalmap.xy * 2.0 - 1.0;
+ normalmap.z = sqrt(max(0.0, 1.0 - dot(normalmap.xy, normalmap.xy))); //always ignore Z, as it can be RG packed, Z may be pos/neg, etc.
+
+ normal = normalize(mix(normal, tangent * normalmap.x + binormal * normalmap.y + normal * normalmap.z, normaldepth));
+
+#endif
+
+#if defined(LIGHT_ANISOTROPY_USED)
+
+ if (anisotropy > 0.01) {
+ //rotation matrix
+ mat3 rot = mat3(tangent, binormal, normal);
+ //make local to space
+ tangent = normalize(rot * vec3(anisotropy_flow.x, anisotropy_flow.y, 0.0));
+ binormal = normalize(rot * vec3(-anisotropy_flow.y, anisotropy_flow.x, 0.0));
+ }
+
+#endif
+
+#ifdef ENABLE_CLIP_ALPHA
+ if (albedo.a < 0.99) {
+ //used for doublepass and shadowmapping
+ discard;
+ }
+#endif
+
+ /////////////////////// LIGHTING //////////////////////////////
+
+ //apply energy conservation
+
+ vec3 specular_light = vec3(0.0, 0.0, 0.0);
+ vec3 diffuse_light = vec3(0.0, 0.0, 0.0);
+ vec3 ambient_light = vec3( 0.0, 0.0, 0.0);
+
+ //radiance
+
+ float specular_blob_intensity = 1.0;
+
+#if defined(SPECULAR_TOON)
+ specular_blob_intensity *= specular * 2.0;
+#endif
+
+ //gi probes
+
+ //lightmap
+
+ //lightmap capture
+
+ //process reflections
+
+ {
+
+#if defined(DIFFUSE_TOON)
+ //simplify for toon, as
+ specular_light *= specular * metallic * albedo * 2.0;
+#else
+
+ // scales the specular reflections, needs to be be computed before lighting happens,
+ // but after environment, GI, and reflection probes are added
+ // Environment brdf approximation (Lazarov 2013)
+ // see https://www.unrealengine.com/en-US/blog/physically-based-shading-on-mobile
+ const vec4 c0 = vec4(-1.0, -0.0275, -0.572, 0.022);
+ const vec4 c1 = vec4(1.0, 0.0425, 1.04, -0.04);
+ vec4 r = roughness * c0 + c1;
+ float ndotv = clamp(dot(normal, eye_vec), 0.0, 1.0);
+ float a004 = min(r.x * r.x, exp2(-9.28 * ndotv)) * r.x + r.y;
+ vec2 env = vec2(-1.04, 1.04) * a004 + r.zw;
+
+ vec3 f0 = F0(metallic, specular, albedo);
+ specular_light *= env.x * f0 + env.y;
+#endif
+ }
+
+ //directional light
+
+
+ //process omni and spots
+
+#ifdef USE_SHADOW_TO_OPACITY
+ alpha = min(alpha, clamp(length(ambient_light), 0.0, 1.0));
+
+#if defined(ALPHA_SCISSOR_USED)
+ if (alpha < alpha_scissor) {
+ discard;
+ }
+#endif // ALPHA_SCISSOR_USED
+
+#ifdef USE_OPAQUE_PREPASS
+
+ if (alpha < opaque_prepass_threshold) {
+ discard;
+ }
+
+#endif // USE_OPAQUE_PREPASS
+
+#endif // USE_SHADOW_TO_OPACITY
+
+
+#ifdef MODE_RENDER_DEPTH
+//nothing happens, so a tree-ssa optimizer will result in no fragment shader :)
+#else
+
+ specular_light *= reflection_multiplier;
+ ambient_light *= albedo; //ambient must be multiplied by albedo at the end
+
+#if defined(ENABLE_AO)
+ ambient_light *= ao;
+ ao_light_affect = mix(1.0, ao, ao_light_affect);
+ specular_light *= ao_light_affect;
+ diffuse_light *= ao_light_affect;
+#endif
+
+ // base color remapping
+ diffuse_light *= 1.0 - metallic; // TODO: avoid all diffuse and ambient light calculations when metallic == 1 up to this point
+ ambient_light *= 1.0 - metallic;
+
+ //fog
+
+#ifdef MODE_MULTIPLE_RENDER_TARGETS
+
+#ifdef USE_NO_SHADING
+ diffuse_buffer = vec4(albedo.rgb, 0.0);
+ specular_buffer = vec4(0.0);
+
+#else
+
+ diffuse_buffer = vec4(emission + diffuse_light + ambient_light, sss_strenght);
+ specular_buffer = vec4(specular_light, metallic);
+
+#endif
+
+#else //MODE_MULTIPLE_RENDER_TARGETS
+
+#ifdef USE_NO_SHADING
+ frag_color = vec4(albedo, alpha);
+#else
+ frag_color = vec4(emission + ambient_light + diffuse_light + specular_light, alpha);
+
+#endif //USE_NO_SHADING
+
+#endif //MODE_MULTIPLE_RENDER_TARGETS
+
+#endif //MODE_RENDER_DEPTH
+}
diff --git a/servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl b/servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl
new file mode 100644
index 0000000000..189371c2c0
--- /dev/null
+++ b/servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl
@@ -0,0 +1,141 @@
+
+#define M_PI 3.14159265359
+#define ROUGHNESS_MAX_LOD 5
+
+/* Set 0 Scene data, screen and sources (changes the least) */
+
+layout(set=0,location=1) uniform texture2D depth_buffer;
+layout(set=0,location=2) uniform texture2D color_buffer;
+layout(set=0,location=3) uniform texture2D normal_buffer;
+
+layout(set=0,binding=4,std140) uniform SceneData {
+
+ mat4 projection_matrix;
+ mat4 inv_projection_matrix;
+
+ mat4 camera_matrix;
+ mat4 inv_camera_matrix;
+
+ vec2 viewport_size;
+ vec2 screen_pixel_size;
+
+ //used for shadow mapping only
+ float z_offset;
+ float z_slope_scale;
+
+
+ float time;
+ float reflection_multiplier; // one normally, zero when rendering reflections
+
+#if 0
+ vec4 ambient_light_color;
+ vec4 bg_color;
+
+ vec4 fog_color_enabled;
+ vec4 fog_sun_color_amount;
+
+ float ambient_energy;
+ float bg_energy;
+
+#endif
+
+#if 0
+ vec2 shadow_atlas_pixel_size;
+ vec2 directional_shadow_pixel_size;
+
+
+ float z_far;
+
+ float subsurface_scatter_width;
+ float ambient_occlusion_affect_light;
+ float ambient_occlusion_affect_ao_channel;
+ float opaque_prepass_threshold;
+
+ bool fog_depth_enabled;
+ float fog_depth_begin;
+ float fog_depth_end;
+ float fog_density;
+ float fog_depth_curve;
+ bool fog_transmit_enabled;
+ float fog_transmit_curve;
+ bool fog_height_enabled;
+ float fog_height_min;
+ float fog_height_max;
+ float fog_height_curve;
+#endif
+} scene_data;
+
+layout(set = 0, binding = 5) uniform sampler material_samplers[12];
+
+#if 0
+struct DirectionalLightData {
+
+ vec4 light_pos_inv_radius;
+ vec4 light_direction_attenuation;
+ vec4 light_color_energy;
+ vec4 light_params; // cone attenuation, angle, specular, shadow enabled,
+ vec4 light_clamp;
+ vec4 shadow_color_contact;
+ mat4 shadow_matrix1;
+ mat4 shadow_matrix2;
+ mat4 shadow_matrix3;
+ mat4 shadow_matrix4;
+ vec4 shadow_split_offsets;
+};
+#endif
+
+/* Set 1 Skeleton Data (most objects lack it, so it changes little */
+
+#if 0
+layout(set = 1 binding = 0, std140) uniform SkeletonData {
+ mat4 transform;
+ bool use_skeleton;
+ bool use_world_coords;
+ bool pad1;
+ bool pad2;
+} skeleton;
+
+layout(set = 1, binding = 1) uniform textureBuffer skeleton_bones;
+#endif
+
+/* Set 2 Custom Material Data (changess less than instance) */
+
+
+/* Set 3 Instance Data (Set on every draw call) */
+
+layout(push_constant, binding = 0, std430) uniform DrawData {
+ //used in forward rendering, 16 bits indices, max 8
+ uvec4 reflection_probe_indices;
+ uvec4 omni_light_indices;
+ uvec4 spot_light_indices;
+ uvec4 decal_indices;
+} draw_data;
+
+layout(set = 3 binding = 0, std140) uniform InstanceData {
+ mat4 transform;
+ mat3 normal_transform;
+ uint flags;
+ uint pad0;
+ uint pad0;
+ uint pad0;
+} instance_data;
+
+layout(set = 3, binding = 1) uniform textureBuffer multimesh_transforms;
+
+#ifdef USE_LIGHTMAP
+
+layout(set = 3, binding = 2) uniform texture2D lightmap;
+
+#endif
+
+#ifdef USE_VOXEL_CONE_TRACING
+
+layout(set = 3, binding = 3) uniform texture3D gi_probe[2];
+
+#ifdef USE_ANISOTROPIC_VOXEL_CONE_TRACING
+layout(set = 3, binding = 4) uniform texture3D gi_probe_aniso_pos[2];
+layout(set = 3, binding = 5) uniform texture3D gi_probe_aniso_neg[2];
+#endif
+
+
+#endif
diff --git a/servers/visual/rendering_device.h b/servers/visual/rendering_device.h
index 49a10a684a..64c4f0f0c1 100644
--- a/servers/visual/rendering_device.h
+++ b/servers/visual/rendering_device.h
@@ -568,7 +568,7 @@ public:
};
virtual RID shader_create(const Vector<ShaderStageData> &p_stages) = 0;
- virtual Vector<int> shader_get_vertex_input_locations_used(RID p_shader) = 0;
+ virtual uint32_t shader_get_vertex_input_attribute_mask(RID p_shader) = 0;
/******************/
/**** UNIFORMS ****/
@@ -613,6 +613,7 @@ public:
virtual bool uniform_set_is_valid(RID p_uniform_set) = 0;
virtual Error buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const void *p_data, bool p_sync_with_draw = false) = 0; //this function can be used from any thread and it takes effect at the begining of the frame, unless sync with draw is used, which is used to mix updates with draw calls
+ virtual PoolVector<uint8_t> buffer_get_data(RID p_buffer) = 0; //this causes stall, only use to retrieve large buffers for saving
/*************************/
/**** RENDER PIPELINE ****/
diff --git a/servers/visual/shader_types.cpp b/servers/visual/shader_types.cpp
index 9c7c97ffe5..5cd5f0b7bb 100644
--- a/servers/visual/shader_types.cpp
+++ b/servers/visual/shader_types.cpp
@@ -72,11 +72,13 @@ ShaderTypes::ShaderTypes() {
//builtins
shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["WORLD_MATRIX"] = ShaderLanguage::TYPE_MAT4;
+ shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["WORLD_NORMAL_MATRIX"] = ShaderLanguage::TYPE_MAT3;
shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["INV_CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4;
- shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["MODELVIEW_MATRIX"] = ShaderLanguage::TYPE_MAT4;
shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["INV_PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
+ shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["MODELVIEW_MATRIX"] = ShaderLanguage::TYPE_MAT4;
+ shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["MODELVIEW_NORMAL_MATRIX"] = ShaderLanguage::TYPE_MAT3;
shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEWPORT_SIZE"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["OUTPUT_IS_SRGB"] = constt(ShaderLanguage::TYPE_BOOL);
@@ -114,11 +116,11 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["DEPTH"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_UV"] = ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["POINT_COORD"] = constt(ShaderLanguage::TYPE_VEC2);
- shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["ALPHA_SCISSOR"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["OUTPUT_IS_SRGB"] = constt(ShaderLanguage::TYPE_BOOL);
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["WORLD_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["WORLD_NORMAL_MATRIX"] = constt(ShaderLanguage::TYPE_MAT3);
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["INV_CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
@@ -162,15 +164,17 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_SPATIAL].modes.push_back("depth_draw_opaque");
shader_modes[VS::SHADER_SPATIAL].modes.push_back("depth_draw_always");
shader_modes[VS::SHADER_SPATIAL].modes.push_back("depth_draw_never");
- shader_modes[VS::SHADER_SPATIAL].modes.push_back("depth_draw_alpha_prepass");
- shader_modes[VS::SHADER_SPATIAL].modes.push_back("depth_test_disable");
+ shader_modes[VS::SHADER_SPATIAL].modes.push_back("depth_prepass_alpha");
+
+ shader_modes[VS::SHADER_SPATIAL].modes.push_back("depth_test_disabled");
shader_modes[VS::SHADER_SPATIAL].modes.push_back("cull_back");
shader_modes[VS::SHADER_SPATIAL].modes.push_back("cull_front");
shader_modes[VS::SHADER_SPATIAL].modes.push_back("cull_disabled");
shader_modes[VS::SHADER_SPATIAL].modes.push_back("unshaded");
+ shader_modes[VS::SHADER_SPATIAL].modes.push_back("wireframe");
shader_modes[VS::SHADER_SPATIAL].modes.push_back("diffuse_lambert");
shader_modes[VS::SHADER_SPATIAL].modes.push_back("diffuse_lambert_wrap");
diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h
index 2122587304..3168359473 100644
--- a/servers/visual/visual_server_raster.h
+++ b/servers/visual/visual_server_raster.h
@@ -218,11 +218,18 @@ public:
/* MESH API */
+ virtual RID mesh_create_from_surfaces(const Vector<SurfaceData> &p_surfaces) {
+ RID mesh = mesh_create();
+ for (int i = 0; i < p_surfaces.size(); i++) {
+ mesh_add_surface(mesh, p_surfaces[i]);
+ }
+ return mesh;
+ }
+
BIND0R(RID, mesh_create)
- BIND10(mesh_add_surface, RID, uint32_t, PrimitiveType, const PoolVector<uint8_t> &, int, const PoolVector<uint8_t> &, int, const AABB &, const Vector<PoolVector<uint8_t> > &, const Vector<AABB> &)
+ BIND2(mesh_add_surface, RID, const SurfaceData &)
- BIND2(mesh_set_blend_shape_count, RID, int)
BIND1RC(int, mesh_get_blend_shape_count, RID)
BIND2(mesh_set_blend_shape_mode, RID, BlendShapeMode)
@@ -233,20 +240,8 @@ public:
BIND3(mesh_surface_set_material, RID, int, RID)
BIND2RC(RID, mesh_surface_get_material, RID, int)
- BIND2RC(int, mesh_surface_get_array_len, RID, int)
- BIND2RC(int, mesh_surface_get_array_index_len, RID, int)
-
- BIND2RC(PoolVector<uint8_t>, mesh_surface_get_array, RID, int)
- BIND2RC(PoolVector<uint8_t>, mesh_surface_get_index_array, RID, int)
-
- BIND2RC(uint32_t, mesh_surface_get_format, RID, int)
- BIND2RC(PrimitiveType, mesh_surface_get_primitive_type, RID, int)
-
- BIND2RC(AABB, mesh_surface_get_aabb, RID, int)
- BIND2RC(Vector<PoolVector<uint8_t> >, mesh_surface_get_blend_shapes, RID, int)
- BIND2RC(Vector<AABB>, mesh_surface_get_skeleton_aabb, RID, int)
+ BIND2RC(SurfaceData, mesh_get_surface, RID, int)
- BIND2(mesh_remove_surface, RID, int)
BIND1RC(int, mesh_get_surface_count, RID)
BIND2(mesh_set_custom_aabb, RID, const AABB &)
@@ -475,8 +470,6 @@ public:
BIND2(viewport_set_hide_scenario, RID, bool)
BIND2(viewport_set_hide_canvas, RID, bool)
BIND2(viewport_set_disable_environment, RID, bool)
- BIND2(viewport_set_disable_3d, RID, bool)
- BIND2(viewport_set_keep_3d_linear, RID, bool)
BIND2(viewport_attach_camera, RID, RID)
BIND2(viewport_set_scenario, RID, RID)
@@ -491,8 +484,6 @@ public:
BIND2(viewport_set_shadow_atlas_size, RID, int)
BIND3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int)
BIND2(viewport_set_msaa, RID, ViewportMSAA)
- BIND2(viewport_set_hdr, RID, bool)
- BIND2(viewport_set_usage, RID, ViewportUsage)
BIND2R(int, viewport_get_render_info, RID, ViewportRenderInfo)
BIND2(viewport_set_debug_draw, RID, ViewportDebugDraw)
diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp
index 27632be2b4..76ff6265cc 100644
--- a/servers/visual/visual_server_scene.cpp
+++ b/servers/visual/visual_server_scene.cpp
@@ -360,6 +360,11 @@ void VisualServerScene::instance_set_base(RID p_instance, RID p_base) {
instance->octree_id = 0;
}
+ if (instance->custom_data) {
+ VSG::scene_render->instance_free_custom_data(instance);
+ instance->custom_data = nullptr;
+ }
+
switch (instance->base_type) {
case VS::INSTANCE_LIGHT: {
@@ -489,6 +494,8 @@ void VisualServerScene::instance_set_base(RID p_instance, RID p_base) {
//forcefully update the dependency now, so if for some reason it gets removed, we can immediately clear it
VSG::storage->base_update_dependency(p_base, instance);
+
+ VSG::scene_render->instance_create_custom_data(instance);
}
_instance_queue_update(instance, true, true);
@@ -703,6 +710,8 @@ void VisualServerScene::instance_set_use_lightmap(RID p_instance, RID p_lightmap
lightmap_capture->users.insert(instance);
instance->lightmap = p_lightmap;
}
+
+ VSG::scene_render->instance_custom_data_update_lightmap(instance);
}
void VisualServerScene::instance_set_custom_aabb(RID p_instance, AABB p_aabb) {
@@ -932,6 +941,10 @@ void VisualServerScene::_update_instance(Instance *p_instance) {
p_instance->transformed_aabb = new_aabb;
+ if (p_instance->custom_data) {
+ VSG::scene_render->instance_custom_data_update_transform(p_instance);
+ }
+
if (!p_instance->scenario) {
return;
@@ -1684,7 +1697,7 @@ bool VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons
return animated_material_found;
}
-void VisualServerScene::render_camera(RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas) {
+void VisualServerScene::render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas) {
// render to mono camera
#ifndef _3D_DISABLED
@@ -1731,11 +1744,11 @@ void VisualServerScene::render_camera(RID p_camera, RID p_scenario, Size2 p_view
}
_prepare_scene(camera->transform, camera_matrix, ortho, camera->env, camera->visible_layers, p_scenario, p_shadow_atlas, RID());
- _render_scene(camera->transform, camera_matrix, ortho, camera->env, p_scenario, p_shadow_atlas, RID(), -1);
+ _render_scene(p_render_buffers, camera->transform, camera_matrix, ortho, camera->env, p_scenario, p_shadow_atlas, RID(), -1);
#endif
}
-void VisualServerScene::render_camera(Ref<ARVRInterface> &p_interface, ARVRInterface::Eyes p_eye, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas) {
+void VisualServerScene::render_camera(RID p_render_buffers, Ref<ARVRInterface> &p_interface, ARVRInterface::Eyes p_eye, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas) {
// render for AR/VR interface
Camera *camera = camera_owner.getornull(p_camera);
@@ -1816,7 +1829,7 @@ void VisualServerScene::render_camera(Ref<ARVRInterface> &p_interface, ARVRInter
}
// And render our scene...
- _render_scene(cam_transform, camera_matrix, false, camera->env, p_scenario, p_shadow_atlas, RID(), -1);
+ _render_scene(p_render_buffers, cam_transform, camera_matrix, false, camera->env, p_scenario, p_shadow_atlas, RID(), -1);
};
void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe) {
@@ -1955,6 +1968,10 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca
}
geom->lighting_dirty = false;
+
+ if (ins->custom_data) {
+ VSG::scene_render->instance_custom_data_update_lights(ins);
+ }
}
if (geom->reflection_dirty) {
@@ -1970,6 +1987,10 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca
}
geom->reflection_dirty = false;
+
+ if (ins->custom_data) {
+ VSG::scene_render->instance_custom_data_update_reflection_probes(ins);
+ }
}
if (geom->gi_probes_dirty) {
@@ -1985,6 +2006,10 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca
}
geom->gi_probes_dirty = false;
+
+ if (ins->custom_data) {
+ VSG::scene_render->instance_custom_data_update_gi_probes(ins);
+ }
}
ins->depth = near_plane.distance_to(ins->transform.origin);
@@ -2145,7 +2170,7 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca
}
}
-void VisualServerScene::_render_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
+void VisualServerScene::_render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
Scenario *scenario = scenario_owner.getornull(p_scenario);
@@ -2161,10 +2186,10 @@ void VisualServerScene::_render_scene(const Transform p_cam_transform, const Cam
/* PROCESS GEOMETRY AND DRAW SCENE */
- VSG::scene_render->render_scene(p_cam_transform, p_cam_projection, p_cam_orthogonal, (RasterizerScene::InstanceBase **)instance_cull_result, instance_cull_count, light_instance_cull_result, light_cull_count + directional_light_count, reflection_probe_instance_cull_result, reflection_probe_cull_count, environment, p_shadow_atlas, scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass);
+ VSG::scene_render->render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_orthogonal, (RasterizerScene::InstanceBase **)instance_cull_result, instance_cull_count, light_instance_cull_result, light_cull_count + directional_light_count, reflection_probe_instance_cull_result, reflection_probe_cull_count, environment, p_shadow_atlas, scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass);
}
-void VisualServerScene::render_empty_scene(RID p_scenario, RID p_shadow_atlas) {
+void VisualServerScene::render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) {
#ifndef _3D_DISABLED
@@ -2175,7 +2200,7 @@ void VisualServerScene::render_empty_scene(RID p_scenario, RID p_shadow_atlas) {
environment = scenario->environment;
else
environment = scenario->fallback_environment;
- VSG::scene_render->render_scene(Transform(), CameraMatrix(), true, NULL, 0, NULL, 0, NULL, 0, environment, p_shadow_atlas, scenario->reflection_atlas, RID(), 0);
+ VSG::scene_render->render_scene(p_render_buffers, Transform(), CameraMatrix(), true, NULL, 0, NULL, 0, NULL, 0, environment, p_shadow_atlas, scenario->reflection_atlas, RID(), 0);
#endif
}
@@ -2240,7 +2265,7 @@ bool VisualServerScene::_render_reflection_probe_step(Instance *p_instance, int
}
_prepare_scene(xform, cm, false, RID(), VSG::storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, shadow_atlas, reflection_probe->instance);
- _render_scene(xform, cm, false, RID(), p_instance->scenario->self, shadow_atlas, reflection_probe->instance, p_step);
+ _render_scene(RID(), xform, cm, false, RID(), p_instance->scenario->self, shadow_atlas, reflection_probe->instance, p_step);
} else {
//do roughness postprocess step until it believes it's done
@@ -3368,6 +3393,8 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) {
if (!cast_shadows) {
can_cast_shadows = false;
}
+
+ VSG::storage->base_update_dependency(mesh, p_instance);
}
} else if (p_instance->base_type == VS::INSTANCE_IMMEDIATE) {
diff --git a/servers/visual/visual_server_scene.h b/servers/visual/visual_server_scene.h
index 4a04e3b056..ad0c1caff3 100644
--- a/servers/visual/visual_server_scene.h
+++ b/servers/visual/visual_server_scene.h
@@ -478,11 +478,11 @@ public:
_FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_shadow_atlas, Scenario *p_scenario);
void _prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe);
- void _render_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
- void render_empty_scene(RID p_scenario, RID p_shadow_atlas);
+ void _render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
+ void render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas);
- void render_camera(RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas);
- void render_camera(Ref<ARVRInterface> &p_interface, ARVRInterface::Eyes p_eye, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas);
+ void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas);
+ void render_camera(RID p_render_buffers, Ref<ARVRInterface> &p_interface, ARVRInterface::Eyes p_eye, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas);
void update_dirty_instances();
//probes
diff --git a/servers/visual/visual_server_viewport.cpp b/servers/visual/visual_server_viewport.cpp
index c4447bed10..0baf2032bc 100644
--- a/servers/visual/visual_server_viewport.cpp
+++ b/servers/visual/visual_server_viewport.cpp
@@ -69,9 +69,9 @@ void VisualServerViewport::_draw_3d(Viewport *p_viewport, ARVRInterface::Eyes p_
}
if (p_viewport->use_arvr && arvr_interface.is_valid()) {
- VSG::scene->render_camera(arvr_interface, p_eye, p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
+ VSG::scene->render_camera(p_viewport->render_buffers, arvr_interface, p_eye, p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
} else {
- VSG::scene->render_camera(p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
+ VSG::scene->render_camera(p_viewport->render_buffers, p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
}
}
@@ -95,7 +95,7 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
}
}
- bool can_draw_3d = !p_viewport->disable_3d && !p_viewport->disable_3d_by_usage && VSG::scene->camera_owner.owns(p_viewport->camera);
+ bool can_draw_3d = !VSG::scene->camera_owner.owns(p_viewport->camera);
if (p_viewport->clear_mode != VS::VIEWPORT_CLEAR_NEVER) {
if (p_viewport->transparent_bg) {
@@ -106,6 +106,12 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
}
}
+ if ((scenario_draw_canvas_bg || can_draw_3d) && !p_viewport->render_buffers.is_valid()) {
+ //wants to draw 3D but there is no render buffer, create
+ p_viewport->render_buffers = VSG::scene_render->render_buffers_create();
+ VSG::scene_render->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, p_viewport->size.width, p_viewport->size.height, p_viewport->msaa);
+ }
+
VSG::storage->render_target_request_clear(p_viewport->render_target, bgcolor);
if (!scenario_draw_canvas_bg && can_draw_3d) {
@@ -218,7 +224,7 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
if (scenario_draw_canvas_bg && canvas_map.front() && canvas_map.front()->key().get_layer() > scenario_canvas_max_layer) {
if (!can_draw_3d) {
- VSG::scene->render_empty_scene(p_viewport->scenario, p_viewport->shadow_atlas);
+ VSG::scene->render_empty_scene(p_viewport->render_buffers, p_viewport->scenario, p_viewport->shadow_atlas);
} else {
_draw_3d(p_viewport, p_eye);
}
@@ -247,7 +253,7 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
if (scenario_draw_canvas_bg && E->key().get_layer() >= scenario_canvas_max_layer) {
if (!can_draw_3d) {
- VSG::scene->render_empty_scene(p_viewport->scenario, p_viewport->shadow_atlas);
+ VSG::scene->render_empty_scene(p_viewport->render_buffers, p_viewport->scenario, p_viewport->shadow_atlas);
} else {
_draw_3d(p_viewport, p_eye);
}
@@ -258,7 +264,7 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
if (scenario_draw_canvas_bg) {
if (!can_draw_3d) {
- VSG::scene->render_empty_scene(p_viewport->scenario, p_viewport->shadow_atlas);
+ VSG::scene->render_empty_scene(p_viewport->render_buffers, p_viewport->scenario, p_viewport->shadow_atlas);
} else {
_draw_3d(p_viewport, p_eye);
}
@@ -427,6 +433,9 @@ void VisualServerViewport::viewport_set_size(RID p_viewport, int p_width, int p_
viewport->size = Size2(p_width, p_height);
VSG::storage->render_target_set_size(viewport->render_target, p_width, p_height);
+ if (viewport->render_buffers.is_valid()) {
+ VSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa);
+ }
}
void VisualServerViewport::viewport_set_active(RID p_viewport, bool p_active) {
@@ -523,13 +532,6 @@ void VisualServerViewport::viewport_set_update_mode(RID p_viewport, VS::Viewport
viewport->update_mode = p_mode;
}
-void VisualServerViewport::viewport_set_vflip(RID p_viewport, bool p_enable) {
-
- Viewport *viewport = viewport_owner.getornull(p_viewport);
- ERR_FAIL_COND(!viewport);
-
- VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_VFLIP, p_enable);
-}
RID VisualServerViewport::viewport_get_texture(RID p_viewport) const {
@@ -561,25 +563,6 @@ void VisualServerViewport::viewport_set_disable_environment(RID p_viewport, bool
viewport->disable_environment = p_disable;
}
-void VisualServerViewport::viewport_set_disable_3d(RID p_viewport, bool p_disable) {
-
- Viewport *viewport = viewport_owner.getornull(p_viewport);
- ERR_FAIL_COND(!viewport);
-
- viewport->disable_3d = p_disable;
- //VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_NO_3D, p_disable);
- //this should be just for disabling rendering of 3D, to actually disable it, set usage
-}
-
-void VisualServerViewport::viewport_set_keep_3d_linear(RID p_viewport, bool p_keep_3d_linear) {
-
- Viewport *viewport = viewport_owner.getornull(p_viewport);
- ERR_FAIL_COND(!viewport);
-
- viewport->keep_3d_linear = p_keep_3d_linear;
- VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_KEEP_3D_LINEAR, p_keep_3d_linear);
-}
-
void VisualServerViewport::viewport_attach_camera(RID p_viewport, RID p_camera) {
Viewport *viewport = viewport_owner.getornull(p_viewport);
@@ -678,55 +661,12 @@ void VisualServerViewport::viewport_set_msaa(RID p_viewport, VS::ViewportMSAA p_
Viewport *viewport = viewport_owner.getornull(p_viewport);
ERR_FAIL_COND(!viewport);
-#ifndef _MSC_VER
-#warning this will no longer go in the render target, but in the 3D view
-#endif
- //VSG::storage->render_target_set_msaa(viewport->render_target, p_msaa);
-}
-
-void VisualServerViewport::viewport_set_hdr(RID p_viewport, bool p_enabled) {
-
- Viewport *viewport = viewport_owner.getornull(p_viewport);
- ERR_FAIL_COND(!viewport);
-
- VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_HDR, p_enabled);
-}
-
-void VisualServerViewport::viewport_set_usage(RID p_viewport, VS::ViewportUsage p_usage) {
-
- Viewport *viewport = viewport_owner.getornull(p_viewport);
- ERR_FAIL_COND(!viewport);
-
- switch (p_usage) {
- case VS::VIEWPORT_USAGE_2D: {
-
- VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_NO_3D, true);
- VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_NO_3D_EFFECTS, true);
- VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_NO_SAMPLING, false);
-
- viewport->disable_3d_by_usage = true;
- } break;
- case VS::VIEWPORT_USAGE_2D_NO_SAMPLING: {
-
- VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_NO_3D, true);
- VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_NO_3D_EFFECTS, true);
- VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_NO_SAMPLING, true);
- viewport->disable_3d_by_usage = true;
- } break;
- case VS::VIEWPORT_USAGE_3D: {
-
- VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_NO_3D, false);
- VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_NO_3D_EFFECTS, false);
- VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_NO_SAMPLING, false);
- viewport->disable_3d_by_usage = false;
- } break;
- case VS::VIEWPORT_USAGE_3D_NO_EFFECTS: {
-
- VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_NO_3D, false);
- VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_NO_3D_EFFECTS, true);
- VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_NO_SAMPLING, false);
- viewport->disable_3d_by_usage = false;
- } break;
+ if (viewport->msaa == p_msaa) {
+ return;
+ }
+ viewport->msaa = p_msaa;
+ if (viewport->render_buffers.is_valid()) {
+ VSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, p_msaa);
}
}
@@ -757,6 +697,9 @@ bool VisualServerViewport::free(RID p_rid) {
VSG::storage->free(viewport->render_target);
VSG::scene_render->free(viewport->shadow_atlas);
+ if (viewport->render_buffers.is_valid()) {
+ VSG::scene_render->free(viewport->render_buffers);
+ }
while (viewport->canvas_map.front()) {
viewport_remove_canvas(p_rid, viewport->canvas_map.front()->key());
diff --git a/servers/visual/visual_server_viewport.h b/servers/visual/visual_server_viewport.h
index f701e3612a..eecbe0d1db 100644
--- a/servers/visual/visual_server_viewport.h
+++ b/servers/visual/visual_server_viewport.h
@@ -56,6 +56,9 @@ public:
VS::ViewportUpdateMode update_mode;
RID render_target;
RID render_target_texture;
+ RID render_buffers;
+
+ VS::ViewportMSAA msaa;
int viewport_to_screen;
Rect2 viewport_to_screen_rect;
@@ -64,7 +67,6 @@ public:
bool hide_scenario;
bool hide_canvas;
bool disable_environment;
- bool disable_3d;
bool disable_3d_by_usage;
bool keep_3d_linear;
@@ -117,10 +119,9 @@ public:
disable_environment = false;
viewport_to_screen = 0;
shadow_atlas_size = 0;
- disable_3d = false;
- disable_3d_by_usage = false;
keep_3d_linear = false;
debug_draw = VS::VIEWPORT_DEBUG_DRAW_DISABLED;
+ msaa = VS::VIEWPORT_MSAA_DISABLED;
for (int i = 0; i < VS::VIEWPORT_RENDER_INFO_MAX; i++) {
render_info[i] = 0;
}
@@ -174,8 +175,6 @@ public:
void viewport_set_hide_scenario(RID p_viewport, bool p_hide);
void viewport_set_hide_canvas(RID p_viewport, bool p_hide);
void viewport_set_disable_environment(RID p_viewport, bool p_disable);
- void viewport_set_disable_3d(RID p_viewport, bool p_disable);
- void viewport_set_keep_3d_linear(RID p_viewport, bool p_keep_3d_linear);
void viewport_attach_camera(RID p_viewport, RID p_camera);
void viewport_set_scenario(RID p_viewport, RID p_scenario);
@@ -191,8 +190,6 @@ public:
void viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv);
void viewport_set_msaa(RID p_viewport, VS::ViewportMSAA p_msaa);
- void viewport_set_hdr(RID p_viewport, bool p_enabled);
- void viewport_set_usage(RID p_viewport, VS::ViewportUsage p_usage);
virtual int viewport_get_render_info(RID p_viewport, VS::ViewportRenderInfo p_info);
virtual void viewport_set_debug_draw(RID p_viewport, VS::ViewportDebugDraw p_draw);
diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h
index c2e7f659ab..135e4a8bd0 100644
--- a/servers/visual/visual_server_wrap_mt.h
+++ b/servers/visual/visual_server_wrap_mt.h
@@ -149,11 +149,14 @@ public:
/* MESH API */
+ virtual RID mesh_create_from_surfaces(const Vector<SurfaceData> &p_surfaces) {
+ return visual_server->mesh_create_from_surfaces(p_surfaces);
+ }
+
FUNCRID(mesh)
- FUNC10(mesh_add_surface, RID, uint32_t, PrimitiveType, const PoolVector<uint8_t> &, int, const PoolVector<uint8_t> &, int, const AABB &, const Vector<PoolVector<uint8_t> > &, const Vector<AABB> &)
+ FUNC2(mesh_add_surface, RID, const SurfaceData &)
- FUNC2(mesh_set_blend_shape_count, RID, int)
FUNC1RC(int, mesh_get_blend_shape_count, RID)
FUNC2(mesh_set_blend_shape_mode, RID, BlendShapeMode)
@@ -164,20 +167,8 @@ public:
FUNC3(mesh_surface_set_material, RID, int, RID)
FUNC2RC(RID, mesh_surface_get_material, RID, int)
- FUNC2RC(int, mesh_surface_get_array_len, RID, int)
- FUNC2RC(int, mesh_surface_get_array_index_len, RID, int)
-
- FUNC2RC(PoolVector<uint8_t>, mesh_surface_get_array, RID, int)
- FUNC2RC(PoolVector<uint8_t>, mesh_surface_get_index_array, RID, int)
-
- FUNC2RC(uint32_t, mesh_surface_get_format, RID, int)
- FUNC2RC(PrimitiveType, mesh_surface_get_primitive_type, RID, int)
-
- FUNC2RC(AABB, mesh_surface_get_aabb, RID, int)
- FUNC2RC(Vector<PoolVector<uint8_t> >, mesh_surface_get_blend_shapes, RID, int)
- FUNC2RC(Vector<AABB>, mesh_surface_get_skeleton_aabb, RID, int)
+ FUNC2RC(SurfaceData, mesh_get_surface, RID, int)
- FUNC2(mesh_remove_surface, RID, int)
FUNC1RC(int, mesh_get_surface_count, RID)
FUNC2(mesh_set_custom_aabb, RID, const AABB &)
@@ -390,15 +381,12 @@ public:
FUNC1(viewport_detach, RID)
FUNC2(viewport_set_update_mode, RID, ViewportUpdateMode)
- FUNC2(viewport_set_vflip, RID, bool)
FUNC1RC(RID, viewport_get_texture, RID)
FUNC2(viewport_set_hide_scenario, RID, bool)
FUNC2(viewport_set_hide_canvas, RID, bool)
FUNC2(viewport_set_disable_environment, RID, bool)
- FUNC2(viewport_set_disable_3d, RID, bool)
- FUNC2(viewport_set_keep_3d_linear, RID, bool)
FUNC2(viewport_attach_camera, RID, RID)
FUNC2(viewport_set_scenario, RID, RID)
@@ -413,8 +401,6 @@ public:
FUNC2(viewport_set_shadow_atlas_size, RID, int)
FUNC3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int)
FUNC2(viewport_set_msaa, RID, ViewportMSAA)
- FUNC2(viewport_set_hdr, RID, bool)
- FUNC2(viewport_set_usage, RID, ViewportUsage)
//this passes directly to avoid stalling, but it's pretty dangerous, so don't call after freeing a viewport
virtual int viewport_get_render_info(RID p_viewport, ViewportRenderInfo p_info) {
diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp
index 4f14a6b27d..60822f1746 100644
--- a/servers/visual_server.cpp
+++ b/servers/visual_server.cpp
@@ -360,24 +360,7 @@ Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_
// setting vertices means regenerating the AABB
Rect2 aabb;
- if (p_format & ARRAY_COMPRESS_VERTEX) {
-
- for (int i = 0; i < p_vertex_array_len; i++) {
-
- uint16_t vector[2] = { Math::make_half_float(src[i].x), Math::make_half_float(src[i].y) };
-
- copymem(&vw[p_offsets[ai] + i * p_stride], vector, sizeof(uint16_t) * 2);
-
- if (i == 0) {
-
- aabb = Rect2(src[i], SMALL_VEC2); //must have a bit of size
- } else {
-
- aabb.expand_to(src[i]);
- }
- }
-
- } else {
+ {
for (int i = 0; i < p_vertex_array_len; i++) {
float vector[2] = { src[i].x, src[i].y };
@@ -406,24 +389,7 @@ Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_
// setting vertices means regenerating the AABB
AABB aabb;
- if (p_format & ARRAY_COMPRESS_VERTEX) {
-
- for (int i = 0; i < p_vertex_array_len; i++) {
-
- uint16_t vector[4] = { Math::make_half_float(src[i].x), Math::make_half_float(src[i].y), Math::make_half_float(src[i].z), Math::make_half_float(1.0) };
-
- copymem(&vw[p_offsets[ai] + i * p_stride], vector, sizeof(uint16_t) * 4);
-
- if (i == 0) {
-
- aabb = AABB(src[i], SMALL_VEC3);
- } else {
-
- aabb.expand_to(src[i]);
- }
- }
-
- } else {
+ {
for (int i = 0; i < p_vertex_array_len; i++) {
float vector[3] = { src[i].x, src[i].y, src[i].z };
@@ -624,7 +590,7 @@ Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_
const real_t *src = read.ptr();
- if (p_format & ARRAY_COMPRESS_WEIGHTS) {
+ {
for (int i = 0; i < p_vertex_array_len; i++) {
@@ -635,17 +601,6 @@ Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_
copymem(&vw[p_offsets[ai] + i * p_stride], data, 2 * 4);
}
- } else {
-
- for (int i = 0; i < p_vertex_array_len; i++) {
-
- float data[VS::ARRAY_WEIGHTS_SIZE];
- for (int j = 0; j < VS::ARRAY_WEIGHTS_SIZE; j++) {
- data[j] = src[i * VS::ARRAY_WEIGHTS_SIZE + j];
- }
-
- copymem(&vw[p_offsets[ai] + i * p_stride], data, 4 * 4);
- }
}
} break;
@@ -661,30 +616,15 @@ Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_
const int *src = read.ptr();
- if (!(p_format & ARRAY_FLAG_USE_16_BIT_BONES)) {
-
- for (int i = 0; i < p_vertex_array_len; i++) {
+ for (int i = 0; i < p_vertex_array_len; i++) {
- uint8_t data[VS::ARRAY_WEIGHTS_SIZE];
- for (int j = 0; j < VS::ARRAY_WEIGHTS_SIZE; j++) {
- data[j] = CLAMP(src[i * VS::ARRAY_WEIGHTS_SIZE + j], 0, 255);
- max_bone = MAX(data[j], max_bone);
- }
-
- copymem(&vw[p_offsets[ai] + i * p_stride], data, 4);
+ uint16_t data[VS::ARRAY_WEIGHTS_SIZE];
+ for (int j = 0; j < VS::ARRAY_WEIGHTS_SIZE; j++) {
+ data[j] = src[i * VS::ARRAY_WEIGHTS_SIZE + j];
+ max_bone = MAX(data[j], max_bone);
}
- } else {
- for (int i = 0; i < p_vertex_array_len; i++) {
-
- uint16_t data[VS::ARRAY_WEIGHTS_SIZE];
- for (int j = 0; j < VS::ARRAY_WEIGHTS_SIZE; j++) {
- data[j] = src[i * VS::ARRAY_WEIGHTS_SIZE + j];
- max_bone = MAX(data[j], max_bone);
- }
-
- copymem(&vw[p_offsets[ai] + i * p_stride], data, 2 * 4);
- }
+ copymem(&vw[p_offsets[ai] + i * p_stride], data, 2 * 4);
}
} break;
@@ -814,9 +754,7 @@ uint32_t VisualServer::mesh_surface_make_offsets_from_format(uint32_t p_format,
elem_size = 3;
}
- if (p_format & ARRAY_COMPRESS_VERTEX) {
- elem_size *= sizeof(int16_t);
- } else {
+ {
elem_size *= sizeof(float);
}
@@ -870,20 +808,12 @@ uint32_t VisualServer::mesh_surface_make_offsets_from_format(uint32_t p_format,
} break;
case VS::ARRAY_WEIGHTS: {
- if (p_format & ARRAY_COMPRESS_WEIGHTS) {
- elem_size = sizeof(uint16_t) * 4;
- } else {
- elem_size = sizeof(float) * 4;
- }
+ elem_size = sizeof(uint16_t) * 4;
} break;
case VS::ARRAY_BONES: {
- if (p_format & ARRAY_FLAG_USE_16_BIT_BONES) {
- elem_size = sizeof(uint16_t) * 4;
- } else {
- elem_size = sizeof(uint32_t);
- }
+ elem_size = sizeof(uint16_t) * 4;
} break;
case VS::ARRAY_INDEX: {
@@ -914,10 +844,10 @@ uint32_t VisualServer::mesh_surface_make_offsets_from_format(uint32_t p_format,
return total_elem_size;
}
-void VisualServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes, uint32_t p_compress_format) {
+Error VisualServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surface_data, PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes, const Dictionary &p_lods, uint32_t p_compress_format) {
- ERR_FAIL_INDEX(p_primitive, VS::PRIMITIVE_MAX);
- ERR_FAIL_COND(p_arrays.size() != VS::ARRAY_MAX);
+ ERR_FAIL_INDEX_V(p_primitive, VS::PRIMITIVE_MAX, ERR_INVALID_PARAMETER);
+ ERR_FAIL_COND_V(p_arrays.size() != VS::ARRAY_MAX, ERR_INVALID_PARAMETER);
uint32_t format = 0;
@@ -948,14 +878,14 @@ void VisualServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_prim
}
array_len = PoolVector3Array(p_arrays[i]).size();
- ERR_FAIL_COND(array_len == 0);
+ ERR_FAIL_COND_V(array_len == 0, ERR_INVALID_DATA);
} else if (i == VS::ARRAY_INDEX) {
index_array_len = PoolIntArray(p_arrays[i]).size();
}
}
- ERR_FAIL_COND((format & VS::ARRAY_FORMAT_VERTEX) == 0); // mandatory
+ ERR_FAIL_COND_V((format & VS::ARRAY_FORMAT_VERTEX) == 0, ERR_INVALID_PARAMETER); // mandatory
if (p_blend_shapes.size()) {
//validate format for morphs
@@ -969,7 +899,7 @@ void VisualServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_prim
bsformat |= (1 << j);
}
- ERR_FAIL_COND((bsformat) != (format & (VS::ARRAY_FORMAT_INDEX - 1)));
+ ERR_FAIL_COND_V((bsformat) != (format & (VS::ARRAY_FORMAT_INDEX - 1)), ERR_INVALID_PARAMETER);
}
}
@@ -1001,9 +931,7 @@ void VisualServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_prim
elem_size = (p_compress_format & ARRAY_FLAG_USE_2D_VERTICES) ? 2 : 3;
}
- if (p_compress_format & ARRAY_COMPRESS_VERTEX) {
- elem_size *= sizeof(int16_t);
- } else {
+ {
elem_size *= sizeof(float);
}
@@ -1058,33 +986,12 @@ void VisualServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_prim
} break;
case VS::ARRAY_WEIGHTS: {
- if (p_compress_format & ARRAY_COMPRESS_WEIGHTS) {
- elem_size = sizeof(uint16_t) * 4;
- } else {
- elem_size = sizeof(float) * 4;
- }
+ elem_size = sizeof(uint16_t) * 4;
} break;
case VS::ARRAY_BONES: {
- PoolVector<int> bones = p_arrays[VS::ARRAY_BONES];
- int max_bone = 0;
-
- {
- int bc = bones.size();
- PoolVector<int>::Read r = bones.read();
- for (int j = 0; j < bc; j++) {
- max_bone = MAX(r[j], max_bone);
- }
- }
-
- if (max_bone > 255) {
- p_compress_format |= ARRAY_FLAG_USE_16_BIT_BONES;
- elem_size = sizeof(uint16_t) * 4;
- } else {
- p_compress_format &= ~ARRAY_FLAG_USE_16_BIT_BONES;
- elem_size = sizeof(uint32_t);
- }
+ elem_size = sizeof(uint16_t) * 4;
} break;
case VS::ARRAY_INDEX: {
@@ -1105,7 +1012,7 @@ void VisualServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_prim
continue;
}
default: {
- ERR_FAIL();
+ ERR_FAIL_V(ERR_BUG);
}
}
@@ -1130,7 +1037,7 @@ void VisualServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_prim
Vector<AABB> bone_aabb;
Error err = _surface_set_data(p_arrays, format, offsets, total_elem_size, vertex_array, array_len, index_array, index_array_len, aabb, bone_aabb);
- ERR_FAIL_COND_MSG(err, "Invalid array format for surface.");
+ ERR_FAIL_COND_V_MSG(err != OK, ERR_INVALID_DATA, "Invalid array format for surface.");
Vector<PoolVector<uint8_t> > blend_shape_data;
@@ -1143,12 +1050,74 @@ void VisualServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_prim
AABB laabb;
Error err2 = _surface_set_data(p_blend_shapes[i], format & ~ARRAY_FORMAT_INDEX, offsets, total_elem_size, vertex_array_shape, array_len, noindex, 0, laabb, bone_aabb);
aabb.merge_with(laabb);
- ERR_FAIL_COND_MSG(err2 != OK, "Invalid blend shape array format for surface.");
+ ERR_FAIL_COND_V_MSG(err2 != OK, ERR_INVALID_DATA, "Invalid blend shape array format for surface.");
blend_shape_data.push_back(vertex_array_shape);
}
+ Vector<SurfaceData::LOD> lods;
+ if (index_array_len) {
+
+ List<Variant> keys;
+ p_lods.get_key_list(&keys);
+ for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
+ float distance = E->get();
+ ERR_CONTINUE(distance <= 0.0);
+ PoolVector<int> indices = p_lods[E->get()];
+ ERR_CONTINUE(indices.size() == 0);
+ uint32_t index_count = indices.size();
+ ERR_CONTINUE(index_count >= (uint32_t)index_array_len); //should be smaller..
+
+ PoolVector<int>::Read r = indices.read();
+
+ PoolVector<uint8_t> data;
+ if (array_len <= 65536) {
+ //16 bits indices
+ data.resize(indices.size() * 2);
+ PoolVector<uint8_t>::Write w = data.write();
+ uint16_t *index_ptr = (uint16_t *)w.ptr();
+ for (uint32_t i = 0; i < index_count; i++) {
+ index_ptr[i] = r[i];
+ }
+ } else {
+ //32 bits indices
+ data.resize(indices.size() * 4);
+ PoolVector<uint8_t>::Write w = data.write();
+ uint32_t *index_ptr = (uint32_t *)w.ptr();
+ for (uint32_t i = 0; i < index_count; i++) {
+ index_ptr[i] = r[i];
+ }
+ }
+
+ SurfaceData::LOD lod;
+ lod.edge_length = distance;
+ lod.index_data = data;
+ lods.push_back(lod);
+ }
+ }
+
+ SurfaceData &surface_data = *r_surface_data;
+ surface_data.format = format;
+ surface_data.primitive = p_primitive;
+ surface_data.aabb = aabb;
+ surface_data.vertex_data = vertex_array;
+ surface_data.vertex_count = array_len;
+ surface_data.index_data = index_array;
+ surface_data.index_count = index_array_len;
+ surface_data.blend_shapes = blend_shape_data;
+ surface_data.bone_aabbs = bone_aabb;
+ surface_data.lods = lods;
- mesh_add_surface(p_mesh, format, p_primitive, vertex_array, array_len, index_array, index_array_len, aabb, blend_shape_data, bone_aabb);
+ return OK;
+}
+
+void VisualServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes, const Dictionary &p_lods, uint32_t p_compress_format) {
+
+ SurfaceData sd;
+ Error err = mesh_create_surface_data_from_arrays(&sd, p_primitive, p_arrays, p_blend_shapes, p_lods, p_compress_format);
+ if (err != OK) {
+ return;
+ }
+ mesh_add_surface(p_mesh, sd);
}
Array VisualServer::_get_array_from_surface(uint32_t p_format, PoolVector<uint8_t> p_vertex_data, int p_vertex_len, PoolVector<uint8_t> p_index_data, int p_index_len) const {
@@ -1176,9 +1145,7 @@ Array VisualServer::_get_array_from_surface(uint32_t p_format, PoolVector<uint8_
elem_size = 3;
}
- if (p_format & ARRAY_COMPRESS_VERTEX) {
- elem_size *= sizeof(int16_t);
- } else {
+ {
elem_size *= sizeof(float);
}
@@ -1232,20 +1199,12 @@ Array VisualServer::_get_array_from_surface(uint32_t p_format, PoolVector<uint8_
} break;
case VS::ARRAY_WEIGHTS: {
- if (p_format & ARRAY_COMPRESS_WEIGHTS) {
- elem_size = sizeof(uint16_t) * 4;
- } else {
- elem_size = sizeof(float) * 4;
- }
+ elem_size = sizeof(uint16_t) * 4;
} break;
case VS::ARRAY_BONES: {
- if (p_format & ARRAY_FLAG_USE_16_BIT_BONES) {
- elem_size = sizeof(uint16_t) * 4;
- } else {
- elem_size = sizeof(uint32_t);
- }
+ elem_size = sizeof(uint16_t) * 4;
} break;
case VS::ARRAY_INDEX: {
@@ -1293,16 +1252,7 @@ Array VisualServer::_get_array_from_surface(uint32_t p_format, PoolVector<uint8_
PoolVector<Vector2> arr_2d;
arr_2d.resize(p_vertex_len);
- if (p_format & ARRAY_COMPRESS_VERTEX) {
-
- PoolVector<Vector2>::Write w = arr_2d.write();
-
- for (int j = 0; j < p_vertex_len; j++) {
-
- const uint16_t *v = (const uint16_t *)&r[j * total_elem_size + offsets[i]];
- w[j] = Vector2(Math::halfptr_to_float(&v[0]), Math::halfptr_to_float(&v[1]));
- }
- } else {
+ {
PoolVector<Vector2>::Write w = arr_2d.write();
@@ -1319,16 +1269,7 @@ Array VisualServer::_get_array_from_surface(uint32_t p_format, PoolVector<uint8_
PoolVector<Vector3> arr_3d;
arr_3d.resize(p_vertex_len);
- if (p_format & ARRAY_COMPRESS_VERTEX) {
-
- PoolVector<Vector3>::Write w = arr_3d.write();
-
- for (int j = 0; j < p_vertex_len; j++) {
-
- const uint16_t *v = (const uint16_t *)&r[j * total_elem_size + offsets[i]];
- w[j] = Vector3(Math::halfptr_to_float(&v[0]), Math::halfptr_to_float(&v[1]), Math::halfptr_to_float(&v[2]));
- }
- } else {
+ {
PoolVector<Vector3>::Write w = arr_3d.write();
@@ -1484,7 +1425,7 @@ Array VisualServer::_get_array_from_surface(uint32_t p_format, PoolVector<uint8_
PoolVector<float> arr;
arr.resize(p_vertex_len * 4);
- if (p_format & ARRAY_COMPRESS_WEIGHTS) {
+ {
PoolVector<float>::Write w = arr.write();
for (int j = 0; j < p_vertex_len; j++) {
@@ -1494,16 +1435,6 @@ Array VisualServer::_get_array_from_surface(uint32_t p_format, PoolVector<uint8_
w[j * 4 + k] = float(v[k] / 65535.0);
}
}
- } else {
-
- PoolVector<float>::Write w = arr.write();
-
- for (int j = 0; j < p_vertex_len; j++) {
- const float *v = (const float *)&r[j * total_elem_size + offsets[i]];
- for (int k = 0; k < 4; k++) {
- w[j * 4 + k] = v[k];
- }
- }
}
ret[i] = arr;
@@ -1513,26 +1444,14 @@ Array VisualServer::_get_array_from_surface(uint32_t p_format, PoolVector<uint8_
PoolVector<int> arr;
arr.resize(p_vertex_len * 4);
- if (p_format & ARRAY_FLAG_USE_16_BIT_BONES) {
-
- PoolVector<int>::Write w = arr.write();
- for (int j = 0; j < p_vertex_len; j++) {
-
- const uint16_t *v = (const uint16_t *)&r[j * total_elem_size + offsets[i]];
- for (int k = 0; k < 4; k++) {
- w[j * 4 + k] = v[k];
- }
- }
- } else {
+ PoolVector<int>::Write w = arr.write();
- PoolVector<int>::Write w = arr.write();
+ for (int j = 0; j < p_vertex_len; j++) {
- for (int j = 0; j < p_vertex_len; j++) {
- const uint8_t *v = (const uint8_t *)&r[j * total_elem_size + offsets[i]];
- for (int k = 0; k < 4; k++) {
- w[j * 4 + k] = v[k];
- }
+ const uint16_t *v = (const uint16_t *)&r[j * total_elem_size + offsets[i]];
+ for (int k = 0; k < 4; k++) {
+ w[j * 4 + k] = v[k];
}
}
@@ -1577,28 +1496,59 @@ Array VisualServer::_get_array_from_surface(uint32_t p_format, PoolVector<uint8_
Array VisualServer::mesh_surface_get_arrays(RID p_mesh, int p_surface) const {
- PoolVector<uint8_t> vertex_data = mesh_surface_get_array(p_mesh, p_surface);
- ERR_FAIL_COND_V(vertex_data.size() == 0, Array());
- int vertex_len = mesh_surface_get_array_len(p_mesh, p_surface);
+ SurfaceData sd = mesh_get_surface(p_mesh, p_surface);
+ return mesh_create_arrays_from_surface_data(sd);
+}
- PoolVector<uint8_t> index_data = mesh_surface_get_index_array(p_mesh, p_surface);
- int index_len = mesh_surface_get_array_index_len(p_mesh, p_surface);
+Dictionary VisualServer::mesh_surface_get_lods(RID p_mesh, int p_surface) const {
- uint32_t format = mesh_surface_get_format(p_mesh, p_surface);
+ SurfaceData sd = mesh_get_surface(p_mesh, p_surface);
+ ERR_FAIL_COND_V(sd.vertex_count == 0, Dictionary());
- return _get_array_from_surface(format, vertex_data, vertex_len, index_data, index_len);
+ Dictionary ret;
+
+ for (int i = 0; i < sd.lods.size(); i++) {
+ PoolVector<int> lods;
+ if (sd.vertex_count <= 65536) {
+ uint32_t lc = sd.lods[i].index_data.size() / 2;
+ lods.resize(lc);
+ PoolVector<uint8_t>::Read r = sd.lods[i].index_data.read();
+ const uint16_t *rptr = (const uint16_t *)r.ptr();
+ PoolVector<int>::Write w = lods.write();
+ for (uint32_t j = 0; j < lc; j++) {
+ w[j] = rptr[i];
+ }
+ } else {
+ uint32_t lc = sd.lods[i].index_data.size() / 4;
+ lods.resize(lc);
+ PoolVector<uint8_t>::Read r = sd.lods[i].index_data.read();
+ const uint32_t *rptr = (const uint32_t *)r.ptr();
+ PoolVector<int>::Write w = lods.write();
+ for (uint32_t j = 0; j < lc; j++) {
+ w[j] = rptr[i];
+ }
+ }
+
+ ret[sd.lods[i].edge_length] = lods;
+ }
+
+ return ret;
}
Array VisualServer::mesh_surface_get_blend_shape_arrays(RID p_mesh, int p_surface) const {
- Vector<PoolVector<uint8_t> > blend_shape_data = mesh_surface_get_blend_shapes(p_mesh, p_surface);
+ SurfaceData sd = mesh_get_surface(p_mesh, p_surface);
+ ERR_FAIL_COND_V(sd.vertex_count == 0, Array());
+
+ Vector<PoolVector<uint8_t> > blend_shape_data = sd.blend_shapes;
+
if (blend_shape_data.size() > 0) {
- int vertex_len = mesh_surface_get_array_len(p_mesh, p_surface);
+ int vertex_len = sd.vertex_count;
- PoolVector<uint8_t> index_data = mesh_surface_get_index_array(p_mesh, p_surface);
- int index_len = mesh_surface_get_array_index_len(p_mesh, p_surface);
+ PoolVector<uint8_t> index_data = sd.index_data;
+ int index_len = sd.index_count;
- uint32_t format = mesh_surface_get_format(p_mesh, p_surface);
+ uint32_t format = sd.format;
Array blend_shape_array;
blend_shape_array.resize(blend_shape_data.size());
@@ -1612,6 +1562,21 @@ Array VisualServer::mesh_surface_get_blend_shape_arrays(RID p_mesh, int p_surfac
}
}
+Array VisualServer::mesh_create_arrays_from_surface_data(const SurfaceData &p_data) const {
+
+ PoolVector<uint8_t> vertex_data = p_data.vertex_data;
+
+ ERR_FAIL_COND_V(vertex_data.size() == 0, Array());
+ int vertex_len = p_data.vertex_count;
+
+ PoolVector<uint8_t> index_data = p_data.index_data;
+ int index_len = p_data.index_count;
+
+ uint32_t format = p_data.format;
+
+ return _get_array_from_surface(format, vertex_data, vertex_len, index_data, index_len);
+}
+#if 0
Array VisualServer::_mesh_surface_get_skeleton_aabb_bind(RID p_mesh, int p_surface) const {
Vector<AABB> vec = VS::get_singleton()->mesh_surface_get_skeleton_aabb(p_mesh, p_surface);
@@ -1621,7 +1586,7 @@ Array VisualServer::_mesh_surface_get_skeleton_aabb_bind(RID p_mesh, int p_surfa
}
return arr;
}
-
+#endif
void VisualServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("force_sync"), &VisualServer::sync);
@@ -1664,24 +1629,14 @@ void VisualServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("mesh_surface_get_format_offset", "format", "vertex_len", "index_len", "array_index"), &VisualServer::mesh_surface_get_format_offset);
ClassDB::bind_method(D_METHOD("mesh_surface_get_format_stride", "format", "vertex_len", "index_len"), &VisualServer::mesh_surface_get_format_stride);
ClassDB::bind_method(D_METHOD("mesh_add_surface_from_arrays", "mesh", "primitive", "arrays", "blend_shapes", "compress_format"), &VisualServer::mesh_add_surface_from_arrays, DEFVAL(Array()), DEFVAL(ARRAY_COMPRESS_DEFAULT));
- ClassDB::bind_method(D_METHOD("mesh_set_blend_shape_count", "mesh", "amount"), &VisualServer::mesh_set_blend_shape_count);
ClassDB::bind_method(D_METHOD("mesh_get_blend_shape_count", "mesh"), &VisualServer::mesh_get_blend_shape_count);
ClassDB::bind_method(D_METHOD("mesh_set_blend_shape_mode", "mesh", "mode"), &VisualServer::mesh_set_blend_shape_mode);
ClassDB::bind_method(D_METHOD("mesh_get_blend_shape_mode", "mesh"), &VisualServer::mesh_get_blend_shape_mode);
ClassDB::bind_method(D_METHOD("mesh_surface_update_region", "mesh", "surface", "offset", "data"), &VisualServer::mesh_surface_update_region);
ClassDB::bind_method(D_METHOD("mesh_surface_set_material", "mesh", "surface", "material"), &VisualServer::mesh_surface_set_material);
ClassDB::bind_method(D_METHOD("mesh_surface_get_material", "mesh", "surface"), &VisualServer::mesh_surface_get_material);
- ClassDB::bind_method(D_METHOD("mesh_surface_get_array_len", "mesh", "surface"), &VisualServer::mesh_surface_get_array_len);
- ClassDB::bind_method(D_METHOD("mesh_surface_get_array_index_len", "mesh", "surface"), &VisualServer::mesh_surface_get_array_index_len);
- ClassDB::bind_method(D_METHOD("mesh_surface_get_array", "mesh", "surface"), &VisualServer::mesh_surface_get_array);
- ClassDB::bind_method(D_METHOD("mesh_surface_get_index_array", "mesh", "surface"), &VisualServer::mesh_surface_get_index_array);
ClassDB::bind_method(D_METHOD("mesh_surface_get_arrays", "mesh", "surface"), &VisualServer::mesh_surface_get_arrays);
ClassDB::bind_method(D_METHOD("mesh_surface_get_blend_shape_arrays", "mesh", "surface"), &VisualServer::mesh_surface_get_blend_shape_arrays);
- ClassDB::bind_method(D_METHOD("mesh_surface_get_format", "mesh", "surface"), &VisualServer::mesh_surface_get_format);
- ClassDB::bind_method(D_METHOD("mesh_surface_get_primitive_type", "mesh", "surface"), &VisualServer::mesh_surface_get_primitive_type);
- ClassDB::bind_method(D_METHOD("mesh_surface_get_aabb", "mesh", "surface"), &VisualServer::mesh_surface_get_aabb);
- ClassDB::bind_method(D_METHOD("mesh_surface_get_skeleton_aabb", "mesh", "surface"), &VisualServer::_mesh_surface_get_skeleton_aabb_bind);
- ClassDB::bind_method(D_METHOD("mesh_remove_surface", "mesh", "index"), &VisualServer::mesh_remove_surface);
ClassDB::bind_method(D_METHOD("mesh_get_surface_count", "mesh"), &VisualServer::mesh_get_surface_count);
ClassDB::bind_method(D_METHOD("mesh_set_custom_aabb", "mesh", "aabb"), &VisualServer::mesh_set_custom_aabb);
ClassDB::bind_method(D_METHOD("mesh_get_custom_aabb", "mesh"), &VisualServer::mesh_get_custom_aabb);
@@ -1842,13 +1797,11 @@ void VisualServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("viewport_set_render_direct_to_screen", "viewport", "enabled"), &VisualServer::viewport_set_render_direct_to_screen);
ClassDB::bind_method(D_METHOD("viewport_detach", "viewport"), &VisualServer::viewport_detach);
ClassDB::bind_method(D_METHOD("viewport_set_update_mode", "viewport", "update_mode"), &VisualServer::viewport_set_update_mode);
- ClassDB::bind_method(D_METHOD("viewport_set_vflip", "viewport", "enabled"), &VisualServer::viewport_set_vflip);
ClassDB::bind_method(D_METHOD("viewport_set_clear_mode", "viewport", "clear_mode"), &VisualServer::viewport_set_clear_mode);
ClassDB::bind_method(D_METHOD("viewport_get_texture", "viewport"), &VisualServer::viewport_get_texture);
ClassDB::bind_method(D_METHOD("viewport_set_hide_scenario", "viewport", "hidden"), &VisualServer::viewport_set_hide_scenario);
ClassDB::bind_method(D_METHOD("viewport_set_hide_canvas", "viewport", "hidden"), &VisualServer::viewport_set_hide_canvas);
ClassDB::bind_method(D_METHOD("viewport_set_disable_environment", "viewport", "disabled"), &VisualServer::viewport_set_disable_environment);
- ClassDB::bind_method(D_METHOD("viewport_set_disable_3d", "viewport", "disabled"), &VisualServer::viewport_set_disable_3d);
ClassDB::bind_method(D_METHOD("viewport_attach_camera", "viewport", "camera"), &VisualServer::viewport_attach_camera);
ClassDB::bind_method(D_METHOD("viewport_set_scenario", "viewport", "scenario"), &VisualServer::viewport_set_scenario);
ClassDB::bind_method(D_METHOD("viewport_attach_canvas", "viewport", "canvas"), &VisualServer::viewport_attach_canvas);
@@ -1860,8 +1813,6 @@ void VisualServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("viewport_set_shadow_atlas_size", "viewport", "size"), &VisualServer::viewport_set_shadow_atlas_size);
ClassDB::bind_method(D_METHOD("viewport_set_shadow_atlas_quadrant_subdivision", "viewport", "quadrant", "subdivision"), &VisualServer::viewport_set_shadow_atlas_quadrant_subdivision);
ClassDB::bind_method(D_METHOD("viewport_set_msaa", "viewport", "msaa"), &VisualServer::viewport_set_msaa);
- ClassDB::bind_method(D_METHOD("viewport_set_hdr", "viewport", "enabled"), &VisualServer::viewport_set_hdr);
- ClassDB::bind_method(D_METHOD("viewport_set_usage", "viewport", "usage"), &VisualServer::viewport_set_usage);
ClassDB::bind_method(D_METHOD("viewport_get_render_info", "viewport", "info"), &VisualServer::viewport_get_render_info);
ClassDB::bind_method(D_METHOD("viewport_set_debug_draw", "viewport", "draw"), &VisualServer::viewport_set_debug_draw);
@@ -2068,22 +2019,21 @@ void VisualServer::_bind_methods() {
BIND_ENUM_CONSTANT(ARRAY_FORMAT_BONES);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_WEIGHTS);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_INDEX);
- BIND_ENUM_CONSTANT(ARRAY_COMPRESS_VERTEX);
+
BIND_ENUM_CONSTANT(ARRAY_COMPRESS_NORMAL);
BIND_ENUM_CONSTANT(ARRAY_COMPRESS_TANGENT);
BIND_ENUM_CONSTANT(ARRAY_COMPRESS_COLOR);
BIND_ENUM_CONSTANT(ARRAY_COMPRESS_TEX_UV);
BIND_ENUM_CONSTANT(ARRAY_COMPRESS_TEX_UV2);
- BIND_ENUM_CONSTANT(ARRAY_COMPRESS_BONES);
- BIND_ENUM_CONSTANT(ARRAY_COMPRESS_WEIGHTS);
BIND_ENUM_CONSTANT(ARRAY_COMPRESS_INDEX);
BIND_ENUM_CONSTANT(ARRAY_FLAG_USE_2D_VERTICES);
- BIND_ENUM_CONSTANT(ARRAY_FLAG_USE_16_BIT_BONES);
BIND_ENUM_CONSTANT(ARRAY_COMPRESS_DEFAULT);
BIND_ENUM_CONSTANT(PRIMITIVE_POINTS);
BIND_ENUM_CONSTANT(PRIMITIVE_LINES);
+ BIND_ENUM_CONSTANT(PRIMITIVE_LINE_STRIP);
BIND_ENUM_CONSTANT(PRIMITIVE_TRIANGLES);
+ BIND_ENUM_CONSTANT(PRIMITIVE_TRIANGLE_STRIP);
BIND_ENUM_CONSTANT(PRIMITIVE_MAX);
BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_NORMALIZED);
@@ -2137,11 +2087,6 @@ void VisualServer::_bind_methods() {
BIND_ENUM_CONSTANT(VIEWPORT_MSAA_EXT_2X);
BIND_ENUM_CONSTANT(VIEWPORT_MSAA_EXT_4X);
- BIND_ENUM_CONSTANT(VIEWPORT_USAGE_2D);
- BIND_ENUM_CONSTANT(VIEWPORT_USAGE_2D_NO_SAMPLING);
- BIND_ENUM_CONSTANT(VIEWPORT_USAGE_3D);
- BIND_ENUM_CONSTANT(VIEWPORT_USAGE_3D_NO_EFFECTS);
-
BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME);
BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_VERTICES_IN_FRAME);
BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_MATERIAL_CHANGES_IN_FRAME);
diff --git a/servers/visual_server.h b/servers/visual_server.h
index 957b8fe48f..e2c27675fb 100644
--- a/servers/visual_server.h
+++ b/servers/visual_server.h
@@ -229,41 +229,68 @@ public:
ARRAY_FORMAT_INDEX = 1 << ARRAY_INDEX,
ARRAY_COMPRESS_BASE = (ARRAY_INDEX + 1),
- ARRAY_COMPRESS_VERTEX = 1 << (ARRAY_VERTEX + ARRAY_COMPRESS_BASE), // mandatory
ARRAY_COMPRESS_NORMAL = 1 << (ARRAY_NORMAL + ARRAY_COMPRESS_BASE),
ARRAY_COMPRESS_TANGENT = 1 << (ARRAY_TANGENT + ARRAY_COMPRESS_BASE),
ARRAY_COMPRESS_COLOR = 1 << (ARRAY_COLOR + ARRAY_COMPRESS_BASE),
ARRAY_COMPRESS_TEX_UV = 1 << (ARRAY_TEX_UV + ARRAY_COMPRESS_BASE),
ARRAY_COMPRESS_TEX_UV2 = 1 << (ARRAY_TEX_UV2 + ARRAY_COMPRESS_BASE),
- ARRAY_COMPRESS_BONES = 1 << (ARRAY_BONES + ARRAY_COMPRESS_BASE),
- ARRAY_COMPRESS_WEIGHTS = 1 << (ARRAY_WEIGHTS + ARRAY_COMPRESS_BASE),
ARRAY_COMPRESS_INDEX = 1 << (ARRAY_INDEX + ARRAY_COMPRESS_BASE),
ARRAY_FLAG_USE_2D_VERTICES = ARRAY_COMPRESS_INDEX << 1,
- ARRAY_FLAG_USE_16_BIT_BONES = ARRAY_COMPRESS_INDEX << 2,
ARRAY_FLAG_USE_DYNAMIC_UPDATE = ARRAY_COMPRESS_INDEX << 3,
- ARRAY_COMPRESS_DEFAULT = ARRAY_COMPRESS_NORMAL | ARRAY_COMPRESS_TANGENT | ARRAY_COMPRESS_COLOR | ARRAY_COMPRESS_TEX_UV | ARRAY_COMPRESS_TEX_UV2 | ARRAY_COMPRESS_WEIGHTS
+ ARRAY_COMPRESS_DEFAULT = ARRAY_COMPRESS_NORMAL | ARRAY_COMPRESS_TANGENT | ARRAY_COMPRESS_COLOR | ARRAY_COMPRESS_TEX_UV | ARRAY_COMPRESS_TEX_UV2
};
enum PrimitiveType {
PRIMITIVE_POINTS,
PRIMITIVE_LINES,
+ PRIMITIVE_LINE_STRIP,
PRIMITIVE_TRIANGLES,
+ PRIMITIVE_TRIANGLE_STRIP,
PRIMITIVE_MAX,
};
+ struct SurfaceData {
+
+ PrimitiveType primitive = PRIMITIVE_MAX;
+
+ uint32_t format = 0;
+ PoolVector<uint8_t> vertex_data;
+ uint32_t vertex_count = 0;
+ PoolVector<uint8_t> index_data;
+ uint32_t index_count = 0;
+
+ AABB aabb;
+ struct LOD {
+ float edge_length;
+ PoolVector<uint8_t> index_data;
+ };
+ Vector<LOD> lods;
+ Vector<AABB> bone_aabbs;
+
+ Vector<PoolVector<uint8_t> > blend_shapes;
+
+ RID material;
+ };
+
+ virtual RID mesh_create_from_surfaces(const Vector<SurfaceData> &p_surfaces) = 0;
virtual RID mesh_create() = 0;
virtual uint32_t mesh_surface_get_format_offset(uint32_t p_format, int p_vertex_len, int p_index_len, int p_array_index) const;
virtual uint32_t mesh_surface_get_format_stride(uint32_t p_format, int p_vertex_len, int p_index_len) const;
/// Returns stride
virtual uint32_t mesh_surface_make_offsets_from_format(uint32_t p_format, int p_vertex_len, int p_index_len, uint32_t *r_offsets) const;
- virtual void mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), uint32_t p_compress_format = ARRAY_COMPRESS_DEFAULT);
- virtual void mesh_add_surface(RID p_mesh, uint32_t p_format, PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<PoolVector<uint8_t> > &p_blend_shapes = Vector<PoolVector<uint8_t> >(), const Vector<AABB> &p_bone_aabbs = Vector<AABB>()) = 0;
+ virtual Error mesh_create_surface_data_from_arrays(SurfaceData *r_surface_data, PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), const Dictionary &p_lods = Dictionary(), uint32_t p_compress_format = ARRAY_COMPRESS_DEFAULT);
+ Array mesh_create_arrays_from_surface_data(const SurfaceData &p_data) const;
+ Array mesh_surface_get_arrays(RID p_mesh, int p_surface) const;
+ Array mesh_surface_get_blend_shape_arrays(RID p_mesh, int p_surface) const;
+ Dictionary mesh_surface_get_lods(RID p_mesh, int p_surface) const;
+
+ virtual void mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), const Dictionary &p_lods = Dictionary(), uint32_t p_compress_format = ARRAY_COMPRESS_DEFAULT);
+ virtual void mesh_add_surface(RID p_mesh, const SurfaceData &p_surface) = 0;
- virtual void mesh_set_blend_shape_count(RID p_mesh, int p_amount) = 0;
virtual int mesh_get_blend_shape_count(RID p_mesh) const = 0;
enum BlendShapeMode {
@@ -279,24 +306,8 @@ public:
virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) = 0;
virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const = 0;
- virtual int mesh_surface_get_array_len(RID p_mesh, int p_surface) const = 0;
- virtual int mesh_surface_get_array_index_len(RID p_mesh, int p_surface) const = 0;
+ virtual SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const = 0;
- virtual PoolVector<uint8_t> mesh_surface_get_array(RID p_mesh, int p_surface) const = 0;
- virtual PoolVector<uint8_t> mesh_surface_get_index_array(RID p_mesh, int p_surface) const = 0;
-
- virtual Array mesh_surface_get_arrays(RID p_mesh, int p_surface) const;
- virtual Array mesh_surface_get_blend_shape_arrays(RID p_mesh, int p_surface) const;
-
- virtual uint32_t mesh_surface_get_format(RID p_mesh, int p_surface) const = 0;
- virtual PrimitiveType mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const = 0;
-
- virtual AABB mesh_surface_get_aabb(RID p_mesh, int p_surface) const = 0;
- virtual Vector<PoolVector<uint8_t> > mesh_surface_get_blend_shapes(RID p_mesh, int p_surface) const = 0;
- virtual Vector<AABB> mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const = 0;
- Array _mesh_surface_get_skeleton_aabb_bind(RID p_mesh, int p_surface) const;
-
- virtual void mesh_remove_surface(RID p_mesh, int p_index) = 0;
virtual int mesh_get_surface_count(RID p_mesh) const = 0;
virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) = 0;
@@ -604,7 +615,6 @@ public:
};
virtual void viewport_set_update_mode(RID p_viewport, ViewportUpdateMode p_mode) = 0;
- virtual void viewport_set_vflip(RID p_viewport, bool p_enable) = 0;
enum ViewportClearMode {
@@ -620,8 +630,6 @@ public:
virtual void viewport_set_hide_scenario(RID p_viewport, bool p_hide) = 0;
virtual void viewport_set_hide_canvas(RID p_viewport, bool p_hide) = 0;
virtual void viewport_set_disable_environment(RID p_viewport, bool p_disable) = 0;
- virtual void viewport_set_disable_3d(RID p_viewport, bool p_disable) = 0;
- virtual void viewport_set_keep_3d_linear(RID p_viewport, bool p_disable) = 0;
virtual void viewport_attach_camera(RID p_viewport, RID p_camera) = 0;
virtual void viewport_set_scenario(RID p_viewport, RID p_scenario) = 0;
@@ -648,16 +656,6 @@ public:
virtual void viewport_set_msaa(RID p_viewport, ViewportMSAA p_msaa) = 0;
- enum ViewportUsage {
- VIEWPORT_USAGE_2D,
- VIEWPORT_USAGE_2D_NO_SAMPLING,
- VIEWPORT_USAGE_3D,
- VIEWPORT_USAGE_3D_NO_EFFECTS,
- };
-
- virtual void viewport_set_hdr(RID p_viewport, bool p_enabled) = 0;
- virtual void viewport_set_usage(RID p_viewport, ViewportUsage p_usage) = 0;
-
enum ViewportRenderInfo {
VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME,
@@ -1075,7 +1073,6 @@ VARIANT_ENUM_CAST(VisualServer::LightParam);
VARIANT_ENUM_CAST(VisualServer::ViewportUpdateMode);
VARIANT_ENUM_CAST(VisualServer::ViewportClearMode);
VARIANT_ENUM_CAST(VisualServer::ViewportMSAA);
-VARIANT_ENUM_CAST(VisualServer::ViewportUsage);
VARIANT_ENUM_CAST(VisualServer::ViewportRenderInfo);
VARIANT_ENUM_CAST(VisualServer::ViewportDebugDraw);
VARIANT_ENUM_CAST(VisualServer::ScenarioDebugMode);