From 98ee7b3f91dda6847865c2c1574aa0addd99d7c7 Mon Sep 17 00:00:00 2001 From: Tim Anema Date: Fri, 19 Dec 2014 20:33:58 -0500 Subject: [PATCH] added stencils --- lib/init.lua | 20 ++++++++------------ lib/light.lua | 20 ++++++++++++++++++++ lib/shaders/shine.glsl | 21 +++++++++++++-------- lib/util.lua | 4 ++-- 4 files changed, 43 insertions(+), 22 deletions(-) diff --git a/lib/init.lua b/lib/init.lua index adb1270..4dc8e62 100644 --- a/lib/init.lua +++ b/lib/init.lua @@ -78,6 +78,10 @@ function light_world:refreshScreenSize(w, h) self.refractionMap = love.graphics.newCanvas(w, h) self.reflectionMap = love.graphics.newCanvas(w, h) + for i = 1, #self.lights do + self.lights[i]:refresh() + end + self.post_shader:refreshScreenSize(w, h) end @@ -149,26 +153,18 @@ function light_world:drawShadows(l,t,w,h,s) for i = 1, #self.lights do local light = self.lights[i] if light:isVisible() then + light:updateShadowMap(l, t, s, self.bodies) self.shineShader:send('lightColor', {light.red / 255.0, light.green / 255.0, light.blue / 255.0}) self.shineShader:send("lightPosition", {(light.x + l/s) * s, (h/s - (light.y + t/s)) * s, (light.z * 10) / 255.0}) self.shineShader:send('lightRange', light.range * s) self.shineShader:send("lightSmooth", light.smooth) self.shineShader:send("lightGlow", {1.0 - light.glowSize, light.glowStrength}) self.shineShader:send('AmbientColor',{self.ambient[1] / 255, self.ambient[2] / 255, self.ambient[3] / 255, 0.2}) - util.process(self.shadowMap, { + util.drawCanvasToCanvas(light.shadowMap, self.shadowMap, { blendmode = 'additive', shader = self.shineShader, - istencil = function() - love.graphics.translate(l, t) - love.graphics.scale(s) - for k = 1, #self.bodies do - if self.bodies[k]:isInLightRange(light) and self.bodies[k]:isVisible() then - self.bodies[k]:drawShadow(light) - end - end - local angle = math.pi - light.angle / 2.0 - love.graphics.setColor(0, 0, 0) - love.graphics.arc("fill", light.x, light.y, light.range, light.direction - angle, light.direction + angle) + stencil = function() + love.graphics.circle("fill", light.x, light.y, light.range) end }) end diff --git a/lib/light.lua b/lib/light.lua index 85ee45d..b5e5614 100644 --- a/lib/light.lua +++ b/lib/light.lua @@ -1,5 +1,6 @@ local _PACKAGE = (...):match("^(.+)[%./][^%./]+") or "" local class = require(_PACKAGE.."/class") +local util = require(_PACKAGE.."/util") local light = class() @@ -18,6 +19,11 @@ function light:init(x, y, r, g, b, range) self.glowStrength = 0.0 self.visible = true self.is_on_screen = true + self:refresh(love.window.getWidth(), love.window.getHeight()) +end + +function light:refresh(w, h) + self.shadowMap = love.graphics.newCanvas(w, h) end -- set position @@ -117,4 +123,18 @@ function light:isVisible() return self.visible and self.is_on_screen end +function light:updateShadowMap(l, t, s, bodies) + self.shadowMap:clear() + util.drawto(self.shadowMap, l, t, s, function() + for k = 1, #bodies do + if bodies[k]:isInLightRange(self) and bodies[k]:isVisible() then + bodies[k]:drawShadow(self) + end + end + local angle = math.pi - self.angle / 2.0 + love.graphics.setColor(0, 0, 0) + love.graphics.arc("fill", self.x, self.y, self.range, self.direction - angle, self.direction + angle) + end) +end + return light diff --git a/lib/shaders/shine.glsl b/lib/shaders/shine.glsl index f070f19..cd3afbd 100644 --- a/lib/shaders/shine.glsl +++ b/lib/shaders/shine.glsl @@ -9,13 +9,18 @@ extern vec2 lightGlow = vec2(0.5, 0.5); //how brightly the light bulb part extern vec4 AmbientColor; //ambient RGBA -- alpha is intensity vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 pixel_coords) { - float dist = distance(lightPosition, vec3(pixel_coords, 1.0)); - //if the pixel is within this lights range - //calculater attenuation of light based on the distance - float att = clamp((1.0 - dist / lightRange) / lightSmooth, 0.0, 1.0); - // if not on the normal map draw attenuated shadows - vec3 Ambient = AmbientColor.rgb * AmbientColor.a; - vec3 pixel = lightColor * pow(att, lightSmooth) + pow(smoothstep(lightGlow.x, 1.0, att), lightSmooth) * lightGlow.y; - return vec4(Ambient + pixel, 1.0); + vec4 pixelColor = Texel(texture, texture_coords); + if(pixelColor.a > 0){ + return pixelColor; + } else { + float dist = distance(lightPosition, vec3(pixel_coords, 1.0)); + //if the pixel is within this lights range + //calculater attenuation of light based on the distance + float att = clamp((1.0 - dist / lightRange) / lightSmooth, 0.0, 1.0); + // if not on the normal map draw attenuated shadows + vec3 Ambient = AmbientColor.rgb * AmbientColor.a; + vec3 pixel = lightColor * pow(att, lightSmooth) + pow(smoothstep(lightGlow.x, 1.0, att), lightSmooth) * lightGlow.y; + return vec4(Ambient + pixel, 1.0); + } } diff --git a/lib/util.lua b/lib/util.lua index 54560f4..48b71da 100644 --- a/lib/util.lua +++ b/lib/util.lua @@ -15,7 +15,7 @@ function util.drawCanvasToCanvas(canvas, other_canvas, options) love.graphics.setShader(options["shader"]) end if options["stencil"] then - love.graphics.setInvertedStencil(options["stencil"]) + love.graphics.setStencil(options["stencil"]) end if options["istencil"] then love.graphics.setInvertedStencil(options["istencil"]) @@ -33,7 +33,7 @@ function util.drawCanvasToCanvas(canvas, other_canvas, options) love.graphics.setShader() end if options["stencil"] then - love.graphics.setInvertedStencil() + love.graphics.setStencil() end if options["istencil"] then love.graphics.setInvertedStencil()