Low-poly Island
Generate a low poly 3D ISLAND with a noise algo by notchris
by notchris
HTML
<script>
if (!window) {
var window = {}
} else if (!module) {
var module = {}
}
window.crusoe = module.exports = (function () {
function getColor (n, colors) {
if (n > 0.9) {
return colors.A
} else if (n > 0.8) {
return colors.B
} else if (n > 0.7) {
return colors.C
} else if (n > 0.5) {
return colors.D
} else if (n > 0) {
return colors.E
} else if (n > -0.1) {
return colors.F
} else if (n > -0.15) {
return colors.G
} else if (n > -0.2) {
return colors.H
} else if (n > -0.25) {
return colors.I
} else if (n > -0.3) {
return colors.J
} else if (n > -0.35) {
return colors.K
} else {
return colors.L
}
}
var defaultOptions = {
width: 100,
height: 100,
noiseReduction: 10,
seed: 0,
size: 1,
elevation: 3,
lakeSize: 3,
curve: 1
}
function generateMap (options) {
options = Object.assign({}, defaultOptions, options)
var width = options.width
var height = options.height
var seed = options.seed
var size = options.size - 1
var curve = options.curve * 2
var elevation = -2 + options.elevation
var lakeSize = options.lakeSize
var scale = options.noiseReduction
var scaleHalf = scale / 2
var scale2 = scale * 2
var islandW = width * 0.5
var islandH = height * 0.5
var diagonalHalf = Math.sqrt(width * width + height * height)
noise.seed(seed)
var data = []
for (var x = 0; x < width; x++) {
data[x] = []
for (var y = 0; y < height; y++) {
var dist = Math.sqrt(Math.pow((x - width / 2) / islandW, 2) + Math.pow((y - height / 2) / islandH, 2))
var islandFactor = (dist < diagonalHalf ? Math.cos(dist * Math.PI / 2) + size : -10) * 4 * curve
var terrainFactor = (noise.simplex2(x / scale, y / scale) + noise.perlin2(x / scaleHalf, y / scaleHalf)) / 3
var lakeFactor = islandFactor > 0 ? noise.perlin2(x /...
CSS
body {
background-color: #000;
margin: 0px;
overflow: hidden;
}
#canvas {
position: absolute;
top: 0;
left: 0;
image-rendering: pixelated;
}
JavaScript
import * as THREE from "https://cdn.skypack.dev/[email protected]";
import {
OrbitControls
} from "https://cdn.skypack.dev/[email protected]/examples/jsm/controls/OrbitControls";
const options = {
sharpness: 1,
size: 0.8,
resolution: 0.3,
noise: 1.0,
elevation: 2.0,
lakeSize: 2.0,
curve: 2.0
}
let mesh, renderer, scene, camera, controls;
function map(val, smin, smax, emin, emax) {
const t = (val - smin) / (smax - smin)
return (emax - emin) * t + emin
}
const canvas = document.getElementById('canvas')
canvas.width = 25
canvas.height = 25
const ctx = canvas.getContext('2d')
function generateTexture() {
const rendered = crusoe.renderMap(crusoe.generateMap({
seed: Date.now(),
width: 120 * options.resolution,
height: 120 * options.resolution,
size: parseFloat(options.size, 10),
noiseReduction: options.noise,
elevation: options.elevation,
lakeSize: options.lakeSize,
curve: options.curve
}), {
A: '#EEEEEE',
B: '#DDDDDD',
C: '#CCCCCC',
D: '#BBBBBB',
E: '#AAAAAA',
F: '#1d2e5b',
G: '#1d2e5b',
H: '#1d2e5b',
I: '#1d2e5b',
J: '#1d2e5b',
K: '#1d2e5b',
L: '#1d2e5b'
})
for (let x = 0; x < rendered.width; x++) {
for (let y = 0; y < rendered.height; y++) {
ctx.fillStyle = rendered.colors[x][y]
const gridSize = (canvas.width / (120 * options.resolution))
ctx.fillRect(x * gridSize, y * gridSize, gridSize, gridSize)
}
}
return ctx.getImageData(0, 0, canvas.width, canvas.height)
}
init();
animate();
function init() {
let data = generateTexture();
// renderer
renderer = new THREE.WebGLRenderer({
antialias: true
})
renderer.setSize(window.innerWidth, window.innerHeight)
renderer.setPixelRatio(window.devicePixelRatio)
renderer.shadowMap.enabled = true
renderer.shadowMap.type = THREE.PCFSoftShadowMap
document.body.appendChild(renderer.domElement)
// scene
scene = new THREE.Scene();
// camera
const aspect =...