Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save ShaneBrumback/7b140eac3805096c08fee036f930a674 to your computer and use it in GitHub Desktop.
Save ShaneBrumback/7b140eac3805096c08fee036f930a674 to your computer and use it in GitHub Desktop.
Threejs Examples Animating 3D Spheres & Fragment Shaders
<html>
<head>
<title>Three.js Examples - Animating 3D Spheres and Fragment Shaders</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/three@latest/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@latest/examples/js/controls/OrbitControls.js"></script>
<script>
// Set up Three js scene
const scene = new THREE.Scene();
// Set up the camera
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 500);
camera.position.z = 5;
// Configure renderer settings
let renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.toneMapping = THREE.ReinhardToneMapping;
renderer.domElement.id = 'renderer';
renderer.setClearColor(0x000000, 1); // Set background color to black
renderer.domElement.style.position = 'fixed';
renderer.domElement.style.zIndex = '-1';
renderer.domElement.style.left = '0';
renderer.domElement.style.top = '0';
document.body.appendChild(renderer.domElement);
// // Create the gradient shader material
var shaderGradientAnimatedMaterial = new THREE.ShaderMaterial({
side: THREE.DoubleSide,
uniforms: {
time: { value: 0.0 }
},
vertexShader: `
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
`,
fragmentShader: `
uniform float time;
void main() {
gl_FragColor = vec4(
sin( time + gl_FragCoord.x * 0.01 ) * 0.5 + 0.5,
sin( time + gl_FragCoord.y * 0.01 ) * 0.5 + 0.5,
sin( time ) * 0.5 + 0.5,
1.0
);
}
`
});
// Set up the orbital controls
const controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.dampingFactor = 0.1; // Reduce camera damping for smoother movement
controls.autoRotate = true; // Make the camera rotate sinuously around the spheres
// Create and add the spheres to the scene
const sphereGeometry = new THREE.SphereGeometry(0.5, 32, 32);
for (let i = 0; i < 100; i++) {
const sphereMaterial = new THREE.MeshLambertMaterial({ color: Math.random() * 0xffffff });
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphere.position.x = Math.random() * 10 - 5;
sphere.position.y = Math.random() * 10 - 5;
sphere.position.z = Math.random() * 10 - 5;
sphere.velocity = new THREE.Vector3(Math.random() * 0.2 - 0.1, Math.random() * 0.2 - 0.1, Math.random() * 0.2 - 0.1);
scene.add(sphere);
}
// Create the spotlight with shadows
const spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(10, 20, 30);
spotLight.castShadow = true;
scene.add(spotLight);
// Add ambient light
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);
// Enable shadows on the spheres
scene.traverse(function (node) {
if (node instanceof THREE.Mesh) {
node.castShadow = true;
}
});
// Create the plane's geometry
const planeGeometry = new THREE.PlaneGeometry(100, 100);
// Create a material to apply to the plane
const planeMaterial = new THREE.MeshBasicMaterial({
color: 'blue',
side: THREE.DoubleSide,
depthWrite: false
});
// Create the plane
const plane = new THREE.Mesh(planeGeometry, shaderGradientAnimatedMaterial);
plane.rotation.x = Math.PI / 2
plane.rotation.z = Math.PI;
plane.position.y = -6;
plane.receiveShadow = true;
plane.castShadow = true
// Add the plane to the scene
scene.add(plane);
//Add a grid helper
var grid = new THREE.GridHelper(100, 30);
//grid.renderOrder = 0;
grid.position.y = -6;
scene.add(grid);
// Animate the spheres
function animate() {
requestAnimationFrame(animate);
controls.update();
// Move the spheres
scene.traverse(function (node) {
if (node instanceof THREE.Mesh) {
let objectName = node.geometry.type
if (objectName == 'SphereGeometry') {
node.position.add(node.velocity);
// Check boundaries and change direction if necessary
if (node.position.x < -5 || node.position.x > 5) {
node.velocity.x *= -1;
}
if (node.position.y < -5 || node.position.y > 5) {
node.velocity.y *= -1;
}
if (node.position.z < -5 || node.position.z > 5) {
node.velocity.z *= -1;
}
}
}
});
shaderGradientAnimatedMaterial.uniforms.time.value += 0.05;
renderer.render(scene, camera);
}
animate();
// Add event listener for window resize
window.addEventListener('resize', onWindowResize);
// Function to handle window resize
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment