File size: 4,797 Bytes
d069959 fa8d333 d069959 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Procedural Terrain</title>
<style>
body { margin: 0; overflow: hidden; }
#controls {
position: fixed;
top: 20px;
left: 20px;
background: rgba(0,0,0,0.7);
padding: 20px;
border-radius: 10px;
color: white;
font-family: Arial, sans-serif;
}
.control-group {
margin: 10px 0;
}
label {
display: inline-block;
width: 120px;
}
input[type="range"] {
width: 200px;
}
</style>
</head>
<body>
<div id="controls">
<div class="control-group">
<label>Height Scale:</label>
<input type="range" id="heightScale" min="0" max="100" value="20">
</div>
<div class="control-group">
<label>Water Level:</label>
<input type="range" id="waterLevel" min="0" max="50" value="10">
</div>
<div class="control-group">
<label>Roughness:</label>
<input type="range" id="roughness" min="0" max="10" value="3" step="0.1">
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
let scene, camera, renderer, terrain, water;
const size = 128;
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Add lighting
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
directionalLight.position.set(1, 1, 1);
scene.add(directionalLight);
camera.position.set(50, 50, 50);
camera.lookAt(0, 0, 0);
createTerrain();
createWater();
animate();
}
function createTerrain() {
const geometry = new THREE.PlaneGeometry(100, 100, size, size);
const material = new THREE.MeshPhongMaterial({
color: 0x808080,
wireframe: false,
flatShading: true
});
terrain = new THREE.Mesh(geometry, material);
terrain.rotation.x = -Math.PI / 2;
scene.add(terrain);
updateTerrain();
}
function createWater() {
const geometry = new THREE.PlaneGeometry(100, 100);
const material = new THREE.MeshPhongMaterial({
color: 0x0077ff,
transparent: true,
opacity: 0.6
});
water = new THREE.Mesh(geometry, material);
water.rotation.x = -Math.PI / 2;
scene.add(water);
}
function updateTerrain() {
const heightScale = document.getElementById('heightScale').value;
const roughness = document.getElementById('roughness').value;
const vertices = terrain.geometry.attributes.position.array;
for(let i = 0; i < vertices.length; i += 3) {
const x = i / 3 % (size + 1);
const y = Math.floor(i / 3 / (size + 1));
vertices[i + 2] = generateHeight(x, y) * heightScale / 20;
}
terrain.geometry.attributes.position.needsUpdate = true;
terrain.geometry.computeVertexNormals();
}
function generateHeight(x, y) {
const roughness = document.getElementById('roughness').value;
return (Math.sin(x/10 * roughness) + Math.sin(y/10 * roughness)) / 2;
}
function updateWater() {
const waterLevel = document.getElementById('waterLevel').value;
water.position.y = waterLevel / 5;
}
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
updateWater();
}
// Event Listeners
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
document.getElementById('heightScale').addEventListener('input', updateTerrain);
document.getElementById('roughness').addEventListener('input', updateTerrain);
init();
</script>
</body>
</html> |