Repository: godotengine/godot (language: cpp)

Issue:
Shadowmasks broken on Web exports when using RGTC texture compression
### Tested versions

Godot v4.4.beta1

### System information

Godot v4.4.beta1 - Manjaro Linux #1 SMP PREEMPT_DYNAMIC Thu, 02 Jan 2025 10:28:29 +0000 on X11 - X11 display driver, Multi-window, 1 monitor - OpenGL 3 (Compatibility) - NVIDIA GeForce RTX 3060 (nvidia) - AMD Ryzen 9 9900X 12-Core Processor (24 threads)

### Issue description

![Image](https://github.com/user-attachments/assets/2adb5b44-29bb-4d81-a7db-859235388156)
Currently in the beta build the shadow-masks are rendered incorrectly. Here I have the shadowmask mode set to **Replace** and you can clearly see the distance at which it switches to the shadow mask and there's a shadowed line.

![Image](https://github.com/user-attachments/assets/70d4d39c-649c-4e3a-886a-5eda04fdbc10)
Here it is with the shadowmask mode set to **None**

![Image](https://github.com/user-attachments/assets/a29b26a9-aa65-475e-a960-59fd69fcd868)
And with the shadowmask mode set to **Overlay** (notice how much brighter the people are, as they're lit dynamically and not with the lightmap)

and finally what it *should* look like (and what it looks like in the editor or when exported as an android build):
![Image](https://github.com/user-attachments/assets/1a1cbea1-7205-49f0-a6b0-8b7ff4008562)
shadowmask mode set to **Overlay** in android build


Hopefully this is possible to fix, shadowmasks are *incredibly* useful for web builds where performance is paramount.
### Steps to reproduce

Create a scene with lightmap GI and the shadowmask mode set to replace or overlay and notice the broken shadows. 

### Minimal reproduction project (MRP)

Here's a simple MRP with the same behavior shown (shadowmasks broken only on web builds):

![Image](https://github.com/user-attachments/assets/829e1d26-d289-4540-b0c8-6edc5502a1fc)

[shadowmask-test.zip](https://github.com/user-attachments/files/18458584/shadowmask-test.zip)


Discussion / hints:
@BlueCube3310 you might have an idea of what is going wrong here?

I'm assuming it's some shader code errors beyond my ability to diagnose 😅
Looks like the shadow texture doesn't get initialized properly and is fully black, I'll look into it
Update: This is likely related to RGTC compression. Changing the shadowmask's compression mode to VRAM uncompressed works correctly
I can confirm that Changing the shadowmask's compression mode to VRAM uncompressed works for my application as well.

I'll use that as a workaround for now.

Much appreciated! 
This seems to specifically happen when using array textures with RGTC. Other formats seem to work fine, and regular 2d textures work correctly too.
I wouldn't be surprised if this was a WebGL 2.0 idiosyncacy or limitation.

I suppose we should `decompress()` the lightmap on load on the web platform to work around the issue, as we don't want to get rid of VRAM compression on all platforms. (Also, the same lightmap may be used in Forward+/Mobile *and* Compatibility in the same project, so I wouldn't set the VRAM compression mode based on the current rendering method at the time of baking.)
Some more test results:
Windows:
![Image](https://github.com/user-attachments/assets/9c309d65-cc05-4b51-9867-ce8227adb74f)
Web:
![Image](https://github.com/user-attachments/assets/a6752113-b336-4384-88aa-887df58debc9)

Fix patch:
diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp
index e74747954f51..c1b2784bfc05 100644
--- a/drivers/gles3/storage/texture_storage.cpp
+++ b/drivers/gles3/storage/texture_storage.cpp
@@ -1509,8 +1509,17 @@ void TextureStorage::_texture_set_data(RID p_texture, const Ref<Image> &p_image,
 	GLenum internal_format;
 	bool compressed = false;
 
+	bool needs_decompress = texture->resize_to_po2;
+
+	// Support for RGTC-compressed Texture Arrays isn't mandated by GLES3/WebGL.
+	if (!RasterizerGLES3::is_gles_over_gl() && texture->target == GL_TEXTURE_2D_ARRAY) {
+		if (p_image->get_format() == Image::FORMAT_RGTC_R || p_image->get_format() == Image::FORMAT_RGTC_RG) {
+			needs_decompress = true;
+		}
+	}
+
 	Image::Format real_format;
-	Ref<Image> img = _get_gl_image_and_format(p_image, p_image->get_format(), real_format, format, internal_format, type, compressed, texture->resize_to_po2);
+	Ref<Image> img = _get_gl_image_and_format(p_image, p_image->get_format(), real_format, format, internal_format, type, compressed, needs_decompress);
 	ERR_FAIL_COND(img.is_null());
 	if (texture->resize_to_po2) {
 		if (p_image->is_compressed()) {


Test patch: