Page 1 of 1

Help with normal mapping

Posted: Tue Jul 04, 2023 4:25 pm
by Arônimo
I looked through some code and examples posted in the forums about dinamyc lighting and normal mapping, although i could not replicate it myself. The only thing that makes the effect not work with me, is because the nearest the top of the screen the light is, it seems like the code thinks it is behind, and near the bottom it seems like its going further from it, towards the camera screen or something:
Image
Image


this is the code (lua and glsl):

Code: Select all

local image
local normal_map

local shader
local shader_code
function love.load()
    image = love.graphics.newImage("brick.jpg")
    normal_map = love.graphics.newImage("brick_normal.jpg")

    local f = assert(io.open('shader.glsl', "r"))
    shader_code = f:read("*all")
    f:close()

    shader = love.graphics.newShader(shader_code)
end

function love.draw()
    love.graphics.setShader(shader)

    shader:send("screen", {
        love.graphics.getWidth(),
        love.graphics.getHeight()
    })

    shader:send("num_lights", 1)

    shader:send("lights[0].position", {
        love.mouse.getPosition()
    })

    shader:send("lights[0].diffuse", {
        10, 10, 10
    })

    shader:send("lights[0].power", 26)

    shader:send("normal_map", normal_map)

    love.graphics.draw(image, 0, 0)
    love.graphics.setShader()
end

function love.keypressed(k)
    if k == 'r' then
        love.event.quit('restart')
    end
end

Code: Select all

#define NUM_LIGHTS 32

struct Light
{
    vec2 position;
    vec3 diffuse;
    float power;
};

extern Light lights[NUM_LIGHTS];
extern int num_lights;
extern vec2 screen;
extern Image normal_map;

const float constant = 1.0;
const float linear = 0.09;
const float quadratic = 0.032;

vec4 effect(vec4 color, Image image, vec2 uv, vec2 screen_coords)
{
    vec4 pixel =  Texel(image, uv);
    vec3 normal = normalize(Texel(normal_map, uv).xyz * 2.0 - 1.0);

    vec2 norm_screen = screen_coords / screen;
    vec3 diffuse = vec3(0);

    for(int i = 0; i < num_lights; i++)
    {
        Light light = lights[i];
        vec2 norm_pos = light.position / screen;
        float dist = length(norm_pos - norm_screen) * light.power;
        float attenuation = 1.0 /
            (constant + linear * dist + quadratic * (dist * dist));
        
        float diff = max(dot(norm_pos, normal.zx), 0.0);

        diffuse += diff * (light.diffuse * attenuation);
    }

    diffuse = clamp(diffuse, 0.0, 1.0);

    return pixel * vec4(diffuse, 1.0);
}
Any help is appreciated!

Re: Help with normal mapping

Posted: Wed Jul 05, 2023 11:35 am
by Arônimo
A z axis was missing for the normal calculations, i did just that:

Code: Select all

    vec4 pixel =  Texel(image, uv);
    vec3 normal = normalize(vec3(Texel(normal_map, uv).xy * 2.0 - 1.0, 1));

    vec2 norm_screen = screen_coords / screen;
    vec3 diffuse = vec3(0);

    for(int i = 0; i < num_lights; i++)
    {
        Light light = lights[i];
        vec2 norm_pos = light.position / screen;
        float dist = length(norm_pos - norm_screen) * light.power;
        float attenuation = 1.0 /
            (constant + linear * dist + quadratic * (dist * dist));
        
        float diff = max(dot(normalize(vec3(norm_pos, 1)), normal.xyz), 0.0);

        diffuse += diff * (light.diffuse * attenuation);
    }
But still, doesnt look quite good:
Image