I am trying to write a shader for normal mapping. It works fine (more or less), but the shape of the light does strange things. Since some parts of the code is copy/paste I am not sure where the problem could be.
Next problem: how can I draw two images at once? I need the diffuse and the normal one at the same time, do I?
I took this as inspiration: viewtopic.php?t=11076
my code takes an image, calculate a hightmap first and then calculates a normalmap. Not professional, but it should work.
use the mouse to move lightning at the first image.
Code: Select all
canvas = {300, 300}
light_canvas = love.graphics.newCanvas(canvas[1], canvas[2])
diffuse_canvas = love.graphics.newCanvas(canvas[1], canvas[2])
heightmap_canvas = love.graphics.newCanvas(canvas[1], canvas[2], "r8")
normal_canvas = love.graphics.newCanvas(canvas[1], canvas[2])
img_diffuse = love.graphics.newImage("diffuse.jpg")
screen = {w = 1200, h = 400}
love.window.setMode(screen.w, screen.h)
function love.load()
local s = math.max(canvas[1]/img_diffuse:getWidth(), canvas[2]/img_diffuse:getHeight())
love.graphics.setCanvas(diffuse_canvas)
love.graphics.draw(img_diffuse, 0, 0, 0, s)
--render heightmmap
love.graphics.setCanvas(heightmap_canvas)
love.graphics.setShader(generate_heightmap_shader)
love.graphics.draw(diffuse_canvas)
love.graphics.setShader()
love.graphics.setCanvas()
--render normalmap
generate_normal_shader:send("size", canvas[1])
love.graphics.setCanvas(normal_canvas)
love.graphics.setShader(generate_normal_shader)
love.graphics.draw(heightmap_canvas)
love.graphics.setShader()
love.graphics.setCanvas()
end
function love.draw()
bumb:send("light_vec", {love.mouse.getX(), love.mouse.getY(), 5})
local s = (screen.w / 3) / canvas[1]
love.graphics.setShader(bumb)
love.graphics.setCanvas(light_canvas)
love.graphics.clear()
love.graphics.draw(normal_canvas)
love.graphics.setCanvas()
love.graphics.setShader()
love.graphics.draw(diffuse_canvas, 0, 0, 0, s)
love.graphics.setColor(200, 160, 160)
--love.graphics.rectangle("fill", 0, 0, 400, 400)
love.graphics.setColor(255, 255, 255)
love.graphics.draw(light_canvas, 0, 0, 0, s)
love.graphics.setShader(draw_heightmap_shader)
love.graphics.draw(heightmap_canvas, 300*s, 0, 0, s)
love.graphics.setShader(draw_normal_shader)
love.graphics.draw(normal_canvas, 600*s, 0, 0, s)
love.graphics.setShader()
end
generate_heightmap_shader = love.graphics.newShader[[
vec4 effect(vec4 color, Image texture, vec2 tc, vec2 sc)
{
vec4 c = Texel(texture, tc);
float b = (c[0]+c[1]+c[2]+c[3])/4;
return vec4(b, 0, 0, 1);
}
]]
generate_normal_shader = love.graphics.newShader[[
extern float size;
vec4 effect(vec4 color, Image texture, vec2 tc, vec2 sc)
{
float c1 = Texel(texture, tc + vec2(-1, 0)/size).r;
float c2 = Texel(texture, tc + vec2(1, 0)/size).r;
float c3 = Texel(texture, tc + vec2(0, -1)/size).r;
float c4 = Texel(texture, tc + vec2(0, 1)/size).r;
vec3 x = {2, 0, c2-c1};
vec3 y = {0, 2, c4-c3};
return vec4(cross(x, y)*5, 1);
}
]]
draw_heightmap_shader = love.graphics.newShader[[
vec4 effect(vec4 color, Image texture, vec2 tc, vec2 sc)
{
float c = Texel(texture, tc).r;
return vec4(c, c, c, 1);
}
]]
draw_normal_shader = love.graphics.newShader[[
vec4 effect(vec4 color, Image texture, vec2 tc, vec2 sc)
{
vec4 c = Texel(texture, tc);
return c;
}
]]
bumb = love.graphics.newShader[[
extern vec3 light_vec;
vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 pixel_coords) {
vec3 light_direction = light_vec - vec3(pixel_coords, 0);
float distance = length(light_direction);
light_direction = normalize(light_direction);
vec3 normal = Texel(texture, texture_coords).xyz;
//normal = normalize(mix(vec3(-1), vec3(1), normal));
float attenuation = 500/pow(distance, 1.2);
float diffuse_term = clamp(attenuation * dot(normal, light_direction), 0.0, 1.0);
vec3 dark_color = vec3(0.0, 0.0, 1);
vec3 light_color = vec3(0.8, 0.8, 0.0);
vec3 ambient = mix(dark_color, light_color, diffuse_term) * 0.20;
float cel_diffuse_term = smoothstep(0.49, 0.52, diffuse_term)/2 + 0.5;
vec3 l = cel_diffuse_term * vec3(0.8,0.5,0.6) + ambient;
return vec4(cel_diffuse_term + ambient, length(cel_diffuse_term));
}
]]