Skip to content

Commit 7a1d375

Browse files
committed
- Allowed projector texture in directional light
- Added projector scale / offset in directional light - Added directional light matrix, scale and offset in forward shaders - Added computation logic of the projection in the forward and forward mobile shaders - Computing projector matrix in the update_light_buffers and pushing it to the gpu - Adapted light models to have projector scale and offset stored (even in gles3 for the future inclusion of projectors) - Added a sub group for the directional light projector properties - Added directional projector pipeline specialization constant for mobile and forward rendering TODO: - Find a way to hide the delimitation of the projector texture repetition when using mimap or linear projector filtering due the use of an atlas
1 parent 19bb187 commit 7a1d375

21 files changed

Lines changed: 247 additions & 34 deletions

drivers/gles3/storage/light_storage.cpp

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -181,18 +181,30 @@ void LightStorage::light_set_projector(RID p_light, RID p_texture) {
181181
return;
182182
}
183183

184-
if (light->type != RS::LIGHT_DIRECTIONAL && light->projector.is_valid()) {
184+
if (light->projector.is_valid()) {
185185
texture_storage->texture_remove_from_decal_atlas(light->projector, light->type == RS::LIGHT_OMNI);
186186
}
187187

188188
light->projector = p_texture;
189189

190-
if (light->type != RS::LIGHT_DIRECTIONAL) {
191-
if (light->projector.is_valid()) {
192-
texture_storage->texture_add_to_decal_atlas(light->projector, light->type == RS::LIGHT_OMNI);
193-
}
194-
light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR);
190+
if (light->projector.is_valid()) {
191+
texture_storage->texture_add_to_decal_atlas(light->projector, light->type == RS::LIGHT_OMNI);
195192
}
193+
light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR);
194+
}
195+
196+
void LightStorage::light_set_projector_scale(RID p_light, const Vector2 &p_scale) {
197+
Light *light = light_owner.get_or_null(p_light);
198+
ERR_FAIL_NULL(light);
199+
200+
light->projector_scale = p_scale;
201+
}
202+
203+
void LightStorage::light_set_projector_offset(RID p_light, const Vector2 &p_offset) {
204+
Light *light = light_owner.get_or_null(p_light);
205+
ERR_FAIL_NULL(light);
206+
207+
light->projector_offset = p_offset;
196208
}
197209

198210
void LightStorage::light_set_negative(RID p_light, bool p_enable) {

drivers/gles3/storage/light_storage.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ struct Light {
5050
float param[RS::LIGHT_PARAM_MAX];
5151
Color color = Color(1, 1, 1, 1);
5252
RID projector;
53+
Vector2 projector_scale;
54+
Vector2 projector_offset;
5355
bool shadow = false;
5456
bool negative = false;
5557
bool reverse_cull = false;
@@ -322,6 +324,8 @@ class LightStorage : public RendererLightStorage {
322324
virtual void light_set_param(RID p_light, RS::LightParam p_param, float p_value) override;
323325
virtual void light_set_shadow(RID p_light, bool p_enabled) override;
324326
virtual void light_set_projector(RID p_light, RID p_texture) override;
327+
virtual void light_set_projector_scale(RID p_light, const Vector2 &p_scale) override;
328+
virtual void light_set_projector_offset(RID p_light, const Vector2 &p_offset) override;
325329
virtual void light_set_negative(RID p_light, bool p_enable) override;
326330
virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) override;
327331
virtual void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) override;

scene/3d/light_3d.cpp

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,24 @@ Ref<Texture2D> Light3D::get_projector() const {
222222
return projector;
223223
}
224224

225+
void Light3D::set_projector_scale(const Vector2 &p_scale) {
226+
projector_scale = p_scale;
227+
RS::get_singleton()->light_set_projector_scale(light, p_scale);
228+
}
229+
230+
Vector2 Light3D::get_projector_scale() const {
231+
return projector_scale;
232+
}
233+
234+
void Light3D::set_projector_offset(const Vector2 &p_offset) {
235+
projector_offset = p_offset;
236+
RS::get_singleton()->light_set_projector_offset(light, p_offset);
237+
}
238+
239+
Vector2 Light3D::get_projector_offset() const {
240+
return projector_offset;
241+
}
242+
225243
void Light3D::owner_changed_notify() {
226244
// For cases where owner changes _after_ entering tree (as example, editor editing).
227245
_update_visibility();
@@ -327,8 +345,8 @@ void Light3D::_validate_property(PropertyInfo &p_property) const {
327345
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
328346
}
329347

330-
if (get_light_type() != RS::LIGHT_DIRECTIONAL && (p_property.name == "light_angular_distance" || p_property.name == "light_intensity_lux")) {
331-
// Angular distance and Light Intensity Lux are only used in DirectionalLight3D.
348+
if (get_light_type() != RS::LIGHT_DIRECTIONAL && (p_property.name == "light_angular_distance" || p_property.name == "light_intensity_lux" || p_property.name == "Projector" || p_property.name == "light_projector_scale" || p_property.name == "light_projector_offset")) {
349+
// Angular distance, Light Intensity Lux and Projector Subgroup/Scale/Offset are only used in DirectionalLight3D.
332350
p_property.usage = PROPERTY_USAGE_NONE;
333351
} else if (get_light_type() == RS::LIGHT_DIRECTIONAL && p_property.name == "light_intensity_lumens") {
334352
p_property.usage = PROPERTY_USAGE_NONE;
@@ -386,6 +404,12 @@ void Light3D::_bind_methods() {
386404
ClassDB::bind_method(D_METHOD("set_projector", "projector"), &Light3D::set_projector);
387405
ClassDB::bind_method(D_METHOD("get_projector"), &Light3D::get_projector);
388406

407+
ClassDB::bind_method(D_METHOD("set_projector_scale", "scale"), &Light3D::set_projector_scale);
408+
ClassDB::bind_method(D_METHOD("get_projector_scale"), &Light3D::get_projector_scale);
409+
410+
ClassDB::bind_method(D_METHOD("set_projector_offset", "offset"), &Light3D::set_projector_offset);
411+
ClassDB::bind_method(D_METHOD("get_projector_offset"), &Light3D::get_projector_offset);
412+
389413
ClassDB::bind_method(D_METHOD("set_temperature", "temperature"), &Light3D::set_temperature);
390414
ClassDB::bind_method(D_METHOD("get_temperature"), &Light3D::get_temperature);
391415
ClassDB::bind_method(D_METHOD("get_correlated_color"), &Light3D::get_correlated_color);
@@ -398,8 +422,13 @@ void Light3D::_bind_methods() {
398422
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_energy", PROPERTY_HINT_RANGE, "0,16,0.001,or_greater"), "set_param", "get_param", PARAM_ENERGY);
399423
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_indirect_energy", PROPERTY_HINT_RANGE, "0,16,0.001,or_greater"), "set_param", "get_param", PARAM_INDIRECT_ENERGY);
400424
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_volumetric_fog_energy", PROPERTY_HINT_RANGE, "0,16,0.001,or_greater"), "set_param", "get_param", PARAM_VOLUMETRIC_FOG_ENERGY);
425+
401426
// Only allow texture types that display correctly.
427+
ADD_SUBGROUP("Projector", "light_projector_");
402428
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_projector", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D,-AnimatedTexture,-AtlasTexture,-CameraTexture,-CanvasTexture,-MeshTexture,-Texture2DRD,-ViewportTexture"), "set_projector", "get_projector");
429+
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "light_projector_scale", PROPERTY_HINT_NONE, "suffix:px"), "set_projector_scale", "get_projector_scale");
430+
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "light_projector_offset"), "set_projector_offset", "get_projector_offset");
431+
403432
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_size", PROPERTY_HINT_RANGE, "0,1,0.001,or_greater,suffix:m"), "set_param", "get_param", PARAM_SIZE);
404433
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_angular_distance", PROPERTY_HINT_RANGE, "0,90,0.01,degrees"), "set_param", "get_param", PARAM_SIZE);
405434
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "light_negative"), "set_negative", "is_negative");
@@ -560,7 +589,7 @@ void DirectionalLight3D::_validate_property(PropertyInfo &p_property) const {
560589
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
561590
}
562591

563-
if (p_property.name == "light_size" || p_property.name == "light_projector") {
592+
if (p_property.name == "light_size") {
564593
// Not implemented in DirectionalLight3D (`light_size` is replaced by `light_angular_distance`).
565594
p_property.usage = PROPERTY_USAGE_NONE;
566595
}
@@ -614,6 +643,7 @@ DirectionalLight3D::DirectionalLight3D() :
614643
set_shadow_mode(SHADOW_PARALLEL_4_SPLITS);
615644
blend_splits = false;
616645
set_sky_mode(SKY_MODE_LIGHT_AND_SKY);
646+
set_projector_scale(Vector2(1, 1));
617647
}
618648

619649
void OmniLight3D::set_shadow_mode(ShadowMode p_mode) {

scene/3d/light_3d.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ class Light3D : public VisualInstance3D {
8484
void _update_visibility();
8585
BakeMode bake_mode = BAKE_DYNAMIC;
8686
Ref<Texture2D> projector;
87+
Vector2 projector_scale;
88+
Vector2 projector_offset;
8789
Color correlated_color = Color(1.0, 1.0, 1.0);
8890
float temperature = 6500.0;
8991

@@ -145,6 +147,12 @@ class Light3D : public VisualInstance3D {
145147
void set_projector(const Ref<Texture2D> &p_texture);
146148
Ref<Texture2D> get_projector() const;
147149

150+
void set_projector_scale(const Vector2 &p_scale);
151+
Vector2 get_projector_scale() const;
152+
153+
void set_projector_offset(const Vector2 &p_offset);
154+
Vector2 get_projector_offset() const;
155+
148156
void set_temperature(const float p_temperature);
149157
float get_temperature() const;
150158
Color get_correlated_color() const;

servers/rendering/dummy/storage/light_storage.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ class LightStorage : public RendererLightStorage {
7373
virtual void light_set_param(RID p_light, RS::LightParam p_param, float p_value) override {}
7474
virtual void light_set_shadow(RID p_light, bool p_enabled) override {}
7575
virtual void light_set_projector(RID p_light, RID p_texture) override {}
76+
virtual void light_set_projector_scale(RID p_light, const Vector2 &p_scale) override {}
77+
virtual void light_set_projector_offset(RID p_light, const Vector2 &p_offset) override {}
7678
virtual void light_set_negative(RID p_light, bool p_enable) override {}
7779
virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) override {}
7880
virtual void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) override {}

0 commit comments

Comments
 (0)