Last active
March 19, 2024 05:17
-
-
Save ShaneBrumback/7b140eac3805096c08fee036f930a674 to your computer and use it in GitHub Desktop.
Threejs Examples Animating 3D Spheres & Fragment Shaders
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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