diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp index 9997b15336d..0210b238b7a 100644 --- a/drivers/vulkan/rendering_device_vulkan.cpp +++ b/drivers/vulkan/rendering_device_vulkan.cpp @@ -1866,6 +1866,93 @@ RID RenderingDeviceVulkan::texture_create_shared(const TextureView &p_view, RID return id; } +RID RenderingDeviceVulkan::texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, int p_layer, int p_mipmap) { + + Texture *src_texture = texture_owner.getornull(p_with_texture); + ERR_FAIL_COND_V(!src_texture, RID()); + + if (src_texture->owner.is_valid()) { //ahh this is a share + p_with_texture = src_texture->owner; + src_texture = texture_owner.getornull(src_texture->owner); + ERR_FAIL_COND_V(!src_texture, RID()); //this is a bug + } + + //create view + + Texture texture = *src_texture; + + uint32_t array_layer_multiplier = 1; + if (texture.type == TEXTURE_TYPE_CUBE_ARRAY || texture.type == TEXTURE_TYPE_CUBE) { + array_layer_multiplier = 6; + } + + VkImageViewCreateInfo image_view_create_info; + image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + image_view_create_info.pNext = NULL; + image_view_create_info.flags = 0; + image_view_create_info.image = texture.image; + + static const VkImageViewType view_types[TEXTURE_TYPE_MAX] = { + VK_IMAGE_VIEW_TYPE_1D, + VK_IMAGE_VIEW_TYPE_2D, + VK_IMAGE_VIEW_TYPE_2D, + VK_IMAGE_VIEW_TYPE_2D, + VK_IMAGE_VIEW_TYPE_1D, + VK_IMAGE_VIEW_TYPE_2D, + VK_IMAGE_VIEW_TYPE_2D, + }; + + image_view_create_info.viewType = view_types[texture.type]; + if (p_view.format_override == DATA_FORMAT_MAX || p_view.format_override == texture.format) { + image_view_create_info.format = vulkan_formats[texture.format]; + } else { + ERR_FAIL_INDEX_V(p_view.format_override, DATA_FORMAT_MAX, RID()); + + ERR_FAIL_COND_V_MSG(texture.allowed_shared_formats.find(p_view.format_override) == -1, RID(), + "Format override is not in the list of allowed shareable formats for original texture."); + image_view_create_info.format = vulkan_formats[p_view.format_override]; + } + + static const VkComponentSwizzle component_swizzles[TEXTURE_SWIZZLE_MAX] = { + VK_COMPONENT_SWIZZLE_IDENTITY, + VK_COMPONENT_SWIZZLE_ZERO, + VK_COMPONENT_SWIZZLE_ONE, + VK_COMPONENT_SWIZZLE_R, + VK_COMPONENT_SWIZZLE_G, + VK_COMPONENT_SWIZZLE_B, + VK_COMPONENT_SWIZZLE_A + }; + + image_view_create_info.components.r = component_swizzles[p_view.swizzle_r]; + image_view_create_info.components.g = component_swizzles[p_view.swizzle_g]; + image_view_create_info.components.b = component_swizzles[p_view.swizzle_b]; + image_view_create_info.components.a = component_swizzles[p_view.swizzle_a]; + + ERR_FAIL_INDEX_V(p_mipmap, texture.mipmaps, RID()); + image_view_create_info.subresourceRange.baseMipLevel = p_mipmap; + image_view_create_info.subresourceRange.levelCount = 1; + image_view_create_info.subresourceRange.layerCount = 1; + image_view_create_info.subresourceRange.baseArrayLayer = p_layer; + + if (texture.usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { + image_view_create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + } else { + image_view_create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + } + + VkResult err = vkCreateImageView(device, &image_view_create_info, NULL, &texture.view); + + if (err) { + ERR_FAIL_V(RID()); + } + + texture.owner = p_with_texture; + RID id = texture_owner.make_rid(texture); + _add_dependency(id, p_with_texture); + + return id; +} + Error RenderingDeviceVulkan::texture_update(RID p_texture, uint32_t p_layer, const PoolVector &p_data, bool p_sync_with_draw) { _THREAD_SAFE_METHOD_ @@ -2618,10 +2705,18 @@ RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_format_c fb_format.E = E; fb_format.color_attachments = color_references; fb_format.render_pass = render_pass; + fb_format.samples = p_format[0].samples; framebuffer_formats[id] = fb_format; return id; } +RenderingDevice::TextureSamples RenderingDeviceVulkan::framebuffer_format_get_texture_samples(FramebufferFormatID p_format) { + Map::Element *E = framebuffer_formats.find(p_format); + ERR_FAIL_COND_V(!E, TEXTURE_SAMPLES_1); + + return E->get().samples; +} + /***********************/ /**** RENDER TARGET ****/ /***********************/ @@ -5690,6 +5785,41 @@ void RenderingDeviceVulkan::_free_rids(T &p_owner, const char *p_type) { } } +int RenderingDeviceVulkan::limit_get(Limit p_limit) { + switch (p_limit) { + case LIMIT_MAX_BOUND_UNIFORM_SETS: return limits.maxBoundDescriptorSets; + case LIMIT_MAX_FRAMEBUFFER_COLOR_ATTACHMENTS: return limits.maxColorAttachments; + case LIMIT_MAX_TEXTURES_PER_UNIFORM_SET: return limits.maxDescriptorSetSampledImages; + case LIMIT_MAX_SAMPLERS_PER_UNIFORM_SET: return limits.maxDescriptorSetSamplers; + case LIMIT_MAX_STORAGE_BUFFERS_PER_UNIFORM_SET: return limits.maxDescriptorSetStorageBuffers; + case LIMIT_MAX_STORAGE_IMAGES_PER_UNIFORM_SET: return limits.maxDescriptorSetStorageImages; + case LIMIT_MAX_UNIFORM_BUFFERS_PER_UNIFORM_SET: return limits.maxDescriptorSetUniformBuffers; + case LIMIT_MAX_DRAW_INDEXED_INDEX: return limits.maxDrawIndexedIndexValue; + case LIMIT_MAX_FRAMEBUFFER_HEIGHT: return limits.maxFramebufferHeight; + case LIMIT_MAX_FRAMEBUFFER_WIDTH: return limits.maxFramebufferWidth; + case LIMIT_MAX_TEXTURE_ARRAY_LAYERS: return limits.maxImageArrayLayers; + case LIMIT_MAX_TEXTURE_SIZE_1D: return limits.maxImageDimension1D; + case LIMIT_MAX_TEXTURE_SIZE_2D: return limits.maxImageDimension2D; + case LIMIT_MAX_TEXTURE_SIZE_3D: return limits.maxImageDimension3D; + case LIMIT_MAX_TEXTURE_SIZE_CUBE: return limits.maxImageDimensionCube; + case LIMIT_MAX_TEXTURES_PER_SHADER_STAGE: return limits.maxPerStageDescriptorSampledImages; + case LIMIT_MAX_SAMPLERS_PER_SHADER_STAGE: return limits.maxPerStageDescriptorSamplers; + case LIMIT_MAX_STORAGE_BUFFERS_PER_SHADER_STAGE: return limits.maxPerStageDescriptorStorageBuffers; + case LIMIT_MAX_STORAGE_IMAGES_PER_SHADER_STAGE: return limits.maxPerStageDescriptorStorageImages; + case LIMIT_MAX_UNIFORM_BUFFERS_PER_SHADER_STAGE: return limits.maxPerStageDescriptorUniformBuffers; + case LIMIT_MAX_PUSH_CONSTANT_SIZE: return limits.maxPushConstantsSize; + case LIMIT_MAX_UNIFORM_BUFFER_SIZE: return limits.maxUniformBufferRange; + case LIMIT_MAX_VERTEX_INPUT_ATTRIBUTE_OFFSET: return limits.maxVertexInputAttributeOffset; + case LIMIT_MAX_VERTEX_INPUT_ATTRIBUTES: return limits.maxVertexInputAttributes; + case LIMIT_MAX_VERTEX_INPUT_BINDINGS: return limits.maxVertexInputBindings; + case LIMIT_MAX_VERTEX_INPUT_BINDING_STRIDE: return limits.maxVertexInputBindingStride; + case LIMIT_MIN_UNIFORM_BUFFER_OFFSET_ALIGNMENT: return limits.minUniformBufferOffsetAlignment; + default: ERR_FAIL_V(0); + } + + return 0; +} + void RenderingDeviceVulkan::finalize() { //free all resources diff --git a/drivers/vulkan/rendering_device_vulkan.h b/drivers/vulkan/rendering_device_vulkan.h index 0404297c64a..3b7477c54df 100644 --- a/drivers/vulkan/rendering_device_vulkan.h +++ b/drivers/vulkan/rendering_device_vulkan.h @@ -234,6 +234,7 @@ class RenderingDeviceVulkan : public RenderingDevice { const Map::Element *E; VkRenderPass render_pass; //here for constructing shaders, never used, see section (7.2. Render Pass Compatibility from Vulkan spec) int color_attachments; //used for pipeline validation + TextureSamples samples; }; Map framebuffer_formats; @@ -714,6 +715,7 @@ class RenderingDeviceVulkan : public RenderingDevice { public: virtual RID texture_create(const TextureFormat &p_format, const TextureView &p_view, const Vector > &p_data = Vector >()); virtual RID texture_create_shared(const TextureView &p_view, RID p_with_texture); + virtual RID texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, int p_layer, int p_mipmap); virtual Error texture_update(RID p_texture, uint32_t p_layer, const PoolVector &p_data, bool p_sync_with_draw = false); virtual PoolVector texture_get_data(RID p_texture, uint32_t p_layer); @@ -725,7 +727,8 @@ public: /**** FRAMEBUFFER ****/ /*********************/ - FramebufferFormatID framebuffer_format_create(const Vector &p_format); + virtual FramebufferFormatID framebuffer_format_create(const Vector &p_format); + virtual TextureSamples framebuffer_format_get_texture_samples(FramebufferFormatID p_format); virtual RID framebuffer_create(const Vector &p_texture_attachments, FramebufferFormatID p_format_check = INVALID_ID); @@ -814,6 +817,8 @@ public: virtual void free(RID p_id); + virtual int limit_get(Limit p_limit); + virtual void prepare_screen_for_drawing(); void initialize(VulkanContext *p_context); void finalize(); diff --git a/drivers/vulkan/vulkan_context.cpp b/drivers/vulkan/vulkan_context.cpp index 9c7cdcf3917..8b4bc541217 100644 --- a/drivers/vulkan/vulkan_context.cpp +++ b/drivers/vulkan/vulkan_context.cpp @@ -86,6 +86,7 @@ VKAPI_ATTR VkBool32 VKAPI_CALL VulkanContext::_debug_messenger_callback(VkDebugU free(message); + abort(); // Don't bail out, but keep going. return false; } diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp index 6b819f65295..4dd485faf17 100644 --- a/scene/2d/light_2d.cpp +++ b/scene/2d/light_2d.cpp @@ -290,17 +290,6 @@ int Light2D::get_shadow_buffer_size() const { return shadow_buffer_size; } -void Light2D::set_shadow_gradient_length(float p_multiplier) { - - shadow_gradient_length = p_multiplier; - VS::get_singleton()->canvas_light_set_shadow_gradient_length(canvas_light, p_multiplier); -} - -float Light2D::get_shadow_gradient_length() const { - - return shadow_gradient_length; -} - void Light2D::set_shadow_filter(ShadowFilter p_filter) { ERR_FAIL_INDEX(p_filter, SHADOW_FILTER_MAX); shadow_filter = p_filter; @@ -421,9 +410,6 @@ void Light2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_shadow_smooth", "smooth"), &Light2D::set_shadow_smooth); ClassDB::bind_method(D_METHOD("get_shadow_smooth"), &Light2D::get_shadow_smooth); - ClassDB::bind_method(D_METHOD("set_shadow_gradient_length", "multiplier"), &Light2D::set_shadow_gradient_length); - ClassDB::bind_method(D_METHOD("get_shadow_gradient_length"), &Light2D::get_shadow_gradient_length); - ClassDB::bind_method(D_METHOD("set_shadow_filter", "filter"), &Light2D::set_shadow_filter); ClassDB::bind_method(D_METHOD("get_shadow_filter"), &Light2D::get_shadow_filter); @@ -450,7 +436,6 @@ void Light2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_enabled"), "set_shadow_enabled", "is_shadow_enabled"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "shadow_color"), "set_shadow_color", "get_shadow_color"); ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_buffer_size", PROPERTY_HINT_RANGE, "32,16384,1"), "set_shadow_buffer_size", "get_shadow_buffer_size"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "shadow_gradient_length", PROPERTY_HINT_RANGE, "0,4096,0.1"), "set_shadow_gradient_length", "get_shadow_gradient_length"); ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_filter", PROPERTY_HINT_ENUM, "None,PCF5,PCF13"), "set_shadow_filter", "get_shadow_filter"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "shadow_filter_smooth", PROPERTY_HINT_RANGE, "0,64,0.1"), "set_shadow_smooth", "get_shadow_smooth"); ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_item_cull_mask", PROPERTY_HINT_LAYERS_2D_RENDER), "set_item_shadow_cull_mask", "get_item_shadow_cull_mask"); @@ -482,7 +467,6 @@ Light2D::Light2D() { item_shadow_mask = 1; mode = MODE_ADD; shadow_buffer_size = 2048; - shadow_gradient_length = 0; energy = 1.0; shadow_color = Color(0, 0, 0, 0); shadow_filter = SHADOW_FILTER_NONE; diff --git a/scene/2d/light_2d.h b/scene/2d/light_2d.h index fb9047929fe..5027a77cd9b 100644 --- a/scene/2d/light_2d.h +++ b/scene/2d/light_2d.h @@ -70,7 +70,6 @@ private: int item_shadow_mask; int shadow_buffer_size; float shadow_smooth; - float shadow_gradient_length; Mode mode; Ref texture; Vector2 texture_offset; @@ -145,9 +144,6 @@ public: void set_shadow_buffer_size(int p_size); int get_shadow_buffer_size() const; - void set_shadow_gradient_length(float p_multiplier); - float get_shadow_gradient_length() const; - void set_shadow_filter(ShadowFilter p_filter); ShadowFilter get_shadow_filter() const; diff --git a/servers/visual/rasterizer/rasterizer.h b/servers/visual/rasterizer/rasterizer.h index 0726e43bf2b..f6ff980ece6 100644 --- a/servers/visual/rasterizer/rasterizer.h +++ b/servers/visual/rasterizer/rasterizer.h @@ -616,7 +616,6 @@ public: RID canvas; bool use_shadow; int shadow_buffer_size; - float shadow_gradient_length; VS::CanvasLightShadowFilter shadow_filter; Color shadow_color; float shadow_smooth; @@ -636,10 +635,12 @@ public: Light *mask_next_ptr; RID light_internal; + uint64_t version; int32_t render_index_cache; Light() { + version = 0; enabled = true; color = Color(1, 1, 1); shadow_color = Color(0, 0, 0, 0); @@ -659,7 +660,6 @@ public: filter_next_ptr = NULL; use_shadow = false; shadow_buffer_size = 2048; - shadow_gradient_length = 0; shadow_filter = VS::CANVAS_LIGHT_FILTER_NONE; shadow_smooth = 0.0; render_index_cache = -1; @@ -1062,6 +1062,13 @@ public: return command; } + struct CustomData { + + virtual ~CustomData() {} + }; + + mutable CustomData *custom_data; //implementation dependent + void clear() { Command *c = commands; while (c) { @@ -1110,6 +1117,7 @@ public: light_masked = false; update_when_visible = false; z_final = 0; + custom_data = NULL; } virtual ~Item() { clear(); @@ -1117,6 +1125,9 @@ public: memfree(blocks[i].memory); } if (copy_back_buffer) memdelete(copy_back_buffer); + if (custom_data) { + memdelete(custom_data); + } } }; diff --git a/servers/visual/rasterizer/rasterizer_canvas_rd.cpp b/servers/visual/rasterizer/rasterizer_canvas_rd.cpp index d09b353007b..93f905b72b8 100644 --- a/servers/visual/rasterizer/rasterizer_canvas_rd.cpp +++ b/servers/visual/rasterizer/rasterizer_canvas_rd.cpp @@ -225,42 +225,34 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector polygon_buffer; polygon_buffer.resize(buffer_size * sizeof(float)); Vector descriptions; descriptions.resize(5); + Vector buffers; + buffers.resize(5); { PoolVector::Read r = polygon_buffer.read(); float *fptr = (float *)r.ptr(); uint32_t *uptr = (uint32_t *)r.ptr(); - uint32_t single_offset = 0; - + uint32_t base_offset = 0; { //vertices RD::VertexDescription vd; vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; @@ -281,7 +273,7 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vectorvertex_format_create(descriptions); @@ -432,11 +411,12 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vectorvertex_buffer_create(polygon_buffer.size(), polygon_buffer); - Vector buffers; - buffers.resize(descriptions.size()); for (int i = 0; i < descriptions.size(); i++) { - buffers.write[i] = pb.vertex_buffer; + if (buffers[i] == RID()) { //if put in vertex, use as vertex + buffers.write[i] = pb.vertex_buffer; + } } + pb.vertex_array = RD::get_singleton()->vertex_array_create(p_points.size(), vertex_id, buffers); if (p_indices.size()) { @@ -508,9 +488,10 @@ Size2i RasterizerCanvasRD::_bind_texture_binding(TextureBindingID p_binding, RD: } //////////////////// -void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_item, RenderTargetFormat p_render_target_format, RD::TextureSamples p_samples, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights) { +void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_item, RD::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights) { //create an empty push constant + PushConstant push_constant; Transform2D base_transform = p_canvas_transform_inverse * p_item->final_transform; _update_transform_2d_to_mat2x3(base_transform, push_constant.world); @@ -538,30 +519,190 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ uint32_t base_flags = 0; + bool light_uniform_set_dirty = false; + + if (!p_item->custom_data) { + p_item->custom_data = memnew(ItemStateData); + light_uniform_set_dirty = true; + } + + ItemStateData *state_data = (ItemStateData *)p_item->custom_data; + + Light *light_cache[DEFAULT_MAX_LIGHTS_PER_ITEM]; + uint16_t light_count = 0; + PipelineLightMode light_mode; + { + Light *light = p_lights; - uint16_t light_count = 0; while (light) { if (light->render_index_cache >= 0 && p_item->light_mask & light->item_mask && p_item->z_final >= light->z_min && p_item->z_final <= light->z_max && p_item->global_rect_cache.intersects_transformed(light->xform_cache, light->rect_cache)) { uint32_t light_index = light->render_index_cache; push_constant.lights[light_count >> 2] |= light_index << ((light_count & 3) * 8); + + if (!light_uniform_set_dirty && (state_data->light_cache[light_count].light != light || state_data->light_cache[light_count].light_version != light->version)) { + light_uniform_set_dirty = true; + } + + light_cache[light_count] = light; + light_count++; if (light->mode == VS::CANVAS_LIGHT_MODE_MASK) { base_flags |= FLAGS_USING_LIGHT_MASK; } - if (light_count == MAX_LIGHTS_PER_ITEM) { + if (light_count == state.max_lights_per_item) { break; } } light = light->next_ptr; } + if (light_count != state_data->light_cache_count) { + light_uniform_set_dirty = true; + } base_flags |= light_count << FLAGS_LIGHT_COUNT_SHIFT; } + if (light_count) { + + //validate and update lighs if they are being used + bool invalid_uniform = state_data->light_uniform_set.is_valid() && !RD::get_singleton()->uniform_set_is_valid(state_data->light_uniform_set); + + if (state_data->light_uniform_set.is_null() || invalid_uniform || light_uniform_set_dirty) { + //recreate uniform set + if (state_data->light_uniform_set.is_valid() && !invalid_uniform) { + RD::get_singleton()->free(state_data->light_uniform_set); + } + + state_data->light_uniform_set = RID(); + + Vector uniforms; + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 0; + u.ids.push_back(state.lights_uniform_buffer); + uniforms.push_back(u); + } + + { + + RD::Uniform u_lights; + u_lights.type = RD::UNIFORM_TYPE_TEXTURE; + u_lights.binding = 1; + + RD::Uniform u_shadows; + u_shadows.type = RD::UNIFORM_TYPE_TEXTURE; + u_shadows.binding = 2; + + //lights + for (uint32_t i = 0; i < state.max_lights_per_item; i++) { + if (i < light_count) { + + CanvasLight *cl = canvas_light_owner.getornull(light_cache[i]->light_internal); + ERR_CONTINUE(!cl); + + RID rd_texture; + + if (cl->texture.is_valid()) { + rd_texture = storage->texture_get_rd_texture(cl->texture); + } + if (rd_texture.is_valid()) { + u_lights.ids.push_back(rd_texture); + } else { + u_lights.ids.push_back(default_textures.white_texture); + } + if (cl->shadow.texture.is_valid()) { + u_shadows.ids.push_back(cl->shadow.texture); + } else { + u_shadows.ids.push_back(default_textures.black_texture); + } + } else { + u_lights.ids.push_back(default_textures.white_texture); + u_shadows.ids.push_back(default_textures.black_texture); + } + } + + uniforms.push_back(u_lights); + uniforms.push_back(u_shadows); + } + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_SAMPLER; + u.binding = 3; + u.ids.push_back(state.shadow_sampler); + uniforms.push_back(u); + } + + state_data->light_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader.default_version_rd_shader_light, 3); + } + + RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, state_data->light_uniform_set, 3); + light_mode = PIPELINE_LIGHT_MODE_ENABLED; + } else { + light_mode = PIPELINE_LIGHT_MODE_DISABLED; + } + + { + //state uniform + bool invalid_uniform = state_data->state_uniform_set.is_valid() && !RD::get_singleton()->uniform_set_is_valid(state_data->state_uniform_set); + + if (state_data->state_uniform_set.is_null() || invalid_uniform) { + if (state_data->state_uniform_set.is_valid() && !invalid_uniform) { + RD::get_singleton()->free(state_data->state_uniform_set); + } + state_data->state_uniform_set = RID(); + + Vector uniforms; + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 0; + u.ids.push_back(state.canvas_state_buffer); + uniforms.push_back(u); + } + + if (false && p_item->skeleton.is_valid()) { + //bind skeleton stuff + } else { + //bind default + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 0; + u.ids.push_back(state.canvas_state_buffer); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE_BUFFER; + u.binding = 1; + u.ids.push_back(shader.default_skeleton_texture_buffer); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 2; + u.ids.push_back(shader.default_skeleton_uniform_buffer); + uniforms.push_back(u); + } + } + + state_data->state_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader.default_version_rd_shader, 2); + } + + RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, state_data->state_uniform_set, 2); + } + PipelineVariants *pipeline_variants = &shader.pipeline_variants; bool reclip = false; @@ -579,7 +720,7 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ //bind pipeline { - RID pipeline = pipeline_variants->variants[p_render_target_format][PIPELINE_VARIANT_QUAD].get_render_pipeline(RD::INVALID_ID, p_samples); + RID pipeline = pipeline_variants->variants[light_mode][PIPELINE_VARIANT_QUAD].get_render_pipeline(RD::INVALID_ID, p_framebuffer_format); RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline); } @@ -679,7 +820,7 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ //bind pipeline { - RID pipeline = pipeline_variants->variants[p_render_target_format][PIPELINE_VARIANT_NINEPATCH].get_render_pipeline(RD::INVALID_ID, p_samples); + RID pipeline = pipeline_variants->variants[light_mode][PIPELINE_VARIANT_NINEPATCH].get_render_pipeline(RD::INVALID_ID, p_framebuffer_format); RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline); } @@ -761,7 +902,7 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ { static const PipelineVariant variant[VS::PRIMITIVE_MAX] = { PIPELINE_VARIANT_ATTRIBUTE_POINTS, PIPELINE_VARIANT_ATTRIBUTE_LINES, PIPELINE_VARIANT_ATTRIBUTE_TRIANGLES }; ERR_CONTINUE(polygon->primitive < 0 || polygon->primitive >= VS::PRIMITIVE_MAX); - RID pipeline = pipeline_variants->variants[p_render_target_format][variant[polygon->primitive]].get_render_pipeline(pb->vertex_format_id, p_samples); + RID pipeline = pipeline_variants->variants[light_mode][variant[polygon->primitive]].get_render_pipeline(pb->vertex_format_id, p_framebuffer_format); RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline); } @@ -815,7 +956,7 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ { static const PipelineVariant variant[4] = { PIPELINE_VARIANT_PRIMITIVE_POINTS, PIPELINE_VARIANT_PRIMITIVE_LINES, PIPELINE_VARIANT_PRIMITIVE_TRIANGLES, PIPELINE_VARIANT_PRIMITIVE_TRIANGLES }; ERR_CONTINUE(primitive->point_count == 0 || primitive->point_count > 4); - RID pipeline = pipeline_variants->variants[p_render_target_format][variant[primitive->point_count - 1]].get_render_pipeline(RD::INVALID_ID, p_samples); + RID pipeline = pipeline_variants->variants[light_mode][variant[primitive->point_count - 1]].get_render_pipeline(RD::INVALID_ID, p_framebuffer_format); RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline); } @@ -1184,7 +1325,6 @@ void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count, Item *current_clip = NULL; - RenderTargetFormat render_target_format = RENDER_TARGET_FORMAT_8_BIT_INT; Transform2D canvas_transform_inverse = p_canvas_transform_inverse; RID framebuffer = storage->render_target_get_rd_framebuffer(p_to_render_target); @@ -1197,10 +1337,9 @@ void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count, storage->render_target_disable_clear_request(p_to_render_target); } #warning TODO obtain from framebuffer format eventually when this is implemented - RD::TextureSamples texture_samples = RD::TEXTURE_SAMPLES_1; - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, clear ? RD::INITIAL_ACTION_CLEAR : RD::INITIAL_ACTION_KEEP_COLOR, RD::FINAL_ACTION_READ_COLOR_DISCARD_DEPTH, clear_colors); + RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, state.canvas_state_uniform_set, 3); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, clear ? RD::INITIAL_ACTION_CLEAR : RD::INITIAL_ACTION_KEEP_COLOR, RD::FINAL_ACTION_READ_COLOR_DISCARD_DEPTH, clear_colors); for (int i = 0; i < p_item_count; i++) { @@ -1221,104 +1360,18 @@ void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count, } } - if (false) { //not skeleton - - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, shader.default_skeleton_uniform_set, 1); - } - - _render_item(draw_list, ci, render_target_format, texture_samples, canvas_transform_inverse, current_clip, p_lights); + _render_item(draw_list, ci, fb_format, canvas_transform_inverse, current_clip, p_lights); } RD::get_singleton()->draw_list_end(); } -void RasterizerCanvasRD::_update_canvas_state_uniform_set() { - - if (state.canvas_state_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(state.canvas_state_uniform_set)) { - return; //nothing to update - } - - Vector uniforms; - - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 0; - u.ids.push_back(state.canvas_state_buffer); - uniforms.push_back(u); - } - - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 1; - u.ids.push_back(state.lights_uniform_buffer); - uniforms.push_back(u); - } - - { - - RD::Uniform u_lights; - u_lights.type = RD::UNIFORM_TYPE_TEXTURE; - u_lights.binding = 2; - - RD::Uniform u_shadows; - u_shadows.type = RD::UNIFORM_TYPE_TEXTURE; - u_shadows.binding = 3; - - //lights - for (uint32_t i = 0; i < MAX_LIGHT_TEXTURES; i++) { - if (i < canvas_light_owner.get_rid_count()) { - CanvasLight *cl = canvas_light_owner.get_rid_by_index(i); - cl->texture_index = i; - RID rd_texture; - - if (cl->texture.is_valid()) { - rd_texture = storage->texture_get_rd_texture(cl->texture); - } - if (rd_texture.is_valid()) { - u_lights.ids.push_back(rd_texture); - } else { - u_lights.ids.push_back(default_textures.white_texture); - } - if (cl->shadow.texture.is_valid()) { - u_shadows.ids.push_back(cl->shadow.texture); - } else { - u_shadows.ids.push_back(default_textures.black_texture); - } - } else { - u_lights.ids.push_back(default_textures.white_texture); - u_shadows.ids.push_back(default_textures.black_texture); - } - } - - //in case there are more - for (uint32_t i = MAX_LIGHT_TEXTURES; i < canvas_light_owner.get_rid_count(); i++) { - CanvasLight *cl = canvas_light_owner.get_rid_by_index(i); - cl->texture_index = -1; //make invalid (no texture) - } - - uniforms.push_back(u_lights); - uniforms.push_back(u_shadows); - } - - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER; - u.binding = 4; - u.ids.push_back(state.shadow_sampler); - uniforms.push_back(u); - } - - state.canvas_state_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader.default_version_rd_shader, 3); // uses index 3 -} - void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, const Transform2D &p_canvas_transform) { int item_count = 0; //setup canvas state uniforms if needed - _update_canvas_state_uniform_set(); + Transform2D canvas_transform_inverse = p_canvas_transform.affine_inverse(); { @@ -1356,14 +1409,14 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite while (l) { - if (index == MAX_RENDER_LIGHTS) { + if (index == state.max_lights_per_render) { l->render_index_cache = -1; l = l->next_ptr; continue; } CanvasLight *clight = canvas_light_owner.getornull(l->light_internal); - if (!clight || clight->texture_index < 0) { //unused or invalid texture + if (!clight) { //unused or invalid texture l->render_index_cache = -1; l = l->next_ptr; ERR_CONTINUE(!clight); @@ -1390,7 +1443,7 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite } else { state.light_uniforms[index].shadow_pixel_size = 1.0; } - state.light_uniforms[index].flags = clight->texture_index; + state.light_uniforms[index].flags |= l->mode << LIGHT_FLAGS_BLEND_SHIFT; state.light_uniforms[index].flags |= l->shadow_filter << LIGHT_FLAGS_FILTER_SHIFT; if (clight->shadow.texture.is_valid()) { @@ -1439,7 +1492,6 @@ RID RasterizerCanvasRD::light_create() { CanvasLight canvas_light; canvas_light.shadow.size = 0; - canvas_light.texture_index = -1; return canvas_light_owner.make_rid(canvas_light); } @@ -1451,11 +1503,6 @@ void RasterizerCanvasRD::light_set_texture(RID p_rid, RID p_texture) { } cl->texture = p_texture; - - //canvas state uniform set needs updating - if (state.canvas_state_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(state.canvas_state_uniform_set)) { - RD::get_singleton()->free(state.canvas_state_uniform_set); - } } void RasterizerCanvasRD::light_set_use_shadow(RID p_rid, bool p_enable, int p_resolution) { CanvasLight *cl = canvas_light_owner.getornull(p_rid); @@ -1506,11 +1553,6 @@ void RasterizerCanvasRD::light_set_use_shadow(RID p_rid, bool p_enable, int p_re } cl->shadow.size = p_resolution; - - //canvas state uniform set needs updating - if (state.canvas_state_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(state.canvas_state_uniform_set)) { - RD::get_singleton()->free(state.canvas_state_uniform_set); - } } void RasterizerCanvasRD::light_update_shadow(RID p_rid, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders) { @@ -1831,35 +1873,58 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { } { //shader variants + + uint32_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE); + + String global_defines; + if (textures_per_stage <= 16) { + //ARM pretty much, and very old Intel GPUs under Linux + state.max_lights_per_item = 4; //sad + global_defines += "#define MAX_LIGHT_TEXTURES 4\n"; + } else if (textures_per_stage <= 32) { + //Apple (Metal) + state.max_lights_per_item = 8; //sad + global_defines += "#define MAX_LIGHT_TEXTURES 8\n"; + } else { + //Anything else (16 lights per item) + state.max_lights_per_item = DEFAULT_MAX_LIGHTS_PER_ITEM; + global_defines += "#define MAX_LIGHT_TEXTURES " + itos(DEFAULT_MAX_LIGHTS_PER_ITEM) + "\n"; + } + + uint32_t uniform_max_size = RD::get_singleton()->limit_get(RD::LIMIT_MAX_UNIFORM_BUFFER_SIZE); + if (uniform_max_size < 65536) { + //Yes, you guessed right, ARM again + state.max_lights_per_render = 64; + global_defines += "#define MAX_LIGHTS 64\n"; + } else { + state.max_lights_per_render = DEFAULT_MAX_LIGHTS_PER_RENDER; + global_defines += "#define MAX_LIGHTS " + itos(DEFAULT_MAX_LIGHTS_PER_RENDER) + "\n"; + } + + state.light_uniforms = memnew_arr(LightUniform, state.max_lights_per_render); Vector variants; + //non light variants variants.push_back(""); //none by default is first variant variants.push_back("#define USE_NINEPATCH\n"); //ninepatch is the second variant variants.push_back("#define USE_PRIMITIVE\n"); //primitve is the third variants.push_back("#define USE_PRIMITIVE\n#define USE_POINT_SIZE\n"); //points need point size variants.push_back("#define USE_ATTRIBUTES\n"); // attributes for vertex arrays variants.push_back("#define USE_ATTRIBUTES\n#define USE_POINT_SIZE\n"); //attributes with point size - shader.canvas_shader.initialize(variants); + //light variants + variants.push_back("#define USE_LIGHTING\n"); //none by default is first variant + variants.push_back("#define USE_LIGHTING\n#define USE_NINEPATCH\n"); //ninepatch is the second variant + variants.push_back("#define USE_LIGHTING\n#define USE_PRIMITIVE\n"); //primitve is the third + variants.push_back("#define USE_LIGHTING\n#define USE_PRIMITIVE\n#define USE_POINT_SIZE\n"); //points need point size + variants.push_back("#define USE_LIGHTING\n#define USE_ATTRIBUTES\n"); // attributes for vertex arrays + variants.push_back("#define USE_LIGHTING\n#define USE_ATTRIBUTES\n#define USE_POINT_SIZE\n"); //attributes with point size + + shader.canvas_shader.initialize(variants, global_defines); shader.default_version = shader.canvas_shader.version_create(); + shader.default_version_rd_shader = shader.canvas_shader.version_get_shader(shader.default_version, SHADER_VARIANT_QUAD); + shader.default_version_rd_shader_light = shader.canvas_shader.version_get_shader(shader.default_version, SHADER_VARIANT_QUAD_LIGHT); - { - //framebuffer formats - RD::AttachmentFormat af; - af.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - af.samples = RD::TEXTURE_SAMPLES_1; - af.usage_flags = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_RETRIEVE_BIT; - Vector formats; - formats.push_back(af); - shader.framebuffer_formats[RENDER_TARGET_FORMAT_8_BIT_INT] = RD::get_singleton()->framebuffer_format_create(formats); - - formats.clear(); - af.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - formats.push_back(af); - shader.framebuffer_formats[RENDER_TARGET_FORMAT_16_BIT_FLOAT] = RD::get_singleton()->framebuffer_format_create(formats); - } - - for (int i = 0; i < RENDER_TARGET_FORMAT_MAX; i++) { - RD::FramebufferFormatID fb_format = shader.framebuffer_formats[i]; + for (int i = 0; i < PIPELINE_LIGHT_MODE_MAX; i++) { for (int j = 0; j < PIPELINE_VARIANT_MAX; j++) { RD::RenderPrimitive primitive[PIPELINE_VARIANT_MAX] = { RD::RENDER_PRIMITIVE_TRIANGLES, @@ -1871,23 +1936,31 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { RD::RENDER_PRIMITIVE_LINES, RD::RENDER_PRIMITIVE_POINTS, }; - ShaderVariant shader_variants[PIPELINE_VARIANT_MAX] = { - SHADER_VARIANT_QUAD, - SHADER_VARIANT_NINEPATCH, - SHADER_VARIANT_PRIMITIVE, - SHADER_VARIANT_PRIMITIVE, - SHADER_VARIANT_PRIMITIVE_POINTS, - SHADER_VARIANT_ATTRIBUTES, - SHADER_VARIANT_ATTRIBUTES, - SHADER_VARIANT_ATTRIBUTES_POINTS + ShaderVariant shader_variants[PIPELINE_LIGHT_MODE_MAX][PIPELINE_VARIANT_MAX] = { + { //non lit + SHADER_VARIANT_QUAD, + SHADER_VARIANT_NINEPATCH, + SHADER_VARIANT_PRIMITIVE, + SHADER_VARIANT_PRIMITIVE, + SHADER_VARIANT_PRIMITIVE_POINTS, + SHADER_VARIANT_ATTRIBUTES, + SHADER_VARIANT_ATTRIBUTES, + SHADER_VARIANT_ATTRIBUTES_POINTS }, + { //lit + SHADER_VARIANT_QUAD_LIGHT, + SHADER_VARIANT_NINEPATCH_LIGHT, + SHADER_VARIANT_PRIMITIVE_LIGHT, + SHADER_VARIANT_PRIMITIVE_LIGHT, + SHADER_VARIANT_PRIMITIVE_POINTS_LIGHT, + SHADER_VARIANT_ATTRIBUTES_LIGHT, + SHADER_VARIANT_ATTRIBUTES_LIGHT, + SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT }, }; - RID shader_variant = shader.canvas_shader.version_get_shader(shader.default_version, shader_variants[j]); - shader.pipeline_variants.variants[i][j].setup(shader_variant, fb_format, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_blend(), 0); + RID shader_variant = shader.canvas_shader.version_get_shader(shader.default_version, shader_variants[i][j]); + shader.pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_blend(), 0); } } - - shader.default_version_rd_shader = shader.canvas_shader.version_get_shader(shader.default_version, 0); } { //shadow rendering @@ -1901,6 +1974,7 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { RD::AttachmentFormat af_color; af_color.format = RD::DATA_FORMAT_R32_SFLOAT; af_color.usage_flags = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + af_color.samples = RenderingDevice::TEXTURE_SAMPLES_64; attachments.push_back(af_color); @@ -1908,6 +1982,7 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { af_depth.format = RD::DATA_FORMAT_D24_UNORM_S8_UINT; af_depth.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_X8_D24_UNORM_PACK32, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_X8_D24_UNORM_PACK32 : RD::DATA_FORMAT_D32_SFLOAT; af_depth.usage_flags = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + af_depth.samples = RenderingDevice::TEXTURE_SAMPLES_64; attachments.push_back(af_depth); @@ -1944,7 +2019,7 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { { //state allocate state.canvas_state_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(State::Buffer)); - state.lights_uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(LightUniform) * MAX_RENDER_LIGHTS); + state.lights_uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(LightUniform) * state.max_lights_per_render); RD::SamplerState shadow_sampler_state; shadow_sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR; @@ -1956,6 +2031,60 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { } { + { + PoolVector colors; + colors.resize(sizeof(float) * 4); + { + PoolVector::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 uvs; + uvs.resize(sizeof(float) * 2); + { + PoolVector::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 bones; + bones.resize(sizeof(uint32_t) * 4); + { + PoolVector::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 weights; + weights.resize(sizeof(float) * 4); + { + PoolVector::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; } @@ -1987,28 +2116,13 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { { //default skeleton buffer - shader.default_skeleton_uniform = RD::get_singleton()->uniform_buffer_create(sizeof(SkeletonUniform)); + shader.default_skeleton_uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SkeletonUniform)); SkeletonUniform su; _update_transform_2d_to_mat4(Transform2D(), su.skeleton_inverse); _update_transform_2d_to_mat4(Transform2D(), su.skeleton_transform); - RD::get_singleton()->buffer_update(shader.default_skeleton_uniform, 0, sizeof(SkeletonUniform), &su); - } + RD::get_singleton()->buffer_update(shader.default_skeleton_uniform_buffer, 0, sizeof(SkeletonUniform), &su); - { //default material uniform set - Vector default_material_uniforms; - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 2; - u.ids.push_back(shader.default_skeleton_uniform); - default_material_uniforms.push_back(u); - - u.ids.clear(); - u.type = RD::UNIFORM_TYPE_TEXTURE_BUFFER; - u.binding = 1; - u.ids.push_back(default_textures.default_multimesh_tb); - default_material_uniforms.push_back(u); - - shader.default_skeleton_uniform_set = RD::get_singleton()->uniform_set_create(default_material_uniforms, shader.canvas_shader.version_get_shader(shader.default_version, SHADER_VARIANT_ATTRIBUTES), 2); + shader.default_skeleton_texture_buffer = RD::get_singleton()->texture_buffer_create(32, RD::DATA_FORMAT_R32G32B32A32_SFLOAT); } ERR_FAIL_COND(sizeof(PushConstant) != 128); @@ -2021,10 +2135,6 @@ bool RasterizerCanvasRD::free(RID p_rid) { ERR_FAIL_COND_V(!cl, false); light_set_use_shadow(p_rid, false, 64); canvas_light_owner.free(p_rid); - //canvas state uniform set needs updating - if (state.canvas_state_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(state.canvas_state_uniform_set)) { - RD::get_singleton()->free(state.canvas_state_uniform_set); - } } else if (occluder_polygon_owner.owns(p_rid)) { occluder_polygon_set_shape_as_lines(p_rid, PoolVector()); occluder_polygon_owner.free(p_rid); @@ -2043,10 +2153,6 @@ RasterizerCanvasRD::~RasterizerCanvasRD() { RD::get_singleton()->free(state.canvas_state_buffer); } - if (state.canvas_state_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(state.canvas_state_uniform_set)) { - RD::get_singleton()->free(state.canvas_state_uniform_set); - } - //bindings { @@ -2070,8 +2176,6 @@ RasterizerCanvasRD::~RasterizerCanvasRD() { //shaders - RD::get_singleton()->free(shader.default_skeleton_uniform_set); - RD::get_singleton()->free(shader.default_skeleton_uniform); shader.canvas_shader.version_free(shader.default_version); //buffers diff --git a/servers/visual/rasterizer/rasterizer_canvas_rd.h b/servers/visual/rasterizer/rasterizer_canvas_rd.h index 81e2815d6f1..dfeecddfc10 100644 --- a/servers/visual/rasterizer/rasterizer_canvas_rd.h +++ b/servers/visual/rasterizer/rasterizer_canvas_rd.h @@ -6,7 +6,6 @@ #include "servers/visual/rasterizer/render_pipeline_vertex_format_cache_rd.h" #include "servers/visual/rasterizer/shaders/canvas.glsl.gen.h" #include "servers/visual/rasterizer/shaders/canvas_occlusion.glsl.gen.h" -#include "servers/visual/rasterizer/shaders/canvas_occlusion_fix.glsl.gen.h" #include "servers/visual/rendering_device.h" class RasterizerCanvasRD : public RasterizerCanvas { @@ -20,15 +19,15 @@ class RasterizerCanvasRD : public RasterizerCanvas { SHADER_VARIANT_PRIMITIVE_POINTS, SHADER_VARIANT_ATTRIBUTES, SHADER_VARIANT_ATTRIBUTES_POINTS, + SHADER_VARIANT_QUAD_LIGHT, + SHADER_VARIANT_NINEPATCH_LIGHT, + SHADER_VARIANT_PRIMITIVE_LIGHT, + SHADER_VARIANT_PRIMITIVE_POINTS_LIGHT, + SHADER_VARIANT_ATTRIBUTES_LIGHT, + SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT, SHADER_VARIANT_MAX }; - enum RenderTargetFormat { - RENDER_TARGET_FORMAT_8_BIT_INT, - RENDER_TARGET_FORMAT_16_BIT_FLOAT, - RENDER_TARGET_FORMAT_MAX - }; - enum { FLAGS_INSTANCING_STRIDE_MASK = 0xF, FLAGS_INSTANCING_ENABLED = (1 << 4), @@ -71,8 +70,8 @@ class RasterizerCanvasRD : public RasterizerCanvas { enum { MAX_RENDER_ITEMS = 256 * 1024, MAX_LIGHT_TEXTURES = 1024, - MAX_LIGHTS_PER_ITEM = 16, - MAX_RENDER_LIGHTS = 256 + DEFAULT_MAX_LIGHTS_PER_ITEM = 16, + DEFAULT_MAX_LIGHTS_PER_RENDER = 256 }; /****************/ @@ -90,22 +89,28 @@ class RasterizerCanvasRD : public RasterizerCanvas { PIPELINE_VARIANT_ATTRIBUTE_POINTS, PIPELINE_VARIANT_MAX }; + enum PipelineLightMode { + PIPELINE_LIGHT_MODE_DISABLED, + PIPELINE_LIGHT_MODE_ENABLED, + PIPELINE_LIGHT_MODE_MAX + }; + struct PipelineVariants { - RenderPipelineVertexFormatCacheRD variants[RENDER_TARGET_FORMAT_MAX][PIPELINE_VARIANT_MAX]; + RenderPipelineVertexFormatCacheRD variants[PIPELINE_LIGHT_MODE_MAX][PIPELINE_VARIANT_MAX]; }; struct { CanvasShaderRD canvas_shader; - RD::FramebufferFormatID framebuffer_formats[RENDER_TARGET_FORMAT_MAX]; RID default_version; RID default_version_rd_shader; + RID default_version_rd_shader_light; RID quad_index_buffer; RID quad_index_array; PipelineVariants pipeline_variants; // default_skeleton uniform set - RID default_skeleton_uniform; - RID default_skeleton_uniform_set; + RID default_skeleton_uniform_buffer; + RID default_skeleton_texture_buffer; } shader; @@ -194,6 +199,10 @@ class RasterizerCanvasRD : public RasterizerCanvas { struct { HashMap polygons; PolygonID last_id; + RID default_color_buffer; + RID default_uv_buffer; + RID default_bone_buffer; + RID default_weight_buffer; } polygon_buffers; /********************/ @@ -214,7 +223,6 @@ class RasterizerCanvasRD : public RasterizerCanvas { struct CanvasLight { - int32_t texture_index; RID texture; struct { int size; @@ -256,9 +264,8 @@ class RasterizerCanvasRD : public RasterizerCanvas { float position[2]; uint32_t flags; //index to light texture float height; - float shadow_softness; float shadow_pixel_size; - float pad[2]; + float pad[3]; }; RID_Owner occluder_polygon_owner; @@ -277,6 +284,36 @@ class RasterizerCanvasRD : public RasterizerCanvas { //state that does not vary across rendering all items + struct ItemStateData : public Item::CustomData { + + struct LightCache { + uint64_t light_version; + Light *light; + }; + + LightCache light_cache[DEFAULT_MAX_LIGHTS_PER_ITEM]; + uint32_t light_cache_count; + RID light_uniform_set; + RID state_uniform_set; + ItemStateData() { + + for (int i = 0; i < DEFAULT_MAX_LIGHTS_PER_ITEM; i++) { + light_cache[i].light_version = 0; + light_cache[i].light = NULL; + } + light_cache_count = 0xFFFFFFFF; + } + + ~ItemStateData() { + if (light_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(light_uniform_set)) { + RD::get_singleton()->free(light_uniform_set); + } + if (state_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(state_uniform_set)) { + RD::get_singleton()->free(state_uniform_set); + } + } + }; + struct State { //state buffer @@ -289,14 +326,14 @@ class RasterizerCanvasRD : public RasterizerCanvas { //uint32_t pad[3]; }; - LightUniform light_uniforms[MAX_RENDER_LIGHTS]; + LightUniform *light_uniforms; RID lights_uniform_buffer; RID canvas_state_buffer; RID shadow_sampler; - //uniform set for all the above - RID canvas_state_uniform_set; + uint32_t max_lights_per_render; + uint32_t max_lights_per_item; } state; struct PushConstant { @@ -331,7 +368,7 @@ class RasterizerCanvasRD : public RasterizerCanvas { Item *items[MAX_RENDER_ITEMS]; Size2i _bind_texture_binding(TextureBindingID p_binding, RenderingDevice::DrawListID p_draw_list, uint32_t &flags); - void _render_item(RenderingDevice::DrawListID p_draw_list, const Item *p_item, RenderTargetFormat p_render_target_format, RenderingDevice::TextureSamples p_samples, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights); + void _render_item(RenderingDevice::DrawListID p_draw_list, const Item *p_item, RenderingDevice::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights); void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights); _FORCE_INLINE_ void _update_transform_2d_to_mat2x4(const Transform2D &p_transform, float *p_mat2x4); @@ -342,8 +379,6 @@ class RasterizerCanvasRD : public RasterizerCanvas { _FORCE_INLINE_ void _update_specular_shininess(const Color &p_transform, uint32_t *r_ss); - void _update_canvas_state_uniform_set(); - public: TextureBindingID request_texture_binding(RID p_texture, RID p_normalmap, RID p_specular, VS::CanvasItemTextureFilter p_filter, VS::CanvasItemTextureRepeat p_repeat, RID p_multimesh); void free_texture_binding(TextureBindingID p_binding); diff --git a/servers/visual/rasterizer/render_pipeline_vertex_format_cache_rd.cpp b/servers/visual/rasterizer/render_pipeline_vertex_format_cache_rd.cpp index be2aa95c34b..2c2d6e9ca09 100644 --- a/servers/visual/rasterizer/render_pipeline_vertex_format_cache_rd.cpp +++ b/servers/visual/rasterizer/render_pipeline_vertex_format_cache_rd.cpp @@ -1,43 +1,39 @@ #include "render_pipeline_vertex_format_cache_rd.h" #include "core/os/memory.h" -RID RenderPipelineVertexFormatCacheRD::_generate_version(RD::VertexFormatID p_format_id, RenderingDevice::TextureSamples p_samples) { +RID RenderPipelineVertexFormatCacheRD::_generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id) { - RD::PipelineMultisampleState multisample_state_version; - if (p_samples != RD::TEXTURE_SAMPLES_1) { - multisample_state_version = multisample_state; - multisample_state_version.sample_count = p_samples; - } - RID pipeline = RD::get_singleton()->render_pipeline_create(shader, framebuffer_format, p_format_id, render_primitive, rasterization_state, multisample_state, depth_stencil_state, blend_state, dynamic_state_flags); + RD::PipelineMultisampleState multisample_state_version = multisample_state; + multisample_state_version.sample_count = RD::get_singleton()->framebuffer_format_get_texture_samples(p_framebuffer_format_id); + + RID pipeline = RD::get_singleton()->render_pipeline_create(shader, p_framebuffer_format_id, p_vertex_format_id, render_primitive, rasterization_state, multisample_state_version, depth_stencil_state, blend_state, dynamic_state_flags); ERR_FAIL_COND_V(pipeline.is_null(), RID()); - versions[p_samples] = (Version *)memrealloc(versions[p_samples], sizeof(Version) * (version_count[p_samples] + 1)); - versions[p_samples][version_count[p_samples]].format_id = p_format_id; - versions[p_samples][version_count[p_samples]].pipeline = pipeline; - version_count[p_samples]++; + versions = (Version *)memrealloc(versions, sizeof(Version) * (version_count + 1)); + versions[version_count].framebuffer_id = p_framebuffer_format_id; + versions[version_count].vertex_id= p_vertex_format_id; + versions[version_count].pipeline = pipeline; + version_count++; return pipeline; } void RenderPipelineVertexFormatCacheRD::_clear() { - for (int v = 0; v < RD::TEXTURE_SAMPLES_MAX; v++) { - if (versions[v]) { - for (uint32_t i = 0; i < version_count[v]; i++) { - //shader may be gone, so this may not be valid - if (RD::get_singleton()->render_pipeline_is_valid(versions[v][i].pipeline)) { - RD::get_singleton()->free(versions[v][i].pipeline); - } + if (versions) { + for (uint32_t i = 0; i < version_count; i++) { + //shader may be gone, so this may not be valid + if (RD::get_singleton()->render_pipeline_is_valid(versions[i].pipeline)) { + RD::get_singleton()->free(versions[i].pipeline); } - version_count[v] = 0; - memfree(versions[v]); - versions[v] = NULL; } + version_count = 0; + memfree(versions); + versions = NULL; } } -void RenderPipelineVertexFormatCacheRD::setup(RID p_shader, RD::FramebufferFormatID p_framebuffer_format, RD::RenderPrimitive p_primitive, const RD::PipelineRasterizationState &p_rasterization_state, RD::PipelineMultisampleState p_multisample, const RD::PipelineDepthStencilState &p_depth_stencil_state, const RD::PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags) { +void RenderPipelineVertexFormatCacheRD::setup(RID p_shader, RD::RenderPrimitive p_primitive, const RD::PipelineRasterizationState &p_rasterization_state, RD::PipelineMultisampleState p_multisample, const RD::PipelineDepthStencilState &p_depth_stencil_state, const RD::PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags) { ERR_FAIL_COND(p_shader.is_null()); shader = p_shader; - framebuffer_format = p_framebuffer_format; render_primitive = p_primitive; rasterization_state = p_rasterization_state; multisample_state = p_multisample; @@ -49,14 +45,12 @@ void RenderPipelineVertexFormatCacheRD::setup(RID p_shader, RD::FramebufferForma void RenderPipelineVertexFormatCacheRD::update_shader(RID p_shader) { ERR_FAIL_COND(p_shader.is_null()); _clear(); - setup(p_shader, framebuffer_format, render_primitive, rasterization_state, multisample_state, depth_stencil_state, blend_state, dynamic_state_flags); + setup(p_shader, render_primitive, rasterization_state, multisample_state, depth_stencil_state, blend_state, dynamic_state_flags); } RenderPipelineVertexFormatCacheRD::RenderPipelineVertexFormatCacheRD() { - for (int i = 0; i < RD::TEXTURE_SAMPLES_MAX; i++) { - version_count[i] = 0; - versions[i] = NULL; - } + version_count = 0; + versions = NULL; } RenderPipelineVertexFormatCacheRD::~RenderPipelineVertexFormatCacheRD() { diff --git a/servers/visual/rasterizer/render_pipeline_vertex_format_cache_rd.h b/servers/visual/rasterizer/render_pipeline_vertex_format_cache_rd.h index 02b34c3a1bd..cdbfda05f1b 100644 --- a/servers/visual/rasterizer/render_pipeline_vertex_format_cache_rd.h +++ b/servers/visual/rasterizer/render_pipeline_vertex_format_cache_rd.h @@ -16,29 +16,29 @@ class RenderPipelineVertexFormatCacheRD { int dynamic_state_flags; struct Version { - RD::VertexFormatID format_id; + RD::VertexFormatID vertex_id; + RD::FramebufferFormatID framebuffer_id; RID pipeline; }; - Version *versions[RD::TEXTURE_SAMPLES_MAX]; - uint32_t version_count[RD::TEXTURE_SAMPLES_MAX]; + Version *versions; + uint32_t version_count; - RID _generate_version(RD::VertexFormatID p_format_id, RD::TextureSamples p_samples); + RID _generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id); void _clear(); public: - void setup(RID p_shader, RD::FramebufferFormatID p_framebuffer_format, RD::RenderPrimitive p_primitive, const RD::PipelineRasterizationState &p_rasterization_state, RD::PipelineMultisampleState p_multisample, const RD::PipelineDepthStencilState &p_depth_stencil_state, const RD::PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags = 0); + void setup(RID p_shader, RD::RenderPrimitive p_primitive, const RD::PipelineRasterizationState &p_rasterization_state, RD::PipelineMultisampleState p_multisample, const RD::PipelineDepthStencilState &p_depth_stencil_state, const RD::PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags = 0); void update_shader(RID p_shader); - _FORCE_INLINE_ RID get_render_pipeline(RD::VertexFormatID p_format_id, RD::TextureSamples p_samples) { - ERR_FAIL_INDEX_V(p_samples, RD::TEXTURE_SAMPLES_MAX, RID()); - for (uint32_t i = 0; i < version_count[p_samples]; i++) { - if (versions[p_samples][i].format_id == p_format_id) { - return versions[p_samples][i].pipeline; + _FORCE_INLINE_ RID get_render_pipeline(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id) { + 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; } } - return _generate_version(p_format_id, p_samples); + return _generate_version(p_vertex_format_id, p_framebuffer_format_id); } RenderPipelineVertexFormatCacheRD(); diff --git a/servers/visual/rasterizer/shader_rd.cpp b/servers/visual/rasterizer/shader_rd.cpp index ff07fa1695e..36fb6475190 100644 --- a/servers/visual/rasterizer/shader_rd.cpp +++ b/servers/visual/rasterizer/shader_rd.cpp @@ -180,7 +180,9 @@ void ShaderRD::_compile_version(Version *p_version) { builder.append(vertex_codev.get_data()); // version info (if exists) builder.append("\n"); //make sure defines begin at newline + builder.append(general_defines.get_data()); builder.append(variant_defines[i].get_data()); + for (int j = 0; j < p_version->custom_defines.size(); j++) { builder.append(p_version->custom_defines[j].get_data()); } @@ -214,6 +216,7 @@ void ShaderRD::_compile_version(Version *p_version) { builder.append(fragment_codev.get_data()); // version info (if exists) builder.append("\n"); //make sure defines begin at newline + builder.append(general_defines.get_data()); builder.append(variant_defines[i].get_data()); for (int j = 0; j < p_version->custom_defines.size(); j++) { builder.append(p_version->custom_defines[j].get_data()); @@ -307,9 +310,10 @@ bool ShaderRD::version_free(RID p_version) { return true; } -void ShaderRD::initialize(const Vector &p_variant_defines) { +void ShaderRD::initialize(const Vector &p_variant_defines, const String &p_general_defines) { ERR_FAIL_COND(variant_defines.size()); ERR_FAIL_COND(p_variant_defines.size() == 0); + general_defines = p_general_defines.utf8(); for (int i = 0; i < p_variant_defines.size(); i++) { variant_defines.push_back(p_variant_defines[i].utf8()); diff --git a/servers/visual/rasterizer/shader_rd.h b/servers/visual/rasterizer/shader_rd.h index 814c87d2818..c7a8cdaa378 100644 --- a/servers/visual/rasterizer/shader_rd.h +++ b/servers/visual/rasterizer/shader_rd.h @@ -44,6 +44,7 @@ class ShaderRD { //versions + CharString general_defines; Vector variant_defines; int vertex_code_start; @@ -114,7 +115,7 @@ public: bool version_free(RID p_version); - void initialize(const Vector &p_variant_defines); + void initialize(const Vector &p_variant_defines, const String &p_general_defines = ""); virtual ~ShaderRD(); }; diff --git a/servers/visual/rasterizer/shaders/SCsub b/servers/visual/rasterizer/shaders/SCsub index ef1df0c2032..37290e997f8 100644 --- a/servers/visual/rasterizer/shaders/SCsub +++ b/servers/visual/rasterizer/shaders/SCsub @@ -5,4 +5,3 @@ Import('env') if 'RD_GLSL' in env['BUILDERS']: env.RD_GLSL('canvas.glsl'); env.RD_GLSL('canvas_occlusion.glsl'); - env.RD_GLSL('canvas_occlusion_fix.glsl'); diff --git a/servers/visual/rasterizer/shaders/canvas.glsl b/servers/visual/rasterizer/shaders/canvas.glsl index defe8630be3..8d36a2e3eab 100644 --- a/servers/visual/rasterizer/shaders/canvas.glsl +++ b/servers/visual/rasterizer/shaders/canvas.glsl @@ -426,8 +426,11 @@ FRAGMENT_SHADER_CODE } color*=canvas_data.canvas_modulation; - - for(uint i=0;i=light_count) { + break; + } uint light_base; if (i<8) { if (i<4) { @@ -445,16 +448,8 @@ FRAGMENT_SHADER_CODE light_base>>=(i&3)*8; light_base&=0xFF; -#define LIGHT_FLAGS_BLEND_MASK (3<<16) -#define LIGHT_FLAGS_BLEND_MODE_ADD (0<<16) -#define LIGHT_FLAGS_BLEND_MODE_SUB (1<<16) -#define LIGHT_FLAGS_BLEND_MODE_MIX (2<<16) -#define LIGHT_FLAGS_BLEND_MODE_MASK (3<<16) - - vec2 tex_uv = (vec4(vertex,0.0,1.0) * mat4(light_array.data[light_base].matrix[0],light_array.data[light_base].matrix[1],vec4(0.0,0.0,1.0,0.0),vec4(0.0,0.0,0.0,1.0))).xy; //multiply inverse given its transposed. Optimizer removes useless operations. - uint texture_idx = light_array.data[light_base].flags&LIGHT_FLAGS_TEXTURE_MASK; - vec4 light_color = texture(sampler2D(light_textures[texture_idx],texture_sampler),tex_uv); + vec4 light_color = texture(sampler2D(light_textures[i],texture_sampler),tex_uv); vec4 light_base_color = light_array.data[light_base].color; light_color.rgb*=light_base_color.rgb*light_base_color.a; @@ -526,32 +521,32 @@ FRAGMENT_SHADER_CODE vec4 shadow_uv = vec4(tex_ofs,0.0,distance,1.0); if (shadow_mode==LIGHT_FLAGS_SHADOW_NEAREST) { - shadow = textureProj(sampler2DShadow(shadow_textures[texture_idx],shadow_sampler),shadow_uv).x; + shadow = textureProj(sampler2DShadow(shadow_textures[i],shadow_sampler),shadow_uv).x; } else if (shadow_mode==LIGHT_FLAGS_SHADOW_PCF5) { vec4 shadow_pixel_size = vec4(light_array.data[light_base].shadow_pixel_size,0.0,0.0,0.0); shadow = 0.0; - shadow += textureProj(sampler2DShadow(shadow_textures[texture_idx],shadow_sampler),shadow_uv-shadow_pixel_size*2.0).x; - shadow += textureProj(sampler2DShadow(shadow_textures[texture_idx],shadow_sampler),shadow_uv-shadow_pixel_size).x; - shadow += textureProj(sampler2DShadow(shadow_textures[texture_idx],shadow_sampler),shadow_uv).x; - shadow += textureProj(sampler2DShadow(shadow_textures[texture_idx],shadow_sampler),shadow_uv+shadow_pixel_size).x; - shadow += textureProj(sampler2DShadow(shadow_textures[texture_idx],shadow_sampler),shadow_uv+shadow_pixel_size*2.0).x; + shadow += textureProj(sampler2DShadow(shadow_textures[i],shadow_sampler),shadow_uv-shadow_pixel_size*2.0).x; + shadow += textureProj(sampler2DShadow(shadow_textures[i],shadow_sampler),shadow_uv-shadow_pixel_size).x; + shadow += textureProj(sampler2DShadow(shadow_textures[i],shadow_sampler),shadow_uv).x; + shadow += textureProj(sampler2DShadow(shadow_textures[i],shadow_sampler),shadow_uv+shadow_pixel_size).x; + shadow += textureProj(sampler2DShadow(shadow_textures[i],shadow_sampler),shadow_uv+shadow_pixel_size*2.0).x; shadow/=5.0; - } else if (shadow_mode==LIGHT_FLAGS_SHADOW_PCF13) { + } else { //PCF13 vec4 shadow_pixel_size = vec4(light_array.data[light_base].shadow_pixel_size,0.0,0.0,0.0); shadow = 0.0; - shadow += textureProj(sampler2DShadow(shadow_textures[texture_idx],shadow_sampler),shadow_uv-shadow_pixel_size*6.0).x; - shadow += textureProj(sampler2DShadow(shadow_textures[texture_idx],shadow_sampler),shadow_uv-shadow_pixel_size*5.0).x; - shadow += textureProj(sampler2DShadow(shadow_textures[texture_idx],shadow_sampler),shadow_uv-shadow_pixel_size*4.0).x; - shadow += textureProj(sampler2DShadow(shadow_textures[texture_idx],shadow_sampler),shadow_uv-shadow_pixel_size*3.0).x; - shadow += textureProj(sampler2DShadow(shadow_textures[texture_idx],shadow_sampler),shadow_uv-shadow_pixel_size*2.0).x; - shadow += textureProj(sampler2DShadow(shadow_textures[texture_idx],shadow_sampler),shadow_uv-shadow_pixel_size).x; - shadow += textureProj(sampler2DShadow(shadow_textures[texture_idx],shadow_sampler),shadow_uv).x; - shadow += textureProj(sampler2DShadow(shadow_textures[texture_idx],shadow_sampler),shadow_uv+shadow_pixel_size).x; - shadow += textureProj(sampler2DShadow(shadow_textures[texture_idx],shadow_sampler),shadow_uv+shadow_pixel_size*2.0).x; - shadow += textureProj(sampler2DShadow(shadow_textures[texture_idx],shadow_sampler),shadow_uv+shadow_pixel_size*3.0).x; - shadow += textureProj(sampler2DShadow(shadow_textures[texture_idx],shadow_sampler),shadow_uv+shadow_pixel_size*4.0).x; - shadow += textureProj(sampler2DShadow(shadow_textures[texture_idx],shadow_sampler),shadow_uv+shadow_pixel_size*5.0).x; - shadow += textureProj(sampler2DShadow(shadow_textures[texture_idx],shadow_sampler),shadow_uv+shadow_pixel_size*6.0).x; + shadow += textureProj(sampler2DShadow(shadow_textures[i],shadow_sampler),shadow_uv-shadow_pixel_size*6.0).x; + shadow += textureProj(sampler2DShadow(shadow_textures[i],shadow_sampler),shadow_uv-shadow_pixel_size*5.0).x; + shadow += textureProj(sampler2DShadow(shadow_textures[i],shadow_sampler),shadow_uv-shadow_pixel_size*4.0).x; + shadow += textureProj(sampler2DShadow(shadow_textures[i],shadow_sampler),shadow_uv-shadow_pixel_size*3.0).x; + shadow += textureProj(sampler2DShadow(shadow_textures[i],shadow_sampler),shadow_uv-shadow_pixel_size*2.0).x; + shadow += textureProj(sampler2DShadow(shadow_textures[i],shadow_sampler),shadow_uv-shadow_pixel_size).x; + shadow += textureProj(sampler2DShadow(shadow_textures[i],shadow_sampler),shadow_uv).x; + shadow += textureProj(sampler2DShadow(shadow_textures[i],shadow_sampler),shadow_uv+shadow_pixel_size).x; + shadow += textureProj(sampler2DShadow(shadow_textures[i],shadow_sampler),shadow_uv+shadow_pixel_size*2.0).x; + shadow += textureProj(sampler2DShadow(shadow_textures[i],shadow_sampler),shadow_uv+shadow_pixel_size*3.0).x; + shadow += textureProj(sampler2DShadow(shadow_textures[i],shadow_sampler),shadow_uv+shadow_pixel_size*4.0).x; + shadow += textureProj(sampler2DShadow(shadow_textures[i],shadow_sampler),shadow_uv+shadow_pixel_size*5.0).x; + shadow += textureProj(sampler2DShadow(shadow_textures[i],shadow_sampler),shadow_uv+shadow_pixel_size*6.0).x; shadow/=13.0; } @@ -577,6 +572,7 @@ FRAGMENT_SHADER_CODE } break; } } +#endif frag_color = color; diff --git a/servers/visual/rasterizer/shaders/canvas_occlusion_fix.glsl b/servers/visual/rasterizer/shaders/canvas_occlusion_fix.glsl deleted file mode 100644 index 7c9651201e3..00000000000 --- a/servers/visual/rasterizer/shaders/canvas_occlusion_fix.glsl +++ /dev/null @@ -1,99 +0,0 @@ -/* clang-format off */ -[vertex] -/* clang-format on */ - -#version 450 - -layout(location = 0) out highp float u; - -void main() { - - if (gl_VertexIndex==0) { - u=0.0; - gl_Position=vec4(-1.0,-1.0,0.0,1.0); - } else if (gl_VertexIndex==1) { - u=0.0; - gl_Position=vec4(-1.0,1.0,0.0,1.0); - } else if (gl_VertexIndex==2) { - u=1.0; - gl_Position=vec4(1.0,1.0,0.0,1.0); - } else { - u=1.0; - gl_Position=vec4(1.0,-1.0,0.0,1.0); - } -} - -/* clang-format off */ -[fragment] -/* clang-format on */ - -#version 450 - -#define PI 3.14159265359 - -layout(set=0, binding=0) uniform sampler2D textures[4]; -layout(location = 0) in highp float u; -layout(location = 0) out highp float distance; - -layout(push_constant, binding = 0, std430) uniform Constants { - mat4 projection; - float far; - float pad[3]; -} constants; - -void main() { - - //0-1 in the texture we are writing to represents a circle, 0-2PI) - //obtain the quarter circle from the source textures - float angle=fract(u+1.0-0.125); - - float depth; -#if 0 - if (angle<0.25) { - highp float sub_angle = ((angle/0.25)*2.0-1.0)*(PI/4.0); - highp float x=tan(sub_angle)*0.5+0.5; - depth=texture(textures[0],vec2(x,0.0)).x; - } else if (angle<0.50) { - highp float sub_angle = (((angle-0.25)/0.25)*2.0-1.0)*(PI/4.0); - highp float x=tan(sub_angle)*0.5+0.5; - depth=texture(textures[1],vec2(x,0.0)).x; - } else if (angle<0.75) { - highp float sub_angle = (((angle-0.5)/0.25)*2.0-1.0)*(PI/4.0); - highp float x=tan(sub_angle)*0.5+0.5; - depth=texture(textures[2],vec2(x,0.0)).x; - } else { - highp float sub_angle = (((angle-0.75)/0.25)*2.0-1.0)*(PI/4.0); - highp float x=tan(sub_angle)*0.5+0.5; - depth=texture(textures[3],vec2(x,0.0)).x; - } -#else - if (angle<0.25) { - highp float sub_angle = ((angle/0.25)*2.0-1.0)*(PI/4.0); - vec2 pos = vec2(cos(sub_angle),sin(sub_angle))*constants.far; - vec4 proj = constants.projection * vec4(pos,0.0,1.0); - float coord = (proj.x/proj.w)*0.5+0.5; - depth=texture(textures[0],vec2(coord,0.0)).x; - } else if (angle<0.50) { - highp float sub_angle = (((angle-0.25)/0.25)*2.0-1.0)*(PI/4.0); - vec2 pos = vec2(cos(sub_angle),sin(sub_angle))*constants.far; - vec4 proj = constants.projection * vec4(pos,0.0,1.0); - float coord = (proj.x/proj.w)*0.5+0.5; - depth=texture(textures[1],vec2(coord,0.0)).x; - } else if (angle<0.75) { - highp float sub_angle = (((angle-0.5)/0.25)*2.0-1.0)*(PI/4.0); - vec2 pos = vec2(cos(sub_angle),sin(sub_angle))*constants.far; - vec4 proj = constants.projection * vec4(pos,0.0,1.0); - float coord = (proj.x/proj.w)*0.5+0.5; - depth=texture(textures[2],vec2(coord,0.0)).x; - } else { - highp float sub_angle = (((angle-0.75)/0.25)*2.0-1.0)*(PI/4.0); - vec2 pos = vec2(cos(sub_angle),sin(sub_angle))*constants.far; - vec4 proj = constants.projection * vec4(pos,0.0,1.0); - float coord = (proj.x/proj.w)*0.5+0.5; - depth=texture(textures[3],vec2(coord,0.0)).x; - } - - -#endif - distance=depth; -} diff --git a/servers/visual/rasterizer/shaders/canvas_uniforms_inc.glsl b/servers/visual/rasterizer/shaders/canvas_uniforms_inc.glsl index 36a86c7f63f..7b2ec81fb1d 100644 --- a/servers/visual/rasterizer/shaders/canvas_uniforms_inc.glsl +++ b/servers/visual/rasterizer/shaders/canvas_uniforms_inc.glsl @@ -1,11 +1,8 @@ -/* SET0: Per draw primitive settings */ +/* SET0: Draw Primitive */ #define M_PI 3.14159265359 -#define MAX_LIGHT_TEXTURES 1024 -#define MAX_RENDER_LIGHTS 256 - #define FLAGS_INSTANCING_STRIDE_MASK 0xF #define FLAGS_INSTANCING_ENABLED (1<<4) #define FLAGS_INSTANCING_HAS_COLORS (1 << 5) @@ -64,22 +61,10 @@ layout(set = 0, binding = 5) uniform textureBuffer instancing_buffer; // -/* SET2: Is the skeleton */ +/* SET2: Canvas Item State */ -#ifdef USE_ATTRIBUTES -layout(set = 2, binding = 0) uniform textureBuffer skeleton_buffer; - -layout(set = 2, binding = 1, std140) uniform SkeletonData { - mat4 skeleton_transform; //in world coordinates - mat4 skeleton_transform_inverse; -} skeleton_data; - -#endif - -/* SET3: Per Scene settings */ - -layout(set = 3, binding = 0, std140) uniform CanvasData { +layout(set = 2, binding = 0, std140) uniform CanvasData { mat4 canvas_transform; mat4 screen_transform; mat4 canvas_normal_transform; @@ -87,7 +72,19 @@ layout(set = 3, binding = 0, std140) uniform CanvasData { //uint light_count; } canvas_data; -#define LIGHT_FLAGS_TEXTURE_MASK 0xFFFF +layout(set = 2, binding = 1) uniform textureBuffer skeleton_buffer; + +layout(set = 2, binding = 2, std140) uniform SkeletonData { + mat4 skeleton_transform; //in world coordinates + mat4 skeleton_transform_inverse; +} skeleton_data; + + + +/* SET3: Lighting */ + +#ifdef USE_LIGHTING + #define LIGHT_FLAGS_BLEND_MASK (3<<16) #define LIGHT_FLAGS_BLEND_MODE_ADD (0<<16) #define LIGHT_FLAGS_BLEND_MODE_SUB (1<<16) @@ -109,17 +106,19 @@ struct Light { vec2 position; uint flags; //index to light texture float height; - float shadow_softness; float shadow_pixel_size; float pad0; float pad1; + float pad2; }; -layout(set = 3, binding = 1, std140) uniform LightData { - Light data[MAX_RENDER_LIGHTS]; +layout(set = 3, binding = 0, std140) uniform LightData { + Light data[MAX_LIGHTS]; } light_array; -layout(set = 3, binding = 2) uniform texture2D light_textures[MAX_LIGHT_TEXTURES]; -layout(set = 3, binding = 3) uniform texture2D shadow_textures[MAX_LIGHT_TEXTURES]; +layout(set = 3, binding = 1) uniform texture2D light_textures[MAX_LIGHT_TEXTURES]; +layout(set = 3, binding = 2) uniform texture2D shadow_textures[MAX_LIGHT_TEXTURES]; -layout(set = 3, binding = 4) uniform sampler shadow_sampler; +layout(set = 3, binding = 3) uniform sampler shadow_sampler; + +#endif diff --git a/servers/visual/rendering_device.h b/servers/visual/rendering_device.h index 8f0578b8747..11a3e7e0526 100644 --- a/servers/visual/rendering_device.h +++ b/servers/visual/rendering_device.h @@ -334,6 +334,7 @@ public: } }; + struct TextureView { DataFormat format_override; TextureSwizzle swizzle_r; @@ -352,6 +353,8 @@ public: virtual RID texture_create(const TextureFormat &p_format, const TextureView &p_view, const Vector > &p_data = Vector >()) = 0; virtual RID texture_create_shared(const TextureView &p_view, RID p_with_texture) = 0; + virtual RID texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture,int p_layer,int p_mipmap) = 0; + virtual Error texture_update(RID p_texture, uint32_t p_layer, const PoolVector &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 texture_get_data(RID p_texture, uint32_t p_layer) = 0; // CPU textures will return immediately, while GPU textures will most likely force a flush @@ -373,6 +376,7 @@ public: // This ID is warranted to be unique for the same formats, does not need to be freed virtual FramebufferFormatID framebuffer_format_create(const Vector &p_format) = 0; + virtual TextureSamples framebuffer_format_get_texture_samples(FramebufferFormatID p_format) =0; virtual RID framebuffer_create(const Vector &p_texture_attachments, FramebufferFormatID p_format_check = INVALID_ID) = 0; @@ -865,12 +869,49 @@ public: virtual void draw_list_end() = 0; + /***************/ /**** FREE! ****/ /***************/ virtual void free(RID p_id) = 0; + /****************/ + /**** LIMITS ****/ + /****************/ + + enum Limit { + LIMIT_MAX_BOUND_UNIFORM_SETS, + LIMIT_MAX_FRAMEBUFFER_COLOR_ATTACHMENTS, + LIMIT_MAX_TEXTURES_PER_UNIFORM_SET, + LIMIT_MAX_SAMPLERS_PER_UNIFORM_SET, + LIMIT_MAX_STORAGE_BUFFERS_PER_UNIFORM_SET, + LIMIT_MAX_STORAGE_IMAGES_PER_UNIFORM_SET, + LIMIT_MAX_UNIFORM_BUFFERS_PER_UNIFORM_SET, + LIMIT_MAX_DRAW_INDEXED_INDEX, + LIMIT_MAX_FRAMEBUFFER_HEIGHT, + LIMIT_MAX_FRAMEBUFFER_WIDTH, + LIMIT_MAX_TEXTURE_ARRAY_LAYERS, + LIMIT_MAX_TEXTURE_SIZE_1D, + LIMIT_MAX_TEXTURE_SIZE_2D, + LIMIT_MAX_TEXTURE_SIZE_3D, + LIMIT_MAX_TEXTURE_SIZE_CUBE, + LIMIT_MAX_TEXTURES_PER_SHADER_STAGE, + LIMIT_MAX_SAMPLERS_PER_SHADER_STAGE, + LIMIT_MAX_STORAGE_BUFFERS_PER_SHADER_STAGE, + LIMIT_MAX_STORAGE_IMAGES_PER_SHADER_STAGE, + LIMIT_MAX_UNIFORM_BUFFERS_PER_SHADER_STAGE, + LIMIT_MAX_PUSH_CONSTANT_SIZE, + LIMIT_MAX_UNIFORM_BUFFER_SIZE, + LIMIT_MAX_VERTEX_INPUT_ATTRIBUTE_OFFSET, + LIMIT_MAX_VERTEX_INPUT_ATTRIBUTES, + LIMIT_MAX_VERTEX_INPUT_BINDINGS, + LIMIT_MAX_VERTEX_INPUT_BINDING_STRIDE, + LIMIT_MIN_UNIFORM_BUFFER_OFFSET_ALIGNMENT , + }; + + virtual int limit_get(Limit p_limit) =0; + //methods below not exposed, used by RenderingDeviceRD virtual void prepare_screen_for_drawing() =0; virtual void finalize_frame() = 0; diff --git a/servers/visual/visual_server_canvas.cpp b/servers/visual/visual_server_canvas.cpp index 886fa28d904..ad13f9af0e5 100644 --- a/servers/visual/visual_server_canvas.cpp +++ b/servers/visual/visual_server_canvas.cpp @@ -65,14 +65,13 @@ void VisualServerCanvas::_render_canvas_item_tree(RID p_to_render_target, Canvas VSG::canvas_render->canvas_render_items(p_to_render_target, list, p_modulate, p_lights, p_transform); } -void _collect_ysort_children(VisualServerCanvas::Item *p_canvas_item, Transform2D p_transform, VisualServerCanvas::Item *p_material_owner, const Color p_modulate, VisualServerCanvas::Item **r_items, int &r_index) { +void _collect_ysort_children(VisualServerCanvas::Item *p_canvas_item, Transform2D p_transform, VisualServerCanvas::Item *p_material_owner, VisualServerCanvas::Item **r_items, int &r_index) { int child_item_count = p_canvas_item->child_items.size(); VisualServerCanvas::Item **child_items = p_canvas_item->child_items.ptrw(); for (int i = 0; i < child_item_count; i++) { if (child_items[i]->visible) { if (r_items) { r_items[r_index] = child_items[i]; - child_items[i]->ysort_modulate = p_modulate; child_items[i]->ysort_xform = p_transform; child_items[i]->ysort_pos = p_transform.xform(child_items[i]->xform.elements[2]); child_items[i]->material_owner = child_items[i]->use_parent_material ? p_material_owner : NULL; @@ -81,11 +80,7 @@ void _collect_ysort_children(VisualServerCanvas::Item *p_canvas_item, Transform2 r_index++; if (child_items[i]->sort_y) - _collect_ysort_children(child_items[i], - p_transform * child_items[i]->xform, - child_items[i]->use_parent_material ? p_material_owner : child_items[i], - p_modulate * child_items[i]->modulate, - r_items, r_index); + _collect_ysort_children(child_items[i], p_transform * child_items[i]->xform, child_items[i]->use_parent_material ? p_material_owner : child_items[i], r_items, r_index); } } } @@ -146,14 +141,14 @@ void VisualServerCanvas::_cull_canvas_item(Item *p_canvas_item, const Transform2 if (ci->ysort_children_count == -1) { ci->ysort_children_count = 0; - _collect_ysort_children(ci, Transform2D(), p_material_owner, Color(1, 1, 1, 1), NULL, ci->ysort_children_count); + _collect_ysort_children(ci, Transform2D(), p_material_owner, NULL, ci->ysort_children_count); } child_item_count = ci->ysort_children_count; child_items = (Item **)alloca(child_item_count * sizeof(Item *)); int i = 0; - _collect_ysort_children(ci, Transform2D(), p_material_owner, Color(1, 1, 1, 1), child_items, i); + _collect_ysort_children(ci, Transform2D(), p_material_owner, child_items, i); SortArray sorter; sorter.sort(child_items, child_item_count); @@ -169,7 +164,7 @@ void VisualServerCanvas::_cull_canvas_item(Item *p_canvas_item, const Transform2 if (!child_items[i]->behind || (ci->sort_y && child_items[i]->sort_y)) continue; if (ci->sort_y) { - _cull_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate * child_items[i]->ysort_modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner); + _cull_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner); } else { _cull_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner); } @@ -213,7 +208,7 @@ void VisualServerCanvas::_cull_canvas_item(Item *p_canvas_item, const Transform2 if (child_items[i]->behind || (ci->sort_y && child_items[i]->sort_y)) continue; if (ci->sort_y) { - _cull_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate * child_items[i]->ysort_modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner); + _cull_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner); } else { _cull_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner); } @@ -835,7 +830,7 @@ void VisualServerCanvas::canvas_item_add_triangle_array(RID p_item, const Vector ERR_FAIL_COND(!p_bones.empty() && p_bones.size() != vertex_count * 4); ERR_FAIL_COND(!p_weights.empty() && p_weights.size() != vertex_count * 4); - const Vector &indices = p_indices; + Vector indices = p_indices; Item::CommandPolygon *polygon = canvas_item->alloc_command(); ERR_FAIL_COND(!polygon); @@ -1057,6 +1052,7 @@ void VisualServerCanvas::canvas_light_set_texture(RID p_light, RID p_texture) { ERR_FAIL_COND(!clight); clight->texture = p_texture; + clight->version++; VSG::canvas_render->light_set_texture(clight->light_internal, p_texture); } void VisualServerCanvas::canvas_light_set_texture_offset(RID p_light, const Vector2 &p_offset) { @@ -1134,7 +1130,7 @@ void VisualServerCanvas::canvas_light_set_shadow_enabled(RID p_light, bool p_ena return; } clight->use_shadow = p_enabled; - + clight->version++; VSG::canvas_render->light_set_use_shadow(clight->light_internal, clight->use_shadow, clight->shadow_buffer_size); } @@ -1150,19 +1146,11 @@ void VisualServerCanvas::canvas_light_set_shadow_buffer_size(RID p_light, int p_ return; clight->shadow_buffer_size = next_power_of_2(p_size); + clight->version++; VSG::canvas_render->light_set_use_shadow(clight->light_internal, clight->use_shadow, clight->shadow_buffer_size); } -void VisualServerCanvas::canvas_light_set_shadow_gradient_length(RID p_light, float p_length) { - - ERR_FAIL_COND(p_length < 0); - - RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); - ERR_FAIL_COND(!clight); - - clight->shadow_gradient_length = p_length; -} void VisualServerCanvas::canvas_light_set_shadow_filter(RID p_light, VS::CanvasLightShadowFilter p_filter) { RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); diff --git a/servers/visual/visual_server_canvas.h b/servers/visual/visual_server_canvas.h index b76987d341e..e508d5a8b12 100644 --- a/servers/visual/visual_server_canvas.h +++ b/servers/visual/visual_server_canvas.h @@ -245,7 +245,6 @@ public: void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled); void canvas_light_set_shadow_buffer_size(RID p_light, int p_size); - void canvas_light_set_shadow_gradient_length(RID p_light, float p_length); void canvas_light_set_shadow_filter(RID p_light, VS::CanvasLightShadowFilter p_filter); void canvas_light_set_shadow_color(RID p_light, const Color &p_color); void canvas_light_set_shadow_smooth(RID p_light, float p_smooth); diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index 941ece8b537..08a8c3f02d5 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -659,7 +659,6 @@ public: BIND2(canvas_light_set_shadow_enabled, RID, bool) BIND2(canvas_light_set_shadow_buffer_size, RID, int) - BIND2(canvas_light_set_shadow_gradient_length, RID, float) BIND2(canvas_light_set_shadow_filter, RID, CanvasLightShadowFilter) BIND2(canvas_light_set_shadow_color, RID, const Color &) BIND2(canvas_light_set_shadow_smooth, RID, float) diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index 9dc2a94251f..7ccd75dcffb 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -572,7 +572,6 @@ public: FUNC2(canvas_light_set_shadow_enabled, RID, bool) FUNC2(canvas_light_set_shadow_buffer_size, RID, int) - FUNC2(canvas_light_set_shadow_gradient_length, RID, float) FUNC2(canvas_light_set_shadow_filter, RID, CanvasLightShadowFilter) FUNC2(canvas_light_set_shadow_color, RID, const Color &) FUNC2(canvas_light_set_shadow_smooth, RID, float) diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index d5d2e87f234..04c726716bc 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -1977,7 +1977,6 @@ void VisualServer::_bind_methods() { ClassDB::bind_method(D_METHOD("canvas_light_set_mode", "light", "mode"), &VisualServer::canvas_light_set_mode); ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_enabled", "light", "enabled"), &VisualServer::canvas_light_set_shadow_enabled); ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_buffer_size", "light", "size"), &VisualServer::canvas_light_set_shadow_buffer_size); - ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_gradient_length", "light", "length"), &VisualServer::canvas_light_set_shadow_gradient_length); ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_filter", "light", "filter"), &VisualServer::canvas_light_set_shadow_filter); ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_color", "light", "color"), &VisualServer::canvas_light_set_shadow_color); ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_smooth", "light", "smooth"), &VisualServer::canvas_light_set_shadow_smooth); diff --git a/servers/visual_server.h b/servers/visual_server.h index b41cc0812a2..ea1818ea9f7 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -964,7 +964,6 @@ public: virtual void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled) = 0; virtual void canvas_light_set_shadow_buffer_size(RID p_light, int p_size) = 0; - virtual void canvas_light_set_shadow_gradient_length(RID p_light, float p_length) = 0; virtual void canvas_light_set_shadow_filter(RID p_light, CanvasLightShadowFilter p_filter) = 0; virtual void canvas_light_set_shadow_color(RID p_light, const Color &p_color) = 0; virtual void canvas_light_set_shadow_smooth(RID p_light, float p_smooth) = 0;