Multiple vertex lights

Blitz3D Forums/Blitz3D Programming/Multiple vertex lights

Ferret(Posted 2005) [#1]
Hi,

I started experimenting with vertex lighting with a example from the code archives. This had 1 light and i made changes for multiple lights.
Now it still works with 1 light but with multiple lights they cancel eachother out.
How can i get the right light value?

Code:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Based on the code example for Stellar. By rob cummings (rob@...). ;;
;; Code archives/3D Graphics - Misc/MathLights                                ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

HidePointer:AppTitle "Lights"
Graphics3D 640,480,16,2

camera=CreateCamera()
CameraRange camera,1,5000
PositionEntity camera,0,150,0
RotateEntity camera,90,0,0

Type FDLight
	Field ent
End Type

Type FDReciever
	Field ent
End Type

Global radius=8 ; higher radius = smaller light - crazy but true here!
Global TestLight = F3D_CreateLight(50,0,0)
;Global TestLight2 = F3D_CreateLight(-50,0,0)
;EntityParent TestLight2,TestLight

Global TestEnt=CreateSphere(32)
ScaleEntity TestEnt,20,20,40
EntityFX TestEnt,2+1
F3D_CreateReciever(TestEnt)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
While Not KeyHit(1)
	;Move the lights
	MoveEntity TestLight,MouseXSpeed(),0,-MouseYSpeed()
	MoveMouse GraphicsWidth()/2,GraphicsHeight()/2
	
	;Update all lights
	F3D_UpdateLights()
	
	UpdateWorld()
	RenderWorld()
	Text 0,0,"Move the mouse to move the light"
	Flip(False)
Wend
End
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Function F3D_CreateLight(x,y,z)
	l.fdlight = New fdlight
	l\ent = CreateSphere() ;use createpivot()
	EntityFX l\ent,1
	MoveMouse GraphicsWidth()/2,GraphicsHeight()/2
	PositionEntity l\ent,x,y,z
	Return l\ent
End Function
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Function F3D_CreateReciever(ent)
	r.fdreciever = New fdreciever
	r\ent = ent
	Return r\ent
End Function
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Function F3D_UpdateLights()
	For l.fdlight = Each fdlight
		For r.fdreciever = Each fdreciever
			;Calculate vertex colors
			s=GetSurface(r\ent,1)
			For i=1 To CountVertices(s)-1
				TFormPoint VertexX(s,i),VertexY(s,i),VertexZ(s,i),r\ent,0
				xd#=TFormedX()-EntityX(l\ent)
				yd#=TFormedY()-EntityY(l\ent)
				zd#=TFormedZ()-EntityZ(l\ent)
				dist#=Sqr(xd*xd + yd*yd + zd*zd)*radius		
				VertexColor s,i,0,0,255-dist ;How to get the right value???
			Next
		Next
	Next
End Function
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



octothorpe(Posted 2005) [#2]
Light follows the Inverse Square Law as it gets dimmer the farther away it is from a point source. The simplified version of the formula is: intensity = source_strength / distance^2.

Also, you'll want to sum together the intensities of all lights illuminating a vertex. This would probably be easier if you looped over the lights for each vertex instead of the other way around.


Ferret(Posted 2005) [#3]
So if i'm righ i just add a range parameter to the lights and sum them together.
intensity = (range / distance^2) / number of lights
And i got the right value?


octothorpe(Posted 2005) [#4]
Why would you divide by the total number of lights? All existing lights would become dimmer every time you add a new one.

The following code assumes you'll add a "source_strength" field to FDLight instead of using a global for light strength.

Function F3D_UpdateLights()
	For r.fdreciever = Each fdreciever
		;Calculate vertex colors
		s=GetSurface(r\ent,1)
		For i=1 To CountVertices(s)-1
			TFormPoint VertexX(s,i),VertexY(s,i),VertexZ(s,i),r\ent,0
			local intensity# = 0
			For l.fdlight = Each fdlight
				xd#=TFormedX()-EntityX(l\ent)
				yd#=TFormedY()-EntityY(l\ent)
				zd#=TFormedZ()-EntityZ(l\ent)
				dist#=Sqr(xd*xd + yd*yd + zd*zd)*radius
				intensity = intensity + l\source_strength / (xd*xd + yd*yd + zd*zd) ; ()=distance^2
			Next
			if intensity > 255 then intensity = 255
			VertexColor s,i,intensity,intensity,intensity
		Next
	Next
End Function


Implementing multi-coloured lights (r,g,b) should be trivial.


Ferret(Posted 2005) [#5]
Thank you so much, got colored lights working to :)
I also got a animated shadows working, maybe i should post both in the code archives?


Danny(Posted 2005) [#6]
yeah sounds cool ferret! would love to see that!


Ferret(Posted 2005) [#7]
Sorry for the late reply.

Its a system now :), verry easy to use like,
CretaeLight()
CreateReciever()
UpdateLights()

And some functions to control the lights in realtime.
I'm putting it in a showcase with a nice demo and will put a link here for you.


Ferret(Posted 2005) [#8]
Here is the link:
http://www.codersworkshop.com/viewshowcase.php?id=640


Danny(Posted 2005) [#9]
cheers dude, checking it out now..