Removed canvas lights and shadows.

This commit is contained in:
Relintai 2023-12-15 18:53:27 +01:00
parent 219534c1ae
commit d821a15748
22 changed files with 30 additions and 2869 deletions

View File

@ -404,15 +404,8 @@ public:
void render_target_set_use_debanding(RID p_render_target, bool p_debanding) {}
void render_target_set_sharpen_intensity(RID p_render_target, float p_intensity) {}
/* CANVAS SHADOW */
RID canvas_light_shadow_buffer_create(int p_width) { return RID(); }
/* LIGHT SHADOW MAPPING */
RID canvas_light_occluder_create() { return RID(); }
void canvas_light_occluder_set_polylines(RID p_occluder, const PoolVector<Vector2> &p_lines) {}
RS::InstanceType get_base_type(RID p_rid) const {
if (mesh_owner.owns(p_rid)) {
return RS::INSTANCE_MESH;
@ -461,17 +454,10 @@ public:
class RasterizerCanvasDummy : public RasterizerCanvas {
public:
RID light_internal_create() { return RID(); }
void light_internal_update(RID p_rid, Light *p_light) {}
void light_internal_free(RID p_rid) {}
void canvas_begin(){};
void canvas_end(){};
void canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light, const Transform2D &p_transform){};
void canvas_debug_viewport_shadows(Light *p_lights_with_shadow){};
void canvas_light_shadow_buffer_update(RID p_buffer, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders, Projection *p_xform_cache) {}
void canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, const Transform2D &p_transform){};
void reset_canvas() {}

View File

@ -40,21 +40,10 @@
#define glClearDepth glClearDepthf
#endif
RID RasterizerCanvasBaseGLES2::light_internal_create() {
return RID();
}
void RasterizerCanvasBaseGLES2::light_internal_update(RID p_rid, Light *p_light) {
}
void RasterizerCanvasBaseGLES2::light_internal_free(RID p_rid) {
}
void RasterizerCanvasBaseGLES2::canvas_begin() {
state.using_transparent_rt = false;
// always start with light_angle unset
state.using_light_angle = false;
state.using_large_vertex = false;
state.using_modulate = false;
@ -164,11 +153,6 @@ void RasterizerCanvasBaseGLES2::_set_texture_rect_mode(bool p_texture_rect, bool
// always set this directly (this could be state checked)
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, p_texture_rect);
if (state.using_light_angle != p_light_angle) {
state.using_light_angle = p_light_angle;
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_ATTRIB_LIGHT_ANGLE, p_light_angle);
}
if (state.using_modulate != p_modulate) {
state.using_modulate = p_modulate;
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_ATTRIB_MODULATE, p_modulate);
@ -342,39 +326,6 @@ void RasterizerCanvasBaseGLES2::_set_uniforms() {
state.canvas_shader.set_uniform(CanvasShaderGLES2::SCREEN_PIXEL_SIZE, screen_pixel_size);
}
if (state.using_light) {
Light *light = state.using_light;
state.canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_MATRIX, light->light_shader_xform);
Transform2D basis_inverse = light->light_shader_xform.affine_inverse().orthonormalized();
basis_inverse[2] = Vector2();
state.canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_MATRIX_INVERSE, basis_inverse);
state.canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_LOCAL_MATRIX, light->xform_cache.affine_inverse());
state.canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_COLOR, light->color * light->energy);
state.canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_POS, light->light_shader_pos);
state.canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_HEIGHT, light->height);
state.canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_OUTSIDE_ALPHA, light->mode == RS::CANVAS_LIGHT_MODE_MASK ? 1.0 : 0.0);
if (state.using_shadow) {
RasterizerStorageGLES2::CanvasLightShadow *cls = storage->canvas_light_shadow_owner.get(light->shadow_buffer);
WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 5);
glBindTexture(GL_TEXTURE_2D, cls->distance);
state.canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_MATRIX, light->shadow_matrix_cache);
state.canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_SHADOW_COLOR, light->shadow_color);
state.canvas_shader.set_uniform(CanvasShaderGLES2::SHADOWPIXEL_SIZE, (1.0 / light->shadow_buffer_size) * (1.0 + light->shadow_smooth));
if (light->radius_cache == 0) {
state.canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_GRADIENT, 0.0);
} else {
state.canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_GRADIENT, light->shadow_gradient_length / (light->radius_cache * 1.1));
}
state.canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_DISTANCE_MULT, light->radius_cache * 1.1);
/*canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_MATRIX,light->shadow_matrix_cache);
canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_ESM_MULTIPLIER,light->shadow_esm_mult);
canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_SHADOW_COLOR,light->shadow_color);*/
}
}
}
void RasterizerCanvasBaseGLES2::reset_canvas() {
@ -403,9 +354,6 @@ void RasterizerCanvasBaseGLES2::reset_canvas() {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
void RasterizerCanvasBaseGLES2::canvas_debug_viewport_shadows(Light *p_lights_with_shadow) {
}
void RasterizerCanvasBaseGLES2::_copy_texscreen(const Rect2 &p_rect) {
state.canvas_texscreen_used = true;
@ -750,126 +698,6 @@ void RasterizerCanvasBaseGLES2::_copy_screen(const Rect2 &p_rect) {
glEnable(GL_BLEND);
}
void RasterizerCanvasBaseGLES2::canvas_light_shadow_buffer_update(RID p_buffer, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders, Projection *p_xform_cache) {
RasterizerStorageGLES2::CanvasLightShadow *cls = storage->canvas_light_shadow_owner.get(p_buffer);
ERR_FAIL_COND(!cls);
glDisable(GL_BLEND);
glDisable(GL_SCISSOR_TEST);
glDisable(GL_DITHER);
glDisable(GL_CULL_FACE);
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
glDepthMask(true);
glBindFramebuffer(GL_FRAMEBUFFER, cls->fbo);
state.canvas_shadow_shader.set_conditional(CanvasShadowShaderGLES2::USE_RGBA_SHADOWS, storage->config.use_rgba_2d_shadows);
state.canvas_shadow_shader.bind();
glViewport(0, 0, cls->size, cls->height);
glClearDepth(1.0f);
glClearColor(1, 1, 1, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
RS::CanvasOccluderPolygonCullMode cull = RS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED;
for (int i = 0; i < 4; i++) {
//make sure it remains orthogonal, makes easy to read angle later
Transform light;
light.origin[0] = p_light_xform[2][0];
light.origin[1] = p_light_xform[2][1];
light.basis[0][0] = p_light_xform[0][0];
light.basis[0][1] = p_light_xform[1][0];
light.basis[1][0] = p_light_xform[0][1];
light.basis[1][1] = p_light_xform[1][1];
//light.basis.scale(Vector3(to_light.elements[0].length(),to_light.elements[1].length(),1));
//p_near=1;
Projection projection;
{
real_t fov = 90;
real_t nearp = p_near;
real_t farp = p_far;
real_t aspect = 1.0;
real_t ymax = nearp * Math::tan(Math::deg2rad(fov * 0.5));
real_t ymin = -ymax;
real_t xmin = ymin * aspect;
real_t xmax = ymax * aspect;
projection.set_frustum(xmin, xmax, ymin, ymax, nearp, farp);
}
Vector3 cam_target = Basis(Vector3(0, 0, Math_PI * 2 * (i / 4.0))).xform(Vector3(0, 1, 0));
projection = projection * Projection(Transform().looking_at(cam_target, Vector3(0, 0, -1)).affine_inverse());
state.canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES2::PROJECTION_MATRIX, projection);
state.canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES2::LIGHT_MATRIX, light);
state.canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES2::DISTANCE_NORM, 1.0 / p_far);
if (i == 0) {
*p_xform_cache = projection;
}
glViewport(0, (cls->height / 4) * i, cls->size, cls->height / 4);
LightOccluderInstance *instance = p_occluders;
while (instance) {
RasterizerStorageGLES2::CanvasOccluder *cc = storage->canvas_occluder_owner.getornull(instance->polygon_buffer);
if (!cc || cc->len == 0 || !(p_light_mask & instance->light_mask)) {
instance = instance->next;
continue;
}
state.canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES2::WORLD_MATRIX, instance->xform_cache);
RS::CanvasOccluderPolygonCullMode transformed_cull_cache = instance->cull_cache;
if (transformed_cull_cache != RS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED &&
(p_light_xform.basis_determinant() * instance->xform_cache.basis_determinant()) < 0) {
transformed_cull_cache = (transformed_cull_cache == RS::CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE)
? RS::CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE
: RS::CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE;
}
if (cull != transformed_cull_cache) {
cull = transformed_cull_cache;
switch (cull) {
case RS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED: {
glDisable(GL_CULL_FACE);
} break;
case RS::CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE: {
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
} break;
case RS::CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE: {
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
} break;
}
}
glBindBuffer(GL_ARRAY_BUFFER, cc->vertex_id);
glEnableVertexAttribArray(RS::ARRAY_VERTEX);
glVertexAttribPointer(RS::ARRAY_VERTEX, 3, GL_FLOAT, false, 0, nullptr);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cc->index_id);
glDrawElements(GL_TRIANGLES, cc->len * 3, GL_UNSIGNED_SHORT, nullptr);
instance = instance->next;
}
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
void RasterizerCanvasBaseGLES2::draw_lens_distortion_rect(const Rect2 &p_rect, float p_k1, float p_k2, const Vector2 &p_eye_center, float p_oversample) {
Vector2 half_size;
if (storage->frame.current_rt) {
@ -1031,7 +859,6 @@ void RasterizerCanvasBaseGLES2::initialize() {
state.canvas_shader.init();
state.using_light_angle = false;
state.using_large_vertex = false;
state.using_modulate = false;
@ -1044,7 +871,6 @@ void RasterizerCanvasBaseGLES2::initialize() {
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_PIXEL_SNAP, GLOBAL_DEF("rendering/2d/snapping/use_gpu_pixel_snap", false));
state.using_light = nullptr;
state.using_transparent_rt = false;
}

View File

@ -78,7 +78,6 @@ public:
bool using_texture_rect;
bool using_light_angle;
bool using_modulate;
bool using_large_vertex;
@ -89,8 +88,6 @@ public:
RasterizerStorageGLES2::Texture *current_tex_ptr;
Transform vp;
Light *using_light;
bool using_shadow;
bool using_transparent_rt;
} state;
@ -106,10 +103,6 @@ public:
void _set_uniforms();
virtual RID light_internal_create();
virtual void light_internal_update(RID p_rid, Light *p_light);
virtual void light_internal_free(RID p_rid);
virtual void canvas_begin();
virtual void canvas_end();
@ -127,8 +120,6 @@ public:
void draw_lens_distortion_rect(const Rect2 &p_rect, float p_k1, float p_k2, const Vector2 &p_eye_center, float p_oversample);
virtual void reset_canvas();
virtual void canvas_light_shadow_buffer_update(RID p_buffer, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders, Projection *p_xform_cache);
virtual void canvas_debug_viewport_shadows(Light *p_lights_with_shadow);
RasterizerStorageGLES2::Texture *_bind_canvas_texture(const RID &p_texture, const RID &p_normal_map);
void _set_texture_rect_mode(bool p_texture_rect, bool p_light_angle = false, bool p_modulate = false, bool p_large_vertex = false);

View File

@ -1202,24 +1202,23 @@ void RasterizerCanvasGLES2::canvas_begin() {
RasterizerCanvasBaseGLES2::canvas_begin();
}
void RasterizerCanvasGLES2::canvas_render_items_begin(const Color &p_modulate, Light *p_light, const Transform2D &p_base_transform) {
batch_canvas_render_items_begin(p_modulate, p_light, p_base_transform);
void RasterizerCanvasGLES2::canvas_render_items_begin(const Color &p_modulate, const Transform2D &p_base_transform) {
batch_canvas_render_items_begin(p_modulate, p_base_transform);
}
void RasterizerCanvasGLES2::canvas_render_items_end() {
batch_canvas_render_items_end();
}
void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light, const Transform2D &p_base_transform) {
batch_canvas_render_items(p_item_list, p_z, p_modulate, p_light, p_base_transform);
void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, const Transform2D &p_base_transform) {
batch_canvas_render_items(p_item_list, p_z, p_modulate, p_base_transform);
}
void RasterizerCanvasGLES2::canvas_render_items_implementation(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light, const Transform2D &p_base_transform) {
void RasterizerCanvasGLES2::canvas_render_items_implementation(Item *p_item_list, int p_z, const Color &p_modulate, const Transform2D &p_base_transform) {
// parameters are easier to pass around in a structure
RenderItemState ris;
ris.item_group_z = p_z;
ris.item_group_modulate = p_modulate;
ris.item_group_light = p_light;
ris.item_group_base_transform = p_base_transform;
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_SKELETON, false);
@ -1412,105 +1411,6 @@ bool RasterizerCanvasGLES2::try_join_item(Item *p_ci, RenderItemState &r_ris, bo
}
}
if ((blend_mode == RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_MIX || blend_mode == RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_PMALPHA) && r_ris.item_group_light && !unshaded) {
// we cannot join lit items easily.
// it is possible, but not if they overlap, because
// a + light_blend + b + light_blend IS NOT THE SAME AS
// a + b + light_blend
bool light_allow_join = true;
// this is a quick getout if we have turned off light joining
if ((bdata.settings_light_max_join_items == 0) || r_ris.light_region.too_many_lights) {
light_allow_join = false;
} else {
// do light joining...
// first calculate the light bitfield
uint64_t light_bitfield = 0;
uint64_t shadow_bitfield = 0;
Light *light = r_ris.item_group_light;
int light_count = -1;
while (light) {
light_count++;
uint64_t light_bit = 1ULL << light_count;
// note that as a cost of batching, the light culling will be less effective
if (p_ci->light_mask & light->item_mask && r_ris.item_group_z >= light->z_min && r_ris.item_group_z <= light->z_max) {
// Note that with the above test, it is possible to also include a bound check.
// Tests so far have indicated better performance without it, but there may be reason to change this at a later stage,
// so I leave the line here for reference:
// && p_ci->global_rect_cache.intersects_transformed(light->xform_cache, light->rect_cache)) {
light_bitfield |= light_bit;
bool has_shadow = light->shadow_buffer.is_valid() && p_ci->light_mask & light->item_shadow_mask;
if (has_shadow) {
shadow_bitfield |= light_bit;
}
}
light = light->next_ptr;
}
// now compare to previous
if ((r_ris.light_region.light_bitfield != light_bitfield) || (r_ris.light_region.shadow_bitfield != shadow_bitfield)) {
light_allow_join = false;
r_ris.light_region.light_bitfield = light_bitfield;
r_ris.light_region.shadow_bitfield = shadow_bitfield;
} else {
// only do these checks if necessary
if (join && (!r_batch_break)) {
// we still can't join, even if the lights are exactly the same, if there is overlap between the previous and this item
if (r_ris.joined_item && light_bitfield) {
if ((int)r_ris.joined_item->num_item_refs <= bdata.settings_light_max_join_items) {
for (uint32_t r = 0; r < r_ris.joined_item->num_item_refs; r++) {
Item *pRefItem = bdata.item_refs[r_ris.joined_item->first_item_ref + r].item;
if (p_ci->global_rect_cache.intersects(pRefItem->global_rect_cache)) {
light_allow_join = false;
break;
}
}
#ifdef DEBUG_ENABLED
if (light_allow_join) {
bdata.stats_light_items_joined++;
}
#endif
} // if below max join items
else {
// just don't allow joining if above overlap check max items
light_allow_join = false;
}
}
} // if not batch broken already (no point in doing expensive overlap tests if not needed)
} // if bitfields don't match
} // if do light joining
if (!light_allow_join) {
// can't join
join = false;
// we also dont want to allow joining this item with the next item, because the next item could have no lights!
r_batch_break = true;
}
} else {
// if the last item had lights, we should not join it to this one (which has no lights)
if (r_ris.light_region.light_bitfield || r_ris.light_region.shadow_bitfield) {
join = false;
// setting these to zero ensures that any following item with lights will, by definition,
// be affected by a different set of lights, and thus prevent a join
r_ris.light_region.light_bitfield = 0;
r_ris.light_region.shadow_bitfield = 0;
}
}
if (reclip) {
join = false;
}
@ -1724,123 +1624,6 @@ void RasterizerCanvasGLES2::_legacy_canvas_render_item(Item *p_ci, RenderItemSta
r_ris.rebind_shader = true; // hacked in for now.
if ((blend_mode == RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_MIX || blend_mode == RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_PMALPHA) && r_ris.item_group_light && !unshaded) {
Light *light = r_ris.item_group_light;
bool light_used = false;
RS::CanvasLightMode mode = RS::CANVAS_LIGHT_MODE_ADD;
state.uniforms.final_modulate = p_ci->final_modulate; // remove the canvas modulate
while (light) {
if (p_ci->light_mask & light->item_mask && r_ris.item_group_z >= light->z_min && r_ris.item_group_z <= light->z_max && p_ci->global_rect_cache.intersects_transformed(light->xform_cache, light->rect_cache)) {
//intersects this light
if (!light_used || mode != light->mode) {
mode = light->mode;
switch (mode) {
case RS::CANVAS_LIGHT_MODE_ADD: {
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
} break;
case RS::CANVAS_LIGHT_MODE_SUB: {
glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
} break;
case RS::CANVAS_LIGHT_MODE_MIX:
case RS::CANVAS_LIGHT_MODE_MASK: {
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
} break;
}
}
if (!light_used) {
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_LIGHTING, true);
light_used = true;
}
bool has_shadow = light->shadow_buffer.is_valid() && p_ci->light_mask & light->item_shadow_mask;
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_SHADOWS, has_shadow);
if (has_shadow) {
state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_USE_GRADIENT, light->shadow_gradient_length > 0);
state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_NEAREST, light->shadow_filter == RS::CANVAS_LIGHT_FILTER_NONE);
state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF3, light->shadow_filter == RS::CANVAS_LIGHT_FILTER_PCF3);
state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF5, light->shadow_filter == RS::CANVAS_LIGHT_FILTER_PCF5);
state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF7, light->shadow_filter == RS::CANVAS_LIGHT_FILTER_PCF7);
state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF9, light->shadow_filter == RS::CANVAS_LIGHT_FILTER_PCF9);
state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF13, light->shadow_filter == RS::CANVAS_LIGHT_FILTER_PCF13);
}
state.canvas_shader.bind();
state.using_light = light;
state.using_shadow = has_shadow;
//always re-set uniforms, since light parameters changed
_set_uniforms();
state.canvas_shader.use_material((void *)material_ptr);
WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 6);
RasterizerStorageGLES2::Texture *t = storage->texture_owner.getornull(light->texture);
if (!t) {
glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
} else {
t = t->get_ptr();
glBindTexture(t->target, t->tex_id);
}
WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
_legacy_canvas_item_render_commands(p_ci, nullptr, reclip, material_ptr); //redraw using light
state.using_light = nullptr;
}
light = light->next_ptr;
}
if (light_used) {
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_LIGHTING, false);
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_SHADOWS, false);
state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_NEAREST, false);
state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF3, false);
state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF5, false);
state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF7, false);
state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF9, false);
state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF13, false);
state.canvas_shader.bind();
r_ris.last_blend_mode = -1;
/*
//this is set again, so it should not be needed anyway?
state.canvas_item_modulate = unshaded ? ci->final_modulate : Color(
ci->final_modulate.r * p_modulate.r,
ci->final_modulate.g * p_modulate.g,
ci->final_modulate.b * p_modulate.b,
ci->final_modulate.a * p_modulate.a );
state.canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX,state.final_transform);
state.canvas_shader.set_uniform(CanvasShaderGLES2::EXTRA_MATRIX,Transform2D());
state.canvas_shader.set_uniform(CanvasShaderGLES2::FINAL_MODULATE,state.canvas_item_modulate);
glBlendEquation(GL_FUNC_ADD);
if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
} else {
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
//@TODO RESET canvas_blend_mode
*/
}
}
if (reclip) {
glEnable(GL_SCISSOR_TEST);
int y = storage->frame.current_rt->height - (r_ris.current_clip->final_clip_rect.position.y + r_ris.current_clip->final_clip_rect.size.y);
@ -2066,145 +1849,6 @@ void RasterizerCanvasGLES2::render_joined_item(const BItemJoined &p_bij, RenderI
r_ris.rebind_shader = true; // hacked in for now.
if ((blend_mode == RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_MIX || blend_mode == RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_PMALPHA) && r_ris.item_group_light && !unshaded) {
Light *light = r_ris.item_group_light;
bool light_used = false;
RS::CanvasLightMode mode = RS::CANVAS_LIGHT_MODE_ADD;
// we leave this set to 1, 1, 1, 1 if using software because the colors are baked into the vertices
if (p_bij.is_single_item()) {
state.uniforms.final_modulate = ci->final_modulate; // remove the canvas modulate
}
while (light) {
// use the bounding rect of the joined items, NOT only the bounding rect of the first item.
// note this is a cost of batching, the light culling will be less effective
// note that the r_ris.item_group_z will be out of date because we are using deferred rendering till canvas_render_items_end()
// so we have to test z against the stored value in the joined item
if (ci->light_mask & light->item_mask && p_bij.z_index >= light->z_min && p_bij.z_index <= light->z_max && p_bij.bounding_rect.intersects_transformed(light->xform_cache, light->rect_cache)) {
//intersects this light
if (!light_used || mode != light->mode) {
mode = light->mode;
switch (mode) {
case RS::CANVAS_LIGHT_MODE_ADD: {
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
} break;
case RS::CANVAS_LIGHT_MODE_SUB: {
glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
} break;
case RS::CANVAS_LIGHT_MODE_MIX:
case RS::CANVAS_LIGHT_MODE_MASK: {
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
} break;
}
}
if (!light_used) {
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_LIGHTING, true);
light_used = true;
}
bool has_shadow = light->shadow_buffer.is_valid() && ci->light_mask & light->item_shadow_mask;
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_SHADOWS, has_shadow);
if (has_shadow) {
state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_USE_GRADIENT, light->shadow_gradient_length > 0);
state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_NEAREST, light->shadow_filter == RS::CANVAS_LIGHT_FILTER_NONE);
state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF3, light->shadow_filter == RS::CANVAS_LIGHT_FILTER_PCF3);
state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF5, light->shadow_filter == RS::CANVAS_LIGHT_FILTER_PCF5);
state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF7, light->shadow_filter == RS::CANVAS_LIGHT_FILTER_PCF7);
state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF9, light->shadow_filter == RS::CANVAS_LIGHT_FILTER_PCF9);
state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF13, light->shadow_filter == RS::CANVAS_LIGHT_FILTER_PCF13);
}
state.canvas_shader.bind();
state.using_light = light;
state.using_shadow = has_shadow;
//always re-set uniforms, since light parameters changed
_set_uniforms();
state.canvas_shader.use_material((void *)material_ptr);
WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0 + storage->config.max_texture_image_units - 6);
RasterizerStorageGLES2::Texture *t = storage->texture_owner.getornull(light->texture);
if (!t) {
glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
} else {
t = t->get_ptr();
glBindTexture(t->target, t->tex_id);
}
WRAPPED_GL_ACTIVE_TEXTURE(GL_TEXTURE0);
// redraw using light.
// if there is no clip item, we can consider scissoring to the intersection area between the light and the item
// this can greatly reduce fill rate ..
// at the cost of glScissor commands, so is optional
if (!bdata.settings_scissor_lights || r_ris.current_clip) {
render_joined_item_commands(p_bij, nullptr, reclip, material_ptr, true, r_ris);
} else {
bool scissor = _light_scissor_begin(p_bij.bounding_rect, light->xform_cache, light->rect_cache);
render_joined_item_commands(p_bij, nullptr, reclip, material_ptr, true, r_ris);
if (scissor) {
glDisable(GL_SCISSOR_TEST);
}
}
state.using_light = nullptr;
}
light = light->next_ptr;
}
if (light_used) {
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_LIGHTING, false);
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_SHADOWS, false);
state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_NEAREST, false);
state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF3, false);
state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF5, false);
state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF7, false);
state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF9, false);
state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF13, false);
state.canvas_shader.bind();
r_ris.last_blend_mode = -1;
/*
//this is set again, so it should not be needed anyway?
state.canvas_item_modulate = unshaded ? ci->final_modulate : Color(
ci->final_modulate.r * p_modulate.r,
ci->final_modulate.g * p_modulate.g,
ci->final_modulate.b * p_modulate.b,
ci->final_modulate.a * p_modulate.a );
state.canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX,state.final_transform);
state.canvas_shader.set_uniform(CanvasShaderGLES2::EXTRA_MATRIX,Transform2D());
state.canvas_shader.set_uniform(CanvasShaderGLES2::FINAL_MODULATE,state.canvas_item_modulate);
glBlendEquation(GL_FUNC_ADD);
if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
} else {
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
//@TODO RESET canvas_blend_mode
*/
}
}
if (reclip) {
glEnable(GL_SCISSOR_TEST);
int y = storage->frame.current_rt->height - (r_ris.current_clip->final_clip_rect.position.y + r_ris.current_clip->final_clip_rect.size.y);

View File

@ -39,9 +39,9 @@ class RasterizerCanvasGLES2 : public RasterizerCanvasBaseGLES2, public Rasterize
friend class RasterizerCanvasBatcher<RasterizerCanvasGLES2, RasterizerStorageGLES2>;
public:
virtual void canvas_render_items_begin(const Color &p_modulate, Light *p_light, const Transform2D &p_base_transform);
virtual void canvas_render_items_begin(const Color &p_modulate, const Transform2D &p_base_transform);
virtual void canvas_render_items_end();
virtual void canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light, const Transform2D &p_base_transform);
virtual void canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, const Transform2D &p_base_transform);
virtual void canvas_begin();
virtual void canvas_end();
@ -50,7 +50,7 @@ private:
void _legacy_canvas_render_item(Item *p_ci, RenderItemState &r_ris);
// high level batch funcs
void canvas_render_items_implementation(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light, const Transform2D &p_base_transform);
void canvas_render_items_implementation(Item *p_item_list, int p_z, const Color &p_modulate, const Transform2D &p_base_transform);
void render_joined_item(const BItemJoined &p_bij, RenderItemState &r_ris);
bool try_join_item(Item *p_ci, RenderItemState &r_ris, bool &r_batch_break);
void render_batches(Item *p_current_clip, bool &r_reclip, RasterizerStorageGLES2::Material *p_material);

View File

@ -4326,157 +4326,6 @@ void RasterizerStorageGLES2::render_target_set_sharpen_intensity(RID p_render_ta
rt->sharpen_intensity = p_intensity;
}
/* CANVAS SHADOW */
RID RasterizerStorageGLES2::canvas_light_shadow_buffer_create(int p_width) {
CanvasLightShadow *cls = memnew(CanvasLightShadow);
if (p_width > config.max_texture_size) {
p_width = config.max_texture_size;
}
cls->size = p_width;
cls->height = 16;
gl_wrapper.gl_active_texture(GL_TEXTURE0);
glGenFramebuffers(1, &cls->fbo);
glBindFramebuffer(GL_FRAMEBUFFER, cls->fbo);
glGenRenderbuffers(1, &cls->depth);
glBindRenderbuffer(GL_RENDERBUFFER, cls->depth);
glRenderbufferStorage(GL_RENDERBUFFER, config.depth_buffer_internalformat, cls->size, cls->height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, cls->depth);
glGenTextures(1, &cls->distance);
glBindTexture(GL_TEXTURE_2D, cls->distance);
if (config.use_rgba_2d_shadows) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, cls->size, cls->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
} else {
#ifdef GLES_OVER_GL
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, cls->size, cls->height, 0, _RED_OES, GL_FLOAT, nullptr);
#else
glTexImage2D(GL_TEXTURE_2D, 0, GL_FLOAT, cls->size, cls->height, 0, _RED_OES, GL_FLOAT, NULL);
#endif
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, cls->distance, 0);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
//printf("errnum: %x\n",status);
glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES2::system_fbo);
if (status != GL_FRAMEBUFFER_COMPLETE) {
memdelete(cls);
ERR_FAIL_COND_V(status != GL_FRAMEBUFFER_COMPLETE, RID());
}
return canvas_light_shadow_owner.make_rid(cls);
}
/* LIGHT SHADOW MAPPING */
RID RasterizerStorageGLES2::canvas_light_occluder_create() {
CanvasOccluder *co = memnew(CanvasOccluder);
co->index_id = 0;
co->vertex_id = 0;
co->len = 0;
return canvas_occluder_owner.make_rid(co);
}
void RasterizerStorageGLES2::canvas_light_occluder_set_polylines(RID p_occluder, const PoolVector<Vector2> &p_lines) {
CanvasOccluder *co = canvas_occluder_owner.get(p_occluder);
ERR_FAIL_COND(!co);
co->lines = p_lines;
if (p_lines.size() != co->len) {
if (co->index_id) {
glDeleteBuffers(1, &co->index_id);
}
if (co->vertex_id) {
glDeleteBuffers(1, &co->vertex_id);
}
co->index_id = 0;
co->vertex_id = 0;
co->len = 0;
}
if (p_lines.size()) {
PoolVector<float> geometry;
PoolVector<uint16_t> indices;
int lc = p_lines.size();
geometry.resize(lc * 6);
indices.resize(lc * 3);
PoolVector<float>::Write vw = geometry.write();
PoolVector<uint16_t>::Write iw = indices.write();
PoolVector<Vector2>::Read lr = p_lines.read();
const int POLY_HEIGHT = 16384;
for (int i = 0; i < lc / 2; i++) {
vw[i * 12 + 0] = lr[i * 2 + 0].x;
vw[i * 12 + 1] = lr[i * 2 + 0].y;
vw[i * 12 + 2] = POLY_HEIGHT;
vw[i * 12 + 3] = lr[i * 2 + 1].x;
vw[i * 12 + 4] = lr[i * 2 + 1].y;
vw[i * 12 + 5] = POLY_HEIGHT;
vw[i * 12 + 6] = lr[i * 2 + 1].x;
vw[i * 12 + 7] = lr[i * 2 + 1].y;
vw[i * 12 + 8] = -POLY_HEIGHT;
vw[i * 12 + 9] = lr[i * 2 + 0].x;
vw[i * 12 + 10] = lr[i * 2 + 0].y;
vw[i * 12 + 11] = -POLY_HEIGHT;
iw[i * 6 + 0] = i * 4 + 0;
iw[i * 6 + 1] = i * 4 + 1;
iw[i * 6 + 2] = i * 4 + 2;
iw[i * 6 + 3] = i * 4 + 2;
iw[i * 6 + 4] = i * 4 + 3;
iw[i * 6 + 5] = i * 4 + 0;
}
//if same buffer len is being set, just use BufferSubData to avoid a pipeline flush
if (!co->vertex_id) {
glGenBuffers(1, &co->vertex_id);
glBindBuffer(GL_ARRAY_BUFFER, co->vertex_id);
glBufferData(GL_ARRAY_BUFFER, lc * 6 * sizeof(real_t), vw.ptr(), GL_STATIC_DRAW);
} else {
glBindBuffer(GL_ARRAY_BUFFER, co->vertex_id);
glBufferSubData(GL_ARRAY_BUFFER, 0, lc * 6 * sizeof(real_t), vw.ptr());
}
glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
if (!co->index_id) {
glGenBuffers(1, &co->index_id);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, co->index_id);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, lc * 3 * sizeof(uint16_t), iw.ptr(), GL_DYNAMIC_DRAW);
} else {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, co->index_id);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, lc * 3 * sizeof(uint16_t), iw.ptr());
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); //unbind
co->len = lc;
}
}
RS::InstanceType RasterizerStorageGLES2::get_base_type(RID p_rid) const {
if (mesh_owner.owns(p_rid)) {
return RS::INSTANCE_MESH;
@ -4618,29 +4467,6 @@ bool RasterizerStorageGLES2::free(RID p_rid) {
multimesh_owner.free(p_rid);
memdelete(multimesh);
return true;
} else if (canvas_occluder_owner.owns(p_rid)) {
CanvasOccluder *co = canvas_occluder_owner.get(p_rid);
if (co->index_id) {
glDeleteBuffers(1, &co->index_id);
}
if (co->vertex_id) {
glDeleteBuffers(1, &co->vertex_id);
}
canvas_occluder_owner.free(p_rid);
memdelete(co);
return true;
} else if (canvas_light_shadow_owner.owns(p_rid)) {
CanvasLightShadow *cls = canvas_light_shadow_owner.get(p_rid);
glDeleteFramebuffers(1, &cls->fbo);
glDeleteRenderbuffers(1, &cls->depth);
glDeleteTextures(1, &cls->distance);
canvas_light_shadow_owner.free(p_rid);
memdelete(cls);
return true;
} else {
return false;

View File

@ -951,34 +951,6 @@ public:
virtual void render_target_set_use_debanding(RID p_render_target, bool p_debanding);
virtual void render_target_set_sharpen_intensity(RID p_render_target, float p_intensity);
/* CANVAS SHADOW */
struct CanvasLightShadow : public RID_Data {
int size;
int height;
GLuint fbo;
GLuint depth;
GLuint distance; //for older devices
};
RID_Owner<CanvasLightShadow> canvas_light_shadow_owner;
virtual RID canvas_light_shadow_buffer_create(int p_width);
/* LIGHT SHADOW MAPPING */
struct CanvasOccluder : public RID_Data {
GLuint vertex_id; // 0 means, unconfigured
GLuint index_id; // 0 means, unconfigured
PoolVector<Vector2> lines;
int len;
};
RID_Owner<CanvasOccluder> canvas_occluder_owner;
virtual RID canvas_light_occluder_create();
virtual void canvas_light_occluder_set_polylines(RID p_occluder, const PoolVector<Vector2> &p_lines);
virtual RS::InstanceType get_base_type(RID p_rid) const;
virtual bool free(RID p_rid);

View File

@ -271,11 +271,9 @@ public:
void reset() {
light_bitfield = 0;
shadow_bitfield = 0;
too_many_lights = false;
}
uint64_t light_bitfield;
uint64_t shadow_bitfield;
bool too_many_lights; // we can only do light region optimization if there are 64 or less lights
};
struct BatchData {
@ -512,7 +510,6 @@ public:
last_blend_mode = -1;
canvas_last_material = RID();
item_group_z = 0;
item_group_light = nullptr;
final_modulate = Color(-1.0, -1.0, -1.0, -1.0); // just something unlikely
joined_item_batch_type_flags_curr = 0;
@ -543,7 +540,6 @@ public:
// 'item group' is data over a single call to canvas_render_items
int item_group_z;
Color item_group_modulate;
RasterizerCanvas::Light *item_group_light;
Transform2D item_group_base_transform;
} _render_item_state;
@ -566,9 +562,9 @@ protected:
void batch_canvas_begin();
void batch_canvas_end();
void batch_canvas_render_items_begin(const Color &p_modulate, RasterizerCanvas::Light *p_light, const Transform2D &p_base_transform);
void batch_canvas_render_items_begin(const Color &p_modulate, const Transform2D &p_base_transform);
void batch_canvas_render_items_end();
void batch_canvas_render_items(RasterizerCanvas::Item *p_item_list, int p_z, const Color &p_modulate, RasterizerCanvas::Light *p_light, const Transform2D &p_base_transform);
void batch_canvas_render_items(RasterizerCanvas::Item *p_item_list, int p_z, const Color &p_modulate, const Transform2D &p_base_transform);
// recording and sorting items from the initial pass
void record_items(RasterizerCanvas::Item *p_item_list, int p_z);
@ -746,7 +742,7 @@ PREAMBLE(void)::batch_canvas_end() {
#endif
}
PREAMBLE(void)::batch_canvas_render_items_begin(const Color &p_modulate, RasterizerCanvas::Light *p_light, const Transform2D &p_base_transform) {
PREAMBLE(void)::batch_canvas_render_items_begin(const Color &p_modulate, const Transform2D &p_base_transform) {
// if we are debugging, flash each frame between batching renderer and old version to compare for regressions
if (bdata.settings_flash_batching) {
if ((Engine::get_singleton()->get_frames_drawn() % 2) == 0) {
@ -767,7 +763,6 @@ PREAMBLE(void)::batch_canvas_render_items_begin(const Color &p_modulate, Rasteri
// set up render item state for all the z_indexes (this is common to all z_indexes)
_render_item_state.reset();
_render_item_state.item_group_modulate = p_modulate;
_render_item_state.item_group_light = p_light;
_render_item_state.item_group_base_transform = p_base_transform;
_render_item_state.light_region.reset();
@ -778,25 +773,6 @@ PREAMBLE(void)::batch_canvas_render_items_begin(const Color &p_modulate, Rasteri
// whether to join across z indices depends on whether there are z ranged lights.
// joined z_index items can be wrongly classified with z ranged lights.
bdata.join_across_z_indices = true;
int light_count = 0;
while (p_light) {
light_count++;
if ((p_light->z_min != RS::CANVAS_ITEM_Z_MIN) || (p_light->z_max != RS::CANVAS_ITEM_Z_MAX)) {
// prevent joining across z indices. This would have caused visual regressions
bdata.join_across_z_indices = false;
}
p_light = p_light->next_ptr;
}
// can't use the light region bitfield if there are too many lights
// hopefully most games won't blow this limit..
// if they do they will work but it won't batch join items just in case
if (light_count > 64) {
_render_item_state.light_region.too_many_lights = true;
}
}
PREAMBLE(void)::batch_canvas_render_items_end() {
@ -814,7 +790,6 @@ PREAMBLE(void)::batch_canvas_render_items_end() {
// batching render is deferred until after going through all the z_indices, joining all the items
get_this()->canvas_render_items_implementation(nullptr, 0, _render_item_state.item_group_modulate,
_render_item_state.item_group_light,
_render_item_state.item_group_base_transform);
bdata.items_joined.reset();
@ -822,7 +797,7 @@ PREAMBLE(void)::batch_canvas_render_items_end() {
bdata.sort_items.reset();
}
PREAMBLE(void)::batch_canvas_render_items(RasterizerCanvas::Item *p_item_list, int p_z, const Color &p_modulate, RasterizerCanvas::Light *p_light, const Transform2D &p_base_transform) {
PREAMBLE(void)::batch_canvas_render_items(RasterizerCanvas::Item *p_item_list, int p_z, const Color &p_modulate, const Transform2D &p_base_transform) {
// stage 1 : join similar items, so that their state changes are not repeated,
// and commands from joined items can be batched together
if (bdata.settings_use_batching) {
@ -831,7 +806,7 @@ PREAMBLE(void)::batch_canvas_render_items(RasterizerCanvas::Item *p_item_list, i
}
// only legacy renders at this stage, batched renderer doesn't render until canvas_render_items_end()
get_this()->canvas_render_items_implementation(p_item_list, p_z, p_modulate, p_light, p_base_transform);
get_this()->canvas_render_items_implementation(p_item_list, p_z, p_modulate, p_base_transform);
}
// Default batches will not occur in software transform only items

View File

@ -1,478 +0,0 @@
/*************************************************************************/
/* light_2d.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "light_2d.h"
#include "core/config/engine.h"
#include "servers/rendering_server.h"
#ifdef TOOLS_ENABLED
Dictionary Light2D::_edit_get_state() const {
Dictionary state = Node2D::_edit_get_state();
state["offset"] = get_texture_offset();
return state;
}
void Light2D::_edit_set_state(const Dictionary &p_state) {
Node2D::_edit_set_state(p_state);
set_texture_offset(p_state["offset"]);
}
void Light2D::_edit_set_pivot(const Point2 &p_pivot) {
set_position(get_transform().xform(p_pivot));
set_texture_offset(get_texture_offset() - p_pivot);
}
Point2 Light2D::_edit_get_pivot() const {
return Vector2();
}
bool Light2D::_edit_use_pivot() const {
return true;
}
Rect2 Light2D::_edit_get_rect() const {
if (texture.is_null()) {
return Rect2();
}
Size2 s = texture->get_size() * _scale;
return Rect2(texture_offset - s / 2.0, s);
}
bool Light2D::_edit_use_rect() const {
return !texture.is_null();
}
#endif
Rect2 Light2D::get_anchorable_rect() const {
if (texture.is_null()) {
return Rect2();
}
Size2 s = texture->get_size() * _scale;
return Rect2(texture_offset - s / 2.0, s);
}
void Light2D::owner_changed_notify() {
// For cases where owner changes _after_ entering tree (as example, editor editing).
_update_light_visibility();
}
void Light2D::_update_light_visibility() {
if (!is_inside_tree()) {
return;
}
bool editor_ok = true;
#ifdef TOOLS_ENABLED
if (editor_only) {
if (!Engine::get_singleton()->is_editor_hint()) {
editor_ok = false;
} else {
editor_ok = (get_tree()->get_edited_scene_root() && (this == get_tree()->get_edited_scene_root() || get_owner() == get_tree()->get_edited_scene_root()));
}
}
#else
if (editor_only) {
editor_ok = false;
}
#endif
RS::get_singleton()->canvas_light_set_enabled(canvas_light, enabled && is_visible_in_tree() && editor_ok);
}
void Light2D::set_enabled(bool p_enabled) {
enabled = p_enabled;
_update_light_visibility();
}
bool Light2D::is_enabled() const {
return enabled;
}
void Light2D::set_editor_only(bool p_editor_only) {
editor_only = p_editor_only;
_update_light_visibility();
}
bool Light2D::is_editor_only() const {
return editor_only;
}
void Light2D::set_texture(const Ref<Texture> &p_texture) {
texture = p_texture;
if (texture.is_valid()) {
RS::get_singleton()->canvas_light_set_texture(canvas_light, texture->get_rid());
} else {
RS::get_singleton()->canvas_light_set_texture(canvas_light, RID());
}
update_configuration_warning();
}
Ref<Texture> Light2D::get_texture() const {
return texture;
}
void Light2D::set_texture_offset(const Vector2 &p_offset) {
texture_offset = p_offset;
RS::get_singleton()->canvas_light_set_texture_offset(canvas_light, texture_offset);
item_rect_changed();
_change_notify("offset");
}
Vector2 Light2D::get_texture_offset() const {
return texture_offset;
}
void Light2D::set_color(const Color &p_color) {
color = p_color;
RS::get_singleton()->canvas_light_set_color(canvas_light, color);
}
Color Light2D::get_color() const {
return color;
}
void Light2D::set_height(float p_height) {
height = p_height;
RS::get_singleton()->canvas_light_set_height(canvas_light, height);
}
float Light2D::get_height() const {
return height;
}
void Light2D::set_energy(float p_energy) {
energy = p_energy;
RS::get_singleton()->canvas_light_set_energy(canvas_light, energy);
}
float Light2D::get_energy() const {
return energy;
}
void Light2D::set_texture_scale(float p_scale) {
_scale = p_scale;
// Avoid having 0 scale values, can lead to errors in physics and rendering.
if (_scale == 0) {
_scale = CMP_EPSILON;
}
RS::get_singleton()->canvas_light_set_scale(canvas_light, _scale);
item_rect_changed();
}
float Light2D::get_texture_scale() const {
return _scale;
}
void Light2D::set_z_range_min(int p_min_z) {
z_min = p_min_z;
RS::get_singleton()->canvas_light_set_z_range(canvas_light, z_min, z_max);
}
int Light2D::get_z_range_min() const {
return z_min;
}
void Light2D::set_z_range_max(int p_max_z) {
z_max = p_max_z;
RS::get_singleton()->canvas_light_set_z_range(canvas_light, z_min, z_max);
}
int Light2D::get_z_range_max() const {
return z_max;
}
void Light2D::set_layer_range_min(int p_min_layer) {
layer_min = p_min_layer;
RS::get_singleton()->canvas_light_set_layer_range(canvas_light, layer_min, layer_max);
}
int Light2D::get_layer_range_min() const {
return layer_min;
}
void Light2D::set_layer_range_max(int p_max_layer) {
layer_max = p_max_layer;
RS::get_singleton()->canvas_light_set_layer_range(canvas_light, layer_min, layer_max);
}
int Light2D::get_layer_range_max() const {
return layer_max;
}
void Light2D::set_item_cull_mask(int p_mask) {
item_mask = p_mask;
RS::get_singleton()->canvas_light_set_item_cull_mask(canvas_light, item_mask);
}
int Light2D::get_item_cull_mask() const {
return item_mask;
}
void Light2D::set_item_shadow_cull_mask(int p_mask) {
item_shadow_mask = p_mask;
RS::get_singleton()->canvas_light_set_item_shadow_cull_mask(canvas_light, item_shadow_mask);
}
int Light2D::get_item_shadow_cull_mask() const {
return item_shadow_mask;
}
void Light2D::set_mode(Mode p_mode) {
mode = p_mode;
RS::get_singleton()->canvas_light_set_mode(canvas_light, RS::CanvasLightMode(p_mode));
}
Light2D::Mode Light2D::get_mode() const {
return mode;
}
void Light2D::set_shadow_enabled(bool p_enabled) {
shadow = p_enabled;
RS::get_singleton()->canvas_light_set_shadow_enabled(canvas_light, shadow);
}
bool Light2D::is_shadow_enabled() const {
return shadow;
}
void Light2D::set_shadow_buffer_size(int p_size) {
shadow_buffer_size = p_size;
RS::get_singleton()->canvas_light_set_shadow_buffer_size(canvas_light, shadow_buffer_size);
}
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;
RS::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) {
shadow_filter = p_filter;
RS::get_singleton()->canvas_light_set_shadow_filter(canvas_light, RS::CanvasLightShadowFilter(p_filter));
}
Light2D::ShadowFilter Light2D::get_shadow_filter() const {
return shadow_filter;
}
void Light2D::set_shadow_color(const Color &p_shadow_color) {
shadow_color = p_shadow_color;
RS::get_singleton()->canvas_light_set_shadow_color(canvas_light, shadow_color);
}
Color Light2D::get_shadow_color() const {
return shadow_color;
}
void Light2D::_physics_interpolated_changed() {
RenderingServer::get_singleton()->canvas_light_set_interpolated(canvas_light, is_physics_interpolated());
}
void Light2D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
RS::get_singleton()->canvas_light_attach_to_canvas(canvas_light, get_canvas());
_update_light_visibility();
} break;
case NOTIFICATION_EXIT_TREE: {
RS::get_singleton()->canvas_light_attach_to_canvas(canvas_light, RID());
_update_light_visibility();
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
RS::get_singleton()->canvas_light_set_transform(canvas_light, get_global_transform());
} break;
case NOTIFICATION_VISIBILITY_CHANGED: {
_update_light_visibility();
} break;
case NOTIFICATION_RESET_PHYSICS_INTERPOLATION: {
if (is_visible_in_tree() && is_physics_interpolated()) {
RenderingServer::get_singleton()->canvas_light_reset_physics_interpolation(canvas_light);
}
} break;
}
}
String Light2D::get_configuration_warning() const {
String warning = Node2D::get_configuration_warning();
if (!texture.is_valid()) {
if (warning != String()) {
warning += "\n\n";
}
warning += TTR("A texture with the shape of the light must be supplied to the \"Texture\" property.");
}
return warning;
}
void Light2D::set_shadow_smooth(float p_amount) {
shadow_smooth = p_amount;
RS::get_singleton()->canvas_light_set_shadow_smooth(canvas_light, shadow_smooth);
}
float Light2D::get_shadow_smooth() const {
return shadow_smooth;
}
void Light2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &Light2D::set_enabled);
ClassDB::bind_method(D_METHOD("is_enabled"), &Light2D::is_enabled);
ClassDB::bind_method(D_METHOD("set_editor_only", "editor_only"), &Light2D::set_editor_only);
ClassDB::bind_method(D_METHOD("is_editor_only"), &Light2D::is_editor_only);
ClassDB::bind_method(D_METHOD("set_texture", "texture"), &Light2D::set_texture);
ClassDB::bind_method(D_METHOD("get_texture"), &Light2D::get_texture);
ClassDB::bind_method(D_METHOD("set_texture_offset", "texture_offset"), &Light2D::set_texture_offset);
ClassDB::bind_method(D_METHOD("get_texture_offset"), &Light2D::get_texture_offset);
ClassDB::bind_method(D_METHOD("set_color", "color"), &Light2D::set_color);
ClassDB::bind_method(D_METHOD("get_color"), &Light2D::get_color);
ClassDB::bind_method(D_METHOD("set_height", "height"), &Light2D::set_height);
ClassDB::bind_method(D_METHOD("get_height"), &Light2D::get_height);
ClassDB::bind_method(D_METHOD("set_energy", "energy"), &Light2D::set_energy);
ClassDB::bind_method(D_METHOD("get_energy"), &Light2D::get_energy);
ClassDB::bind_method(D_METHOD("set_texture_scale", "texture_scale"), &Light2D::set_texture_scale);
ClassDB::bind_method(D_METHOD("get_texture_scale"), &Light2D::get_texture_scale);
ClassDB::bind_method(D_METHOD("set_z_range_min", "z"), &Light2D::set_z_range_min);
ClassDB::bind_method(D_METHOD("get_z_range_min"), &Light2D::get_z_range_min);
ClassDB::bind_method(D_METHOD("set_z_range_max", "z"), &Light2D::set_z_range_max);
ClassDB::bind_method(D_METHOD("get_z_range_max"), &Light2D::get_z_range_max);
ClassDB::bind_method(D_METHOD("set_layer_range_min", "layer"), &Light2D::set_layer_range_min);
ClassDB::bind_method(D_METHOD("get_layer_range_min"), &Light2D::get_layer_range_min);
ClassDB::bind_method(D_METHOD("set_layer_range_max", "layer"), &Light2D::set_layer_range_max);
ClassDB::bind_method(D_METHOD("get_layer_range_max"), &Light2D::get_layer_range_max);
ClassDB::bind_method(D_METHOD("set_item_cull_mask", "item_cull_mask"), &Light2D::set_item_cull_mask);
ClassDB::bind_method(D_METHOD("get_item_cull_mask"), &Light2D::get_item_cull_mask);
ClassDB::bind_method(D_METHOD("set_item_shadow_cull_mask", "item_shadow_cull_mask"), &Light2D::set_item_shadow_cull_mask);
ClassDB::bind_method(D_METHOD("get_item_shadow_cull_mask"), &Light2D::get_item_shadow_cull_mask);
ClassDB::bind_method(D_METHOD("set_mode", "mode"), &Light2D::set_mode);
ClassDB::bind_method(D_METHOD("get_mode"), &Light2D::get_mode);
ClassDB::bind_method(D_METHOD("set_shadow_enabled", "enabled"), &Light2D::set_shadow_enabled);
ClassDB::bind_method(D_METHOD("is_shadow_enabled"), &Light2D::is_shadow_enabled);
ClassDB::bind_method(D_METHOD("set_shadow_buffer_size", "size"), &Light2D::set_shadow_buffer_size);
ClassDB::bind_method(D_METHOD("get_shadow_buffer_size"), &Light2D::get_shadow_buffer_size);
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);
ClassDB::bind_method(D_METHOD("set_shadow_color", "shadow_color"), &Light2D::set_shadow_color);
ClassDB::bind_method(D_METHOD("get_shadow_color"), &Light2D::get_shadow_color);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editor_only"), "set_editor_only", "is_editor_only");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset"), "set_texture_offset", "get_texture_offset");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "texture_scale", PROPERTY_HINT_RANGE, "0.01,50,0.01"), "set_texture_scale", "get_texture_scale");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_color", "get_color");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_energy", "get_energy");
ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Add,Sub,Mix,Mask"), "set_mode", "get_mode");
ADD_GROUP("Range", "range_");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "range_height", PROPERTY_HINT_RANGE, "-2048,2048,0.1,or_lesser,or_greater"), "set_height", "get_height");
ADD_PROPERTY(PropertyInfo(Variant::INT, "range_z_min", PROPERTY_HINT_RANGE, itos(RS::CANVAS_ITEM_Z_MIN) + "," + itos(RS::CANVAS_ITEM_Z_MAX) + ",1"), "set_z_range_min", "get_z_range_min");
ADD_PROPERTY(PropertyInfo(Variant::INT, "range_z_max", PROPERTY_HINT_RANGE, itos(RS::CANVAS_ITEM_Z_MIN) + "," + itos(RS::CANVAS_ITEM_Z_MAX) + ",1"), "set_z_range_max", "get_z_range_max");
ADD_PROPERTY(PropertyInfo(Variant::INT, "range_layer_min", PROPERTY_HINT_RANGE, "-512,512,1"), "set_layer_range_min", "get_layer_range_min");
ADD_PROPERTY(PropertyInfo(Variant::INT, "range_layer_max", PROPERTY_HINT_RANGE, "-512,512,1"), "set_layer_range_max", "get_layer_range_max");
ADD_PROPERTY(PropertyInfo(Variant::INT, "range_item_cull_mask", PROPERTY_HINT_LAYERS_2D_RENDER), "set_item_cull_mask", "get_item_cull_mask");
ADD_GROUP("Shadow", "shadow_");
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,PCF3,PCF5,PCF7,PCF9,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");
BIND_ENUM_CONSTANT(MODE_ADD);
BIND_ENUM_CONSTANT(MODE_SUB);
BIND_ENUM_CONSTANT(MODE_MIX);
BIND_ENUM_CONSTANT(MODE_MASK);
BIND_ENUM_CONSTANT(SHADOW_FILTER_NONE);
BIND_ENUM_CONSTANT(SHADOW_FILTER_PCF3);
BIND_ENUM_CONSTANT(SHADOW_FILTER_PCF5);
BIND_ENUM_CONSTANT(SHADOW_FILTER_PCF7);
BIND_ENUM_CONSTANT(SHADOW_FILTER_PCF9);
BIND_ENUM_CONSTANT(SHADOW_FILTER_PCF13);
}
Light2D::Light2D() {
canvas_light = RID_PRIME(RenderingServer::get_singleton()->canvas_light_create());
enabled = true;
editor_only = false;
shadow = false;
color = Color(1, 1, 1);
height = 0;
_scale = 1.0;
z_min = -1024;
z_max = 1024;
layer_min = 0;
layer_max = 0;
item_mask = 1;
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;
shadow_smooth = 0;
set_notify_transform(true);
}
Light2D::~Light2D() {
RenderingServer::get_singleton()->free(canvas_light);
}

View File

@ -1,174 +0,0 @@
#ifndef LIGHT_2D_H
#define LIGHT_2D_H
/*************************************************************************/
/* light_2d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "scene/main/node_2d.h"
class Light2D : public Node2D {
GDCLASS(Light2D, Node2D);
public:
enum Mode {
MODE_ADD,
MODE_SUB,
MODE_MIX,
MODE_MASK,
};
enum ShadowFilter {
SHADOW_FILTER_NONE,
SHADOW_FILTER_PCF3,
SHADOW_FILTER_PCF5,
SHADOW_FILTER_PCF7,
SHADOW_FILTER_PCF9,
SHADOW_FILTER_PCF13,
};
private:
RID canvas_light;
bool enabled;
bool editor_only;
bool shadow;
Color color;
Color shadow_color;
float height;
float _scale;
float energy;
int z_min;
int z_max;
int layer_min;
int layer_max;
int item_mask;
int item_shadow_mask;
int shadow_buffer_size;
float shadow_smooth;
float shadow_gradient_length;
Mode mode;
Ref<Texture> texture;
Vector2 texture_offset;
ShadowFilter shadow_filter;
void _update_light_visibility();
virtual void owner_changed_notify();
virtual void _physics_interpolated_changed();
protected:
void _notification(int p_what);
static void _bind_methods();
public:
#ifdef TOOLS_ENABLED
virtual Dictionary _edit_get_state() const;
virtual void _edit_set_state(const Dictionary &p_state);
virtual void _edit_set_pivot(const Point2 &p_pivot);
virtual Point2 _edit_get_pivot() const;
virtual bool _edit_use_pivot() const;
virtual Rect2 _edit_get_rect() const;
virtual bool _edit_use_rect() const;
#endif
virtual Rect2 get_anchorable_rect() const;
void set_enabled(bool p_enabled);
bool is_enabled() const;
void set_editor_only(bool p_editor_only);
bool is_editor_only() const;
void set_texture(const Ref<Texture> &p_texture);
Ref<Texture> get_texture() const;
void set_texture_offset(const Vector2 &p_offset);
Vector2 get_texture_offset() const;
void set_color(const Color &p_color);
Color get_color() const;
void set_height(float p_height);
float get_height() const;
void set_energy(float p_energy);
float get_energy() const;
void set_texture_scale(float p_scale);
float get_texture_scale() const;
void set_z_range_min(int p_min_z);
int get_z_range_min() const;
void set_z_range_max(int p_max_z);
int get_z_range_max() const;
void set_layer_range_min(int p_min_layer);
int get_layer_range_min() const;
void set_layer_range_max(int p_max_layer);
int get_layer_range_max() const;
void set_item_cull_mask(int p_mask);
int get_item_cull_mask() const;
void set_item_shadow_cull_mask(int p_mask);
int get_item_shadow_cull_mask() const;
void set_mode(Mode p_mode);
Mode get_mode() const;
void set_shadow_enabled(bool p_enabled);
bool is_shadow_enabled() const;
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;
void set_shadow_color(const Color &p_shadow_color);
Color get_shadow_color() const;
void set_shadow_smooth(float p_amount);
float get_shadow_smooth() const;
String get_configuration_warning() const;
Light2D();
~Light2D();
};
VARIANT_ENUM_CAST(Light2D::Mode);
VARIANT_ENUM_CAST(Light2D::ShadowFilter);
#endif // LIGHT_2D_H

View File

@ -1,296 +0,0 @@
/*************************************************************************/
/* light_occluder_2d.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "light_occluder_2d.h"
#include "core/config/engine.h"
#define LINE_GRAB_WIDTH 8
#ifdef TOOLS_ENABLED
Rect2 OccluderPolygon2D::_edit_get_rect() const {
if (rect_cache_dirty) {
if (closed) {
PoolVector<Vector2>::Read r = polygon.read();
item_rect = Rect2();
for (int i = 0; i < polygon.size(); i++) {
Vector2 pos = r[i];
if (i == 0) {
item_rect.position = pos;
} else {
item_rect.expand_to(pos);
}
}
rect_cache_dirty = false;
} else {
if (polygon.size() == 0) {
item_rect = Rect2();
} else {
Vector2 d = Vector2(LINE_GRAB_WIDTH, LINE_GRAB_WIDTH);
item_rect = Rect2(polygon[0] - d, 2 * d);
for (int i = 1; i < polygon.size(); i++) {
item_rect.expand_to(polygon[i] - d);
item_rect.expand_to(polygon[i] + d);
}
}
}
}
return item_rect;
}
bool OccluderPolygon2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
if (closed) {
return Geometry::is_point_in_polygon(p_point, Variant(polygon));
} else {
const real_t d = LINE_GRAB_WIDTH / 2 + p_tolerance;
PoolVector<Vector2>::Read points = polygon.read();
for (int i = 0; i < polygon.size() - 1; i++) {
Vector2 p = Geometry::get_closest_point_to_segment_2d(p_point, &points[i]);
if (p.distance_to(p_point) <= d) {
return true;
}
}
return false;
}
}
#endif
void OccluderPolygon2D::set_polygon(const PoolVector<Vector2> &p_polygon) {
polygon = p_polygon;
rect_cache_dirty = true;
RS::get_singleton()->canvas_occluder_polygon_set_shape(occ_polygon, p_polygon, closed);
emit_changed();
}
PoolVector<Vector2> OccluderPolygon2D::get_polygon() const {
return polygon;
}
void OccluderPolygon2D::set_closed(bool p_closed) {
if (closed == p_closed) {
return;
}
closed = p_closed;
if (polygon.size()) {
RS::get_singleton()->canvas_occluder_polygon_set_shape(occ_polygon, polygon, closed);
}
emit_changed();
}
bool OccluderPolygon2D::is_closed() const {
return closed;
}
void OccluderPolygon2D::set_cull_mode(CullMode p_mode) {
cull = p_mode;
RS::get_singleton()->canvas_occluder_polygon_set_cull_mode(occ_polygon, RS::CanvasOccluderPolygonCullMode(p_mode));
}
OccluderPolygon2D::CullMode OccluderPolygon2D::get_cull_mode() const {
return cull;
}
RID OccluderPolygon2D::get_rid() const {
return occ_polygon;
}
void OccluderPolygon2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_closed", "closed"), &OccluderPolygon2D::set_closed);
ClassDB::bind_method(D_METHOD("is_closed"), &OccluderPolygon2D::is_closed);
ClassDB::bind_method(D_METHOD("set_cull_mode", "cull_mode"), &OccluderPolygon2D::set_cull_mode);
ClassDB::bind_method(D_METHOD("get_cull_mode"), &OccluderPolygon2D::get_cull_mode);
ClassDB::bind_method(D_METHOD("set_polygon", "polygon"), &OccluderPolygon2D::set_polygon);
ClassDB::bind_method(D_METHOD("get_polygon"), &OccluderPolygon2D::get_polygon);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "closed"), "set_closed", "is_closed");
ADD_PROPERTY(PropertyInfo(Variant::INT, "cull_mode", PROPERTY_HINT_ENUM, "Disabled,ClockWise,CounterClockWise"), "set_cull_mode", "get_cull_mode");
ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "polygon"), "set_polygon", "get_polygon");
BIND_ENUM_CONSTANT(CULL_DISABLED);
BIND_ENUM_CONSTANT(CULL_CLOCKWISE);
BIND_ENUM_CONSTANT(CULL_COUNTER_CLOCKWISE);
}
OccluderPolygon2D::OccluderPolygon2D() {
occ_polygon = RID_PRIME(RS::get_singleton()->canvas_occluder_polygon_create());
closed = true;
cull = CULL_DISABLED;
rect_cache_dirty = true;
}
OccluderPolygon2D::~OccluderPolygon2D() {
RS::get_singleton()->free(occ_polygon);
}
void LightOccluder2D::_poly_changed() {
#ifdef DEBUG_ENABLED
update();
#endif
}
void LightOccluder2D::_physics_interpolated_changed() {
RenderingServer::get_singleton()->canvas_light_occluder_set_interpolated(occluder, is_physics_interpolated());
}
void LightOccluder2D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_CANVAS: {
RS::get_singleton()->canvas_light_occluder_attach_to_canvas(occluder, get_canvas());
RS::get_singleton()->canvas_light_occluder_set_transform(occluder, get_global_transform());
RS::get_singleton()->canvas_light_occluder_set_enabled(occluder, is_visible_in_tree());
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
RS::get_singleton()->canvas_light_occluder_set_transform(occluder, get_global_transform());
} break;
case NOTIFICATION_VISIBILITY_CHANGED: {
RS::get_singleton()->canvas_light_occluder_set_enabled(occluder, is_visible_in_tree());
} break;
case NOTIFICATION_DRAW: {
if (Engine::get_singleton()->is_editor_hint()) {
if (occluder_polygon.is_valid()) {
PoolVector<Vector2> poly = occluder_polygon->get_polygon();
if (poly.size()) {
if (occluder_polygon->is_closed()) {
Vector<Color> color;
color.push_back(Color(0, 0, 0, 0.6));
draw_polygon(Variant(poly), color);
} else {
int ps = poly.size();
PoolVector<Vector2>::Read r = poly.read();
for (int i = 0; i < ps - 1; i++) {
draw_line(r[i], r[i + 1], Color(0, 0, 0, 0.6), 3);
}
}
}
}
}
} break;
case NOTIFICATION_EXIT_CANVAS: {
RS::get_singleton()->canvas_light_occluder_attach_to_canvas(occluder, RID());
} break;
case NOTIFICATION_RESET_PHYSICS_INTERPOLATION: {
if (is_visible_in_tree() && is_physics_interpolated()) {
RenderingServer::get_singleton()->canvas_light_occluder_reset_physics_interpolation(occluder);
}
} break;
}
}
#ifdef TOOLS_ENABLED
Rect2 LightOccluder2D::_edit_get_rect() const {
return occluder_polygon.is_valid() ? occluder_polygon->_edit_get_rect() : Rect2();
}
bool LightOccluder2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
return occluder_polygon.is_valid() ? occluder_polygon->_edit_is_selected_on_click(p_point, p_tolerance) : false;
}
#endif
void LightOccluder2D::set_occluder_polygon(const Ref<OccluderPolygon2D> &p_polygon) {
#ifdef DEBUG_ENABLED
if (occluder_polygon.is_valid()) {
occluder_polygon->disconnect("changed", this, "_poly_changed");
}
#endif
occluder_polygon = p_polygon;
if (occluder_polygon.is_valid()) {
RS::get_singleton()->canvas_light_occluder_set_polygon(occluder, occluder_polygon->get_rid());
} else {
RS::get_singleton()->canvas_light_occluder_set_polygon(occluder, RID());
}
#ifdef DEBUG_ENABLED
if (occluder_polygon.is_valid()) {
occluder_polygon->connect("changed", this, "_poly_changed");
}
update();
#endif
}
Ref<OccluderPolygon2D> LightOccluder2D::get_occluder_polygon() const {
return occluder_polygon;
}
void LightOccluder2D::set_occluder_light_mask(int p_mask) {
mask = p_mask;
RS::get_singleton()->canvas_light_occluder_set_light_mask(occluder, mask);
}
int LightOccluder2D::get_occluder_light_mask() const {
return mask;
}
String LightOccluder2D::get_configuration_warning() const {
String warning = Node2D::get_configuration_warning();
if (!occluder_polygon.is_valid()) {
if (warning != String()) {
warning += "\n\n";
}
warning += TTR("An occluder polygon must be set (or drawn) for this occluder to take effect.");
}
if (occluder_polygon.is_valid() && occluder_polygon->get_polygon().size() == 0) {
if (warning != String()) {
warning += "\n\n";
}
warning += TTR("The occluder polygon for this occluder is empty. Please draw a polygon.");
}
return warning;
}
void LightOccluder2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_occluder_polygon", "polygon"), &LightOccluder2D::set_occluder_polygon);
ClassDB::bind_method(D_METHOD("get_occluder_polygon"), &LightOccluder2D::get_occluder_polygon);
ClassDB::bind_method(D_METHOD("set_occluder_light_mask", "mask"), &LightOccluder2D::set_occluder_light_mask);
ClassDB::bind_method(D_METHOD("get_occluder_light_mask"), &LightOccluder2D::get_occluder_light_mask);
ClassDB::bind_method("_poly_changed", &LightOccluder2D::_poly_changed);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "occluder", PROPERTY_HINT_RESOURCE_TYPE, "OccluderPolygon2D"), "set_occluder_polygon", "get_occluder_polygon");
ADD_PROPERTY(PropertyInfo(Variant::INT, "light_mask", PROPERTY_HINT_LAYERS_2D_RENDER), "set_occluder_light_mask", "get_occluder_light_mask");
}
LightOccluder2D::LightOccluder2D() {
occluder = RID_PRIME(RS::get_singleton()->canvas_light_occluder_create());
mask = 1;
set_notify_transform(true);
}
LightOccluder2D::~LightOccluder2D() {
RS::get_singleton()->free(occluder);
}

View File

@ -1,112 +0,0 @@
#ifndef LIGHTOCCLUDER2D_H
#define LIGHTOCCLUDER2D_H
/*************************************************************************/
/* light_occluder_2d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "scene/main/node_2d.h"
class OccluderPolygon2D : public Resource {
GDCLASS(OccluderPolygon2D, Resource);
public:
enum CullMode {
CULL_DISABLED,
CULL_CLOCKWISE,
CULL_COUNTER_CLOCKWISE
};
private:
RID occ_polygon;
PoolVector<Vector2> polygon;
bool closed;
CullMode cull;
mutable Rect2 item_rect;
mutable bool rect_cache_dirty;
protected:
static void _bind_methods();
public:
#ifdef TOOLS_ENABLED
virtual Rect2 _edit_get_rect() const;
virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const;
#endif
void set_polygon(const PoolVector<Vector2> &p_polygon);
PoolVector<Vector2> get_polygon() const;
void set_closed(bool p_closed);
bool is_closed() const;
void set_cull_mode(CullMode p_mode);
CullMode get_cull_mode() const;
virtual RID get_rid() const;
OccluderPolygon2D();
~OccluderPolygon2D();
};
VARIANT_ENUM_CAST(OccluderPolygon2D::CullMode);
class LightOccluder2D : public Node2D {
GDCLASS(LightOccluder2D, Node2D);
RID occluder;
bool enabled;
int mask;
Ref<OccluderPolygon2D> occluder_polygon;
void _poly_changed();
virtual void _physics_interpolated_changed();
protected:
void _notification(int p_what);
static void _bind_methods();
public:
#ifdef TOOLS_ENABLED
virtual Rect2 _edit_get_rect() const;
virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const;
#endif
void set_occluder_polygon(const Ref<OccluderPolygon2D> &p_polygon);
Ref<OccluderPolygon2D> get_occluder_polygon() const;
void set_occluder_light_mask(int p_mask);
int get_occluder_light_mask() const;
String get_configuration_warning() const;
LightOccluder2D();
~LightOccluder2D();
};
#endif // LIGHTOCCLUDER2D_H

View File

@ -45,8 +45,6 @@
#include "scene/2d/collision_shape_2d.h"
#include "scene/2d/cpu_particles_2d.h"
#include "scene/2d/joints_2d.h"
#include "scene/2d/light_2d.h"
#include "scene/2d/light_occluder_2d.h"
#include "scene/2d/line_2d.h"
#include "scene/2d/listener_2d.h"
#include "scene/2d/mesh_instance_2d.h"
@ -413,9 +411,6 @@ void register_scene_types() {
ClassDB::register_class<VisibilityNotifier2D>();
ClassDB::register_class<VisibilityEnabler2D>();
ClassDB::register_class<Polygon2D>();
ClassDB::register_class<Light2D>();
ClassDB::register_class<LightOccluder2D>();
ClassDB::register_class<OccluderPolygon2D>();
ClassDB::register_class<YSort>();
ClassDB::register_class<BackBufferCopy>();

View File

@ -381,15 +381,6 @@ public:
virtual void render_target_set_use_debanding(RID p_render_target, bool p_debanding) = 0;
virtual void render_target_set_sharpen_intensity(RID p_render_target, float p_intensity) = 0;
/* CANVAS SHADOW */
virtual RID canvas_light_shadow_buffer_create(int p_width) = 0;
/* LIGHT SHADOW MAPPING */
virtual RID canvas_light_occluder_create() = 0;
virtual void canvas_light_occluder_set_polylines(RID p_occluder, const PoolVector<Vector2> &p_lines) = 0;
/* INTERPOLATION */
struct InterpolationData {
void notify_free_multimesh(RID p_rid);
@ -440,80 +431,6 @@ public:
CANVAS_RECT_CLIP_UV = 32
};
struct Light : public RID_Data {
bool enabled : 1;
bool on_interpolate_transform_list : 1;
bool interpolated : 1;
Color color;
Transform2D xform_curr;
Transform2D xform_prev;
float height;
float energy;
float scale;
int z_min;
int z_max;
int layer_min;
int layer_max;
int item_mask;
int item_shadow_mask;
RS::CanvasLightMode mode;
RID texture;
Vector2 texture_offset;
RID canvas;
RID shadow_buffer;
int shadow_buffer_size;
float shadow_gradient_length;
RS::CanvasLightShadowFilter shadow_filter;
Color shadow_color;
float shadow_smooth;
void *texture_cache; // implementation dependent
Rect2 rect_cache;
Transform2D xform_cache;
float radius_cache; //used for shadow far plane
Projection shadow_matrix_cache;
Transform2D light_shader_xform;
Vector2 light_shader_pos;
Light *shadows_next_ptr;
Light *filter_next_ptr;
Light *next_ptr;
Light *mask_next_ptr;
RID light_internal;
Light() {
enabled = true;
on_interpolate_transform_list = false;
interpolated = true;
color = Color(1, 1, 1);
shadow_color = Color(0, 0, 0, 0);
height = 0;
z_min = -1024;
z_max = 1024;
layer_min = 0;
layer_max = 0;
item_mask = 1;
scale = 1.0;
energy = 1.0;
item_shadow_mask = 1;
mode = RS::CANVAS_LIGHT_MODE_ADD;
texture_cache = nullptr;
next_ptr = nullptr;
mask_next_ptr = nullptr;
filter_next_ptr = nullptr;
shadow_buffer_size = 2048;
shadow_gradient_length = 0;
shadow_filter = RS::CANVAS_LIGHT_FILTER_NONE;
shadow_smooth = 0.0;
}
};
virtual RID light_internal_create() = 0;
virtual void light_internal_update(RID p_rid, Light *p_light) = 0;
virtual void light_internal_free(RID p_rid) = 0;
struct Item : public RID_Data {
struct Command {
enum Type {
@ -970,38 +887,9 @@ public:
virtual void canvas_begin() = 0;
virtual void canvas_end() = 0;
virtual void canvas_render_items_begin(const Color &p_modulate, Light *p_light, const Transform2D &p_base_transform) {}
virtual void canvas_render_items_begin(const Color &p_modulate, const Transform2D &p_base_transform) {}
virtual void canvas_render_items_end() {}
virtual void canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light, const Transform2D &p_base_transform) = 0;
virtual void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) = 0;
struct LightOccluderInstance : public RID_Data {
bool enabled : 1;
bool on_interpolate_transform_list : 1;
bool interpolated : 1;
RID canvas;
RID polygon;
RID polygon_buffer;
Rect2 aabb_cache;
Transform2D xform_curr;
Transform2D xform_prev;
Transform2D xform_cache;
int light_mask;
RS::CanvasOccluderPolygonCullMode cull_cache;
LightOccluderInstance *next;
LightOccluderInstance() {
enabled = true;
next = nullptr;
light_mask = 1;
cull_cache = RS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED;
on_interpolate_transform_list = false;
interpolated = true;
}
};
virtual void canvas_light_shadow_buffer_update(RID p_buffer, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders, Projection *p_xform_cache) = 0;
virtual void canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, const Transform2D &p_base_transform) = 0;
virtual void reset_canvas() = 0;

View File

@ -40,7 +40,7 @@
static const int z_range = RS::CANVAS_ITEM_Z_MAX - RS::CANVAS_ITEM_Z_MIN + 1;
void RenderingServerCanvas::_render_canvas_item_tree(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RasterizerCanvas::Light *p_lights) {
void RenderingServerCanvas::_render_canvas_item_tree(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate) {
memset(z_list, 0, z_range * sizeof(RasterizerCanvas::Item *));
memset(z_last_list, 0, z_range * sizeof(RasterizerCanvas::Item *));
@ -53,12 +53,12 @@ void RenderingServerCanvas::_render_canvas_item_tree(Item *p_canvas_item, const
_render_canvas_item_cull_by_item(p_canvas_item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, nullptr, nullptr);
}
RSG::canvas_render->canvas_render_items_begin(p_modulate, p_lights, p_transform);
RSG::canvas_render->canvas_render_items_begin(p_modulate, p_transform);
for (int i = 0; i < z_range; i++) {
if (!z_list[i]) {
continue;
}
RSG::canvas_render->canvas_render_items(z_list[i], RS::CANVAS_ITEM_Z_MIN + i, p_modulate, p_lights, p_transform);
RSG::canvas_render->canvas_render_items(z_list[i], RS::CANVAS_ITEM_Z_MIN + i, p_modulate, p_transform);
}
RSG::canvas_render->canvas_render_items_end();
}
@ -697,24 +697,7 @@ void RenderingServerCanvas::_render_canvas_item_cull_by_node(Item *p_canvas_item
}
}
void RenderingServerCanvas::_light_mask_canvas_items(int p_z, RasterizerCanvas::Item *p_canvas_item, RasterizerCanvas::Light *p_masked_lights, int p_canvas_layer_id) {
RasterizerCanvas::Item *ci = p_canvas_item;
while (ci) {
RasterizerCanvas::Light *light = p_masked_lights;
while (light) {
if ((p_canvas_layer_id >= light->layer_min) && (p_canvas_layer_id <= light->layer_max) && (ci->light_mask & light->item_mask) && (p_z >= light->z_min) && (p_z <= light->z_max) && (ci->global_rect_cache.intersects_transformed(light->xform_cache, light->rect_cache))) {
ci->light_masked = true;
}
light = light->mask_next_ptr;
}
ci = ci->next;
}
}
void RenderingServerCanvas::render_canvas(Canvas *p_canvas, const Transform2D &p_transform, RasterizerCanvas::Light *p_lights, RasterizerCanvas::Light *p_masked_lights, const Rect2 &p_clip_rect, int p_canvas_layer_id) {
void RenderingServerCanvas::render_canvas(Canvas *p_canvas, const Transform2D &p_transform, const Rect2 &p_clip_rect, int p_canvas_layer_id) {
RSG::canvas_render->canvas_begin();
if (p_canvas->children_order_dirty) {
@ -785,36 +768,32 @@ void RenderingServerCanvas::render_canvas(Canvas *p_canvas, const Transform2D &p
}
} // if not measure
RSG::canvas_render->canvas_render_items_begin(p_canvas->modulate, p_lights, p_transform);
RSG::canvas_render->canvas_render_items_begin(p_canvas->modulate, p_transform);
for (int i = 0; i < z_range; i++) {
if (!z_list[i]) {
continue;
}
if (p_masked_lights) {
_light_mask_canvas_items(RS::CANVAS_ITEM_Z_MIN + i, z_list[i], p_masked_lights, p_canvas_layer_id);
}
RSG::canvas_render->canvas_render_items(z_list[i], RS::CANVAS_ITEM_Z_MIN + i, p_canvas->modulate, p_lights, p_transform);
RSG::canvas_render->canvas_render_items(z_list[i], RS::CANVAS_ITEM_Z_MIN + i, p_canvas->modulate, p_transform);
}
RSG::canvas_render->canvas_render_items_end();
} else {
for (int i = 0; i < l; i++) {
const Canvas::ChildItem &ci2 = p_canvas->child_items[i];
_render_canvas_item_tree(ci2.item, p_transform, p_clip_rect, p_canvas->modulate, p_lights);
_render_canvas_item_tree(ci2.item, p_transform, p_clip_rect, p_canvas->modulate);
//mirroring (useful for scrolling backgrounds)
if (ci2.mirror.x != 0) {
Transform2D xform2 = p_transform * Transform2D(0, Vector2(ci2.mirror.x, 0));
_render_canvas_item_tree(ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights);
_render_canvas_item_tree(ci2.item, xform2, p_clip_rect, p_canvas->modulate);
}
if (ci2.mirror.y != 0) {
Transform2D xform2 = p_transform * Transform2D(0, Vector2(0, ci2.mirror.y));
_render_canvas_item_tree(ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights);
_render_canvas_item_tree(ci2.item, xform2, p_clip_rect, p_canvas->modulate);
}
if (ci2.mirror.y != 0 && ci2.mirror.x != 0) {
Transform2D xform2 = p_transform * Transform2D(0, ci2.mirror);
_render_canvas_item_tree(ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights);
_render_canvas_item_tree(ci2.item, xform2, p_clip_rect, p_canvas->modulate);
}
}
}
@ -1606,44 +1585,6 @@ void RenderingServerCanvas::canvas_item_set_interpolated(RID p_item, bool p_inte
canvas_item->interpolated = p_interpolated;
}
void RenderingServerCanvas::canvas_light_set_interpolated(RID p_light, bool p_interpolated) {
RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
ERR_FAIL_COND(!clight);
clight->interpolated = p_interpolated;
}
void RenderingServerCanvas::canvas_light_reset_physics_interpolation(RID p_light) {
RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
ERR_FAIL_COND(!clight);
clight->xform_prev = clight->xform_curr;
}
void RenderingServerCanvas::canvas_light_transform_physics_interpolation(RID p_light, Transform2D p_transform) {
RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
ERR_FAIL_COND(!clight);
clight->xform_prev = p_transform * clight->xform_prev;
clight->xform_curr = p_transform * clight->xform_curr;
}
void RenderingServerCanvas::canvas_light_occluder_set_interpolated(RID p_occluder, bool p_interpolated) {
RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder);
ERR_FAIL_COND(!occluder);
occluder->interpolated = p_interpolated;
}
void RenderingServerCanvas::canvas_light_occluder_reset_physics_interpolation(RID p_occluder) {
RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder);
ERR_FAIL_COND(!occluder);
occluder->xform_prev = occluder->xform_curr;
}
void RenderingServerCanvas::canvas_light_occluder_transform_physics_interpolation(RID p_occluder, Transform2D p_transform) {
RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder);
ERR_FAIL_COND(!occluder);
occluder->xform_prev = p_transform * occluder->xform_prev;
occluder->xform_curr = p_transform * occluder->xform_curr;
}
void RenderingServerCanvas::canvas_item_attach_skeleton(RID p_item, RID p_skeleton) {
}
@ -1725,328 +1666,6 @@ void RenderingServerCanvas::canvas_item_set_use_parent_material(RID p_item, bool
_make_bound_dirty(canvas_item);
}
RID RenderingServerCanvas::canvas_light_create() {
RasterizerCanvas::Light *clight = memnew(RasterizerCanvas::Light);
clight->light_internal = RSG::canvas_render->light_internal_create();
return canvas_light_owner.make_rid(clight);
}
void RenderingServerCanvas::canvas_light_attach_to_canvas(RID p_light, RID p_canvas) {
RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
ERR_FAIL_COND(!clight);
if (clight->canvas.is_valid()) {
Canvas *canvas = canvas_owner.getornull(clight->canvas);
canvas->lights.erase(clight);
}
if (!canvas_owner.owns(p_canvas)) {
p_canvas = RID();
}
clight->canvas = p_canvas;
if (clight->canvas.is_valid()) {
Canvas *canvas = canvas_owner.get(clight->canvas);
canvas->lights.insert(clight);
}
}
void RenderingServerCanvas::canvas_light_set_enabled(RID p_light, bool p_enabled) {
RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
ERR_FAIL_COND(!clight);
clight->enabled = p_enabled;
}
void RenderingServerCanvas::canvas_light_set_scale(RID p_light, float p_scale) {
RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
ERR_FAIL_COND(!clight);
clight->scale = p_scale;
}
void RenderingServerCanvas::canvas_light_set_transform(RID p_light, const Transform2D &p_transform) {
RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
ERR_FAIL_COND(!clight);
if (_interpolation_data.interpolation_enabled && clight->interpolated) {
if (!clight->on_interpolate_transform_list) {
_interpolation_data.canvas_light_transform_update_list_curr->push_back(p_light);
clight->on_interpolate_transform_list = true;
} else {
DEV_ASSERT(_interpolation_data.canvas_light_transform_update_list_curr->size());
}
}
clight->xform_curr = p_transform;
}
void RenderingServerCanvas::canvas_light_set_texture(RID p_light, RID p_texture) {
RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
ERR_FAIL_COND(!clight);
clight->texture = p_texture;
}
void RenderingServerCanvas::canvas_light_set_texture_offset(RID p_light, const Vector2 &p_offset) {
RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
ERR_FAIL_COND(!clight);
clight->texture_offset = p_offset;
}
void RenderingServerCanvas::canvas_light_set_color(RID p_light, const Color &p_color) {
RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
ERR_FAIL_COND(!clight);
clight->color = p_color;
}
void RenderingServerCanvas::canvas_light_set_height(RID p_light, float p_height) {
RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
ERR_FAIL_COND(!clight);
clight->height = p_height;
}
void RenderingServerCanvas::canvas_light_set_energy(RID p_light, float p_energy) {
RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
ERR_FAIL_COND(!clight);
clight->energy = p_energy;
}
void RenderingServerCanvas::canvas_light_set_z_range(RID p_light, int p_min_z, int p_max_z) {
RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
ERR_FAIL_COND(!clight);
clight->z_min = p_min_z;
clight->z_max = p_max_z;
}
void RenderingServerCanvas::canvas_light_set_layer_range(RID p_light, int p_min_layer, int p_max_layer) {
RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
ERR_FAIL_COND(!clight);
clight->layer_max = p_max_layer;
clight->layer_min = p_min_layer;
}
void RenderingServerCanvas::canvas_light_set_item_cull_mask(RID p_light, int p_mask) {
RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
ERR_FAIL_COND(!clight);
clight->item_mask = p_mask;
}
void RenderingServerCanvas::canvas_light_set_item_shadow_cull_mask(RID p_light, int p_mask) {
RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
ERR_FAIL_COND(!clight);
clight->item_shadow_mask = p_mask;
}
void RenderingServerCanvas::canvas_light_set_mode(RID p_light, RS::CanvasLightMode p_mode) {
RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
ERR_FAIL_COND(!clight);
clight->mode = p_mode;
}
void RenderingServerCanvas::canvas_light_set_shadow_enabled(RID p_light, bool p_enabled) {
RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
ERR_FAIL_COND(!clight);
if (clight->shadow_buffer.is_valid() == p_enabled) {
return;
}
if (p_enabled) {
clight->shadow_buffer = RSG::storage->canvas_light_shadow_buffer_create(clight->shadow_buffer_size);
} else {
RSG::storage->free(clight->shadow_buffer);
clight->shadow_buffer = RID();
}
}
void RenderingServerCanvas::canvas_light_set_shadow_buffer_size(RID p_light, int p_size) {
ERR_FAIL_COND(p_size < 32 || p_size > 16384);
RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
ERR_FAIL_COND(!clight);
int new_size = next_power_of_2(p_size);
if (new_size == clight->shadow_buffer_size) {
return;
}
clight->shadow_buffer_size = next_power_of_2(p_size);
if (clight->shadow_buffer.is_valid()) {
RSG::storage->free(clight->shadow_buffer);
clight->shadow_buffer = RSG::storage->canvas_light_shadow_buffer_create(clight->shadow_buffer_size);
}
}
void RenderingServerCanvas::canvas_light_set_shadow_gradient_length(RID p_light, float p_length) {
ERR_FAIL_COND(p_length < 0);
RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
ERR_FAIL_COND(!clight);
clight->shadow_gradient_length = p_length;
}
void RenderingServerCanvas::canvas_light_set_shadow_filter(RID p_light, RS::CanvasLightShadowFilter p_filter) {
RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
ERR_FAIL_COND(!clight);
clight->shadow_filter = p_filter;
}
void RenderingServerCanvas::canvas_light_set_shadow_color(RID p_light, const Color &p_color) {
RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
ERR_FAIL_COND(!clight);
clight->shadow_color = p_color;
}
void RenderingServerCanvas::canvas_light_set_shadow_smooth(RID p_light, float p_smooth) {
RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
ERR_FAIL_COND(!clight);
clight->shadow_smooth = p_smooth;
}
RID RenderingServerCanvas::canvas_light_occluder_create() {
RasterizerCanvas::LightOccluderInstance *occluder = memnew(RasterizerCanvas::LightOccluderInstance);
return canvas_light_occluder_owner.make_rid(occluder);
}
void RenderingServerCanvas::canvas_light_occluder_attach_to_canvas(RID p_occluder, RID p_canvas) {
RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder);
ERR_FAIL_COND(!occluder);
if (occluder->canvas.is_valid()) {
Canvas *canvas = canvas_owner.get(occluder->canvas);
canvas->occluders.erase(occluder);
}
if (!canvas_owner.owns(p_canvas)) {
p_canvas = RID();
}
occluder->canvas = p_canvas;
if (occluder->canvas.is_valid()) {
Canvas *canvas = canvas_owner.get(occluder->canvas);
canvas->occluders.insert(occluder);
}
}
void RenderingServerCanvas::canvas_light_occluder_set_enabled(RID p_occluder, bool p_enabled) {
RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder);
ERR_FAIL_COND(!occluder);
occluder->enabled = p_enabled;
}
void RenderingServerCanvas::canvas_light_occluder_set_polygon(RID p_occluder, RID p_polygon) {
RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder);
ERR_FAIL_COND(!occluder);
if (occluder->polygon.is_valid()) {
LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(occluder->polygon);
if (occluder_poly) {
occluder_poly->owners.erase(occluder);
}
}
occluder->polygon = p_polygon;
occluder->polygon_buffer = RID();
if (occluder->polygon.is_valid()) {
LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(p_polygon);
if (!occluder_poly) {
occluder->polygon = RID();
ERR_FAIL_COND(!occluder_poly);
} else {
occluder_poly->owners.insert(occluder);
occluder->polygon_buffer = occluder_poly->occluder;
occluder->aabb_cache = occluder_poly->aabb;
occluder->cull_cache = occluder_poly->cull_mode;
}
}
}
void RenderingServerCanvas::canvas_light_occluder_set_transform(RID p_occluder, const Transform2D &p_xform) {
RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder);
ERR_FAIL_COND(!occluder);
if (_interpolation_data.interpolation_enabled && occluder->interpolated) {
if (!occluder->on_interpolate_transform_list) {
_interpolation_data.canvas_light_occluder_transform_update_list_curr->push_back(p_occluder);
occluder->on_interpolate_transform_list = true;
} else {
DEV_ASSERT(_interpolation_data.canvas_light_occluder_transform_update_list_curr->size());
}
}
occluder->xform_curr = p_xform;
}
void RenderingServerCanvas::canvas_light_occluder_set_light_mask(RID p_occluder, int p_mask) {
RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder);
ERR_FAIL_COND(!occluder);
occluder->light_mask = p_mask;
}
RID RenderingServerCanvas::canvas_occluder_polygon_create() {
LightOccluderPolygon *occluder_poly = memnew(LightOccluderPolygon);
occluder_poly->occluder = RSG::storage->canvas_light_occluder_create();
return canvas_light_occluder_polygon_owner.make_rid(occluder_poly);
}
void RenderingServerCanvas::canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const PoolVector<Vector2> &p_shape, bool p_closed) {
if (p_shape.size() < 3) {
canvas_occluder_polygon_set_shape_as_lines(p_occluder_polygon, p_shape);
return;
}
PoolVector<Vector2> lines;
int lc = p_shape.size() * 2;
lines.resize(lc - (p_closed ? 0 : 2));
{
PoolVector<Vector2>::Write w = lines.write();
PoolVector<Vector2>::Read r = p_shape.read();
int max = lc / 2;
if (!p_closed) {
max--;
}
for (int i = 0; i < max; i++) {
Vector2 a = r[i];
Vector2 b = r[(i + 1) % (lc / 2)];
w[i * 2 + 0] = a;
w[i * 2 + 1] = b;
}
}
canvas_occluder_polygon_set_shape_as_lines(p_occluder_polygon, lines);
}
void RenderingServerCanvas::canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon, const PoolVector<Vector2> &p_shape) {
LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(p_occluder_polygon);
ERR_FAIL_COND(!occluder_poly);
ERR_FAIL_COND(p_shape.size() & 1);
int lc = p_shape.size();
occluder_poly->aabb = Rect2();
{
PoolVector<Vector2>::Read r = p_shape.read();
for (int i = 0; i < lc; i++) {
if (i == 0) {
occluder_poly->aabb.position = r[i];
} else {
occluder_poly->aabb.expand_to(r[i]);
}
}
}
RSG::storage->canvas_light_occluder_set_polylines(occluder_poly->occluder, p_shape);
for (RBSet<RasterizerCanvas::LightOccluderInstance *>::Element *E = occluder_poly->owners.front(); E; E = E->next()) {
E->get()->aabb_cache = occluder_poly->aabb;
}
}
void RenderingServerCanvas::canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon, RS::CanvasOccluderPolygonCullMode p_mode) {
LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(p_occluder_polygon);
ERR_FAIL_COND(!occluder_poly);
occluder_poly->cull_mode = p_mode;
for (RBSet<RasterizerCanvas::LightOccluderInstance *>::Element *E = occluder_poly->owners.front(); E; E = E->next()) {
E->get()->cull_cache = p_mode;
}
}
bool RenderingServerCanvas::free(RID p_rid) {
if (canvas_owner.owns(p_rid)) {
Canvas *canvas = canvas_owner.get(p_rid);
@ -2067,14 +1686,6 @@ bool RenderingServerCanvas::free(RID p_rid) {
canvas->child_items[i].item->parent = RID();
}
for (RBSet<RasterizerCanvas::Light *>::Element *E = canvas->lights.front(); E; E = E->next()) {
E->get()->canvas = RID();
}
for (RBSet<RasterizerCanvas::LightOccluderInstance *>::Element *E = canvas->occluders.front(); E; E = E->next()) {
E->get()->canvas = RID();
}
canvas_owner.free(p_rid);
memdelete(canvas);
@ -2083,7 +1694,6 @@ bool RenderingServerCanvas::free(RID p_rid) {
Item *canvas_item = canvas_item_owner.get(p_rid);
ERR_FAIL_COND_V(!canvas_item, true);
_make_bound_dirty(canvas_item);
_interpolation_data.notify_free_canvas_item(p_rid, *canvas_item);
if (canvas_item->parent.is_valid()) {
if (canvas_owner.owns(canvas_item->parent)) {
@ -2114,59 +1724,6 @@ bool RenderingServerCanvas::free(RID p_rid) {
memdelete(canvas_item);
} else if (canvas_light_owner.owns(p_rid)) {
RasterizerCanvas::Light *canvas_light = canvas_light_owner.get(p_rid);
ERR_FAIL_COND_V(!canvas_light, true);
_interpolation_data.notify_free_canvas_light(p_rid, *canvas_light);
if (canvas_light->canvas.is_valid()) {
Canvas *canvas = canvas_owner.get(canvas_light->canvas);
if (canvas) {
canvas->lights.erase(canvas_light);
}
}
if (canvas_light->shadow_buffer.is_valid()) {
RSG::storage->free(canvas_light->shadow_buffer);
}
RSG::canvas_render->light_internal_free(canvas_light->light_internal);
canvas_light_owner.free(p_rid);
memdelete(canvas_light);
} else if (canvas_light_occluder_owner.owns(p_rid)) {
RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_rid);
ERR_FAIL_COND_V(!occluder, true);
_interpolation_data.notify_free_canvas_light_occluder(p_rid, *occluder);
if (occluder->polygon.is_valid()) {
LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(occluder->polygon);
if (occluder_poly) {
occluder_poly->owners.erase(occluder);
}
}
if (occluder->canvas.is_valid() && canvas_owner.owns(occluder->canvas)) {
Canvas *canvas = canvas_owner.get(occluder->canvas);
canvas->occluders.erase(occluder);
}
canvas_light_occluder_owner.free(p_rid);
memdelete(occluder);
} else if (canvas_light_occluder_polygon_owner.owns(p_rid)) {
LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(p_rid);
ERR_FAIL_COND_V(!occluder_poly, true);
RSG::storage->free(occluder_poly->occluder);
while (occluder_poly->owners.size()) {
occluder_poly->owners.front()->get()->polygon = RID();
occluder_poly->owners.erase(occluder_poly->owners.front());
}
canvas_light_occluder_polygon_owner.free(p_rid);
memdelete(occluder_poly);
} else {
return false;
}
@ -2304,48 +1861,10 @@ void RenderingServerCanvas::update_interpolation_tick(bool p_process) {
_interpolation_data.LIST_CURR->clear();
PANDEMONIUM_UPDATE_INTERPOLATION_TICK(canvas_item_transform_update_list_prev, canvas_item_transform_update_list_curr, Item, canvas_item_owner);
PANDEMONIUM_UPDATE_INTERPOLATION_TICK(canvas_light_transform_update_list_prev, canvas_light_transform_update_list_curr, RasterizerCanvas::Light, canvas_light_owner);
PANDEMONIUM_UPDATE_INTERPOLATION_TICK(canvas_light_occluder_transform_update_list_prev, canvas_light_occluder_transform_update_list_curr, RasterizerCanvas::LightOccluderInstance, canvas_light_occluder_owner);
#undef PANDEMONIUM_UPDATE_INTERPOLATION_TICK
}
void RenderingServerCanvas::InterpolationData::notify_free_canvas_item(RID p_rid, RenderingServerCanvas::Item &r_canvas_item) {
r_canvas_item.on_interpolate_transform_list = false;
if (!interpolation_enabled) {
return;
}
// If the instance was on any of the lists, remove.
canvas_item_transform_update_list_curr->erase_multiple_unordered(p_rid);
canvas_item_transform_update_list_prev->erase_multiple_unordered(p_rid);
}
void RenderingServerCanvas::InterpolationData::notify_free_canvas_light(RID p_rid, RasterizerCanvas::Light &r_canvas_light) {
r_canvas_light.on_interpolate_transform_list = false;
if (!interpolation_enabled) {
return;
}
// If the instance was on any of the lists, remove.
canvas_light_transform_update_list_curr->erase_multiple_unordered(p_rid);
canvas_light_transform_update_list_prev->erase_multiple_unordered(p_rid);
}
void RenderingServerCanvas::InterpolationData::notify_free_canvas_light_occluder(RID p_rid, RasterizerCanvas::LightOccluderInstance &r_canvas_light_occluder) {
r_canvas_light_occluder.on_interpolate_transform_list = false;
if (!interpolation_enabled) {
return;
}
// If the instance was on any of the lists, remove.
canvas_light_occluder_transform_update_list_curr->erase_multiple_unordered(p_rid);
canvas_light_occluder_transform_update_list_prev->erase_multiple_unordered(p_rid);
}
RenderingServerCanvas::RenderingServerCanvas() {
_canvas_cull_mode = CANVAS_CULL_MODE_NODE;

View File

@ -92,23 +92,6 @@ public:
}
};
struct LightOccluderPolygon : RID_Data {
bool active;
Rect2 aabb;
RS::CanvasOccluderPolygonCullMode cull_mode;
RID occluder;
RBSet<RasterizerCanvas::LightOccluderInstance *> owners;
LightOccluderPolygon() {
active = false;
cull_mode = RS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED;
}
};
RID_Owner<LightOccluderPolygon> canvas_light_occluder_polygon_owner;
RID_Owner<RasterizerCanvas::LightOccluderInstance> canvas_light_occluder_owner;
struct Canvas : public RenderingServerViewport::CanvasBase {
RBSet<RID> viewports;
struct ChildItem {
@ -119,10 +102,6 @@ public:
}
};
RBSet<RasterizerCanvas::Light *> lights;
RBSet<RasterizerCanvas::LightOccluderInstance *> occluders;
bool children_order_dirty;
Vector<ChildItem> child_items;
Color modulate;
@ -153,7 +132,6 @@ public:
mutable RID_Owner<Canvas> canvas_owner;
RID_Owner<Item> canvas_item_owner;
RID_Owner<RasterizerCanvas::Light> canvas_light_owner;
bool disable_scale;
@ -164,9 +142,9 @@ private:
};
CanvasCullMode _canvas_cull_mode;
void _render_canvas_item_tree(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RasterizerCanvas::Light *p_lights);
void _render_canvas_item_tree(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate);
void _light_mask_canvas_items(int p_z, RasterizerCanvas::Item *p_canvas_item, RasterizerCanvas::Light *p_masked_lights, int p_canvas_layer_id);
void _light_mask_canvas_items(int p_z, RasterizerCanvas::Item *p_canvas_item, int p_canvas_layer_id);
RasterizerCanvas::Item **z_list;
RasterizerCanvas::Item **z_last_list;
@ -205,7 +183,7 @@ private:
//////////////////////////////////////////////////////////////////////////////
public:
void render_canvas(Canvas *p_canvas, const Transform2D &p_transform, RasterizerCanvas::Light *p_lights, RasterizerCanvas::Light *p_masked_lights, const Rect2 &p_clip_rect, int p_canvas_layer_id);
void render_canvas(Canvas *p_canvas, const Transform2D &p_transform, const Rect2 &p_clip_rect, int p_canvas_layer_id);
RID canvas_create();
void canvas_set_item_mirroring(RID p_canvas, RID p_item, const Point2 &p_mirroring);
@ -270,49 +248,6 @@ public:
void _canvas_item_invalidate_local_bound(RID p_item);
void _canvas_item_remove_references(RID p_item, RID p_rid);
RID canvas_light_create();
void canvas_light_attach_to_canvas(RID p_light, RID p_canvas);
void canvas_light_set_enabled(RID p_light, bool p_enabled);
void canvas_light_set_scale(RID p_light, float p_scale);
void canvas_light_set_transform(RID p_light, const Transform2D &p_transform);
void canvas_light_set_texture(RID p_light, RID p_texture);
void canvas_light_set_texture_offset(RID p_light, const Vector2 &p_offset);
void canvas_light_set_color(RID p_light, const Color &p_color);
void canvas_light_set_height(RID p_light, float p_height);
void canvas_light_set_energy(RID p_light, float p_energy);
void canvas_light_set_z_range(RID p_light, int p_min_z, int p_max_z);
void canvas_light_set_layer_range(RID p_light, int p_min_layer, int p_max_layer);
void canvas_light_set_item_cull_mask(RID p_light, int p_mask);
void canvas_light_set_item_shadow_cull_mask(RID p_light, int p_mask);
void canvas_light_set_mode(RID p_light, RS::CanvasLightMode p_mode);
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, RS::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);
void canvas_light_set_interpolated(RID p_light, bool p_interpolated);
void canvas_light_reset_physics_interpolation(RID p_light);
void canvas_light_transform_physics_interpolation(RID p_light, Transform2D p_transform);
RID canvas_light_occluder_create();
void canvas_light_occluder_attach_to_canvas(RID p_occluder, RID p_canvas);
void canvas_light_occluder_set_enabled(RID p_occluder, bool p_enabled);
void canvas_light_occluder_set_polygon(RID p_occluder, RID p_polygon);
void canvas_light_occluder_set_transform(RID p_occluder, const Transform2D &p_xform);
void canvas_light_occluder_set_light_mask(RID p_occluder, int p_mask);
void canvas_light_occluder_set_interpolated(RID p_occluder, bool p_interpolated);
void canvas_light_occluder_reset_physics_interpolation(RID p_occluder);
void canvas_light_occluder_transform_physics_interpolation(RID p_occluder, Transform2D p_transform);
RID canvas_occluder_polygon_create();
void canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const PoolVector<Vector2> &p_shape, bool p_closed);
void canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon, const PoolVector<Vector2> &p_shape);
void canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon, RS::CanvasOccluderPolygonCullMode p_mode);
bool free(RID p_rid);
// Interpolation
@ -321,22 +256,10 @@ public:
void set_physics_interpolation_enabled(bool p_enabled) { _interpolation_data.interpolation_enabled = p_enabled; }
struct InterpolationData {
void notify_free_canvas_item(RID p_rid, RenderingServerCanvas::Item &r_canvas_item);
void notify_free_canvas_light(RID p_rid, RasterizerCanvas::Light &r_canvas_light);
void notify_free_canvas_light_occluder(RID p_rid, RasterizerCanvas::LightOccluderInstance &r_canvas_light_occluder);
LocalVector<RID> canvas_item_transform_update_lists[2];
LocalVector<RID> *canvas_item_transform_update_list_curr = &canvas_item_transform_update_lists[0];
LocalVector<RID> *canvas_item_transform_update_list_prev = &canvas_item_transform_update_lists[1];
LocalVector<RID> canvas_light_transform_update_lists[2];
LocalVector<RID> *canvas_light_transform_update_list_curr = &canvas_light_transform_update_lists[0];
LocalVector<RID> *canvas_light_transform_update_list_prev = &canvas_light_transform_update_lists[1];
LocalVector<RID> canvas_light_occluder_transform_update_lists[2];
LocalVector<RID> *canvas_light_occluder_transform_update_list_curr = &canvas_light_occluder_transform_update_lists[0];
LocalVector<RID> *canvas_light_occluder_transform_update_list_prev = &canvas_light_occluder_transform_update_lists[1];
bool interpolation_enabled = false;
} _interpolation_data;

View File

@ -470,51 +470,6 @@ public:
BIND1(canvas_item_reset_physics_interpolation, RID)
BIND2(canvas_item_transform_physics_interpolation, RID, Transform2D)
BIND0R(RID, canvas_light_create)
BIND2(canvas_light_attach_to_canvas, RID, RID)
BIND2(canvas_light_set_enabled, RID, bool)
BIND2(canvas_light_set_scale, RID, float)
BIND2(canvas_light_set_transform, RID, const Transform2D &)
BIND2(canvas_light_set_texture, RID, RID)
BIND2(canvas_light_set_texture_offset, RID, const Vector2 &)
BIND2(canvas_light_set_color, RID, const Color &)
BIND2(canvas_light_set_height, RID, float)
BIND2(canvas_light_set_energy, RID, float)
BIND3(canvas_light_set_z_range, RID, int, int)
BIND3(canvas_light_set_layer_range, RID, int, int)
BIND2(canvas_light_set_item_cull_mask, RID, int)
BIND2(canvas_light_set_item_shadow_cull_mask, RID, int)
BIND2(canvas_light_set_mode, RID, CanvasLightMode)
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)
BIND2(canvas_light_set_interpolated, RID, bool)
BIND1(canvas_light_reset_physics_interpolation, RID)
BIND2(canvas_light_transform_physics_interpolation, RID, Transform2D)
BIND0R(RID, canvas_light_occluder_create)
BIND2(canvas_light_occluder_attach_to_canvas, RID, RID)
BIND2(canvas_light_occluder_set_enabled, RID, bool)
BIND2(canvas_light_occluder_set_polygon, RID, RID)
BIND2(canvas_light_occluder_set_transform, RID, const Transform2D &)
BIND2(canvas_light_occluder_set_light_mask, RID, int)
BIND2(canvas_light_occluder_set_interpolated, RID, bool)
BIND1(canvas_light_occluder_reset_physics_interpolation, RID)
BIND2(canvas_light_occluder_transform_physics_interpolation, RID, Transform2D)
BIND0R(RID, canvas_occluder_polygon_create)
BIND3(canvas_occluder_polygon_set_shape, RID, const PoolVector<Vector2> &, bool)
BIND2(canvas_occluder_polygon_set_shape_as_lines, RID, const PoolVector<Vector2> &)
BIND2(canvas_occluder_polygon_set_cull_mode, RID, CanvasOccluderPolygonCullMode)
/* BLACK BARS */
virtual void black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom);

View File

@ -91,112 +91,14 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport) {
RBMap<Viewport::CanvasKey, Viewport::CanvasData *> canvas_map;
Rect2 clip_rect(0, 0, p_viewport->size.x, p_viewport->size.y);
RasterizerCanvas::Light *lights = nullptr;
RasterizerCanvas::Light *lights_with_shadow = nullptr;
RasterizerCanvas::Light *lights_with_mask = nullptr;
Rect2 shadow_rect;
for (RBMap<RID, Viewport::CanvasData>::Element *E = p_viewport->canvas_map.front(); E; E = E->next()) {
RenderingServerCanvas::Canvas *canvas = static_cast<RenderingServerCanvas::Canvas *>(E->get().canvas);
Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E->get(), clip_rect.size);
//find lights in canvas
for (RBSet<RasterizerCanvas::Light *>::Element *F = canvas->lights.front(); F; F = F->next()) {
RasterizerCanvas::Light *cl = F->get();
if (cl->enabled && cl->texture.is_valid()) {
//not super efficient..
Size2 tsize = RSG::storage->texture_size_with_proxy(cl->texture);
// Skip using lights with texture of 0 size
if (!tsize.x || !tsize.y) {
continue;
}
tsize *= cl->scale;
Vector2 offset = tsize / 2.0;
cl->rect_cache = Rect2(-offset + cl->texture_offset, tsize);
if (!RSG::canvas->_interpolation_data.interpolation_enabled || !cl->interpolated) {
cl->xform_cache = xf * cl->xform_curr;
} else {
real_t f = Engine::get_singleton()->get_physics_interpolation_fraction();
TransformInterpolator::interpolate_transform_2d(cl->xform_prev, cl->xform_curr, cl->xform_cache, f);
cl->xform_cache = xf * cl->xform_cache;
}
if (clip_rect.intersects_transformed(cl->xform_cache, cl->rect_cache)) {
cl->filter_next_ptr = lights;
lights = cl;
cl->texture_cache = nullptr;
Transform2D scale;
scale.scale(cl->rect_cache.size);
scale.columns[2] = cl->rect_cache.position;
cl->light_shader_xform = (cl->xform_cache * scale).affine_inverse();
cl->light_shader_pos = cl->xform_cache[2];
if (cl->shadow_buffer.is_valid()) {
cl->shadows_next_ptr = lights_with_shadow;
if (lights_with_shadow == nullptr) {
shadow_rect = cl->xform_cache.xform(cl->rect_cache);
} else {
shadow_rect = shadow_rect.merge(cl->xform_cache.xform(cl->rect_cache));
}
lights_with_shadow = cl;
cl->radius_cache = cl->rect_cache.size.length();
}
if (cl->mode == RS::CANVAS_LIGHT_MODE_MASK) {
cl->mask_next_ptr = lights_with_mask;
lights_with_mask = cl;
}
}
RSG::canvas_render->light_internal_update(cl->light_internal, cl);
}
}
canvas_map[Viewport::CanvasKey(E->key(), E->get().layer, E->get().sublayer)] = &E->get();
}
if (lights_with_shadow) {
//update shadows if any
RasterizerCanvas::LightOccluderInstance *occluders = nullptr;
//make list of occluders
for (RBMap<RID, Viewport::CanvasData>::Element *E = p_viewport->canvas_map.front(); E; E = E->next()) {
RenderingServerCanvas::Canvas *canvas = static_cast<RenderingServerCanvas::Canvas *>(E->get().canvas);
Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E->get(), clip_rect.size);
for (RBSet<RasterizerCanvas::LightOccluderInstance *>::Element *F = canvas->occluders.front(); F; F = F->next()) {
RasterizerCanvas::LightOccluderInstance *occluder = F->get();
if (!occluder->enabled) {
continue;
}
if (!RSG::canvas->_interpolation_data.interpolation_enabled || !occluder->interpolated) {
occluder->xform_cache = xf * occluder->xform_curr;
} else {
real_t f = Engine::get_singleton()->get_physics_interpolation_fraction();
TransformInterpolator::interpolate_transform_2d(occluder->xform_prev, occluder->xform_curr, occluder->xform_cache, f);
occluder->xform_cache = xf * occluder->xform_cache;
}
if (shadow_rect.intersects_transformed(occluder->xform_cache, occluder->aabb_cache)) {
occluder->next = occluders;
occluders = occluder;
}
}
}
//update the light shadowmaps with them
RasterizerCanvas::Light *light = lights_with_shadow;
while (light) {
RSG::canvas_render->canvas_light_shadow_buffer_update(light->shadow_buffer, light->xform_cache.affine_inverse(), light->item_shadow_mask, light->radius_cache / 1000.0, light->radius_cache * 1.1, occluders, &light->shadow_matrix_cache);
light = light->shadows_next_ptr;
}
//RSG::canvas_render->reset_canvas();
}
RSG::rasterizer->restore_render_target(!scenario_draw_canvas_bg && can_draw_3d);
if (scenario_draw_canvas_bg && canvas_map.front() && canvas_map.front()->key().get_layer() > scenario_canvas_max_layer) {
@ -213,19 +115,9 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport) {
Transform2D xform = _canvas_get_transform(p_viewport, canvas, E->get(), clip_rect.size);
RasterizerCanvas::Light *canvas_lights = nullptr;
RasterizerCanvas::Light *ptr = lights;
int canvas_layer_id = E->get()->layer;
while (ptr) {
if (canvas_layer_id >= ptr->layer_min && canvas_layer_id <= ptr->layer_max) {
ptr->next_ptr = canvas_lights;
canvas_lights = ptr;
}
ptr = ptr->filter_next_ptr;
}
RSG::canvas->render_canvas(canvas, xform, canvas_lights, lights_with_mask, clip_rect, canvas_layer_id);
RSG::canvas->render_canvas(canvas, xform, clip_rect, canvas_layer_id);
if (scenario_draw_canvas_bg && E->key().get_layer() >= scenario_canvas_max_layer) {
if (!can_draw_3d) {

View File

@ -151,8 +151,6 @@ void RenderingServerWrapMT::finish() {
instance_free_cached_ids();
canvas_free_cached_ids();
canvas_item_free_cached_ids();
canvas_light_occluder_free_cached_ids();
canvas_occluder_polygon_free_cached_ids();
}
void RenderingServerWrapMT::set_use_vsync_callback(bool p_enable) {

View File

@ -383,51 +383,6 @@ public:
FUNC1(canvas_item_reset_physics_interpolation, RID)
FUNC2(canvas_item_transform_physics_interpolation, RID, Transform2D)
FUNC0R(RID, canvas_light_create)
FUNC2(canvas_light_attach_to_canvas, RID, RID)
FUNC2(canvas_light_set_enabled, RID, bool)
FUNC2(canvas_light_set_scale, RID, float)
FUNC2(canvas_light_set_transform, RID, const Transform2D &)
FUNC2(canvas_light_set_texture, RID, RID)
FUNC2(canvas_light_set_texture_offset, RID, const Vector2 &)
FUNC2(canvas_light_set_color, RID, const Color &)
FUNC2(canvas_light_set_height, RID, float)
FUNC2(canvas_light_set_energy, RID, float)
FUNC3(canvas_light_set_z_range, RID, int, int)
FUNC3(canvas_light_set_layer_range, RID, int, int)
FUNC2(canvas_light_set_item_cull_mask, RID, int)
FUNC2(canvas_light_set_item_shadow_cull_mask, RID, int)
FUNC2(canvas_light_set_mode, RID, CanvasLightMode)
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)
FUNC2(canvas_light_set_interpolated, RID, bool)
FUNC1(canvas_light_reset_physics_interpolation, RID)
FUNC2(canvas_light_transform_physics_interpolation, RID, Transform2D)
FUNCRID(canvas_light_occluder)
FUNC2(canvas_light_occluder_attach_to_canvas, RID, RID)
FUNC2(canvas_light_occluder_set_enabled, RID, bool)
FUNC2(canvas_light_occluder_set_polygon, RID, RID)
FUNC2(canvas_light_occluder_set_transform, RID, const Transform2D &)
FUNC2(canvas_light_occluder_set_light_mask, RID, int)
FUNC2(canvas_light_occluder_set_interpolated, RID, bool)
FUNC1(canvas_light_occluder_reset_physics_interpolation, RID)
FUNC2(canvas_light_occluder_transform_physics_interpolation, RID, Transform2D)
FUNCRID(canvas_occluder_polygon)
FUNC3(canvas_occluder_polygon_set_shape, RID, const PoolVector<Vector2> &, bool)
FUNC2(canvas_occluder_polygon_set_shape_as_lines, RID, const PoolVector<Vector2> &)
FUNC2(canvas_occluder_polygon_set_cull_mode, RID, CanvasOccluderPolygonCullMode)
/* BLACK BARS */
FUNC4(black_bars_set_margins, int, int, int, int)

View File

@ -2043,45 +2043,6 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("canvas_item_set_use_parent_material", "item", "enabled"), &RenderingServer::canvas_item_set_use_parent_material);
ClassDB::bind_method(D_METHOD("debug_canvas_item_get_rect", "item"), &RenderingServer::debug_canvas_item_get_rect);
ClassDB::bind_method(D_METHOD("debug_canvas_item_get_local_bound", "item"), &RenderingServer::debug_canvas_item_get_local_bound);
ClassDB::bind_method(D_METHOD("canvas_light_create"), &RenderingServer::canvas_light_create);
ClassDB::bind_method(D_METHOD("canvas_light_attach_to_canvas", "light", "canvas"), &RenderingServer::canvas_light_attach_to_canvas);
ClassDB::bind_method(D_METHOD("canvas_light_set_enabled", "light", "enabled"), &RenderingServer::canvas_light_set_enabled);
ClassDB::bind_method(D_METHOD("canvas_light_set_scale", "light", "scale"), &RenderingServer::canvas_light_set_scale);
ClassDB::bind_method(D_METHOD("canvas_light_set_transform", "light", "transform"), &RenderingServer::canvas_light_set_transform);
ClassDB::bind_method(D_METHOD("canvas_light_set_texture", "light", "texture"), &RenderingServer::canvas_light_set_texture);
ClassDB::bind_method(D_METHOD("canvas_light_set_texture_offset", "light", "offset"), &RenderingServer::canvas_light_set_texture_offset);
ClassDB::bind_method(D_METHOD("canvas_light_set_color", "light", "color"), &RenderingServer::canvas_light_set_color);
ClassDB::bind_method(D_METHOD("canvas_light_set_height", "light", "height"), &RenderingServer::canvas_light_set_height);
ClassDB::bind_method(D_METHOD("canvas_light_set_energy", "light", "energy"), &RenderingServer::canvas_light_set_energy);
ClassDB::bind_method(D_METHOD("canvas_light_set_z_range", "light", "min_z", "max_z"), &RenderingServer::canvas_light_set_z_range);
ClassDB::bind_method(D_METHOD("canvas_light_set_layer_range", "light", "min_layer", "max_layer"), &RenderingServer::canvas_light_set_layer_range);
ClassDB::bind_method(D_METHOD("canvas_light_set_item_cull_mask", "light", "mask"), &RenderingServer::canvas_light_set_item_cull_mask);
ClassDB::bind_method(D_METHOD("canvas_light_set_item_shadow_cull_mask", "light", "mask"), &RenderingServer::canvas_light_set_item_shadow_cull_mask);
ClassDB::bind_method(D_METHOD("canvas_light_set_mode", "light", "mode"), &RenderingServer::canvas_light_set_mode);
ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_enabled", "light", "enabled"), &RenderingServer::canvas_light_set_shadow_enabled);
ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_buffer_size", "light", "size"), &RenderingServer::canvas_light_set_shadow_buffer_size);
ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_gradient_length", "light", "length"), &RenderingServer::canvas_light_set_shadow_gradient_length);
ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_filter", "light", "filter"), &RenderingServer::canvas_light_set_shadow_filter);
ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_color", "light", "color"), &RenderingServer::canvas_light_set_shadow_color);
ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_smooth", "light", "smooth"), &RenderingServer::canvas_light_set_shadow_smooth);
ClassDB::bind_method(D_METHOD("canvas_light_set_interpolated", "light", "interpolated"), &RenderingServer::canvas_light_set_interpolated);
ClassDB::bind_method(D_METHOD("canvas_light_reset_physics_interpolation", "light"), &RenderingServer::canvas_light_reset_physics_interpolation);
ClassDB::bind_method(D_METHOD("canvas_light_transform_physics_interpolation", "light", "xform"), &RenderingServer::canvas_light_transform_physics_interpolation);
ClassDB::bind_method(D_METHOD("canvas_light_occluder_create"), &RenderingServer::canvas_light_occluder_create);
ClassDB::bind_method(D_METHOD("canvas_light_occluder_attach_to_canvas", "occluder", "canvas"), &RenderingServer::canvas_light_occluder_attach_to_canvas);
ClassDB::bind_method(D_METHOD("canvas_light_occluder_set_enabled", "occluder", "enabled"), &RenderingServer::canvas_light_occluder_set_enabled);
ClassDB::bind_method(D_METHOD("canvas_light_occluder_set_polygon", "occluder", "polygon"), &RenderingServer::canvas_light_occluder_set_polygon);
ClassDB::bind_method(D_METHOD("canvas_light_occluder_set_transform", "occluder", "transform"), &RenderingServer::canvas_light_occluder_set_transform);
ClassDB::bind_method(D_METHOD("canvas_light_occluder_set_light_mask", "occluder", "mask"), &RenderingServer::canvas_light_occluder_set_light_mask);
ClassDB::bind_method(D_METHOD("canvas_light_occluder_set_interpolated", "occluder", "interpolated"), &RenderingServer::canvas_light_occluder_set_interpolated);
ClassDB::bind_method(D_METHOD("canvas_light_occluder_reset_physics_interpolation", "occluder"), &RenderingServer::canvas_light_occluder_reset_physics_interpolation);
ClassDB::bind_method(D_METHOD("canvas_light_occluder_transform_physics_interpolation", "occluder", "xform"), &RenderingServer::canvas_light_occluder_transform_physics_interpolation);
ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_create"), &RenderingServer::canvas_occluder_polygon_create);
ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_set_shape", "occluder_polygon", "shape", "closed"), &RenderingServer::canvas_occluder_polygon_set_shape);
ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_set_shape_as_lines", "occluder_polygon", "shape"), &RenderingServer::canvas_occluder_polygon_set_shape_as_lines);
ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_set_cull_mode", "occluder_polygon", "mode"), &RenderingServer::canvas_occluder_polygon_set_cull_mode);
ClassDB::bind_method(D_METHOD("black_bars_set_margins", "left", "top", "right", "bottom"), &RenderingServer::black_bars_set_margins);
ClassDB::bind_method(D_METHOD("black_bars_set_images", "left", "top", "right", "bottom"), &RenderingServer::black_bars_set_images);
@ -2256,22 +2217,6 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(NINE_PATCH_TILE);
BIND_ENUM_CONSTANT(NINE_PATCH_TILE_FIT);
BIND_ENUM_CONSTANT(CANVAS_LIGHT_MODE_ADD);
BIND_ENUM_CONSTANT(CANVAS_LIGHT_MODE_SUB);
BIND_ENUM_CONSTANT(CANVAS_LIGHT_MODE_MIX);
BIND_ENUM_CONSTANT(CANVAS_LIGHT_MODE_MASK);
BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_NONE);
BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_PCF3);
BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_PCF5);
BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_PCF7);
BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_PCF9);
BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_PCF13);
BIND_ENUM_CONSTANT(CANVAS_OCCLUDER_POLYGON_CULL_DISABLED);
BIND_ENUM_CONSTANT(CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE);
BIND_ENUM_CONSTANT(CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE);
BIND_ENUM_CONSTANT(INFO_OBJECTS_IN_FRAME);
BIND_ENUM_CONSTANT(INFO_VERTICES_IN_FRAME);
BIND_ENUM_CONSTANT(INFO_MATERIAL_CHANGES_IN_FRAME);

View File

@ -676,72 +676,6 @@ public:
virtual void canvas_item_reset_physics_interpolation(RID p_item) = 0;
virtual void canvas_item_transform_physics_interpolation(RID p_item, Transform2D p_transform) = 0;
virtual RID canvas_light_create() = 0;
virtual void canvas_light_attach_to_canvas(RID p_light, RID p_canvas) = 0;
virtual void canvas_light_set_enabled(RID p_light, bool p_enabled) = 0;
virtual void canvas_light_set_scale(RID p_light, float p_scale) = 0;
virtual void canvas_light_set_transform(RID p_light, const Transform2D &p_transform) = 0;
virtual void canvas_light_set_texture(RID p_light, RID p_texture) = 0;
virtual void canvas_light_set_texture_offset(RID p_light, const Vector2 &p_offset) = 0;
virtual void canvas_light_set_color(RID p_light, const Color &p_color) = 0;
virtual void canvas_light_set_height(RID p_light, float p_height) = 0;
virtual void canvas_light_set_energy(RID p_light, float p_energy) = 0;
virtual void canvas_light_set_z_range(RID p_light, int p_min_z, int p_max_z) = 0;
virtual void canvas_light_set_layer_range(RID p_light, int p_min_layer, int p_max_layer) = 0;
virtual void canvas_light_set_item_cull_mask(RID p_light, int p_mask) = 0;
virtual void canvas_light_set_item_shadow_cull_mask(RID p_light, int p_mask) = 0;
virtual void canvas_light_set_interpolated(RID p_light, bool p_interpolated) = 0;
virtual void canvas_light_reset_physics_interpolation(RID p_light) = 0;
virtual void canvas_light_transform_physics_interpolation(RID p_light, Transform2D p_transform) = 0;
enum CanvasLightMode {
CANVAS_LIGHT_MODE_ADD,
CANVAS_LIGHT_MODE_SUB,
CANVAS_LIGHT_MODE_MIX,
CANVAS_LIGHT_MODE_MASK,
};
virtual void canvas_light_set_mode(RID p_light, CanvasLightMode p_mode) = 0;
enum CanvasLightShadowFilter {
CANVAS_LIGHT_FILTER_NONE,
CANVAS_LIGHT_FILTER_PCF3,
CANVAS_LIGHT_FILTER_PCF5,
CANVAS_LIGHT_FILTER_PCF7,
CANVAS_LIGHT_FILTER_PCF9,
CANVAS_LIGHT_FILTER_PCF13,
};
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;
virtual RID canvas_light_occluder_create() = 0;
virtual void canvas_light_occluder_attach_to_canvas(RID p_occluder, RID p_canvas) = 0;
virtual void canvas_light_occluder_set_enabled(RID p_occluder, bool p_enabled) = 0;
virtual void canvas_light_occluder_set_polygon(RID p_occluder, RID p_polygon) = 0;
virtual void canvas_light_occluder_set_transform(RID p_occluder, const Transform2D &p_xform) = 0;
virtual void canvas_light_occluder_set_light_mask(RID p_occluder, int p_mask) = 0;
virtual void canvas_light_occluder_set_interpolated(RID p_occluder, bool p_interpolated) = 0;
virtual void canvas_light_occluder_reset_physics_interpolation(RID p_occluder) = 0;
virtual void canvas_light_occluder_transform_physics_interpolation(RID p_occluder, Transform2D p_transform) = 0;
virtual RID canvas_occluder_polygon_create() = 0;
virtual void canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const PoolVector<Vector2> &p_shape, bool p_closed) = 0;
virtual void canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon, const PoolVector<Vector2> &p_shape) = 0;
enum CanvasOccluderPolygonCullMode {
CANVAS_OCCLUDER_POLYGON_CULL_DISABLED,
CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE,
CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE,
};
virtual void canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon, CanvasOccluderPolygonCullMode p_mode) = 0;
/* BLACK BARS */
virtual void black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom) = 0;
@ -854,9 +788,6 @@ VARIANT_ENUM_CAST(RenderingServer::ViewportDebugDraw);
VARIANT_ENUM_CAST(RenderingServer::ScenarioDebugMode);
VARIANT_ENUM_CAST(RenderingServer::InstanceType);
VARIANT_ENUM_CAST(RenderingServer::NinePatchAxisMode);
VARIANT_ENUM_CAST(RenderingServer::CanvasLightMode);
VARIANT_ENUM_CAST(RenderingServer::CanvasLightShadowFilter);
VARIANT_ENUM_CAST(RenderingServer::CanvasOccluderPolygonCullMode);
VARIANT_ENUM_CAST(RenderingServer::RenderInfo);
VARIANT_ENUM_CAST(RenderingServer::Features);
VARIANT_ENUM_CAST(RenderingServer::MultimeshTransformFormat);