Base 3D engine done, still untested, though.

This commit is contained in:
Juan Linietsky 2019-08-18 19:40:52 -03:00
parent 7fa9785170
commit 449df8f688
50 changed files with 4913 additions and 1053 deletions

View file

@ -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

View file

@ -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 ****/

View file

@ -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);

View file

@ -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);

View file

@ -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) {

View file

@ -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,
Mesh::PRIMITIVE_LINES, //loop not supported, should ce converted
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];

View file

@ -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);
}

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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;
}

View file

@ -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];
}

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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;

View file

@ -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);

View file

@ -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,57 +962,55 @@ 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);
}
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;
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);
/* make aABB? */ {
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();
// check AABB
AABB aabb;
for (int i = 0; i < len; i++) {
if (i == 0)
aabb.position = vtx[i];
else
aabb.expand_to(vtx[i]);
}
s.aabb = aabb;
s.is_2d = arr.get_type() == Variant::POOL_VECTOR2_ARRAY;
surfaces.push_back(s);
_recompute_aabb();
}
VisualServer::get_singleton()->mesh_add_surface(mesh, sd);
clear_cache();
_change_notify();
emit_changed();
}
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) {
ERR_FAIL_COND(p_arrays.size() != ARRAY_MAX);
VS::SurfaceData surface;
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);
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 {
ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Array());
@ -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);
}
}

View file

@ -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;

View file

@ -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() {

View file

@ -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);

View file

@ -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);

View file

@ -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 VS::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 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 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
};

View file

@ -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
}

View file

@ -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;
/********************/

View file

@ -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

View file

@ -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

View file

@ -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));
}

File diff suppressed because it is too large Load diff

View file

@ -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 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 default_render_buffer_uniform_set;
/* Instance Data */
struct InstanceData {
struct UBO {
};
RID state_buffer;
RID uniform_set;
};
RID_Owner<InstanceData> instance_data_owner;
/* Scene State UBO */
struct SceneState {
struct UBO {
float projection_matrix[16];
float inv_projection_matrix[16];
float camera_matrix[16];
float inv_camera_matrix[16];
float viewport_size[2];
float screen_pixel_size[2];
float shadow_z_offset;
float shadow_z_slope_scale;
float time;
float reflection_multiplier;
};
UBO ubo;
RID uniform_buffer;
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;
/* Render List */
struct RenderList {
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);
class RasterizerSceneForwardRD : public RasterizerScene {
public:
/* SHADOW ATLAS API */
virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) {}
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; }
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) {}
int get_directional_light_shadow_size(RID p_light_intance) { return 0; }
void set_directional_shadow_count(int p_count) {}
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);
/* ENVIRONMENT API */
virtual bool free(RID p_rid);
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) {}
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) {}
void set_scene_pass(uint64_t p_pass) {}
void set_debug_draw_mode(VS::ViewportDebugDraw p_debug_draw) {}
bool free(RID p_rid) { return true; }
RasterizerSceneForwardRD() {}
~RasterizerSceneForwardRD() {}
RasterizerSceneForwardRD(RasterizerStorageRD *p_storage);
~RasterizerSceneForwardRD();
};
#endif // RASTERIZER_SCENE_FORWARD_RD_H

View file

@ -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() {
}

View file

@ -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

View file

@ -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]);
}
}

View file

@ -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();
/// Return stride
virtual void mesh_add_surface(RID p_mesh, const VS::SurfaceData &p_surface);
virtual int mesh_get_blend_shape_count(RID p_mesh) const;
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;
virtual void mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const PoolVector<uint8_t> &p_data);
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;
virtual VS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const;
virtual int mesh_get_surface_count(RID p_mesh) const;
virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb);
virtual AABB mesh_get_custom_aabb(RID p_mesh) const;
virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID());
virtual void mesh_clear(RID p_mesh);
_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();
}
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);
_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);
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;
Mesh::Surface *s = mesh->surfaces[p_surface_index];
r_index_array_rd = s->index_array;
s->version_lock.lock();
//there will never be more than, at much, 3 or 4 versions, so iterating is the fastest way
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;
}
uint32_t version = s->version_count; //gets added at the end
_mesh_surface_generate_version_for_input_mask(s, p_input_mask);
r_vertex_format = s->versions[version].vertex_format;
r_vertex_array_rd = s->versions[version].vertex_array;
s->version_lock.unlock();
}
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;
_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];
}
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;
}
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;
}
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(); }
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);
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);
return m->surfaces[p_surface].index_count;
}
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>());
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>());
return m->surfaces[p_surface].index_array;
}
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);
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);
return m->surfaces[p_surface].primitive;
}
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());
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> >());
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>());
return m->surfaces[p_surface].bone_aabbs;
}
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());
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();
}
void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) {}
AABB mesh_get_custom_aabb(RID p_mesh) const { return AABB(); }
AABB mesh_get_aabb(RID p_mesh, RID p_skeleton) const { return AABB(); }
void mesh_clear(RID p_mesh) {}
/* 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();

View file

@ -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;

View file

@ -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();
};

View file

@ -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');

View file

@ -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
}

View file

@ -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

View file

@ -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 ****/

View file

@ -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");

View file

@ -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(SurfaceData, mesh_get_surface, 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)
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)

View file

@ -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) {

View file

@ -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

View file

@ -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());

View file

@ -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);

View file

@ -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(SurfaceData, mesh_get_surface, 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)
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) {

View file

@ -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) {
mesh_add_surface(p_mesh, format, p_primitive, vertex_array, array_len, index_array, index_array_len, aabb, blend_shape_data, bone_aabb);
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;
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();
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 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();
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);

View file

@ -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);