Code archives/3D Graphics - Effects/Lens Flares
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
| ***DOWNLOAD THE DEMO*** complete with source code and media here: http://game.barliesque.com/blitz3d/sun_flares_demo.zip (1.7 MB) This system produces one of the best lens flares I've seen, IMHO. It's not quite perfect yet, but I'm working on making it perfect! :) For now, I think this is a good start. Features: - Flares change size and intensity based on how directly they're viewed - Flares are tinted, based on the colour of the light source (great for stained glass windows!) ![]() All code and media included here are available for you to use as you please. If you do use it in a project, a small credit would be quite nice. Also, if you produce your own flares image or come up with some good changes, please post them here. Special Thanks: - SyntaxError for "Sprite Control" - Fredborg for the little landscape that appears in this demo - BloodLocust for the simple lens flare code, which provided a start | |||||
;=======================================================================================
; "SUN FLARES"
; by David Barlia (a.k.a. Barliesque)
; david[at]barliesque[dot]com
;
; Please feel free to make use of this code as you wish.
; If you do use it in a project, a little credit would be nice.
; Also, if you should happen to make some exciting improvements,
; don't hesitate to post your changes (or alternate flares image?)
; to the code archives.
;
; This code makes use of a modified version of "Sprite COntrol" by SyntaxError.
; If you are already using "Sprite Control" in your project, and want to add
; this code, you will probably have no problem changing to this modified version.
; See "Sprite Control.bb" for further info.
;
;=======================================================================================
AppTitle = "Sun Flares Demo"
HidePointer
graphics3D 640,480,32,1
Include "Sprite Control.bb"
Global camera, player
Global cam_pitch#, cam_yaw#
Global mvx#,mvy#,mvz#,targetpitch#,targetyaw#
Global playerheight#=32 ;height of collision sphere
Global FrameTime, FPS#=80.0
;-------------------------
; Set up the Camera/Player
;-------------------------
setbuffer Backbuffer()
player=CreatePivot()
camera=CreateCamera(player)
RotateEntity player,0,180,0
MoveEntity camera,0,playerheight,0
camerarange camera,1,5000
CameraFogMode camera,0
CameraFogColor camera,210,200,150
CameraFogRange camera,200,1000
AmbientLight 35,30,40
CameraClsMode camera,True,True
ClearTextureFilters
MoveMouse GraphicsWidth()/2,GraphicsHeight()/2
;-------------------------
; Set up Sprite Control
; and our flares
;-------------------------
Global ViewX=GraphicsWidth(),ViewY=GraphicsHeight()
Global ViewAspect# = float(viewx)/float(viewy)
global FlareRed, FlareGreen, FlareBlue
dim Flare(15)
spritecamera = camera
spritepivot = CreateSpritePivot(spritecamera,1.01)
SetupFlares("Media\lens-flares.jpg")
;-------------------------
; Load the Scene
;-------------------------
Scene = LoadAnimMesh("Media\Scene.b3d")
Sun = FindChild(Scene,"Sun")
Sky = FindChild(Scene,"Sky")
SkyTurn# = 0.0
;----------------------------------------------
; Set PickModes...
; Use 1 for flare sources
; Use 2 for objects that can block the sun
;----------------------------------------------
restore PickSettings
repeat
read ChildName$, PickMode
if ChildName<>"" then EntityPickMode FindChild(scene,ChildName$),PickMode
until ChildName=""
.PickSettings
data "Sun", 1
data "Landscape", 2
data "Stand 1 Upper", 2
data "Stand 1 Lower", 2
;data "Stand 1 Frame", 2
data "Stand 2 Upper", 2
data "Stand 2 Lower", 2
;data "Stand 2 Frame", 2
data "Stand 3 Upper", 2
data "Stand 3 Lower", 2
;data "Stand 3 Frame", 2
data "Stand 4 Upper", 2
data "Stand 4 Lower", 2
;data "Stand 4 Frame", 2
data "", 0
;MAIN LOOP * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
While Not KeyHit(1)
PlayerControls()
rate# = RatePerFrame#(0.0005, 240.0)
skyTurn = SkyTurn + rate
if SkyTurn>=360.0 then skyTurn=SkyTurn-360.0
TurnEntity Sky,0,SkyTurn,0
PointEntity Sun, Camera
UpdateFlare(camera, Sun)
Sync()
Wend
End
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
function Sync()
UpdateWorld
RenderWorld
time = millisecs() - FrameTime
FrameTime = millisecs()
FPS = 1000.0/float(time)
text 50,0,"FPS: " + FPS
vwait : Flip false
end function
function RatePerFrame#(delta# = 1.0, secs# = 1.0)
rate# = delta / float(secs * FPS)
return rate#
end function
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Function PlayerControls()
;***
;*** Free Look
;***
mxspd# = MouseXSpeed()*0.25
myspd# = MouseYSpeed()*0.25
MoveMouse GraphicsWidth()/2,GraphicsHeight()/2
targetpitch = targetpitch + myspd
targetpitch = clampvaLUE(targetpitch, -85,85)
targetyaw = targetyaw - mxspd
cam_pitch = cam_pitch + (targetpitch - cam_pitch)/8.0
cam_yaw = cam_yaw + (targetyaw - cam_yaw)/8.0
RotateEntity player,0,cam_yaw,0
RotateEntity camera,cam_pitch,0,0
;***
;*** Movement
;***
If KeyDown(203) Then mvx=mvx-.25
If KeyDown(205) Then mvx=mvx+.25
If KeyDown(200) Then mvz=mvz+.25
If KeyDown(208) Then mvz=mvz-.25
If KeyDown(30) Then mvx=mvx-.25
If KeyDown(32) Then mvx=mvx+.25
If KeyDown(17) Then mvz=mvz+.25
If KeyDown(31) Then mvz=mvz-.25
TranslateEntity player,0,mvy,0
MoveEntity player,mvx,0,mvz
mvx=mvx/1.2
mvy=mvy/1.2
mvz=mvz/1.2
End Function
;-----------------------------------------------------
function ClampValue(Original#, low#, high#)
if Original<low then return low
if Original>high then return high
return Original
end function
;-----------------------------------------------------
Function UpdateFlare(cam_entity,source)
cameraProject cam_entity,EntityX(source,True),EntityY(source,True),EntityZ(source,True)
SourceX# = ProjectedX#()
SourceY# = ProjectedY#()
x# = SourceX/viewx
y# = SourceY/viewy
text 40,0,"X,Y: " + X + ", " + Y
SeeSource = camerapick(cam_entity,SourceX,SourceY)
if ((SeeSource = Source) or (SeeSource = 0)) and entityinview(source,cam_entity) and (x>0 And x<=1) And (y>0 And y<=1)
GetFlareColor(cam_entity, source, SourceX, SourceY)
scale# = ViewX/800.0
restore FlareData
read TotalFlares
for f=1 to TotalFlares
read Distance, FlareSize, ColorInfluence#, Alpha#, Frame
flare_x# = SourceX - (((x-0.5)*2.0)*Distance)
flare_y# = SourceY - (((y-0.5)*2.0)*(Distance/ViewAspect))
r = (ColorInfluence * FlareRed + 255.0*(1.0-ColorInfluence))
g = (ColorInfluence * FlareGreen + 255.0*(1.0-ColorInfluence))
b = (ColorInfluence * FlareBlue + 255.0*(1.0-ColorInfluence))
entitycolor Flare(f), r,g,b
FlareSize = FlareSize * scale * (x + y + (cos(Distance*0.45)/2.0) + 0.5)
ResizeImage3D Flare(f),FlareSize,FlareSize
if lowest#(x,y)<0.1 then
EntityAlpha Flare(f),Alpha * lowest#(x,y)/0.2
else
EntityAlpha Flare(f),Alpha
endif
DrawImage3D Flare(f),flare_x,flare_y,Frame
ShowEntity Flare(f)
next
else
restore FlareData
read TotalFlares
for f=1 to TotalFlares
HideEntity Flare(f)
next
endif
End Function
; FLARE DATA: Distance, FlareSize, ColorInfluence#, Alpha#, Frame
;
; Distance - Maximum offset from source
; FlareSize - Maximum size of flare
; ColorInfluence - How strongly colour of source affects the flare's colour
; Alpha - Maximum alpha level (0.0 to 1.0)
; Frame - Frame of the lens flare texture (1 to 16)
.FlareData
Data 15
Data -100, 400, 1.00, 0.40, 1 ;Red Crescent (50% to 0%)
Data -95, 35, 0.80, 0.40, 2 ;Orange/Yellow Gradient (80% to 0%)
Data 0, 130, 0.60, 1.00, 3 ;Bright Flare Center (100%)
Data 95, 35, 0.35, 0.50, 4 ;Purple Disc (60%)
Data 150, 45, 0.50, 0.30, 5 ;Blue Disc (60%)
Data 120, 70, 0.60, 0.40, 6 ;Blue Gradient (50% to 20%)
Data 200, 20, 0.90, 0.40, 7 ;Orange Disc (80%)
Data 250, 8, 0.10, 1.00, 15 ;Sharp point (100%)
Data 280, 15, 0.15, 1.00, 8 ;Fuzzy Star (100%)
Data 345, 80, 0.90, 0.20, 7 ;Orange Disc (50%)
Data 390, 60, 0.80, 0.60, 7 ;Orange Disc (80%)
Data 395, 30, 0.40, 0.40, 9 ;Green Disc (80%)
Data 460, 100, 0.90, 0.40, 10 ;Orange Gradiant (90% to 0%)
Data 550, 160, 0.70, 0.50, 11 ;Yellow Ring (90%) with Green Gradient (60% to 0%)
Data 800, 350, 0.80, 0.30, 12 ;Rainbow Halo (outside to in: Red,Orange/Yellow,Violet) (50%)
;-----------------------------------------------------------
function SetupFlares(filename$)
FirstFlare = LoadAnimImage3D(filename$,4,4,1)
restore FlareData
read TotalFlares
for i=1 to TotalFlares
read Distance, FlareSize, ColorInfluence#, Alpha#, Frame
Flare(i) = CopyImage3D(FirstFlare)
ResizeImage3D Flare(i),FlareSize,FlareSize
EntityAlpha Flare(i),Alpha
EntityBlend Flare(i),3
EntityOrder Flare(i),-100-i
midhandle3D Flare(i)
entitycolor Flare(i),255,255,255
HideEntity Flare(i)
next
FreeImage3D(FirstFlare)
end function
;-----------------------------------------------------------
function GetFlareColor(cam_entity, source, SourceX, SourceY)
; This function is responsible for the majority of
; resource drain. For just the sun, it may be an acceptable
; slowdown. For things like candles and indoor lights
; this feature should probably not be used.
CameraProjMode cam_entity, 0
sample_cam = createcamera()
positionentity sample_cam, EntityX(player,true),playerheight,EntityZ(player,true)
pointentity sample_cam, source
CameraProjMode sample_cam, 2
if SourceX<0 then SourceX=0
if SourceY<0 then SourceY=0
cameraviewport sample_cam, SourceX, SourceY, 1,1
for f=1 to 15 : hideentity Flare(f) : next
updateworld
RenderWorld
getcolor SourceX,SourceY
FlareRed = ColorRed()
FlareGreen = ColorGreen()
FlareBlue = ColorBlue()
color 255,255,255
CameraProjMode cam_entity, 1
FreeEntity sample_cam
end function
;-----------------------------------------------------------
function lowest#(val1#, val2#)
if val1<val2 then
return val1
else
return val2
endif
end function |
Comments
| ||
| Very nice lenflare !!! thanks to release code !! |
| ||
| Thank you! :) I just made a small change to correct an error in GetFlareColor() where it was off a little bit from the centre of the flare. positionentity sample_cam, EntityX(camera,true),EntityY(camera,true),EntityZ(camera,true) ...changed to: positionentity sample_cam, EntityX(player,true),playerheight,EntityZ(player,true) ...though I'm not clear why this would fix it! :S |
| ||
| Very nice effect! |
| ||
| Best lens flare effect I have seen. Ever. |
| ||
| This is incredible.... Wow *Attempts to shut gob smacked mouth* I can't believe this is open source :) Funkkkyyyy |
| ||
| Nice!!! |
| ||
| Hi Barliesque, It didn't take you long to get used to Blitz then!! A really nice piece of work. I've given it a test in one of my space themes and it looks stunning. I'm going to try and write it into my TrainSim, it should give some nice effects for early morning and late evening running. I've managed to get a locomotive working and looking quite good on the Port Daniel line but no coaches yet, so passengers are still a bit irate!!! Return tickets holders are now certain of being returned to where they started from because they never leave in the first place!!! Thanks again. Carpman |
| ||
| Woah, i get 90 fps almost constantly on my pIII 800, GF MX440. quite impressive... i like the effect of the blending colors, superb stuff! |
| ||
| It is brillant. I will use it and I will credit you. thanks |
| ||
| Wow, *very* pretty - thanks for sharing! |
| ||
| Oh ! Another sweet effect ! - reallistic lens FX - paper pen FX - black light FX - sand of time FX - motion blur FX - glow FX |
| ||
| Thank you all! Really great to read all your comments! I look forward to seeing it in use in your projects. Woah, i get 90 fps almost constantly on my pIII 800, GF MX440. quite impressive... i like the effect of the blending colors, superb stuff! Excellent news. I was wondering how well the flare colouring effects would work with other systems. I was amazed I could get away with rendering the scene a second time (even if it is just for a single pixel) and still manage a strong frame rate. I love Blitz3D!!! Return tickets holders are now certain of being returned to where they started from because they never leave in the first place!!! Just like the real thing! You are a stickler for realism, Carpman. ;) |
| ||
| Recently, a user was having difficulty integrating the code into his project. So here are some notes I wrote up to help him solve the trouble. Maybe others will find this helpful: 1) Be sure to include the file "Sprite Control.bb" 2) Two globals are being used by GetFlareColor() Global player
Global playerheight#=32They'll need to be defined in your main program (or you may prefer to make them parameters of that function, rather than relying on globals. Looking back at the code now, I'm not sure why I did it the way I did!) 3) The following bit of code from the demo contains global declarations that are essential. This code should come AFTER your graphics3D command, so that ViewX and ViewY are correctly set. ;-------------------------
; Set up Sprite Control
; and our flares
;-------------------------
Global ViewX=GraphicsWidth(),ViewY=GraphicsHeight()
Global ViewAspect# = float(viewx)/float(viewy)
global FlareRed, FlareGreen, FlareBlue
dim Flare(15)
spritecamera = camera
spritepivot = CreateSpritePivot(spritecamera,1.01)
SetupFlares("Media\lens-flares.jpg")4) Of course, the last line above needs to be changed if the lens flare image is in a different location. 5) In your main program loop, you need only one command: UpdateFlare(camera, Sun) ...where "camera" is the camera entity, and "Sun" is the entity of a pivot where the sun should be. Note alse these lines from the intialisation part of the demo: Scene = LoadAnimMesh("Media\Scene.b3d")
Sun = FindChild(Scene,"Sun")An object within the hierarchy of the sample scene model was named "Sun." This statement finds that entity so that the flare functions can refer to it as a "light source" |
| ||
| great! thx a lot! |
| ||
| Awesome! Here it is at work in my project; |
| ||
| Ahhh, great! Nice to see it in use. Thanks for posting the pretty screenshot. |
Code Archives Forum
