Full index.js
code. Just in case:
import './style';
import * as THREE from 'three';
import GUI from 'lil-gui';
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
100
);
camera.position.z = 5;
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
window.addEventListener("resize", () => {
camera.aspect = innerWidth / innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(innerWidth, innerHeight);
});
// 🌟 Step 2: Heatmap Data (Color, Coordinates, Intensity)
const heatmapData = [
{
color: new THREE.Color(1, 0, 0),
coordinate: new THREE.Vector3(-2, 1, 0),
intensity: 2.3,
}, // Red (Hot)
{
color: new THREE.Color(0, 0, 1),
coordinate: new THREE.Vector3(2, -1, 0),
intensity: 1.3,
}, // Blue (Cold)
{
color: new THREE.Color(0, 1, 0),
coordinate: new THREE.Vector3(-1, -1, 0),
intensity: 1.8,
}, // Green
{
color: new THREE.Color(1, 1, 0),
coordinate: new THREE.Vector3(1, 1, 0),
intensity: 1.5,
}, // Yellow
];
// const MAX_POINTS = 100; // Define a reasonable max size
// const dataCount = heatmapData.length; // Actual count
// 🌟 Step 3: Plane Geometry & Shader Material
const geometry = new THREE.PlaneGeometry(15, 15);
const material = new THREE.ShaderMaterial({
uniforms: {
heatPoints: { value: heatmapData.map((d) => {return d.coordinate.clone()}) },
colors: { value: heatmapData.map((d) => {return d.color.clone()}) },
intensities: { value: heatmapData.map((d) => {return d.intensity}) },
},
vertexShader: `
varying vec3 vPos;
void main() {
vPos = position;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}`,
fragmentShader: `
uniform vec3 colors[${heatmapData.length}];
uniform vec3 heatPoints[${heatmapData.length}];
uniform float intensities[${heatmapData.length}];
varying vec3 vPos;
void main() {
vec3 heatColor = vec3(0.0);
for (int i = 0; i < ${heatmapData.length}; i++) { // Use actual count instead of a fixed size
float dist = distance(vPos, heatPoints[i]);
float heat = exp(-dist * intensities[i]); // Smooth blending
heatColor += colors[i] * heat;
}
gl_FragColor = vec4(heatColor, 1.0);
}`,
});
// 🌟 Step 4: Create Heatmap Mesh & Add to Scene
const heatMapMesh = new THREE.Mesh(geometry, material);
scene.add(heatMapMesh);
// 🌟 Step 5: GUI Controls (Adjust Colors & Intensities)
const gui = new GUI();
heatmapData.forEach((_, index) => {
gui.addColor(material.uniforms.colors.value, index).name(`Color ${index}`);
gui.add(material.uniforms.intensities.value, index, 0.5, 5.0).name(`Intensity ${index}`);
});
animate();
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
Result: