2D lighting — Gideros Forum

#### Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

# 2D lighting

Member
edited April 2020
Here I posted a video of 2d lighting effect. I was using a simple ray casting algorithm. But it gives incorrect result depending on amount of rays.

So, I thought that is would be a good idea to use GPU So I created a simple shader that can calculate the shadow mask for a given object (using ray marching algorithm).
Pros:
• Pretty accurate result
• Good performance (? not sure)
Cons:
• It is ONLY visual effect
• 2 render targets (1 for final light mask, another for a shadow).
• This version works only with AABB's
Code is here: https://github.com/MultiPain/Gideros_examples/tree/master/2d_light
Smooth version: http://forum.giderosmobile.com/discussion/comment/62655/#Comment_62655

The algorithm is very simple:

Code:
 ```function Light:update() local x,y = self:getPosition()   -- self.world - Bump world local list, len = self.world:queryRect(x,y,self.r*2,self.r*2)   if len > 0 then LightShader:setConstant("fResolution", Shader.CFLOAT2, 1, {self.r*2,self.r*2}) -- draw light mask self.canvas:clear(0,0) self.canvas:draw(self.lightSourceImg)   for i,rect in ipairs(list) do local bx,by = rect:getPosition() local bw,bh = rect:getSize() local lx,ly = self:globalToLocal(bx,by) -- let shader calculate shadow LightShader:setConstant("rectPos", Shader.CFLOAT2, 1, {lx,ly}) LightShader:setConstant("rectSize", Shader.CFLOAT2, 1, {bw,bh}) -- draw this shadow to light mask self.canvas:draw(self.shadow) end end end```
In order to check if object is visible by light you can simply use a ray casting method
See this video from 00:18 to 01:02. Its actualy not that hard.

Ray vs AABB function:
 ```--rx1,ry1,rx2,ry2 ray start position and end position -- bx,by - position of top left corner -- bw,bh - size -- return intersection point or nil if there is no intersection local function rayVSaabb(rx1,ry1,rx2,ry2, bx,by,bw,bh) local nx = rx2-rx1 local ny = ry2-ry1   local rix = 1 / nx local riy = 1 / ny   local tx1 = (bx - rx1) * rix local tx2 = (bx + bw - rx1) * rix   local tmin = mmin(tx1, tx2) local tmax = mmax(tx1, tx2)   local ty1 = (by - ry1) * riy local ty2 = (by + bh - ry1) * riy   tmin = mmax(tmin, mmin(ty1, ty2)) tmax = mmin(tmax, mmax(ty1, ty2))   if (tmin > tmax) then return nil end   if (tmin < 0) then local px = rx1 + nx * tmax local py = ry1 + ny * tmax return px, py end local px = rx1 + nx * tmin local py = ry1 + ny * tmin return px, py end```

• Member
using clipper library is still an interesting approach as it would be completely accurate and also one can easily have heights for the objects. the method would be to calculate all shadow polygons separately and then take their union.
• Member
edited April 2020
@keszegh you said that its slow, so I did not even tried
• Member
well, i don't remember exactly, it may have been the older lua version of the clipper library. although i cannot find my old codes... now i've found them and apparently it was made back in 2011 using flash, before i've found gideros. later in gideros i started to play around with the clipper library but never get to reproduce a working demo. so i expect gideros+native clipper could be fast enough.
• Member
edited April 2020

Code is here: https://github.com/MultiPain/Gideros_examples/tree/master/2D_SmoothLight

Video:

+1 -1 (+4 / -0 )Share on Facebook
• Maintainer
This should be added to the demos in the distro.
Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
https://deluxepixel.com
• Member
for me it did not do anything, i just see the objects in the dark.
• Member
@keszegh have you tried right clicking on the screen?
my growING GIDEROS github repositories: https://github.com/mokalux?tab=repositories
• Member
thanks for the tip, i just tried left-clicking. right-click works.
btw if i go near an object then it looks strange, see attached image.
• Member
@keszegh it is inside or exactly on the edge.

There is a problems btw Shader works correctly only with POT (Power Of Two) radius. Maybe @hgy29 can tell me why?))
sh.png 54.6K
• Maintainer
rrraptor said:

There is a problems btw Shader works correctly only with POT (Power Of Two) radius. Maybe @hgy29 can tell me why?))

Sure!
The radius defines the size of your RT which is used as a source texture for a Bitmap. Gideros internally makes sure that all textures are POT (because some devices still don't handle NPOT textures correctly, even now!), but the shader is unaware of that and expects the texcoords to go from 0 to 1 on each axis while they no longer do!

The solution is to correct the texcoords in the vertex shader. Gideros can supply the actual texture extent in a uniform, so:
a) In the uniforms definiton in lua, add:
 ` {name="vTexInfo",type=Shader.CFLOAT4,sys=Shader.SYS_TEXTUREINFO,vertex=true},`
 `uniform mediump vec4 vTexInfo;`
and
 ` fTexCoord=vTexCoord/vTexInfo.xy;`
+1 -1 (+2 / -0 )Share on Facebook
• Member
edited April 2020

Using the same approach but not only AABB, i can handle any type of object, even polygons, and rotating polygons, all coordinates tooks from level file made in Tiled

But Im using for each shadow a new Sprite, with edge smoothing using shader.

Likes: SinisterSoft

vk.com/yan_alex
+1 -1 (+1 / -0 )Share on Facebook