<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>WebGL Three.js构建3D霓虹幻梦空间</title>
<style>
body {
margin: 0;
}
</style>
</head>
<body>
<!-- Vertex Shader -->
<script id="vertexShader" type="x-shader/x-vertex">
attribute vec3 color;
uniform float time;
uniform float size;
varying vec4 vMvPosition;
varying vec3 vColor;
float map(float value, float beforeMin, float beforeMax, float afterMin, float afterMax) {
return afterMin + (afterMax - afterMin) * ((value - beforeMin) / (beforeMax - beforeMin));
}
void main() {
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
vMvPosition = mvPosition;
vColor = color;
gl_PointSize = (size + map(sin(time * 0.05), -1.0, 1.0, -100.0, 100.0)) * (100.0 / length(mvPosition.xyz));
gl_Position = projectionMatrix * mvPosition;
}
</script>
<!-- Fragment Shader -->
<script id="fragmentShader" type="x-shader/x-fragment">
uniform sampler2D texture;
uniform float time;
varying vec4 vMvPosition;
varying vec3 vColor;
void main() {
float opacity = 200.0 / length(vMvPosition.xyz);
vec2 uv = gl_PointCoord.xy * 2.0 - 1.0;
float orb = 0.1 / length(vec2(0.0) - uv) * step(0.5, 1.0 - length(uv));
orb = smoothstep(0.0, 1.0, orb);
vec3 color = vec3(orb) * vColor;
gl_FragColor = vec4(color, 1.0);
}
</script>
<script src="js/three.min.js"></script>
<script>
var vertexShader = document.getElementById('vertexShader').textContent;
var fragmentShader = document.getElementById('fragmentShader').textContent;
var clock = new THREE.Clock();
var scene = new THREE.Scene();
var colorsPerFace = [
"#3628EF", "#FF5DEF", "#8747FE", "#088FFE", "#03A6CE"
];
// from https://stackoverflow.com/a/5624139
function hexToRgb(hex) {
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return {
r: parseInt(result[1], 16) / 255,
g: parseInt(result[2], 16) / 255,
b: parseInt(result[3], 16) / 255
};
}
var vertices = [];
var colors = [];
var particleCount = 50000;
var geometry = new THREE.BufferGeometry();
for (var i = 0; i < particleCount; i++) {
var x = Math.floor(Math.random() * 1000 - 500);
var y = Math.floor(Math.random() * 1000 - 500);
var z = Math.floor(Math.random() * 1000 - 500);
vertices.push(x, y, z);
var rgbColor = hexToRgb(colorsPerFace[Math.floor(Math.random() * colorsPerFace.length)]);
colors.push(rgbColor.r, rgbColor.g, rgbColor.b);
}
var verticesArray = new Float32Array(vertices);
geometry.addAttribute('position', new THREE.BufferAttribute(verticesArray, 3));
var colorsArray = new Float32Array(colors);
geometry.addAttribute('color', new THREE.BufferAttribute(colorsArray, 3));
var uniforms = {
time: {
type: 'f',
value: 0.0
},
size: {
type: 'f',
value: 200.0
}
};
var material = new THREE.ShaderMaterial({
uniforms: uniforms,
vertexShader: vertexShader,
fragmentShader: fragmentShader,
transparent: true,
depthWrite: false,
blending: THREE.AdditiveBlending
});
var points = new THREE.Points(geometry, material);
scene.add(points);
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight);
var renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0x111111);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.shadowMap.enabled = true;
document.body.appendChild(renderer.domElement);
var render = function render() {
clock.getDelta();
var time = clock.elapsedTime * 0.2;
uniforms.time.value += 0.5;
var cameraDistance = 100;
camera.position.x = cameraDistance * Math.sin(time);
camera.position.z = cameraDistance * Math.cos(time);
camera.lookAt(new THREE.Vector3(0, 0, 0));
renderer.render(scene, camera);
requestAnimationFrame(render);
};
onResize();
render();
window.addEventListener("resize", onResize);
function onResize() {
var width = window.innerWidth;
var height = window.innerHeight;
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(width, height);
}
</script>
</body>
</html>