AxisAngles
Prole
Posts: 12
Joined: Mon Feb 22, 2016 9:02 am

So I solved a little double integral to see how much light gets to a point, assuming you have a hemisphere of infinite size where light is coming in uniformly from all directions except the circular base, and a rectangle on a plane aligned with the base of that hemisphere. The result is pretty awesome.

demos are attached.

code:

Code: Select all

--local r=rectshadow.new([height],[posx],[posy],[sizex],[sizey])
--You can set r.h, r.px, r.py, r.sx, r.sy
--In order to delete a rectangle shadow, just do r:remove()

--What do you have to do to add this?
--For each button, make a new rectangle shadow with its pixel dimensions and height.
--	DO NOT MAKE A NEW ONE EACH FRAME, ONLY HAVE AS MAKE RECTANGLE OBJECTS AS YOU HAVE BUTTONS OR WHATEVER

--Each time you change the position of a rectangle button or frame or whatever, set r.px and  r.py to change the position of the shadow thing.

--Draw all of your stuff to a canvas, for example lolcanvas, instead of the screen.

--Then when you want to finalize your UI (probably the last step in your render process)
--	leave outcanvas to nil to have it draw directly to the screen

local setmt=setmetatable
local unpack=unpack

local getcanvas=love.graphics.getCanvas
local setcanvas=love.graphics.setCanvas
local draw=love.graphics.draw

local nrects=0
local rects={}
local htab={}
local ptab={}

local rect={
update=true;
i=0;
h=h or 0;
px=px or 0; py=py or 0;
sx=sx or 0; sy=sy or 0;
}

local meta={}
local funcs={}

function meta:__newindex(i,v)
rect[i]=v
rect.update=true
end
meta.__index=rect

local removed=false
function funcs:remove()
if not removed then
removed=true
local i=rect.i
rects[nrects].i=i
rects[i]=rects[nrects]
htab[i]=htab[nrects]
ptab[i]=ptab[nrects]
nrects=nrects-1
end
end

nrects=nrects+1
rects[nrects]=rect
htab[nrects]=h or 0
ptab[nrects]={
px or 0,py or 0,
(px or 0)+(sx or 0),
(py or 0)+(sy or 0)
}
rect.i=nrects

return setmt(funcs,meta)
end

extern number w;
extern number h;
//Must be sorted based on height from least to greatest
extern float height[64];
//Stores upper left corner in xy, lower right corner in zw
extern vec4 pos[64];
extern number n;

//idk lol.
float lightfromarea(in float x0,in float y0,in float x1,in float y1){
float sx0=inversesqrt(1+x0*x0);
float sy0=inversesqrt(1+y0*y0);
float sx1=inversesqrt(1+x1*x1);
float sy1=inversesqrt(1+y1*y1);
float atx0=atan(sx0*y0)-atan(sx0*y1);
float atx1=atan(sx1*y1)-atan(sx1*y0);
float aty0=atan(sy0*x0)-atan(sy0*x1);
float aty1=atan(sy1*x1)-atan(sy1*x0);
return 0.15915494*(sx0*x0*atx0+sx1*x1*atx1+sy0*y0*aty0+sy1*y1*aty1);
}

//As long as stuff doesn't overlap, it's exactly correct.
vec4 effect(vec4 colorin,Image texturein,vec2 posin, vec2 pixelin){
float px=w*posin.x;
float py=h*posin.y;

float besth=0;

for(int i=0;i<n;i++){
if(
besth<height[i]
&&pos[i].x<=px
&&pos[i].y<=py
&&px<=pos[i].z
&&py<=pos[i].w
){
besth=height[i];
}
}

float br=1;

for(int i=0;i<n;i++){
float dheight=height[i]-besth;
if(0<dheight){
br-=lightfromarea(
(pos[i].x-px)/dheight,
(pos[i].y-py)/dheight,
(pos[i].z-px)/dheight,
(pos[i].w-py)/dheight
);
}
}

return max(0,br)*Texel(texturein,posin);
}
]])

if 0<nrects then
for i=1,nrects do
local rect=rects[i]
if rect.update then
rect.update=false
htab[i]=rect.h
local p=ptab[i]
p[1]=rect.px
p[2]=rect.py
p[3]=rect.px+rect.sx
p[4]=rect.py+rect.sy
end
end
--Is there a less shitty way of doing this?
--I'd like to do :send("height[5]",x)
end

local w,h=incanvas:getDimensions()

local lastcanvas=getcanvas()

setcanvas(outcanvas)
draw(incanvas)

setcanvas(lastcanvas)
end
end
Attachments

ivan
Party member
Posts: 1455
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Runs very slow on my old 64-bit Core2 Duo laptop.
Looks pretty good though I think this sort of effect
could be achieved using a couple of transparent textures and setColor.
Here my ugly 36-line version without the shaders and tweening.
Attachments
colorpicker.love

AxisAngles
Prole
Posts: 12
Joined: Mon Feb 22, 2016 9:02 am

Okay yeah, it is a bit ridiculous to be running approximately 512 atans and 256 inversesqrts per pixel per frame.

Of course, it could be worse. I could be integrating over the pixel

I'll work on making it faster.

Nuthen224
Citizen
Posts: 50
Joined: Sun Jul 28, 2013 9:40 pm

It looks very cool!

DanielPower
Citizen
Posts: 50
Joined: Wed Apr 29, 2015 5:28 pm

It looks cool, but is extremely inefficient. Runs at about 1 frame every 5 seconds with integrated graphics on a core i7. Whether or not it runs at an acceptable frame rate on dedicated graphics, I cannot say. But to put such a strain on the hardware for a simple effect is wasteful.

Will test on my gaming rig later.

zorg
Party member
Posts: 2620
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

It does run decently on my rig, GTX 960.
Me and my stuff True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.

AxisAngles
Prole
Posts: 12
Joined: Mon Feb 22, 2016 9:02 am

Just realized it uses 70% of my GTX1080Ti running at 240fps. I had no idea.

### Who is online

Users browsing this forum: Exabot [Bot] and 6 guests