38 lines
1.7 KiB
Python
38 lines
1.7 KiB
Python
# Writes a procedural equirectangular sky (blue gradient, haze at the horizon, a sun, a plain
|
|
# ground) as a PNG for the test scenes; a real HDRI drops in the same way.
|
|
# Usage: python3 util/makeSky.py testScripts/sky.png [width]
|
|
import sys, math
|
|
import numpy as np
|
|
from PIL import Image
|
|
out = sys.argv[1]
|
|
W = int(sys.argv[2]) if len(sys.argv) > 2 else 1024
|
|
H = W // 2
|
|
v = (np.arange(H) + 0.5) / H
|
|
u = (np.arange(W) + 0.5) / W
|
|
theta = v * math.pi # 0 at the zenith
|
|
phi = (u - 0.5) * 2 * math.pi # 0 faces -Z
|
|
T, P = np.meshgrid(theta, phi, indexing='ij')
|
|
y = np.cos(T)
|
|
x = np.sin(T) * np.sin(P)
|
|
z = -np.sin(T) * np.cos(P)
|
|
img = np.zeros((H, W, 3))
|
|
# Sky: deep blue overhead to pale at the horizon.
|
|
t = np.clip(y, 0, 1)
|
|
sky = (1 - t)[..., None] * np.array([0.72, 0.80, 0.92]) + t[..., None] * np.array([0.20, 0.42, 0.85])
|
|
# Sun toward +X, high up, with a soft glow.
|
|
sun = np.array([0.55, 0.65, -0.52]); sun /= np.linalg.norm(sun)
|
|
cosang = x * sun[0] + y * sun[1] + z * sun[2]
|
|
glow = np.exp((cosang - 1) * 60) * 1.5 + np.exp((cosang - 1) * 700) * 6.0
|
|
sky += glow[..., None] * np.array([1.0, 0.95, 0.85])
|
|
# Haze just above the horizon.
|
|
haze = np.exp(-np.abs(y) * 12) * 0.35
|
|
sky += haze[..., None] * np.array([0.9, 0.85, 0.8])
|
|
# Ground: a muted olive that darkens straight down.
|
|
g = np.clip(-y, 0, 1)
|
|
ground = (1 - g)[..., None] * np.array([0.45, 0.42, 0.34]) + g[..., None] * np.array([0.22, 0.20, 0.16])
|
|
img = np.where((y >= 0)[..., None], sky, ground)
|
|
# To sRGB bytes; the engine decodes PNG skies back to linear.
|
|
img = np.clip(img, 0, 1)
|
|
srgb = np.where(img <= 0.0031308, img * 12.92, 1.055 * np.power(img, 1 / 2.4) - 0.055)
|
|
Image.fromarray((srgb * 255).astype(np.uint8)).save(out)
|
|
print(out, W, H)
|