2d Shadows

Miscellaneous Forums/Blitz Showcase/2d Shadows

hi!

Graphics 1024, 768, 32, 2
SetBuffer BackBuffer()
ClsColor 0, 127, 255
SeedRnd MilliSecs()
HidePointer()

;Globs
Type Polygon
	Field seg
	Field x, y, rot#
	Field size
End Type
Global LightX, LightY

;Polygons
p1 = CreatePolygon(8, 200, 200, 0, 100)
p2 = CreatePolygon(3, 820, 350, 0, 100)
p3 = CreatePolygon(30, 500, 550, 0, 100)

While Not KeyHit(1)
	PositionLight(MouseX(), MouseY())
	rot# = rot# + 1
	RotatePolygon(p1, rot#)
	RotatePolygon(p2, rot#)
	RotatePolygon(p3, rot#)
	Render()
	Flip
	Cls
Wend
End

Function PositionLight(x, y)
LightX = x
LightY = y
End Function

Function CreatePolygon(seg, x, y, rot#, size)
p.Polygon = New Polygon
p\seg = seg
p\x = x
p\y = y
p\rot# = rot#
p\size = size
Return Handle(p)
End Function

Function RotatePolygon(poly, rot#)
p.Polygon = Object.Polygon(poly)
p\rot# = rot#
End Function

Function Render()
LockBuffer()
For p.Polygon = Each Polygon
	po1x = -1
	po2x = -1
	For i = 0 To p\seg - 1
		p0x = Cos((i - 1) * 360.0 / p\seg + p\rot#) * p\size + p\x
		p0y = Sin((i - 1) * 360.0 / p\seg + p\rot#) * p\size + p\y
		p1x = Cos(i       * 360.0 / p\seg + p\rot#) * p\size + p\x
		p1y = Sin(i       * 360.0 / p\seg + p\rot#) * p\size + p\y
		p2x = Cos((i + 1) * 360.0 / p\seg + p\rot#) * p\size + p\x
		p2y = Sin((i + 1) * 360.0 / p\seg + p\rot#) * p\size + p\y
		
		Color 0, 0, 0
		lx = p1x + (p1x - LightX) * 1000
		ly = p1y + (p1y - LightY) * 1000
		If Cull(p1x, p1y, p2x, p2y) <> Cull(p0x, p0y, p1x, p1y) Then
			ClipLine(p1x, p1y, lx, ly)
			If po1x = -1 Then
				po1x = p1x
				po1y = p1y
				po1lx = ClipX
				po1ly = ClipY
			Else
				po2x = p1x
				po2y = p1y
				po2lx = ClipX
				po2ly = ClipY
			EndIf
		EndIf
	Next
	If po1x <> -1 And po2x <> -1 Then
		TriangleFlat(po1x, po1y, po2x, po2y, po2lx, po2ly, $004080)
		TriangleFlat(po1x, po1y, po1lx, po1ly, po2lx, po2ly, $004080)
	EndIf
Next
For p.Polygon = Each Polygon
	po1x = -1
	p0x = Cos(p\rot#) * p\size + p\x
	p0y = Sin(p\rot#) * p\size + p\y
	For i = 1 To p\seg - 2
		p1x = Cos(i       * 360.0 / p\seg + p\rot#) * p\size + p\x
		p1y = Sin(i       * 360.0 / p\seg + p\rot#) * p\size + p\y
		p2x = Cos((i + 1) * 360.0 / p\seg + p\rot#) * p\size + p\x
		p2y = Sin((i + 1) * 360.0 / p\seg + p\rot#) * p\size + p\y
		TriangleFlat(p0x, p0y, p1x, p1y, p2x, p2y, $007700)
	Next
Next
UnlockBuffer()
Color 255, 255, 0
Oval LightX - 5, LightY - 5, 10, 10
End Function

Function Cull(p1x, p1y, p2x, p2y)
e1x = p1x - p2x
e1y = p1y - p2y
e2x = p2x - p1x
e2y = p2y - p1y
nx# = (p1x - LightX) * (e1y - e2y)
ny# = (p1y - LightY) * (e2x - e1x)
Return nx# + ny# > 0
End Function

Global ClipX, ClipY
Function ClipLine(p1x, p1y, p2x, p2y)
gx = -GraphicsWidth() * 2
gy = -GraphicsHeight() * 2
gw = GraphicsWidth() * 3
gh = GraphicsHeight() * 3
If p2x < gx Then
	p2y = Intp(gx, p1x, p2x, p1y, p2y)
	p2x = gx
ElseIf p2x > gw
	p2y = Intp(gw, p1x, p2x, p1y, p2y)
	p2x = gw
EndIf
If p2y < gy Then
	p2x = Intp(gy, p1y, p2y, p1x, p2x)
	p2y = gy
ElseIf p2y > gh
	p2x = Intp(gh, p1y, p2y, p1x, p2x)
	p2y = gh
EndIf
ClipX = p2x
ClipY = p2y
End Function

Function Intp(value, vMin, vMax, retMin, retMax)
Return retMin + (value - vMin) * (retMax - retMin) / (vMax - vMin)
End Function







Function TriangleFlat(p1x, p1y, p2x, p2y, p3x, p3y, col = $FFFFFF)
gh = GraphicsHeight() - 1
If p1y > p2y Then
	ptx = p1x
	pty = p1y
	p1x = p2x
	p1y = p2y
	p2x = ptx
	p2y = pty
EndIf
If p2y > p3y Then
	ptx = p2x
	pty = p2y
	p2x = p3x
	p2y = p3y
	p3x = ptx
	p3y = pty
	If p1y > p2y Then
		ptx = p1x
		pty = p1y
		p1x = p2x
		p1y = p2y
		p2x = ptx
		p2y = pty
	EndIf
EndIf
If p1y <> p2y Then
	For y = p1y To p2y
		If y => 0 Then
			If y > gh Then Exit
			x1 = Intp(y, p1y, p3y, p1x, p3x)
			x2 = Intp(y, p1y, p2y, p1x, p2x)
			TriangleFlatLine(x1, x2, y, col)
		EndIf
	Next
EndIf
If p2y <> p3y Then
	For y = p2y To p3y
		If y => 0 Then
			If y > gh Then Exit
			x1 = Intp(y, p1y, p3y, p1x, p3x)
			x2 = Intp(y, p2y, p3y, p2x, p3x)
			TriangleFlatLine(x1, x2, y, col)
		EndIf
	Next
EndIf
End Function
Function TriangleFlatLine(p1x, p2x, y, col)
If p1x = p2x Then Return
If p1x > p2x Then
	ptx = p1x
	p1x = p2x
	p2x = ptx
EndIf
gw = GraphicsWidth() - 1
If p1x < 0 Then p1x = 0 ElseIf p1x > gw Then p1x = gw
If p2x < 0 Then p2x = 0 ElseIf p2x > gw Then p2x = gw
x = p1x
While x < p2x
	WritePixelFast x, y, col
	x = x + 1
Wend
End Function


if i find out how to calculate outer shadow edges they will be soft!
bye

looking good so far ;)

cool...

Neat.

The light source must be behind the objects? If the light source is hidden by the object, normally, the whole screen should be shadowed, no?

I found it most interesting.

_33: if you unterstood the technical, so you can adding "shadow-order". This source is good enough for learning.

_33: if you unterstood the technical, so you can adding "shadow-order". This source is good enough for learning.


I've got other projects to worry about right now. And the math expert is not me, but Devils Child.