Problem with normal mapping

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
User avatar
Luke100000
Party member
Posts: 232
Joined: Mon Jul 22, 2013 9:17 am
Location: Austria
Contact:

Problem with normal mapping

Post by Luke100000 »

Hello,
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));
	}
]]
Attachments
test.love
(548.96 KiB) Downloaded 83 times
cval
Citizen
Posts: 58
Joined: Sun Apr 20, 2014 2:15 pm
Location: Ukraine

Re: Problem with normal mapping

Post by cval »

Couldn't get your love file to work, it says
err.png
err.png (23.91 KiB) Viewed 3221 times
However, i think you dont really need to draw anything simultaneously. If i get things correctly, you calculate your diffuse in your shader and then draw it as final image.

Here is my old code with normal mapping experiments, hope it helps. You can use arrows to move light around and pgup and pgdown to increase or decrease its height.
shader.love
(1.9 MiB) Downloaded 111 times
User avatar
s-ol
Party member
Posts: 1077
Joined: Mon Sep 15, 2014 7:41 pm
Location: Cologne, Germany
Contact:

Re: Problem with normal mapping

Post by s-ol »

You pass one image into the shader with Shader:send and an "extern image" in the shader code.

s-ol.nu /blog  -  p.s-ol.be /st8.lua  -  g.s-ol.be /gtglg /curcur

Code: Select all

print( type(love) )
if false then
  baby:hurt(me)
end
User avatar
Luke100000
Party member
Posts: 232
Joined: Mon Jul 22, 2013 9:17 am
Location: Austria
Contact:

Re: Problem with normal mapping

Post by Luke100000 »

cval wrote:Couldn't get your love file to work, it says
err.png
However, i think you dont really need to draw anything simultaneously. If i get things correctly, you calculate your diffuse in your shader and then draw it as final image.

Here is my old code with normal mapping experiments, hope it helps. You can use arrows to move light around and pgup and pgdown to increase or decrease its height.
shader.love
Thanks, it really helped!
s-ol wrote:You pass one image into the shader with Shader:send and an "extern image" in the shader code.
How fast is this? I want to redraw the image every second.
User avatar
s-ol
Party member
Posts: 1077
Joined: Mon Sep 15, 2014 7:41 pm
Location: Cologne, Germany
Contact:

Re: Problem with normal mapping

Post by s-ol »

Luke100000 wrote:
s-ol wrote:You pass one image into the shader with Shader:send and an "extern image" in the shader code.
How fast is this? I want to redraw the image every second.
so? just do. it's not very performance intensive. You should still sort the stuff you draw by texture anyway though (draw everything with texture and normal map A first, then B, then C....)

s-ol.nu /blog  -  p.s-ol.be /st8.lua  -  g.s-ol.be /gtglg /curcur

Code: Select all

print( type(love) )
if false then
  baby:hurt(me)
end
User avatar
Luke100000
Party member
Posts: 232
Joined: Mon Jul 22, 2013 9:17 am
Location: Austria
Contact:

Re: Problem with normal mapping

Post by Luke100000 »

Next problem: My shader starts flickering at certain pixels when using the length() function.

Code: Select all

	extern vec3 l;
	
	vec4 effect(vec4 colour, Image tex, vec2 tc, vec2 pixCoord) {
		vec4 norm_txl = Texel(tex,tc);
		vec3 normal = normalize(norm_txl.rgb*2.0-1.0);
		vec3 light_vec = normalize(l-pixCoord);
		float attenuation = min(2/pow(length(l-pixCoord)/32, 2), 2);
		float diffuse = max(dot(normal, light_vec)*attenuation, 0.0);
		
		if (tc.x < 0.5) {
			return vec4(1,1,1,1);
		} else {
			return vec4(diffuse, diffuse, diffuse, 1);
		}
	}
Attachments
test2.love
(9.09 KiB) Downloaded 89 times
User avatar
4aiman
Party member
Posts: 262
Joined: Sat Jan 16, 2016 10:30 am

Re: Problem with normal mapping

Post by 4aiman »

Sadly,
Снимок экрана_2016-06-06_10-49-56.png
Снимок экрана_2016-06-06_10-49-56.png (23.35 KiB) Viewed 2981 times
:(
Post Reply

Who is online

Users browsing this forum: No registered users and 203 guests