Quick Links: Download Gideros Studio | Gideros Documentation | Gideros community chat | DONATE
2D lighting — Gideros Forum

2D lighting

rrraptorrrraptor Member
edited April 2020 in Code snippets
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 :D 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
image.png
499 x 299 - 51K
final2.png
1459 x 976 - 215K

Comments

Sign In or Register to comment.