GLBasic forum

Codesnippets => Code Snippets => Topic started by: Albert on 2011-Sep-21

Title: Ray of lights
Post by: Albert on 2011-Sep-21
Hi!

I'm experimenting with ray of lights. You can download the fully commented project from here or you can found in the attachment.
http://dl.dropbox.com/u/292449/lightrays.zip (http://dl.dropbox.com/u/292449/lightrays.zip)




[attachment deleted by admin]
Title: Re: Ray of lights
Post by: Albert on 2011-Sep-21
Here is the code:

Code: (glbasic) [Select]
// --------------------------------- //
// Project: Shadow
// Start: September 21, 2011
// IDE Version: 9.006

//written by Bence Dobos, 2011

SETCURRENTDIR("Media") // seperate media and binaries?
SYSTEMPOINTER TRUE

LOADFONT "smalfont2.png",1
SETFONT 1

//card
GLOBAL maxcard = 4
GLOBAL spr_card = 0
GLOBAL card_w, card_h
GLOBAL map[]

//player
GLOBAL spr_player = 10
GLOBAL plr_x=1000, plr_y=1050

//blob
GLOBAL spr_blob = 20 //first blob

//screen
GLOBAL scr_w, scr_h
GLOBAL scr_wf, scr_hf //half

//gui object
GLOBAL gui AS UIState

//all the variables you can change using the GUI
GLOBAL r=255,g=255,b=255
GLOBAL alpha=150
GLOBAL alpha2=20
GLOBAL LightSource=TRUE
GLOBAL iter=2 //keep it low for slower machines
GLOBAL raystep=1
GLOBAL scale=10
GLOBAL nblob=0
GLOBAL showGUI=FALSE
GLOBAL lightrays=TRUE
GLOBAL controlsheme=0 //0 keyboard, 1 mouse
//init
GETSCREENSIZE scr_w, scr_h
scr_wf=scr_w/2
scr_hf=scr_h/2

//creating random map, for a nice background
DIM map[10][10]
FOR x=0 TO 9
FOR y=0 TO 9
map[x][y]=RND(maxcard-1)
NEXT
NEXT

//loadind cards
//NOTE: all the graphics from Draco by Puli Games (c)
FOR i=0 TO maxcard-1
LOADSPRITE "card"+i+".png", spr_card+i
NEXT
GETSPRITESIZE spr_card, card_w, card_h
DEBUG card_w+"\n"
DEBUG card_h+"\n"
IF card_w=0 OR card_h=0
DEBUG "card not loaded!\n"
END
ENDIF


//loading player
//NOTE: all the graphics from Draco by Puli Games (c)
LOADSPRITE "player0.png", spr_player

//loading blobs
LOADSPRITE "blob.png", spr_blob
LOADSPRITE "blobinv.png", spr_blob+1
LOADSPRITE "blobtrans.png", spr_blob+2

//creating screens
CREATESCREEN 5, 250, scr_w, scr_h
CREATESCREEN 6, 251, scr_w, scr_h

//gameloop
WHILE KEY(1)=0
//prepare the gui, and catch all the interesting keyboard and mouse events
gui.prepare()

//render the background
ALPHAMODE 0
rendermap()

IF lightrays
//render ray of lights
USESCREEN 5
CLEARSCREEN

//initial light source
ALPHAMODE (alpha-100)/100.0
PolySprite( spr_blob+nblob, scr_wf-plr_x+1000, scr_hf-plr_y+1050, scale/10.0, scale/10.0, RGB(r,g,b),0.5,0.5,0.0)

//overlapping player sprite rendered in black
ALPHAMODE 0
PolySprite( spr_player, scr_wf+plr_x-1000, scr_hf+plr_y-1050, 0.5, 0.5, RGB(0,0,0),0.5,0.5,0.0)

//now we have the light source with some covering black image in it (the player)

//this is the trick
//copying the same image to itself, but zooming it bigger every time
//we have to use two screens, and wsitching them.
//IF you using only one AND copying it on itself, you get unexpected result
LOCAL m
LOCAL n
FOR i=1 TO (iter)*2 //start from odd (1), end to even (3,5,7,etc.)!
m=MOD(i,2) //this is the destination screen
n=1-m //this is the source screen
USESCREEN 5+m //we want draw into the destination screen
m=250+m
n=250+n
//copy the whole source screen
DRAWSPRITE n, 0, 0
//then draw again the source screen but zoom it and blend
ALPHAMODE (alpha-100)/100.0
PolySprite( n, scr_wf, scr_hf, 1+(i)/(raystep+1), 1+(i)/(raystep+1), RGB(r,g,b),0.5,0.5,0.0)
NEXT

//back to normal screen
USESCREEN -1

IF LightSource
//a strong additional light to the background, only for fun
ALPHAMODE (190-100)/100.0
PolySprite( spr_blob, scr_wf-plr_x+1000, scr_hf-plr_y+1050, scale/10.0, scale/10.0, RGB(r,g,b),0.5,0.5,0.0)
ENDIF

//blend the raylight screen
ALPHAMODE (alpha2-100)/100.0
PolySprite( 250, scr_wf, scr_hf, 1, 1, RGB(r,g,b),0.5,0.5,0.0)

//player
ALPHAMODE 0
PolySprite( spr_player, scr_wf+plr_x-1000, scr_hf+plr_y-1050, 0.5, 0.5, RGB(255,255,255),0.5,0.5,0.0)

ELSE
//player
PolySprite( spr_player, scr_wf, scr_hf, 0.5, 0.5, RGB(255,255,255),0.5,0.5,0.0)
//blend
ALPHAMODE (alpha-100)/100.0
PolySprite( spr_blob+nblob, scr_wf, scr_hf, scale/10.0, scale/10.0, RGB(r,g,b),0.5,0.5,0.0)
ENDIF

//draw GUI
ALPHAMODE 0
LOCAL color
IF showGUI
IF nblob=0
color=RGB(128,255,128)
ELSE
color=RGB(64,64,64)
ENDIF
IF button(1, 5, 5, 110, 20, color, "blob.png")
nblob=0
ENDIF
IF nblob=1
color=RGB(128,255,128)
ELSE
color=RGB(64,64,64)
ENDIF
IF button(2, 115, 5, 110, 20, color, "blobinv.png")
nblob=1
ENDIF
IF nblob=2
color=RGB(128,255,128)
ELSE
color=RGB(64,64,64)
ENDIF
IF button(3, 225, 5, 110, 20, color, "blobtrans.png")
nblob=2
ENDIF
sliderH(5, 5, 30, 400, 200, alpha)
PRINT FORMAT$(2,1,alpha-100)+"% alpha", 450,30, TRUE
IF button(9, 420, 30, 20, 20, RGB(255,255,0), "0") THEN alpha=100
sliderH(6, 5, 50, 400, 400, scale)
PRINT FORMAT$(2,1,scale/10.0)+"% scale", 420,50, TRUE
sliderH(10, 5, 70, 255, 255, r)
PRINT "R "+r, 270,70, TRUE
sliderH(11, 5, 90, 255, 255, g)
PRINT "G "+g, 270,90, TRUE
sliderH(12, 5, 110, 255, 255, b)
PRINT "B "+b, 270,110, TRUE
IF lightrays
color=RGB(128,255,128)
ELSE
color=RGB(64,64,64)
ENDIF
IF button(13, 5, 130, 110, 18, color, "Light Rays")
lightrays = 1-lightrays
ENDIF
IF LightSource
color=RGB(128,255,128)
ELSE
color=RGB(64,64,64)
ENDIF
IF button(14, 150, 130, 110, 18, color, "Light Source")
LightSource = 1-LightSource
ENDIF
sliderH(15, 5, 150, 200, 20, iter)
iter = INTEGER(iter)
PRINT (iter)*2+" iterations", 215,150, TRUE
sliderH(16, 5, 170, 200, 20, raystep)
raystep = INTEGER(raystep)
PRINT (raystep+1)+" ray step", 215,170, TRUE
sliderH(17, 5, 190, 400, 200, alpha2)
PRINT FORMAT$(2,1,alpha2-100)+"% alpha2", 450,190, TRUE
IF button(18, 420, 190, 20, 20, RGB(255,255,0), "0") THEN alpha2=100
IF controlsheme=0
IF button(20, 5, 220, 120, 20, RGB(255,100,100), "Keyboard") THEN controlsheme=1
ELSE
IF button(20, 5, 220, 120, 20, RGB(255,100,100), "Mouse") THEN controlsheme=0
ENDIF
ENDIF
//draw buttons to bottom. Presets
IF button(50, 5, scr_h-30, 50, 20, RGB(0,255,0), "GUI") THEN showGUI=NOT showGUI
IF button(51, 105, scr_h-30, 90, 20, RGB(255,255,0), "Light")
nblob=0
alpha=145
r=255
g=255
b=255
scale=20
alpha2=200
ENDIF
IF button(52, 205, scr_h-30, 90, 20, RGB(255,255,0), "Sun")
nblob=1
alpha=145
r=255
g=240
b=180
scale=20
alpha2=200
ENDIF
IF button(53, 305, scr_h-30, 90, 20, RGB(255,255,0), "Light+dark")
nblob=1
alpha=5
r=255
g=255
b=255
iter=5
scale=40
alpha2=200
ENDIF
IF button(54, 405, scr_h-30, 90, 20, RGB(255,255,0), "Laser1")
nblob=2
alpha=200
r=255
g=255
b=255
iter=5
scale=70
alpha2=0
ENDIF
IF button(55, 505, scr_h-30, 90, 20, RGB(255,255,0), "Laser2")
nblob=2
alpha=200
r=255
g=255
b=255
iter=5
scale=70
alpha2=200
ENDIF

//move player
IF controlsheme=0
IF gui.up THEN DEC plr_y
IF gui.down THEN INC plr_y
IF gui.left THEN DEC plr_x
IF gui.right THEN INC plr_x
ELSE
plr_x = gui.mousex + 1000 - scr_wf
plr_y = gui.mousey + 1050 - scr_hf
ENDIF
SHOWSCREEN

gui.finish()
WEND

//simplified render function from Draco
FUNCTION rendermap:
LOCAL x=plr_x-scr_wf, y=plr_y-scr_hf
LOCAL mx%=x/card_w, my%=y/card_h
LOCAL cx, cy
cx=mx*card_w-x
cy=my*card_h-y
WHILE my<10 AND cy<scr_h
IF (mx>=0 AND my>=0 AND mx<10 AND my<10)
DRAWSPRITE map[mx][my], cx, cy
ENDIF
INC mx, 1
INC cx, card_w
IF mx>scr_w
mx=x/card_w
cx=mx*card_w-x
INC my, 1
INC cy, card_h
ENDIF
WEND
ENDFUNCTION

//made for blobmondter by Bence Dobos

//Draw and colorize a sprite. You can set the handle point, rotation, scale and color of the sprite
//Written by Bence Dobos
//spr - the ID of the sprite
//scalex, scaley - the ratio of the sprite scale [0.0-inf]
//color - 0xffffff is the normal color
//xc,yc - the ratio of the handle point of the sprite [0.0-1.0], this point is used to draw the sprite, rotate and scale. 0,0 is the top-left point, 0.5,0.5 is the center point
//rot - rotation of the sprite [0-360]
//w,h - width, height of the sprite in pixel, if not specified it's determined automatically
FUNCTION PolySprite: spr, x, y, scalex, scaley, color=0xffffff, xc=0.0, yc=0.0, rot=0, w=-1, h=-1
IF w=-1
GETSPRITESIZE spr, w, h
ENDIF
LOCAL w2=w*scalex
LOCAL h2=h*scaley
LOCAL xcenter=x+xc*w2
LOCAL ycenter=y+yc*h2
LOCAL xr1=-xc*w2
LOCAL yr1=-yc*h2
LOCAL xr2=(1.0-xc)*w2
LOCAL yr2=-yc*h2
LOCAL xr3=(1.0-xc)*w2
LOCAL yr3=(1.0-yc)*h2
LOCAL xr4=-xc*w2
LOCAL yr4=(1.0-yc)*h2

LOCAL x1, y1, x2, y2
LOCAL x3, y3, x4, y4
IF rot<>0
LOCAL sp = SIN(rot)
LOCAL cp = COS(rot)
x1 = xr1*cp-yr1*sp+x
y1 = xr1*sp+yr1*cp+y
x2 = xr2*cp-yr2*sp+x
y2 = xr2*sp+yr2*cp+y
x3 = xr3*cp-yr3*sp+x
y3 = xr3*sp+yr3*cp+y
x4 = xr4*cp-yr4*sp+x
y4 = xr4*sp+yr4*cp+y
ELSE
x1=xr1+x
y1=yr1+y
x2=xr2+x
y2=yr2+y
x3=xr3+x
y3=yr3+y
x4=xr4+x
y4=yr4+y
ENDIF

STARTPOLY spr
  POLYVECTOR   x1, y1,  0,  0, color
  POLYVECTOR   x2, y2,  w,  0, color
  POLYVECTOR   x3, y3,  w,  h, color
  POLYVECTOR   x4, y4,  0,  h, color
ENDPOLY
ENDFUNCTION

About IMGUI: http://www.glbasic.com/forum/index.php?topic=5431.0
Title: Re: Ray of lights
Post by: Ian Price on 2011-Sep-21
That's really cool. Nice one =D
Title: Re: Ray of lights
Post by: Albert on 2011-Sep-21
Changed the program a bit to adapt to the Galaxy S 800x480 resolution. Running fast on android.
However IMGUI not so good with touchscreen.
Title: Re: Ray of lights
Post by: bigsofty on 2011-Sep-21
It's lovely affect, had fun just messing around with the params! ;)
Title: Re: Ray of lights
Post by: Nathan on 2011-Sep-21
I agree with the above, superb work!
Title: Re: Ray of lights
Post by: Marmor on 2011-Sep-21
thx a lot ! great work
Title: Re: Ray of lights
Post by: Wampus on 2011-Sep-21
Very cool
Title: Re: Ray of lights
Post by: Albert on 2011-Sep-22
You can create a whole bunch of light sources if you want, this not affect the speed, only the number of iteration and the screen's resolution.

So change the rows after the comment //initial light source

Code: (glbasic) [Select]
//initial light source
ALPHAMODE (alpha-100)/100.0
//PolySprite( spr_blob+nblob, scr_wf-plr_x+1000, scr_hf-plr_y+1050, scale/10.0, scale/10.0, RGB(r,g,b),0.5,0.5,0.0)
DRAWRECT scr_wf-plr_x+1000 - 100, scr_hf-plr_y+1050 - 150, 50,50, RGB(255, 255, 255)
DRAWRECT scr_wf-plr_x+1000 - 50, scr_hf-plr_y+1050 + 100, 200,20, RGB(255, 255, 255)
DRAWRECT scr_wf-plr_x+1000 - 10, scr_hf-plr_y+1050 - 100, 30, 30, RGB(100, 100, 255)
DRAWRECT scr_wf-plr_x+1000 + 100, scr_hf-plr_y+1050 + 50, 50,50, RGB(255, 0, 255)
DRAWRECT scr_wf-plr_x+1000 + 10, scr_hf-plr_y+1050 + 100, 200,50, RGB(255, 255, 255)
DRAWRECT scr_wf-plr_x+1000 + 0, scr_hf-plr_y+1050 - 50, 20, 20, RGB(100, 100, 255)

This code draw some rectangles:
(http://dl.dropbox.com/u/292449/img/lightrays13.png)

And with the ray light effect:
(http://dl.dropbox.com/u/292449/img/lightrays14.png)

Oh this is very rough, even if you push up the iterations and the ray step parameters. It's cool if you use soft shapes, but very jaggy with theese rectangles.
Would be nice some sort of blur. It's easy to implement, just draw the screen to a temporary buffer, but scale it down (lower the resolution) then scale it back and draw.
To achieve this we need a new screen:
//creating screens
CREATESCREEN 5, 250, scr_w, scr_h
CREATESCREEN 6, 251, scr_w, scr_h
CREATESCREEN 7, 252, scr_wf, scr_hf

and change the iteration:
      //this is the trick
      //copying the same image to itself, but zooming it bigger every time
      //we have to use two screens, and wsitching them.
      //IF you using only one AND copying it on itself, you get unexpected result
      LOCAL o
      LOCAL m
      LOCAL n
      FOR i=1 TO (iter)*2 //start from odd (1), end to even (3,5,7,etc.)!
         o=MOD(i,2)   //this is the destination screen
         n=1-o      //this is the source screen
         USESCREEN 5+o   //we want draw into the destination screen
         m=250+o
         n=250+n
         //copy the whole source screen
         DRAWSPRITE n, 0, 0
         //blur
         USESCREEN 7
         STRETCHSPRITE n, 0, 0, scr_wf/i, scr_hf/i      

         //then draw again the source screen but zoom it and blend
         USESCREEN 5+o         
         ALPHAMODE (alpha-100)/100.0
         //PolySprite( n, scr_wf, scr_hf, 1+(i)/(raystep+1), 1+(i)/(raystep+1), RGB(r,g,b),0.5,0.5,0.0)
         PolySprite( 252, scr_wf, scr_hf, (1+(i)/(raystep+1))*i*2, (1+(i)/(raystep+1))*i*2, RGB(r,g,b),0.5,0.5,0.0, scr_wf/i, scr_hf/i)
      NEXT

Also change the draw order, draw the player before the completed ray light sprite.

(http://dl.dropbox.com/u/292449/img/lightrays12.png)
Title: Re: Ray of lights
Post by: Schranz0r on 2011-Sep-23
WOW... nothing more to say!
Title: Re: Ray of lights
Post by: mentalthink on 2011-Sep-27
Awesome!!!, only a question, I can implement part of your code in my developement, I think this effect, can be abosulty brutal in my game.

Kinds Regards,
Iván J.

PS: I test whit animates Sprite and it´s abosulutely a beatifull for look.
Title: Re: Ray of lights
Post by: Albert on 2011-Sep-28
Iván of yourse you can! I would love to see what you guys can do with this effect.
I experimented with bloom effect, and I tried to add some very simple shader, but it's really buggy. Are you interested? It would be nice if somebody could fix my shader...
Title: Re: Ray of lights
Post by: mentalthink on 2011-Sep-28
Quote
I experimented with bloom effect, and I tried to add some very simple shader, but it's really buggy. Are you interested? It would be nice if somebody could fix my shader...

 :nw: :nw: :nw: , We are speaking in 3D?¿, Sure my friend, I goes crazy for have a 3d Bloom effect, this can be absolutelly brutal.

If you can do, and not it´s too much disturb, for me will be great have a set of shaders.... or only the bloom FX

Thanks again, for your code, and  for permet the use in my game....

Kinds Regards,
Iván J.
Title: Re: Ray of lights
Post by: Albert on 2011-Sep-28
2D
Title: Re: Ray of lights
Post by: mentalthink on 2011-Sep-28
Ok, it´s perfect too!!!, thanks again.
Title: Re: Ray of lights
Post by: Albert on 2011-Sep-28
For bloom we have to do some things.
First, we have to copy the whole screen and apply a tolerance (only keep the bright spots).
Second, we want to blur this copied screen.
Finally we can copy this screen over our original screen.
I couldn't found a fast algorithm for this. The only way to do the TOLERANCE and the BLUR is from shader. :(

Here is a test without any shader. I tuned up all the effect to see, but it's wrong and it's even worse if you start to move around the screen.

(http://dl.dropbox.com/u/292449/img/wrongbloom.png)

And if I switch on my Horizontal blur shader, then the shader works, but the scene falls apart. Why???

(http://dl.dropbox.com/u/292449/img/wrongbloom_shader.png)

Here is the project in the attachment.
To enable the shader look here:
Code: (glbasic) [Select]
//IF YOU USE THIS SHADER THE RENDER FALL APART??
//X_SETSHADER 13
DRAWSPRITE map[mx][my], cx, cy
//X_SETSHADER -1




[attachment deleted by admin]
Title: Re: Ray of lights
Post by: mentalthink on 2011-Sep-28
Thanks Albert, I try more later, but have a good look.

 :nw: :nw: :nw:

Kinds Regards,
Iván J.
Title: Re: Ray of lights
Post by: mentalthink on 2011-Sep-28
Albert, agains you do it, absolutely fantastic, it´s very very nice the effect image, and touching a little the parameters, you have a fake 8 bits effects, like a dirty image in a old CPC from de Asmtrad.

Thanks again.

Iván J.
Title: Re: Ray of lights
Post by: Albert on 2011-Sep-29
Iván, if you can use this effect, then I would love to see what you can achieve it. So use it freely, if you manage to mix the parameters and get something fun, share with us.
Title: Re: Ray of lights
Post by: Kitty Hello on 2011-Sep-29
For a radial blur, there's an old technique that requires no shaders:
http://nehe.gamedev.net/tutorial/radial_blur__rendering_to_a_texture/18004/ (http://nehe.gamedev.net/tutorial/radial_blur__rendering_to_a_texture/18004/)

Basicall he does:
-Render the blur objects to a texture.
-Optionally: Scale the texture down to 1/4 of the original size (for more speed)
-Draw the very same texture on itself like:
Code: (glbasic) [Select]
USESCREEN 1
FOR i=0 TO 10
   ALPHAMODE 0.5
   ZOOMSPRITE 1, 0,0, 1.05, 1.05
NEXT
USESCREEN -1
-Draw that sprite now over the final scene
Code: (glbasic) [Select]
ALPHAMODE 0.9
   STRETCHSPRITE 1, 0,0,screenx, screeny


You get the idea...
Title: Re: Ray of lights
Post by: Albert on 2011-Sep-30
Thanks Gernot, this is what I'm used for the lightray algorithm just with some doublebuffering or what :)
But this NeHe tutorial gave me an idea to blur the screen without zooming, just displacing a bit. Here is my results:

(http://dl.dropbox.com/u/292449/img/bloom1.png)

(http://dl.dropbox.com/u/292449/img/bloom3.png)
Title: Re: Ray of lights
Post by: chve on 2011-Oct-30
I am new still in GLBasic forum and I have just donwloaded "Ray of lights" Albert.
It is awesome!!!  :good: :good: :good:


Congratulations!!
Title: Re: Ray of lights
Post by: Hatonastick on 2011-Oct-30
Those examples are seriously cool!  Now I'm tempted to think up ways and programs I can use them in.  :good:
Title: Re: Ray of lights
Post by: Qedo on 2020-May-14
@Albert
I'm interested in the Bloom effect and I'd like to study your code which is unfortunately no longer available in the forum.
Could you attach it?
Thanks
Ciao