attribute float size; attribute vec3 customColor; varying vec3 vColor; void main() { vColor = customColor; vec4 mvPosition = modelViewMatrix * vec4(position, 1.0); gl_PointSize = size * (300.0 / -mvPosition.z); gl_Position = projectionMatrix * mvPosition; } uniform vec3 color; uniform sampler2D pointTexture; uniform float alphaTest; varying vec3 vColor; void main() { gl_FragColor = vec4(color * vColor, 1.0); gl_FragColor = gl_FragColor * texture2D(pointTexture, gl_PointCoord); if (gl_FragColor.a < alphaTest) discard; } import * as THREE from 'https://unpkg.com/three@0.127.0/build/three.module.js'; let container = document.getElementById('threejs-container'); let scene = new THREE.Scene(); scene.background = new THREE.Color('#fec75c'); let camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 10000); camera.position.z = 250; let renderer = new THREE.WebGLRenderer(); renderer.setPixelRatio(window.devicePixelRatio); renderer.setSize(window.innerWidth, window.innerHeight); container.appendChild(renderer.domElement); let raycaster = new THREE.Raycaster(); let pointer = new THREE.Vector2(); const PARTICLE_SIZE = 20; let particles; initParticles(); animate(); function initParticles() { const geometry = new THREE.IcosahedronGeometry(140, 10); // Second number updates number of points, 6 is less, 8 is more const vertices = geometry.getAttribute('position').array; const colors = new Float32Array(vertices.length); const sizes = new Float32Array(vertices.length / 3); for (let i = 0, l = vertices.length / 3; i < l; i++) { const hue = 180 / 360; const saturation = 0.7; const lightness = 0.2 + 0.1 * (i / l); // Variable lightness const colorIndex = i * 3; const color = new THREE.Color().setHSL(hue, saturation, lightness); colors[colorIndex] = color.r; colors[colorIndex + 1] = color.g; colors[colorIndex + 2] = color.b; sizes[i] = PARTICLE_SIZE * 0.35; } const particleGeometry = new THREE.BufferGeometry(); particleGeometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3)); particleGeometry.setAttribute('customColor', new THREE.BufferAttribute(colors, 3)); particleGeometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1)); const material = new THREE.ShaderMaterial({ uniforms: { color: { value: new THREE.Color(0xffffff) }, pointTexture: { value: new THREE.TextureLoader().load('https://assets-global.website-files.com/65bdc8d1c1d14c7ba1112827/65bef2d8afe1cc2af3470926_disc.png') }, alphaTest: { value: 0.9 } }, vertexShader: document.getElementById('vertexshader').textContent, fragmentShader: document.getElementById('fragmentshader').textContent, }); particles = new THREE.Points(particleGeometry, material); scene.add(particles); window.addEventListener('resize', onWindowResize); document.addEventListener('pointermove', onPointerMove); } function onPointerMove(event) { pointer.x = ((event.clientX - renderer.domElement.offsetLeft) / renderer.domElement.clientWidth) * 2 - 1; pointer.y = -((event.clientY - renderer.domElement.offsetTop) / renderer.domElement.clientHeight) * 2 + 1; } function onWindowResize() { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); } function animate() { requestAnimationFrame(animate); render(); } function render() { particles.rotation.x += 0.0005; particles.rotation.y += 0.001; raycaster.setFromCamera(pointer, camera); const intersects = raycaster.intersectObject(particles); const sizes = particles.geometry.attributes.size.array; for (let i = 0; i < intersects.length; i++) { const particleIndex = intersects[i].index; sizes[particleIndex] = PARTICLE_SIZE * .7; } if (intersects.length > 0) { particles.geometry.attributes.size.needsUpdate = true; } renderer.render(scene, camera); }
introduction

Searchable planet for a sustainable future

Othersphere indexes the globe to accelerate deployment of high performance, sustainable infrastructure

Supported BY
What we deliver

Build better projects, faster

Othersphere Explorer helps you develop infrastructure with confidence, providing rapid, data-driven insights to accelerate project timelines, reduce risks, and improve economic and environmental performance

Learn more ↗
DEMO

Try Othersphere Explorer

Request a demo
HOw it works

Wicked problems require a wicked solution

Our core technology — a global index of human, economic, and environmental systems — is purpose-built to help solve the complex challenges facing deployment of sustainable infrastructure

Learn more ↗
News & Press releases

Our news and insights

Read more ↗
CONTACT

Get in touch

Please reach out if you would like to learn more about Othersphere, our products, and opportunities to partner in accelerating global industrial decarbonization.

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.