rem Phong Shading Demo, By Jim Shaw 16 September 2002

rem triangle points x,y,z,normal x,normal y,normal z
dim tp(3,5)

rem light normal/direction
dim ln(3)
rem light colour
dim lcol(3)

rem ambient colour
dim acol(3)

rem set up some default values for the 1st render
ln(0)=0
ln(1)=0
ln(2)=1
lcol(0)=255
lcol(1)=192
lcol(2)=192

acol(0)=32
acol(1)=32
acol(2)=32

tp(0,0)=220
tp(0,1)=156
tp(0,2)=0
nx = -0.7
ny = 0
nz = 0.5
normalize()
tp(0,3)=nnx
tp(0,4)=nny
tp(0,5)=nnz

tp(1,0)=420
tp(1,1)=156
tp(1,2)=0
nx = 0.7
ny = 0.3
nz = 0.5
normalize()
tp(1,3)=nnx
tp(1,4)=nny
tp(1,5)=nnz

tp(2,0)=320
tp(2,1)=356
tp(2,2)=0
nx = 0.3
ny = -0.5
nz = 0.2
normalize()
tp(2,3)=nnx
tp(2,4)=nny
tp(2,5)=nnz

rem specular highlight power
power=6

rem edge lists to hold the sides of the triangle as we draw then
components = 4
dim rasters(512,2,components)

open window 640,512

repeat
	clear window

	showtriangle()

	clearraster()

	rem draw the triangle edges into rasteredge
	rasteredge(0,1)
	rasteredge(1,2)
	rasteredge(2,0)	

	rem draw the horizontal scans
	for y = 0 to 512
		rasterscan(y)
	next y

	rem get some random values for next time
	randomlight()
	randomcorners()
	power = 3+int(ran(9))

until (1=0)

rem show the original triangle, the normals, and the light direction
sub showtriangle()
	setrgb 1,255,255,255
	text 50,50,"Specular Power : "+str$(power)
	triangle tp(0,0),tp(0,1) to tp(1,0),tp(1,1) to tp(2,0),tp(2,1)
	setrgb 1,255,0,0
	for c = 0 to 2
		nx = tp(c,3)*20
		ny = tp(c,4)*20
		line tp(c,0),tp(c,1) to tp(c,0)+nx,tp(c,1)+ny
	next c
	setrgb 1,255,255,0
'	text 450,300,"Light Direction"
'	nx = ln(0)*20
'	ny = ln(1)*20
'	line 450,320 to 450+nx,320+ny
end sub

sub randomlight()
	nx = ran(2)-1
	ny = ran(2)-1
	nz = ran()+0.5
	normalize()
'	ln(0)=nnx
'	ln(1)=nny
'	ln(2)=nnz
	lcol(0)=192+ran(63)
	lcol(1)=192+ran(63)
	lcol(2)=192+ran(63)
end sub

sub randomcorners()
	for c = 0 to 2
'		nx = ran(2)-1
		if (c=0) nx = ran(-1)
		if (c=1) nx = ran(1)
		ny = ran(2)-1
		nz = ran()+0.5
		normalize()
		tp(c,3)=nnx
		tp(c,4)=nny
		tp(c,5)=nnz
	next c
end sub

sub clearraster()
	for x = 0 to 512
		rasters(x,0,0)=-1
	next x
end sub

sub swapraster(y)
	for i = 0 to components
		rasters(y,1,i) = rasters(y,0,i)
	next i
end sub

sub rasteredge(s,e)

	if (tp(s,1) > tp(e,1)) then
		t = s
		s = e
		e = t
	fi

	dy = tp(e,1)-tp(s,1)
	if (dy = 0) return

	dx = tp(e,0)-tp(s,0)
	dxdy = dx/dy
	x = tp(s,0)

	dnx = tp(e,3)-tp(s,3)
	dnxdy = dnx/dy	
	nx = tp(s,3)
	
	dny = tp(e,4)-tp(s,4)
	dnydy = dny/dy	
	ny = tp(s,4)

	dnz = tp(e,5)-tp(s,5)
	dnzdy = dnz/dy	

	nz = tp(s,5)

	for y = tp(s,1) to tp(e,1)
		offset = 0
		if (rasters(y,0,0) <> -1) then
			if (rasters(y,0,0) > x) then
				swapraster(y)
			else
				offset = 1
			fi
		fi

		rasters(y,offset,0)=x
		rasters(y,offset,1)=nx
		rasters(y,offset,2)=ny
		rasters(y,offset,3)=nz
		x = x + dxdy
		nx = nx + dnxdy
		ny = ny + dnydy
		nz = nz + dnzdy
	next y
end sub

rem normalize (make unit length) the interpolated normal
sub normalize()
	m = nx*nx + ny*ny + nz*nz
	m = 1/sqrt(m)
	nnx = nx * m
	nny = ny * m
	nnz = nz * m
end sub

rem the phong lighting eqation
sub light()
	rem dot product
	i = nnx * ln(0) + nny * ln(1) + nnz * ln(2)
	rem facing away from light
	if (i < 0) i = 0
	rem specular power
	i = i^power
	rem set it!
	r = min(255,acol(0) + i * lcol(0))
	g = min(255,acol(1) + i * lcol(1))
	b = min(255,acol(2) + i * lcol(2))
	setrgb 1,r,g,b
end sub

sub rasterscan(y)

	if (rasters(y,0,0) = -1) return

	dx = rasters(y,1,0)-rasters(y,0,0)
	if (dx = 0) return

	dnx = rasters(y,1,1)-rasters(y,0,1)
	dnxdx = dnx/dx
	nx = rasters(y,0,1)

	dny = rasters(y,1,2)-rasters(y,0,2)
	dnydx = dny/dx
	ny = rasters(y,0,2)

	dnz = rasters(y,1,3)-rasters(y,0,3)
	dnzdx = dnz/dx
	nz = rasters(y,0,3)

	for x = rasters(y,0,0) to rasters(y,1,0)-1
		normalize()
		light()
		fill rectangle x,y to x+1,y+1
		nx = nx + dnxdx
		ny = ny + dnydx
		nz = nz + dnzdx
	next x

end sub


  
