diff --git a/modules/vertex_lights_2d/vertex_light_data.cpp b/modules/vertex_lights_2d/vertex_light_data.cpp index 78721eeb81..ac33ed1a1f 100644 --- a/modules/vertex_lights_2d/vertex_light_data.cpp +++ b/modules/vertex_lights_2d/vertex_light_data.cpp @@ -39,6 +39,61 @@ void VertexLights2DServer::VertexLightQuadrant2D::get_lights(Listenabled) { + continue; + } + + if (l->range.x == 0 || l->range.y == 0) { + continue; + } + + if ((l->item_cull_mask & p_item_cull_mask) == 0) { + continue; + } + + if (p_layer < l->z_range.x || p_layer > l->z_range.y) { + continue; + } + + Vector2 light_to_pos = p_position - l->position; + + Vector2 light_to_pos_normal_space = light_to_pos; + light_to_pos_normal_space.x /= static_cast(l->range.x); + light_to_pos_normal_space.y /= static_cast(l->range.y); + + real_t ltpnsl = light_to_pos_normal_space.length(); + + // Position is outside the light's range. + if (ltpnsl >= 1) { + continue; + } + + real_t attenuation = pow(1.0 - ltpnsl, l->attenuation); + + Color ac = l->color * attenuation; + + switch (l->mode) { + case VertexLights2DServer::VERTEX_LIGHT_2D_MODE_ADD: { + c += ac; + } break; + case VertexLights2DServer::VERTEX_LIGHT_2D_MODE_SUB: { + c -= ac; + } break; + case VertexLights2DServer::VERTEX_LIGHT_2D_MODE_MIX: { + c = c.blend(ac); + } break; + } + } + + return c; +} + //VertexLightMap2D void VertexLights2DServer::VertexLightMap2D::recreate_quadrants() { @@ -124,3 +179,23 @@ void VertexLights2DServer::VertexLightMap2D::clear() { l->quadrant = NULL; } } + +Color VertexLights2DServer::VertexLightMap2D::sample_light(const Vector2 &p_position, const int p_item_cull_mask, const int p_layer) { + Color c = Color(); + + Vector2i quadrant_position = to_quadrant_position(p_position); + + for (int x = quadrant_position.x - 1; x <= quadrant_position.x + 1; ++x) { + for (int y = quadrant_position.y - 1; y <= quadrant_position.y + 1; ++y) { + Vector2i qp = Vector2i(x, y); + + if (quadrants.has(qp)) { + VertexLightQuadrant2D *q = quadrants[qp]; + + c = q->sample_light(c, p_position, p_item_cull_mask, p_layer); + } + } + } + + return c; +} diff --git a/modules/vertex_lights_2d/vertex_lights_2d_server.cpp b/modules/vertex_lights_2d/vertex_lights_2d_server.cpp index 2c431639dd..d076b9e198 100644 --- a/modules/vertex_lights_2d/vertex_lights_2d_server.cpp +++ b/modules/vertex_lights_2d/vertex_lights_2d_server.cpp @@ -245,6 +245,15 @@ void VertexLights2DServer::light_set_item_cull_mask(RID p_light, const int p_ite light->item_cull_mask = p_item_cull_mask; } +// Sampling + +Color VertexLights2DServer::sample_light(RID p_map, const Vector2 &p_position, const int p_item_cull_mask, const int p_layer) { + VertexLightMap2D *map = map_owner.getornull(p_map); + ERR_FAIL_COND_V(map == NULL, Color()); + + return map->sample_light(p_position, p_item_cull_mask, p_layer); +} + // Rest void VertexLights2DServer::free(RID p_rid) { @@ -337,6 +346,10 @@ void VertexLights2DServer::_bind_methods() { ClassDB::bind_method(D_METHOD("light_get_item_cull_mask", "light"), &VertexLights2DServer::light_get_item_cull_mask); ClassDB::bind_method(D_METHOD("light_set_item_cull_mask", "light", "item_cull_mask"), &VertexLights2DServer::light_set_item_cull_mask); + + // Sampling + + ClassDB::bind_method(D_METHOD("sample_light", "map", "position", "item_cull_mask", "layer"), &VertexLights2DServer::sample_light, DEFVAL(1), DEFVAL(0)); // Rest diff --git a/modules/vertex_lights_2d/vertex_lights_2d_server.h b/modules/vertex_lights_2d/vertex_lights_2d_server.h index 429b27f19f..d9280fb7c5 100644 --- a/modules/vertex_lights_2d/vertex_lights_2d_server.h +++ b/modules/vertex_lights_2d/vertex_lights_2d_server.h @@ -83,7 +83,7 @@ class VertexLights2DServer : public Object { Vector2i light_get_range(RID p_light); void light_set_range(RID p_light, const Vector2i &p_range); - + real_t light_get_attenuation(RID p_light); void light_set_attenuation(RID p_light, const real_t p_attenuation); @@ -104,6 +104,8 @@ class VertexLights2DServer : public Object { // Sampling + Color sample_light(RID p_map, const Vector2 &p_position, const int p_item_cull_mask = 1, const int p_layer = 0); + // Rest void free(RID p_rid); @@ -161,6 +163,8 @@ class VertexLights2DServer : public Object { VertexLightMap2D *map; void get_lights(List *p_lights); + + Color sample_light(const Color &p_current_color, const Vector2 &p_local_position, const int p_item_cull_mask, const int p_layer); VertexLightQuadrant2D() { map = NULL; @@ -186,6 +190,8 @@ class VertexLights2DServer : public Object { void set_light_position(VertexLightData2D *p_light, const Vector2 &p_position); void clear(); + + Color sample_light(const Vector2 &p_position, const int p_item_cull_mask = 1, const int p_layer = 0); _FORCE_INLINE_ Vector2i to_quadrant_position(const Vector2 &p_position) { return Vector2i(p_position.x / quadrant_size.x, p_position.y / quadrant_size.y);