DEFINT A-Z¶
¶
REDIM gfxbuf(32000) 'FAR 64k array (double-buffer rendering backend)¶
¶
SCREEN 13¶
' Set up a regular 6x6x7 RGB palette (252-color)¶
OUT &H3C8, 0¶
FOR r=0 TO 5: FOR g=0 TO 5: FOR b=0 TO 6¶
OUT &H3C9, r*12.6: OUT &H3C9, g*12.6: OUT &H3C9, b*10.5¶
NEXT b,g,r¶
¶
' Set up a 8x8 bayer-dithering matrix.¶
DIM dither8x8(8,8) AS SINGLE¶
FOR y=0 TO 7: FOR x=0 TO 7¶
q = x XOR y¶
p = (x AND 4)\4 + (x AND 2)*2 + (x AND 1)*16¶
q = (q AND 4)\2 + (q AND 2)*4 + (q AND 1)*32¶
dither8x8(y,x) = ((p+q)) / 64.0¶
NEXT x,y¶
¶
CONST N = 1000¶
DIM starx(N), stary(N), starz(N), starR!(N),starG!(N),starB!(N)¶
'Generate stars¶
FOR c = 1 TO N¶
'random 3D position¶
starx(c) = CINT(RND*1000)-500¶
stary(c) = CINT(RND*1000)-500¶
starz(c) = CINT(RND*400)+1¶
'random RGB color¶
starR!(c) = RND+0.01¶
starG!(c) = RND+0.01¶
starB!(c) = RND+0.01¶
'normalize hue (maximize brightness)¶
maxhue! = starR!(c)¶
IF starG!(c) > maxhue! THEN maxhue! = starG!(c)¶
IF starB!(c) > maxhue! THEN maxhue! = starB!(c)¶
starR!(c) = starR!(c) * (3/maxhue!)¶
starG!(c) = starG!(c) * (3/maxhue!)¶
starB!(c) = starB!(c) * (3/maxhue!)¶
NEXT¶
¶
'Define assembler subroutine for swapping the screen with one from a buffer¶
DIM asmswapscreen(16)¶
DATA 8955,1ee5,5e8b,8b06,a77,5f8e,b802,a000,c08e,b9,317d,fcff,a5f3,5d1f,2ca,0¶
FOR c=0 TO 15: READ s$: asmswapscreen(c) = VAL("&H"+s$): NEXT¶
#include <cmath>¶
#include <cstdio>¶
#include <cstdlib>¶
¶
' Main loop¶
DIM px!(N), py!(N), radius!(N)¶
ambient! = 0.2 / SQR(N)¶
WHILE INKEY$ = ""¶
' Move each star¶
'LOCATE 1: print "Moving stars"¶
FOR c = 1 TO N¶
newz = starz(c) - 10¶
IF newz <= 10 THEN¶
rerandomize:¶
newz = 400 - RND*10¶
starx(c) = CINT(RND*1000)-500¶
stary(c) = CINT(RND*1000)-500¶
END IF¶
starz(c) = newz¶
'Do perspective transformation¶
px!(c) = starx(c) * 100! / starz(c)¶
py!(c) = stary(c) * 80! / starz(c)¶
radius!(c) = 600 / starz(c)¶
IF ABS(px!(c)+radius!(c)) > 230 OR ABS(py!(c)+radius!(c)) > 180 THEN GOTO rerandomize¶
NEXT¶
'LOCATE 1: PRINT "Rendering..."¶
' Render each pixel¶
c& = 0¶
DEF SEG = VARSEG(gfxbuf(0)) '&HA000¶
FOR y = -99 TO 100 STEP 1¶
FOR x = -159 TO 160 STEP 1¶
R! = 0¶
G! = 0¶
B! = 0¶
FOR c = 1 TO N¶
'Determine how much it affects the pixel color¶
distx! = x - px!(c)¶
disty! = y - py!(c)¶
distance! = SQR(distx!*distx! + disty!*disty!)¶
IF distance! < radius!(c) THEN¶
scaleddist! = distance! / radius!(c)¶
sz! = (1 - starz(c) / 400)¶
sz! = (1 - SQR(scaleddist!)) * sz! * sz!¶
R! = R! + starR!(c) * sz! + ambient!¶
G! = G! + starG!(c) * sz! + ambient!¶
B! = B! + starB!(c) * sz! + ambient!¶
END IF¶
NEXT¶
q! = dither8x8(x AND 7, y AND 7)¶
rr = INT(R! * 5 + q!): IF rr>5 THEN rr=5¶
gg = INT(G! * 5 + q!): IF gg>5 THEN gg=5¶
bb = INT(B! * 6 + q!): IF bb>6 THEN bb=6¶
POKE c&, bb + gg*7 + rr*42¶
c& = c& + 1¶
'PSET(x+160, y+100), bb+gg*7+rr*42¶
NEXT x,y¶
' Swap screens¶
DEF SEG = VARSEG(asmswapscreen(0))¶
CALL ABSOLUTE(gfxbuf(), VARPTR(asmswapscreen(0)))¶
WEND¶
int main()¶
{¶
unsigned char Palette[256][3];¶
// Set up a regular 6x6x7 RGB palette (252-color)¶
for(unsigned c=0,r=0; r<6; ++r)¶
for(unsigned g=0; g<6; ++g)¶
for(unsigned b=0; b<7; ++b,++c)¶
Palette[c][0] = r*12.6 + 0.5,¶
Palette[c][1] = g*12.6 + 0.5,¶
Palette[c][2] = b*10.5 + 0.5;¶
// Set up a 8x8 bayer-dithering matrix.¶
float dither8x8[8][8];¶
for(unsigned y=0; y<8; ++y)¶
for(unsigned x=0; x<8; ++x)¶
{¶
unsigned p, q = x ^ y;¶
p = ((x & 4)>>2) + ((x & 2)<<1) + ((x&1)<<4);¶
q = ((q & 4)>>1) + ((q & 2)<<2) + ((q&1)<<5);¶
dither8x8[y][x] = ((p+q)) / 64.0f;¶
}¶
const unsigned N = 1000;¶
int starx[N], stary[N], starz[N];¶
float starR[N], starG[N], starB[N];¶
// Generate stars¶
for(unsigned c=0; c<N; ++c)¶
{¶
// random 3D position¶
starx[c] = int(0.5+std::rand()*1000.0/RAND_MAX)-500;¶
stary[c] = int(0.5+std::rand()*1000.0/RAND_MAX)-500;¶
starz[c] = int(0.5+std::rand()*400.0/RAND_MAX)+1;¶
// random RGB color¶
starR[c] = std::rand()/float(RAND_MAX)+0.01;¶
starG[c] = std::rand()/float(RAND_MAX)+0.01;¶
starB[c] = std::rand()/float(RAND_MAX)+0.01;¶
// normalize hue (maximize brightness)¶
float maxhue = starR[c];¶
if(starG[c] > maxhue) maxhue = starG[c];¶
if(starB[c] > maxhue) maxhue = starB[c];¶
starR[c] *= 3/maxhue;¶
starG[c] *= 3/maxhue;¶
starB[c] *= 3/maxhue;¶
}¶
// Main loop¶
float px[N], py[N], radius[N];¶
const float ambient = 0.2 / std::sqrt(N);¶
for(;;)¶
{¶
// Move each star¶
for(unsigned c=0; c<N; ++c)¶
{¶
int newz = starz[c] - 2;¶
if(newz <= 10)¶
{¶
rerandomize:¶
newz = 400 - std::rand()*10.0/RAND_MAX;¶
starx[c] = int(0.5 + std::rand()*1000.0/RAND_MAX)-500;¶
stary[c] = int(0.5 + std::rand()*1000.0/RAND_MAX)-500;¶
}¶
starz[c] = newz;¶
// Do perspective transformation¶
px[c] = starx[c] * 200.0f / starz[c];¶
py[c] = stary[c] * 180.0f / starz[c];¶
radius[c] = 900.0f / starz[c];¶
if(std::fabs(px[c]+radius[c]) > 230¶
|| std::fabs(py[c]+radius[c]) > 180) goto rerandomize;¶
}¶
¶
PRINT "Done"¶
END¶
unsigned char Frame[640*400*3];¶
// Render each pixel¶
#pragma omp parallel for¶
for(int y=-99; y<=100; ++y)¶
{¶
unsigned fptr = ((y+99)*2 * 640) * 3;¶
for(int x=-159; x<=160; ++x)¶
{¶
float R = 0, G = 0, B = 0;¶
for(unsigned c=0; c<N; ++c)¶
{¶
// Determine how much it affects the pixel color¶
float distx = x - px[c];¶
float disty = y - py[c];¶
float distance = std::sqrt(distx*distx + disty*disty);¶
if(distance < radius[c])¶
{¶
float scaleddist = distance / radius[c];¶
float sz = (1 - starz[c] / 400.0f);¶
sz = (1 - std::sqrt(scaleddist)) * sz*sz;¶
R += starR[c] * sz + ambient;¶
G += starG[c] * sz + ambient;¶
B += starB[c] * sz + ambient;¶
} }¶
float q = dither8x8[x & 7][y & 7];¶
int rr = int(R * 5 + q); if(rr > 5) rr = 5;¶
int gg = int(G * 5 + q); if(gg > 5) gg = 5;¶
int bb = int(B * 6 + q); if(bb > 6) bb = 6;¶
int color = bb + gg*7 + rr*42;¶
const unsigned offstab[4] = {0,3, 640*3, 641*3};¶
for(unsigned p=0; p<4; ++p)¶
for(unsigned c=0; c<3; ++c)¶
Frame[fptr+offstab[p]+c] = Palette[color][c]*4;¶
fptr += 6;¶
}¶
}¶
static unsigned screenno = 0;¶
std::fprintf(stderr, "screen %u...\n", screenno++);¶
std::fflush(stderr);¶
std::fwrite(Frame, 3, 640*400, stdout);¶
}¶
std::fprintf(stderr, "Done, end.\n");¶
}¶