Skip to content

Commit b12ceaf

Browse files
committed
- Allowed projector texture in directional light
- Added projector size / offset in directional light - Added directional light matrix, size 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 size 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 - Edited the way decals store texture to now repeat in the border instead of storing black color - Added projector warning for DirectionalLight3D in compatibility mode (Moved the projector warning to Light3D level since all can use projector now)
1 parent 6459609 commit b12ceaf

25 files changed

Lines changed: 267 additions & 61 deletions

drivers/gles3/storage/light_storage.cpp

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -186,18 +186,30 @@ void LightStorage::light_set_projector(RID p_light, RID p_texture) {
186186
return;
187187
}
188188

189-
if (light->type != RSE::LIGHT_DIRECTIONAL && light->projector.is_valid()) {
189+
if (light->projector.is_valid()) {
190190
texture_storage->texture_remove_from_decal_atlas(light->projector, light->type == RSE::LIGHT_OMNI);
191191
}
192192

193193
light->projector = p_texture;
194194

195-
if (light->type != RSE::LIGHT_DIRECTIONAL) {
196-
if (light->projector.is_valid()) {
197-
texture_storage->texture_add_to_decal_atlas(light->projector, light->type == RSE::LIGHT_OMNI);
198-
}
199-
light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR);
195+
if (light->projector.is_valid()) {
196+
texture_storage->texture_add_to_decal_atlas(light->projector, light->type == RSE::LIGHT_OMNI);
200197
}
198+
light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR);
199+
}
200+
201+
void LightStorage::light_set_projector_size(RID p_light, const Vector2 &p_size) {
202+
Light *light = light_owner.get_or_null(p_light);
203+
ERR_FAIL_NULL(light);
204+
205+
light->projector_size = p_size;
206+
}
207+
208+
void LightStorage::light_set_projector_offset(RID p_light, const Vector2 &p_offset) {
209+
Light *light = light_owner.get_or_null(p_light);
210+
ERR_FAIL_NULL(light);
211+
212+
light->projector_offset = p_offset;
201213
}
202214

203215
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
@@ -51,6 +51,8 @@ struct Light {
5151
float param[RSE::LIGHT_PARAM_MAX];
5252
Color color = Color(1, 1, 1, 1);
5353
RID projector;
54+
Vector2 projector_size;
55+
Vector2 projector_offset;
5456
bool shadow = false;
5557
bool negative = false;
5658
bool reverse_cull = false;
@@ -322,6 +324,8 @@ class LightStorage : public RendererLightStorage {
322324
virtual void light_set_param(RID p_light, RSE::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_size(RID p_light, const Vector2 &p_size) 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: 41 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,14 @@ PackedStringArray Light3D::get_configuration_warnings() const {
189189
warnings.push_back(RTR("A light's scale does not affect the visual size of the light."));
190190
}
191191

192+
if (!has_shadow() && get_projector().is_valid()) {
193+
warnings.push_back(RTR("Projector texture only works with shadows active."));
194+
}
195+
196+
if (get_projector().is_valid() && (OS::get_singleton()->get_current_rendering_method() == "gl_compatibility" || OS::get_singleton()->get_current_rendering_method() == "dummy")) {
197+
warnings.push_back(RTR("Projector textures are not supported when using the Compatibility renderer yet. Support will be added in a future release."));
198+
}
199+
192200
return warnings;
193201
}
194202

@@ -226,6 +234,24 @@ Ref<Texture2D> Light3D::get_projector() const {
226234
return projector;
227235
}
228236

237+
void Light3D::set_projector_size(const Vector2 &p_size) {
238+
projector_size = p_size;
239+
RS::get_singleton()->light_set_projector_size(light, p_size);
240+
}
241+
242+
Vector2 Light3D::get_projector_size() const {
243+
return projector_size;
244+
}
245+
246+
void Light3D::set_projector_offset(const Vector2 &p_offset) {
247+
projector_offset = p_offset;
248+
RS::get_singleton()->light_set_projector_offset(light, p_offset);
249+
}
250+
251+
Vector2 Light3D::get_projector_offset() const {
252+
return projector_offset;
253+
}
254+
229255
void Light3D::owner_changed_notify() {
230256
// For cases where owner changes _after_ entering tree (as example, editor editing).
231257
_update_visibility();
@@ -327,8 +353,8 @@ bool Light3D::is_editor_only() const {
327353
}
328354

329355
void Light3D::_validate_property(PropertyInfo &p_property) const {
330-
if (get_light_type() != RSE::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.
356+
if (get_light_type() != RSE::LIGHT_DIRECTIONAL && (p_property.name == "light_angular_distance" || p_property.name == "light_intensity_lux" || p_property.name == "Projector" || p_property.name == "light_projector_size" || p_property.name == "light_projector_offset")) {
357+
// Angular distance, Light Intensity Lux and Projector Subgroup/Size/Offset are only used in DirectionalLight3D.
332358
p_property.usage = PROPERTY_USAGE_NONE;
333359
} else if (get_light_type() == RSE::LIGHT_DIRECTIONAL && p_property.name == "light_intensity_lumens") {
334360
p_property.usage = PROPERTY_USAGE_NONE;
@@ -380,6 +406,12 @@ void Light3D::_bind_methods() {
380406
ClassDB::bind_method(D_METHOD("set_projector", "projector"), &Light3D::set_projector);
381407
ClassDB::bind_method(D_METHOD("get_projector"), &Light3D::get_projector);
382408

409+
ClassDB::bind_method(D_METHOD("set_projector_size", "size"), &Light3D::set_projector_size);
410+
ClassDB::bind_method(D_METHOD("get_projector_size"), &Light3D::get_projector_size);
411+
412+
ClassDB::bind_method(D_METHOD("set_projector_offset", "offset"), &Light3D::set_projector_offset);
413+
ClassDB::bind_method(D_METHOD("get_projector_offset"), &Light3D::get_projector_offset);
414+
383415
ClassDB::bind_method(D_METHOD("set_temperature", "temperature"), &Light3D::set_temperature);
384416
ClassDB::bind_method(D_METHOD("get_temperature"), &Light3D::get_temperature);
385417
ClassDB::bind_method(D_METHOD("get_correlated_color"), &Light3D::get_correlated_color);
@@ -392,8 +424,13 @@ void Light3D::_bind_methods() {
392424
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_energy", PROPERTY_HINT_RANGE, "0,16,0.001,or_greater"), "set_param", "get_param", PARAM_ENERGY);
393425
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_indirect_energy", PROPERTY_HINT_RANGE, "0,16,0.001,or_greater"), "set_param", "get_param", PARAM_INDIRECT_ENERGY);
394426
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);
427+
395428
// Only allow texture types that display correctly.
429+
ADD_SUBGROUP("Projector", "light_projector_");
396430
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_projector", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D,-AnimatedTexture,-AtlasTexture,-CameraTexture,-CanvasTexture,-MeshTexture,-Texture2DRD,-ViewportTexture"), "set_projector", "get_projector");
431+
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "light_projector_size", PROPERTY_HINT_LINK, "suffix:m"), "set_projector_size", "get_projector_size");
432+
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "light_projector_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_projector_offset", "get_projector_offset");
433+
397434
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_size", PROPERTY_HINT_RANGE, "0,1,0.001,or_greater,suffix:m"), "set_param", "get_param", PARAM_SIZE);
398435
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_angular_distance", PROPERTY_HINT_RANGE, "0,90,0.01,degrees"), "set_param", "get_param", PARAM_SIZE);
399436
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "light_negative"), "set_negative", "is_negative");
@@ -555,7 +592,7 @@ void DirectionalLight3D::_validate_property(PropertyInfo &p_property) const {
555592
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
556593
}
557594
}
558-
if (p_property.name == "light_size" || p_property.name == "light_projector") {
595+
if (p_property.name == "light_size") {
559596
// Not implemented in DirectionalLight3D (`light_size` is replaced by `light_angular_distance`).
560597
p_property.usage = PROPERTY_USAGE_NONE;
561598
} else if (p_property.name == "distance_fade_enabled" || p_property.name == "distance_fade_begin" || p_property.name == "distance_fade_shadow" || p_property.name == "distance_fade_length") {
@@ -607,6 +644,7 @@ DirectionalLight3D::DirectionalLight3D() :
607644
set_shadow_mode(SHADOW_PARALLEL_4_SPLITS);
608645
blend_splits = false;
609646
set_sky_mode(SKY_MODE_LIGHT_AND_SKY);
647+
set_projector_size(Vector2(100.0, 100.0));
610648
}
611649

612650
void OmniLight3D::set_shadow_mode(ShadowMode p_mode) {
@@ -618,20 +656,6 @@ OmniLight3D::ShadowMode OmniLight3D::get_shadow_mode() const {
618656
return shadow_mode;
619657
}
620658

621-
PackedStringArray OmniLight3D::get_configuration_warnings() const {
622-
PackedStringArray warnings = Light3D::get_configuration_warnings();
623-
624-
if (!has_shadow() && get_projector().is_valid()) {
625-
warnings.push_back(RTR("Projector texture only works with shadows active."));
626-
}
627-
628-
if (get_projector().is_valid() && (OS::get_singleton()->get_current_rendering_method() == "gl_compatibility" || OS::get_singleton()->get_current_rendering_method() == "dummy")) {
629-
warnings.push_back(RTR("Projector textures are not supported when using the Compatibility renderer yet. Support will be added in a future release."));
630-
}
631-
632-
return warnings;
633-
}
634-
635659
void OmniLight3D::_bind_methods() {
636660
ClassDB::bind_method(D_METHOD("set_shadow_mode", "mode"), &OmniLight3D::set_shadow_mode);
637661
ClassDB::bind_method(D_METHOD("get_shadow_mode"), &OmniLight3D::get_shadow_mode);
@@ -657,14 +681,6 @@ PackedStringArray SpotLight3D::get_configuration_warnings() const {
657681
warnings.push_back(RTR("A SpotLight3D with an angle wider than 90 degrees cannot cast shadows."));
658682
}
659683

660-
if (!has_shadow() && get_projector().is_valid()) {
661-
warnings.push_back(RTR("Projector texture only works with shadows active."));
662-
}
663-
664-
if (get_projector().is_valid() && (OS::get_singleton()->get_current_rendering_method() == "gl_compatibility" || OS::get_singleton()->get_current_rendering_method() == "dummy")) {
665-
warnings.push_back(RTR("Projector textures are not supported when using the Compatibility renderer yet. Support will be added in a future release."));
666-
}
667-
668684
return warnings;
669685
}
670686

scene/3d/light_3d.h

Lines changed: 8 additions & 2 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_size;
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_size(const Vector2 &p_scale);
151+
Vector2 get_projector_size() 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;
@@ -220,8 +228,6 @@ class OmniLight3D : public Light3D {
220228
void set_shadow_mode(ShadowMode p_mode);
221229
ShadowMode get_shadow_mode() const;
222230

223-
PackedStringArray get_configuration_warnings() const override;
224-
225231
OmniLight3D();
226232
};
227233

servers/rendering/dummy/storage/light_storage.h

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

servers/rendering/renderer_rd/effects/copy_effects.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -570,7 +570,7 @@ void CopyEffects::copy_depth_to_rect_and_linearize(RID p_source_rd_texture, RID
570570
RD::get_singleton()->compute_list_end();
571571
}
572572

573-
void CopyEffects::copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_uv_rect, RD::DrawListID p_draw_list, bool p_flip_y, bool p_panorama) {
573+
void CopyEffects::copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_uv_rect, RD::DrawListID p_draw_list, bool p_flip_y, bool p_panorama, Vector2 uv_offset) {
574574
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
575575
ERR_FAIL_NULL(uniform_set_cache);
576576
MaterialStorage *material_storage = MaterialStorage::get_singleton();
@@ -590,8 +590,11 @@ void CopyEffects::copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuff
590590

591591
copy_to_fb.push_constant.luminance_multiplier = 1.0;
592592

593+
copy_to_fb.push_constant.set_color[0] = uv_offset.x;
594+
copy_to_fb.push_constant.set_color[1] = uv_offset.y;
595+
593596
// setup our uniforms
594-
RID default_sampler = material_storage->sampler_rd_get_default(RSE::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RSE::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
597+
RID default_sampler = material_storage->sampler_rd_get_default(RSE::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RSE::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
595598

596599
RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
597600

servers/rendering/renderer_rd/effects/copy_effects.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ class CopyEffects {
371371
void copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false);
372372
void copy_depth_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, float p_z_near, float p_z_far);
373373
void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false, bool p_srgb = false, RID p_secondary = RID(), bool p_multiview = false, bool alpha_to_one = false, bool p_linear = false, bool p_normal = false, const Rect2 &p_src_rect = Rect2(), float p_linear_luminance_multiplier = 1.0);
374-
void copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_uv_rect, RD::DrawListID p_draw_list, bool p_flip_y = false, bool p_panorama = false);
374+
void copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_uv_rect, RD::DrawListID p_draw_list, bool p_flip_y = false, bool p_panorama = false, Vector2 uv_offset = Vector2());
375375
void copy_to_drawlist(RD::DrawListID p_draw_list, RD::FramebufferFormatID p_fb_format, RID p_source_rd_texture, bool p_linear = false, float p_linear_luminance_multiplier = 1.0);
376376
void copy_raster(RID p_source_texture, RID p_dest_framebuffer);
377377

0 commit comments

Comments
 (0)