mirror of
https://github.com/Relintai/pandemonium_engine_minimal.git
synced 2024-12-21 16:56:50 +01:00
Removed canvas lights and shadows.
This commit is contained in:
parent
219534c1ae
commit
d821a15748
@ -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() {}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
@ -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
|
@ -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);
|
||||
}
|
@ -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
|
@ -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>();
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user