Modified light rendering to make it more compatible.

Modified polygon management to make it more compatible with MoltenVK
This commit is contained in:
Juan Linietsky 2019-07-10 17:44:55 -03:00
parent a3f8ffac63
commit ef083a583b
23 changed files with 682 additions and 498 deletions

View file

@ -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<uint8_t> &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<FramebufferFormatID, FramebufferFormat>::Element *E = framebuffer_formats.find(p_format);
ERR_FAIL_COND_V(!E, TEXTURE_SAMPLES_1);
return E->get().samples;
}
/***********************/
/**** RENDER TARGET ****/
/***********************/
@ -5689,6 +5784,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

View file

@ -234,6 +234,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
const Map<FramebufferFormatKey, FramebufferFormatID>::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<FramebufferFormatID, FramebufferFormat> 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<PoolVector<uint8_t> > &p_data = Vector<PoolVector<uint8_t> >());
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<uint8_t> &p_data, bool p_sync_with_draw = false);
virtual PoolVector<uint8_t> texture_get_data(RID p_texture, uint32_t p_layer);
@ -725,7 +727,8 @@ public:
/**** FRAMEBUFFER ****/
/*********************/
FramebufferFormatID framebuffer_format_create(const Vector<AttachmentFormat> &p_format);
virtual FramebufferFormatID framebuffer_format_create(const Vector<AttachmentFormat> &p_format);
virtual TextureSamples framebuffer_format_get_texture_samples(FramebufferFormatID p_format);
virtual RID framebuffer_create(const Vector<RID> &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();

View file

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

View file

@ -296,17 +296,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;
@ -427,9 +416,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);
@ -456,7 +442,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");
@ -488,7 +473,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;

View file

@ -70,7 +70,6 @@ private:
int item_shadow_mask;
int shadow_buffer_size;
float shadow_smooth;
float shadow_gradient_length;
Mode mode;
Ref<Texture2D> texture;
Vector2 texture_offset;
@ -147,9 +146,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;

View file

@ -618,7 +618,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;
@ -638,10 +637,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);
@ -661,7 +662,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;
@ -1064,6 +1064,13 @@ public:
return command;
}
struct CustomData {
virtual ~CustomData() {}
};
mutable CustomData *custom_data; //implementation dependent
void clear() {
Command *c = commands;
while (c) {
@ -1112,6 +1119,7 @@ public:
light_masked = false;
update_when_visible = false;
z_final = 0;
custom_data = NULL;
}
virtual ~Item() {
clear();
@ -1119,6 +1127,9 @@ public:
memfree(blocks[i].memory);
}
if (copy_back_buffer) memdelete(copy_back_buffer);
if (custom_data) {
memdelete(custom_data);
}
}
};

View file

@ -225,42 +225,34 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int
// that need to be created for these formats.
uint32_t vertex_count = p_points.size();
uint32_t base_offset = 0;
uint32_t stride = 2; //vertices always repeat
if ((uint32_t)p_colors.size() == vertex_count) {
if ((uint32_t)p_colors.size() == vertex_count || p_colors.size() == 1) {
stride += 4;
} else {
base_offset += 4;
}
if ((uint32_t)p_uvs.size() == vertex_count) {
stride += 2;
} else {
base_offset += 2;
}
if ((uint32_t)p_bones.size() == vertex_count * 4) {
stride += 4;
} else {
base_offset += 4;
}
if ((uint32_t)p_weights.size() == vertex_count * 4) {
stride += 4;
} else {
base_offset += 4;
}
uint32_t buffer_size = base_offset + stride * p_points.size();
uint32_t buffer_size = stride * p_points.size();
PoolVector<uint8_t> polygon_buffer;
polygon_buffer.resize(buffer_size * sizeof(float));
Vector<RD::VertexDescription> descriptions;
descriptions.resize(5);
Vector<RID> buffers;
buffers.resize(5);
{
PoolVector<uint8_t>::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 Vector<int
}
//colors
if ((uint32_t)p_colors.size() == vertex_count) {
if ((uint32_t)p_colors.size() == vertex_count || p_colors.size() == 1) {
RD::VertexDescription vd;
vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
vd.offset = base_offset * sizeof(float);
@ -290,31 +282,34 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int
descriptions.write[1] = vd;
const Color *color_ptr = p_colors.ptr();
if (p_colors.size() == 1) {
Color color = p_colors[0];
for (uint32_t i = 0; i < vertex_count; i++) {
fptr[base_offset + i * stride + 0] = color.r;
fptr[base_offset + i * stride + 1] = color.g;
fptr[base_offset + i * stride + 2] = color.b;
fptr[base_offset + i * stride + 3] = color.a;
}
} else {
const Color *color_ptr = p_colors.ptr();
for (uint32_t i = 0; i < vertex_count; i++) {
fptr[base_offset + i * stride + 0] = color_ptr[i].r;
fptr[base_offset + i * stride + 1] = color_ptr[i].g;
fptr[base_offset + i * stride + 2] = color_ptr[i].b;
fptr[base_offset + i * stride + 3] = color_ptr[i].a;
for (uint32_t i = 0; i < vertex_count; i++) {
fptr[base_offset + i * stride + 0] = color_ptr[i].r;
fptr[base_offset + i * stride + 1] = color_ptr[i].g;
fptr[base_offset + i * stride + 2] = color_ptr[i].b;
fptr[base_offset + i * stride + 3] = color_ptr[i].a;
}
}
base_offset += 4;
} else {
RD::VertexDescription vd;
vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
vd.offset = single_offset * sizeof(float);
vd.offset = 0;
vd.location = VS::ARRAY_COLOR;
vd.stride = 0;
descriptions.write[1] = vd;
Color color = p_colors.size() ? p_colors[0] : Color(1, 1, 1, 1);
fptr[single_offset + 0] = color.r;
fptr[single_offset + 1] = color.g;
fptr[single_offset + 2] = color.b;
fptr[single_offset + 3] = color.a;
single_offset += 4;
buffers.write[1] = polygon_buffers.default_color_buffer;
}
//uvs
@ -337,17 +332,12 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int
} else {
RD::VertexDescription vd;
vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
vd.offset = single_offset * sizeof(float);
vd.offset = 0;
vd.location = VS::ARRAY_TEX_UV;
vd.stride = 0;
descriptions.write[2] = vd;
Vector2 uv;
fptr[single_offset + 0] = uv.x;
fptr[single_offset + 1] = uv.y;
single_offset += 2;
buffers.write[2] = polygon_buffers.default_uv_buffer;
}
//bones
@ -373,17 +363,12 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int
} else {
RD::VertexDescription vd;
vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT;
vd.offset = single_offset * sizeof(float);
vd.offset = 0;
vd.location = VS::ARRAY_BONES;
vd.stride = 0;
descriptions.write[3] = vd;
uptr[single_offset + 0] = 0;
uptr[single_offset + 1] = 0;
uptr[single_offset + 2] = 0;
uptr[single_offset + 3] = 0;
single_offset += 4;
buffers.write[3] = polygon_buffers.default_bone_buffer;
}
//bones
@ -409,22 +394,16 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int
} else {
RD::VertexDescription vd;
vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
vd.offset = single_offset * sizeof(float);
vd.offset = 0;
vd.location = VS::ARRAY_WEIGHTS;
vd.stride = 0;
descriptions.write[4] = vd;
fptr[single_offset + 0] = 0.0;
fptr[single_offset + 1] = 0.0;
fptr[single_offset + 2] = 0.0;
fptr[single_offset + 3] = 0.0;
single_offset += 4;
buffers.write[4] = polygon_buffers.default_weight_buffer;
}
//check that everything is as it should be
ERR_FAIL_COND_V(single_offset != (base_offset - stride), 0);
ERR_FAIL_COND_V(((base_offset - stride) + stride * vertex_count) != buffer_size, 0);
ERR_FAIL_COND_V(base_offset != stride, 0); //bug
}
RD::VertexFormatID vertex_id = RD::get_singleton()->vertex_format_create(descriptions);
@ -432,11 +411,12 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int
PolygonBuffers pb;
pb.vertex_buffer = RD::get_singleton()->vertex_buffer_create(polygon_buffer.size(), polygon_buffer);
Vector<RID> 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 *&current_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 *&current_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<RD::Uniform> 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<RD::Uniform> 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<RD::Uniform> 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<String> 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<RD::AttachmentFormat> 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<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;
}
@ -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<RD::Uniform> 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<Vector2>());
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

View file

@ -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<PolygonID, PolygonBuffers> 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<OccluderPolygon> 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 *&current_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 *&current_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);

View file

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

View file

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

View file

@ -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<String> &p_variant_defines) {
void ShaderRD::initialize(const Vector<String> &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());

View file

@ -44,6 +44,7 @@
class ShaderRD {
//versions
CharString general_defines;
Vector<CharString> variant_defines;
int vertex_code_start;
@ -114,7 +115,7 @@ public:
bool version_free(RID p_version);
void initialize(const Vector<String> &p_variant_defines);
void initialize(const Vector<String> &p_variant_defines, const String &p_general_defines = "");
virtual ~ShaderRD();
};

View file

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

View file

@ -426,8 +426,11 @@ FRAGMENT_SHADER_CODE
}
color*=canvas_data.canvas_modulation;
for(uint i=0;i<light_count;i++) {
#ifdef USE_LIGHTING
for(uint i=0;i<MAX_LIGHT_TEXTURES;i++) {
if (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;

View file

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

View file

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

View file

@ -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<PoolVector<uint8_t> > &p_data = Vector<PoolVector<uint8_t> >()) = 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<uint8_t> &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> 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<AttachmentFormat> &p_format) = 0;
virtual TextureSamples framebuffer_format_get_texture_samples(FramebufferFormatID p_format) =0;
virtual RID framebuffer_create(const Vector<RID> &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;

View file

@ -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<Item *, ItemPtrSort> 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<int> &indices = p_indices;
Vector<int> indices = p_indices;
Item::CommandPolygon *polygon = canvas_item->alloc_command<Item::CommandPolygon>();
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);

View file

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

View file

@ -658,7 +658,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)

View file

@ -571,7 +571,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)

View file

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

View file

@ -965,7 +965,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;