#AppType Console
#Include <Include/Windows.inc>
Dim %NZ[511, 511], !WB[1024, 384 To 768], !WX[1023, 384 To 767], !WY[1023, 384 To 767]
Dim %Col[1023, 767], %CC[128, 8]
Dim FC, SX, SY, $PS * 64
SetWindowLong(ME, GWL_STYLE, &H6000000)
Resize(ME, 0, 0, 1024, 768)
Center(ME): Show(ME)
Begin Events
Select Case CBMSG
Case WM_NCHITTEST
Return HTCAPTION
Case WM_COMMAND
If CBWPARAM = 2 Then PostMessage(ME, WM_CLOSE, 0, 0)
Case WM_PAINT
InvalidateRect(ME, NULL, FALSE)
Render(BeginPaint(ME, PS)): EndPaint(ME, PS): Return 0
End Select
End Events
Sub Render(hDC)
Initialize()
Sky()
Colorize()
Water()
Air(hDC)
End Sub
Sub Initialize()
Dim x, y, d = 64, d2 = 128, gtc = GetTickCount()
Print "Running Initialize() ";
Randomize
Do
For y = 0 To 511 Step d2
For x = 0 To 511 Step d2
NZ[(x + d) BAnd 511, y] = (NZ[x, y] + NZ[(x + d2) BAnd 511, y]) * 0.5 + d * (Rnd() - 0.5)
NZ[x, (y + d) BAnd 511] = (NZ[x, y] + NZ[x, (y + d2) BAnd 511]) * 0.5 + d * (Rnd() - 0.5)
NZ[(x + d) BAnd 511, (y + d) BAnd 511] = (NZ[x, y] + NZ[(x + d2) BAnd 511, (y + d2) BAnd 511] + NZ[x, (y + d2) BAnd 511] + NZ[(x + d2) BAnd 511, y]) * 0.25 + d * (Rnd() - 0.5)
Next
Next
If d = 1 Then Exit Do
d = d \ 2: d2 = d + d
Loop
Print GetTickCount() - gtc, " msec"
End Sub
Sub Air(hDC)
Dim x, y, c, k1, k2, s, gtc = GetTickCount()
Print "Running Air() ";
For y = 0 To 767
k1 = (1 - Abs(383.5 - y) / 384) ^ 5
For x = 0 To 1023
If y = SY Then
k2 = 0.25
Else
k2 = ATn((x - SX) / (y - SY)) / M_TWOPI + 0.25
End If
If y - SY < 0 Then k2 = k2 + 0.5
k2 = BN(k2 * 512, 0) * 0.03
k2 = 0.2 - k2 ^ 2: If k2 < 0 Then k2 = 0
s = 30 / SqR((x - SX) ^ 2 + (y - SY) ^ 2)
If s > 1 Then s = 1
c = Lerp(&HFFFFFF, FC, k2 * (1 - s))
SetPixelV(hDC, x, y, Lerp(c, Col[x, y], k1))
Next
Next
Print GetTickCount() - gtc, " msec"
End Sub
Sub Water()
Dim x, y, x1, y1, k, kx, sx1, sy1, sx2, sy2, gtc = GetTickCount()
Print "Running Water() ";
For y = 767 DownTo 384
k = (y - 383) * 0.5: kx = (900 - y) / 580
For x = 1023 DownTo 0
sy1 = 64000 / (y - 380)
sx1 = (x - 511.5) * sy1 * 0.002
sy2 = sy1 * 0.34 - sx1 * 0.71
sx2 = sx1 * 0.34 + sy1 * 0.71
sy1 = sy2 * 0.34 - sx2 * 0.21
sx1 = sx2 * 0.34 + sy2 * 0.21
WB[x, y] = BN(sx1, sy1) - BN(sx2, sy2)
WX[x, y] = (WB[x + 1, y] - WB[x, y]) * k * kx
WY[x, y] = (WB[x, y + 1] - WB[x, y]) * k
x1 = Abs(x + WX[x, y])
y1 = 768 - y + WY[x, y]
If y1 < 0 Then
y1 = 0
ElseIf y1 > 383 Then
y1 = 383
End If
Col[x, y] = Lerp(BC(x1 / 8 / 2, y1 / 48 / 2), &H251510, kx) ' water tint
Next
Next
Print GetTickCount() - gtc, " msec"
End Sub
Sub Sky()
Dim x, y, c1, c2, k, s, sx1, sy1, dy, gtc = GetTickCount()
Print "Running Sky() ";
SX = 100 + Rnd() * 824: SY = 192 + Rnd() * 157
For y = 0 To 383
sy1 = 100000 / (390 - y)
For x = 0 To 1023
sx1 = (x - 511.5) * sy1 * 0.0005
k = BN(sx1, sy1) - BN(sx1 * 0.14 + sy1 * 0.21, sy1 * 0.14 - sx1 * 0.21)
If k < -8 Then
k = 0
Else
k = (k + 8) * 0.02 ' cloud density
End If
If k > 1 Then k = 1
dy = y / 384
FC = &H908000 + (SY + 500) * 0.2 ' haze tint
c1 = Lerp(FC + 25, &H906050, dy)
c2 = Lerp(&H807080, &HD0D0D0, dy)
s = 30 / SqR((x - SX) ^ 2 + (y - SY) ^ 2) ' sun size
If s > 1 Then s = 1
c1 = Lerp(&HFFFFFF, c1, s)
Col[x, y] = Lerp(c2, c1, k)
Next
Next
Print GetTickCount() - gtc, " msec"
End Sub
Sub Colorize()
Dim x, y, xx, yy, c, r, g, b, gtc = GetTickCount()
Print "Running Colorize() ";
For x = 0 To 127
For y = 0 To 7
Let(r, g, b) = 0
For yy = 0 To 47
For xx = 0 To 7
c = Col[xx + x * 8, yy + y * 48]
r = r + (c BAnd &HFF)
g = g + (c BAnd &HFF00)
b = b + ((c BAnd &HFF0000) >> 8)
Next
Next
CC[x, y] = r \ 384 + ((g \ 384) BAnd &HFF00) + (((b \ 384) BAnd &HFF00) << 8)
Next
CC[x, 8] = CC[x, 7]
Next
Print GetTickCount() - gtc, " msec"
End Sub
Function BC(x, y)
Dim ix = Floor(x), iy = Floor(y), SX = x - ix, SY = y - iy, c0, c1, c2, c3
Dim ixy = (1 - SX) * (1 - SY), isxy = SX * (1 - SY), isyx = SY * (1 - SX), xy = SX * SY
c0 = CC[ix BAnd 127, iy Mod 9]
c1 = CC[(ix + 1) BAnd 127, iy Mod 9]
c2 = CC[ix BAnd 127, (iy + 1) Mod 9]
c3 = CC[(ix + 1) BAnd 127, (iy + 1) Mod 9]
Return (c0 BAnd &HFF) * ixy + (c1 BAnd &HFF) * isxy + (c2 BAnd &HFF) * isyx + (c3 BAnd &HFF) * xy + _
((c0 BAnd &HFF00) * ixy + (c1 BAnd &HFF00) * isxy + (c2 BAnd &HFF00) * isyx + (c3 BAnd &HFF00) * xy BAnd &HFF00) + _
((c0 BAnd &HFF0000) * ixy + (c1 BAnd &HFF0000) * isxy + (c2 BAnd &HFF0000) * isyx + (c3 BAnd &HFF0000) * xy BAnd &HFF0000)
End Function
Function BN(x, y)
Dim ix = Floor(x), iy = Floor(y), SX = x - ix, SY = y - iy, isx = 1 - SX, isy = 1 - SY, dx = (ix + 1) BAnd 511, dy = (iy + 1) BAnd 511
ix = ix BAnd 511: iy = iy BAnd 511
Return NZ[ix, iy] * isx * isy + NZ[dx, iy] * SX * isy + NZ[ix, dy] * isx * SY + NZ[dx, dy] * SX * SY
End Function
Function Lerp(c1, c2, k)
Return((c1 BAnd &HFF) * k + (c2 BAnd &HFF) * (1 - k)) BOr (((c1 BAnd &HFF00) * k + (c2 BAnd &HFF00) * (1 - k)) BAnd &HFF00) BOr (((c1 BAnd &HFF0000) * k + (c2 BAnd &HFF0000) * (1 - k)) BAnd &HFF0000)
End Function