From aa4813676deb7cd580f8efa552b2ca656af045d6 Mon Sep 17 00:00:00 2001 From: Marcus Ihde Date: Thu, 6 Mar 2014 16:56:25 +0100 Subject: [PATCH] Add glow light. --- conf.lua | 2 +- chest.png => gfx/chest.png | Bin gfx/chest_normal.png | Bin 0 -> 1268 bytes circle.png => gfx/circle.png | Bin circle_normal.png => gfx/circle_normal.png | Bin cone.png => gfx/cone.png | Bin 1324 -> 1301 bytes cone_normal.png => gfx/cone_normal.png | Bin floor.png => gfx/floor.png | Bin 1821 -> 1821 bytes gfx/font.png | Bin 0 -> 3411 bytes gfx/machine.png | Bin 0 -> 1244 bytes gfx/machine2.png | Bin 0 -> 1346 bytes chest_normal.png => gfx/machine2_glow.png | Bin 1074 -> 988 bytes gfx/machine2_normal.png | Bin 0 -> 1337 bytes gfx/machine_glow.png | Bin 0 -> 979 bytes gfx/machine_normal.png | Bin 0 -> 1099 bytes normal_palett.png => gfx/normal_palett.png | Bin light.lua | 178 +++++++++++----- main.lua | 230 ++++++++++++++------- postshader.lua | 2 + shader/blurh.glsl | 13 +- shader/blurv.glsl | 13 +- shader/pixel_self_shadow.glsl | 4 +- 22 files changed, 306 insertions(+), 136 deletions(-) rename chest.png => gfx/chest.png (100%) create mode 100644 gfx/chest_normal.png rename circle.png => gfx/circle.png (100%) rename circle_normal.png => gfx/circle_normal.png (100%) rename cone.png => gfx/cone.png (70%) rename cone_normal.png => gfx/cone_normal.png (100%) rename floor.png => gfx/floor.png (96%) create mode 100644 gfx/font.png create mode 100644 gfx/machine.png create mode 100644 gfx/machine2.png rename chest_normal.png => gfx/machine2_glow.png (66%) create mode 100644 gfx/machine2_normal.png create mode 100644 gfx/machine_glow.png create mode 100644 gfx/machine_normal.png rename normal_palett.png => gfx/normal_palett.png (100%) diff --git a/conf.lua b/conf.lua index 87841a8..b5987b4 100644 --- a/conf.lua +++ b/conf.lua @@ -13,7 +13,7 @@ function love.conf(t) t.window.minheight = 1 -- Minimum window height if the window is resizable (number) t.window.fullscreen = false -- Enable fullscreen (boolean) t.window.fullscreentype = "normal" -- Standard fullscreen or desktop fullscreen mode (string) - t.window.vsync = false -- Enable vertical sync (boolean) + t.window.vsync = true -- Enable vertical sync (boolean) t.window.fsaa = 0 -- The number of samples to use with multi-sampled antialiasing (number) t.window.display = 1 -- Index of the monitor to show the window in (number) t.window.highdpi = false -- Enable high-dpi mode for the window on a Retina display (boolean). Added in 0.9.1 diff --git a/chest.png b/gfx/chest.png similarity index 100% rename from chest.png rename to gfx/chest.png diff --git a/gfx/chest_normal.png b/gfx/chest_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..cb0decfb3978d26558aed7baa43478762ac0ddc0 GIT binary patch literal 1268 zcmeAS@N?(olHy`uVBq!ia0vp^3P5bY!3-qbi#lR~6id3JuOkD)#(wTUiL49^%nSiO zA+EKxf9mS~*4O{5{Zm`_x32zQz4w;q4GsUBn*KNJ{Mhinq49rX)BmRC|II)XM!{$Z z46_h;agZeu=q1hqkH}&M2EM%@%;^4m!djr9WQl7;NpOBzNqJ&XDnmeGW?qS&pKFLh znX#U!o`tz}129)Hrh2+KhFJKo4T>&0tiZEnrKpC|_x*Y0s>w@k8UM|gGNCYGEC0i_ z{{nBbGyaWB@fTY9?&`kO{6Dn}SHd>#6)e5B*mH}xjyCfb0alh)ZN{wl2~NGc%oi5~i>_kk&D%Vs>xp7K#5 zbJE&|6y99Mnk?4Cjyn{J4S#&eIJ8H7ykG!GnO014PWpZ3r4S$A^W+W|&d<~DH1m~uG6gTe~DWM4fY|`R( literal 0 HcmV?d00001 diff --git a/circle.png b/gfx/circle.png similarity index 100% rename from circle.png rename to gfx/circle.png diff --git a/circle_normal.png b/gfx/circle_normal.png similarity index 100% rename from circle_normal.png rename to gfx/circle_normal.png diff --git a/cone.png b/gfx/cone.png similarity index 70% rename from cone.png rename to gfx/cone.png index 01b7fd53155485950703830478c70cd325ab6a04..6b18ab733626cbe80c26ef878faa03f0caf90b66 100644 GIT binary patch delta 183 zcmV;o07(C=3Y7|wJh4Ce0tWy90ACuhnzKCv7Xb>k000iQ0nW&|rITI+D1UlML_t(I zPu-JC62Kq`Ln-&av*i~m$kJ8asCgn|Cen)W#K4|x0o7-d6jV8ofK%5Z8g(HwomcHD z;He8s4<3kU3OX{y!N#yn5CW#J;sm&>5Px|)>|=7y07uFHM}aS2}PHV{s=r9MK(dL~W?!hL)k`z^h&S4Q}(qQFVq0Ry+Uz002ov JPDHLkV1jkOQ`Z0h diff --git a/cone_normal.png b/gfx/cone_normal.png similarity index 100% rename from cone_normal.png rename to gfx/cone_normal.png diff --git a/floor.png b/gfx/floor.png similarity index 96% rename from floor.png rename to gfx/floor.png index f11b5faf390e204b2d82a20f74c0b6d9a74ca1fc..51948898dd57127874557c39be7ebb04998a6265 100644 GIT binary patch delta 23 fcmbQsHMe3}^mT=WP! diff --git a/gfx/font.png b/gfx/font.png new file mode 100644 index 0000000000000000000000000000000000000000..35a49d8fb8b6765a19c180b629e31f75fbe33293 GIT binary patch literal 3411 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 delta 277 zcmcb^zKKJzGr-TCmrII^fq{Y7)59eQNGkxb0S7aXbT8_Nov0|m&AWxwK3Ort~ z|Np;p^kU9}_N?OUB@-N;%$TCXG9`xpw-=|;TkSx$)mJ3B+P5fbF3LYBuuE;?Mmqy=VdBRrXq&z!w-qo!s;trh)TW07n?TBN$asNH9 zkb+s-{YJ$L_Hw>#mY*2*6m6HfV9hD!_4@LKSIi6F3oSmg{ciKUnO<{tPP+QSZa;q| Z<4;-!PC{xWt~$(69DYRYzP1V diff --git a/gfx/machine2_normal.png b/gfx/machine2_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..879997fb75f33d0819ca6c4f60a12161ecd4a828 GIT binary patch literal 1337 zcmeAS@N?(olHy`uVBq!ia0vp^5!lvNA9*GX(gA zxB|t^%uY&pZ{cg$DY0dX=%EJblMO1D8gy?rSUhPkJ9*OOO+&z^hL~>+-p{vW{%k1v z(@^=hq3&NpgX*o5W+$I}Z)s@w-}tYg{cl6xpN8o_8g?08A^iug8z?fz!3bM zT@@H1oCO|{#S9F5J3yE*%kgV8P*AeOHKHUqKdq!Zu_%=xATcwqM9#n8cVo4Gy|0PEuMVz^OJPiG_Dc z;sG^1HML*!8zqBnJzN@jIK#wp(ll2YZrD_qcxuJ!CY2jIe*`Rja%HNbkj$K#ngUB8 z5LMm5V$Q$bM#SUviA7!?xH-5wy*<2oy&RYXCBi~DCjGzB%cN?NQ|2&9W7*RSTYmqy kU$y!{r_`ASOYv#E42K`LGza*WXM+-*r>mdKI;Vst0M^;4w*UYD literal 0 HcmV?d00001 diff --git a/gfx/machine_glow.png b/gfx/machine_glow.png new file mode 100644 index 0000000000000000000000000000000000000000..897c0da0c0fee652013805d63773bc59cc833576 GIT binary patch literal 979 zcmeAS@N?(olHy`uVBq!ia0vp^3P5bY!3-qbi#lR~6id3JuOkD)#(wTUiL49^%nSiO zA+A7i24hx+G%kjj{0wJA82(FwL`K1A2#kyn$nWdA1@tLrfk$L90|Vb)5N34$Jz*_S zP_o1|q9iy!t)x7$D3u`~F*C13&(AePq0Cs%RL{cPx&f4{Ts&PILoEE?PB0W=P~bTf zwf6u2P2Ac>20JEL9)G%mt5Si#rs_d}fC{U9jmC{>P4_owf=Mv@f=G_{!Tbunn3LMf Uyy>=6Z-TP-p4LW@|c{c5V=&>VQZQO`@>mhrZ2p;xbur%oVSwg1Vj7g2{Ce? zLcIc4Ot$&yzpkRl-0c6VoV^XJ9>0CKzUl{qwzdRwO2)pupvd-g^>bP0l+XkK 0 and curLightX-curLightRange < love.graphics.getWidth() - and curLightY+curLightRange > 0 and curLightY-curLightRange < love.graphics.getHeight() + if curLightX + curLightRange > 0 and curLightX - curLightRange < love.graphics.getWidth() + and curLightY + curLightRange > 0 and curLightY - curLightRange < love.graphics.getHeight() then local lightposrange = {curLightX, love.graphics.getHeight() - curLightY, curLightRange} LOVE_LIGHT_CURRENT = o.lights[i] @@ -88,6 +93,10 @@ function love.light.newWorld() love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight()) lightsOnScreen = lightsOnScreen + 1 + + o.lights[i].visible = true + else + o.lights[i].visible = false end o.lights[i].changed = o.changed @@ -105,8 +114,11 @@ function love.light.newWorld() love.graphics.setColor(255, 255, 255) love.graphics.setBlendMode("additive") for i = 1, #o.lights do - love.graphics.draw(o.lights[i].shadow) + if o.lights[i].visible then + love.graphics.draw(o.lights[i].shadow) + end end + o.isShadowBlur = false end -- update shine @@ -114,26 +126,34 @@ function love.light.newWorld() love.graphics.setColor(unpack(o.ambient)) love.graphics.setBlendMode("alpha") love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight()) - love.graphics.setColor(255,255,255) + love.graphics.setColor(255, 255, 255) love.graphics.setBlendMode("additive") for i = 1, #o.lights do - love.graphics.draw(o.lights[i].shine) - end - - love.graphics.setColor(255, 255, 255) - love.graphics.setBlendMode("alpha") - o.pixelShadow:clear() - math.randomseed(2) - love.graphics.setShader() - love.graphics.setCanvas(o.pixelShadow) - - for i = 1, #o.img do - if o.img[i].normal then - love.graphics.draw(o.img[i].normal, o.img[i].x - o.img[i].ox2, o.img[i].y - o.img[i].oy2) + if o.lights[i].visible then + love.graphics.draw(o.lights[i].shine) end end -- update pixel shadow + love.graphics.setColor(255, 255, 255) + love.graphics.setBlendMode("alpha") + + -- create normal map + if o.changed then + o.normalMap:clear() + love.graphics.setShader() + love.graphics.setCanvas(o.normalMap) + for i = 1, #o.img do + if o.img[i].normal then + 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) + else + love.graphics.setColor(127, 127, 255) + 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 + o.pixelShadow2:clear() love.graphics.setCanvas(o.pixelShadow2) love.graphics.setBlendMode("additive") @@ -145,17 +165,19 @@ function love.light.newWorld() o.ambient[3] / 255.0 } for i = 1, #o.lights do - local curLightColor = { - o.lights[i].red / 255.0, - o.lights[i].green / 255.0, - o.lights[i].blue / 255.0 - } - o.shader2:send("lightPosition", {o.lights[i].x, love.graphics.getHeight() - o.lights[i].y, 16}) - o.shader2:send("lightRange", {o.lights[i].range}) - o.shader2:send("lightColor", curLightColor) - o.shader2:send("lightAmbient", curLightAmbient) - o.shader2:send("lightSmooth", {o.lights[i].smooth}) - love.graphics.draw(o.pixelShadow) + if o.lights[i].visible then + local curLightColor = { + o.lights[i].red / 255.0, + o.lights[i].green / 255.0, + o.lights[i].blue / 255.0 + } + o.shader2:send("lightPosition", {o.lights[i].x, love.graphics.getHeight() - o.lights[i].y, 16}) + o.shader2:send("lightRange", {o.lights[i].range}) + 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 love.graphics.setShader() @@ -164,6 +186,18 @@ function love.light.newWorld() love.graphics.setBlendMode("alpha") love.graphics.draw(o.pixelShadow2) + -- create glow map + if o.changed then + o.glowMap:clear(0, 0, 0) + love.graphics.setCanvas(o.glowMap) + for i = 1, #o.img do + if o.img[i].glow then + love.graphics.draw(o.img[i].glow, o.img[i].x - o.img[i].ox2, o.img[i].y - o.img[i].oy2) + end + end + o.isGlowBlur = false + end + love.graphics.setShader() love.graphics.setBlendMode("alpha") love.graphics.setStencil() @@ -176,12 +210,15 @@ function love.light.newWorld() love.graphics.setColor(255, 255, 255) if o.blur then LOVE_LIGHT_LAST_BUFFER = love.graphics.getCanvas() + LOVE_LIGHT_BLURV:send("steps", o.blur) + LOVE_LIGHT_BLURH:send("steps", o.blur) love.graphics.setBlendMode("alpha") - love.graphics.setCanvas(o.shadow) + love.graphics.setCanvas(o.shadow2) love.graphics.setShader(LOVE_LIGHT_BLURV) love.graphics.draw(o.shadow) + love.graphics.setCanvas(o.shadow) love.graphics.setShader(LOVE_LIGHT_BLURH) - love.graphics.draw(o.shadow) + love.graphics.draw(o.shadow2) love.graphics.setCanvas(LOVE_LIGHT_LAST_BUFFER) love.graphics.setBlendMode("multiplicative") love.graphics.setShader() @@ -205,24 +242,37 @@ function love.light.newWorld() -- draw pixel shadow o.drawPixelShadow = function() love.graphics.setColor(255, 255, 255) - if o.blur and false then - LOVE_LIGHT_LAST_BUFFER = love.graphics.getCanvas() - love.graphics.setBlendMode("alpha") - love.graphics.setCanvas(o.pixelShadow) - love.graphics.setShader(LOVE_LIGHT_BLURV) - love.graphics.draw(o.pixelShadow) - love.graphics.setShader(LOVE_LIGHT_BLURH) - love.graphics.draw(o.pixelShadow) - love.graphics.setCanvas(LOVE_LIGHT_LAST_BUFFER) - love.graphics.setBlendMode("multiplicative") + love.graphics.setBlendMode("multiplicative") + love.graphics.setShader() + love.graphics.draw(o.pixelShadow) + love.graphics.setBlendMode("alpha") + end + -- draw glow + o.drawGlow = function() + love.graphics.setColor(255, 255, 255) + if o.isGlowBlur then + love.graphics.setBlendMode("additive") love.graphics.setShader() - love.graphics.draw(o.pixelShadow) + love.graphics.draw(o.glowMap) love.graphics.setBlendMode("alpha") else - love.graphics.setBlendMode("multiplicative") - love.graphics.setShader() - love.graphics.draw(o.pixelShadow) + LOVE_LIGHT_BLURV:send("steps", 1.0) + LOVE_LIGHT_BLURH:send("steps", 1.0) + LOVE_LIGHT_LAST_BUFFER = love.graphics.getCanvas() love.graphics.setBlendMode("alpha") + love.graphics.setCanvas(o.glowMap2) + love.graphics.setShader(LOVE_LIGHT_BLURV) + love.graphics.draw(o.glowMap) + love.graphics.setCanvas(o.glowMap) + love.graphics.setShader(LOVE_LIGHT_BLURH) + love.graphics.draw(o.glowMap2) + love.graphics.setCanvas(LOVE_LIGHT_LAST_BUFFER) + love.graphics.setBlendMode("additive") + love.graphics.setShader() + love.graphics.draw(o.glowMap) + love.graphics.setBlendMode("alpha") + + o.isGlowBlur = true end end -- new light @@ -234,12 +284,14 @@ function love.light.newWorld() -- clear lights o.clearLights = function() o.lights = {} + o.changed = true end -- clear objects o.clearObjects = function() o.poly = {} o.circle = {} o.img = {} + o.changed = true end -- set ambient color o.setAmbientColor = function(red, green, blue) @@ -294,6 +346,18 @@ function love.light.newWorld() o.getPoints = function(n) return unpack(o.poly[n].data) end + -- set light position + o.setLightPosition = function(n, x, y) + o.lights[n].setPosition(x, y) + end + -- set light x + o.setLightX = function(n, x) + o.lights[n].setX(x) + end + -- set light y + o.setLightY = function(n, y) + o.lights[n].setY(y) + end -- get light count o.getLightCount = function() return #o.lights @@ -326,6 +390,7 @@ function love.light.newLight(p, x, y, red, green, blue, range) o.glowSize = 0.1 o.glowStrength = 0.0 o.changed = true + o.visible = true -- set position o.setPosition = function(x, y) if x ~= o.x or y ~= o.y then @@ -334,6 +399,20 @@ function love.light.newLight(p, x, y, red, green, blue, range) o.changed = true end end + -- set x + o.setX = function(x) + if x ~= o.x then + o.x = x + o.changed = true + end + end + -- set y + o.setY = function(y) + if y ~= o.y then + o.y = y + o.changed = true + end + end -- set color o.setColor = function(red, green, blue) o.red = red @@ -549,6 +628,7 @@ function love.light.newImage(p, img, x, y, width, height, ox, oy) o.id = #p.img o.img = img o.normal = nil + o.glow = nil o.x = x o.y = y o.width = width or img:getWidth() @@ -557,6 +637,8 @@ function love.light.newImage(p, img, x, y, width, height, ox, oy) o.oy = o.height / 2.0 o.ox2 = ox or o.width / 2.0 o.oy2 = oy or o.height / 2.0 + o.imgWidth = img:getWidth() + o.imgHeight = img:getHeight() o.shine = true p.changed = true o.data = { @@ -611,9 +693,13 @@ function love.light.newImage(p, img, x, y, width, height, ox, oy) o.img = img end -- set normal - o.setNormal = function(normal) + o.setNormalMap = function(normal) o.normal = normal end + -- set normal + o.setGlowMap = function(glow) + o.glow = glow + end -- get type o.getType = function() return "image" diff --git a/main.lua b/main.lua index 5f4e3a3..5699501 100644 --- a/main.lua +++ b/main.lua @@ -24,11 +24,6 @@ function initScene() wall4.shape = love.physics.newRectangleShape(0, 0, 800, 10) wall4.fixture = love.physics.newFixture(wall4.body, wall4.shape) - myPoly1 = lightWorld.newPolygon(wall1.body:getWorldPoints(wall1.shape:getPoints())) - myPoly2 = lightWorld.newPolygon(wall2.body:getWorldPoints(wall2.shape:getPoints())) - myPoly3 = lightWorld.newPolygon(wall3.body:getWorldPoints(wall3.shape:getPoints())) - myPoly4 = lightWorld.newPolygon(wall4.body:getWorldPoints(wall4.shape:getPoints())) - phyCnt = 0 phyLight = {} phyBody = {} @@ -39,55 +34,63 @@ end function love.load() love.graphics.setBackgroundColor(0, 0, 0) love.graphics.setDefaultFilter("nearest", "nearest") - quadScreen = love.graphics.newQuad(0, 0, love.window.getWidth(), love.window.getHeight(), 32, 32) - imgFloor = love.graphics.newImage("floor.png") + + -- load image font + font = love.graphics.newImageFont("gfx/font.png", " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,!?-+/():;%&`'*#=[]\"") + love.graphics.setFont(font) + + -- set background + quadScreen = love.graphics.newQuad(0, 0, love.window.getWidth() + 32, love.window.getHeight() + 24, 32, 24) + imgFloor = love.graphics.newImage("gfx/floor.png") imgFloor:setWrap("repeat", "repeat") - circle = love.graphics.newImage "circle.png" - circle_normal = love.graphics.newImage "circle_normal.png" - cone = love.graphics.newImage "cone.png" - cone_normal = love.graphics.newImage "cone_normal.png" - chest = love.graphics.newImage "chest.png" - chest_normal = love.graphics.newImage "chest_normal.png" + -- load image examples + circle = love.graphics.newImage "gfx/circle.png" + circle_normal = love.graphics.newImage "gfx/circle_normal.png" + cone = love.graphics.newImage "gfx/cone.png" + cone_normal = love.graphics.newImage "gfx/cone_normal.png" + chest = love.graphics.newImage "gfx/chest.png" + chest_normal = love.graphics.newImage "gfx/chest_normal.png" + machine = love.graphics.newImage "gfx/machine.png" + machine_normal = love.graphics.newImage "gfx/machine_normal.png" + machine_glow = love.graphics.newImage "gfx/machine_glow.png" + machine2 = love.graphics.newImage "gfx/machine2.png" + machine2_normal = love.graphics.newImage "gfx/machine2_normal.png" + machine2_glow = love.graphics.newImage "gfx/machine2_glow.png" -- light world - lightRange = 400 + lightRange = 300 lightSmooth = 1.0 lightWorld = love.light.newWorld() lightWorld.setAmbientColor(15, 15, 31) mouseLight = lightWorld.newLight(0, 0, 255, 127, 63, lightRange) mouseLight.setGlowStrength(0.3) + mouseLight.setSmooth(lightSmooth) -- init physic world initScene() - helpOn = true + helpOn = false physicOn = false lightOn = true gravityOn = 1 - shadowBlurOn = true + shadowBlur = 2.0 bloomOn = true textureOn = true + + offsetX = 0.0 + offsetY = 0.0 + offsetOldX = 0.0 + offsetOldY = 0.0 + offsetChanged = false end function love.update(dt) - love.window.setTitle("FPS:" .. love.timer.getFPS()) + love.window.setTitle("Light vs. Shadow Engine (FPS:" .. love.timer.getFPS() .. ")") mouseLight.setPosition(love.mouse.getX(), love.mouse.getY()) mx = love.mouse.getX() my = love.mouse.getY() - for i = 1, phyCnt do - if phyBody[i]:isAwake() then - if phyLight[i].getType() == "polygon" then - phyLight[i].setPoints(phyBody[i]:getWorldPoints(phyShape[i]:getPoints())) - elseif phyLight[i].getType() == "circle" then - phyLight[i].setPosition(phyBody[i]:getX(), phyBody[i]:getY()) - elseif phyLight[i].getType() == "image" then - phyLight[i].setPosition(phyBody[i]:getX(), phyBody[i]:getY()) - end - end - end - if love.keyboard.isDown("w") then for i = 1, phyCnt do phyBody[i]:applyForce(0, -2000) @@ -108,17 +111,57 @@ function love.update(dt) end end + if love.keyboard.isDown("up") then + offsetY = offsetY + dt * 200 + elseif love.keyboard.isDown("down") then + offsetY = offsetY - dt * 200 + end + + if love.keyboard.isDown("left") then + offsetX = offsetX + dt * 200 + elseif love.keyboard.isDown("right") then + offsetX = offsetX - dt * 200 + end + + if offsetX ~= offsetOldX or offsetY ~= offsetOldY then + offsetChanged = true + for i = 2, lightWorld.getLightCount() do + lightWorld.setLightPosition(i, lightWorld.getLightX(i) + (offsetX - offsetOldX), lightWorld.getLightY(i) + (offsetY - offsetOldY)) + end + else + offsetChanged = false + end + + for i = 1, phyCnt do + if phyBody[i]:isAwake() or offsetChanged then + if offsetChanged then + phyBody[i]:setX(phyBody[i]:getX() + (offsetX - offsetOldX)) + phyBody[i]:setY(phyBody[i]:getY() + (offsetY - offsetOldY)) + end + if phyLight[i].getType() == "polygon" then + phyLight[i].setPoints(phyBody[i]:getWorldPoints(phyShape[i]:getPoints())) + elseif phyLight[i].getType() == "circle" then + phyLight[i].setPosition(phyBody[i]:getX(), phyBody[i]:getY()) + elseif phyLight[i].getType() == "image" then + phyLight[i].setPosition(phyBody[i]:getX(), phyBody[i]:getY()) + end + end + end + if physicOn then physicWorld:update(dt) end - -- update lightmap - if lightOn then - lightWorld.update(dt) - end + offsetOldX = offsetX + offsetOldY = offsetY end function love.draw() + -- update lightmap (don't need deltatime) + if lightOn then + lightWorld.update() + end + -- set shader buffer if bloomOn then love.postshader.setBuffer("render") @@ -127,7 +170,7 @@ function love.draw() love.graphics.setBlendMode("alpha") love.graphics.setColor(255, 255, 255) if textureOn then - love.graphics.draw(imgFloor, quadScreen) + love.graphics.draw(imgFloor, quadScreen, offsetX % 32 - 32, offsetY % 24 - 24) else love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight()) end @@ -151,76 +194,89 @@ function love.draw() end for i = 1, phyCnt do - love.graphics.setColor(191 + math.sin(i) * 63, 191 + math.cos(i) * 63, 191 + math.tan(i) * 63) if phyLight[i].getType() == "image" then + love.graphics.setColor(223 + math.sin(i) * 31, 223 + math.cos(i) * 31, 223 + math.tan(i) * 31) love.graphics.draw(phyLight[i].img, phyLight[i].x - phyLight[i].ox2, phyLight[i].y - phyLight[i].oy2) end end -- draw pixel shadow - lightWorld.drawPixelShadow() + if lightOn then + lightWorld.drawPixelShadow() + end + + -- draw glow + if lightOn then + lightWorld.drawGlow() + end -- draw help if helpOn then + love.graphics.setBlendMode("alpha") love.graphics.setColor(0, 0, 0, 191) - love.graphics.rectangle("fill", 8, 8, 210, 16 * 16) - love.graphics.setColor(0, 127, 255) - love.graphics.print("WASD: Move objects", 16, 16) + love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), 44) + love.graphics.rectangle("fill", 0, love.graphics.getHeight() - 68, 240, 68) + love.graphics.rectangle("fill", love.graphics.getWidth() - 244, love.graphics.getHeight() - 84, 244, 84) love.graphics.setColor(0, 255, 0) - love.graphics.print("F1: Help on", 16, 32) + love.graphics.print("F1: Help (on)", 4 + 152 * 0, 4) if physicOn then love.graphics.setColor(0, 255, 0) - love.graphics.print("F2: Physic on", 16, 48) + love.graphics.print("F2: Physic (on)", 4 + 152 * 1, 4) else love.graphics.setColor(255, 0, 0) - love.graphics.print("F2: Physic off", 16, 48) + love.graphics.print("F2: Physic (off)", 4 + 152 * 1, 4) end if lightOn then love.graphics.setColor(0, 255, 0) - love.graphics.print("F3: Light on", 16, 64) + love.graphics.print("F3: Light (on)", 4 + 152 * 2, 4) else love.graphics.setColor(255, 0, 0) - love.graphics.print("F3: Light off", 16, 64) + love.graphics.print("F3: Light (off)", 4 + 152 * 2, 4) end if gravityOn == 1.0 then love.graphics.setColor(0, 255, 0) - love.graphics.print("F4: Gravity on", 16, 80) + love.graphics.print("F4: Gravity (on)", 4 + 152 * 3, 4) else love.graphics.setColor(255, 0, 0) - love.graphics.print("F4: Gravity off", 16, 80) + love.graphics.print("F4: Gravity (off)", 4 + 152 * 3, 4) end - if shadowBlurOn then + if shadowBlur >= 1.0 then love.graphics.setColor(0, 255, 0) - love.graphics.print("F5: Shadowblur on", 16, 96) + love.graphics.print("F5: Shadowblur (" .. shadowBlur .. ")", 4 + 152 * 4, 4) else love.graphics.setColor(255, 0, 0) - love.graphics.print("F5: Shadowblur off", 16, 96) + love.graphics.print("F5: Shadowblur (off)", 4 + 152 * 4, 4) end if bloomOn then love.graphics.setColor(0, 255, 0) - love.graphics.print("F6: Bloom on", 16, 112) + love.graphics.print("F6: Bloom on", 4 + 152 * 0, 4 + 20 * 1) else love.graphics.setColor(255, 0, 0) - love.graphics.print("F6: Bloom off", 16, 112) + love.graphics.print("F6: Bloom off", 4 + 152 * 0, 4 + 20 * 1) end if textureOn then love.graphics.setColor(0, 255, 0) - love.graphics.print("F7: Texture on", 16, 128) + love.graphics.print("F7: Texture on", 4 + 152 * 1, 4 + 20 * 1) else love.graphics.setColor(255, 0, 0) - love.graphics.print("F7: Texture off", 16, 128) + love.graphics.print("F7: Texture off", 4 + 152 * 1, 4 + 20 * 1) end - love.graphics.setColor(255, 255, 255) - love.graphics.print("F11: Clear objects", 16, 144) - love.graphics.print("F12: Clear lights", 16, 160) - love.graphics.print("M.left: Add cube", 16, 176) - love.graphics.print("M.middle: Add light", 16, 192) - love.graphics.print("M.right: Add circle", 16, 208) - love.graphics.print("M.scroll: Change smooth", 16, 224) - love.graphics.print("1-3: Add image", 16, 240) + love.graphics.setColor(255, 0, 255) + 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.setColor(0, 127, 255) + love.graphics.print("WASD Keys: Move objects", 4, love.graphics.getHeight() - 20 * 3) + love.graphics.print("Arrow Keys: Move map", 4, love.graphics.getHeight() - 20 * 2) + love.graphics.print("1-5 Keys: Add image", 4, love.graphics.getHeight() - 20 * 1) + love.graphics.setColor(255, 127, 0) + love.graphics.print("M.left: Add cube", love.graphics.getWidth() - 240, love.graphics.getHeight() - 20 * 4) + love.graphics.print("M.middle: Add light", love.graphics.getWidth() - 240, love.graphics.getHeight() - 20 * 3) + love.graphics.print("M.right: Add circle", love.graphics.getWidth() - 240, love.graphics.getHeight() - 20 * 2) + love.graphics.print("M.scroll: Change smooth", love.graphics.getWidth() - 240, love.graphics.getHeight() - 20 * 1) + love.graphics.setColor(255, 127, 0) else - love.graphics.setColor(255, 255, 255, 63) - love.graphics.print("F1: Help", 8, 8) + love.graphics.setColor(255, 255, 255, 191) + love.graphics.print("F1: Help", 4, 4) end -- draw shader @@ -262,11 +318,15 @@ function love.mousepressed(x, y, c) phyFixture[phyCnt] = love.physics.newFixture(phyBody[phyCnt], phyShape[phyCnt]) phyFixture[phyCnt]:setRestitution(0.5) elseif c == "wu" then - lightSmooth = lightSmooth * 1.1 - mouseLight.setSmooth(lightSmooth) + if lightSmooth < 4.0 then + lightSmooth = lightSmooth * 1.1 + mouseLight.setSmooth(lightSmooth) + end elseif c == "wd" then - lightSmooth = lightSmooth / 1.1 - mouseLight.setSmooth(lightSmooth) + if lightSmooth > 0.5 then + lightSmooth = lightSmooth / 1.1 + mouseLight.setSmooth(lightSmooth) + end end end @@ -282,8 +342,11 @@ function love.keypressed(k, u) gravityOn = 1 - gravityOn physicWorld:setGravity(0, gravityOn * 9.81 * 64) elseif k == "f5" then - shadowBlurOn = not shadowBlurOn - lightWorld.setBlur(shadowBlurOn) + shadowBlur = math.max(1, shadowBlur * 2.0) + if shadowBlur > 8.0 then + shadowBlur = 0.0 + end + lightWorld.setBlur(shadowBlur) elseif k == "f6" then bloomOn = not bloomOn elseif k == "f7" then @@ -296,11 +359,12 @@ function love.keypressed(k, u) lightWorld.clearLights() mouseLight = lightWorld.newLight(0, 0, 255, 127, 63, lightRange) mouseLight.setGlowStrength(0.3) + mouseLight.setSmooth(lightSmooth) elseif k == "1" then -- add image phyCnt = phyCnt + 1 phyLight[phyCnt] = lightWorld.newImage(circle, mx, my) - phyLight[phyCnt].setNormal(circle_normal) + phyLight[phyCnt].setNormalMap(circle_normal) phyBody[phyCnt] = love.physics.newBody(physicWorld, mx, my, "dynamic") phyShape[phyCnt] = love.physics.newRectangleShape(0, 0, 32, 32) phyFixture[phyCnt] = love.physics.newFixture(phyBody[phyCnt], phyShape[phyCnt]) @@ -309,19 +373,39 @@ function love.keypressed(k, u) -- add image phyCnt = phyCnt + 1 phyLight[phyCnt] = lightWorld.newImage(cone, mx, my, 24, 12, 12, 28) - phyLight[phyCnt].setNormal(cone_normal) + phyLight[phyCnt].setNormalMap(cone_normal) phyBody[phyCnt] = love.physics.newBody(physicWorld, mx, my, "dynamic") - phyShape[phyCnt] = love.physics.newRectangleShape(0, 0, 25, 32) + phyShape[phyCnt] = love.physics.newRectangleShape(0, 0, 24, 32) phyFixture[phyCnt] = love.physics.newFixture(phyBody[phyCnt], phyShape[phyCnt]) phyFixture[phyCnt]:setRestitution(0.5) elseif k == "3" then -- add image phyCnt = phyCnt + 1 phyLight[phyCnt] = lightWorld.newImage(chest, mx, my, 32, 24, 16, 36) - phyLight[phyCnt].setNormal(chest_normal) + phyLight[phyCnt].setNormalMap(chest_normal) phyBody[phyCnt] = love.physics.newBody(physicWorld, mx, my, "dynamic") phyShape[phyCnt] = love.physics.newRectangleShape(0, 0, 32, 24) phyFixture[phyCnt] = love.physics.newFixture(phyBody[phyCnt], phyShape[phyCnt]) phyFixture[phyCnt]:setRestitution(0.5) + elseif k == "4" then + -- add image + phyCnt = phyCnt + 1 + phyLight[phyCnt] = lightWorld.newImage(machine, mx, my, 32, 24, 16, 36) + phyLight[phyCnt].setNormalMap(machine_normal) + phyLight[phyCnt].setGlowMap(machine_glow) + phyBody[phyCnt] = love.physics.newBody(physicWorld, mx, my, "dynamic") + phyShape[phyCnt] = love.physics.newRectangleShape(0, 0, 32, 24) + phyFixture[phyCnt] = love.physics.newFixture(phyBody[phyCnt], phyShape[phyCnt]) + phyFixture[phyCnt]:setRestitution(0.5) + elseif k == "5" then + -- add image + phyCnt = phyCnt + 1 + phyLight[phyCnt] = lightWorld.newImage(machine2, mx, my, 24, 12, 12, 28) + phyLight[phyCnt].setNormalMap(machine2_normal) + phyLight[phyCnt].setGlowMap(machine2_glow) + phyBody[phyCnt] = love.physics.newBody(physicWorld, mx, my, "dynamic") + phyShape[phyCnt] = love.physics.newRectangleShape(0, 0, 24, 32) + phyFixture[phyCnt] = love.physics.newFixture(phyBody[phyCnt], phyShape[phyCnt]) + phyFixture[phyCnt]:setRestitution(0.5) end end \ No newline at end of file diff --git a/postshader.lua b/postshader.lua index 0d8db31..e96e7ed 100644 --- a/postshader.lua +++ b/postshader.lua @@ -46,6 +46,8 @@ love.postshader.draw = function(shader) love.graphics.setBlendMode("alpha") elseif shader == "blur" then -- Blur Shader + LOVE_POSTSHADER_BLURV:send("steps", 2.0) + LOVE_POSTSHADER_BLURH:send("steps", 2.0) love.graphics.setCanvas(LOVE_POSTSHADER_BUFFER_BACK) love.graphics.setBlendMode("alpha") diff --git a/shader/blurh.glsl b/shader/blurh.glsl index 275c6bd..747f383 100644 --- a/shader/blurh.glsl +++ b/shader/blurh.glsl @@ -1,14 +1,13 @@ extern vec2 screen = vec2(800.0, 600.0); +extern float steps = 2.0; vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 pixel_coords) { vec2 pSize = vec2(1.0 / screen.x, 1.0 / screen.y); vec4 col = Texel(texture, texture_coords); - col = col + Texel(texture, vec2(texture_coords.x, texture_coords.y - pSize.y)); - col = col + Texel(texture, vec2(texture_coords.x, texture_coords.y + pSize.y)); - col = col + Texel(texture, vec2(texture_coords.x, texture_coords.y - pSize.y * 2)); - col = col + Texel(texture, vec2(texture_coords.x, texture_coords.y + pSize.y * 2)); - col = col + Texel(texture, vec2(texture_coords.x, texture_coords.y - pSize.y * 3)); - col = col + Texel(texture, vec2(texture_coords.x, texture_coords.y + pSize.y * 3)); - col = col / 7.0; + for(int i = 1; i <= steps; i++) { + col = col + Texel(texture, vec2(texture_coords.x, texture_coords.y - pSize.y * i)); + col = col + Texel(texture, vec2(texture_coords.x, texture_coords.y + pSize.y * i)); + } + col = col / (steps * 2.0 + 1.0); return vec4(col.r, col.g, col.b, 1.0); } \ No newline at end of file diff --git a/shader/blurv.glsl b/shader/blurv.glsl index 645acc4..f92b51a 100644 --- a/shader/blurv.glsl +++ b/shader/blurv.glsl @@ -1,14 +1,13 @@ extern vec2 screen = vec2(800.0, 600.0); +extern float steps = 2.0; vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 pixel_coords) { vec2 pSize = vec2(1.0 / screen.x, 1.0 / screen.y); vec4 col = Texel(texture, texture_coords); - col = col + Texel(texture, vec2(texture_coords.x - pSize.x, texture_coords.y)); - col = col + Texel(texture, vec2(texture_coords.x + pSize.x, texture_coords.y)); - col = col + Texel(texture, vec2(texture_coords.x - pSize.x * 2, texture_coords.y)); - col = col + Texel(texture, vec2(texture_coords.x + pSize.x * 2, texture_coords.y)); - col = col + Texel(texture, vec2(texture_coords.x - pSize.x * 3, texture_coords.y)); - col = col + Texel(texture, vec2(texture_coords.x + pSize.x * 3, texture_coords.y)); - col = col / 7.0; + for(int i = 1; i <= steps; i++) { + col = col + Texel(texture, vec2(texture_coords.x - pSize.x * i, texture_coords.y)); + col = col + Texel(texture, vec2(texture_coords.x + pSize.x * i, texture_coords.y)); + } + col = col / (steps * 2.0 + 1.0); return vec4(col.r, col.g, col.b, 1.0); } \ No newline at end of file diff --git a/shader/pixel_self_shadow.glsl b/shader/pixel_self_shadow.glsl index c430c1e..61d4603 100644 --- a/shader/pixel_self_shadow.glsl +++ b/shader/pixel_self_shadow.glsl @@ -14,8 +14,8 @@ vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 pixel_coords) { float att = 1 - distance / lightRange; - if(distance < lightRange && pixel.a > 0.0) { - return vec4(vec3(clamp(1 - dot(normal, lightDirection), 0.0, 1.0)) * lightColor * pow(att, lightSmooth) + lightAmbient, 1.0); + 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 {