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 +=...