Normal Maps to improve surfaces texture appearance

Hello! I have a request for a feature that may be a bit difficult to add. Can you please add Normal maps into Gdevelop? It would be located under the effects tab and could be very useful to give some depth to your 2D game. If you don’t know what a normal map is, it’s basically a way to give dynamic lighting to 2D sprites. Normal maps consist of two images.
The first image is called the diffuse image. It’s basically just the normal image.
The second image is the color map. It shows how light interacts with the image.

8 Likes

Using color maps can give your sprite a feeling of depth. This is an example:
normalmapComparison
If you could add this feature, I would be very glad.

2 Likes

isn’t that for 3D objects?..cos you said 2d sprites

1 Like

Normal maps can be used to fake volume of a sprite when interacting with lights.

3 Likes

No, not really. Normal maps can be used on 2d and 3d objects.

1 Like

ok,thx i didn’t knew it.
upvoted cos i probably gonna need it too

2 Likes

Ok! Glad to help, @RMDB!

2 Likes

another question…how do you light em…i mean do we have a way to dynamically light em(physical lights)?

asking this bcs i know a bit of 3d and for reflection you need dynamic lighting, instead in GD light looks likes works only on brightness the image…
I’m asking…bcs i really don’t know…thaz why i tought in 3D manner

1 Like

tbh, I don’t really know how they could implement it into Gdevelop, but I think they would find a way. I don’t know much about it, but this video explains somethings.

In this video it uses kind of the same lighting in Gdevelop, just in godot… I think

yep thaz what i meant.
U need 3d? lights on 2d objects…that is a point light in Godot acting on a 2D sprite.
I never touched the 3D part in GD, for the 2D part i haven’t found anything similar.
Dunno if i’m using the light wrong but i see them act only on the image’s brightness.

It will idd be great to have them implemented.
Like eg: point, disk,directional, and spherical lights.
but i guess it means to have a pysical light engine on the 2D part i dunno how muchh work would it costs.

1 Like

yehhh…. I don’t really know either. Lets just hope that they find a way.

at the moment i don’t think it can be done.

sprites in GD are’n really recognized for their silohuette but with their bounding box.
A physical light acting on a 2d character will illluminate the squared box surrounding and part of the character.Hope i’m wrong…

i’d really love em to be implemented

2 Likes

ig this is just and offset in the normal thing?? i might be able to make an extension for that

6 Likes

Really?? WOW!
That would be very awesome!

1 Like

this is as far as i came, it doesnt work so idek

objects.forEach(object => {
    const threeObject = object.get3DRendererObject();
    
    if (threeObject) {
        const normalMapTexture = eventsFunctionContext.getArgument("Texture");
        const materialIndex = eventsFunctionContext.getArgument("Face");
        
        // Handle materials (for cube, material should be an array of 6 materials)
        if (Array.isArray(threeObject.material) && threeObject.material[materialIndex]) {
            let material = threeObject.material[materialIndex];
            
            // Convert to MeshStandardMaterial if needed
            if (!(material instanceof THREE.MeshStandardMaterial)) {
                const oldMap = material.map;
                material = new THREE.MeshStandardMaterial({
                    map: oldMap,
                    roughness: 1.0,
                    metalness: 0.0
                });
                threeObject.material[materialIndex] = material;
            }
            
            // Create and apply the normal map
            if (normalMapTexture) {
                const texture = gdjs.getTexture(normalMapTexture);
                const normalMap = new THREE.Texture(texture.getImage());
                
                // Set texture parameters
                normalMap.wrapS = THREE.RepeatWrapping;
                normalMap.wrapT = THREE.RepeatWrapping;
                normalMap.needsUpdate = true;
                
                // Apply to material
                material.normalMap = normalMap;
                material.normalScale.set(
                    eventsFunctionContext.getArgument("NormalStrength"),
                    eventsFunctionContext.getArgument("NormalStrength")
                );
                material.needsUpdate = true;
            }
        } else {
            console.warn('Material array or index not valid');
        }
    }
});
1 Like

Dang! Tysm! this is incredible! Honestly, I don’t know how to import it into Gdevelop. Do you know how?

it doesnt rlly work but u gotta make an action and put that in as a javascript event

1 Like