Page 1 of 1

Trouble With Shadows / Raycasting with Physics and Shaders

Posted: Mon Sep 03, 2018 9:59 pm
by harrison
I am trying to set up a extremely basic shadow system using physics (for raycasting shapes) and shaders (for the shadows). This is what I have so far but I am stuck on a couple things.

1. How do I get my array of shadow/bright from lua into the shader? I have heard of Shader:send() but it says it only supports vectors of up to 4 variables. I suppose I could try to send a single extremely long number (like 01001111000...) instead of an array, but that sounds very inefficient.

2. I am getting a strange error with physics (and googling it doesn't help):

Code: Select all

Error

main.lua:33: Box2D assertion failed: r.LengthSquared() > 0.0f


Traceback

[C]: in function 'rayCast'
main.lua:33: in function 'draw'
[C]: in function 'xpcall'
main.lua (should be able to run on its own but definitely has some bugs)

Code: Select all


function love.load()
	love.physics.setMeter(25)
	world = love.physics.newWorld(0,0,true)
	objects = {}
	objects.obstacle = {}
	objects.obstacle.body = love.physics.newBody(world, 200, 200)
	objects.obstacle.shape = love.physics.newRectangleShape(50, 50)
	objects.obstacle.fixture = love.physics.newFixture(objects.obstacle.body, objects.obstacle.shape)
	objects.lightSource = {}
	objects.lightSource.body = love.physics.newBody(world, 350, 250)
	objects.lightSource.shape = love.physics.newCircleShape(10)
	objects.lightSource.fixture = love.physics.newFixture(objects.obstacle.body, objects.obstacle.shape)

	myShader = love.graphics.newShader[[
		vec4 effect( vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords ){
			vec4 pixel = Texel(texture, texture_coords);
			if (true){ 
				return vec4(pixel.r, pixel.g, pixel.b, 1);
			}
			else {
				return vec4(pixel.r, pixel.g, pixel.b,0);
			}
		}
	]]
end

function love.draw()
	--perform raytracing for each pixel
	isPixelLit = {}
	for y=0, love.graphics.getHeight() do
		for x=0, love.graphics.getWidth() do
			collision = false
			world:rayCast(objects.lightSource.body:getX(), objects.lightSource.body:getY(), x, y, worldRayCastCallback)
			if(collision) then
				isPixelLit[#isPixelLit+1] = 0
			else
				isPixelLit[#isPixelLit+1] = 1
			end
		end
	end
	
	--send the pixel table to the shader
	--not sure how to do this...
	
	love.graphics.setShader(myShader) --draw something here

	love.graphics.setColor(1, 0, 0)
	love.graphics.circle("fill", objects.lightSource.body:getX(), objects.lightSource.body:getY(), objects.lightSource.shape:getRadius())
	love.graphics.setColor(0, 1, 0)
	love.graphics.polygon("fill", objects.obstacle.body:getWorldPoints(objects.obstacle.shape:getPoints()))
  
	love.graphics.setShader() --disable the shader for the remaining objects to draw
end

function love.update(dt)
	world:update(dt)
end

function worldRayCastCallback()
	collision = true
	
	return 1
end
I was hoping somebody could help me out with these two issues.
Also, is this a terrible way to add shadows to my game? I feel like there is probably a much better/cleaner way of doing this.

Re: Trouble With Shadows / Raycasting with Physics and Shaders

Posted: Tue Sep 04, 2018 8:52 am
by NotARaptor
Can't help you with point 2, but for point 1, store the array data in a texture - it can be 1 pixel high and n pixels wide, send that to the shader with shader:send. The shader can then read it using the Texel() function.

Re: Trouble With Shadows / Raycasting with Physics and Shaders

Posted: Wed Sep 05, 2018 12:07 pm
by Nixola
For point 2, sounds like you're casting a ray from a point to the same point? Maybe you should add a check against that