godotengine / godotengine/godot

When using a SubViewport to show 2D scenes the normal map information is lost.

Open
#96,976 3 comments 0 reactions 0 assignees View on GitHub
topic:rendering
Dominant language
C++
Stars
117k
Forks
26.8k
PR merge metrics
PR metrics pending

Description

### Tested versions

4.3.stable

### System information

Windows 11 - 4.3.stable.official Vulkan 1.3.280 - Forward+ - Using Device #0: NVIDIA - NVIDIA GeForce RTX 3060 Laptop GPU

### Issue description

When using a SubViewport to show 2D scenes the normal map information is lost.
SubViewport.get_texture() returns a ViewportTexture that does not contain the information regarding normal maps.
For example, if I wanted to project a scene containing some Sprite2D and related textures (CanvasTexture containing diffuse_texture and normal_texture) onto a PlaneMesh using a SubViewport, currently there is no way to make it interact properly with the light coming on the mesh in the 3D environment, because the data about the normal maps is lost.

Here I am projecting a 2D scene on a SubViewport rendered on a mesh, there is no way to retrieve the normal map informations to make it react to the light in the 3D environment (the relative Sprite2D in the 2D scene has a normal map):
![image](https://github.com/user-attachments/assets/0d55f5be-7d2d-49cb-a7ba-8fb8e0c3a033)

On the contrary using a 3D scene it is possible to see its normal information and use it throught Rendering > Debug Draw > Normal Buffer:
![image](https://github.com/user-attachments/assets/8aabb4f1-3d3b-488a-b596-5dbe0330901a)

I have thought of a few solutions:
- Set the diffuse_texture and normal_texture properties to ViewportTexture, mimicking the behavior of CanvasTexture.
- Add the get_normal() method to SubViewport.
- Make the SubViewport Rendering > Debug Draw > Normal Buffer feature that already works with 3D scenes work for 2D scenes as well.

### Steps to reproduce

- Create a 2D scene with one or more Sprite2D with a CanvasTexture and relative diffuse_texture and normal_texture.
- Create a 3D scene with a MeshInstance3D and a shape.
- Add a SubViewport node to the 3D scene and instantiate the 2D scene as a child of the SubViewport.
- Add a material to the mesh, and add the SubViewport as a ViewportTexture in the albedo property.
- From here there is no way to retrieve the normal map from the 2D scene and use it as a normal map for the material. Did not found any workaround.

### Minimal reproduction project (MRP)

Here there is a little project with a SubViewport where both 3D and 2D scenes projection can be experimented. I animated the lights so that the results can be seen easily.
[bug_sub_viewport_normals.zip](https://github.com/user-attachments/files/16998791/bug_sub_viewport_normals.zip)

Contributor guide

Open the contributing guide

Research direction

Start with the attached minimal reproduction project and trace how SubViewport.get_texture() exposes a ViewportTexture when a CanvasTexture has diffuse and normal textures. Compare the 2D and 3D projection behavior described in the issue; done means the projected 2D scene's normal information can be retrieved and used for lighting on the 3D mesh.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
computer-graphics
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.