LensFlares 
By Relsoft BSN RN
HTTP://Rel.Betterwebber.com



I. Defint A - Z

	I was supposed to write a tutorial on game object systems when a friend asked me if  could help him with his ASM project. The ASM project he submitted was just an input function and a floormapper but I got a lot of $$$ for it since a lot of groups wanted me to help them with their ASM projects.  One group did not pay in currency but with the whole Hunter X Hunter "Greed Island OVA" (including G.I Final, about 9 CD's / 23 episodes).  That's where the idea of making a lens flare article struck me.  The Anime, as good as it was has blended CG effects with traditional hand drawn pixels to achieve a masterpiece! And one of the effects used to the fullest are lens flares.

	So what are lens flares?  It's those things you see in your camera when a bright light passes on the camera field of view.  Lens flares are not that hard to model.  They're just blended lightmaps put in a linear fashion superimposed together.  One common thing with lens flare models is that they rotate from the center of the screen.  


2. Coding

	You need some basic undestanding of vectors if you want to understand the concepts I'm about to rant here.  You can get an intro in vector math in Chapter 3 of my 3d tutorial <Pete: Pimp Chapter 3 URL here>.  The basic idea of making the flare movement believable is to use linear interpolation.  To lineary interpolate, we need two points, in screen 13:
	

	1.  The Center of the screen (cx, cy) or (160, 100) 
	2.  The Light's position on the screen (Lx, Ly) 
	
	<vector.gif>

	Now that we have the 2 points, we need to define a vector between those 2 points.  For those who haven't read the URL above, to get a vector from Center to Light point:


	Vector = Center - Light

	or


	QBcode:

	Vector.x = Center.x - Light.x
	Vector.y = Center.y - Light.y

	The vector we have at this moment is next to useless since directly manipulating the flare's position with it is a little cumbersome.  What we need to do is to "normalize" this vector. That is, make its length equal to 1.  To normalize this vector:

	Normalized Vec = Vec / VecLength


	We get the vector's length by using the distance formula:

	c = Sqr(a^2 + b^2)


	QBcode:

	dx! = v.x
	dy! = v.y
	dist! = SQR(dx! * dx! + dy! * dy!)
    	IF dist! < .00001 THEN EXIT SUB  'just a precaution for too small
                                     	 'values
	v.x = dx! / dist!
    	v.y = dy! / dist!
    	v.mag = dist!

	Where:  
	v.x -> x component of vector
	v.y -> y component of vector
	v.mag -> Length of vector (may be used for scaling sprites)



	How do we calculate each flares' position relative to the center of screen?  That's the easy part.  We define how far the farthest flare from the center and multiply it with the components of our normalized vector. Let's say we want the farthest flare to be 100 units(pixels) away from the center:


	QB code:

	Distance = 100
	Flarex = vector.x * Distance
	Flarey = vector.y * Distance
	pset (Flarex, Flarey), col


	That would be the location to the farthest flare.  To calculate flares in between the center and the first flare, we just divide the value of the Distance and multiply it with the vector's components. So to get the position in the half-way mark:

	(Assuming the distance is 100)

	Flarex = vector.x * (Distance/2)
	Flarey = vector.y * (Distance/2)
	pset (Flarex, Flarey), col

	
	Try these values:

	1. Distance/4
	2. Distance/8
	3. Distance/1.8
	4. -Distance/4
	5. -Distance/8
	6. -Distance/1.8

		

	Here's and example file:
	<Flarmove.Bas>



III.  Sprite

	I suggest you try to make your lens flare images with Photoshop. There are a lot of tutorials on the net on how to make nice flare textures.  The textures I'm using here are all generated using some mathematical sampling I got from BLACKPAWN <http://www.blackpawn.com/texts/lensflare/default.html >.  And I'm not using some 13h color hack so that you'd understand the concepts behind them.  For a thorough explanation of how to generate these textures, I suggest you visit his site.  It's in C/Pseudocode but it's realy easy to understand.  But the best way really is to get some free images off the net as there are tons of them.


IV.  Blending

	The blending method I would use here is pretty straightforward.  The concept behind blending is easy.  You just "attenuate" the RGB values of each pixel depending on the flares pixel and the pixel behind the flare.  Weighted mean in statistics would come in handy. :*)

	To attenuate in true color with normal weights, you just get the average RGB values of the pixels. ie:
	
	NewR = (ScreenR + FlareR) / 2
	NewG = (ScreenG + FlareG) / 2
	NewB = (ScreenB + FlareB) / 2

	putpixel (x, y), RGB(NewR, NewG, NewB)

	One problem though is the fact that we are using palettised screen 13.  So we cannot do some nice true-color stuff here.  What we will do is to arrange our palette from black to bright-white in a gradient so that we could calculate the colors to pset easily.


	eg.
	color = (screencolor + flarecolor) /2
	pset (x, y), color


	Image() is a 2d integer array:

	QBcode:

	SUB transsprite (x%, y%, image%())
	'Draws out images translucently using a simple
	'blending method

	xmax% = UBOUND(image%, 1)
	ymax% = UBOUND(image%, 2)
	FOR ny% = 0 TO ymax%
	FOR nx% = 0 TO xmax%
	    c% = image%(nx%, ny%)                           'get color of image
	    IF c% <> 0 THEN                                 '0?
        	dc% = POINT(x% + nx%, y% + ny%)             'get color of screen
	        PSET (x% + nx%, y% + ny%), (c% + dc%) \ 2   'blend and draw
	    END IF
	NEXT nx%
	NEXT ny%



V.  Demo

	Now that we have the sprites, then math, and the concept behind, making the program would be a cinch.  All we have to do is to put(blended) the flare's images instead of pixels.  To center the images on the points:

	x, y -> point we want to center the flare image

	x = x - (imagewidth/2)
	y = y - (imageheight/2)

	Transput (x, y), image()

	We also would want to add flicker to the flare. Again, it's very easy. We just alternately draw a blank screen with the flare screen.

	do
		frame = frame + 1
		if (frame and 1) = 0 then
			draw flares
		else
			don't draw flares
		end if
	Loop
	

		
	Here's the whole demo:
        <flaretut.exe> exe
	<flaretut.bas> source

	And if you want to see the demo in 32-bit...
	<FBFlare.Exe>  Exe
	<FBFlare.BAS>  Source
	(Made with FreeBasic and TinyPTC)




GOSUB CREDITS

END


Credits:

Blackpawn for his nice flare textures tute <http://www.blackpawn.com/texts/lensflare/default.html>
Plasma for SetVideoSeg
Pete fro this mag
v3cz0r for the coolest 32-Bit BASIC compiler
Gaffer for TinyPTC

return 



