Vertex lighting.

Blitz3D Forums/Blitz3D Programming/Vertex lighting.

Vertigo(Posted 2007) [#1]
I know this may sound lame. But does anyone know of a blitz source or lib that does simple vertex lighting. Ala, I make a .x model that has lighting info and have it be loaded and manipulated. Basically im looking for a half-dynamic way of using mulitple(more than 7) lights in a given scene. Light mapping drives me crazy due to the time and the static nature of it... sure it looks nicer, but im more concerned about quick and dirty lighting and blitz' built in light just dont seem to cut it.


MadJack(Posted 2007) [#2]
\/Ert|g0

This from the code archives
http://www.blitzbasic.com/codearcs/codearcs.php?code=284

However there is a catch. To use vertex lighting, each mesh must be unique, i.e. you can't vertex light a copied entity as each copied entity takes its (vertex) lighting from the source mesh rather than show its own lighting.

Unfortunately one of the key methods in keeping framerates up is to keep the number of surfaces in a scene to a minimum. Each unique mesh (e.g. loadmesh or copymesh) adds to the total surface count. Copyentity simply references the source mesh and does not add to the surface count.


OrcSlayer(Posted 2007) [#3]
Actually, from what I understand, copyentity DOES add to the surfacecount, hence why single surface particle systems have to be so complex and merge everything into a single mesh, rather than simply copying particles with copyentity...

However, it seems a copied entity uses no additional memory, unlike loading the mesh over and over again does.

Anyone know if this is correct? I'm pretty sure that's the way it works...


MadJack(Posted 2007) [#4]
My understanding is that particle systems are single surface to avoid the huge numbers of separate entities that would be required e.g. 100's to 1000's


Jasu(Posted 2007) [#5]
Particle systems avoid using multiple surfaces, not multiple entities.

http://www.blitzbasic.com/Community/posts.php?topic=41648#467889

CopyEntity does always add a new surface at least for sprites. That's why intense particle systems shouldn't use it. I'd think CopyEntity for meshes works the same way but I'm not sure since I havn't tested it.


Sledge(Posted 2007) [#6]
We've done this a few times -- seems that copyentity() is faster than creating something new from scratch but not as fast as a manual single-surface system.

When I wrote Ice-Teroids I used copyentity() on a source mesh to create particles and the surface handle for each was the same. See this:



EDIT: Slightly updated to show handle difference in created entities' surfaces.


MadJack(Posted 2007) [#7]
Sledge

Thanks for the code - I guess the lesson here is that it is important to use copyentity to keep framerates up.

I found this in my own game where I was getting some brilliant multi-lighting effects (8+) using vertex lighting, but the framerate was dropping heavily due to the number of unique meshes I was using.


Vertigo(Posted 2007) [#8]
Ok for the most part that worked, however im having some issues. Any particular reason why the colors are almost negated? EG: Mapping the color everywhere BUT where the light/radius is? Also is this a good solution for using multiple lights? And what kind of speed impact will this have with multiple lights against multiple surfaces? Any idea what the limit would be?



Function light_it_up(model)

	s=GetSurface(model,1)

For L.lamp=Each lamp

	For i=1 To CountVertices(s)-1

		TFormPoint VertexX(s,i),VertexY(s,i),VertexZ(s,i),model,0
		xd#=TFormedX()-EntityX(L\x)
		yd#=TFormedY()-EntityY(L\Y)
		zd#=TFormedZ()-EntityZ(L\Z)
		dist#=Sqr(xd*xd + yd*yd + zd*zd)*radius		

		If dist<0 Then dist=0
		If dist>255 Then dist=255
		
		VertexColor s,i,L\R - dist,L\G - dist,L\B - dist

	Next

Next

End Function





Stevie G(Posted 2007) [#9]
For better speed I would do a bounding check to see if the mesh is in range based on a sphere which covers it's entire area.

Note that you should also be calculating the dot product of the light vector and the vertex normal to see which vertices are actually facing the light.

If you're using linear falloff it'd also be better to clamp the r,g & b to zero if less than zero.

Stevie


Vertigo(Posted 2007) [#10]
The bounding check was a given, I have another function to check each model, if its inside the light range then it calls the above function. The problem I have is that the type that im creating has RGB values and its a "lamp". When I use the above, it seems I can only use one color at a time.

IE:

; This works
; If I Set L's Green value to something and ignore R and B values.

VertexColor s,i,Amblight,Amblight+ L\G - dist,Amblight


; This goes whacky and the colors arent correct at all.

VertexColor s,i,Amblight+ L\R - dist,Amblight+ L\G - dist,Amblight+ L\B - dist



Any ideas?

Also... to a textured model... How do I apply white to it? For example if I have a bright yellow color to it, and I apply a max lighting, that yellow should turn almost completely white, and it just stays yellow. Any easy way to add highlights?

Thanks guys.


Vertigo(Posted 2007) [#11]
Also how would I calculate the dot product of the light vector and the vertex normal to see which vertices are actually facing the light?


Stevie G(Posted 2007) [#12]
Something like this ...

;tform normal into Global coords 
TFormNormal VertexNX( s, i ) , VertexNY( s, i ) , VertexNZ( s, i ), model, 0
Nx# = TFormedX() : Ny# = TFormedY() : Nz# = TFormedZ()
TFormNormal 0,0,1, LIGHT, 0
Lx# = TFormedX() : Ly# = TFormedY() : Lz# = TFormedZ()

;dot product
Dot# = Lx * Nx + Ly * Ny + Lz * Nz

If Dot > 0 			
	;apply light
End If


Also, you need to be adding the new light color to the existing vertex colors otherwise previous lights are overwritten.

Have you considered using lightmesh? You can simulate mutiple lights and colours with this pretty well ...

Graphics3D 640,480 ,16,1 
camera=CreateCamera() 

ent=CreateSphere() 
EntityFX ent,2 ; enable vertex colors 
LightMesh ent,-255,-255,-255 ; reset vertex colors from 255,255,255 (default) to 0,0,0 
LightMesh ent,128,128,0,50,-20,20,-20 ; apply fake lighting yellow
LightMesh ent,0,0,255,50,20,20,-20 ; apply fake lighting dark blue


MoveEntity camera,0,2,-10 
PointEntity camera,ent 

While Not KeyDown(1) 
RenderWorld 
Flip 
Wend 
End 



Stevie


Vertigo(Posted 2007) [#13]
I guess I just dont understand the whole vertex lighting thing haha. Ok, well I had originally thought of using Lightmesh, however, each model I have that animates is made up of several parts. Ie Hand, Forearm, Upper Arm are all different meshes. I do not like using children as I swap these parts frequently and end up getting errors etc(plus I just dont like searching through them). Grouping them to the same mesh doesnt work either as I lose control of the individual parts orientation and positions. With lightmesh I get a gradient that effects EACH part of the mesh. So with the above example I would get yellow on one end of the hand, blue on the other.... then yellow again on the forearm instead of blue like it should as it should flow. Any suggestions?


Stevie G(Posted 2007) [#14]
Can you e-mail me your code and detailed description of what your trying to do?


Danny(Posted 2007) [#15]
Hi vertigo, I haven't read all in the thread so might be stating what's been said before.

I also use a vertex lighting system on my static meshes. Which looks 'ok' - not fab, but I'm happy with it.
It would obviously be way too slow to light my dynamic meshes in a similar way (or to have dynamic lights), so for my dynamic entities I use the same routine, except aaplying the lighting result to individual vertices I use it to 'light' each mesh seperatly - using Entitycolor I can darken, lighten and even color my dynamic meshes in real-time (leaving the static set untouched). This works quite ok. So when a character walks from the outside (sun light) into a building (dark), it nicely changes shade...
Might be an idea?!

I made a routine GetLightColorAt(x,y,z) and returns an rgb value (checking all available lights, their individual color, range, shape, intensity and shadow casting options - and returns a net RGB value, I can post a copy if you like). With vertex lighting I apply the rgb to a vertex, for the entity I use the same routine but apply it with EntityColor.

Also, lighting my set (with ""ray-traced"" shadows) takes about 2 minutes. But once rendered, I save each vertex's rgb to a file. Loading this back, and simply re-applying it with a for..next loop takes less than a second!!!

D.


Vertigo(Posted 2007) [#16]
Stevie, I appreciate the help, but there is no code haha. My engine is huge and quite portable, but there is no lighting. I just finished the scripting language and started working on building levels. i have place holders and can manipulate them however I want, but I was wanting to write a "plug in" lighting solution to light the levels... as well as to have a solution to light up character model parts as they get near these "lit zones".

Danny. What youre describing with the lighting set saving all the values to a file and then reloading sounds exactly like what im looking for as far as the static levels are concerned, and honestly using entity color would give performance and a cheap but effective work around. Whatever you'd be willing to post would be greatly appreciated.