<div class="main">
<canvas id="bg"></canvas>
</div>
body {
margin: 0;
}
#bg {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: #000;
}
.main {
width: 100%;
}
window.addEventListener("load", init);
function random(num) {
return Math.random() * num * 2 - num;
}
let scene = new THREE.Scene(),
camera,
renderer;
// グラデーションのためのvertex shader
const vertexShader = `
uniform vec3 boundingBoxMin;
uniform vec3 boundingBoxMax;
varying vec2 vUv;
void main() {
vUv.y = (position.y - boundingBoxMin.y) / (boundingBoxMax.y - boundingBoxMin.y);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
}
`;
// グラデーションのためのfragment shader
const fragmentShader = `
uniform vec3 color1;
uniform vec3 color2;
varying vec2 vUv;
void main() {
gl_FragColor = vec4(mix(color1, color2, vUv.y), 1.0);
}
`;
function init() {
this.color1 = 0xffffff;
this.color2 = 0xff0000;
// GUI
var controls = new (function () {
this.color1 = 0xffffff;
this.color2 = 0xff0000;
this.redraw = function () {
if (scene.getObjectByName("circle")) {
scene.remove(scene.getObjectByName("circle"));
}
if (scene.getObjectByName("box")) {
scene.remove(scene.getObjectByName("box"));
}
if (scene.getObjectByName("quadrangle")) {
scene.remove(scene.getObjectByName("quadrangle"));
}
if (scene.getObjectByName("wireframe")) {
scene.remove(scene.getObjectByName("wireframe"));
}
createObjects(controls.color1, controls.color2);
};
})();
var gui = new dat.GUI();
gui.addColor(controls, "color1").onChange(controls.redraw);
gui.addColor(controls, "color2").onChange(controls.redraw);
const element = document.getElementById("bg");
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(
75,
element.width / element.height,
0.1,
1000
);
camera.position.set(20, 10, 30);
camera.rotation.set(0, 0, 0);
renderer = new THREE.WebGLRenderer({
canvas: element,
antialias: true,
alpha: true,
transparent: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
controls.redraw();
function createObjects(color1, color2) {
// 円
const radius = 5;
const segmentCount = 600;
const segmentPoints = [];
// 円周上に点を配置
const SEG_RADS = (2 * Math.PI) / segmentCount;
for (let c = 0; c < segmentCount; c++) {
const x = radius * Math.cos(c * SEG_RADS);
const y = radius * Math.sin(c * SEG_RADS);
segmentPoints.push(new THREE.Vector3(x, y, 0));
}
// 円のgeometry作成
const stemCurve = new THREE.CatmullRomCurve3(segmentPoints, true);
const splinePoints = stemCurve.getPoints(segmentCount);
const geometry = new THREE.BufferGeometry().setFromPoints(splinePoints);
geometry.computeBoundingBox();
// グラデーションがかかるように
const material = new THREE.ShaderMaterial({
uniforms: {
color1: {
value: new THREE.Color(color1)
},
color2: {
value: new THREE.Color(color2)
},
boundingBoxMin: {
value: geometry.boundingBox.min
},
boundingBoxMax: {
value: geometry.boundingBox.max
}
},
vertexShader,
fragmentShader,
opacity: 1
});
const circle = new THREE.Line(geometry, material);
circle.name = "circle";
circle.position.set(20, 20, 0);
scene.add(circle);
// box ---------------------
const boxGeometry = new THREE.BoxBufferGeometry(5, 5, 5);
boxGeometry.computeBoundingBox();
// グラデーションがかかるように
const boxMaterial = new THREE.ShaderMaterial({
uniforms: {
color1: {
value: new THREE.Color(color1)
},
color2: {
value: new THREE.Color(color2)
},
boundingBoxMin: {
value: boxGeometry.boundingBox.min
},
boundingBoxMax: {
value: boxGeometry.boundingBox.max
}
},
vertexShader,
fragmentShader,
opacity: 1
});
const box = new THREE.Mesh(boxGeometry, boxMaterial);
box.name = "box";
box.position.set(20, 0, 0);
box.rotation.set(0, 0, 0);
scene.add(box);
// 平面の四角形 -----------------
const quadrangleGeometry = new THREE.BoxBufferGeometry(4, 4, 0.1);
quadrangleGeometry.computeBoundingBox();
// グラデーションがかかるように
const quadrangleMaterial = new THREE.ShaderMaterial({
uniforms: {
color1: {
value: new THREE.Color(color1)
},
color2: {
value: new THREE.Color(color2)
},
boundingBoxMin: {
value: quadrangleGeometry.boundingBox.min
},
boundingBoxMax: {
value: quadrangleGeometry.boundingBox.max
}
},
vertexShader,
fragmentShader,
opacity: 1
});
const quadrangle = new THREE.Mesh(quadrangleGeometry, quadrangleMaterial);
quadrangle.name = "quadrangle";
quadrangle.position.set(20, 10, 0);
scene.add(quadrangle);
// wireframe -----------------
const wireframeGeometry = new THREE.CircleGeometry(4, 100);
wireframeGeometry.computeBoundingBox();
// グラデーションがかかるように
const wireframeMaterial = new THREE.ShaderMaterial({
uniforms: {
color1: {
value: new THREE.Color(color1)
},
color2: {
value: new THREE.Color(color2)
},
boundingBoxMin: {
value: wireframeGeometry.boundingBox.min
},
boundingBoxMax: {
value: wireframeGeometry.boundingBox.max
}
},
vertexShader,
fragmentShader,
opacity: 1,
wireframe: true
});
const wireframe = new THREE.Mesh(wireframeGeometry, wireframeMaterial);
wireframe.name = "wireframe";
wireframe.position.set(30, 20, 0);
scene.add(wireframe);
}
render();
}
function render() {
renderer.render(scene, camera);
window.requestAnimationFrame(render);
scene.children.forEach((child) => {
child.rotation.y += 0.01;
});
}
This Pen doesn't use any external CSS resources.