Code archives/3D Graphics - Effects/Sunbeams in the air

This code has been declared by its author to be Public Domain code.

Download source code

Sunbeams in the air by jfk EO-111102004
Well, this is not only an effect, but it creates a Mesh that is using Vertex Alpha to blend the sunbeams in.

Download the demo including the textures used in the demo from here:
http://www.melog.ch/dl/sunbeams.zip (67 kB)
; CSP Demo: Hitman 2 like "Sunbeams-in-dusty-air" Effect. This Function takes a Texture and creates
; sunbeams based on the images colors, using a lowpoly method.
Graphics3D 800,600,32,2
SetBuffer BackBuffer()


camera=CreateCamera()
TranslateEntity camera,0,0,-12

;create a "building"
wall=CreateCube()
walltex=LoadTexture("stone19.jpg")
EntityTexture wall,walltex
EntityColor wall,110,110,110 ; a bit darker please
ScaleEntity wall,7,6,7
TranslateEntity wall,6.9,0,0
FlipMesh wall 



window=CreateSunbeams("churchwin3.jpg",40,5,5,1.0,-1.0,10.0,1,1)
ScaleEntity window,1,4,2


;display the result...
EntityParent wall,window
While Not KeyDown(1)
 ang#=(ang#+1) Mod 180
 RotateEntity window,0,ang-180,0
 RenderWorld()
 Text 0,0,"Tris Rendered: "+TrisRendered()
 Flip
Wend
End




; CreateSunbeams() usage:
;texpath$ ; used texture-file
;transp=40 ; beams transparency (0 to 255)
;numsurfx#= number of vertical beam-quads
;numsurfy#= number of horizontal beam-quads
;zoom#=1.0 ; used to create a cone-shaped projection. this can be used 
;            only when no vertical beam-quads are used
;height# ; this will define the angle the "sun" shines down, eg. -1.0
;lenght#=5 ; this will define the lenght of the beams
;vertical_on=1 ; this will turn on/off vertical quads
;horizontal_on=1 ; this will turn on/off horizontal quads
Function CreateSunbeams(texpath$,transp=40,numsurfx#=5,numsurfy#=5,zoom#=1.0,height#=-1.0,lenght#=3.0,vertical_on=1,horizontal_on=1)

 tex=LoadTexture(texpath$) ; used for "glass"
 tex2=LoadTexture(texpath$,2) ; used for beams

 ; amplyfy beam-significant texels
 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 Then
    a = transp 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 BackBuffer()

 ; window glass mesh
 win=CreateQuad()
 EntityTexture win,tex
 EntityFX win,1

 ; beams quads mesh
 mesh=CreateMesh()
 surf=CreateSurface(mesh)

 ;vertical beam quads
 If vertical_on
  For i=0 To numsurfx#
   where#=(((Float(i)-numsurfx)/numsurfx)*2.0)+1.0
   wherev#=(where#+1.0)/2.0
   v0=AddVertex(surf,-1.0,-1.0,where#,wherev,1.0 )
   v1=AddVertex(surf, 1.0*Lenght,-1.0+height,where#,wherev,1.0)
   v2=AddVertex(surf, 1.0*Lenght,1.0+height,where#,wherev,0.0)
   v3=AddVertex(surf,-1,1.0,where#,wherev,0.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

 ;horizontal beam quads
 If horizontal_on
  For i=0 To numsurfy#
   where#=(((Float(i)-numsurfy)/numsurfy)*2.0)+1.0
   wherev#=(where#+1.0)/2.0
   v0=AddVertex(surf,-1.0,where#,-1,1,-wherev )
   v1=AddVertex(surf, 1.0*lenght,where#*zoom+height,-1,1,-wherev )
   v2=AddVertex(surf, 1.0*lenght,where#*zoom+height,1,0,-wherev )
   v3=AddVertex(surf,-1.0,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

 UpdateNormals mesh
 EntityFX mesh,16 Or 1 Or 2
 EntityTexture mesh,tex2
 ;EntityBlend mesh,3
 TranslateEntity mesh,1,0,0
 EntityParent mesh,win
 Return win
End Function



Function CreateQuad()
  ; creates a quad, facing to the right side
  mesh=CreateMesh()
  surf=CreateSurface(mesh)
  v0=AddVertex(surf,0, -1.0,  -1.0, 0,1 )
  v1=AddVertex(surf,0,  1.0,  -1.0, 0,0 )
  v2=AddVertex(surf,0,  1.0,   1.0, 1,0 )
  v3=AddVertex(surf,0, -1.0,   1.0, 1,1 )
  AddTriangle(surf,v0,v1,v2)
  AddTriangle(surf,v2,v3,v0)
  UpdateNormals mesh
  Return mesh
End Function

Comments

puki2004
Ooh, another good code archive by "jfk" - based on image colours as well - very good stuff.


aCiD22004
Nicely done, you need to make the faded vertex's vary their alpha i think (in the main loop) to give the effect of the dust moving


xmlspy2004
Really cool!


Dabbede2004
veeeery cool!
... but I'm agree with aCiD2!


big10p2004
Amazing low-poly effect. Well done! ;)


TartanTangerine (was Indiepath)2004
now that is veeeery sweeet :)


Clyde2004
Remarkable mate!
Really clever stuff and a neat effect to boot :)

Cheers,
MIkey F


D4NM4N2004
the manīs a geeeeenius!!!


FireballStarfish2008
Very cool!!!
But you made a mistake nobody mentioned up to now ;)

Change the 4th parameter of the AddVertex-functions in the ";horizontal beam quads" section from -1 to 1 and vice versa. Then it works correctly :)
Because the way it is, the horizontal quads are "mirrored"... just take a high "transp" value and an asymetric texture (for example black with a white rect in one corner) and you will see what I mean ^^


_332008
FireballFlame, is this what you're talking about?
 ;horizontal beam quads
 If horizontal_on
  For i=0 To numsurfy#
   where#=(((Float(i)-numsurfy)/numsurfy)*2.0)+1.0
   wherev#=(where#+1.0)/2.0
   v0=AddVertex(surf,-1.0       ,where#,             1,1,-wherev )
   v1=AddVertex(surf, 1.0*lenght,where#*zoom+height, 1,1,-wherev )
   v2=AddVertex(surf, 1.0*lenght,where#*zoom+height,-1,0,-wherev )
   v3=AddVertex(surf,-1.0       ,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


Can't see what difference it makes... I'm also having difficulty using the parms in the CreateSunbeams function. Most of them don,t seem to be affecting anything.


FireballStarfish2008
Yes, thats what I mean. Here an example:

This is my test texture:


This is the original code:


This is the changed code:


Well, the parameters of CreateSunbeams:
1st: the texture used for the window the light shines through
2nd: intensity/alpha of the beams (0=invisible to 255=opaque)
3rd+4th: number of horizontal and vertical polygons used for the beams; optimal values depend on the texture and on how much performance you want to allow it to consume (with higher values the effect becomes more detailed but also more intense so you may have to lower the 2nd parameter)
6th: defines the angle of the beams (0=orthogonal to the texture, >0="up", <0="down")
7th: length/range of the beams

The other parameters are of minor importance imo.


plash2008
Can you post the updated version?


plash2008
EDIT: damn double post ;/


Naughty Alien2008
..I was wondering what would be the way to use this technique to create something like furr??


puki2008
"Beaker" did his furry balls.


Naughty Alien2008
do you have code maybe or some link? Im wondering how to do furry things, over custom shape, based on texture assigned on to it...that would be cool..


RemiD2016
nice effect, thanks !
(however why have you chosen this orientation for the window and the rays ? weird...)


jfk EO-111102016
Not sure what you are meaning. Maybe yours is looking diffrent. Here it's considered rather common when windows are vertical and sunbeams fall trough it in like eg. 30deg at 4 o clock pm. And this was ripped right out of hitman, so it can't be that weird ^^


RemiD2016
no i mean that the window and the rays are not oriented towards the +zaxis (like all entities are by default)

i have coded my own procedures to create a similar effect, i consider all colors of the texture of the windows and i only create a number of rays per color which is a percentage of the number of texels of this color.
see :

i have also added the flickering effect (by altering the alpha of the rays each xms) demonstrated by acid2

the problem that remains is if i use several colors in the same window/glass, then it is difficult to light/shade the room with all these colors (one lightsource per color) without having a weird blending (too bright colors)
maybe a solution would be to use global illumination to light/shade the room but it is slow to calculate...


jfk EO-111102016
instead of lighting or lightmapping the room, you may rather project the window to the wall, blurred and in additional blending. like a shadow, except that it's light.


RemiD2016
of course i could project a texture or a colored mesh on the walls of the room, but you will have to light the others areas of the room somehow, else it will be too dark...


jfk EO-111102016
Yes you need to find the right brightness. If you keep the indoor light a bit dark, it will add up fine, jus a little under white at max.

Unless you achieve realtime global illumination, there is no surfacecolor-selective diffuse reflection, but combining prerendered GI lightmaps with add-mode blended decals can work.


Code Archives Forum