Repository: godotengine/godot (language: cpp)

Issue:
LightmapGI: Lightmaps with UV2 imported from Blender are broken on 4.4 Beta1
### Tested versions

Reproducible in: 4.4.beta1
Not Reproducible in: 4.3 stable and 4.4 dev7

### System information

Godot v4.4.beta1 - Windows 11 (build 22631) - Multi-window, 1 monitor - Vulkan (Forward+) - dedicated NVIDIA GeForce RTX 3080 (NVIDIA; 32.0.15.6614) - 12th Gen Intel(R) Core(TM) i7-12700KF (20 threads)

### Issue description

Follow up from #101391, according to @Geometror this seems to be another issue unrelated to the crash.

When baking the tunnel from the follow MRP, which has UV2 imported from Blender, Lightmaps get corrupted on 4.4.beta1.

This issue doesn't happen on 4.3 stable neither 4.4.dev7.

It seems to bake correctly until the [ShadowMask PR](https://github.com/godotengine/godot/pull/85653) (189c8eb) but not on the [transparency PR](https://github.com/godotengine/godot/pull/99538) (a3525bc)



### Steps to reproduce

Bake the lighmaps on the MRP.

Expected: Tunnel is dark with interior lights.
Results: Tunnel is light with weird lights.

Example:

| 4.3 stable | 4.4.beta1 |
|------------|-----------|
| ![Image](https://github.com/user-attachments/assets/f2fbac96-038b-46b4-94bf-f35f73f084f1) | ![Image](https://github.com/user-attachments/assets/9771fa45-7fd9-4d44-a5d2-3773e139ca7c) |

### Minimal reproduction project (MRP)

This MRP contains the `.glb` file from the tunnel and the test scene.
[lightmap-regression.zip](https://github.com/user-attachments/files/18594713/lightmap-regression.zip)


Discussion / hints:
_(Partially) copied and extended from https://github.com/godotengine/godot/issues/101391#issuecomment-2622316438_

I investigated the issue (using the lightmap debug textures) and saw that the lightmap UV2 albedo and emission textures don't match the rest (position/normal/etc.). By that I mean the scale/position in the texture as well as individual UV2 islands for some reason.

I can reproduce this in 4.3 by adding emission to the surface materials of the tunnel. It looks like this has been an unnoticed problem for a long time and the transparency support "revealed" it because we actually check for surface transparency when tracing rays (not just any hits) using the alpha channel of the broken albedo texture.
In the shader albedo/emission and position/normal/etc. textured are sampled the exact same way, so most of the surface becomes transparent. After manually adjusting the UV2 offset and scale in the scene shader for the material uv2 mode (scene_forward_clustered.glsl; line 655), it was almost fixed. Almost, because a simple affine transformation isn't enough. There appears to be something weird going on when blitting of meshes into the atlas.

Albedo                     | Position
:-------------------------:|:-------------------------:
![Image](https://github.com/user-attachments/assets/e32ed5ba-3c99-451a-90c3-4880d6eb02a9) | ![Image](https://github.com/user-attachments/assets/80a6cf40-bb71-48cf-836c-7d1af16fd90c)
> [!NOTE]
> If you look closely at the left picture, you can see that it is not even an affine transformation of the right, it's actually different (look at the space between the floor and wall parts, or the tunnel entrance)

The comparisons below are in the "Display Lightning" mode. I used a stripped down version of the original MRP from the [other](https://github.com/godotengine/godot/issues/101391) issue, where there's only the tunnel with both surfaces having different emission colors:

![Image](https://github.com/user-attachments/assets/36406fe8-8f7f-4978-ae00-8d47a70ea317)

Notice how the emission texture is completely off here as well | Now most of the tunnel is transparent for the lightmapper since the albedo texture doesn't match
:-------------------------:|:-------------------------:
![Image](https://github.com/user-attachments/assets/74346afb-a8c5-4073-a57f-27dca489a37a) | ![Image](https://github.com/user-attachments/assets/8e925b75-4392-4221-b455-7d90b74aade3)

 

This is an issue with rendering the textures using the UV2 channel: 

![Image](https://github.com/user-attachments/assets/1161118b-f126-4010-98c4-9cc36a0a9d2e)

It looks like it's rendered at 1/4 its intended size

Fix patch:
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index f61bb73a85a4..03e8a7c03ad2 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -713,7 +713,14 @@ void main() {
 #endif
 
 #ifdef RENDER_MATERIAL
-	gl_Position.xy = (uv2_attrib.xy + uv_offset) * 2.0 - 1.0;
+	vec2 uv_dest_attrib;
+	if (uv_scale != vec4(0.0)) {
+		uv_dest_attrib = (uv2_attrib.xy - 0.5) * uv_scale.zw;
+	} else {
+		uv_dest_attrib = uv2_attrib.xy;
+	}
+
+	gl_Position.xy = (uv_dest_attrib + uv_offset) * 2.0 - 1.0;
 	gl_Position.z = 0.00001;
 	gl_Position.w = 1.0;
 #endif
diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl
index 242d29d047be..f31a8de16b8a 100644
--- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl
+++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl
@@ -652,8 +652,15 @@ void vertex_shader(vec3 vertex_input,
 #endif
 #ifdef MODE_RENDER_MATERIAL
 	if (scene_data.material_uv2_mode) {
+		vec2 uv_dest_attrib;
+		if (uv_scale != vec4(0.0)) {
+			uv_dest_attrib = (uv2_attrib.xy - 0.5) * uv_scale.zw;
+		} else {
+			uv_dest_attrib = uv2_attrib.xy;
+		}
+
 		vec2 uv_offset = unpackHalf2x16(draw_call.uv_offset);
-		gl_Position.xy = (uv2_attrib.xy + uv_offset) * 2.0 - 1.0;
+		gl_Position.xy = (uv_dest_attrib + uv_offset) * 2.0 - 1.0;
 		gl_Position.z = 0.00001;
 		gl_Position.w = 1.0;
 	}
diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl
index 6ca6ad8fac07..dfcc285297a4 100644
--- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl
+++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl
@@ -557,7 +557,14 @@ void main() {
 #endif // MODE_RENDER_DEPTH
 #ifdef MODE_RENDER_MATERIAL
 	if (scene_data.material_uv2_mode) {
-		gl_Position.xy = (uv2_attrib.xy + draw_call.uv_offset) * 2.0 - 1.0;
+		vec2 uv_dest_attrib;
+		if (uv_scale != vec4(0.0)) {
+			uv_dest_attrib = (uv2_attrib.xy - 0.5) * uv_scale.zw;
+		} else {
+			uv_dest_attrib = uv2_attrib.xy;
+		}
+
+		gl_Position.xy = (uv_dest_attrib + draw_call.uv_offset) * 2.0 - 1.0;
 		gl_Position.z = 0.00001;
 		gl_Position.w = 1.0;
 	}


Test patch: