Implemented vertex light 2d sampling.

This commit is contained in:
Relintai 2024-03-26 06:47:28 +01:00
parent 42171f1fa2
commit d2ed14cf26
3 changed files with 95 additions and 1 deletions

View File

@ -39,6 +39,61 @@ void VertexLights2DServer::VertexLightQuadrant2D::get_lights(List<VertexLightDat
}
}
Color VertexLights2DServer::VertexLightQuadrant2D::sample_light(const Color &p_current_color, const Vector2 &p_position, const int p_item_cull_mask, const int p_layer) {
Color c = p_current_color;
for (uint32_t i = 0; i < lights.size(); ++i) {
VertexLightData2D *l = lights[i];
if (!l->enabled) {
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<real_t>(l->range.x);
light_to_pos_normal_space.y /= static_cast<real_t>(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;
}

View File

@ -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) {
@ -338,6 +347,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
ClassDB::bind_method(D_METHOD("free", "rid"), &VertexLights2DServer::free);

View File

@ -104,6 +104,8 @@ public:
// 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);
@ -162,6 +164,8 @@ protected:
void get_lights(List<VertexLightData2D *> *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;
}
@ -187,6 +191,8 @@ protected:
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);
}