Add heighmap converter, better normal map shader.

This commit is contained in:
Marcus Ihde 2014-03-08 20:48:51 +01:00
parent 1fbc9b0902
commit 249fff23ae
10 changed files with 289 additions and 104 deletions

BIN
gfx/blopp.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

BIN
gfx/normal_palette.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
gfx/tile.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
gfx/tile_glow.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1018 B

BIN
gfx/tile_normal.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1012 B

263
light.lua
View File

@ -7,6 +7,11 @@ LOVE_LIGHT_LAST_BUFFER = nil
LOVE_LIGHT_BLURV = love.graphics.newShader("shader/blurv.glsl") LOVE_LIGHT_BLURV = love.graphics.newShader("shader/blurv.glsl")
LOVE_LIGHT_BLURH = love.graphics.newShader("shader/blurh.glsl") LOVE_LIGHT_BLURH = love.graphics.newShader("shader/blurh.glsl")
LOVE_LIGHT_TRANSLATE_X = 0
LOVE_LIGHT_TRANSLATE_Y = 0
LOVE_LIGHT_TRANSLATE_X_OLD = 0
LOVE_LIGHT_TRANSLATE_Y_OLD = 0
love.light = {} love.light = {}
-- light world -- light world
@ -27,13 +32,20 @@ function love.light.newWorld()
o.pixelShadow = love.graphics.newCanvas() o.pixelShadow = love.graphics.newCanvas()
o.pixelShadow2 = love.graphics.newCanvas() o.pixelShadow2 = love.graphics.newCanvas()
o.shader = love.graphics.newShader("shader/poly_shadow.glsl") o.shader = love.graphics.newShader("shader/poly_shadow.glsl")
o.shader2 = love.graphics.newShader("shader/pixel_self_shadow.glsl") o.normalShader = love.graphics.newShader("shader/normal.glsl")
o.changed = true o.changed = true
o.blur = 2.0 o.blur = 2.0
-- update -- update
o.update = function() o.update = function()
LOVE_LIGHT_LAST_BUFFER = love.graphics.getCanvas() LOVE_LIGHT_LAST_BUFFER = love.graphics.getCanvas()
love.graphics.setShader(o.shader) love.graphics.setShader(o.shader)
if LOVE_LIGHT_TRANSLATE_X ~= LOVE_LIGHT_TRANSLATE_X_OLD or LOVE_LIGHT_TRANSLATE_Y ~= LOVE_LIGHT_TRANSLATE_Y_OLD then
LOVE_LIGHT_TRANSLATE_X_OLD = LOVE_LIGHT_TRANSLATE_X
LOVE_LIGHT_TRANSLATE_Y_OLD = LOVE_LIGHT_TRANSLATE_Y
o.changed = true
end
if o.changed then if o.changed then
love.graphics.setCanvas(o.shadow) love.graphics.setCanvas(o.shadow)
o.shadow:clear(unpack(o.ambient)) o.shadow:clear(unpack(o.ambient))
@ -49,29 +61,15 @@ function love.light.newWorld()
LOVE_LIGHT_IMAGE = o.img LOVE_LIGHT_IMAGE = o.img
for i = 1, #o.lights do for i = 1, #o.lights do
if o.lights[i].changed or o.changed then if o.lights[i].changed or o.changed then
local curLightX = o.lights[i].x if o.lights[i].x + o.lights[i].range > LOVE_LIGHT_TRANSLATE_X and o.lights[i].x - o.lights[i].range < love.graphics.getWidth() + LOVE_LIGHT_TRANSLATE_X
local curLightY = o.lights[i].y and o.lights[i].y + o.lights[i].range > LOVE_LIGHT_TRANSLATE_Y and o.lights[i].y - o.lights[i].range < love.graphics.getHeight() + LOVE_LIGHT_TRANSLATE_Y
local curLightRange = o.lights[i].range
local curLightColor = {
o.lights[i].red / 255.0,
o.lights[i].green / 255.0,
o.lights[i].blue / 255.0
}
local curLightSmooth = o.lights[i].smooth
local curLightGlow = {
1.0 - o.lights[i].glowSize,
o.lights[i].glowStrength
}
if curLightX + curLightRange > 0 and curLightX - curLightRange < love.graphics.getWidth()
and curLightY + curLightRange > 0 and curLightY - curLightRange < love.graphics.getHeight()
then then
local lightposrange = {curLightX, love.graphics.getHeight() - curLightY, curLightRange} local lightposrange = {o.lights[i].x, love.graphics.getHeight() - o.lights[i].y, o.lights[i].range}
LOVE_LIGHT_CURRENT = o.lights[i] LOVE_LIGHT_CURRENT = o.lights[i]
o.shader:send("lightPositionRange", lightposrange) o.shader:send("lightPositionRange", {o.lights[i].x - LOVE_LIGHT_TRANSLATE_X, love.graphics.getHeight() - (o.lights[i].y - LOVE_LIGHT_TRANSLATE_Y), o.lights[i].range})
o.shader:send("lightColor", curLightColor) o.shader:send("lightColor", {o.lights[i].red / 255.0, o.lights[i].green / 255.0, o.lights[i].blue / 255.0})
o.shader:send("smooth", curLightSmooth) o.shader:send("smooth", o.lights[i].smooth)
o.shader:send("glow", curLightGlow) o.shader:send("glow", {1.0 - o.lights[i].glowSize, o.lights[i].glowStrength})
if o.changed then if o.changed then
love.graphics.setCanvas(o.shadow) love.graphics.setCanvas(o.shadow)
@ -83,14 +81,14 @@ function love.light.newWorld()
-- draw shadow -- draw shadow
love.graphics.setInvertedStencil(shadowStencil) love.graphics.setInvertedStencil(shadowStencil)
love.graphics.setBlendMode("additive") love.graphics.setBlendMode("additive")
love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight()) love.graphics.rectangle("fill", LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y, love.graphics.getWidth(), love.graphics.getHeight())
-- draw shine -- draw shine
love.graphics.setCanvas(o.lights[i].shine) love.graphics.setCanvas(o.lights[i].shine)
o.lights[i].shine:clear(255, 255, 255) o.lights[i].shine:clear(255, 255, 255)
love.graphics.setBlendMode("alpha") love.graphics.setBlendMode("alpha")
love.graphics.setStencil(polyStencil) love.graphics.setStencil(polyStencil)
love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight()) love.graphics.rectangle("fill", LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y, love.graphics.getWidth(), love.graphics.getHeight())
lightsOnScreen = lightsOnScreen + 1 lightsOnScreen = lightsOnScreen + 1
@ -110,12 +108,12 @@ function love.light.newWorld()
love.graphics.setStencil() love.graphics.setStencil()
love.graphics.setColor(unpack(o.ambient)) love.graphics.setColor(unpack(o.ambient))
love.graphics.setBlendMode("alpha") love.graphics.setBlendMode("alpha")
love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight()) love.graphics.rectangle("fill", LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y, love.graphics.getWidth(), love.graphics.getHeight())
love.graphics.setColor(255, 255, 255) love.graphics.setColor(255, 255, 255)
love.graphics.setBlendMode("additive") love.graphics.setBlendMode("additive")
for i = 1, #o.lights do for i = 1, #o.lights do
if o.lights[i].visible then if o.lights[i].visible then
love.graphics.draw(o.lights[i].shadow) love.graphics.draw(o.lights[i].shadow, LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y)
end end
end end
o.isShadowBlur = false o.isShadowBlur = false
@ -130,7 +128,7 @@ function love.light.newWorld()
love.graphics.setBlendMode("additive") love.graphics.setBlendMode("additive")
for i = 1, #o.lights do for i = 1, #o.lights do
if o.lights[i].visible then if o.lights[i].visible then
love.graphics.draw(o.lights[i].shine) love.graphics.draw(o.lights[i].shine, LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y)
end end
end end
@ -148,10 +146,11 @@ function love.light.newWorld()
love.graphics.setColor(255, 255, 255) love.graphics.setColor(255, 255, 255)
love.graphics.draw(o.img[i].normal, o.img[i].x - o.img[i].ox2, o.img[i].y - o.img[i].oy2) love.graphics.draw(o.img[i].normal, o.img[i].x - o.img[i].ox2, o.img[i].y - o.img[i].oy2)
else else
love.graphics.setColor(127, 127, 255) love.graphics.setColor(0, 0, 0, 0)
love.graphics.rectangle("fill", o.img[i].x - o.img[i].ox2, o.img[i].y - o.img[i].oy2, o.img[i].imgWidth, o.img[i].imgHeight) love.graphics.rectangle("fill", o.img[i].x - o.img[i].ox2, o.img[i].y - o.img[i].oy2, o.img[i].imgWidth, o.img[i].imgHeight)
end end
end end
love.graphics.setColor(255, 255, 255)
end end
o.pixelShadow2:clear() o.pixelShadow2:clear()
@ -159,24 +158,15 @@ function love.light.newWorld()
love.graphics.setBlendMode("additive") love.graphics.setBlendMode("additive")
love.graphics.setShader(o.shader2) love.graphics.setShader(o.shader2)
local curLightAmbient = {
o.ambient[1] / 255.0,
o.ambient[2] / 255.0,
o.ambient[3] / 255.0
}
for i = 1, #o.lights do for i = 1, #o.lights do
if o.lights[i].visible then if o.lights[i].visible then
local curLightColor = { o.normalShader:send('screenResolution', {love.graphics.getWidth(), love.graphics.getHeight()})
o.lights[i].red / 255.0, o.normalShader:send('lightColor', {o.lights[i].red / 255.0, o.lights[i].green / 255.0, o.lights[i].blue / 255.0})
o.lights[i].green / 255.0, o.normalShader:send('lightPosition',{o.lights[i].x, love.graphics.getHeight() - o.lights[i].y, o.lights[i].z / 255.0})
o.lights[i].blue / 255.0 o.normalShader:send('lightRange',{o.lights[i].range})
} o.normalShader:send("lightSmooth", o.lights[i].smooth)
o.shader2:send("lightPosition", {o.lights[i].x, love.graphics.getHeight() - o.lights[i].y, 16}) love.graphics.setShader(o.normalShader)
o.shader2:send("lightRange", {o.lights[i].range}) love.graphics.draw(o.normalMap, LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y)
o.shader2:send("lightColor", curLightColor)
o.shader2:send("lightAmbient", curLightAmbient)
o.shader2:send("lightSmooth", {o.lights[i].smooth})
love.graphics.draw(o.normalMap)
end end
end end
@ -184,7 +174,11 @@ function love.light.newWorld()
o.pixelShadow:clear(255, 255, 255) o.pixelShadow:clear(255, 255, 255)
love.graphics.setCanvas(o.pixelShadow) love.graphics.setCanvas(o.pixelShadow)
love.graphics.setBlendMode("alpha") love.graphics.setBlendMode("alpha")
love.graphics.draw(o.pixelShadow2) love.graphics.draw(o.pixelShadow2, LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y)
love.graphics.setBlendMode("additive")
love.graphics.setColor({o.ambient[1], o.ambient[2], o.ambient[3]})
love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight())
love.graphics.setBlendMode("alpha")
-- create glow map -- create glow map
if o.changed then if o.changed then
@ -192,7 +186,11 @@ function love.light.newWorld()
love.graphics.setCanvas(o.glowMap) love.graphics.setCanvas(o.glowMap)
for i = 1, #o.img do for i = 1, #o.img do
if o.img[i].glow then if o.img[i].glow then
love.graphics.setColor(255, 255, 255)
love.graphics.draw(o.img[i].glow, o.img[i].x - o.img[i].ox2, o.img[i].y - o.img[i].oy2) love.graphics.draw(o.img[i].glow, o.img[i].x - o.img[i].ox2, o.img[i].y - o.img[i].oy2)
else
love.graphics.setColor(0, 0, 0)
love.graphics.draw(o.img[i].img, o.img[i].x - o.img[i].ox2, o.img[i].y - o.img[i].oy2)
end end
end end
o.isGlowBlur = false o.isGlowBlur = false
@ -215,19 +213,19 @@ function love.light.newWorld()
love.graphics.setBlendMode("alpha") love.graphics.setBlendMode("alpha")
love.graphics.setCanvas(o.shadow2) love.graphics.setCanvas(o.shadow2)
love.graphics.setShader(LOVE_LIGHT_BLURV) love.graphics.setShader(LOVE_LIGHT_BLURV)
love.graphics.draw(o.shadow) love.graphics.draw(o.shadow, LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y)
love.graphics.setCanvas(o.shadow) love.graphics.setCanvas(o.shadow)
love.graphics.setShader(LOVE_LIGHT_BLURH) love.graphics.setShader(LOVE_LIGHT_BLURH)
love.graphics.draw(o.shadow2) love.graphics.draw(o.shadow2, LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y)
love.graphics.setCanvas(LOVE_LIGHT_LAST_BUFFER) love.graphics.setCanvas(LOVE_LIGHT_LAST_BUFFER)
love.graphics.setBlendMode("multiplicative") love.graphics.setBlendMode("multiplicative")
love.graphics.setShader() love.graphics.setShader()
love.graphics.draw(o.shadow) love.graphics.draw(o.shadow, LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y)
love.graphics.setBlendMode("alpha") love.graphics.setBlendMode("alpha")
else else
love.graphics.setBlendMode("multiplicative") love.graphics.setBlendMode("multiplicative")
love.graphics.setShader() love.graphics.setShader()
love.graphics.draw(o.shadow) love.graphics.draw(o.shadow, LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y)
love.graphics.setBlendMode("alpha") love.graphics.setBlendMode("alpha")
end end
end end
@ -236,7 +234,7 @@ function love.light.newWorld()
love.graphics.setColor(255, 255, 255) love.graphics.setColor(255, 255, 255)
love.graphics.setBlendMode("multiplicative") love.graphics.setBlendMode("multiplicative")
love.graphics.setShader() love.graphics.setShader()
love.graphics.draw(o.shine) love.graphics.draw(o.shine, LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y)
love.graphics.setBlendMode("alpha") love.graphics.setBlendMode("alpha")
end end
-- draw pixel shadow -- draw pixel shadow
@ -244,7 +242,7 @@ function love.light.newWorld()
love.graphics.setColor(255, 255, 255) love.graphics.setColor(255, 255, 255)
love.graphics.setBlendMode("multiplicative") love.graphics.setBlendMode("multiplicative")
love.graphics.setShader() love.graphics.setShader()
love.graphics.draw(o.pixelShadow) love.graphics.draw(o.pixelShadow, LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y)
love.graphics.setBlendMode("alpha") love.graphics.setBlendMode("alpha")
end end
-- draw glow -- draw glow
@ -253,7 +251,7 @@ function love.light.newWorld()
if o.isGlowBlur then if o.isGlowBlur then
love.graphics.setBlendMode("additive") love.graphics.setBlendMode("additive")
love.graphics.setShader() love.graphics.setShader()
love.graphics.draw(o.glowMap) love.graphics.draw(o.glowMap, LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y)
love.graphics.setBlendMode("alpha") love.graphics.setBlendMode("alpha")
else else
LOVE_LIGHT_BLURV:send("steps", 1.0) LOVE_LIGHT_BLURV:send("steps", 1.0)
@ -262,14 +260,14 @@ function love.light.newWorld()
love.graphics.setBlendMode("alpha") love.graphics.setBlendMode("alpha")
love.graphics.setCanvas(o.glowMap2) love.graphics.setCanvas(o.glowMap2)
love.graphics.setShader(LOVE_LIGHT_BLURV) love.graphics.setShader(LOVE_LIGHT_BLURV)
love.graphics.draw(o.glowMap) love.graphics.draw(o.glowMap, LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y)
love.graphics.setCanvas(o.glowMap) love.graphics.setCanvas(o.glowMap)
love.graphics.setShader(LOVE_LIGHT_BLURH) love.graphics.setShader(LOVE_LIGHT_BLURH)
love.graphics.draw(o.glowMap2) love.graphics.draw(o.glowMap2, LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y)
love.graphics.setCanvas(LOVE_LIGHT_LAST_BUFFER) love.graphics.setCanvas(LOVE_LIGHT_LAST_BUFFER)
love.graphics.setBlendMode("additive") love.graphics.setBlendMode("additive")
love.graphics.setShader() love.graphics.setShader()
love.graphics.draw(o.glowMap) love.graphics.draw(o.glowMap, LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y)
love.graphics.setBlendMode("alpha") love.graphics.setBlendMode("alpha")
o.isGlowBlur = true o.isGlowBlur = true
@ -293,6 +291,11 @@ function love.light.newWorld()
o.img = {} o.img = {}
o.changed = true o.changed = true
end end
-- set offset
o.setTranslation = function(translateX, translateY)
LOVE_LIGHT_TRANSLATE_X = translateX
LOVE_LIGHT_TRANSLATE_Y = translateY
end
-- set ambient color -- set ambient color
o.setAmbientColor = function(red, green, blue) o.setAmbientColor = function(red, green, blue)
o.ambient = {red, green, blue} o.ambient = {red, green, blue}
@ -389,7 +392,7 @@ function love.light.newLight(p, x, y, red, green, blue, range)
o.shine = love.graphics.newCanvas() o.shine = love.graphics.newCanvas()
o.x = x o.x = x
o.y = y o.y = y
o.z = 1 o.z = 15
o.red = red o.red = red
o.green = green o.green = green
o.blue = blue o.blue = blue
@ -478,6 +481,7 @@ function love.light.newRectangle(p, x, y, width, height)
o.ox = o.width / 2 o.ox = o.width / 2
o.oy = o.height / 2 o.oy = o.height / 2
o.shine = true o.shine = true
o.type = "rectangle"
p.changed = true p.changed = true
o.data = { o.data = {
o.x - o.ox, o.x - o.ox,
@ -564,7 +568,7 @@ function love.light.newRectangle(p, x, y, width, height)
end end
-- get type -- get type
o.getType = function() o.getType = function()
return "rectangle" return o.type
end end
return o return o
@ -579,6 +583,7 @@ function love.light.newCircle(p, x, y, radius)
o.y = y or 0 o.y = y or 0
o.radius = radius or 200 o.radius = radius or 200
o.shine = true o.shine = true
o.type = "circle"
p.changed = true p.changed = true
-- set position -- set position
o.setPosition = function(x, y) o.setPosition = function(x, y)
@ -633,7 +638,7 @@ function love.light.newCircle(p, x, y, radius)
end end
-- get type -- get type
o.getType = function() o.getType = function()
return "circle" return o.type
end end
return o return o
@ -645,6 +650,7 @@ function love.light.newPolygon(p, ...)
p.poly[#p.poly + 1] = o p.poly[#p.poly + 1] = o
o.id = #p.poly o.id = #p.poly
o.shine = true o.shine = true
o.type = "polygon"
p.changed = true p.changed = true
if ... then if ... then
o.data = {...} o.data = {...}
@ -672,7 +678,7 @@ function love.light.newPolygon(p, ...)
end end
-- get type -- get type
o.getType = function() o.getType = function()
return "polygon" return o.type
end end
return o return o
@ -698,6 +704,7 @@ function love.light.newImage(p, img, x, y, width, height, ox, oy)
o.imgWidth = img:getWidth() o.imgWidth = img:getWidth()
o.imgHeight = img:getHeight() o.imgHeight = img:getHeight()
o.shine = true o.shine = true
o.type = "image"
p.changed = true p.changed = true
o.data = { o.data = {
o.x - o.ox, o.x - o.ox,
@ -786,13 +793,90 @@ function love.light.newImage(p, img, x, y, width, height, ox, oy)
o.setNormalMap = function(normal) o.setNormalMap = function(normal)
o.normal = normal o.normal = normal
end end
-- set height map
o.setHeightMap = function(heightMap, strength)
o.normal = HeightMapToNormalMap(heightMap, strength)
end
-- generate flat normal map
o.generateNormalMapFlat = function(mode)
local imgData = o.img:getData()
local imgNormalData = love.image.newImageData(o.imgWidth, o.imgHeight)
local color
if mode == "top" then
color = {127, 127, 255}
elseif mode == "front" then
color = {127, 255, 127}
elseif mode == "back" then
color = {127, 0, 127}
elseif mode == "left" then
color = {31, 255, 223}
elseif mode == "right" then
color = {223, 223, 127}
end
for i = 0, o.imgHeight - 1 do
for k = 0, o.imgWidth - 1 do
local r, g, b, a = imgData:getPixel(k, i)
if a > 0 then
imgNormalData:setPixel(k, i, color[1], color[2], color[3], 255)
end
end
end
o.normal = love.graphics.newImage(imgNormalData)
end
-- generate faded normal map
o.generateNormalMapFade = function(horizontalFade, verticalFade)
local imgData = o.img:getData()
local imgNormalData = love.image.newImageData(o.imgWidth, o.imgHeight)
local dx = 255.0 / o.imgWidth
local dy = 255.0 / o.imgHeight
local nx
local ny
local nz
for i = 0, o.imgWidth - 1 do
for k = 0, o.imgHeight - 1 do
local r, g, b, a = imgData:getPixel(i, k)
if a > 0 then
if horizontalFade == "fade" then
nx = i * dx
elseif horizontalFade == "inverse" then
nx = 255 - i * dx
else
nx = 127
end
if verticalFade == "fade" then
ny = 127 + k * dy * 0.5
nz = 255 - k * dy * 0.5
elseif verticalFade == "inverse" then
ny = 127 - k * dy * 0.5
nz = 127 - k * dy * 0.25
else
ny = 255
nz = 127
end
imgNormalData:setPixel(i, k, nx, ny, nz, 255)
end
end
end
o.normal = love.graphics.newImage(imgNormalData)
end
-- generate normal map
o.generateNormalMap = function(strength)
o.normal = HeightMapToNormalMap(o.img, strength)
end
-- set normal -- set normal
o.setGlowMap = function(glow) o.setGlowMap = function(glow)
o.glow = glow o.glow = glow
end end
-- get type -- get type
o.getType = function() o.getType = function()
return "image" return o.type
end end
return o return o
@ -875,10 +959,10 @@ function calculateShadows(lightsource, geometry, circle, image)
for i, v in pairs(circle) do for i, v in pairs(circle) do
local curShadowGeometry = {} local curShadowGeometry = {}
local angle = math.atan2(lightsource.x - v.x, v.y - lightsource.y) + math.pi / 2 local angle = math.atan2(lightsource.x - v.x, v.y - lightsource.y) + math.pi / 2
local x2 = v.x + math.sin(angle) * v.radius local x2 = (v.x + math.sin(angle) * v.radius)
local y2 = v.y - math.cos(angle) * v.radius local y2 = (v.y - math.cos(angle) * v.radius)
local x3 = v.x - math.sin(angle) * v.radius local x3 = (v.x - math.sin(angle) * v.radius)
local y3 = v.y + math.cos(angle) * v.radius local y3 = (v.y + math.cos(angle) * v.radius)
curShadowGeometry[1] = x2 curShadowGeometry[1] = x2
curShadowGeometry[2] = y2 curShadowGeometry[2] = y2
@ -904,7 +988,7 @@ shadowStencil = function()
love.graphics.polygon("fill", unpack(LOVE_LIGHT_POLY[i].data)) love.graphics.polygon("fill", unpack(LOVE_LIGHT_POLY[i].data))
end end
for i = 1, #LOVE_LIGHT_CIRCLE do for i = 1, #LOVE_LIGHT_CIRCLE do
love.graphics.circle("fill", LOVE_LIGHT_CIRCLE[i].getX(), LOVE_LIGHT_CIRCLE[i].getY(), LOVE_LIGHT_CIRCLE[i].getRadius()) love.graphics.circle("fill", LOVE_LIGHT_CIRCLE[i].x, LOVE_LIGHT_CIRCLE[i].y, LOVE_LIGHT_CIRCLE[i].radius)
end end
for i = 1, #LOVE_LIGHT_IMAGE do for i = 1, #LOVE_LIGHT_IMAGE do
--love.graphics.rectangle("fill", LOVE_LIGHT_IMAGE[i].x, LOVE_LIGHT_IMAGE[i].y, LOVE_LIGHT_IMAGE[i].width, LOVE_LIGHT_IMAGE[i].height) --love.graphics.rectangle("fill", LOVE_LIGHT_IMAGE[i].x, LOVE_LIGHT_IMAGE[i].y, LOVE_LIGHT_IMAGE[i].width, LOVE_LIGHT_IMAGE[i].height)
@ -914,7 +998,7 @@ end
polyStencil = function() polyStencil = function()
for i = 1, #LOVE_LIGHT_CIRCLE do for i = 1, #LOVE_LIGHT_CIRCLE do
if LOVE_LIGHT_CIRCLE[i].shine then if LOVE_LIGHT_CIRCLE[i].shine then
love.graphics.circle("fill", LOVE_LIGHT_CIRCLE[i].getX(), LOVE_LIGHT_CIRCLE[i].getY(), LOVE_LIGHT_CIRCLE[i].getRadius()) love.graphics.circle("fill", LOVE_LIGHT_CIRCLE[i].x, LOVE_LIGHT_CIRCLE[i].y, LOVE_LIGHT_CIRCLE[i].radius)
end end
end end
for i = 1, #LOVE_LIGHT_POLY do for i = 1, #LOVE_LIGHT_POLY do
@ -928,3 +1012,50 @@ polyStencil = function()
end end
end end
end end
function HeightMapToNormalMap(heightMap, strength)
local imgData = heightMap:getData()
local imgData2 = love.image.newImageData(heightMap:getWidth(), heightMap:getHeight())
local red, green, blue, alpha
local x, y
local matrix = {}
matrix[1] = {}
matrix[2] = {}
matrix[3] = {}
strength = strength or 1.0
for i = 0, heightMap:getHeight() - 1 do
for k = 0, heightMap:getWidth() - 1 do
for l = 1, 3 do
for m = 1, 3 do
if k + (l - 1) < 1 then
x = heightMap:getWidth() - 1
elseif k + (l - 1) > heightMap:getWidth() - 1 then
x = 1
else
x = k + l - 1
end
if i + (m - 1) < 1 then
y = heightMap:getHeight() - 1
elseif i + (m - 1) > heightMap:getHeight() - 1 then
y = 1
else
y = i + m - 1
end
local red, green, blue, alpha = imgData:getPixel(x, y)
matrix[l][m] = red
end
end
red = (255 + ((matrix[1][2] - matrix[2][2]) + (matrix[2][2] - matrix[3][2])) * strength) / 2.0
green = (255 - ((matrix[2][2] - matrix[1][1]) + (matrix[2][3] - matrix[2][2])) * strength) / 2.0
blue = 192
imgData2:setPixel(k, i, red, green, blue)
end
end
return love.graphics.newImage(imgData2)
end

View File

@ -57,6 +57,10 @@ function love.load()
machine2 = love.graphics.newImage "gfx/machine2.png" machine2 = love.graphics.newImage "gfx/machine2.png"
machine2_normal = love.graphics.newImage "gfx/machine2_normal.png" machine2_normal = love.graphics.newImage "gfx/machine2_normal.png"
machine2_glow = love.graphics.newImage "gfx/machine2_glow.png" machine2_glow = love.graphics.newImage "gfx/machine2_glow.png"
blopp = love.graphics.newImage "gfx/blopp.png"
tile = love.graphics.newImage "gfx/tile.png"
tile_normal = love.graphics.newImage "gfx/tile_normal.png"
tile_glow = love.graphics.newImage "gfx/tile_glow.png"
-- light world -- light world
lightRange = 300 lightRange = 300
@ -77,6 +81,7 @@ function love.load()
shadowBlur = 2.0 shadowBlur = 2.0
bloomOn = true bloomOn = true
textureOn = true textureOn = true
normalOn = false
offsetX = 0.0 offsetX = 0.0
offsetY = 0.0 offsetY = 0.0
@ -168,14 +173,19 @@ function love.draw()
end end
love.graphics.setBlendMode("alpha") love.graphics.setBlendMode("alpha")
if normalOn then
love.graphics.setColor(127, 127, 255)
love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight())
else
love.graphics.setColor(255, 255, 255) love.graphics.setColor(255, 255, 255)
if textureOn then if textureOn then
love.graphics.draw(imgFloor, quadScreen, offsetX % 32 - 32, offsetY % 24 - 24) love.graphics.draw(imgFloor, quadScreen, offsetX % 32 - 32, offsetY % 24 - 24)
else else
love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight()) love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight())
end end
end
-- draw lightmap shadows -- draw lightmap shadows
if lightOn then if lightOn and not normalOn then
lightWorld.drawShadow() lightWorld.drawShadow()
end end
@ -189,24 +199,30 @@ function love.draw()
end end
-- draw lightmap shine -- draw lightmap shine
if lightOn then if lightOn and not normalOn then
lightWorld.drawShine() lightWorld.drawShine()
end end
for i = 1, phyCnt do for i = 1, phyCnt do
if phyLight[i].getType() == "image" then if phyLight[i].getType() == "image" then
love.graphics.setColor(223 + math.sin(i) * 31, 223 + math.cos(i) * 31, 223 + math.tan(i) * 31) if not normalOn then
--love.graphics.setColor(255, 255, 255)
love.graphics.setColor(127 + math.sin(i) * 127, 127 + math.cos(i) * 127, 127 + math.tan(i) * 127)
love.graphics.draw(phyLight[i].img, phyLight[i].x - phyLight[i].ox2, phyLight[i].y - phyLight[i].oy2) love.graphics.draw(phyLight[i].img, phyLight[i].x - phyLight[i].ox2, phyLight[i].y - phyLight[i].oy2)
elseif phyLight[i].normal then
love.graphics.setColor(255, 255, 255)
love.graphics.draw(phyLight[i].normal, phyLight[i].x - phyLight[i].ox2, phyLight[i].y - phyLight[i].oy2)
end
end end
end end
-- draw pixel shadow -- draw pixel shadow
if lightOn then if lightOn and not normalOn then
lightWorld.drawPixelShadow() lightWorld.drawPixelShadow()
end end
-- draw glow -- draw glow
if lightOn then if lightOn and not normalOn then
lightWorld.drawGlow() lightWorld.drawGlow()
end end
@ -261,6 +277,13 @@ function love.draw()
love.graphics.setColor(255, 0, 0) love.graphics.setColor(255, 0, 0)
love.graphics.print("F7: Texture off", 4 + 152 * 1, 4 + 20 * 1) love.graphics.print("F7: Texture off", 4 + 152 * 1, 4 + 20 * 1)
end end
if normalOn then
love.graphics.setColor(0, 255, 0)
love.graphics.print("F8: Normal on", 4 + 152 * 2, 4 + 20 * 1)
else
love.graphics.setColor(255, 0, 0)
love.graphics.print("F8: Normal off", 4 + 152 * 2, 4 + 20 * 1)
end
love.graphics.setColor(255, 0, 255) love.graphics.setColor(255, 0, 255)
love.graphics.print("F11: Clear obj.", 4 + 152 * 3, 4 + 20 * 1) love.graphics.print("F11: Clear obj.", 4 + 152 * 3, 4 + 20 * 1)
love.graphics.print("F12: Clear lights", 4 + 152 * 4, 4 + 20 * 1) love.graphics.print("F12: Clear lights", 4 + 152 * 4, 4 + 20 * 1)
@ -351,6 +374,8 @@ function love.keypressed(k, u)
bloomOn = not bloomOn bloomOn = not bloomOn
elseif k == "f7" then elseif k == "f7" then
textureOn = not textureOn textureOn = not textureOn
elseif k == "f8" then
normalOn = not normalOn
elseif k == "f11" then elseif k == "f11" then
physicWorld:destroy() physicWorld:destroy()
lightWorld.clearObjects() lightWorld.clearObjects()
@ -407,5 +432,25 @@ function love.keypressed(k, u)
phyShape[phyCnt] = love.physics.newRectangleShape(0, 0, 24, 32) phyShape[phyCnt] = love.physics.newRectangleShape(0, 0, 24, 32)
phyFixture[phyCnt] = love.physics.newFixture(phyBody[phyCnt], phyShape[phyCnt]) phyFixture[phyCnt] = love.physics.newFixture(phyBody[phyCnt], phyShape[phyCnt])
phyFixture[phyCnt]:setRestitution(0.5) phyFixture[phyCnt]:setRestitution(0.5)
elseif k == "6" then
-- add image
phyCnt = phyCnt + 1
phyLight[phyCnt] = lightWorld.newImage(blopp, mx, my, 42, 16, 21, 20)
phyLight[phyCnt].generateNormalMapFade("fade", "fade")
phyBody[phyCnt] = love.physics.newBody(physicWorld, mx, my, "dynamic")
phyShape[phyCnt] = love.physics.newRectangleShape(0, 0, 42, 29)
phyFixture[phyCnt] = love.physics.newFixture(phyBody[phyCnt], phyShape[phyCnt])
phyFixture[phyCnt]:setRestitution(0.5)
elseif k == "7" then
-- add image
phyCnt = phyCnt + 1
phyLight[phyCnt] = lightWorld.newImage(tile, mx, my)
phyLight[phyCnt].setHeightMap(tile_normal, 2.0)
phyLight[phyCnt].setGlowMap(tile_glow)
phyLight[phyCnt].setShadow(false)
phyBody[phyCnt] = love.physics.newBody(physicWorld, mx, my, "dynamic")
phyShape[phyCnt] = love.physics.newRectangleShape(0, 0, 64, 64)
phyFixture[phyCnt] = love.physics.newFixture(phyBody[phyCnt], phyShape[phyCnt])
phyFixture[phyCnt]:setRestitution(0.5)
end end
end end

33
shader/normal.glsl Normal file
View File

@ -0,0 +1,33 @@
extern vec2 screenResolution;
extern vec3 lightPosition;
extern vec3 lightColor;
extern float lightRange;
extern float lightSmooth;
vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords) {
vec4 pixelColor = Texel(texture, texture_coords);
if(pixelColor.a > 0.0) {
vec3 normal = vec3(pixelColor.r, 1 - pixelColor.g, pixelColor.b);
float dist = distance(lightPosition, vec3(screen_coords, normal.b));
if(dist < lightRange) {
vec3 dir = vec3((lightPosition.xy - screen_coords.xy) / screenResolution.xy, lightPosition.z);
dir.x *= screenResolution.x / screenResolution.y;
vec3 N = normalize(normal * 2.0 - 1.0);
vec3 L = normalize(dir);
vec3 diff = lightColor * max(dot(N, L), 0.0);
float att = clamp((1.0 - dist / lightRange) / lightSmooth, 0.0, 1.0);
return vec4(diff * att, 1.0);
} else {
return vec4(0.0, 0.0, 0.0, 1.0);
}
} else {
return vec4(0.0);
}
}

View File

@ -1,24 +0,0 @@
extern vec3 lightPosition;
extern float lightRange;
extern vec3 lightColor;
extern vec3 lightAmbient;
extern float lightSmooth;
vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 pixel_coords) {
vec3 lightDirection = vec3(pixel_coords.xy, 0) - lightPosition.xyz;
float distance = length(lightDirection);
vec4 pixel = Texel(texture, texture_coords);
vec3 normal = vec3(pixel.x, 1 - pixel.y, pixel.z);
normal = mix(vec3(-1), vec3(1), normal);
float att = 1 - distance / lightRange;
if(pixel.a > 0.0 && distance < lightRange) {
return vec4(vec3(clamp((1 - dot(normal, lightDirection)) * pow(att, lightSmooth * 4.0), 0.0, 1.0)) * lightColor + lightAmbient, 1.0);
} else if(pixel.a == 0.0) {
return vec4(0.0);
} else {
return vec4(0.0, 0.0, 0.0, 1.0);
}
}