The 'Stencil shadow' thread

Blitz3D Forums/Blitz3D Programming/The 'Stencil shadow' thread

Hello everybody!

You might remember me and DareDevil... we are the developer of the DevilShadowSystem

Worklog to the new 0.6Beta release: www.blitzbasic.com/logs/userlog.php?user=8270&log=660

So i decided to create a 'stencil shadow' thread. If you have any shadow systems in development or any questions about stencils, post them HERE!

This is the stencil shadow thread.

Regards...

Don't know why your link doesn't work, here is one that should.


http://www.blitzbasic.com/logs/userlog.php?user=8270&log=660

oops, edited, sry!

Is there any reason why I get about 30 fps for the other demos but only 4-6 fps for the busts?

yes, your computer is slow, OR you have still turned the debugger on :)

Wow, turning the debugger off helps...;)

WOW!
60 FPS for everything except the "game" one with the complicated room, which starts stays around 60 but drops to 50 on occasion.

Athlon XP 2500+ (1.8 GHz), Radeon 9600 Pro, 1280 MB RAM, and Windows XP Professional.

I think you should have a few more demos of shadows casting onto uneven surfaces in there. Currently the only ones that show that are the tank one and the Swifty clone one.
A staircase would be a nice showcase :)

1 - 16-20 fps
2 - 16 fps
3 - 8 fps
4 - 8 fps
5 - 4 fps
6 - 10 fps

These results from my laptop with crappy integrated Intel82855/82855GM GPU (debug off). I'm amazed that demos worked flawlessly although fps was not that great :)

Hey Devils Child, Great work (so far).

A quick question if I may, what is the shw file in this line please?

SetShadowMesh(Caster, True, "Media\Warrior.shw")

IPete2.

G R E A T W O R K

@Ipete2: It uses a file .shw to save the info about the shadows as Devils said in his worklog - or I think.

thx for compliments :)

the shw file:

before a caster can cast a volume, he has to initialise the volum caster... this takes 20 secounds for 5.000 polys. Then he saves the 'hacked' data into a file and afterwards he doesnt have to hack the mesh again! he just reads out of this file which is 100-100.000 times faster :)

How about a command refferecne?

InitShadows(Camera) Initialises the shadows. The first command which should be called!
FreeShadows() deletes everything about the shadows.
SetShadowColors(alpha#, r, g, b) Alphe sets the shadow alpha and rgb decides about the shadow colors(should be between 0,0,0 and 40,40,40 at all the times !)
SetShadowLight(ent) Light caster! If you set a secon one, the old one will be automaticly deleted!
SetShadowMesh(ent, casting, path$) - set a shadow mesh. if casting = true then it is a caster and a receiver. otherwise it is a receiver only. when you set a path he writes the informations about the caster down there(this is for the InitTime faster!!!!)
Render(mode) use this instead of renderworld and updateworld. mode0 = no shadows; mode1 = shadows; mode2 = debugmode, volumes only.

do not toucxh any other functions casue the are internal functions. setshadowcaster() is an internal function(for example)

have fun:)

Is this using the new algorithms from here?

yes, it is using the third one, but after initvolumecaster() he saves the caster's informations into a file(faster)!

the shadow volume algorithm is by DareDevil, and optimized by me, so i cant take all the credits :)

btw: where is daredevil again? a big part of this shadow system is by him!!!

I guess that' s the most complete stecil shadows implementation for BLitz3D so far, is it?
Great Job!

Tjo, I also like your work, Devils Child! (=

By the way: What's about integrating depth fail? http://en.wikipedia.org/wiki/Shadow_volume#Depth_fail
(Oha, I just read that there's a patent on the method.. )

..this is very nice, but its still far away from real use..I hope you'll make it faster..

thx inarie :)
it has 60% of the speed of andreymans fx libary yet! i think we wont speed it up, we rather solve the bugs!

inarie: i cant take all the credits... DareDevil is wokring on the shadow volumes, but he is disappeared yet!?

Great job devil :) !

But i have a question ? do you plan to increase the shadow rendering on curved surface ? because stencil shadow on
a sphere draw some strange stuff :)

Continue this great lib !

what you mean filax is soft self shadowing. i dont know how it works, but the only thing left to do is improve shadow rendering!

but maybee i can make ENBM work in our system... :)

seems like stencil shadows and ENBM doesnt like each other :(

Maybe this links help you ? :)

http://www.devmaster.net/articles/shadow_techniques/

http://graphics.cs.lth.se/theses/projects/shadows/so_thesis_lq.pdf

http://www.devmaster.net/articles/shadows/

http://www.gamedev.net/reference/articles/article1873.asp

http://www.gamedev.net/community/forums/topic.asp?topic_id=133985

http://www.3dkingdoms.com/weekly/weekly.php?a=28

http://www.racer.nl/tutorial/shadows.htm

thanks filax, just checking them out, but i dont think i can improve shadow rendering. the only one who can, is tom!

common tom, let us see you shadow rendering algorith(i mean that one, where are no problems with the camera_inside_volume)

öhm, i've been trying to integrate your shadow system into a game of mine (just for a test.. ^^), but öhm, the shadow caster entities aren't rendered at all and every other entity except for my sky cube quad and some few other ones is black. öhm, i guess that you change some rendermodes in a way i don't understand. (i have no clue regarding all these renderstates xD) have you any idea what has to be changed? (the volume building seems to work... render(2) works fine)

ah, and one other thing: how to set a parallel light source? (this of course will only be of interest for me, if you can help me make the shadows working at all ^^)


But i have a question ? do you plan to increase the shadow rendering on curved surface ? because stencil shadow on
a sphere draw some strange stuff :)


It's the self-shadowing that's a bit poppy, isn't it? It would be nice to be able to toggle that off, but this is splendid stuff regardless.

@inarie

every entity in the space must be at least a shadow receiver. and remember: you can set as many receivers as you want, it is no speedloss

just check out the next update which will come in 5 minutes :)
SetShadowLight(entity, parallel = False)

UPDATE FOR PARALLEL LIGHT:

DevilShadowSystem.bb
Include "Includes\ShadowVolumes.bb"
Include "Includes\DX7Const.bb"

Type ShadowMesh
	Field ent, casting
End Type
Type ShadowLight
	Field ent, parallel
End Type
Global ShadowCam, ShadowPlane
Global Debug_TimeRender, Debug_TimeInitVolumes, Debug_TimeVolumesBuilt, Debug_ShadowPolys

Function InitShadows(Cam)
ShadowCam = Cam
;ShadowPlane
ShadowPlane = CreateSprite()
ScaleSprite ShadowPlane, 10, 10
EntityParent ShadowPlane, ShadowCam, 0
MoveEntity ShadowPlane, 0, 0, GetCamRangeStart(ShadowCam) + .001
;Volumes
InitVolumes()
;Init DirectX7
If DX7_SetSystemProperties(SystemProperty$("Direct3D7"), SystemProperty$("Direct3DDevice7"), SystemProperty$("DirectDraw7"), SystemProperty$("AppHWND"), SystemProperty$("AppHINSTANCE")) Then RuntimeError "Error initializing dx7."
If DX7_GetStencilBitDepth() < 8 Then
	DX7_CreateStencilBuffer()
	If DX7_GetStencilBitDepth() < 8 Then RuntimeError "Graphic card does not support stencil buffers."
End If
;Misc
Debug_TimeInitVolumes = 0
SetShadowColors(.5, 0, 0, 0)
End Function

Function FreeShadows()
DX7_RemoveSystemProperties()
FreeVolumes()
Delete Each ShadowMesh
Delete Each ShadowLight
End Function

Function SetShadowColors(alpha#, r = 0, g = 0, b = 0)
If alpha# < 0 Then alpha# = 0
If alpha# > .99 Then alpha# = .99
EntityAlpha ShadowPlane, alpha#
If r < 0 Then r = 0 ElseIf r > 255 Then r = 255
If g < 0 Then g = 0 ElseIf g > 255 Then g = 255
If b < 0 Then b = 0 ElseIf b > 255 Then b = 255
EntityColor ShadowPlane, r, g, b
End Function

Function SetShadowLight(ent, parallel = False)
Delete Each ShadowLight
sl.ShadowLight = New ShadowLight
sl\ent = ent
sl\parallel = parallel
End Function

Function SetShadowMesh(ent, casting = True, path$ = "***")
If casting Then
	ms = MilliSecs()
	RecursiveShadowCaster(ent, path$)
	Debug_TimeInitVolumes = Debug_TimeInitVolumes + MilliSecs() - ms
Else
	sm.ShadowMesh = New ShadowMesh
	sm\ent = ent
EndIf
End Function

Function RecursiveShadowCaster(ent, path$, file = -1)
If FileType(path$) = 1 Then
	LoadVolumeCaster(ent, path$)
Else
	If file = -1 And path$ <> "***" Then file = WriteFile(path$)
	sm.ShadowMesh = New ShadowMesh
	sm\ent = ent
	sm\casting = True
	InitVolumeCaster(sm\ent)
	If file <> - 1 Then
		For etem.ETE_Mesh = Each ETE_Mesh
			If etem\ent = sm\ent Then
				cnt_tris = etem\cnt_tris
				WriteInt file, cnt_tris
				For v = 0 To cnt_tris
					tri.ETE_Triangle = etem\tri[v]
					v1.Point3D = tri\v1
					v2.Point3D = tri\v2
					v3.Point3D = tri\v3
					WriteFloat file, v1\x#
					WriteFloat file, v1\y#
					WriteFloat file, v1\z#
					WriteFloat file, v2\x#
					WriteFloat file, v2\y#
					WriteFloat file, v2\z#
					WriteFloat file, v3\x#
					WriteFloat file, v3\y#
					WriteFloat file, v3\z#
					WriteFloat file, tri\nx#
					WriteFloat file, tri\ny#
					WriteFloat file, tri\nz#
					WriteInt file, tri\tri
					WriteInt file, tri\ta
					WriteInt file, tri\tb
					WriteInt file, tri\tc
				Next
			EndIf
		Next
	EndIf
	cnt_children = CountChildren(ent)
	If cnt_children = 0 Then Return
	For i = 1 To cnt_children
		RecursiveShadowCaster(GetChild(ent, i), "***", file)
	Next
EndIf
End Function

Function Render(mode = 0, tween# = 1)
Select mode
	Case 0, 2
		ClearSurface VolumeSurf
		If mode = 2 Then
			BuildVolumes()
			ShowEntity VolumeMesh
			EntityFX VolumeMesh, 17
			EntityAlpha VolumeMesh, .5
		EndIf
		For sm.ShadowMesh = Each ShadowMesh
			ShowEntity sm\ent
		Next
		HideEntity ShadowPlane
		CameraClsMode ShadowCam, True, True
		ms = MilliSecs()
		UpdateWorld
		RenderWorld tween#
		Debug_TimeRender = MilliSecs() - ms
		If mode = 0 Then
			Debug_TimeVolumesBuilt = 0
			Debug_ShadowPolys = 0
		EndIf
	Case 1
		EntityFX VolumeMesh, 0
		EntityAlpha VolumeMesh, .0001
		ms = MilliSecs()
		RenderShadows(tween#)
		Debug_TimeRender = MilliSecs() - ms - Debug_TimeVolumesBuilt
	Default
		RuntimeError "Wrong render mode."
End Select
End Function

Function RenderShadows(tween#)
HideEntity ShadowPlane
HideEntity VolumeMesh
For sm.ShadowMesh = Each ShadowMesh
	ShowEntity sm\ent
Next
DX7_SetRenderState(D3DRS_ZWRITEENABLE, True)
DX7_SetRenderState(D3DRS_STENCILENABLE, False)
DX7_SetRenderState(D3DRS_ALPHABLENDENABLE, False)
DX7_DeviceClear(7, $00008080, 1, 0)
CameraClsMode ShadowCam, True, True
UpdateWorld
RenderWorld tween#
CameraClsMode ShadowCam, False, False
BuildVolumes()
For sm.ShadowMesh = Each ShadowMesh
	HideEntity sm\ent
Next
ShowEntity VolumeMesh
DX7_SetRenderState(D3DRS_ZWRITEENABLE, False)
DX7_SetRenderState(D3DRS_STENCILENABLE, True)
DX7_SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS)
DX7_SetRenderState(D3DRS_STENCILREF, 1)
DX7_SetRenderState(D3DRS_STENCILMASK, $FFFFFFFF)
DX7_SetRenderState(D3DRS_STENCILWRITEMASK, $FFFFFFFF)
DX7_SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW)
DX7_SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP)
DX7_SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP)
DX7_SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_INCR)
DX7_SetRenderState(D3DRS_ALPHABLENDENABLE, True)
DX7_SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO)
DX7_SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE)
RenderWorld tween#
DX7_SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_DECR)
DX7_SetRenderState(D3DRS_CULLMODE, D3DCULL_CW)
RenderWorld tween#
DX7_SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW)
HideEntity VolumeMesh
DX7_SetRenderState(D3DRS_ZWRITEENABLE, True)
DX7_SetRenderState(D3DRS_STENCILENABLE, False)
DX7_SetRenderState(D3DRS_ALPHABLENDENABLE, False)
DX7_SetRenderState(D3DRS_ZENABLE, False)
DX7_SetRenderState(D3DRS_STENCILENABLE, True)
DX7_SetRenderState(D3DRS_ALPHABLENDENABLE, True)
DX7_SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA)
DX7_SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA)
DX7_SetRenderState(D3DRS_STENCILREF, 1)
DX7_SetRenderState(D3DRS_STENCILFUNC, D3DCMP_LESSEQUAL)
DX7_SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE)
ShowEntity ShadowPlane
RenderWorld tween#
DX7_SetRenderState(D3DRS_ZENABLE, True)
DX7_SetRenderState(D3DRS_STENCILENABLE, False)
DX7_SetRenderState(D3DRS_ALPHABLENDENABLE, True)
HideEntity ShadowPlane
DX7_SetRenderState(D3DRS_ALPHABLENDENABLE, False)
End Function

Function BuildVolumes()
ms = MilliSecs()
sl.ShadowLight = First ShadowLight
ClearSurface VolumeSurf
CreateVolume(sl\ent, sl\parallel)
Debug_ShadowPolys = CountTriangles(VolumeSurf)
Debug_TimeVolumesBuilt = MilliSecs() - ms
End Function


ShadowVolumes.bb
Type ETE_Mesh
	Field ent
	Field cnt_tris, tri.ETE_Triangle[ETE_MaxTriang]
End Type
Type ETE_Triangle
	Field v1.Point3D, v2.Point3D, v3.Point3D, nx#, ny#, nz#
	Field tri, ta, tb, tc
End Type
Type Point3D
	Field x#, y#, z#
End Type
Const ETE_MaxTriang = 65000
Global VolumeMesh, VolumeSurf
Dim TriangleClone.ETE_Triangle(ETE_MaxTriang)

Function InitVolumes()
For i = 0 To ETE_MaxTriang
	TriangleClone.ETE_Triangle(i) = New ETE_Triangle
	TriangleClone(i)\v1 = New Point3D
	TriangleClone(i)\v2 = New Point3D
	TriangleClone(i)\v3 = New Point3D
Next
VolumeMesh = CreateMesh()
VolumeSurf = CreateSurface(VolumeMesh)
EntityColor VolumeMesh, 255, 0, 0
EntityAlpha VolumeMesh, .5
EntityFX VolumeMesh, 17
End Function

Function FreeVolumes()
Delete Each ETE_Mesh
Delete Each ETE_Triangle
Delete Each Point3D
If VolumeMesh Then FreeEntity VolumeMesh
End Function

Function InitVolumeCaster(ent, file = -1)
Local ad1[ETE_MaxTriang], ad2[ETE_MaxTriang], ad3[ETE_MaxTriang]
copy = SingleSurfaceMesh(ent)
etem.ETE_Mesh = New ETE_Mesh
etem\ent = ent
surf = GetSurface(copy, 1)
cnt_tris = CountTriangles(surf) - 1
etem\cnt_tris = cnt_tris
For v = 0 To cnt_tris
	etem\tri[v] = New ETE_Triangle
	etet.ETE_Triangle = etem\tri[v]
	etet\v1 = New Point3D
	etet\v2 = New Point3D
	etet\v3 = New Point3D
	v1.Point3D = etet\v1
	v2.Point3D = etet\v2
	v3.Point3D = etet\v3
	vert0 = TriangleVertex(surf, v, 0)
	vert1 = TriangleVertex(surf, v, 1)
	vert2 = TriangleVertex(surf, v, 2)
	v1\x# = VertexX(surf, vert0)
	v1\y# = VertexY(surf, vert0)
	v1\z# = VertexZ(surf, vert0)
	v2\x# = VertexX(surf, vert1)
	v2\y# = VertexY(surf, vert1)
	v2\z# = VertexZ(surf, vert1)
	v3\x# = VertexX(surf, vert2)
	v3\y# = VertexY(surf, vert2)
	v3\z# = VertexZ(surf, vert2)
	e0x# = v3\x# - v2\x#
	e0y# = v3\y# - v2\y#
	e0z# = v3\z# - v2\z#
	e1x# = v2\x# - v1\x#
	e1y# = v2\y# - v1\y#
	e1z# = v2\z# - v1\z#
	etet\nx# = e0y# * e1z# - e0z# * e1y#
	etet\ny# = e0z# * e1x# - e0x# * e1z#
	etet\nz# = e0x# * e1y# - e0y# * e1x#
	etet\tri = v
	etet\ta = -1
	etet\tb = -1
	etet\tc = -1
	ad1[v] = True
	ad2[v] = True
	ad3[v] = True
Next
For a = 0 To cnt_tris
	ATriang.ETE_Triangle = etem\tri[a]
	v1 = ATriang\v1
	v2 = ATriang\v2
	v3 = ATriang\v3
	For b = a + 1 To cnt_tris
		state1 = ad1<b>
		state2 = ad2[b]
		state3 = ad3[b]
		If a <> b And (state1 Or state2 Or state3) Then
			BTriang.ETE_Triangle = etem\tri[b]
			v2A.Point3D = BTriang\v1
			v2B.Point3D = BTriang\v2
			v2C.Point3D = BTriang\v3
			If state1 Then
				If CheckLine(v1, v2A, v2, v2B) Then
					ATriang\ta = b
					BTriang\ta = a
					ad1[b] = False
					Goto SIDEA
				EndIf
			EndIf
			If state2 Then
				If CheckLine(v1, v2B, v2, v2C) Then
					ATriang\ta = b
					BTriang\tb = a
					ad2[b] = False
					Goto SIDEA
				EndIf
			EndIf
			If state3 Then
				If CheckLine(v1, v2C, v2, v2A) Then
					ATriang\ta = b
					BTriang\tc = a
					ad3[b] = False
				EndIf
			EndIf
			.SIDEA
			If state1 Then
				If CheckLine(v2, v2A, v3, v2B) Then
					ATriang\tb = b
					BTriang\ta = a
					ad1[b] = False
					Goto SIDEB
				EndIf
			EndIf
			If state2 Then
				If CheckLine(v2, v2B, v3, v2C) Then
					ATriang\tb = b
					BTriang\tb = a
					ad2[b] = False
					Goto SIDEB
				EndIf
			EndIf
			If state3 Then
				If CheckLine(v2, v2C, v3, v2A) Then
					ATriang\tb = b
					BTriang\tc = a
					ad3[b] = False
				EndIf
			EndIf
			.SIDEB
			If state1 Then
				If CheckLine(v3, v2A, v1, v2B) Then
					ATriang\tc = b
					BTriang\ta = a
					ad1[b] = False
					Goto SIDEC
				EndIf
			EndIf
			If state2 Then
				If CheckLine(v3, v2B, v1, v2C) Then
					ATriang\tc = b
					BTriang\tb = a
					ad2[b] = False
					Goto SIDEC
				EndIf
			EndIf
			If state3 Then
				If CheckLine(v3, v2C, v1, v2A) Then
					ATriang\tc = b
					BTriang\tc = a
					ad3[b] = False
				EndIf
			EndIf
			.SIDEC
		EndIf
	Next
Next
FreeEntity copy
End Function

Function LoadVolumeCaster(ent, path$, file = -1)
If file = -1 Then file = ReadFile(path$)
sm.ShadowMesh = New ShadowMesh
sm\ent = ent
sm\casting = True
etem.ETE_Mesh = New ETE_Mesh
etem\ent = sm\ent
etem\cnt_tris = ReadInt(file)
For v = 0 To etem\cnt_tris
	etem\tri[v] = New ETE_Triangle
	etet.ETE_Triangle = etem\tri[v]
	tri.ETE_Triangle = etem\tri[v]
	tri\v1 = New Point3D
	tri\v2 = New Point3D
	tri\v3 = New Point3D
	v1.Point3D = tri\v1
	v2.Point3D = tri\v2
	v3.Point3D = tri\v3
	v1\x# = ReadFloat(file)
	v1\y# = ReadFloat(file)
	v1\z# = ReadFloat(file)
	v2\x# = ReadFloat(file)
	v2\y# = ReadFloat(file)
	v2\z# = ReadFloat(file)
	v3\x# = ReadFloat(file)
	v3\y# = ReadFloat(file)
	v3\z# = ReadFloat(file)
	tri\nx# = ReadFloat(file)
	tri\ny# = ReadFloat(file)
	tri\nz# = ReadFloat(file)
	tri\tri = ReadInt(file)
	tri\ta = ReadInt(file)
	tri\tb = ReadInt(file)
	tri\tc = ReadInt(file)
Next
cnt_children = CountChildren(ent)
For i = 1 To cnt_children
	LoadVolumeCaster(GetChild(ent, i), "", file)
Next
End Function

Function CreateVolume(light, parallel = False)
light_x# = EntityX(light, True) * (1 + parallel * 1000000)
light_y# = EntityY(light, True) * (1 + parallel * 1000000)
light_z# = EntityZ(light, True) * (1 + parallel * 1000000)
volume_lenght = 1000
For etem.ETE_Mesh = Each ETE_Mesh
	cnt_tris = etem\cnt_tris
	For v = 0 To cnt_tris
		etet.ETE_Triangle = TriangleClone(v)
		CloneTriangle(etet, etem\tri[v])
		v1.Point3D = etet\v1
		v2.Point3D = etet\v2
		v3.Point3D = etet\v3
		TFormPoint v1\x#, v1\y#, v1\z#, etem\ent, 0
		v1\x# = TFormedX()
		v1\y# = TFormedY()
		v1\z# = TFormedZ()
		TFormPoint v2\x#, v2\y#, v2\z#, etem\ent, 0
		v2\x# = TFormedX()
		v2\y# = TFormedY()
		v2\z# = TFormedZ()
		TFormPoint v3\x#, v3\y#, v3\z#, etem\ent, 0
		v3\x# = TFormedX()
		v3\y# = TFormedY()
		v3\z# = TFormedZ()
		TFormNormal etet\nx#, etet\ny#, etet\nz#, etem\ent, 0
		normlight_x# = (v1\x# + v2\x# + v3\x#) / 3.0 - light_x#
		normlight_y# = (v1\y# + v2\y# + v3\y#) / 3.0 - light_y#
		normlight_z# = (v1\z# + v2\z# + v3\z#) / 3.0 - light_z#
		If TFormedX() * normlight_x# + TFormedY() * normlight_y# + TFormedZ() * normlight_z# < 0 Then etet\tri = -1
	Next
	For v = 0 To cnt_tris
		etet = TriangleClone(v)
		If etet\tri => 0 Then
			ta = etet\ta
			tb = etet\tb
			tc = etet\tc
			If ta > -1 Then check1 = TriangleClone(ta)\tri Else check1 = -1
			If tb > -1 Then check2 = TriangleClone(tb)\tri Else check2 = -1
			If tc > -1 Then check3 = TriangleClone(tc)\tri Else check3 = -1
			If check1 < 0 Or check2 < 0 Or check3 < 0 Then
				v1 = etet\v1
				v2 = etet\v2
				v3 = etet\v3
				If check1 < 0 Then
					rax# = v1\x# + (v1\x# - light_x#) * volume_lenght
					ray# = v1\y# + (v1\y# - light_y#) * volume_lenght
					raz# = v1\z# + (v1\z# - light_z#) * volume_lenght
					rbx# = v2\x# + (v2\x# - light_x#) * volume_lenght
					rby# = v2\y# + (v2\y# - light_y#) * volume_lenght
					rbz# = v2\z# + (v2\z# - light_z#) * volume_lenght
					vert1 = AddVertex(VolumeSurf, v1\x#, v1\y#, v1\z#)
					vert2 = AddVertex(VolumeSurf, rax#, ray#, raz#)
					vert3 = AddVertex(VolumeSurf, rbx#, rby#, rbz#)
					vert4 = AddVertex(VolumeSurf, v2\x#, v2\y#, v2\z#)
					AddTriangle(VolumeSurf, vert1, vert2, vert3)
					AddTriangle(VolumeSurf, vert1, vert3, vert4)
				EndIf
				If check2 < 0 Then
					rbx# = v2\x# + (v2\x# - light_x#) * volume_lenght
					rby# = v2\y# + (v2\y# - light_y#) * volume_lenght
					rbz# = v2\z# + (v2\z# - light_z#) * volume_lenght
					rcx# = v3\x# + (v3\x# - light_x#) * volume_lenght
					rcy# = v3\y# + (v3\y# - light_y#) * volume_lenght
					rcz# = v3\z# + (v3\z# - light_z#) * volume_lenght
					vert1 = AddVertex(VolumeSurf, v2\x#, v2\y#, v2\z#)
					vert2 = AddVertex(VolumeSurf, rbx#, rby#, rbz#)
					vert3 = AddVertex(VolumeSurf, rcx#, rcy#, rcz#)
					vert4 = AddVertex(VolumeSurf, v3\x#, v3\y#, v3\z#)
					AddTriangle(VolumeSurf, vert1, vert2, vert3)
					AddTriangle(VolumeSurf, vert1, vert3, vert4)
				EndIf
				If check3 < 0 Then
					rax# = v1\x# + (v1\x# - light_x#) * volume_lenght
					ray# = v1\y# + (v1\y# - light_y#) * volume_lenght
					raz# = v1\z# + (v1\z# - light_z#) * volume_lenght
					rcx# = v3\x# + (v3\x# - light_x#) * volume_lenght
					rcy# = v3\y# + (v3\y# - light_y#) * volume_lenght
					rcz# = v3\z# + (v3\z# - light_z#) * volume_lenght
					vert1 = AddVertex(VolumeSurf, v1\x#, v1\y#, v1\z#)
					vert2 = AddVertex(VolumeSurf, rax#, ray#, raz#)
					vert3 = AddVertex(VolumeSurf, rcx#, rcy#, rcz#)
					vert4 = AddVertex(VolumeSurf, v3\x#, v3\y#, v3\z#)
					AddTriangle(VolumeSurf, vert1, vert3, vert2)
					AddTriangle(VolumeSurf, vert1, vert4, vert3)
				EndIf
			EndIf
		EndIf
	Next
Next
End Function

Function SingleSurfaceMesh(ent)
ret = CopyMesh(ent)
If CountSurfaces(ret) = 1 Then
	Return ret
Else
	FreeEntity ret
	ret = CreateMesh()
	new_surf = CreateSurface(ret)
	For s = 1 To CountSurfaces(ent)
		surf = GetSurface(ent, s)
		For t = 0 To CountTriangles(surf) - 1
			v0 = TriangleVertex(surf, t, 0)
			v1 = TriangleVertex(surf, t, 1)
			v2 = TriangleVertex(surf, t, 2)
			new_v1 = AddVertex(new_surf, VertexX(surf, v0), VertexY(surf, v0), VertexZ(surf, v0))
			new_v2 = AddVertex(new_surf, VertexX(surf, v1), VertexY(surf, v1), VertexZ(surf, v1))
			new_v3 = AddVertex(new_surf, VertexX(surf, v2), VertexY(surf, v2), VertexZ(surf, v2))
			AddTriangle new_surf, new_v1, new_v2, new_v3
		Next
	Next
	Return ret
EndIf
End Function

Function CloneTriangle(dst.ETE_Triangle, src.ETE_Triangle)
dst\v1\x# = src\v1\x#
dst\v1\y# = src\v1\y#
dst\v1\z# = src\v1\z#
dst\v2\x# = src\v2\x#
dst\v2\y# = src\v2\y#
dst\v2\z# = src\v2\z#
dst\v3\x# = src\v3\x#
dst\v3\y# = src\v3\y#
dst\v3\z# = src\v3\z#
dst\nx# = src\nx#
dst\ny# = src\ny#
dst\nz# = src\nz#
dst\tri = src\tri
dst\ta = src\ta
dst\tb = src\tb
dst\tc = src\tc
End Function

Function CheckLine(a1.Point3D, b1.Point3D, a2.Point3D, b2.Point3D)
c1 = (a1\x# = a2\x# And a1\y# = a2\y# And a1\z# = a2\z#)
c2 = (b1\x# = b2\x# And b1\y# = b2\y# And b1\z# = b2\z#)
c3 = (a1\x# = b2\x# And a1\y# = b2\y# And a1\z# = b2\z#)
c4 = (b1\x# = a2\x# And b1\y# = a2\y# And b1\z# = a2\z#)
If (c1 And c2) Or (c3 And c4) Then Return True Else Return False
End Function


[b]DX7Const.bb
Const D3DCULL_NONE = 1
Const D3DCULL_CW = 2
Const D3DCULL_CCW = 3
Const D3DSTENCILOP_KEEP = 1
Const D3DSTENCILOP_ZERO = 2
Const D3DSTENCILOP_REPLACE = 3
Const D3DSTENCILOP_INCRSAT = 4
Const D3DSTENCILOP_DECRSAT = 5
Const D3DSTENCILOP_INVERT = 6
Const D3DSTENCILOP_INCR = 7
Const D3DSTENCILOP_DECR = 8
Const D3DSTENCILOP_FORCE_DWORD = $7FFFFFFF
Const D3DCMP_NEVER = 1
Const D3DCMP_LESS = 2
Const D3DCMP_EQUAL = 3
Const D3DCMP_LESSEQUAL = 4
Const D3DCMP_GREATER = 5
Const D3DCMP_NOTEQUAL = 6
Const D3DCMP_GREATEREQUAL = 7
Const D3DCMP_ALWAYS = 8
Const D3DCMP_FORCE_DWORD = $7FFFFFFF
Const D3DBLEND_ZERO = 1
Const D3DBLEND_ONE = 2
Const D3DBLEND_SRCCOLOR = 3
Const D3DBLEND_INVSRCCOLOR = 4
Const D3DBLEND_SRCALPHA = 5
Const D3DBLEND_INVSRCALPHA = 6
Const D3DBLEND_DESTALPHA = 7
Const D3DBLEND_INVDESTALPHA = 8
Const D3DBLEND_DESTCOLOR = 9
Const D3DBLEND_INVDESTCOLOR = 10
Const D3DBLEND_SRCALPHASAT = 11
Const D3DBLEND_BOTHSRCALPHA = 12
Const D3DBLEND_BOTHINVSRCALPHA = 13
Const D3DBLEND_FORCE_DWORD = $7FFFFFFF
Const D3DRS_ANTIALIAS= 2
Const D3DRS_TEXTUREPERSPECTIVE = 4
Const D3DRS_ZENABLE = 7
Const D3DRS_FILLMODE = 8
Const D3DRS_SHADEMODE = 9
Const D3DRS_LINEPATTERN = 10
Const D3DRS_ZWRITEENABLE = 14
Const D3DRS_ALPHATESTENABLE = 15
Const D3DRS_LASTPIXEL = 16
Const D3DRS_SRCBLEND = 19
Const D3DRS_DESTBLEND = 20
Const D3DRS_CULLMODE = 22
Const D3DRS_ZFUNC = 23
Const D3DRS_ALPHAREF = 24
Const D3DRS_ALPHAFUNC = 25
Const D3DRS_DITHERENABLE = 26
Const D3DRS_ALPHABLENDENABLE = 27
Const D3DRS_FOGENABLE = 28
Const D3DRS_SPECULARENABLE = 29
Const D3DRS_ZVISIBLE = 30
Const D3DRS_STIPPLEDALPHA = 33
Const D3DRS_FOGCOLOR = 34
Const D3DRS_FOGTABLEMODE = 35
Const D3DRS_FOGSTART = 36
Const D3DRS_FOGEND = 37
Const D3DRS_FOGDENSITY = 38
Const D3DRS_EDGEANTIALIAS = 40
Const D3DRS_COLORKEYENABLE = 41
Const D3DRS_ZBIAS = 47
Const D3DRS_RANGEFOGENABLE = 48
Const D3DRS_STENCILENABLE = 52
Const D3DRS_STENCILFAIL = 53
Const D3DRS_STENCILZFAIL = 54
Const D3DRS_STENCILPASS = 55
Const D3DRS_STENCILFUNC = 56
Const D3DRS_STENCILREF = 57
Const D3DRS_STENCILMASK = 58
Const D3DRS_STENCILWRITEMASK = 59
Const D3DRS_TEXTUREFACTOR = 60
Const D3DCLEAR_TARGET = $00000001
Const D3DCLEAR_ZBUFFER = $00000002
Const D3DCLEAR_STENCIL = $00000004


Here's a demo of my effort, www.tomspeed.com/ss12.zip

w,s,a,d & mouse to move camera, lmb/rmb shadow alpha value, cursors & kepyad 1,0 moves light

Works with static geometry only at the moment, I'm just now looking for a solution for skinned meshes, but I don't think it's gonna be too fast whatever I end up with :)

If you leave the mouse alone when it boots, my FPS settles at 333 fps. 3ghz 32bit XP cpu, ATI x800 gfx card here.

Had some weird results from other people, like 81fps from an amd 800mhz cpu & radeon 9600 (not bad!) ... but only 24 - 40 fps from a 64bit amd 3500 with a I think an FX 5200 card ?!?!?

great job man :-)

can you please make it open source, or can you at least show
me the render code, because the rendering isnt that cute at my system :(...

i have just replaced the fan model with the scene of the swifty sample(i got 36 fps and 200 when SPACE pressed)

your shadow volume function is slow, and my rendering is rubish... how about a deal:

you can juse whatever you want of our system and i can youse your render function?

agree?

..hey Tom..this is something what can be used in real project..its seems to be very fast buddy..I hope skinned animated mesh will be supported and then..whoa..circle is rounded..by the way, this is results on my machine..

290-320 FPS
P4, 2.4 GHz, 1 Gig RAM, nVidia 5600FX, 256MB VRAM, Win XP Pro

As far as I know Tom released a stencil shadow source some time ago (well at least the BB source that was calling some dx stuff in a dx7test.dll). Tho I guess he improved it since then. Wasn't there a problem with some Graphicscards that are not creating a stencil buffer by default?

However, great work. This would be really nice, if you both add your work together.

The speed of stencil shadows isn't that great naturally (Of course, the faster you can make it, the better!). You have to deal with it. For example, higher poly meshes could use an invisible LOD clone for the volume creation. Additionally I'd suggest to use a priority flag for every caster: depending on the machines speed meshes with a certain lower priority won't cast shadows automaticly - or the user may choose a detail level manually.


Had some weird results from other people, like 81fps from an amd 800mhz cpu & radeon 9600 (not bad!) ... but only 24 - 40 fps from a 64bit amd 3500 with a I think an FX 5200 card ?!?!?



R9600PRO beats FX5200 and I think that plain 9600 does that too:





Just because it has FX in the name doesn't mean it's fast :)

http://www.bjorn3d.com/read.php?cID=264

"every entity in the space must be at least a shadow receiver." <- oh, that's definitely a problem... if i make every entity a receiver (i actually don't want my hud to receive shadows...), i'll also have to remove the receiver-entries when i use freeentiy... and i'll have to register new receivers and so on... is there really no other way? :/

Damn it, that'll teach me to type in a long post then accidentaly lose the page :|

Anyways, I'll post an updated DLL & info later, then start updating my worklog.

Inarie: That's not always the case don't worry. It'll just be how Devil has coded his system to work, maybe an oversight in his current method.

Devil: I'll pass on some info later to you. I finaly have a way to have full control of all render states, including (when it comes to stencil workflow) the all important ZWriteEnable & ZTestEnable.

The model from Swifts demo, do you mean beethoven? That thing is near 5000 polys! It would hit the frame rate in most shadow volume systems out there.

On another note, it's NOT a suitable mesh to test with as it's isn't a closed mesh. This causes rendering errors which is a bad idea when you're trying to code stencil shadow routines, you'll be blaming your code and searching for bugs that may not exist! :)

More later.
Tom

tom, this one looks great. i have to say again: you should team up with mark ;-)

Great work from both of you. If it can be made to work a bit faster I'd love to try this out in my verlet engine :)))

@ Tom / Devils CHild,

As you seem to be the Shadow specialists atm, a couple of questions ...

1. As JFK mentions, is it your intention to include the possibility of the system creating proxy shadow volumes based on a lower poly version of the mesh?

2. Again, on a similar note to Jfk, one thing which I've noticed in alot of games ( even some of the next gen stuff ) is that dynamic shadows appear to be disabled on objects which are over a certain distance from the camera .. such a feature would be great for slower systems.

3. With such systems and a static light source is it possible to render a static lightmap mesh which is included in the rendering process but not the volume building?

4. Can directional light sources be used with stencil shadows?

Cheers
Stevie

1. yes, i tried that a certain time ago and it looks really ugly!
2. you mean that object shoul cast their shadows only a few meters far, and that the self-shadowing of spheres should be improved... that is not so easy and i think it would need shaders!
3. maybe i include static objects when i have time for it :) let's see..
4. what you mean is parallel light, and this is supported in the update a few screens above(the 3 codeboxes are the include files!). it works pretty easy! he just moves the light source very far away from the scene. so it is a 99.9% parallel light

Re ..

1. It probably would look ugly if they also self-shadowed 'cos your visible mesh will be different. Without self-shadowing I'm sure they'd be fine.
2. Not as low as a a few metres and not really related to self shadowing. Simply a built in lod type thing to ensure that closer objects project shadows but those further than a certain threshold from the camera don't.
3. Fair enough. Looks forward to seeing what you do.
4. Ah ... never head it being called parallel light before and haven't tried the new demo.

Cheers
Stevie

1: In my own system, I've not looked at that yet.
2: That'd be easy to implement
3: Stencil shadows render on top of whatever other light you use, lots of games do it
4: Mine just does point lights at the moment, but same answer as #2.

wrote you a little email tom :)

Just tried this out, it runs great - nice work! ^-^
It's a shame that self shadowing is a bit 'poppy', but otherwise the results are great.

1. Is there any way to specific a specific mesh to have no self shadowing, but still cast and receive shadows?

2. Do you think it would it be possible to make this code work with vertex animated objects in future?

I think people are forgetting too, that alot of games don't cast shadows onto the actual geometry, but they create a less complex mesh to receive the shadows. A bit like creating a low poly version of your landscape, that is invisible and only used for collisions.

Shadow systems look great guys :o)

thx guys :)

@dock:
1. yes, it would be easy to impement, but nobody wants that :P
2. i guess not. i got too many problems with b3d animations!

@ Devils Child,

1. If it's easy then you should consider it as a user option. I for one would like to see it in 'cos some of that self shadowing can look awful on low poly meshes.

I can't deny that it had potential to be a great system though.

Stevie

1: Ditto - if it's easy to implement then it would be appreciated.

This topic is very good, everybody try to make something good shadow system.
But I don't understand the author of Blitz3D why not
give help or why not give shadow system at Blitz3D.
I like Blitz and this is an opinion only.
Today every lowcost gamemaker system (free engines too) has shadow system.

i want it! no self shadowing.... as an user option. this would be great.

Yes, selfshadowing is a plus thing optional, but a fast , simple shadow system would be very important

first at all i have to improve rendering, because all i will improve now, will be overwritten by the new render algorithm! thats the meaning of why it doesnt support it yet :P

The must important thing is the efficiency.
I was buy adreyman system for 25 $ but is very buggy
and slow and no support no anwers from the russian.
Now in a simple TPS action game are 3-6-8 lowpoly (cca. 1.500/model ) animated models in same time on scene.
The map ( 30.000 ), other dynamic objects ( 10.000).
A good shadowsystem can (must) render this with good 40 - 50 fps.

Right?

yes :) but this is not that easy, our system works takes 20 millisecs on 20.000 shadow polys! to initialise 20.000 polys it takes 1:20 minutes when you disable file-saving. when you enable: 110 millisecs. so you can say it is fast enough!


The model from Swifts demo, do you mean beethoven? That thing is near 5000 polys! It would hit the frame rate in most shadow volume systems out there.

On another note, it's NOT a suitable mesh to test with as it's isn't a closed mesh. This causes rendering errors which is a bad idea when you're trying to code stencil shadow routines, you'll be blaming your code and searching for bugs that may not exist! :)



Muahahaha! That's what you get for stealing my model which I stole from a website with free 3D models and duplicating my demo exactly!

Actually I don't care. I'm more bemused than anything.

And I would like to point out that MY system handles boned vertex-animated B3D meshes, AND beethovens! :-)

Tom, those shadows look just awesome. They'd go well with my rpg I'm working on. All the walls are very simple geometry. Can't wait to try this out.

sswift:andreyman stole your shadow system demo exactly, too! and i did, to compare them :)

tom: yeah, i would like to see it, too!

When I start a demo, I get the following error:
Function 'DX7_SetSystemProperties' not found

move the userlibs into your blitz userlib directory.

Hi and well done on this fantastic contribution!

I have one problem though. You say that you've had problems using B3D files, but because MD2s aren't meshes, it means that most of my current models (all md2/b3d) are unusable with the shadow system!
I'd imagine that most people here use one or both of these for animated models and so it might be worth trying to figure out a way of getting b3d models to work with the engine...

thanks, and good luck!

b3d models work! but those models that vertices you cant handle with b3d might make trouble (md2, terrains, bsp)

carrot: i tried to figure it out, but there was no way yet!! b3d animations might be possible some day, but not md2!! because md2 models are no meshes, and they havent got any vertices or triangles which can be accessed by blitz!

for terrains you just have to use a meshterrain loader ;)

btw: andreymans stencil fw libary doesnt support b3d animations yet, too. so dont matter about that!

Just because another library doesn't support b3d animations does not mean that it isn't important. I've been following this thread with interest (and I'm impressed with your work), but I suspect that for many, if not most, people, support for animated b3d models is essential.

if you go here to look at the md2 specs, I think that perhaps the vertices and triangles CAN be accessed:
http://tfc.duke.free.fr/coding/md2-specs-en.html

I'll second JustLuke's comments.

I'm hoping that GrumpyOldMan's library may offer a new solution. We'll have to wait and see how that progresses, but at the moment, it appears to handle boned animation better than Blitz's own system. So perhaps, his library may also allow access to the information needed to create stencil shadows for bone-animated meshes.

...also, at some point in the render process, the data of an MD2 is turned into polygons, just like any other mesh. Again, it's a matter of gaining access to the necessary data.

After playing around with the .md2 format I came up with a little program that accesses a single vertex. I checked it against the .md2 model that I created and it is accurate. The code can be adapted to read ALL of the vertices and triangles. Pardon the mess as I left in unused types (they WILL be used, however, if you are to read the entire .md2 file). The file has only minimal error checking and you have to provide your own model (I have the filename hard coded)


Graphics 800,600

Type model_t 
   Field magic; must be 844121161
   Field version; must be 8
   Field skinWidth; 
   Field skinHeight; 
   Field frameSize; 
   Field numSkins; 
   Field numVertices; number of vertices per frame
   Field numTexCoords; 
   Field numTriangles; 
   Field numGlCommands; 
   Field numFrames; 
   Field offsetSkins; 
   Field offsetTexCoords; 
   Field offsetTriangles; the position in bytes from the beginning of the file to the triangle data
   Field offsetFrames; 	the position in bytes from the beginning of the file to the frames data
   Field offsetGlCommands; 
   Field offsetEnd; the position in bytes from the beginning of the file to the end of the file
End Type

Type vertex
	Field x,y,z
End Type

Type triangleVertex_t
   Field vertex;
   Field lightNormalIndex;
End Type

Type scale
	Field x#,y#,z#
End Type

Type translate
	Field x#,y#,z#
End Type


Type frame_t
    Field  scale
    Field translate
    Field name$
    Field vertices.triangleVertex_t
End Type

Type vertexIndices
	Field x#,y#,z#
End Type

Type textureIndices
	Field x#,y#,z#
End Type

Type triangle_t
	Field vertexIndices
   	Field textureIndices
End Type

Type textureCoordinate_t
	Field s
	Field t
End Type

Type glCommandVertex_t
	Field s#
	Field t#
	Field vertexIndex
End Type

Type md2_skin_t
	Field name$
End Type

; dim vert#(3)
; vert(i)=(triangleVertex_t.vertex(i)*frame_t.scale(i))+frame_t.translate(i)
; The above is how to convert the scaled vertex position into it's real position


ReadMd2Model("temp.md2",model_t)
WaitKey()
End

Function ReadMD2Model(filename$,model_t)
file=OpenFile(filename$)
If Not file
	End
End If
header=CreateBank(15308*10) ; the 15308 is what I found in offsetEnd
amount=ReadBytes(header,file,0,15308)
If amount=0 Then
	End
End If
CloseFile file

skins_offset=PeekInt(header,44) ; offset for skins
num_skins=PeekInt(header,20) ; number of skins
num_tris=PeekInt(header,32) ; number of triangles
num_verts=PeekInt(header,24) ; number of vertices
tris_offset=PeekInt(header,52) ; offset for triangles
frame_offset=PeekInt(header,56) ; offset to frame start
num_frames=PeekInt(header,40) ; number of frames
frame_size=PeekInt(header,16) ; frame size
end_file=PeekInt(header,64) ; offset for end of file
scaled_x=PeekByte(header,frame_offset+24)
scaled_y=PeekByte(header,frame_offset+28)
scaled_z=PeekByte(header,frame_offset+32)
x_scale=PeekFloat(header,frame_offset)
y_scale=PeekFloat(header,frame_offset+4)
z_scale=PeekFloat(header,frame_offset+8)
x_trans=PeekFloat(header,frame_offset+12)
y_trans=PeekFloat(header,frame_offset+16)
z_trans=PeekFloat(header,frame_offset+20)
real_x=scaled_x*x_scale+x_trans
real_y=scaled_y*y_scale+y_trans
real_z=scaled_z*z_scale+z_trans
Print "Number of Vertices per frame: "+num_verts
Print "Size of each frame: "+frame_size
Print "X Scale: "+PeekFloat(header,frame_offset)
Print "Y Scale: "+PeekFloat(header,frame_offset+4)
Print "Z Scale: "+PeekFloat(header,frame_offset+8)
Print "X Translate: "+PeekFloat(header,frame_offset+12)
Print "Y Translate: "+PeekFloat(header,frame_offset+16)
Print "Z Translate: "+PeekFloat(header,frame_offset+20)
Print "First Vertex X Scaled Position: "+PeekByte(header,frame_offset+24)
Print "First Vertex Y Scaled Position: "+PeekByte(header,frame_offset+28)
Print "First Vertex Z Scaled Position: "+PeekByte(header,frame_offset+32)
Print "Real Position of First Vertex is: "+real_x+","+real_y+","+real_z
freeBank header
End Function


**** EDIT *******
Looking back at my code I see some minor errors such as not making some variables "float". The principle, however, remains the same. This code is free for any to use, by the way.
Kevin

thx kevin. i will check it out now :)

No problem. Hope that it helps :)

I have downloaded your DSS_Release_0.6b, but when I start the program, he sais he doesn't find the getcamrangestart. Where can I download it?

just added b3d animations:


now *.x *.3ds and *.b3d animated objects are supported!
the next release will be in aproxx 2 months(without garanty)

he, that's nice work devil!

This looks really interesting. However, the sudden changes in shading of polygons is really jarring. Is there any way to smooth that out?

I have downloaded your DSS_Release_0.6b, but when I start the program, he sais he doesn't find the getcamrangestart. Where can I download it?

I was getting that error to until I copied the userlibs into Blitz3D's userlibs directory.

thanks

2 months .........


goood work!

i dont know how to smooth it out. maybee playing arroud with the ambient light should do it...

There is a bug in the Init function.

It tries to init 1024x786 instead of 1024x768 :) (wanted to see its true speed so put it into full screen, with no waittimer and flip 0 ... get up to 100 FPS in the example 5 on my 7600Go which is quite nice :)

oops mistyped (sry)
a wonder you got 100 fps in the stress test!
i get 30 fps, and i am using the stress test to see wether my current optimazion was good, or not...

nice work!!!

I get only 10 FPS on my end :|

Anyways, is it possible to use MD2's or will it simply not work...

If it can't, does any one know of a MD2 -> B3D converter? I would really like to use this in a game but until then, I'll use my theory: Squish everything to a pancake, move it down at the feet, then keep it there until the Y axis of the parent model is constant then move the Y of the shadow. It doesn't do Devil's stencil system, but for something that doesn't kill FPS that much and it's the only thing I know to use...

if you wanna get more speed, you have to turn off the debugger!!

if have studied the md2 model format, but without any result!
btw: there is no shadow system which supports md2!! (or at least no STENCIL shadow system or a better one ...)

Umm I get a missing function error for

MoveEntity ShadowPlane, 0, 0, GetCamRangeStart(ShadowCam) + .001

That GetCamRangeStart function is not there.

Well, I use MD2's alot, and I've made a shadow system... but with no name. I'll take a screen shot of what I'm using/made.

EDIT:
...AH Heck... I have no clue what the forum cmds are...

forum codes:

http://www.blitzbasic.com/faq/faq_entry.php?id=2

flame: is this a stencil shadow system or a texture shadow system?

Devil: Do we need to wait for the next release in 2 months before we can use the new code for the b3d models?

Also, it seems that using the sample code provided Kevin above should make md2 models possible at some stage.

Again, great work.

b3d models are not supported in the 0.6 beta above^^
but you can implentate your shadow code, and let the b3d models be receivers only until in 2 months!

also i cannot promise that b3d models will work perfectly. my ant is working seamless, but all my other models are doing strange things!

we'll see whether b3d models will work seamless! if not, don't be angry at me :)

@Devils Child: I'll be on Irc at 7pm GMT if you wanna catch up on this stuff ok :)

but all my other models are doing strange things!


I've had problems with skinned meshes too. This is what I think is the cause.

To get a transformed vert from a skinned mesh, I store all vertices positions in the local space of the bone which has major influence on them. I'm discarding blended weighting for now in the hope it speeds things up a bit.

Bones in a mesh have a 'rest pose'. You must do the above routine when the bones are in this rest pose, else their recorded local bone offset will be wrong, which will cause your TFormB3DVertex() function (or DLL or whatever method you're using) to return bad values.

When creating a skinned mesh, record the rest pose at frame 0, this seems to work ok for me.

You can just see the errors this causes on this robot2.b3d mesh, look closely at the gun/hands and the antenna, there's what looks like ghost geometry. This mesh has no keyed rest pose at frame 0!

In fact, as a quick test, load 2 versions of your mesh, one using LoadMesh() and the other using LoadAnimMesh()

If they don't look exactly the same... you're going to have problems.



i'll be there!

here is another screenshot to keep you entertaining :)


Sry I didnt' respond in a long time. No, my system doesn't use either... well, It's not a true stencil system, and it's not texture based... so I'm not sure what to put it under as...

All that happens is I do some tweeking with the model that has to be shadowed so it creates a shadow of itself... Is that stencil, because if it is, then I might have the only MD2 compatible Shadow system...

as far as i understood, you are squishing the md2 mesh down to the floor, right?

this is no stencil shadow system. and it is not very compatible :/

For something that barely hurts FPS and is understandable, it works fine with me... sure, it's not the BEST thing out there, but again... for something that requires no brain surgery or headaches...or both...

i can understand you, and now i wanna tell you the story of my life:

one year ago, in the thread "stencil shadow volume demo" by tom, if found my idea to make a stencil shadow system.
i tested the code, but at first it was ATI unfirendly! But then he made a fix, and i tried harder on it!
then i made a function which creates volumes from each polygon. not just from the edges! that means a caster with 100 triangles would cast 600 shadow polys. just *6! this looks weird with toms old stencil demo, so i improved it to the carmacks reverse by braincell!
well, for a long time i frozen all researches, cause i thought, i never make a good shadow system :D.
2 months ago, daredevil made a stencil shadow system, too. he had a good volume system, but a slow software-stencil-buffer. so we decided to move together. so we put his volume function optimized into my current system! then, i made some samples and we published the first alpha version of this shadow system! 3 weeks after it he made a new algorithm for shadow volumes...and when he was ready, i checked out that aglorithm. it took a lot of time to initialise the casters, so i build a *.shw caching file.
then i was playing arround with bona animation, and found out, that they can easily be set to a shadow caster by recursive setting each bones!
then i published it to this 0.6 beta!
not b3d models are barely working and the system was more flexible ever :)

this was the time of my life!
between all that sentences were hundrets of ours of research!

bye

Great work Devil's Child. You and Tom and Daredevil have achieved amazing things with this system.

I'd love to see an EXE demo of the ant test you have there, even if there is no source. I'd still like to be able to disable self-shadowing on certain objects if at all possible.

first tom and i have to improve the rendering, before i can improve all other wishes :) but i will do it!

Good .... Good Work!!

Hi Devils Child

Hi All


This is a light optimization , in the "sample 5 " is increment 10-15%

Function CreateVolume(light, parallel = False)
	;===>
	RangeLight# = 10 ; is a range light, all object over range is jump
	;===>
	light_x# = EntityX(light, True) * (1 + parallel * 1000000)
	light_y# = EntityY(light, True) * (1 + parallel * 1000000)
	light_z# = EntityZ(light, True) * (1 + parallel * 1000000)
	volume_lenght = RangeLight
	;===>
	For etem.ETE_Mesh = Each ETE_Mesh
		;===>
		cnt_tris = etem\cnt_tris
		For v = 0 To cnt_tris
			;===>
			etet.ETE_Triangle = TriangleClone(v)
			CloneTriangle(etet, etem\tri[v])
			;===>
			v1.Point3D = etet\v1
			;===>
			TFormPoint v1\x#, v1\y#, v1\z#, etem\ent, 0
			v1\x# = TFormedX()
			v1\y# = TFormedY()
			v1\z# = TFormedZ()
			;===>
			TFormNormal etet\nx#, etet\ny#, etet\nz#, etem\ent, 0
			normlight_x# = (v1\x# - light_x#) * TFormedX()
			normlight_y# = (v1\y# - light_y#) * TFormedY()
			normlight_z# = (v1\z# - light_z#) * TFormedZ()
			;===>
			If (normlight_x# +  normlight_y# + normlight_z#) < 0 Then
				;===>
				etet\tri = -1
			Else
				;===>
				v2.Point3D = etet\v2
				TFormPoint v2\x#, v2\y#, v2\z#, etem\ent, 0
				v2\x# = TFormedX()
				v2\y# = TFormedY()
				v2\z# = TFormedZ()
				;===>
				v3.Point3D = etet\v3
				TFormPoint v3\x#, v3\y#, v3\z#, etem\ent, 0
				v3\x# = TFormedX()
				v3\y# = TFormedY()
				v3\z# = TFormedZ()
				;===>
			EndIf
			;===>
		Next
		;===>

		For v = 0 To cnt_tris
			etet = TriangleClone(v)
			If etet\tri => 0 Then
				ta = etet\ta
				tb = etet\tb
				tc = etet\tc
				If ta > -1 Then check1 = TriangleClone(ta)\tri Else check1 = -1
				If tb > -1 Then check2 = TriangleClone(tb)\tri Else check2 = -1
				If tc > -1 Then check3 = TriangleClone(tc)\tri Else check3 = -1
				If check1 < 0 Or check2 < 0 Or check3 < 0 Then
					v1 = etet\v1
					v2 = etet\v2
					v3 = etet\v3
					If check1 < 0 Then
						rax# = v1\x# + (v1\x# - light_x#) * volume_lenght
						ray# = v1\y# + (v1\y# - light_y#) * volume_lenght
						raz# = v1\z# + (v1\z# - light_z#) * volume_lenght
						rbx# = v2\x# + (v2\x# - light_x#) * volume_lenght
						rby# = v2\y# + (v2\y# - light_y#) * volume_lenght
						rbz# = v2\z# + (v2\z# - light_z#) * volume_lenght
						vert1 = AddVertex(VolumeSurf, v1\x#, v1\y#, v1\z#)
						vert2 = AddVertex(VolumeSurf, rax#, ray#, raz#)
						vert3 = AddVertex(VolumeSurf, rbx#, rby#, rbz#)
						vert4 = AddVertex(VolumeSurf, v2\x#, v2\y#, v2\z#)
						AddTriangle(VolumeSurf, vert1, vert2, vert3)
						AddTriangle(VolumeSurf, vert1, vert3, vert4)
					EndIf
					If check2 < 0 Then
						rbx# = v2\x# + (v2\x# - light_x#) * volume_lenght
						rby# = v2\y# + (v2\y# - light_y#) * volume_lenght
						rbz# = v2\z# + (v2\z# - light_z#) * volume_lenght
						rcx# = v3\x# + (v3\x# - light_x#) * volume_lenght
						rcy# = v3\y# + (v3\y# - light_y#) * volume_lenght
						rcz# = v3\z# + (v3\z# - light_z#) * volume_lenght
						vert1 = AddVertex(VolumeSurf, v2\x#, v2\y#, v2\z#)
						vert2 = AddVertex(VolumeSurf, rbx#, rby#, rbz#)
						vert3 = AddVertex(VolumeSurf, rcx#, rcy#, rcz#)
						vert4 = AddVertex(VolumeSurf, v3\x#, v3\y#, v3\z#)
						AddTriangle(VolumeSurf, vert1, vert2, vert3)
						AddTriangle(VolumeSurf, vert1, vert3, vert4)
					EndIf
					If check3 < 0 Then
						rax# = v1\x# + (v1\x# - light_x#) * volume_lenght
						ray# = v1\y# + (v1\y# - light_y#) * volume_lenght
						raz# = v1\z# + (v1\z# - light_z#) * volume_lenght
						rcx# = v3\x# + (v3\x# - light_x#) * volume_lenght
						rcy# = v3\y# + (v3\y# - light_y#) * volume_lenght
						rcz# = v3\z# + (v3\z# - light_z#) * volume_lenght
						vert1 = AddVertex(VolumeSurf, v1\x#, v1\y#, v1\z#)
						vert2 = AddVertex(VolumeSurf, rax#, ray#, raz#)
						vert3 = AddVertex(VolumeSurf, rcx#, rcy#, rcz#)
						vert4 = AddVertex(VolumeSurf, v3\x#, v3\y#, v3\z#)
						AddTriangle(VolumeSurf, vert1, vert3, vert2)
						AddTriangle(VolumeSurf, vert1, vert4, vert3)
					EndIf
				EndIf
			EndIf
		Next
	Next
End Function



the system is improve create a check for control object in range light, if object in range calculate, if not jump

;)

Bye

allright dare :)
just improved it!
cya

cool

can i disable the self shadows ? i mean if i will have shadows
only on grounds or walls ?

no, i said not yet! it will be supported in the next demo!

~CLOSED~

this shadow thread is now ready to burst.
please write ahead in the new stencil shadow thread 2!!!
http://www.blitzbasic.com/Community/posts.php?topic=62809


@any moderator: close this thread please!