Dark Bit Factory & Gravity
PROGRAMMING => Other languages => Yabasic => Topic started by: rain_storm on October 29, 2009
-
This is a nice lighting effect applied to a cube, It uses the surface normals to calculate the lighting.
Press up/down/left/right to move the light vertically/horizontally
Press triangle/cross to move the light in/out
//
// Demonstration of how to calculate lighting effects
// An improvement to this meathod would be to use a
// per vertex lighting algorithm
//
FALSE = 0
TRUE = 1
DEBUG = FALSE
label Init
open window 640, 512
window origin "cc"
UP = 16
RT = 32
DN = 64
LF = 128
TR = 8192
EX = 16384
label Vertices
read verts
dim px(verts), py(verts), pz(verts)
dim nx(verts), ny(verts), nz(verts)
dim tx(verts), ty(verts)
for i = 0 to verts
read px(i), py(i), pz(i)
next i
label Polygons
read polys
dim p1(polys), p2(polys), p3(polys), p4(polys)
for i = 0 to polys
read p1(i), p2(i), p3(i), p4(i)
next i
label Colours
dim r1(polys), g1(polys), b1(polys)
dim r2(polys), g2(polys), b2(polys)
dim r3(polys), g3(polys), b3(polys)
dim r4(polys), g4(polys), b4(polys)
for i = 0 to polys
read r1(i), g1(i), b1(i)
read r2(i), g2(i), b2(i)
read r3(i), g3(i), b3(i)
read r4(i), g4(i), b4(i)
next i
label Lighting
litX = -64.0
litY = -64.0
litZ = -64.0
Ambient = 0.1
label Camera
camX = 0.0000
camY = 0.0000
camZ = -256.0
Aspect = 512.0
label Loop
c = peek("port1")
if (and(c, UP) > 0) litY = litY - 1.0
if (and(c, RT) > 0) litX = litX + 1.0
if (and(c, DN) > 0) litY = litY + 1.0
if (and(c, LF) > 0) litX = litX - 1.0
if (and(c, TR) > 0) litZ = litZ + 1.0
if (and(c, EX) > 0) litZ = litZ - 1.0
rotX = rotX + 0.0100
rotY = rotY + 0.0020
rotZ = rotZ + 0.0003
Rotate(rotX, rotY, rotZ, -camX,-camY,-camZ)
Render()
goto Loop
sub Rotate(rx,ry,rz, ox,oy,oz)
local cx,cy,cz, sx,sy,sz, px,py,pz, nx,ny,nz, tx,ty,tz
cx = cos(rx)
sx = sin(rx)
cy = cos(ry)
sy = sin(ry)
cz = cos(rz)
sz = sin(rz)
for i = 0 to verts
px = px(i)
py = py(i)
pz = pz(i)
nx = cz*px + sz*py
ny = cz*py - sz*px
nz = cy*pz + sy*nx
tx = cy*nx - sy*pz
ty = cx*ny + sx*nz
tz = cx*nz - sx*ny
nx(i) = tx
ny(i) = ty
nz(i) = tz
tz = Aspect/(tz+oz)
tx(i) = (tx+ox)*tz
ty(i) = (ty+oy)*tz
next i
end sub
sub Render()
setdispbuf draw
draw = 1 - draw
setdrawbuf draw
setrgb 1, 015, 015, 063
setrgb 2, 015, 015, 063
setrgb 3, 063, 063, 255
gtriangle -320.0,256.00 to 320.00,256.00 to 320.00,-256.0
setrgb 2, 063, 063, 255
gtriangle -320.0,256.00 to -320.0,-256.0 to 320.00,-256.0
//
// Draw a white circle for the light
if (litZ >= 0.0) then
setrgb 1, 255, 255, 255
lz = Aspect/(litZ-camZ)
lx = litX*lz
ly = litY*lz
fill circle lx, ly, 10
endif
for i = 0 to polys
x1 = tx(p1(i))
y1 = ty(p1(i))
x2 = tx(p2(i))
y2 = ty(p2(i))
x3 = tx(p3(i))
y3 = ty(p3(i))
x4 = tx(p4(i))
y4 = ty(p4(i))
cp = (x1-x2)*(y3-y2) - (x3-x2)*(y1-y2)
if (cp > 0) then
nx1 = nx(p1(i))
ny1 = ny(p1(i))
nz1 = nz(p1(i))
nx2 = nx(p2(i))
ny2 = ny(p2(i))
nz2 = nz(p2(i))
nx3 = nx(p3(i))
ny3 = ny(p3(i))
nz3 = nz(p3(i))
nx4 = nx(p4(i))
ny4 = ny(p4(i))
nz4 = nz(p4(i))
//
// Calculate the midpoint of polygon
cx = (nx1+nx2+nx3+nx4)*0.25
cy = (ny1+ny2+ny3+ny4)*0.25
cz = (nz1+nz2+nz3+nz4)*0.25
//
// Calculate the normal vector using cross-product
nx = (nz1-nz2)*(ny3-ny2) - (ny1-ny2)*(nz3-nz2)
ny = (nx1-nx2)*(nz3-nz2) - (nz1-nz2)*(nx3-nx2)
nz = (ny1-ny2)*(nx3-nx2) - (nx1-nx2)*(ny3-ny2)
//
// Calculate the lighting vector
lx = litX - cx
ly = litY - cy
lz = litZ - cz
//
// Calculate length of the normal & lighting vectors
n = 1.0/sqrt(nx*nx + ny*ny + nz*nz)
l = 1.0/sqrt(lx*lx + ly*ly + lz*lz)
//
// Normalise the normal & lighting vectors
nx = n*nx
ny = n*ny
nz = n*nz
lx = l*lx
ly = l*ly
lz = l*lz
//
// Calculate dot-product of normal & lighting vectors
dp = max(Ambient, nx*lx + ny*ly + nz*lz + Ambient)
//
// Scale colour channels by dot-product
setrgb 1, r1(i)*dp, g1(i)*dp, b1(i)*dp
setrgb 2, r2(i)*dp, g2(i)*dp, b2(i)*dp
setrgb 3, r3(i)*dp, g3(i)*dp, b3(i)*dp
gtriangle x1, y1 to x2, y2 to x3, y3
setrgb 2, r4(i)*dp, g4(i)*dp, b4(i)*dp
gtriangle x1, y1 to x4, y4 to x3, y3
//
// Debug view of surface normals & midpoints
if (DEBUG = TRUE) then
pz = Aspect/(nz*60-camZ)
py = ny*pz*60
px = nx*pz*60
cz = Aspect/(cz-camZ)
cy = cy*cz
cx = cx*cz
setrgb 1, 255, 255, 000
line cx, cy to px, py
line x1, y1 to px, py
line x2, y2 to px, py
line x3, y3 to px, py
line x4, y4 to px, py
line x1, y1 to cx, cy
line x2, y2 to cx, cy
line x3, y3 to cx, cy
line x4, y4 to cx, cy
line x1, y1 to x2, y2
line x2, y2 to x3, y3
line x3, y3 to x4, y4
line x4, y4 to x1, y1
endif
endif
next i
//
// Draw a white circle for the light
if (litZ < 0.0) then
setrgb 1, 255, 255, 255
lz = Aspect/(litZ-camZ)
lx = litX*lz
ly = litY*lz
fill circle lx, ly, 10
endif
//
// Display data
setrgb 1, 255, 255, 255
text -300,-240, "ROTX : " + str$(rotX)
text -300,-220, "ROTY : " + str$(rotY)
text -300,-200, "ROTZ : " + str$(rotZ)
text -300,-180, "LITX : " + str$(litX)
text -300,-160, "LITY : " + str$(litY)
text -300,-140, "LITZ : " + str$(litZ)
end sub
label Model
data 7 // verts
data -30.0,30.00,30.00
data -30.0,-30.0,30.00
data -30.0,30.00,-30.0
data -30.0,-30.0,-30.0
data 30.00,30.00,30.00
data 30.00,-30.0,30.00
data 30.00,30.00,-30.0
data 30.00,-30.0,-30.0
data 5 // polys
data 2,0,4,6
data 7,5,1,3
data 3,1,0,2
data 6,4,5,7
data 0,1,5,4
data 3,2,6,7
data 000,255,000, 255,000,000, 000,000,255, 200,200,200
data 063,063,063, 255,000,255, 255,255,000, 000,255,255
data 000,255,255, 255,255,000, 255,000,000, 000,255,000
data 200,200,200, 000,000,255, 255,000,255, 063,063,063
data 255,000,000, 255,255,000, 255,000,255, 000,000,255
data 000,255,255, 000,255,000, 200,200,200, 063,063,063
-
Nice effect, I typed it on my clapped out PS2 from the DSi
Wenlock
-
That's a really nice example of how light sourcing should be done there Rainstorm, thanks for posting it :)
K+
-
Hey! This is going to be very useful for me in the future.
Thanks!