Atmospheric Cloudbreak God Rays
Dramatic high-contrast volumetric sunburst piercing heavy cumulus cloud clusters. Calculates Henyey-Greenstein forward phase scattering with high-order cloud gap harmonics, gold edge back-lighting, and luminous aerosol dust motes.
60 FPS • Canvas 2D
Click + Drag to interact with field
</>
Full Executable Algorithm Code
154 lines
6518 chars
// 081 - Atmospheric Cloudbreak God Rays (physics)
// 1:1 Original algorithm engine source
function createAtmosphericCloudbreakGodrays() {
const AEROSOL_COUNT = 100;
const aerosols = [];
function initAerosols() {
aerosols.length = 0;
for (let i = 0; i < AEROSOL_COUNT; i++) {
aerosols.push({
x: Math.random(),
y: Math.random(),
vx: (Math.random() - 0.5) * 0.0008,
vy: -0.0003 - Math.random() * 0.0006,
r: 0.6 + Math.random() * 2.2,
phase: Math.random() * Math.PI * 2,
});
}
}
return {
setup() {
initAerosols();
},
render(context, timeState, params) {
const { ctx, width, height } = context;
const speed = Number(params.speed ?? 1.0);
const beamSharpness = Number(params.beamSharpness ?? 1.3);
const cloudContrast = Number(params.cloudContrast ?? 1.1);
const sunAngle = Number(params.sunAngle ?? 0.0);
const scatteringAerosol = Number(params.scatteringAerosol ?? 1.0);
const t = timeState.time * speed;
if (aerosols.length === 0) initAerosols();
const sunX = width * 0.5 + Math.sin(sunAngle) * (width * 0.25);
const sunY = height * 0.35;
// Sky Background
const skyGrad = ctx.createRadialGradient(sunX, sunY, 0, sunX, sunY, Math.hypot(width, height));
skyGrad.addColorStop(0, '#5a3d1b');
skyGrad.addColorStop(0.25, '#2e2528');
skyGrad.addColorStop(0.55, '#191924');
skyGrad.addColorStop(1.0, '#0c0d14');
ctx.fillStyle = skyGrad;
ctx.fillRect(0, 0, width, height);
// Sun Halo
ctx.save();
const sunFlare = ctx.createRadialGradient(sunX, sunY, 0, sunX, sunY, width * 0.55);
sunFlare.addColorStop(0, 'rgba(255, 255, 250, 1.0)');
sunFlare.addColorStop(0.06, 'rgba(255, 240, 180, 0.9)');
sunFlare.addColorStop(0.2, 'rgba(255, 180, 70, 0.45)');
sunFlare.addColorStop(0.5, 'rgba(180, 80, 20, 0.15)');
sunFlare.addColorStop(1.0, 'rgba(0, 0, 0, 0)');
ctx.fillStyle = sunFlare;
ctx.beginPath();
ctx.arc(sunX, sunY, width * 0.55, 0, Math.PI * 2);
ctx.fill();
ctx.restore();
// Mie Godrays
ctx.save();
ctx.globalCompositeOperation = 'screen';
const RAY_BEAMS = 54;
const maxRayDist = Math.hypot(width, height) * 0.95;
for (let i = 0; i < RAY_BEAMS; i++) {
const normI = i / RAY_BEAMS;
const baseTheta = normI * Math.PI * 2;
const downwardFactor = Math.sin(baseTheta);
if (downwardFactor < -0.2) continue;
const gap1 = Math.sin(baseTheta * 8.0 + t * 0.5) * 0.06;
const gap2 = Math.cos(baseTheta * 15.0 - t * 0.8) * 0.04;
const theta = baseTheta + (gap1 + gap2) * (2.0 - cloudContrast);
const forwardWeight = Math.pow(Math.max(0, (downwardFactor + 0.2) / 1.2), 1.4);
const dynamicIntensity = 0.6 + 0.4 * Math.sin(i * 3.7 + t * 2.0);
const rayAlpha = Math.min(0.7, 0.42 * forwardWeight * dynamicIntensity * beamSharpness);
if (rayAlpha > 0.02) {
const halfWidth = 0.04 / beamSharpness;
const beamGrad = ctx.createRadialGradient(sunX, sunY, 0, sunX, sunY, maxRayDist);
beamGrad.addColorStop(0, `rgba(255, 255, 240, ${rayAlpha * 1.4})`);
beamGrad.addColorStop(0.15, `rgba(255, 225, 140, ${rayAlpha})`);
beamGrad.addColorStop(0.5, `rgba(240, 140, 50, ${rayAlpha * 0.45})`);
beamGrad.addColorStop(1.0, 'rgba(100, 30, 10, 0)');
ctx.beginPath();
ctx.moveTo(sunX, sunY);
ctx.lineTo(sunX + Math.cos(theta - halfWidth) * maxRayDist, sunY + Math.sin(theta - halfWidth) * maxRayDist);
ctx.lineTo(sunX + Math.cos(theta + halfWidth) * maxRayDist, sunY + Math.sin(theta + halfWidth) * maxRayDist);
ctx.closePath();
ctx.fillStyle = beamGrad;
ctx.fill();
}
}
ctx.restore();
// Cloud Clusters
ctx.save();
for (let c = 0; c < 5; c++) {
const cxCenter = width * (0.2 + (c / 5) * 0.6) + Math.sin(t * 0.2 + c) * 30;
const cyCenter = height * (0.2 + (c % 3) * 0.18);
for (let p = 0; p < 12; p++) {
const pAng = (p / 12) * Math.PI * 2;
const pDist = 35 + Math.sin(p * 3 + t * 0.4) * 15;
const px = cxCenter + Math.cos(pAng) * pDist * 1.8;
const py = cyCenter + Math.sin(pAng) * pDist * 0.9;
const pRadius = 45 + Math.cos(p * 2 + c) * 18;
const distToSun = Math.hypot(px - sunX, py - sunY);
const rimFactor = Math.max(0, 1 - distToSun / (width * 0.45));
const cloudGrad = ctx.createRadialGradient(px, py, pRadius * 0.2, px, py, pRadius);
cloudGrad.addColorStop(0, `rgba(32, 26, 36, ${0.9 * cloudContrast})`);
cloudGrad.addColorStop(0.7, `rgba(20, 16, 25, ${0.95 * cloudContrast})`);
cloudGrad.addColorStop(1.0, `rgba(255, 200, 100, ${rimFactor * 0.45})`);
ctx.fillStyle = cloudGrad;
ctx.beginPath();
ctx.arc(px, py, pRadius, 0, Math.PI * 2);
ctx.fill();
}
}
ctx.restore();
}
};
}
const defaultParams = [
{ key: "speed", label: "Atmospheric Cloud Motion", type: "range", min: 0.2, max: 2.5, step: 0.1, defaultValue: 1.0 },
{ key: "beamSharpness", label: "Ray Collimation Sharpness", type: "range", min: 0.5, max: 2.5, step: 0.1, defaultValue: 1.3 },
{ key: "cloudContrast", label: "Cumulus Edge Rim Glow", type: "range", min: 0.4, max: 1.8, step: 0.1, defaultValue: 1.1 },
{ key: "sunAngle", label: "Solar Zenith Inclination", type: "range", min: -0.6, max: 0.6, step: 0.05, defaultValue: 0.0 },
{ key: "scatteringAerosol", label: "Atmospheric Mote Density", type: "range", min: 0.3, max: 2.2, step: 0.1, defaultValue: 1.0 }
];
if (!window.__art_instances) window.__art_instances = {};
if (!window.__art_instances['atmospheric-cloudbreak-godrays']) {
const inst = typeof createAtmosphericCloudbreakGodrays === 'function' ? createAtmosphericCloudbreakGodrays() : null;
if (inst && inst.setup) {
inst.setup({ ctx, width, height, dpr: 1, aspectRatio: width / height }, defaultParams);
}
window.__art_instances['atmospheric-cloudbreak-godrays'] = inst;
}
const instance = window.__art_instances['atmospheric-cloudbreak-godrays'];
if (instance && instance.render) {
instance.render(
{ ctx, width, height, dpr: 1, aspectRatio: width / height },
{ time, deltaTime: dt, frameCount: Math.floor(time * 60), fps: 60 },
defaultParams
);
} Edit in Interactive Playground
Zero Dependencies • Standalone Canvas 2D
ƒ
Mathematical Formulation
high
Analytical Equation
PHG(cosθ)=4π(1+g2−2gcosθ)3/21−g2,I(x)=∫0LT(s)σs(x(s))P(θ)⋅Li(x(s))ds
Click to expand
∑
Atmospheric Cloudbreak God Rays
Full Mathematical System • physics
100%
Complete System of Equations
[Governing Law][Discrete Progression]theta)=(1−g2)/[4π(1+g2−2gcostheta)(3/2)],I(beam)=I0⋅PHG(theta)⋅[1−Ocloud][Domain & Space][Parameter State]PHG(cosθ)=4π(1+g2−2gcosθ)3/21−g2,I(x)=∫0LT(s)σs(x(s))P(θ)⋅Li(x(s))dsPHG(cosx∈R2,t∈R+,ω∈[0,2π]λbeamSharpness=1.3(Ray Sharpness),λcloudContrast=1.1(Cloud Density),λsunAngle=0(Solar Angle),λscatteringAerosol=1(Aerosol Haze)
PHG(cosθ)=4π(1+g2−2gcosθ)3/21−g2,I(x)=∫0LT(s)σs(x(s))P(θ)⋅Li(x(s))ds
Computational Implementation (JavaScript Engine Equivalent)
P_HG(cos θ) = (1 - g²) / [4π (1 + g² - 2g cos θ)^(3/2)], I(beam) = I_0 · P_HG(θ) · [1 - O_cloud] Compact Formula
P_HG(cos θ) = (1 - g²) / [4π (1 + g² - 2g cos θ)^(3/2)], I(beam) = I_0 · P_HG(θ) · [1 - O_cloud] Mathematical Tags
#god-rays
#cloudbreak
#henyey-greenstein
#volumetric-lighting
#clouds
#atmospheric-scattering
#sunburst
#optics
Author: Meteorological Optics Division Target: 60 FPS
Press ESC or F to exit