Carmack's Reverse - (stencil shadows) here it is.

Blitz3D Forums/Blitz3D Programming/Carmack's Reverse - (stencil shadows) here it is.

Yes, i just posted the wrong version which was not fixed. Here is the fixed version,it should work, tell me if it doesnt:


;This is a demo to show implementation of "Carmacks Reverse" way of drawing
;stencil shadows. It is also known as the Depth-Fail or the Z-Fail technique.
;
;			Lenn , 21.01.2005

;D3DCULL
Const D3DCULL_NONE				= 1
Const D3DCULL_CW					= 2
Const D3DCULL_CCW					= 3
		
;D3DSHADE_MODE
Const D3DSHADE_FLAT			= 1
Const D3DSHADE_GOURAUD	= 2
Const D3DSHADE_PHONG		= 3

;D3DFILL_MODE
Const D3DFILL_POINT			= 1
Const D3DFILL_WIREFRAME	= 2
Const D3DFILL_SOLID			= 3

;D3DSTENCILOP
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	;force 32-bit size enum

;D3DCMPFUNC
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	;force 32-bit size enum

;D3DBLEND
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	;force 32-bit size enum



Const D3DRS_ANTIALIAS          = 2    ; D3DANTIALIASMODE */
Const D3DRS_TEXTUREPERSPECTIVE = 4    ; True For perspective correction */
Const D3DRS_ZENABLE            = 7    ; D3DZBUFFERTYPE (Or True/False For legacy) */
Const D3DRS_FILLMODE           = 8    ; D3DFILL_MODE        */
Const D3DRS_SHADEMODE          = 9    ; D3DFILL_MODE */
Const D3DRS_LINEPATTERN        = 10   ; D3DLINEPATTERN */
Const D3DRS_ZWRITEENABLE       = 14   ; True To enable z writes */
Const D3DRS_ALPHATESTENABLE    = 15   ; True To enable alpha tests */
Const D3DRS_LASTPIXEL          = 16   ; True For Last-pixel on lines */
Const D3DRS_SRCBLEND           = 19   ; D3DBLEND */
Const D3DRS_DESTBLEND          = 20   ; D3DBLEND */
Const D3DRS_CULLMODE           = 22   ; D3DCULL */
Const D3DRS_ZFUNC              = 23   ; D3DCMPFUNC */
Const D3DRS_ALPHAREF           = 24   ; D3DFIXED (long) */
Const D3DRS_ALPHAFUNC          = 25   ; D3DCMPFUNC */
Const D3DRS_DITHERENABLE       = 26   ; True To enable dithering */
Const D3DRS_ALPHABLENDENABLE   = 27   ; True To enable alpha blending */
Const D3DRS_FOGENABLE          = 28   ; True To enable fog blending */
Const D3DRS_SPECULARENABLE     = 29   ; True To enable specular */
Const D3DRS_ZVISIBLE           = 30   ; True To enable z checking */
Const D3DRS_STIPPLEDALPHA      = 33   ; True To enable stippled alpha (RGB device only) */
Const D3DRS_FOGCOLOR           = 34   ; D3DCOLOR */  INT (((a) << 24) Or ((r) << 16) Or ((g) << 8) Or (b)))
Const D3DRS_FOGTABLEMODE       = 35   ; D3DFOGMODE */
Const D3DRS_FOGSTART           = 36   ; Float Fog start (For both vertex And pixel fog) 
Const D3DRS_FOGEND             = 37   ; Float Fog End      */
Const D3DRS_FOGDENSITY         = 38   ; Fog density  */
Const D3DRS_EDGEANTIALIAS      = 40   ; True To enable edge antialiasing */
Const D3DRS_COLORKEYENABLE     = 41   ; True To enable source colorkeyed textures */
Const D3DRS_ZBIAS              = 47   ; LONG Z bias */
Const D3DRS_RANGEFOGENABLE     = 48   ; Enables range-based fog */

; *** STENCIL OPS ***
Const D3DRS_STENCILENABLE      = 52   ; BOOL enable/disable stenciling
Const D3DRS_STENCILFAIL        = 53   ; D3DSTENCILOP To do If stencil test fails
Const D3DRS_STENCILZFAIL       = 54   ; D3DSTENCILOP To do If stencil test passes And Z test fails
Const D3DRS_STENCILPASS        = 55   ; D3DSTENCILOP To do If both stencil And Z tests pass */
Const D3DRS_STENCILFUNC        = 56   ; D3DCMPFUNC fn.  Stencil Test passes If ((ref & mask) stencilfn (stencil & mask)) is True */
Const D3DRS_STENCILREF         = 57   ; INT Reference value used in stencil test */
Const D3DRS_STENCILMASK        = 58   ; Mask value used in stencil test  e.g (0xffffffff)
Const D3DRS_STENCILWRITEMASK   = 59   ; Write mask applied To values written To stencil buffer e.g (0xffffffff)
Const D3DRS_TEXTUREFACTOR      = 60   ; D3DCOLOR used For multi-texture blend */

Const D3DCLEAR_TARGET					= $00000001	;Clear target surface
Const D3DCLEAR_ZBUFFER				= $00000002	;Clear target z buffer
Const D3DCLEAR_STENCIL				= $00000004	;Clear Stencil


;ERRORS
Const D3DERR_ZBUFFER_NOTPRESENT					= 2070
Const D3DERR_STENCILBUFFER_NOTPRESENT		= 2071
Const D3DERR_VIEWPORTHASNODEVICE				= 774
Const DDERR_INVALIDOBJECT								= 130
Const DDERR_INVALIDPARAMS								= $80070057

Type BBRect
	Field x1%
	Field lX1%

	Field y1%
	Field lY1%

	Field x2%
	Field lX2%
	
	Field y2%
  Field lY2%
End Type

Graphics3D 1027,768,32,2

Direct3D7=SystemProperty$("Direct3D7")
Direct3DDevice7=SystemProperty$("Direct3DDevice7")
DirectDraw7=SystemProperty$("DirectDraw7")
DirectInput7=SystemProperty$("DirectInput7")
AppHWND=SystemProperty$("AppHWND")
AppHINSTANCE=SystemProperty$("AppHINSTANCE")




cam=CreateCamera()
piv=CreatePivot()
PositionEntity cam,-5,3,-5
PointEntity cam,piv
CameraRange cam,.1,50

light=CreateLight()
RotateEntity light,60,30,0

tex=CreateTexture(512,512)
ScaleTexture tex,.2,.5
SetBuffer TextureBuffer(tex)
Color 100,100,100
Rect 0,0,512,512
Color 200,200,200
Rect 8,8,496,496
Color 255,255,255
SetBuffer BackBuffer()

cyl1=CreateCylinder()
EntityAlpha cyl1,.3
PositionEntity cyl1,2,0,0
ScaleEntity cyl1,3,3,3

cyl2=CreateCylinder()
EntityAlpha cyl2,.3
PositionEntity cyl2,2,0,5
ScaleEntity cyl2,3,3,3

cube=CreateCube()
PositionEntity cube,0,0,0
ScaleEntity cube,5,.2,10
EntityTexture cube,tex



spa#=.3
shadowplane=CreateCube() ; squished Z cube infront of cam
ScaleMesh shadowplane,10,10,.01
EntityParent shadowplane,cam,0
MoveEntity shadowplane,0,0,.2
EntityColor shadowplane,0,0,0
EntityAlpha shadowplane,spa#
;Shadow plane is the object infront of the screen which is drawn where
;the stencil shadow should be drawn (on certain pixels). It means that
;where the shadow volume and scenery intersect, that is where the plane
;will be drawn. Because the color is black, and alpha is spa# its darkness
;will depend on spa#. You can put any other object in its place...


sv=1

; AREA TO CLEAR
r.BBRect=New BBRect
r\lX1=0
r\lY1=0
;r\lX2=GraphicsWidth()/2 ; half the screen (used to show what happens if only half the screen is cleared)
r\lX2=GraphicsWidth() 
r\lY2=GraphicsHeight()


CameraClsMode cam,False,False

While Not KeyHit(1)

.start
	PositionEntity cyl1,(MouseX()-(GraphicsWidth()*.5)) * .01,-(MouseY()-(GraphicsWidth()*.5)) * .02,0
	PositionEntity cyl2,(MouseX()-(GraphicsWidth()*.5)) * .01,-(MouseY()-(GraphicsWidth()*.5)) * .02,2
	
	
	t=MilliSecs()

	;-----------------------------------------------------------------------------------render start	
	HideEntity shadowplane;1-hide plane
	;I =think= that it might be better to hide the volumes here
	HideEntity cyl1  ;1a-hide volumes
	HideEntity cyl2 
	ShowEntity cube  ;2-show scene

	SetRenderState(Direct3DDevice7, D3DRS_ZWRITEENABLE, True) 
	SetRenderState(Direct3DDevice7, D3DRS_STENCILENABLE, False)
	SetRenderState(Direct3DDevice7, D3DRS_ALPHABLENDENABLE, False)


;	DeviceClear2(Direct3DDevice7, r, D3DCLEAR_TARGET Or D3DCLEAR_ZBUFFER Or D3DCLEAR_STENCIL,$00008080,1.0,0)
;	RenderWorld 
DeviceClear(Direct3DDevice7, 7,$00008080,1,0)
CameraClsMode cam,True,True
RenderWorld
CameraClsMode cam,False,False


	ShowEntity cyl1 ;3-show volume
	ShowEntity cyl2
	HideEntity cube ;4-hide scene


; *** RenderShadow() START *** -------- << name of the function as found in C++ DX7SDK examples


	SetRenderState(Direct3DDevice7, D3DRS_ZWRITEENABLE,False)
	SetRenderState(Direct3DDevice7, D3DRS_STENCILENABLE,True)
	
	SetRenderState(Direct3DDevice7, D3DRS_STENCILFUNC, D3DCMP_ALWAYS)
	SetRenderState(Direct3DDevice7, D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP)
	
	SetRenderState(Direct3DDevice7, D3DRS_STENCILPASS, D3DSTENCILOP_KEEP)
	
	SetRenderState(Direct3DDevice7, D3DRS_STENCILREF, 1)
	SetRenderState(Direct3DDevice7, D3DRS_STENCILMASK,$ffffffff)
	SetRenderState(Direct3DDevice7, D3DRS_STENCILWRITEMASK,$ffffffff)

	SetRenderState(Direct3DDevice7, D3DRS_STENCILZFAIL, D3DSTENCILOP_INCR)
	
	SetRenderState(Direct3DDevice7, D3DRS_ALPHABLENDENABLE, True)
	SetRenderState(Direct3DDevice7, D3DRS_SRCBLEND, D3DBLEND_ZERO)
	SetRenderState(Direct3DDevice7, D3DRS_DESTBLEND, D3DBLEND_ONE)
	
	RenderWorld	
	
	SetRenderState(Direct3DDevice7, D3DRS_CULLMODE, D3DCULL_CW)
	RenderWorld
	
	SetRenderState(Direct3DDevice7, D3DRS_CULLMODE, D3DCULL_CCW)
	
	SetRenderState(Direct3DDevice7, D3DRS_STENCILZFAIL, D3DSTENCILOP_DECR)
	RenderWorld 
	
	SetRenderState(Direct3DDevice7, D3DRS_ZWRITEENABLE,     True )
	SetRenderState(Direct3DDevice7, D3DRS_STENCILENABLE,    False )
	SetRenderState(Direct3DDevice7, D3DRS_ALPHABLENDENABLE, False )			
	

	
; *** RenderShadow() END *** --------



; *** DrawShadow() START *** -----------  << name of the function as found in C++ DX7SDK examples
	SetRenderState(Direct3DDevice7, D3DRS_ZENABLE,       False )
	SetRenderState(Direct3DDevice7, D3DRS_STENCILENABLE, True )
	SetRenderState(Direct3DDevice7, D3DRS_FOGENABLE, False)	

	SetRenderState(Direct3DDevice7, D3DRS_ALPHABLENDENABLE, True )
	SetRenderState(Direct3DDevice7, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA )
	SetRenderState(Direct3DDevice7, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA )

	SetRenderState(Direct3DDevice7, D3DRS_STENCILREF,  1 )
	SetRenderState(Direct3DDevice7, D3DRS_STENCILFUNC, D3DCMP_LESSEQUAL )
	SetRenderState(Direct3DDevice7, D3DRS_STENCILPASS, D3DSTENCILOP_KEEP )

	ShowEntity shadowplane ;5-show plane
	RenderWorld

	SetRenderState(Direct3DDevice7, D3DRS_ZENABLE,          True )
	SetRenderState(Direct3DDevice7, D3DRS_STENCILENABLE,    False )
	SetRenderState(Direct3DDevice7, D3DRS_ALPHABLENDENABLE, True )

; *** DrawShadow() END *** -----------

	HideEntity shadowplane ;6-hide plane

	RenderWorld;--------------------------------------------------------------------------render end
	

	SetRenderState(Direct3DDevice7, D3DRS_ALPHABLENDENABLE, False )
	Text 0,0,"Move cylinders (volumes) with mouse/"+"     MS: "+(MilliSecs() - t)
	Text 0,10,"Shadow Alpha: "+spa+ "    LMB/RMB to change value, SPACE to toggle visibility"
	Text 0,20, "A/Z to move back/forward. Enter the volumes and see that it works."

	If MouseDown(1)
		spa=spa-.01
		If spa<0 spa=0
		EntityAlpha shadowplane,spa
	Else If MouseDown(2)
		spa=spa+.01
		If spa>1.0 spa=1.0
		EntityAlpha shadowplane,spa
	End If
	
	If KeyHit(30)
		MoveEntity cam, 0,0,0.1
	End If
	
	If KeyHit(44)
		MoveEntity cam, 0,0,-0.1
	End If	
	

	If KeyHit(57)
		sv=Not sv
		If sv
			EntityAlpha cyl1,.3
			EntityAlpha cyl2,.3
		Else
			EntityAlpha cyl1,0.001
			EntityAlpha cyl2,0.001
		End If
	End If
	
	If KeyHit(24) tra=Not tra 


Flip

Wend


End








Type volumes
	Field mesh
End Type

Function CreateVolume(entity, light)
;entity - the entity that casts the shadow
;light - the light entity from which the light
;
;This function is included in case somebody wants to build shadow volumes and try stuff out.
;This is fairly slow because it extrudes and caps every triangle on a mesh. This means
;that 6 times more triangles need to be made for each one on the mesh.
;(I tried faster methods but trust me its not easy)
;It may be useful only for very basic geometry.


lx#=EntityX(light,True)
ly#=EntityY(light,True)
lz#=EntityZ(light,True)

	a_vol.volumes=New volumes
		a_vol\mesh=CreateMesh()
		
		;EntityBlend a_vol\mesh,2
		;EntityFX a_vol\mesh,1
		EntityColor a_vol\mesh,0,0,0
		EntityAlpha a_vol\mesh,0.001

		volsurf=CreateSurface(a_vol\mesh)
		numsurf=CountSurfaces(entity)		
		vpos=CreatePivot()
		vposend=CreatePivot()
		VolumeDepth#=1000
		
		
		
		;For surfcount=1 To numsurf-1
		surfcount=1

		While surfcount <= numsurf
			cursurface=GetSurface(entity, surfcount)
			maxtricount=CountTriangles (cursurface)
			;For tricount=0 To tricount-1
							
			While tricount < maxtricount
			v1x#=VertexX(cursurface, TriangleVertex(cursurface, tricount, 0))
			v1y#=VertexY(cursurface, TriangleVertex(cursurface, tricount, 0))
			v1z#=VertexZ(cursurface, TriangleVertex(cursurface, tricount, 0))
			TFormPoint v1x#,v1y#,v1z#, entity, 0
			v1x#=TFormedX()
			v1y#=TFormedY()
			v1z#=TFormedZ()
			
			v2x#=VertexX(cursurface, TriangleVertex(cursurface, tricount, 1))
			v2y#=VertexY(cursurface, TriangleVertex(cursurface, tricount, 1))
			v2z#=VertexZ(cursurface, TriangleVertex(cursurface, tricount, 1))			
			TFormPoint v2x#,v2y#,v2z#, entity, 0
			v2x#=TFormedX()
			v2y#=TFormedY()
			v2z#=TFormedZ()
			
			v3x#=VertexX(cursurface, TriangleVertex(cursurface, tricount, 2))
			v3y#=VertexY(cursurface, TriangleVertex(cursurface, tricount, 2))
			v3z#=VertexZ(cursurface, TriangleVertex(cursurface, tricount, 2))
			TFormPoint v3x#,v3y#,v3z#, entity, 0
			v3x#=TFormedX()
			v3y#=TFormedY()
			v3z#=TFormedZ()
			
			
			PositionEntity vpos,v1x#,v1y#,v1z#
			PositionEntity vposend, lx#,ly#,lz#,1
			PointEntity vposend, vpos
			MoveEntity vposend, 0,0,VolumeDepth#
			v1xe#=EntityX(vposend, True)
			v1ye#=EntityY(vposend, True)
			v1ze#=EntityZ(vposend, True)
			
			PositionEntity vpos,v2x#,v2y#,v2z#
			PositionEntity vposend, lx#,ly#,lz#,1
			PointEntity vposend, vpos
			MoveEntity vposend, 0,0,VolumeDepth#
			v2xe#=EntityX(vposend, True)
			v2ye#=EntityY(vposend, True)
			v2ze#=EntityZ(vposend, True)
			
			PositionEntity vpos,v3x#,v3y#,v3z#
			PositionEntity vposend, lx#,ly#,lz#,1
			PointEntity vposend, vpos
			MoveEntity vposend, 0,0,VolumeDepth#
			v3xe#=EntityX(vposend, True)
			v3ye#=EntityY(vposend, True)
			v3ze#=EntityZ(vposend, True)
			
			v1=AddVertex(volsurf,v1x#,v1y#,v1z#)
			v1e=AddVertex(volsurf,v1xe#,v1ye#,v1ze#)
			v2=AddVertex(volsurf,v2x#,v2y#,v2z#)
			v2e=AddVertex(volsurf,v2xe#,v2ye#,v2ze#)
			v3=AddVertex(volsurf,v3x#,v3y#,v3z#)
			v3e=AddVertex(volsurf,v3xe#,v3ye#,v3ze#)			

			AddTriangle (volsurf, v1,v1e,v2)
			AddTriangle (volsurf, v2,v1e,v2e)
			AddTriangle (volsurf, v1,v3,v1e)
			AddTriangle (volsurf, v3,v3e,v1e)
			AddTriangle (volsurf, v3,v2,v3e)
			AddTriangle (volsurf, v2,v2e,v3e)
			AddTriangle (volsurf, v1,v2,v3) 	;cap top
			AddTriangle (volsurf, v1e,v2e,v3e) 	;cap bottom			
			
			tricount=tricount+1
			Wend 
			;Next		
		surfcount=surfcount+1
		Wend
		;Next

FreeEntity vpos
FreeEntity vposend

End Function

Function HideVolumes()
	For a_vol.volumes=Each volumes
		HideEntity a_vol\mesh
	Next
End Function
Function ShowVolumes()
	For a_vol.volumes=Each volumes
		ShowEntity a_vol\mesh
	Next
End Function
Function DeleteVolumes()
	For a_vol.volumes=Each volumes
		FreeEntity a_vol\mesh
		Delete a_vol
	Next
End Function



You also need V1.88 of blitz3d running.

jfk, i heard Mark may be working on stencil shadows for BMax and may just convert them to blitz3d so lets wait for a bit and see what he does. If you dont want to wait, email me (email provided in my details) and i'll reply to you with the stuff i think can be done.