I made vertices using svg path. And I made a text mesh using these vertices.
But the text mesh is not centered. The starting position of a letter is always the same, regardless of the length of the letter.
I always want to see the middle of the text.
If the length of the text is long, the entire text should be displayed on the screen.
How can I solve this problem? Please help me T.T...
The following are gif files that show the current situation.
When I write "hello"
When I write "hello world"
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { FontLoader } from "three/examples/jsm/loaders/FontLoader";
import { TextGeometry } from "three/examples/jsm/geometries/TextGeometry";
import { ALPHAMAP } from "../constants/url";
import { load } from "opentype.js";
import UnDotumBold from "../../assets/UnDotumBold.ttf";
class WebGLCanvas {
constructor(canvas) {
this._canvas = canvas;
this._clock = new THREE.Clock();
this._count = 4000;
this._distance = 2;
this._mouseX = 0;
this._mouseY = 0;
this._vertexShader = document.querySelector("#vertex-shader").textContent;
this._fragmentShader =
document.querySelector("#fragment-shader").textContent;
}
async _setupTextModel() {
const font = await load(UnDotumBold);
// 💡 I created a svg and got the svg paths to create vertices.
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
const g = document.createElementNS("http://www.w3.org/2000/svg", "g");
svg.setAttribute("viewBox", [0, 0, 1920, 1920].join(" "));
g.setAttribute("fill", "black");
let pathMarkup = "";
const fontPaths = font.getPaths(text, 0, 1000, 1000);
fontPaths.forEach((fontPath) => {
const path = fontPath.toSVG();
pathMarkup += path;
});
g.insertAdjacentHTML("beforeend", pathMarkup);
document.body.appendChild(svg);
svg.appendChild(g);
const paths = svg.querySelectorAll("path");
const svgViewBoxWidth = svg.viewBox.baseVal.width;
const svgViewBoxHeight = svg.viewBox.baseVal.height;
svg.remove();
// 💡 vertices
this._textVertices = [];
const colors = [];
const sizes = [];
const delay = 1;
const gradient = chroma.scale([
"ef476f",
"ffd166",
"06d6a0",
"118ab2",
"073b4c",
]);
const colorRGB = {
r: Math.random() * 100,
g: Math.random() * 100,
b: Math.random() * 100,
};
const positionXYZ = {
x: Math.random() * 3000,
y: Math.random() * 3000,
z: Math.random() * 3000,
};
const timeline = gsap.timeline({
onReverseComplete: () => {
timeline.timeScale(1);
timeline.play(0);
},
});
paths.forEach((path) => {
const length = path.getTotalLength();
for (let i = 0; i < length; i += 30) {
const pointLength = i;
const point = path.getPointAtLength(pointLength);
// 💡 end point ❗❗ => I think this part is the problem..
const vector = new THREE.Vector3(
point.x - svgViewBoxWidth / 2,
-point.y + svgViewBoxHeight / 2,
(Math.random() - 0.5) * 15,
);
// 💡 start point
const start = new THREE.Vector3(
vector.x + (Math.random() - 0.5) * positionXYZ.x,
vector.y + (Math.random() - 0.5) * positionXYZ.y,
vector.z + (Math.random() - 0.5) * positionXYZ.z,
);
const coloursX =
point.x / svgViewBoxWidth + (Math.random() - 0.5) * 0.2;
const color = gradient(coloursX).rgb();
this._textVertices.push(vector);
vector.r = 1 - (vector.z + 7.5) / colorRGB.r;
vector.g = 1 - (vector.z + 7.5) / colorRGB.g;
vector.b = 1 - (vector.z + 7.5) / colorRGB.b;
timeline.from(
vector,
{
x: start.x,
y: start.y,
z: start.z,
r: color[0] / 255,
g: color[1] / 255,
b: color[2] / 255,
duration: "random(0.5, 1.5)",
ease: "power2.out",
},
delay * 0.0012,
);
sizes.push(25 * this.renderer.getPixelRatio());
}
});
// 💡 text mesh
this._textGeometry = new THREE.BufferGeometry().setFromPoints(
this._textVertices,
);
this._textGeometry.setAttribute(
"color",
new THREE.Float32BufferAttribute(colors, 3),
);
this._textGeometry.setAttribute(
"size",
new THREE.Float32BufferAttribute(sizes, 1),
);
const textMaterial = new THREE.ShaderMaterial({
uniforms: {
pointTexture: {
value: new THREE.TextureLoader().load(ALPHAMAP.CIRCLE),
},
},
vertexShader: this._vertexShader,
fragmentShader: this._fragmentShader,
transparent: true,
depthTest: false,
});
this._textMesh = new THREE.Points(this._textGeometry, textMaterial);
this._textMesh.scale.set(0.1, 0.1, 0.1);
// this._textMesh.geometry.center(); => ❌ It dosen't work..
// this._getCenterPoint(this._textMesh); => ❌ It dosen't work..
this._textGroup = new THREE.Group();
this._textGroup.add(this._textMesh);
this._textGroup.position.set(0, 0, -240);
this._init();
}
/*
_getCenterPoint(mesh) {
const { geometry } = mesh;
const center = new THREE.Vector3();
geometry.computeBoundingBox();
geometry.boundingBox.getCenter(center);
mesh.localToWorld(center);
return center;
}
*/
_init() {
this.scene = new THREE.Scene();
this._sizes = {
width: window.innerWidth,
height: window.innerHeight,
};
this._setupCamera(this._sizes);
this._setupControls(this.camera, this._canvas);
this._render(this._canvas, this._sizes);
this._tick(this._sizes);
window.addEventListener("resize", this._resize);
window.addEventListener("mousemove", this._mousemove.bind(this));
}
_setupCamera(sizes) {
const camera = new THREE.PerspectiveCamera(
25,
sizes.width / sizes.height,
0.01,
5000,
);
this.scene.add(camera);
this.camera = camera;
}
_setupControls(camera, canvas) {
const control = new OrbitControls(camera, canvas);
control.enableDamping = true;
this.control = control;
}
_render(canvas, sizes) {
const renderer = new THREE.WebGL1Renderer({
canvas,
antialias: true,
alpha: true,
});
renderer.setClearColor(0x000000, 0);
renderer.setSize(sizes.width, sizes.height);
renderer.setPixelRatio(window.devicePixelRatio);
this.renderer = renderer;
}
_tick(sizes) {
this.camera.position.z = 400;
this.scene.add(this._textGroup);
this._textGeometry.setFromPoints(this._textVertices);
const colours = [];
this._textVertices.forEach((vector) => {
colours.push(vector.r, vector.g, vector.b);
});
this._textGeometry.setAttribute(
"customColor",
new THREE.Float32BufferAttribute(colours, 3),
);
this.renderer.render(this.scene, this.camera);
this.control.update();
window.requestAnimationFrame(this._tick.bind(this, sizes));
}
_resize() {
const width = window.innerWidth;
const height = window.innerHeight;
this.camera.aspect = width / height;
this.camera.updateProjectionMatrix();
this.renderer.setSize(width, height);
this.renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
}
_mousemove(event) {
// ...
}
}
export default WebGLCanvas;
Related
I want to join 2 Box Geometries to each other (image below) which are than drag rotatable as one object.
Below is the code for one drag-rotatable boxgeometry ( var geometry1 ), what do I need to add to the code, so that the second box geometry ( var geometry2 ) is joined to the first?
var three = THREE;
var space = new three.Scene();
var cam = new three.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
var rend = new three.WebGLRenderer();
rend.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(rend.domElement);
var geometry1 = new three.BoxGeometry(1, 2, 1);
var geometry2 = new three.BoxGeometry(1, 1, 1);
var material = new three.MeshFaceMaterial([
new three.MeshBasicMaterial({
color: "red"
}),
new three.MeshBasicMaterial({
color: "orange"
}),
new three.MeshBasicMaterial({
color: "yellow"
}),
new three.MeshBasicMaterial({
color: "green"
}),
new three.MeshBasicMaterial({
color: "blue"
}),
new three.MeshBasicMaterial({
color: "cyan"
})
]);
var cube = new three.Mesh(geometry1, material);
cube.rotation.x = Math.PI / 4;
cube.rotation.y = Math.PI / 4;
space.add(cube);
cam.position.z = 5;
var Dragging = false;
var previousMousePosition = {
x: 0,
y: 0
};
$(rend.domElement).on('mousedown', function(e) {
Dragging = true;
})
.on('mousemove', function(e) {
//console.log(e);
var deltaMove = {
x: e.offsetX - previousMousePosition.x,
y: e.offsetY - previousMousePosition.y
};
if (Dragging) {
var deltaRotationQuaternion = new three.Quaternion()
.setFromEuler(new three.Euler(
toRadians(deltaMove.y * 1),
toRadians(deltaMove.x * 1),
0,
'XYZ'
));
cube.quaternion.multiplyQuaternions(deltaRotationQuaternion, cube.quaternion);
}
previousMousePosition = {
x: e.offsetX,
y: e.offsetY
};
});
$(document).on('mouseup', function(e) {
Dragging = false;
});
window.requestAnimFrame = (function() {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
var lastFrameTime = new Date().getTime() / 1000;
var totalGameTime = 0;
function update(dt, t) {
setTimeout(function() {
var TimeNow = new Date().getTime() / 1000;
var dt = TimeNow - (lastFrameTime || TimeNow);
totalGameTime += dt;
update(dt, totalGameTime);
lastFrameTime = TimeNow;
}, 0);
}
function render() {
rend.render(space, cam);
requestAnimFrame(render);
}
render();
update(0, totalGameTime);
function toRadians(angle) {
return angle * (Math.PI / 180);
}
function toDegrees(angle) {
return angle * (180 / Math.PI);
}
You can create a group:
var group = new THREE.Group();
group.add(geometry1);
group.add(geometry2);
scene.add(group);
Now you can change it's position, rotation, quaternion, normally, just by using the group variable.
I'd like to know if there is some property to make objects behind a fog of multiple Points clickable, that means, when the fog appears I could click the objects that are in (or behind) the fog.
I have the following code to create the fog and animate it:
const loadFogEffect = () => {
const geometry = new THREE.Geometry();
const particleCount = 50;
const texture = new THREE.TextureLoader().load('fog.png');
let material = new THREE.PointsMaterial({
size: 5,
map: texture,
// blending: THREE.AdditiveBlending,
depthWrite: false,
transparent: true,
sizeAttenuation: true,
color: 'rgb(30,30,30)',
});
const range = 1;
for (let i = 0; i < particleCount; i++) {
const x = THREE.Math.randInt(-range, range);
const y = THREE.Math.randInt(-range, range);
const z = THREE.Math.randInt(-range, range);
const point = new THREE.Vector3(x, y, z);
point.velocityX = THREE.Math.randFloat(0.008, -0.035);
point.velocityY = THREE.Math.randFloat(0.008, -0.035);
point.velocityZ = THREE.Math.randFloat(0.008, -0.035);
geometry.vertices.push(point);
}
points = new THREE.Points(geometry, material);
points.layers.set(noReflectionLayer);
scene.add(points);
};
const animateFog = () => {
points.geometry.vertices.forEach((v) => {
v.y = v.y + v.velocityY;
v.z = v.z + v.velocityZ;
// v.x = v.x - v.velocityX;
if (v.z >= 2 && v.y === 0) {
v.x = THREE.Math.randInt(0.001, -0.001);
v.y = THREE.Math.randInt(0.001, -0.001);
v.z = 2;
}
});
points.geometry.verticesNeedUpdate = true;
};
Thanks for your help!
I got this with this for anyones interest:
const fogLayer = 2;
...
camera.layers.enable(fogLayer);
and then setting the points in the new layer before adding them to the scene:
points.layers.set(fogLayer);
So that the points are invisible for the raycaster.
I am using Three js to generate point cloud from depth image, but I'm not able to export this point cloud in ply format. Can someone help me, this is the code.
I tried to add it with the html of this from the library of three js to export in ply but I didn't have a good result.
Please Someone can help me.
<canvas></canvas>
<style>
body {
margin: 0;
}
canvas {
width: 100vw;
height: 100vh;
display: block;
}
</style>
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r94/three.min.js"></script>
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r94/js/controls/OrbitControls.js"></script>
<script>
'use strict';
/* global THREE */
function loadImage(url) {
return new Promise((resolve, reject) => {
const img = new Image();
img.crossOrigin = "anonymous";
img.onload = (e) => { resolve(img); };
img.onerror = reject;
img.src = url;
});
}
function getImageData(img) {
const ctx = document.createElement("canvas").getContext("2d");
ctx.canvas.width = img.width;
ctx.canvas.height = img.height;
ctx.drawImage(img, 0, 0);
return ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height);
}
// return the pixel at UV coordinates (0 to 1) in 0 to 1 values
function getPixel(imageData, u, v) {
const x = u * (imageData.width - 1) | 0;
const y = v * (imageData.height - 1) | 0;
if (x < 0 || x >= imageData.width || y < 0 || y >= imageData.height) {
return [0, 0, 0, 0];
} else {
const offset = (y * imageData.width + x) * 4;
return Array.from(imageData.data.slice(offset, offset + 4)).map(v => v / 255);
}
}
async function main() {
const images = await Promise.all([
loadImage("https://i.imgur.com/UKBsvV0.jpg"), // RGB
loadImage("https://i.imgur.com/arPMCZl.jpg"), // Depth
]);
const data = images.map(getImageData);
const canvas = document.querySelector('canvas');
const renderer = new THREE.WebGLRenderer({ canvas: canvas });
const fov = 75;
const aspect = 2; // the canvas default
const near = 1;
const far = 4000;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.z = 2000;
const controls = new THREE.OrbitControls(camera, canvas);
controls.target.set(0, 0, 0);
controls.update();
const scene = new THREE.Scene();
const rgbData = data[0];
const depthData = data[1];
const skip = 20;
const across = Math.ceil(rgbData.width / skip);
const down = Math.ceil(rgbData.height / skip);
const positions = [];
const colors = [];
const color = new THREE.Color();
const spread = 1000;
const depthSpread = 1000;
const imageAspect = rgbData.width / rgbData.height;
for (let y = 0; y < down; ++y) {
const v = y / (down - 1); for (let x = 0; x < across; ++x) {
const u = x /
(across - 1); const rgb = getPixel(rgbData, u, v); const depth = 1 - getPixel(depthData, u, v)[0];
positions.push((u * 2 - 1) * spread * imageAspect, (v * -2 + 1) * spread, depth * depthSpread,);
colors.push(...rgb.slice(0, 3));
}
} const geometry = new THREE.BufferGeometry();
geometry.addAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.addAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
geometry.computeBoundingSphere(); const material = new THREE.PointsMaterial({
size: 15, vertexColors:
THREE.VertexColors
}); const points = new THREE.Points(geometry, material); scene.add(points); function
resizeRendererToDisplaySize(renderer) {
const canvas = renderer.domElement; const
width = canvas.clientWidth; const height = canvas.clientHeight; const needResize = canvas.width !== width ||
canvas.height !== height; if (needResize) { renderer.setSize(width, height, false); } return needResize;
} function render(time) {
time *= 0.001; if (resizeRendererToDisplaySize(renderer)) {
const
canvas = renderer.domElement; camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.updateProjectionMatrix();
} renderer.render(scene, camera); requestAnimationFrame(render);
}
requestAnimationFrame(render);
} main(); </script>
I'm trying to make a database of words where the most important words are closer to the top of the sphere and the less important are further away. So I created a sphere with enough vertices for each word, created a list of those vertices in order of distance from the top of the sphere, and placed the text sprites at the positions of the vertices in order of that sorted list.
Video version: https://i.gyazo.com/aabaf0b4a26f4413dc6a0ebafab2b4bd.mp4
Sounded like a good plan in my head, but clearly the geometry of a sphere causes the words to be further spread out the further away from the top they are. I need a result that looks like a somewhat even distribution across the surface. It doesn't have to be perfect, just visually closer than this.
How can I achieve the desired effect?
Here are the relevant methods:
positionDb(db) {
console.log("mostRelated", db.mostRelated);
console.log("depthList", this.depthList);
let mostRelated = db.mostRelated;
let depthList = this.depthList;
for (let i = 0; i < mostRelated.length; i++) {
this.addTextNode(mostRelated[i].data, this.depthList[i].vertice, this.depthList[i].depth);
}
}
addTextNode(text, vert, distance) {
let fontSize = 0.5 * (600 / distance);
let sprite = new THREE.TextSprite({
fillStyle: '#000000',
fontFamily: '"Arial", san-serif',
fontSize: fontSize,
fontWeight: 'bold',
text: text
});
this.scene.add(sprite);
sprite.position.set(vert.x, vert.y, vert.z);
setTimeout(() => {
sprite.fontFamily = '"Roboto", san-serif';
}, 1000)
}
this.scene = scene;
this.geometry = new THREE.SphereGeometry(420, 50, 550);
var material = new THREE.MeshBasicMaterial({
color: 0x0011ff
});
var sphere = new THREE.Mesh(this.geometry, wireframe);
var wireframe = new THREE.WireframeGeometry(this.geometry);
let frontVert = {
x: 0,
y: 100,
z: 0
}
let depthList = [];
this.geometry.vertices.forEach(vertice => {
let depth = getDistance(frontVert, vertice);
if (depthList.length === 0) {
depthList.push({
depth,
vertice
});
} else {
let flag = false;
for (let i = 0; i < depthList.length; i++) {
let item = depthList[i];
if (depth < item.depth) {
flag = true;
depthList.splice(i, 0, {
depth,
vertice
});
break;
}
}
if (!flag) depthList.push({
depth,
vertice
});
}
});
Maybe a fibonacci sphere
function fibonacciSphere(numPoints, point) {
const rnd = 1;
const offset = 2 / numPoints;
const increment = Math.PI * (3 - Math.sqrt(5));
const y = ((point * offset) - 1) + (offset / 2);
const r = Math.sqrt(1 - Math.pow(y, 2));
const phi = (point + rnd) % numPoints * increment;
const x = Math.cos(phi) * r;
const z = Math.sin(phi) * r;
return new THREE.Vector3(x, y, z);
}
Example:
function fibonacciSphere(numPoints, point) {
const rnd = 1;
const offset = 2 / numPoints;
const increment = Math.PI * (3 - Math.sqrt(5));
const y = ((point * offset) - 1) + (offset / 2);
const r = Math.sqrt(1 - Math.pow(y, 2));
const phi = (point + rnd) % numPoints * increment;
const x = Math.cos(phi) * r;
const z = Math.sin(phi) * r;
return new THREE.Vector3(x, y, z);
}
function main() {
const fov = 75;
const aspect = 2; // the canvas default
const near = 0.1;
const far = 5;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.z = 2;
const scene = new THREE.Scene();
function addTextNode(text, vert) {
const div = document.createElement('div');
div.className = 'label';
div.textContent = text;
div.style.marginTop = '-1em';
const label = new THREE.CSS2DObject(div);
label.position.copy(vert);
scene.add(label);
}
const renderer = new THREE.CSS2DRenderer();
const container = document.querySelector('#c');
container.appendChild(renderer.domElement);
const controls = new THREE.OrbitControls(camera, renderer.domElement);
const numPoints = 50;
for (let i = 0; i < numPoints; ++i) {
addTextNode(`p${i}`, fibonacciSphere(numPoints, i));
}
function render(time) {
time *= 0.001;
// three's poor choice of how to hanlde size strikes again :(
renderer.setSize(container.clientWidth, container.clientHeight);
const canvas = renderer.domElement;
camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.updateProjectionMatrix();
renderer.render(scene, camera);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
}
main();
body {
margin: 0;
overflow: hidden;
}
#c {
width: 100vw;
height: 100vh;
display: block;
}
.label {
color: red;
}
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r113/build/three.min.js"></script>
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r113/examples/js/controls/OrbitControls.js"></script>
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r113/examples/js/renderers/CSS2DRenderer.js"></script>
<div id="c"></div>
I am creating a THREEjs animation which I eventually want to sync with audio. (Can't accomplish this currently) I would like to add and remove shaders at specific points. How can I accomplish this most efficiently?
The way I have it set up now, is that I have a mirror shader inside of a function called turnOnMirror and in my render function, I have a conditional statement,
if (audioSrc.context.currentTime > 32.0) { turnOnMirror(); }
The shader looks like this:
var mirror = mirrorPass = new THREE.ShaderPass( THREE.MirrorShader );
mirror.renderToScreen = true;
composer.addPass(mirror);
(I am doing this for 2 reasons!
A: The renderer is the only place I can grab the actual time to make this call. And B: because for whatever reason, my frequencyData array comes back as 0s.
However, when the scene reaches this point, everything slows down extremely. How can I keep the same frame rate and accomplish what I am attempting to at the same time?
A piece of information for you is that the scene works fine at the same constant speed if I just apply the shader without making the call in the render function.
You can view the site here!
And the source code for the main.js is below!
/* ==================== [ Global Variables ] ==================== */
var scene, camera, renderer, aspectRatio;
var stats;
var composer, effect, clock;
var backMesh;
/* ==================== [ Audio Context ] ==================== */
var ctx = new AudioContext();
var audio = document.getElementById('player');
audio.play();
audio.volume = 1;
// audio.crossOrigin = "anonymous";
var audioSrc = ctx.createMediaElementSource(audio);
var analyser = ctx.createAnalyser();
audioSrc.connect(analyser);
audioSrc.connect(ctx.destination);
// frequencyBinCount tells you how many values you'll receive from the analyser
var frequencyData = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(frequencyData);
console.log(audioSrc);
console.log(audioSrc.context.currentTime);
console.log(frequencyData);
console.log(analyser.fftSize); // 2048 by default
console.log(analyser.frequencyBinCount); // will give us 1024 data points
analyser.fftSize = 64;
console.log(analyser.frequencyBinCount); // fftSize/2 = 32 data points
/* ==================== [ Set Scene & Camera ] ==================== */
scene = new THREE.Scene();
// scene.fog = new THREE.Fog(0x000000, 0, 1200);
aspectRatio = window.innerWidth / window.innerHeight;
camera = new THREE.PerspectiveCamera(75, aspectRatio, 0.1, 100);
// camera.target = new THREE.Vector3( 10, 10, 10 );
// Set the DOM
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor("#000000");
document.body.appendChild(renderer.domElement);
/* ==================== [ Camera Position ] ==================== */
camera.position.z = 15;
camera.position.y = 0;
/* ==================== [ Point Lights ] ==================== */
var pointLightBlue = new THREE.PointLight("#00ccff", 5, 100, 2);
pointLightBlue.position.set(-10, -40, -10);
scene.add(pointLightBlue);
// var pointLightWhite = new THREE.PointLight( "#ffffff", 1, 0, 1 );
// // pointLightWhite.position.set( -10, 160, -10 );
// pointLightWhite.position.set( 0, 0, 1 );
// scene.add(pointLightWhite);
// camera.add(pointLightWhite);
// var pointLightPink = new THREE.PointLight( "#EE567C", 5, 100, 10 );
// pointLightPink.position.set( 1, 0, -5 );
// scene.add(pointLightPink);
var pointLight = new THREE.PointLight("#A805FA", 2, 100, 40);
pointLight.position.set(40, 0, 40);
scene.add(pointLight);
var light2 = new THREE.PointLight( 0xFFFFFF, 1, 100 );
scene.add( light2 );
light2.position.z = 1000;
var pointLight2 = new THREE.PointLight("#07FAA0", 2, 100, 30);
pointLight2.position.set(-40, 0, -40);
scene.add(pointLight2);
/* ==================== [ Particles ] ==================== */
var getCamera = function() {
return camera;
}
// var texture = new Image();
// texture.src = 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/82015/snowflake.png';
// texture.src = './images/particle.png';
//var material = new THREE.ParticleBasicMaterial( { map: new THREE.Texture(texture) } );
var particleCount = 0, particleSystem, particles;
THREE.ImageUtils.crossOrigin = '';
var texture = THREE.ImageUtils.loadTexture('./images/particle.png');
//console.log(texture);
particleCount = 20000,
particles = new THREE.Geometry();
var pMaterial = new THREE.PointCloudMaterial({
color: 0xFFFFFF,
map: texture,
blending: THREE.AdditiveBlending,
depthTest: false,
depthWrite: false,
transparent: true,
opacity: 0.3,
side: THREE.DoubleSide,
size: 1.2
});
for (var i = 0; i < particleCount; i++) {
var pX = Math.random() * 500 - 250,
pY = Math.random() * 500 - 250,
pZ = Math.random() * 500 - 250,
particle = new THREE.Vector3(pX, pY, pZ);
particles.vertices.push(particle);
}
particleSystem = new THREE.ParticleSystem(particles, pMaterial);
particleSystem.sortParticles = false;
particleSystem.frustumCulled = false;
scene.add(particleSystem);
/* ==================== [ Light Beams ] ==================== */
var BEAM_ROT_SPEED = 0.003;
var BEAM_COUNT = 360;
var beamGeometry = new THREE.PlaneBufferGeometry(1, 500, 10, 1);
beamGroup = new THREE.Object3D();
beamMaterial = new THREE.MeshBasicMaterial({
opacity: 0.02,
transparent: true,
});
for (var i = 0; i <= BEAM_COUNT; ++i) {
var beam = new THREE.Mesh(beamGeometry, beamMaterial);
beam.doubleSided = true;
beam.rotation.x = Math.random() * Math.PI;
beam.rotation.y = Math.random() * Math.PI;
beam.rotation.z = Math.random() * Math.PI;
beamGroup.add(beam);
}
scene.add(beamGroup);
beamGroup.translateZ( -5 );
/* ==================== [ Cubes ] ==================== */
var doStrobe = false;
var doShake = false;
var strobeOn = false;
var beatTime = 30;
THREE.ImageUtils.crossOrigin = '';
var imgTextureStripes2 = THREE.ImageUtils.loadTexture( "./images/stripes2.jpg" );
imgTextureStripes2.wrapS = imgTextureStripes2.wrapT = THREE.RepeatWrapping;
imgTextureStripes2.repeat.set( 100, 100 );
backMaterial2 = new THREE.MeshBasicMaterial( {
map:imgTextureStripes2
} );
backMesh2 = new THREE.Mesh( new THREE.SphereGeometry( 1900, 30, 20 ), backMaterial2 );
backMesh2.scale.x = -1;
scene.add( backMesh2 );
backMesh2.visible = false;
function Box() {
this.posn = new THREE.Vector3();
this.rotation = new THREE.Vector3();
this.speed = getRand(3, 20);
this.init();
}
Box.ORIGIN = new THREE.Vector3();
Box.MAX_DISTANCE = 1000;
Box.INIT_POSN_RANGE = 500;
Box.FRONT_PLANE_Z = 1000;
Box.BACK_PLANE_Z = -1000;
Box.prototype.init = function() {
this.posn.copy(Box.ORIGIN);
this.posn.x = getRand(-Box.INIT_POSN_RANGE,Box.INIT_POSN_RANGE);
this.posn.y = getRand(-Box.INIT_POSN_RANGE,Box.INIT_POSN_RANGE);
this.posn.z = Box.BACK_PLANE_Z;
this.rotation.x = (Math.random() * 360 ) * Math.PI / 180;
this.rotation.y = (Math.random() * 360 ) * Math.PI / 180;
this.rotation.z = (Math.random() * 360 ) * Math.PI / 180;
};
Box.prototype.update = function() {
this.posn.z += this.speed * sketchParams.cubeSpeed ;
this.rotation.x += 0.03;
this.rotation.y += 0.01;
if(this.posn.z > Box.FRONT_PLANE_Z) {
this.init();
}
};
// returns random number within a range
function getRand(minVal, maxVal) {
return minVal + (Math.random() * (maxVal - minVal));
}
var cubesize = 100;
var BOX_COUNT;
var geometry = new THREE.CubeGeometry(cubesize, cubesize, cubesize);
cubeHolder = new THREE.Object3D();
THREE.ImageUtils.crossOrigin = '';
imgTextureStripes = THREE.ImageUtils.loadTexture( "./images/stripes2.jpg" );
cubeMaterial = new THREE.MeshPhongMaterial( {
ambient: 0x111111,
color: 0x666666,
specular: 0x999999,
shininess: 30,
shading: THREE.FlatShading,
map:imgTextureStripes
});
for(i = 0; i < BOX_COUNT; i++) {
var box = new Box();
console.log(box);
boxes.push(box);
var cube = new THREE.Mesh(geometry,cubeMaterial );
cube.position = box.posn;
cube.rotation = box.rotation;
cube.ox = cube.scale.x = Math.random() * 1 + 1;
cube.oy = cube.scale.y = Math.random() * 1 + 1;
cube.oz = cube.scale.z = Math.random() * 1 + 1;
cubeHolder.add(cube);
}
scene.add(cubeHolder);
/* ==================== [ Mini Geometries ] ==================== */
/* ==================== [ Post Processing ] ==================== */
composer = new THREE.EffectComposer(renderer);
composer.addPass(new THREE.RenderPass(scene, camera));
effect = new THREE.ShaderPass(THREE.FilmShader);
effect.uniforms['time'].value = 2.0;
effect.uniforms['nIntensity'].value = 0.4;
effect.uniforms['sIntensity'].value = 0.9;
effect.uniforms['sCount'].value = 1800;
effect.uniforms['grayscale'].value = 0.8;
composer.addPass(effect);
// var dot = new THREE.ShaderPass( THREE.DotScreenShader );
// dot.uniforms[ 'scale' ].value = 400;
// dot.uniforms[ 'tDiffuse' ].value = 40;
// dot.uniforms[ 'tSize' ].value = new THREE.Vector2( 256, 256 );
// composer.addPass(dot);
// var kaleidoPass = new THREE.ShaderPass(THREE.KaleidoShader);
// kaleidoPass.uniforms['sides'].value = 3;
// kaleidoPass.uniforms['angle'].value = 45 * Math.PI / 180;
// composer.addPass(kaleidoPass);
// var mirror = mirrorPass = new THREE.ShaderPass( THREE.MirrorShader );
// // mirror.uniforms[ "tDiffuse" ].value = 1.0;
// // mirror.uniforms[ "side" ].value = 3;
// composer.addPass(mirror);
var glitch = new THREE.GlitchPass(64);
glitch.uniforms[ "tDiffuse" ].value = 1.0;
glitch.uniforms[ 'seed' ].value = Math.random() * 5;
glitch.uniforms[ 'byp' ].value = 0;
// glitch.goWild = true;
composer.addPass(glitch);
var superPass = new THREE.ShaderPass(THREE.SuperShader);
superPass.uniforms.vigDarkness.value = 1;
superPass.uniforms.vigOffset.value = 1.3;
superPass.uniforms.glowSize.value = 2;
superPass.uniforms.glowAmount.value = 1;
composer.addPass( superPass );
var tv = new THREE.ShaderPass( THREE.BadTVShader );
tv.uniforms[ "distortion" ].value = 1;
tv.uniforms[ "distortion2" ].value = .01;
// tv.uniforms[ "time" ].value = 1.5;
tv.uniforms[ "speed" ].value = 8.8;
tv.uniforms[ "rollSpeed" ].value = 0.8;
composer.addPass(tv);
var staticPass = new THREE.ShaderPass( THREE.StaticShader );
staticPass.uniforms[ "amount" ].value = 0.15;
staticPass.uniforms[ "size" ].value = 1.0;
staticPass.uniforms[ "time" ].value = 4.5;
composer.addPass(staticPass);
var effect1 = new THREE.ShaderPass(THREE.RGBShiftShader);
effect1.uniforms['amount'].value = 0.003;
effect1.renderToScreen = true;
composer.addPass(effect1);
function turnOnMirror() {
var mirror = mirrorPass = new THREE.ShaderPass( THREE.MirrorShader );
mirror.renderToScreen = true;
composer.addPass(mirror);
}
function turnOffMirror() {
var mirror = mirrorPass = new THREE.ShaderPass( THREE.MirrorShader );
mirror.renderToScreen = false;
composer.addPass(mirror);
}
// add a timer
clock = new THREE.Clock;
/* ==================== [ Stats ] ==================== */
// stats = new Stats();
// stats.domElement.style.position = 'absolute';
// stats.domElement.style.left = '0px';
// stats.domElement.style.top = '0px';
// document.body.appendChild(stats.domElement);
// document.body.appendChild( renderer.domElement );
/* ==================== [ Shapes ] ==================== */
var quantity = 40;
var shapes = [];
for (var i = 0; i < quantity; i++) {
if (Math.random() < 0.5) {
var geometry = new THREE.RingGeometry(4, 40, 3);
// geometry.position = 0;
// var geometry = new THREE.RingGeometry( 30, 30, 18);
// camera.position.z = 60;
// var geometry = new THREE.RingGeometry( 20, 150, 18);
// var geometry = new THREE.RingGeometry( 20, 150, 18);
// var geometry = new THREE.TorusKnotGeometry( 10, 3, 100, 16 );
}
else {
//var geometry = new THREE.RingGeometry( 4, 40, 3);
// var geometry = new THREE.RingGeometry( 30, 30, 18);
// var geometry = new THREE.RingGeometry( 1, 5, 6 );
// var material = new THREE.MeshBasicMaterial( { color: 0xffff00,
// side: THREE.DoubleSide } );
// var mesh = new THREE.Mesh( geometry, material );
// scene.add( mesh );
}
if (i % 7 === 0) {
var material = new THREE.MeshPhongMaterial({
color: "#ffffff"
});
} else if (i % 2 === 0) {
var material = new THREE.MeshPhongMaterial({
color: "#666666"
});
} else {
var material = new THREE.MeshPhongMaterial({
color: "#333333"
});
}
var mesh = new THREE.Mesh(geometry, material);
mesh.position.z = -i * 3;
// mesh.rotation.z = i;
shapes.push(mesh);
scene.add(mesh);
}
// function refRate() {
// curTime = Date.now();
// delta = curTime - oldTime;
//
// if (delta > interval) {
// oldTime = curTime - (delta % interval);
// updateSize();
// }
//
// }
// Variables
var u_time = 0;
/* ==================== [ Render Function ] ==================== */
var render = function () {
requestAnimationFrame(render);
// var timer = Date.now() * 0.0010;
// camera.lookAt(scene.position);
u_time++;
for (var i = 0; i < quantity; i++) {
// Set rotation change of shapes
shapes[i].position.z += 0.2;
shapes[i].rotation.z += 0;
shapes[i].scale.x = 1 + Math.sin(i + u_time * 0.1) * 0.05;
shapes[i].scale.y = 1 + Math.sin(i + u_time * 0.1) * 0.05;
// shapes[i].scale.y = 120 + Math.tan(i + u_time * 5.0) * 0.5;
// shapes[i].scale.x = 120 + Math.tan(i + u_time * 5.0) * 0.5;
var change = 1.5 + Math.sin(u_time * 0.5) * 0.5;
// Set wireframe & width
if (Math.random() < change) {
shapes[i].material.wireframe = false;
shapes[i].material.wireframeLinewidth = Math.random() * 2;
// if (shapes[i] / 2 === 0) {
// turnOnMirror();
// }
}
else {
shapes[i].material.wireframe = false;
}
if (shapes[i].position.z > 10) {
shapes[i].position.z = -70;
shapes[i].rotation.z = i;
}
}
// Set Point light Intensity & Position
pointLight.intensity = Math.abs(Math.sin(u_time * 0.2) * 2);
pointLight2.intensity = Math.abs(Math.cos(u_time * 0.2) * 2);
pointLight.position.z = Math.abs(Math.sin(u_time * 0.02) * 30);
pointLight2.position.z = Math.abs(Math.cos(u_time * 0.02) * 30);
renderer.render(scene, camera);
composer.render();
var pCount = particleCount;
while (pCount--) {
var camz = getCamera().position.z;
var particle = particles.vertices[pCount];
particle.y = Math.random() * 500 - 250;
//particleSystem.vertices[i].z = camz + Math.random()*600 + 200 ;
particleSystem.geometry.vertices.needsUpdate = true;
}
particleSystem.rotation.y += -0.001;
particleSystem.rotation.z += 0.005;
var normLevel = 0.2;
beamGroup.rotation.x += BEAM_ROT_SPEED;
beamGroup.rotation.y += BEAM_ROT_SPEED;
beamMaterial.opacity = Math.min(normLevel * 0.4, 0.6);
camera.rotation.z += 0.003;
if (doShake) {
var maxshake = 60;
var shake = normLevel * maxshake ;
camera.position.x = Math.random()*shake - shake/2;
camera.position.y = Math.random()*shake - shake/2;
}
camera.rotation.z += 0.003;
// camera.rotation.y += 0.005;
// camera.rotation.x -= 0.003;
//camera.rotation.z += 0.03;
if (doStrobe){
strobeOn = !strobeOn;
if (strobeOn){
light2.intensity = 2;
}
else {
light2.intensity = 0.5;
}
}
else {
light2.intensity = 0.2;
}
// flash background on level threshold
if (normLevel > 0.5 ){
renderer.setClearColor ( 0xFFFFFF );
backMesh2.visible = true;
}
else{
renderer.setClearColor ( 0x000000 );
backMesh2.visible = false;
}
// show stripes for 6 frames on beat
backMesh2.visible = beatTime < 6;
for(var i = 0; i < BOX_COUNT; i++) {
boxes[i].update();
}
if (audioSrc.context.currentTime > 32) {
turnOnMirror();
}
// console.log(audioSrc.context.currentTime);
}
render();