Generate Sky Dome Texture

by Ben Gillbanks

CSS

body {
	margin: 0;
	background: #111;
}

canvas {
	width: 512px;
	height: 256px;
	image-rendering: pixelated;
}

JavaScript

const canvas = document.createElement( 'canvas' );
const ctx = canvas.getContext( '2d' );

document.body.appendChild( canvas );

const settings = {
	width: 256,
	height: 128,

	skyTop: '#4f79aa',
	skyMid: '#9fc3dd',
	horizon: '#e7d6b8',

	groundNear: '#405f68',
	groundFar: '#8aa3a8',

  groundType: 'land', // 'land' or 'water'

  reflectionStrength: 0.7,
  reflectionBlur: 2,
  reflectionBrightness: 2,
  reflectionRipple: 0.02,

  landHorizon: '#526f72',
  landNear: '#354d34',
  landPatch: '#20382d',
  landPatchCount: 90,
  landPatchAlpha: 0.12,
  landBottom: '#3f5a40',
  terrainSeed: Math.random() * 1000,

	sunX: 0.72,
	sunHeight: 0.2, // -0.5 = below horizon, 0 = horizon, 0.5 = high noon
  sunSize: 0.12,
  sunGlowSize: 0.35,
  sunBrightness: 3.0,

  cloudStyle: 'mixed', // 'wispy', 'puffy', 'mixed'
  cloudCoverage: 0.6, // 0 to 1
  cloudWind: 1.0, // horizontal stretch
  cloudCount: 28,
  cloudColour: '#ffffff',
  cloudShadow: '#9bb3c2',
  cloudAlpha: 0.22,
  cloudMinY: 0.12,
  cloudMaxY: 0.46,

	grain: 0.025
};

canvas.width = settings.width;
canvas.height = settings.height;

function hexToRgb( hex ) {
	hex = hex.replace( '#', '' );

	return {
		r: parseInt( hex.slice( 0, 2 ), 16 ),
		g: parseInt( hex.slice( 2, 4 ), 16 ),
		b: parseInt( hex.slice( 4, 6 ), 16 )
	};
}

function clamp( value, min, max ) {
	return Math.max( min, Math.min( max, value ) );
}

function mix( a, b, t ) {
	return a + ( b - a ) * t;
}

function smoothstep( edge0, edge1, value ) {
	const t = clamp( ( value - edge0 ) / ( edge1 - edge0 ), 0, 1 );
	return t * t * ( 3 - t * 2 );
}

function mixColour( a, b, t ) {
	return {
		r: mix( a.r, b.r, t ),
		g: mix( a.g, b.g, t ),
		b: mix( a.b, b.b, t )
	};
}

function wrapDistance( a, b ) {
	const diff = Math.abs( a - b );
	return Math.min( diff, 1 - diff );
}

function waveNoise( u, v ) {
	let value = 0;

	value += Math.sin( u * Math.PI * 2 );
	value +=...