Sunbeams-in-dusty-air effect

Miscellaneous Forums/Blitz Showcase/Sunbeams-in-dusty-air effect

Some of you might know the effect used in the engine of Hitman 2 (and maybe used by other engines as well), when sunlight is falling trough a window into a dusty room and there are visible beams in the air, eg. in the church scene. I was pretty impressed by that effect, and now I wrote some code that will take a texture and create some sunbeams based on the images colors:



It's a low poly solution, might look cool in lightmapped levels. I'll put this to the code archives.

looks great jfk.

thanks. looks better when in motion. http://www.melog.ch/dl/sunbeams.zip

looks good, thoughI think the lines are a litle too harsh,

Anyway of softening them up a bit?. i also think that they should fade out a 'little' bit sooner

Sweet effect, thanks for sharing!

I wonder if we had a second smokey texture and moved it about....hmmm

Tom

you can set this in the parameters: lenght, trans (transparency) etc. you can also modify the source, eg. use a smaller version of the texture to achieve less detailed beams.
However, I like it this way since it0s pretty much the same as the one in hitman 2.
Yes, the beams are not very subtile, but as I mentioned you can lower the opaqueness easily, so they become ultra-subtile.

thank you jfk! I have been looking for that effect for ages!

JFK,

I just did the same thing two days ago,but mine doesn't seem as good as yours...

...so thanks for that!

IPete2.

sounds cool jfk, nice work

Really nice as always -- thanks JFK!

This is very nice. I was playing around with something similar a few months back, but it didn't look this good. Very slick.

Very well done jfk! My advice: make it so that the vertex's with an alpha of 0 slowly change there value, that way you could simulate that the dust is moving perhaps?

screw waiting done it my self :D

Global sunpiv = CreatePivot()
Global alpha#

While Not KeyDown(1)
 Text 0,0,"Tris Rendered: "+TrisRendered()
 u = u + .1
 v = v + .1
 win=GetChild(window,1)
 For i = 0 To CountVertices(GetSurface(win,1)) - 1
  PositionEntity sunpiv, VertexX(GetSurface(win,1),i), VertexY(GetSurface(win,1),i), VertexZ(GetSurface(win,1),i)
  alpha = Rnd(VertexAlpha(GetSurface(win,1),i)-.02, VertexAlpha(GetSurface(win,1),i)+.02)
  If EntityDistance(sunpiv,window) > 2 Then 
    If alpha > .4 Then alpha = .4
  Else
    If alpha < .6 Then alpha = .6
  EndIf
  ;DebugLog EntityDistance(sunpiv,window) + " > " + alpha
  VertexColor GetSurface(win,1),i,VertexRed(GetSurface(win,1),i),VertexGreen(GetSurface(win,1),i),VertexBlue(GetSurface(win,1),i),alpha;Rnd(VertexAlpha(GetSurface(win,1),i)-.05, VertexAlpha(GetSurface(win,1),i)+.05)
 Next
 RenderWorld()
 Flip
 ;Stop
Wend
End


Looks a whole lot better like that.
Oh btw - i know its really bad - making the whole thing into a module for Jfk now :)

nice one as well, thanks!

Sunbeam showoff! http://www.downloads.polarstudios.co.uk/SunBeams.zip I added the bloom and dream filter to make it look nice :)


all credit to jfk though - he made the best part ;)

nice!

nice also aCid2

I think this is now ready for use in games. It has my flickering effect of moving dust, and should work where ever the window it. Supports unlimited windows aswell (i've stuck hte bloom filter in this - its easy enough to get rid of though)

; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; aN exAMPle OF How To USe It
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

Graphics3D 800, 600, 0, 2
SetBuffer BackBuffer()
AppTitle "Jfk's 'Sunbeams in dusty air' effect - extended by aCiD2"
HidePointer
MoveMouse 400, 300

; [ - =  3RD Party!  = - ]
Include "BloomFilter.bb"

;#Region Make this its own file and include it
;#Region Comments
	;
	; ************************************************************
	; * Project Name: Sunbeams in dusty air
	; * Author(s): aCiD2, Jfk
	; * Date Started: 19th June 2004
	; * Last Updated: 20th June 2004
	; * Website: <a href="http://www.polarstudios.co.uk" target="_blank">http://www.polarstudios.co.uk</a>
	; * Email: acid2@...
	; * Version: 1.1.00
	; * Copyright: (c) polarStudios 2004
	; ************************************************************
	;
	; This program is free software; you can redistribute it and/or
	; modify it under the terms of the GNU General Public License
	; as published by the Free Software Foundation; either
	; version 2 of the License, or (at your option) any later version.
	; 
	; This program is distributed in the hope that it will be useful,
	; but WITHOUT ANY WARRANTY; without even the implied warranty of
	; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
	; GNU General Public License for more details.
	;
	; You should have received a copy of the GNU General Public License
	; along with this program; if not, write to the Free Software
	; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
	;
	; ************************************************************
	; *
	; *
	; *  Sunbeams in dusty air
	; *
	; *  This is a small libary writen mainly by jfk to simulate
	; *  the effect of sunlight passing through dust particles, giving
	; *  a very nice ray of light effect. I (aCiD2) have extended
	; *  on jfk's code to allow it to have multiple windows, etc
	; *
	; ************************************************************
	; *
	; * This file is of the following category...
	; *		[   ] Main File
	; *		[ x ] Library
	; *		[   ] Constant Collection
	; *		[   ] Test
	; *		[   ] Project Wrapper
	; *
	; ************************************************************
	;
;#End Region

; The window pane type holds each of the windows that can cast light rays
; It holds the window mesh and the light rays surface (the mesh isn't needed)
Type Sunbeams_WindowPane
	
	Field Window%				; This is the window - the light rays are also parented to this
	Field Surf%					; The surface for the light rays
	
End Type

;#Region Create sunbeams
	;;; <summary>This function takes a texture and makes a new window and sunbeams from it.</summary>
	;;; <param name="Texture">The texture path to the texture.</param>
	;;; <param name="Transparancy">How transparent the sunbeams are.</param>
	;;; <param name="NumBeamsX">How many horizonatal beams</param>
	;;; <param name="NumBeamsY">How many vertical beams</param>
	;;; <param name="Zoom">Used with cone shape projection (needs to be used only when no vertical beams are made)</param>
	;;; <param name="Height">The sun height</param>
	;;; <param name="Length">How long the beams are</param>
	;;; <param name="UseVertical">Use vertical beams</param>
	;;; <param name="UseHoriz">Use horizontal beams</param>
	;;; <remarks>Originally made by Jfk - I've only made it create a new type instance</remarks>
	;;; <returns>The window mesh, with the beams parented to it.</returns>
	;;; <subsystem>Realism.Lights.Sunbeams</subsystem>
	Function Sunbeams_Create(Texture$, Transparancy# = .2, NumBeamsX% = 5, NumBeamsY% = 5, Zoom# = 1.0, Height# = -1.0, Length# = 5.0, UseVertical% = True, UseHoriz% = True)
		
		Local s.Sunbeams_WindowPane = New Sunbeams_WindowPane
		Local Tex1%, Tex2%, Buffer%
		Local J%, I%, RGB%, ARGB%, A%, R%, G%, B%, MinV%
		Local Win%, Mesh%, Surf%, Where#, WhereV#, V0%, V1%, V2%, V3%
		
		Tex1 = LoadTexture(Texture)			; The texture for the glass pane
		Tex2 = LoadTexture(Texture, 2)		; The texture for the sun beams
		
		;#Region Amplify texels used to create a beam from
		Buffer = GraphicsBuffer()
		SetBuffer TextureBuffer(Tex2)
		LockBuffer
		
		For J = 0 To TextureHeight(Tex2) - 1
			For I = 0 To TextureWidth(Tex2) - 1
				RGB = ReadPixelFast(I, J) And $ffffff
				
				R = (RGB And $FF0000) Shr 16
				G = (RGB And $FF00) Shr 8
				B = (RGB And $ff)
				
				MinV = 128
				If R > MinV Or G > MinV Or B > MinV
					A = (255 * Transparancy) Shl 24
				Else
					A = 0
				EndIf
				
				R = R * 3
				G = G * 3
				B = B * 3
				
				If R > 255 Then R = 255
				If G > 255 Then G = 255
				If B > 255 Then B = 255
				
				ARGB = A Or (R Shl 16) Or (G Shl 8) Or B
				WritePixelFast I, J, ARGB
			Next
		Next
		
		UnlockBuffer
		SetBuffer Buffer
		;#End Region
		;#Region Crete the window mesh (not the beams)
			Win = CreateMesh()
				Surf = CreateSurface(Win)
				V0 = AddVertex(Surf, 0, -1, -1, 0, 1)
				V1 = AddVertex(Surf, 0, 1,  -1, 0, 0)
				V2 = AddVertex(Surf, 0, 1,   1, 1, 0)
				V3 = AddVertex(Surf, 0, -1,  1, 1, 1)
				AddTriangle Surf, V0, V1, V2
				AddTriangle Surf, V2, V3, V0
				UpdateNormals Win
			
			EntityTexture Win, Tex1
			EntityFX Win, 17
			EntityAlpha Win, .7
		;#End Region
		;#Region Create the beams
			Mesh = CreateMesh(Win)
			Surf = CreateSurface(Mesh)
			
			;#Region Create horizontal beams
				If UseHoriz
					For  I = 0 To NumBeamsY
						Where = (((Float(I) - NumBeamsY) / NumBeamsY) * 2.0) + 1.0
						WhereV = (Where + 1.0) / 2.0
						
						V0 = AddVertex(Surf, -1, Where, -1, 1, -WhereV)
						V1 = AddVertex(Surf, 1 * Length, Where * Zoom + Height, -1, 1, -WhereV)
						V2 = AddVertex(Surf, 1 * Length, Where * Zoom + Height, 1, 0, -WhereV)
						V3 = AddVertex(Surf, -1, Where, 1, 0, -WhereV)
						
						VertexColor Surf, V0, 255, 255, 255, 1
						VertexColor Surf, V1, 0, 0, 0, 0
						VertexColor Surf, V2, 0, 0, 0, 0
						VertexColor Surf, V3, 255, 255, 255, 1
						
						AddTriangle Surf, V0, V1, V2
						AddTriangle Surf, V2, V3, V0
					Next
				EndIf
			;#End Region
			;#Region Create vertical beams
				If UseVertical
					For  I = 0 To NumBeamsX
						Where = (((Float(I) - NumBeamsX) / NumBeamsX) * 2.0) + 1.0
						WhereV = (Where + 1.0) / 2.0
						
						V0 = AddVertex(Surf, -1, -1, Where, WhereV, 1)
						V1 = AddVertex(Surf, 1 * Length, -1 + Height, Where, WhereV, 1)
						V2 = AddVertex(Surf, 1 * Length, 1 + Height, Where, WhereV, 0)
						V3 = AddVertex(Surf, -1, 1, Where, WhereV, 0)
						
						VertexColor Surf, V0, 255, 255, 255, 1
						VertexColor Surf, V1, 0, 0, 0, 0
						VertexColor Surf, V2, 0, 0, 0, 0
						VertexColor Surf, V3, 255, 255, 255, 1
						
						AddTriangle Surf, V0, V1, V2
						AddTriangle Surf, V2, V3, V0
					Next
				EndIf
			;#End Region
			
			UpdateNormals Mesh
			EntityFX Mesh, 19
			EntityBlend Mesh, 3
			EntityTexture Mesh, Tex2
			TranslateEntity Mesh, 1, 0, 0
		;#End Region
		;#Region Setup the type instance
			s\Surf = Surf
			s\Window = Win
		;#End Region
		
		Return Win
	End Function
;#End Region
;#Region Update sunbeams
	Function Sunbeams_Update()
		
		Local s.sunbeams_windowpane
		Local v%, alpha#
		
		For s = Each Sunbeams_WindowPane
			For v = 0 To CountVertices(s\Surf) - 1
				dx = VertexX(s\Surf, v) - VertexX(s\Surf, 0)
				dy = VertexY(s\Surf, v) - VertexY(s\Surf, 0)
				dz = VertexZ(s\Surf, v) - VertexZ(s\Surf, 0)
				
				distance# = Sqr(dx * dx  +  dy * dy  +  dz * dz)
				
				alpha = Rnd(VertexAlpha(s\Surf, v)-.02, VertexAlpha(s\Surf, v) + .02)
				If distance > 5
					alpha = 0
				Else
					If alpha < .2 Then alpha = .2
					If alpha > .3 Then alpha = .3
				EndIf
				
				VertexColor s\Surf, v, 255, 255, 255, alpha
			Next
		Next
		
	End Function
;#End Region
;#End Region
AmbientLight 255, 255, 255

Global camMain = CreateCamera()
	CameraRange camMain, 0.01, 1000
	TranslateEntity camMain, 0, 0, -10
	InitGlow(camMain)
	
Global textWall = LoadTexture("stone19.jpg")
Global meshBuilding = CreateCube()
	FlipMesh meshBuilding
	EntityFX meshBuilding, 16
	EntityTexture meshBuilding, textWall
	EntityColor meshBuilding, 100, 100, 100
	ScaleEntity meshBuilding, 7, 6, 7
	TranslateEntity meshBuilding, 6.9, 0, 0

Global meshWindow = Sunbeams_Create("churchwin3.jpg",128,5,5,1.0,-1,10.0,1,0)
	ScaleEntity meshWindow, 1, 4, 2
	EntityParent meshBuilding, meshWindow
	RotateEntity meshWindow, 0, -90, 0

Global meshWindow2 = Sunbeams_Create("churchwin3.jpg",128,5,5,1.0,-1,10.0,1,0)
	MoveEntity meshWindow2, -6.99, 0, -7
	ScaleEntity meshWindow2, 1, 4, 2

While Not KeyHit(1)
	
	Cls
	
	c = camMain
 	mxs# = mxs + Float(MouseXSpeed())/3
    mys# = mys + Float(MouseYSpeed())/3
    mxs = mxs - mxs/4
    mys = mys - mys/4
    TurnEntity C,mys,-mxs,0
    RotateEntity C,Min(Max(EntityPitch(C),80),-80),EntityYaw(C),0
    MoveEntity C,(KeyDown(205)-KeyDown(203))*.2,0,(KeyDown(200)-KeyDown(208))*.2
    MoveMouse GraphicsWidth()/2,GraphicsHeight()/2
	
	UpdateWorld
	Sunbeams_Update
	
	RenderGlow 
	RenderWorld
	
	Flip
		
Wend

Function Min(A#,B#)
	If A < B Then Return B
	Return A
End Function
Function Max(A#,B#)
	If A > B Then Return B
	Return A
End Function


What looks really cool is if you have moving particles texture-mapped with a projector texture.

halo: anychance of a demo? ;)

Not so hard to code, yes, probably it would look cool, but I ask myself if it's worth the polycount. Imagine, this is not only for a demo that shows off some dusty particles in the air, but for a game engine that has to do a lot of other things as well. Personally I know that if you add a lot of power-consuming effects to an engine, the game will be slow as death.

nice stuff J... really nice...

Thanks

--Mike

Polycount? It's just a particle emitter. It wouldn't really create much overhead at all. UT does this.

A particle emitter that requires to update the uv's each frame I guess. It might be ok when you use it in some kind of VIS system that can hide/deactivate emitters when out of sight. Anyway, I am not a fan of common particle emitters. Torches for example usually are looking so very unrealistic imho.

If you are using a single-surface system, you have to update all vert positions anyways, so using the position for the UV coordinates isn't a big deal.

I would actually use a single emitter for each type of effect, and copy it, so you only have to update one "smoke" emitter.

I agree, animated sprites look much better for fire. But particle smoke and dust rules all.

@aCiD2: none of your "polarstudios.co.uk" links work...

BTW I have already included this effect successfully in my current map work. But there is a problem: I save this mesh with Vertex Colors and Vertex Alpha as B3D Files, so I only have to load and position them using the Interior Dropper. Now when I try to adjust the EntityAlpha on the entire Mesh, Blitz ignores it (as seen with Maplet Meshes as well):


Is there a way to "resensitize" a .B3D to EntityAlpha? Or can I allow it using the Flags in the File Format?

Nifty.

Try adding a light source and rotating the whole thing.
Creates a rotating 'police light'effect.

B.

Very nice work jfk :o)

Exhumation? o_O

Does anyone still has "BloomFilter.bb" or updated sunbeams.zip?