WIP
This commit is contained in:
parent
42778a9d46
commit
d1ae2059f7
39 changed files with 1735 additions and 428 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,2 +1,3 @@
|
|||
/webGLTest.iml
|
||||
/.idea/
|
||||
/build/node_modules/
|
20
build/gulpfile.js
Normal file
20
build/gulpfile.js
Normal file
|
@ -0,0 +1,20 @@
|
|||
const gulp = require('gulp'),
|
||||
spriteBuild = require('./task/spriteBuilder').buildIconSprites,
|
||||
scss = require('./task/scss').buildCSS,
|
||||
js = require('./task/js').build,
|
||||
gui = require('./task/jsonMinifier').build;
|
||||
|
||||
gulp.task('scss', scss);
|
||||
gulp.task('js', js);
|
||||
gulp.task('sprite', spriteBuild);
|
||||
gulp.task('gui', gui);
|
||||
|
||||
gulp.task('watchMe', () => {
|
||||
gulp.watch('./../raw/javascript/**/*.js', gulp.series('js'));
|
||||
gulp.watch('./../raw/scss/**/*.scss', gulp.series('scss'));
|
||||
gulp.watch('./../raw/gui/**/*.json', gulp.series('gui'));
|
||||
});
|
||||
|
||||
gulp.task('default', gulp.parallel('js', 'scss', 'sprite', 'gui'));
|
||||
|
||||
gulp.task('watch', gulp.parallel('js', 'scss', 'sprite', 'gui', 'watchMe'));
|
36
build/package.json
Normal file
36
build/package.json
Normal file
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"name": "vtwebbuild",
|
||||
"version": "1.0.0",
|
||||
"description": "Buildprocess for VTWeb like babble, sass and other things",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://gitlab.com/versustune/vtweb.git"
|
||||
},
|
||||
"author": "Maurice Grönwoldt",
|
||||
"license": "ISC",
|
||||
"bugs": {
|
||||
"url": "https://gitlab.com/versustune/vtweb/issues"
|
||||
},
|
||||
"homepage": "https://gitlab.com/versustune/vtweb#readme",
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-pro": "^5.5.0",
|
||||
"@fortawesome/pro-light-svg-icons": "^5.5.0",
|
||||
"@fortawesome/pro-regular-svg-icons": "^5.5.0",
|
||||
"@fortawesome/pro-solid-svg-icons": "^5.5.0",
|
||||
"fontawesome-svg-sprite-generator": "^1.0.0",
|
||||
"gulp": "^4.0.0",
|
||||
"gulp-clean-css": "^4.0.0",
|
||||
"gulp-concat": "^2.6.1",
|
||||
"gulp-rename": "^1.4.0",
|
||||
"gulp-sass": "^4.0.2",
|
||||
"gulp-terser": "^1.1.7",
|
||||
"merge-stream": "^1.0.1",
|
||||
"node-fs-extra": "^0.8.2",
|
||||
"require-dir": "^1.0.0",
|
||||
"svg-sprite": "^1.4.0"
|
||||
}
|
||||
}
|
37
build/task/js.js
Normal file
37
build/task/js.js
Normal file
|
@ -0,0 +1,37 @@
|
|||
const terser = require('gulp-terser'),
|
||||
concat = require('gulp-concat'),
|
||||
rename = require('gulp-rename'),
|
||||
gulp = require('gulp');
|
||||
|
||||
const basePath = __dirname + '/../../raw/javascript/';
|
||||
const visualPath = basePath + 'visuals/';
|
||||
const visuals = [
|
||||
visualPath + 'sphere.js',
|
||||
//visualPath + 'wave.js',
|
||||
//visualPath + 'water.js',
|
||||
//visualPath + 'experimental.js',
|
||||
]
|
||||
const config = {
|
||||
src: [
|
||||
basePath + 'utils.js',
|
||||
basePath + 'handler.js',
|
||||
basePath + 'audio.js',
|
||||
basePath + 'player.js',
|
||||
basePath + 'gui.js',
|
||||
basePath + 'visual.js',
|
||||
...visuals,
|
||||
basePath + 'app.js'
|
||||
],
|
||||
dest: __dirname + '/../../out/js'
|
||||
};
|
||||
|
||||
function build() {
|
||||
return gulp.src(config.src)
|
||||
.pipe(concat('scripts.js'))
|
||||
.pipe(gulp.dest(config.dest))
|
||||
.pipe(rename('scripts.min.js'))
|
||||
.pipe(terser())
|
||||
.pipe(gulp.dest(config.dest));
|
||||
}
|
||||
|
||||
module.exports.build = build;
|
26
build/task/jsonMinifier.js
Normal file
26
build/task/jsonMinifier.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
const gulp = require('gulp'),
|
||||
fs = require('fs')
|
||||
|
||||
|
||||
const basePath = __dirname + '/../../raw/gui/';
|
||||
|
||||
const config = {
|
||||
src: basePath + '*.json',
|
||||
dest: __dirname + '/../../out/gui/'
|
||||
}
|
||||
|
||||
function build() {
|
||||
fs.readdirSync(basePath).forEach(file => {
|
||||
try {
|
||||
if (fs.lstatSync(basePath + file).isDirectory())
|
||||
return
|
||||
let content = fs.readFileSync(basePath + file).toString()
|
||||
fs.writeFileSync(config.dest + file, JSON.stringify(JSON.parse(content)))
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
})
|
||||
return gulp.src(config.src)
|
||||
}
|
||||
|
||||
module.exports.build = build;
|
17
build/task/scss.js
Normal file
17
build/task/scss.js
Normal file
|
@ -0,0 +1,17 @@
|
|||
const sass = require('gulp-sass'),
|
||||
clean = require('gulp-clean-css'),
|
||||
gulp = require('gulp');
|
||||
|
||||
const config = {
|
||||
src: __dirname + '/../../raw/scss/**/*.scss',
|
||||
dest: __dirname + '/../../out/theme'
|
||||
};
|
||||
|
||||
function buildCSS() {
|
||||
return gulp.src(config.src)
|
||||
.pipe(sass().on('error', sass.logError))
|
||||
.pipe(clean())
|
||||
.pipe(gulp.dest(config.dest));
|
||||
}
|
||||
|
||||
module.exports.buildCSS = buildCSS;
|
104
build/task/spriteBuilder.js
Normal file
104
build/task/spriteBuilder.js
Normal file
|
@ -0,0 +1,104 @@
|
|||
const faSvgSprite = require('fontawesome-svg-sprite-generator'),
|
||||
SVGSpriter = require('svg-sprite'),
|
||||
path = require('path'),
|
||||
fs = require('fs'),
|
||||
fal = require('@fortawesome/pro-light-svg-icons'),
|
||||
far = require('@fortawesome/pro-regular-svg-icons'),
|
||||
fas = require('@fortawesome/pro-solid-svg-icons'),
|
||||
fsextra = require('node-fs-extra'),
|
||||
gulp = require('gulp');
|
||||
|
||||
let toMergeData = [];
|
||||
|
||||
function buildIconSprites() {
|
||||
let config = {
|
||||
src: __dirname + '/../../raw/icons',
|
||||
dest: __dirname + '/../../out/icon-sprite.svg',
|
||||
spriter: {
|
||||
shape: {
|
||||
id: {
|
||||
generator: function (name) {
|
||||
return "vt-" + name.replace('.svg', '');
|
||||
}
|
||||
}
|
||||
},
|
||||
"svg": {
|
||||
"xmlDeclaration": false,
|
||||
"doctypeDeclaration": false
|
||||
},
|
||||
"mode": {
|
||||
"symbol": true
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let icons = {
|
||||
fa: [
|
||||
fal.faPlay,
|
||||
fal.faPause,
|
||||
fal.faCaretRight,
|
||||
fal.faCaretLeft,
|
||||
fal.faRandom,
|
||||
fal.faCogs,
|
||||
fal.faFolderUpload,
|
||||
fal.faListMusic,
|
||||
],
|
||||
vt: []
|
||||
};
|
||||
|
||||
builder.init(config, icons);
|
||||
builder.generateFontAwesome();
|
||||
builder.generateFromIcons();
|
||||
return gulp.src(config.src);
|
||||
}
|
||||
|
||||
let builder = {
|
||||
init: function (config, icons) {
|
||||
this.config = config;
|
||||
this.icons = icons;
|
||||
},
|
||||
|
||||
generateFontAwesome: function () {
|
||||
let sprite = faSvgSprite.generate(this.icons.fa, {license: '', xmlDeclaration: false});
|
||||
toMergeData.push(sprite.svg);
|
||||
},
|
||||
|
||||
generateFromIcons: function () {
|
||||
builder.merge();
|
||||
},
|
||||
|
||||
merge: function () {
|
||||
if (toMergeData.length === 0) {
|
||||
return;
|
||||
}
|
||||
let data = '<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg">';
|
||||
for (let item of toMergeData) {
|
||||
data += item.replace('</svg>', '').replace(/(<svg)([^<]*|[^>]*)/g, '');
|
||||
}
|
||||
data += '</svg>';
|
||||
|
||||
let dirname = path.dirname(builder.config.dest);
|
||||
if (!fs.existsSync(dirname)) {
|
||||
fsextra.mkdirpSync(dirname);
|
||||
}
|
||||
fs.writeFileSync(builder.config.dest, data);
|
||||
},
|
||||
|
||||
readFiles: function (dir, spriter, icons) {
|
||||
let files = fs.readdirSync(dir);
|
||||
for (let file of files) {
|
||||
let split = file.split('.');
|
||||
let suffix = split[split.length - 1];
|
||||
if (suffix === 'svg' && icons.indexOf('vt-' + split[0]) !== -1) {
|
||||
let filePath = path.resolve(dir, file);
|
||||
spriter.add(
|
||||
filePath,
|
||||
file,
|
||||
fs.readFileSync(filePath, {encoding: 'utf-8'})
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.buildIconSprites = buildIconSprites;
|
71
index.html
71
index.html
|
@ -3,32 +3,55 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>WEBGL Test</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<link rel="stylesheet" href="out/theme/style.css">
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="c" width="1900" height="1000"></canvas>
|
||||
<div class="off-can closed">
|
||||
<group id="rotate">
|
||||
<group-label>Rotation</group-label>
|
||||
</group>
|
||||
<group id="translate">
|
||||
<group-label>Transform</group-label>
|
||||
</group>
|
||||
<group id="color">
|
||||
<group-label>Color</group-label>
|
||||
</group>
|
||||
<group id="world">
|
||||
<group-label>World</group-label>
|
||||
</group>
|
||||
<group id="draw">
|
||||
<group-label>Draw</group-label>
|
||||
</group>
|
||||
<div class="loading-screen">
|
||||
<loader></loader>
|
||||
<loader class="delay"></loader>
|
||||
<span>Loading</span>
|
||||
</div>
|
||||
<div class="settings-icon">☰</div>
|
||||
<script src="js/utils.js" defer></script>
|
||||
<script src="js/handler.js"></script>
|
||||
<script src="js/index.js"></script>
|
||||
<script src="js/sphere.js"></script>
|
||||
<script src="js/gui.js"></script>
|
||||
<div class="top-menu-left">
|
||||
<div class="settings-icon menu-icon">
|
||||
<svg role="img" class="icon">
|
||||
<use href="out/icon-sprite.svg#fal-fa-cogs"></use>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="upload menu-icon">
|
||||
<label for="upload">
|
||||
<svg role="img" class="icon">
|
||||
<use href="out/icon-sprite.svg#fal-fa-folder-upload"></use>
|
||||
</svg>
|
||||
</label>
|
||||
<input type="file" accept="audio/*" id="upload">
|
||||
</div>
|
||||
<div class="playlist menu-icon">
|
||||
<svg role="img" class="icon">
|
||||
<use href="out/icon-sprite.svg#fal-fa-list-music"></use>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div class="controls">
|
||||
<button id="previous">
|
||||
<svg role="img" class="icon">
|
||||
<use href="out/icon-sprite.svg#fal-fa-caret-left"></use>
|
||||
</svg>
|
||||
</button>
|
||||
<button id="play">
|
||||
<svg role="img" class="icon hide">
|
||||
<use href="out/icon-sprite.svg#fal-fa-pause"></use>
|
||||
</svg>
|
||||
<svg role="img" class="icon">
|
||||
<use href="out/icon-sprite.svg#fal-fa-play"></use>
|
||||
</svg>
|
||||
</button>
|
||||
<button id="next">
|
||||
<svg role="img" class="icon">
|
||||
<use href="out/icon-sprite.svg#fal-fa-caret-right"></use>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<canvas id="c"></canvas>
|
||||
<script src="out/js/scripts.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -80,4 +80,13 @@ class Shaders {
|
|||
getProgram(name) {
|
||||
return this.programs[name];
|
||||
}
|
||||
|
||||
async loadArray(list, path) {
|
||||
let self = this;
|
||||
for (const e of list) {
|
||||
await self.loadShader(e, path)
|
||||
}
|
||||
await self.createProgramForEach(list)
|
||||
return true;
|
||||
}
|
||||
}
|
59
js/index.js
59
js/index.js
|
@ -1,22 +1,35 @@
|
|||
let shaderHandler, gl, c, actx, analyser, peak;
|
||||
let positionData = [];
|
||||
let positionSize = 8192 * 2 * 2;
|
||||
let shaderHandler, gl, c, actx, analyser, peak, isInit = false;
|
||||
|
||||
function createAudioContextStream(stream) {
|
||||
function createAudioContextStream(audio) {
|
||||
let AudioContext = window.AudioContext || window.webkitAudioContext;
|
||||
if (actx) {
|
||||
actx.close();
|
||||
}
|
||||
actx = new AudioContext();
|
||||
analyser = actx.createAnalyser();
|
||||
let MEDIA_ELEMENT_NODES = new WeakMap();
|
||||
let Source;
|
||||
|
||||
analyser.fftSize = 4096;
|
||||
analyser.maxDecibels = 0;
|
||||
analyser.smoothingTimeConstant = .4;
|
||||
Source = actx.createMediaStreamSource(stream);
|
||||
if (audio) {
|
||||
if (MEDIA_ELEMENT_NODES.has(audio)) {
|
||||
Source = MEDIA_ELEMENT_NODES.get(audio);
|
||||
} else {
|
||||
Source = actx.createMediaElementSource(audio);
|
||||
MEDIA_ELEMENT_NODES.set(audio, Source);
|
||||
}
|
||||
|
||||
Source.connect(analyser);
|
||||
analyser.connect(actx.destination);
|
||||
audio.oncanplay = () => {
|
||||
actx.resume();
|
||||
};
|
||||
audio.onended = function () {
|
||||
actx.pause();
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -28,26 +41,38 @@ async function init() {
|
|||
return false;
|
||||
}
|
||||
shaderHandler = new Shaders(gl);
|
||||
await shaderHandler.loadShader("test", "shaders/");
|
||||
await shaderHandler.loadShader("wave", "shaders/");
|
||||
|
||||
//sphere shader
|
||||
await shaderHandler.loadShader("sphere", "shaders/", gl.VERTEX_SHADER);
|
||||
return shaderHandler.createProgramForEach(["test", "sphere"]);
|
||||
return shaderHandler.createProgramForEach(["wave", "sphere"]);
|
||||
}
|
||||
|
||||
(function () {
|
||||
navigator.mediaDevices.getUserMedia({audio: true, video: false})
|
||||
.then(createAudioContextStream).then(e => {
|
||||
function createView() {
|
||||
if (!isInit) {
|
||||
createAudioContextStream(audioFile);
|
||||
init().then(b => {
|
||||
if (b) {
|
||||
loadConfig();
|
||||
draw();
|
||||
}
|
||||
})
|
||||
isInit = true;
|
||||
}
|
||||
}
|
||||
|
||||
function initGUI() {
|
||||
generateRotationSliders();
|
||||
generateColorSliders();
|
||||
generateWorldSliders();
|
||||
generateDrawSliders();
|
||||
generateTranslateSliders();
|
||||
init().then(b => {
|
||||
if (b) {
|
||||
sphereObject.drawMode = gl.POINTS;
|
||||
draw();
|
||||
}
|
||||
})
|
||||
});
|
||||
})();
|
||||
|
||||
(function () {
|
||||
if (document.readyState === "complete" || document.readyState === "interactive") {
|
||||
initGUI()
|
||||
} else {
|
||||
document.addEventListener('DOMContentLoaded', initGUI);
|
||||
}
|
||||
})()
|
88
js/old.js
88
js/old.js
|
@ -1,88 +0,0 @@
|
|||
function readData() {
|
||||
let items = analyser.fftSize;
|
||||
let dataArray = new Float32Array(items);
|
||||
analyser.getFloatTimeDomainData(dataArray);
|
||||
let space = 255 / (items + 2);
|
||||
let pos = [0, 127.5];
|
||||
let x = space;
|
||||
peak = 0;
|
||||
for (let i = 0; i < items; i++) {
|
||||
let data = (dataArray[i] * 125) + 127.5
|
||||
if (Math.abs(data) > peak) {
|
||||
peak = data;
|
||||
}
|
||||
pos.push(x);
|
||||
pos.push(data);
|
||||
x += space;
|
||||
}
|
||||
pos.push(255, 127.5);
|
||||
positions = pos;
|
||||
}
|
||||
|
||||
let positions = [
|
||||
Math.random(), Math.random(),
|
||||
Math.random(), Math.random(),
|
||||
Math.random(), Math.random(),
|
||||
];
|
||||
|
||||
/*function draw() {
|
||||
readData();
|
||||
let program = shaderHandler.getProgram("test");
|
||||
let positionAttributeLocation = gl.getAttribLocation(program, "a_position");
|
||||
var colorLocation = gl.getUniformLocation(program, "u_color");
|
||||
let positionBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.DYNAMIC_DRAW);
|
||||
let vao = gl.createVertexArray();
|
||||
gl.bindVertexArray(vao);
|
||||
gl.enableVertexAttribArray(positionAttributeLocation);
|
||||
gl.vertexAttribPointer(
|
||||
positionAttributeLocation, 2, gl.FLOAT, false, 0, 0);
|
||||
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
|
||||
|
||||
gl.clearColor(0, 0, 0, 1);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
||||
gl.useProgram(program);
|
||||
gl.uniform4f(colorLocation, peak / 255, (255 - peak) / 255, .2, 1);
|
||||
gl.drawArrays(gl.LINE_STRIP, 0, positions.length / 2);
|
||||
|
||||
let positionBuffer2 = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer2);
|
||||
gl.uniform4f(colorLocation, 0, 0, 1, .3);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.DYNAMIC_DRAW);
|
||||
gl.drawArrays(gl.POINTS, 0, positions.length / 2);
|
||||
|
||||
requestAnimationFrame(draw);
|
||||
}*/
|
||||
|
||||
function setupSphere() {
|
||||
sphereData = [];
|
||||
let data = readData(),
|
||||
radData = data[0];
|
||||
let sin = Math.sin,
|
||||
cos = Math.cos,
|
||||
total = sphereObject.total || 50,
|
||||
cTotal = (total + 1) * (total + 1),
|
||||
r = sphereObject.radius || 1000,
|
||||
rx = r / c.width,
|
||||
ry = r / c.height,
|
||||
counter = 0;
|
||||
for (let i = 1; i <= total; i++) {
|
||||
let lat = VTUtils.map(i, 0, total, 0, Math.PI, false);
|
||||
for (let j = 1; j <= total; j++) {
|
||||
let lon = VTUtils.map(j, 0, total, 0, Math.TWO_PI, false);
|
||||
let map = VTUtils.map(counter, 0, cTotal, 0, radData.length - 1, false);
|
||||
map = Math.floor(map);
|
||||
let realRX = rx + radData[map];
|
||||
let realRY = ry + radData[map];
|
||||
let x = rx * sin(lon) * cos(lat);
|
||||
let y = rx * sin(lon) * sin(lat);
|
||||
let z = ry * cos(lon);
|
||||
sphereData.push(x);
|
||||
sphereData.push(y);
|
||||
sphereData.push(z);
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
return [VTUtils.hsvToRgb(data[1], 1, 1), data[1]];
|
||||
}
|
48
js/sphere.js
48
js/sphere.js
|
@ -7,20 +7,21 @@ let sphereObject = {
|
|||
rotation: [0, 0, 0], //radians
|
||||
rotateInc: [0.0, 0.0, 0.0], //degreesInc
|
||||
rotateByBeat: true,
|
||||
translate: [1, 1, 1],
|
||||
translate: [0, 0, 0],
|
||||
total: 50,
|
||||
radius: 500,
|
||||
color: {r: 0, g: 0, b: 0},
|
||||
colorByBeat: true,
|
||||
drawMode: 0,
|
||||
drawMode: 5,
|
||||
sphereMode: 0,
|
||||
lightPos: [0, 0, 0],
|
||||
pointSize: 2,
|
||||
steps: 512,
|
||||
dirtyMode: false
|
||||
dirtyMode: false,
|
||||
light: 0.3
|
||||
}
|
||||
|
||||
function readData() {
|
||||
function readDataBar() {
|
||||
let items = sphereObject.steps;
|
||||
let dataArray = new Uint8Array(items);
|
||||
analyser.getByteFrequencyData(dataArray);
|
||||
|
@ -36,6 +37,7 @@ function readData() {
|
|||
|
||||
let sphereDataVectors = [], lastTotal = 0;
|
||||
|
||||
// avoid garbage collection each run
|
||||
function prepareData() {
|
||||
let total = sphereObject.total;
|
||||
if (lastTotal !== total) {
|
||||
|
@ -52,7 +54,7 @@ function prepareData() {
|
|||
|
||||
function setupSphere() {
|
||||
sphereData = [];
|
||||
let data = readData(),
|
||||
let data = readDataBar(),
|
||||
radData = data[0],
|
||||
map = VTUtils.map,
|
||||
total = sphereObject.total,
|
||||
|
@ -94,14 +96,21 @@ function setupSphere() {
|
|||
|
||||
function getAddRad(counter, data, total) {
|
||||
let mapping, rAdd, map = VTUtils.map;
|
||||
if (sphereObject.sphereMode === 3) {
|
||||
let h = total / 2;
|
||||
if (sphereObject.sphereMode === 3) {
|
||||
if (counter > h) {
|
||||
mapping = map(counter, h, total, data.length - 1, 0);
|
||||
} else {
|
||||
mapping = map(counter, 0, h, 0, data.length - 1);
|
||||
}
|
||||
rAdd = data[Math.round(mapping)] || 0;
|
||||
} else if (sphereObject.sphereMode === 4) {
|
||||
if (counter > h) {
|
||||
mapping = map(counter, h, total, 0, data.length - 1);
|
||||
} else {
|
||||
mapping = map(counter, 0, h, data.length - 1, 0);
|
||||
}
|
||||
rAdd = data[Math.round(mapping)] || 0;
|
||||
} else {
|
||||
mapping = map(counter, 0, total, 0, data.length - 1);
|
||||
rAdd = data[Math.round(mapping)] || 0;
|
||||
|
@ -109,18 +118,16 @@ function getAddRad(counter, data, total) {
|
|||
return rAdd;
|
||||
}
|
||||
|
||||
let position, world, color, rotate, light, lightPos, lightAngle = 90;
|
||||
let position, color, rotate, light, lightPos;
|
||||
|
||||
function prepare(program) {
|
||||
position = gl.getAttribLocation(program, "a_position");
|
||||
world = gl.getUniformLocation(program, 'u_world');
|
||||
color = gl.getUniformLocation(program, "u_color");
|
||||
light = gl.getUniformLocation(program, "u_light");
|
||||
rotate = gl.getUniformLocation(program, "u_matrix");
|
||||
lightPos = gl.getUniformLocation(program, "u_lightPos");
|
||||
let pointSize = gl.getUniformLocation(program, "u_pointSize");
|
||||
gl.uniformMatrix4fv(world, false, TDUtils.yRotation(TDUtils.degToRad(lightAngle)));
|
||||
gl.uniform3fv(light, [0.95, 0.62, 0.094]);
|
||||
gl.uniform3fv(light, [sphereObject.light, 0, 0]);
|
||||
gl.uniform3fv(lightPos, sphereObject.lightPos);
|
||||
gl.uniform1f(pointSize, sphereObject.pointSize);
|
||||
}
|
||||
|
@ -135,16 +142,15 @@ function draw() {
|
|||
gl.useProgram(program);
|
||||
prepare(program);
|
||||
let matrix = [
|
||||
sphereObject.translate[0] / aspect, 0, 0, 0,
|
||||
0, sphereObject.translate[1], 0, 0,
|
||||
0, 0, sphereObject.translate[2], 0,
|
||||
0, 0, 0, 1
|
||||
1 / aspect, 0, 0, 0,
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
sphereObject.translate[0], sphereObject.translate[1], sphereObject.translate[2], 1
|
||||
]
|
||||
matrix = TDUtils.multiply(matrix, TDUtils.xRotation(sphereObject.rotation[0]));
|
||||
matrix = TDUtils.multiply(matrix, TDUtils.yRotation(sphereObject.rotation[1]));
|
||||
matrix = TDUtils.multiply(matrix, TDUtils.zRotation(sphereObject.rotation[2]));
|
||||
gl.uniformMatrix4fv(rotate, false, matrix);
|
||||
|
||||
let positionBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(sphereData), gl.DYNAMIC_DRAW);
|
||||
|
@ -152,7 +158,6 @@ function draw() {
|
|||
gl.bindVertexArray(vao);
|
||||
gl.enableVertexAttribArray(position);
|
||||
gl.vertexAttribPointer(position, 3, gl.FLOAT, true, 0, 0);
|
||||
|
||||
gl.clearColor(0, 0, 0, 1);
|
||||
gl.enable(gl.DEPTH_TEST);
|
||||
gl.depthFunc(gl.LEQUAL);
|
||||
|
@ -186,12 +191,6 @@ function sphereMode(lat, lon, i, counter, rx, ry) {
|
|||
sin = Math.sin,
|
||||
cos = Math.cos;
|
||||
switch (sphereObject.sphereMode) {
|
||||
case 0:
|
||||
case 3:
|
||||
x = rx * sin(lat) * cos(lon);
|
||||
y = ry * sin(lat) * sin(lon);
|
||||
z = ry * cos(lat);
|
||||
break;
|
||||
case 1:
|
||||
x = rx * sin(lon) * cos(lat);
|
||||
y = ry * sin(lon) * sin(lat);
|
||||
|
@ -202,6 +201,11 @@ function sphereMode(lat, lon, i, counter, rx, ry) {
|
|||
y = ry * sin(lat) * sin(lat);
|
||||
z = ry * cos(lon);
|
||||
break;
|
||||
default:
|
||||
x = rx * sin(lat) * cos(lon);
|
||||
y = ry * sin(lat) * sin(lon);
|
||||
z = ry * cos(lat);
|
||||
break;
|
||||
}
|
||||
return {x: x, y: y, z: z};
|
||||
}
|
37
js/utils.js
37
js/utils.js
|
@ -236,3 +236,40 @@ class TDUtils {
|
|||
return d * Math.PI / 180;
|
||||
}
|
||||
}
|
||||
|
||||
function $(sel, s) {
|
||||
return $$(sel, s)[0];
|
||||
}
|
||||
|
||||
function $$(sel, s) {
|
||||
s = s || document;
|
||||
return s.querySelectorAll(sel);
|
||||
}
|
||||
|
||||
Node.prototype.addDelegatedEventListener = function (type, aim, cb) {
|
||||
this.addEventListener(type, (event) => {
|
||||
let target = event.target;
|
||||
if (target.matches(aim)) {
|
||||
cb(event, target);
|
||||
} else {
|
||||
let parent = target.closest(aim);
|
||||
if (parent) {
|
||||
cb(event, parent);
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
function create(name, content) {
|
||||
let d = document.createElement(name);
|
||||
if (content) {
|
||||
d.innerHTML = content;
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
function append(to, array) {
|
||||
for (let item in array) {
|
||||
to.appendChild(array[item]);
|
||||
}
|
||||
}
|
|
@ -1,40 +1,3 @@
|
|||
function $(sel, s) {
|
||||
return $$(sel, s)[0];
|
||||
}
|
||||
|
||||
function $$(sel, s) {
|
||||
s = s || document;
|
||||
return s.querySelectorAll(sel);
|
||||
}
|
||||
|
||||
Node.prototype.addDelegatedEventListener = function (type, aim, cb) {
|
||||
this.addEventListener(type, (event) => {
|
||||
let target = event.target;
|
||||
if (target.matches(aim)) {
|
||||
cb(event, target);
|
||||
} else {
|
||||
let parent = target.closest(aim);
|
||||
if (parent) {
|
||||
cb(event, parent);
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
function create(name, content) {
|
||||
let d = document.createElement(name);
|
||||
if (content) {
|
||||
d.innerHTML = content;
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
function append(to, array) {
|
||||
for (let item in array) {
|
||||
to.appendChild(array[item]);
|
||||
}
|
||||
}
|
||||
|
||||
function generateRotationSliders() {
|
||||
let group = $('#rotate');
|
||||
generateSlider(["X", "Y", "Z", "X-Inc", "Y-Inc", "Z-Inc"], 0, 360, 0, group, "rotate");
|
||||
|
@ -43,7 +6,7 @@ function generateRotationSliders() {
|
|||
|
||||
function generateTranslateSliders() {
|
||||
let group = $('#translate');
|
||||
generateSlider(["X", "Y", "Z"], -1, 1, 1, group, "translate");
|
||||
generateSlider(["X", "Y", "Z"], -1, 1, 0, group, "translate");
|
||||
}
|
||||
|
||||
function generateColorSliders() {
|
||||
|
@ -54,20 +17,20 @@ function generateColorSliders() {
|
|||
|
||||
function generateWorldSliders() {
|
||||
let group = $('#world');
|
||||
generateSlider(["LightPos-X", "LightPos-Y", "LightPos-Z"], -1, 1, 1, group, "light");
|
||||
generateSlider(["LightAngle"], 0, 360, 90, group, "light");
|
||||
generateSlider(["LightPos-X", "LightPos-Y", "LightPos-Z"], -100, 100, 0, group, "light");
|
||||
generateSlider(["Light"], 0, 1, 0.3, group, "light");
|
||||
}
|
||||
|
||||
function generateDrawSliders() {
|
||||
let group = $('#draw'),
|
||||
g = "drawMode"
|
||||
generateSlider(["DrawMode"], 0, 6, 0, group, g);
|
||||
generateSlider(["Form"], 0, 3, 0, group, g);
|
||||
generateSlider(["Form"], 0, 4, 0, group, g);
|
||||
generateSlider(["Radius"], 20, 1500, 500, group, g);
|
||||
generateSlider(["Total"], 0, 200, 50, group, g);
|
||||
generateSlider(["Total"], 20, 250, 50, group, g);
|
||||
generateSlider(["PointSize"], 1, 10, 2, group, g, .2);
|
||||
generateSlider(["Smoothing"], 0, 1, 0.8, group, g, .05);
|
||||
generateSlider(["Steps"], 512, analyser.fftSize / 2, 512, group, g, 256);
|
||||
generateSlider(["Smoothing"], 0, 100, 80, group, g, 1);
|
||||
generateSlider(["Steps"], 256, 2048, 512, group, g, 16);
|
||||
generateCheckBox(["Dirty"], false, group, g)
|
||||
}
|
||||
|
||||
|
@ -102,11 +65,10 @@ function setColors() {
|
|||
|
||||
function setWorld() {
|
||||
let group = $('#world');
|
||||
sphereObject.lightPos[0] = getValue($('#LightPos-X', group)) * 0.2;
|
||||
sphereObject.lightPos[1] = getValue($('#LightPos-Y', group)) * 0.2;
|
||||
sphereObject.lightPos[2] = getValue($('#LightPos-Z', group)) * 0.2;
|
||||
|
||||
lightAngle = getValue($('#LightAngle', group))
|
||||
sphereObject.lightPos[0] = getValue($('#LightPos-X', group));
|
||||
sphereObject.lightPos[1] = getValue($('#LightPos-Y', group));
|
||||
sphereObject.lightPos[2] = getValue($('#LightPos-Z', group));
|
||||
sphereObject.light = getValue($('#Light', group));
|
||||
}
|
||||
|
||||
function setDraw() {
|
||||
|
@ -118,7 +80,7 @@ function setDraw() {
|
|||
sphereObject.pointSize = getValue($('#PointSize', group));
|
||||
sphereObject.steps = getValue($('#Steps', group));
|
||||
sphereObject.dirtyMode = $('#drawModeDirty', group).checked;
|
||||
analyser.smoothingTimeConstant = getValue($('#Smoothing', group));
|
||||
analyser.smoothingTimeConstant = getValue($('#Smoothing', group)) / 100;
|
||||
}
|
||||
|
||||
function setTranslate() {
|
||||
|
@ -183,6 +145,7 @@ function changeHandler(el) {
|
|||
} else if (d === "drawMode") {
|
||||
setDraw();
|
||||
}
|
||||
saveConfig();
|
||||
}
|
||||
|
||||
document.body.addDelegatedEventListener('input', 'group-input input', (ev, el) => {
|
||||
|
@ -205,4 +168,60 @@ function getValue(slider) {
|
|||
|
||||
$('.settings-icon').addEventListener('click', function () {
|
||||
$('.off-can').classList.toggle("closed");
|
||||
$('.settings-icon').classList.toggle("open");
|
||||
})
|
||||
|
||||
window.addEventListener('keyup', e => {
|
||||
if (e.key === 'F11') {
|
||||
c.requestFullscreen();
|
||||
return;
|
||||
}
|
||||
if (e.key === 'Escape') {
|
||||
if (document.fullscreenElement) {
|
||||
document.exitFullscreen().then(console.log);
|
||||
}
|
||||
}
|
||||
if (e.key === 'p') {
|
||||
audioFile.play();
|
||||
}
|
||||
if (e.key === 's') {
|
||||
audioFile.pause();
|
||||
}
|
||||
});
|
||||
|
||||
function saveConfig() {
|
||||
localStorage.setItem('config-sphere', JSON.stringify(sphereObject));
|
||||
}
|
||||
|
||||
function loadConfig() {
|
||||
let item = localStorage.getItem('config-sphere');
|
||||
if (item && item !== "") {
|
||||
sphereObject = JSON.parse(item);
|
||||
}
|
||||
}
|
||||
|
||||
let uploadField = $('#upload');
|
||||
let audioFile = new Audio();
|
||||
let lastSong = null;
|
||||
uploadField.addEventListener('change', e => {
|
||||
let file = uploadField.files[0];
|
||||
if (file && file.type.indexOf('audio') !== -1 && file.name.match(".m3u") === null && file.name.match(".wma") === null) {
|
||||
if (lastSong) {
|
||||
URL.revokeObjectURL(lastSong);
|
||||
}
|
||||
audioFile.src = URL.createObjectURL(file);
|
||||
document.title = file.name;
|
||||
lastSong = audioFile.src;
|
||||
createView();
|
||||
}
|
||||
})
|
||||
|
||||
$('#play').addEventListener('click', e => {
|
||||
if (audioFile.src !== "") {
|
||||
c.requestFullscreen().then(r => {
|
||||
setTimeout(x => {
|
||||
audioFile.play();
|
||||
}, 1000)
|
||||
});
|
||||
}
|
||||
})
|
0
out/gui/.gitkeep
Normal file
0
out/gui/.gitkeep
Normal file
1
out/gui/sphere.json
Normal file
1
out/gui/sphere.json
Normal file
|
@ -0,0 +1 @@
|
|||
[{"group":"rotation","name":["X","Y","Z"],"props":[0,1,2],"type":"slider","max":360,"min":0},{"group":"rotation","name":["X-Inc","Y-Inc","Z-Inc"],"props":[0,1,2],"type":"slider","max":1,"min":0,"stepSize":0.01},{"group":"rotation","name":"by-Beat","type":"checkbox","value":true,"tooltip":"Rotate the Sphere based by Beat <br> Low-Freq = Y, Mid-Freq = Z, High-Freq = X"},{"group":"color","name":["R","G","B"],"props":["r","g","b"],"type":"slider","max":255,"min":0},{"group":"light","name":["X","Y","Z"],"props":[0,1,2],"type":"slider","max":1,"min":-1,"value":0,"stepSize":0.1},{"group":"light","name":"Light","type":"slider","max":1,"min":0,"stepSize":0.05},{"group":"color","name":"by-Beat","type":"checkbox","value":true,"tooltip":"Draw The Color Strength based on the Low-Freq"},{"group":"draw","name":"DrawMode","type":"slider","max":6,"min":0},{"group":"draw","name":"Form","type":"slider","max":4,"min":0},{"group":"draw","name":"Radius","type":"slider","max":1500,"min":20},{"group":"draw","name":"Total","type":"slider","max":200,"min":20},{"group":"draw","name":"PointSize","type":"slider","max":10,"min":1,"stepSize":0.2},{"group":"draw","name":"Dirty","type":"checkbox","value":false,"tooltip":"Full Draw or with less Points"}]
|
1
out/icon-sprite.svg
Normal file
1
out/icon-sprite.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 7.6 KiB |
431
out/js/scripts.js
Normal file
431
out/js/scripts.js
Normal file
|
@ -0,0 +1,431 @@
|
|||
class VTUtils {
|
||||
static random(min, max) {
|
||||
let rand = Math.random();
|
||||
if (typeof min === 'undefined') {
|
||||
return rand;
|
||||
} else if (typeof max === 'undefined') {
|
||||
if (min instanceof Array) {
|
||||
return min[Math.floor(rand * min.length)];
|
||||
} else {
|
||||
return rand * min;
|
||||
}
|
||||
} else {
|
||||
if (min > max) {
|
||||
let tmp = min;
|
||||
min = max;
|
||||
max = tmp;
|
||||
}
|
||||
return rand * (max - min) + min;
|
||||
}
|
||||
};
|
||||
|
||||
static randomInt(min, max) {
|
||||
return Math.floor(VTUtils.random(min, max));
|
||||
}
|
||||
|
||||
static normalize(val, max, min) {
|
||||
return (val - min) / (max - min);
|
||||
};
|
||||
|
||||
static distance(x, y, x2, y2) {
|
||||
let a = x - x2;
|
||||
let b = y - y2;
|
||||
|
||||
return Math.sqrt(a * a + b * b);
|
||||
}
|
||||
|
||||
static map(n, start1, stop1, start2, stop2, withinBounds) {
|
||||
let newVal = (n - start1) / (stop1 - start1) * (stop2 - start2) + start2;
|
||||
if (!withinBounds) {
|
||||
return newVal;
|
||||
}
|
||||
if (start2 < stop2) {
|
||||
return this.constrain(newVal, start2, stop2);
|
||||
} else {
|
||||
return this.constrain(newVal, stop2, start2);
|
||||
}
|
||||
};
|
||||
|
||||
static constrain(n, low, high) {
|
||||
return Math.max(Math.min(n, high), low);
|
||||
}
|
||||
|
||||
static hsvToRgb(h, s, v) {
|
||||
var r, g, b;
|
||||
|
||||
var i = Math.floor(h * 6);
|
||||
var f = h * 6 - i;
|
||||
var p = v * (1 - s);
|
||||
var q = v * (1 - f * s);
|
||||
var t = v * (1 - (1 - f) * s);
|
||||
|
||||
switch (i % 6) {
|
||||
case 0:
|
||||
r = v, g = t, b = p;
|
||||
break;
|
||||
case 1:
|
||||
r = q, g = v, b = p;
|
||||
break;
|
||||
case 2:
|
||||
r = p, g = v, b = t;
|
||||
break;
|
||||
case 3:
|
||||
r = p, g = q, b = v;
|
||||
break;
|
||||
case 4:
|
||||
r = t, g = p, b = v;
|
||||
break;
|
||||
case 5:
|
||||
r = v, g = p, b = q;
|
||||
break;
|
||||
}
|
||||
|
||||
return {r: r, g: g, b: b};
|
||||
}
|
||||
|
||||
static peakRGB(peak) {
|
||||
return {
|
||||
r: peak,
|
||||
g: 1 - peak,
|
||||
b: 0
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class VTVector {
|
||||
constructor(x, y, z) {
|
||||
this.x = x || 0;
|
||||
this.y = y || 0;
|
||||
this.z = z || 0;
|
||||
}
|
||||
|
||||
//helper
|
||||
static createRandom(x, y, z) {
|
||||
x = x || 1;
|
||||
y = y || 1;
|
||||
z = z || 0;
|
||||
return new VTVector(VTUtils.random(-x, x), VTUtils.random(-y, y), VTUtils.random(-z, z));
|
||||
}
|
||||
|
||||
mult(times) {
|
||||
this.x *= times;
|
||||
this.y *= times;
|
||||
this.z *= times;
|
||||
}
|
||||
|
||||
set(vector) {
|
||||
this.x = vector.x;
|
||||
this.y = vector.y;
|
||||
this.z = vector.z;
|
||||
}
|
||||
|
||||
add(vector) {
|
||||
this.x = this.x + vector.x;
|
||||
this.y = this.y + vector.y;
|
||||
this.z = this.z + vector.z;
|
||||
}
|
||||
|
||||
addXYZ(x, y, z) {
|
||||
this.x += x;
|
||||
this.y += y;
|
||||
this.z += z;
|
||||
}
|
||||
|
||||
setXYZ(x, y, z) {
|
||||
this.x = x || 0;
|
||||
this.y = y || 0;
|
||||
this.z = z || 0;
|
||||
}
|
||||
|
||||
clone() {
|
||||
return new VTVector(this.x, this.y, this.z);
|
||||
}
|
||||
}
|
||||
|
||||
class TDUtils {
|
||||
static multiply(a, b) {
|
||||
let b00 = b[0 * 4 + 0];
|
||||
let b01 = b[0 * 4 + 1];
|
||||
let b02 = b[0 * 4 + 2];
|
||||
let b03 = b[0 * 4 + 3];
|
||||
let b10 = b[1 * 4 + 0];
|
||||
let b11 = b[1 * 4 + 1];
|
||||
let b12 = b[1 * 4 + 2];
|
||||
let b13 = b[1 * 4 + 3];
|
||||
let b20 = b[2 * 4 + 0];
|
||||
let b21 = b[2 * 4 + 1];
|
||||
let b22 = b[2 * 4 + 2];
|
||||
let b23 = b[2 * 4 + 3];
|
||||
let b30 = b[3 * 4 + 0];
|
||||
let b31 = b[3 * 4 + 1];
|
||||
let b32 = b[3 * 4 + 2];
|
||||
let b33 = b[3 * 4 + 3];
|
||||
let a00 = a[0 * 4 + 0];
|
||||
let a01 = a[0 * 4 + 1];
|
||||
let a02 = a[0 * 4 + 2];
|
||||
let a03 = a[0 * 4 + 3];
|
||||
let a10 = a[1 * 4 + 0];
|
||||
let a11 = a[1 * 4 + 1];
|
||||
let a12 = a[1 * 4 + 2];
|
||||
let a13 = a[1 * 4 + 3];
|
||||
let a20 = a[2 * 4 + 0];
|
||||
let a21 = a[2 * 4 + 1];
|
||||
let a22 = a[2 * 4 + 2];
|
||||
let a23 = a[2 * 4 + 3];
|
||||
let a30 = a[3 * 4 + 0];
|
||||
let a31 = a[3 * 4 + 1];
|
||||
let a32 = a[3 * 4 + 2];
|
||||
let a33 = a[3 * 4 + 3];
|
||||
let dst = [];
|
||||
dst[0] = b00 * a00 + b01 * a10 + b02 * a20 + b03 * a30;
|
||||
dst[1] = b00 * a01 + b01 * a11 + b02 * a21 + b03 * a31;
|
||||
dst[2] = b00 * a02 + b01 * a12 + b02 * a22 + b03 * a32;
|
||||
dst[3] = b00 * a03 + b01 * a13 + b02 * a23 + b03 * a33;
|
||||
dst[4] = b10 * a00 + b11 * a10 + b12 * a20 + b13 * a30;
|
||||
dst[5] = b10 * a01 + b11 * a11 + b12 * a21 + b13 * a31;
|
||||
dst[6] = b10 * a02 + b11 * a12 + b12 * a22 + b13 * a32;
|
||||
dst[7] = b10 * a03 + b11 * a13 + b12 * a23 + b13 * a33;
|
||||
dst[8] = b20 * a00 + b21 * a10 + b22 * a20 + b23 * a30;
|
||||
dst[9] = b20 * a01 + b21 * a11 + b22 * a21 + b23 * a31;
|
||||
dst[10] = b20 * a02 + b21 * a12 + b22 * a22 + b23 * a32;
|
||||
dst[11] = b20 * a03 + b21 * a13 + b22 * a23 + b23 * a33;
|
||||
dst[12] = b30 * a00 + b31 * a10 + b32 * a20 + b33 * a30;
|
||||
dst[13] = b30 * a01 + b31 * a11 + b32 * a21 + b33 * a31;
|
||||
dst[14] = b30 * a02 + b31 * a12 + b32 * a22 + b33 * a32;
|
||||
dst[15] = b30 * a03 + b31 * a13 + b32 * a23 + b33 * a33;
|
||||
return dst;
|
||||
}
|
||||
|
||||
static xRotation(angleInRadians) {
|
||||
let c = Math.cos(angleInRadians);
|
||||
let s = Math.sin(angleInRadians);
|
||||
|
||||
return [
|
||||
1, 0, 0, 0,
|
||||
0, c, s, 0,
|
||||
0, -s, c, 0,
|
||||
0, 0, 0, 1,
|
||||
];
|
||||
}
|
||||
|
||||
static yRotation(angleInRadians) {
|
||||
let c = Math.cos(angleInRadians);
|
||||
let s = Math.sin(angleInRadians);
|
||||
|
||||
return [
|
||||
c, 0, -s, 0,
|
||||
0, 1, 0, 0,
|
||||
s, 0, c, 0,
|
||||
0, 0, 0, 1,
|
||||
];
|
||||
}
|
||||
|
||||
static zRotation(angleInRadians) {
|
||||
let c = Math.cos(angleInRadians);
|
||||
let s = Math.sin(angleInRadians);
|
||||
|
||||
return [
|
||||
c, s, 0, 0,
|
||||
-s, c, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, 0, 0, 1,
|
||||
];
|
||||
}
|
||||
|
||||
static degToRad(d) {
|
||||
return d * Math.PI / 180;
|
||||
}
|
||||
}
|
||||
|
||||
function $(sel, s) {
|
||||
return $$(sel, s)[0];
|
||||
}
|
||||
|
||||
function $$(sel, s) {
|
||||
s = s || document;
|
||||
return s.querySelectorAll(sel);
|
||||
}
|
||||
|
||||
Node.prototype.addDelegatedEventListener = function (type, aim, cb) {
|
||||
this.addEventListener(type, (event) => {
|
||||
let target = event.target;
|
||||
if (target.matches(aim)) {
|
||||
cb(event, target);
|
||||
} else {
|
||||
let parent = target.closest(aim);
|
||||
if (parent) {
|
||||
cb(event, parent);
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
function create(name, content) {
|
||||
let d = document.createElement(name);
|
||||
if (content) {
|
||||
d.innerHTML = content;
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
function append(to, array) {
|
||||
for (let item in array) {
|
||||
to.appendChild(array[item]);
|
||||
}
|
||||
}
|
||||
class ShaderHandler {
|
||||
constructor(gl) {
|
||||
this.gl = gl;
|
||||
this.shaderNames = [];
|
||||
this.shaders = {};
|
||||
this.programs = {};
|
||||
}
|
||||
|
||||
setGL(gl) {
|
||||
this.gl = gl;
|
||||
}
|
||||
|
||||
async loadShader(name, path) {
|
||||
this.shaderNames.push(name);
|
||||
await this.load(name, path + name + ".vert", this.gl.VERTEX_SHADER);
|
||||
await this.load(name, path + name + ".frag", this.gl.FRAGMENT_SHADER);
|
||||
}
|
||||
|
||||
async load(name, url, type) {
|
||||
let realName = name + "_" + type;
|
||||
if (!this.shaders[realName]) {
|
||||
let data = await fetch(url);
|
||||
let shader = this.createShader(await data.text(), type);
|
||||
if (shader) {
|
||||
this.shaders[realName] = shader;
|
||||
}
|
||||
}
|
||||
return !!this.shaders[realName];
|
||||
}
|
||||
|
||||
getShader(name, type) {
|
||||
let realName = name + "_" + type;
|
||||
return this.shaders[realName];
|
||||
}
|
||||
|
||||
getAllShaders() {
|
||||
return this.shaderNames;
|
||||
}
|
||||
|
||||
async createProgramForEach(arr) {
|
||||
arr = arr || this.shaderNames;
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
let shader = arr[i];
|
||||
let v = await shaderHandler.createProgram(shader, [shader])
|
||||
if (!v) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
createShader(source, type) {
|
||||
let gl = this.gl;
|
||||
let shader = gl.createShader(type);
|
||||
gl.shaderSource(shader, source);
|
||||
gl.compileShader(shader);
|
||||
if (gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
||||
return shader;
|
||||
}
|
||||
console.error(gl.getShaderInfoLog(shader));
|
||||
gl.deleteShader(shader);
|
||||
return null;
|
||||
}
|
||||
|
||||
createProgram(name, shaders) {
|
||||
let gl = this.gl;
|
||||
let pro = gl.createProgram();
|
||||
for (let i = 0; i < shaders.length; i++) {
|
||||
gl.attachShader(pro, this.getShader(shaders[i], gl.VERTEX_SHADER));
|
||||
gl.attachShader(pro, this.getShader(shaders[i], gl.FRAGMENT_SHADER));
|
||||
}
|
||||
gl.linkProgram(pro);
|
||||
var success = gl.getProgramParameter(pro, gl.LINK_STATUS);
|
||||
if (success) {
|
||||
this.programs[name] = pro;
|
||||
return pro;
|
||||
}
|
||||
|
||||
console.log(gl.getProgramInfoLog(pro));
|
||||
gl.deleteProgram(pro);
|
||||
return null;
|
||||
}
|
||||
|
||||
getProgram(name) {
|
||||
return this.programs[name];
|
||||
}
|
||||
|
||||
async loadArray(list, path) {
|
||||
let self = this;
|
||||
for (const e of list) {
|
||||
await self.loadShader(e, path)
|
||||
}
|
||||
await self.createProgramForEach(list)
|
||||
}
|
||||
}
|
||||
class AudioHandler {
|
||||
async init() {
|
||||
this.audioFile = new Audio();
|
||||
}
|
||||
}
|
||||
class Player {
|
||||
async init() {
|
||||
|
||||
}
|
||||
}
|
||||
class GUI {
|
||||
init() {
|
||||
|
||||
}
|
||||
}
|
||||
class Visual {
|
||||
constructor() {
|
||||
this.data = []; //for drawing
|
||||
this.dataArray = [];
|
||||
}
|
||||
draw() {
|
||||
}
|
||||
|
||||
setup() {
|
||||
}
|
||||
}
|
||||
|
||||
class VisualDrawer {
|
||||
|
||||
}
|
||||
class Sphere extends Visual {
|
||||
draw() {
|
||||
}
|
||||
|
||||
setup() {
|
||||
}
|
||||
}
|
||||
const shaderHandler = new ShaderHandler(null),
|
||||
audioHandler = new AudioHandler(),
|
||||
gui = new GUI(),
|
||||
player = new Player();
|
||||
|
||||
async function startUP() {
|
||||
let c = document.body.querySelector('#c'),
|
||||
gl = c.getContext("webgl2");
|
||||
if (!gl) {
|
||||
alert("SORRY THE BROWSER DOESN'T SUPPORT WEBGL2");
|
||||
return false;
|
||||
}
|
||||
shaderHandler.setGL(gl)
|
||||
await shaderHandler.loadArray(["wave", "sphere"], 'shaders/');
|
||||
await audioHandler.init();
|
||||
await player.init();
|
||||
gui.init();
|
||||
}
|
||||
|
||||
startUP().then(r => {
|
||||
setTimeout(e => {
|
||||
$('.loading-screen').remove();
|
||||
}, 100)
|
||||
});
|
1
out/js/scripts.min.js
vendored
Normal file
1
out/js/scripts.min.js
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
class VTUtils{static random(t,e){let a=Math.random();if(void 0===t)return a;if(void 0===e)return t instanceof Array?t[Math.floor(a*t.length)]:a*t;if(t>e){let a=t;t=e,e=a}return a*(e-t)+t}static randomInt(t,e){return Math.floor(VTUtils.random(t,e))}static normalize(t,e,a){return(t-a)/(e-a)}static distance(t,e,a,r){let s=t-a,i=e-r;return Math.sqrt(s*s+i*i)}static map(t,e,a,r,s,i){let n=(t-e)/(a-e)*(s-r)+r;return i?r<s?this.constrain(n,r,s):this.constrain(n,s,r):n}static constrain(t,e,a){return Math.max(Math.min(t,a),e)}static hsvToRgb(t,e,a){var r,s,i,n=Math.floor(6*t),h=6*t-n,o=a*(1-e),l=a*(1-h*e),c=a*(1-(1-h)*e);switch(n%6){case 0:r=a,s=c,i=o;break;case 1:r=l,s=a,i=o;break;case 2:r=o,s=a,i=c;break;case 3:r=o,s=l,i=a;break;case 4:r=c,s=o,i=a;break;case 5:r=a,s=o,i=l}return{r:r,g:s,b:i}}static peakRGB(t){return{r:t,g:1-t,b:0}}}class VTVector{constructor(t,e,a){this.x=t||0,this.y=e||0,this.z=a||0}static createRandom(t,e,a){return t=t||1,e=e||1,a=a||0,new VTVector(VTUtils.random(-t,t),VTUtils.random(-e,e),VTUtils.random(-a,a))}mult(t){this.x*=t,this.y*=t,this.z*=t}set(t){this.x=t.x,this.y=t.y,this.z=t.z}add(t){this.x=this.x+t.x,this.y=this.y+t.y,this.z=this.z+t.z}addXYZ(t,e,a){this.x+=t,this.y+=e,this.z+=a}setXYZ(t,e,a){this.x=t||0,this.y=e||0,this.z=a||0}clone(){return new VTVector(this.x,this.y,this.z)}}class TDUtils{static multiply(t,e){let a=e[0],r=e[1],s=e[2],i=e[3],n=e[4],h=e[5],o=e[6],l=e[7],c=e[8],d=e[9],u=e[10],g=e[11],m=e[12],S=e[13],y=e[14],f=e[15],T=t[0],w=t[1],p=t[2],E=t[3],P=t[4],R=t[5],M=t[6],A=t[7],H=t[8],V=t[9],x=t[10],U=t[11],z=t[12],b=t[13],L=t[14],v=t[15],N=[];return N[0]=a*T+r*P+s*H+i*z,N[1]=a*w+r*R+s*V+i*b,N[2]=a*p+r*M+s*x+i*L,N[3]=a*E+r*A+s*U+i*v,N[4]=n*T+h*P+o*H+l*z,N[5]=n*w+h*R+o*V+l*b,N[6]=n*p+h*M+o*x+l*L,N[7]=n*E+h*A+o*U+l*v,N[8]=c*T+d*P+u*H+g*z,N[9]=c*w+d*R+u*V+g*b,N[10]=c*p+d*M+u*x+g*L,N[11]=c*E+d*A+u*U+g*v,N[12]=m*T+S*P+y*H+f*z,N[13]=m*w+S*R+y*V+f*b,N[14]=m*p+S*M+y*x+f*L,N[15]=m*E+S*A+y*U+f*v,N}static xRotation(t){let e=Math.cos(t),a=Math.sin(t);return[1,0,0,0,0,e,a,0,0,-a,e,0,0,0,0,1]}static yRotation(t){let e=Math.cos(t),a=Math.sin(t);return[e,0,-a,0,0,1,0,0,a,0,e,0,0,0,0,1]}static zRotation(t){let e=Math.cos(t),a=Math.sin(t);return[e,a,0,0,-a,e,0,0,0,0,1,0,0,0,0,1]}static degToRad(t){return t*Math.PI/180}}function $(t,e){return $$(t,e)[0]}function $$(t,e){return(e=e||document).querySelectorAll(t)}function create(t,e){let a=document.createElement(t);return e&&(a.innerHTML=e),a}function append(t,e){for(let a in e)t.appendChild(e[a])}Node.prototype.addDelegatedEventListener=function(t,e,a){this.addEventListener(t,t=>{let r=t.target;if(r.matches(e))a(t,r);else{let s=r.closest(e);s&&a(t,s)}})};class ShaderHandler{constructor(t){this.gl=t,this.shaderNames=[],this.shaders={},this.programs={}}setGL(t){this.gl=t}async loadShader(t,e){this.shaderNames.push(t),await this.load(t,e+t+".vert",this.gl.VERTEX_SHADER),await this.load(t,e+t+".frag",this.gl.FRAGMENT_SHADER)}async load(t,e,a){let r=t+"_"+a;if(!this.shaders[r]){let t=await fetch(e),s=this.createShader(await t.text(),a);s&&(this.shaders[r]=s)}return!!this.shaders[r]}getShader(t,e){let a=t+"_"+e;return this.shaders[a]}getAllShaders(){return this.shaderNames}async createProgramForEach(t){t=t||this.shaderNames;for(let e=0;e<t.length;e++){let a=t[e];if(!await shaderHandler.createProgram(a,[a]))return!1}return!0}createShader(t,e){let a=this.gl,r=a.createShader(e);return a.shaderSource(r,t),a.compileShader(r),a.getShaderParameter(r,a.COMPILE_STATUS)?r:(console.error(a.getShaderInfoLog(r)),a.deleteShader(r),null)}createProgram(t,e){let a=this.gl,r=a.createProgram();for(let t=0;t<e.length;t++)a.attachShader(r,this.getShader(e[t],a.VERTEX_SHADER)),a.attachShader(r,this.getShader(e[t],a.FRAGMENT_SHADER));return a.linkProgram(r),a.getProgramParameter(r,a.LINK_STATUS)?(this.programs[t]=r,r):(console.log(a.getProgramInfoLog(r)),a.deleteProgram(r),null)}getProgram(t){return this.programs[t]}async loadArray(t,e){let a=this;for(const r of t)await a.loadShader(r,e);await a.createProgramForEach(t)}}class AudioHandler{async init(){this.audioFile=new Audio}}class Player{async init(){}}class GUI{init(){}}class Visual{constructor(){this.data=[],this.dataArray=[]}draw(){}setup(){}}class VisualDrawer{}class Sphere extends Visual{draw(){}setup(){}}const shaderHandler=new ShaderHandler(null),audioHandler=new AudioHandler,gui=new GUI,player=new Player;async function startUP(){let t=document.body.querySelector("#c").getContext("webgl2");if(!t)return alert("SORRY THE BROWSER DOESN'T SUPPORT WEBGL2"),!1;shaderHandler.setGL(t),await shaderHandler.loadArray(["wave","sphere"],"shaders/"),await audioHandler.init(),await player.init(),gui.init()}startUP().then(t=>{setTimeout(t=>{$(".loading-screen").remove()},100)});
|
1
out/theme/style.css
Normal file
1
out/theme/style.css
Normal file
|
@ -0,0 +1 @@
|
|||
*{box-sizing:border-box}:focus{outline:0}body,html{padding:0;margin:0;overflow:hidden;font-size:16px;font-family:sans-serif;background-color:#000}div{position:fixed;color:#fff;padding:1em}.hide{display:none!important}.icon{width:1em;height:1em;vertical-align:middle;font-size:1em;shape-rendering:geometricPrecision;transition:transform .5s cubic-bezier(.22,.61,.36,1);stroke-width:5px;text-align:center;display:block}#c{width:100%;height:100%}group{display:block;padding-bottom:10px;user-select:none}group-label{display:block;border-bottom:1px solid #fff;font-size:21px;font-weight:500;user-select:none}group-input{display:flex;align-items:center;margin-top:5px;user-select:none}group-input label{padding-right:10px;user-select:none;width:150px}group-input input{flex-grow:1;user-select:none;max-width:150px}group-input button{border:1px solid #dcdcdc;background-color:transparent;color:#fff;margin-left:5px}.closed{transform:translateX(-350px);transition:all .5s}.top-menu-left{display:flex}.top-menu-left div{position:relative}.loading-screen{z-index:100;background-color:#000;width:100vw;height:100vh;display:flex;align-items:center;justify-content:center;flex-direction:column}.loading-screen span{font-family:monospace;font-size:4vw;z-index:2}.loading-screen loader{position:absolute;top:calc(6vw + 10px);left:0;right:0;bottom:0;margin:auto;display:block;width:30vw;height:6px;transform:scaleX(0);transform-origin:left;background-color:#006ea8;animation:loadingBar 2s infinite}.loading-screen loader.delay{background-color:rgba(0,110,168,.24);filter:blur(1px);animation-delay:.05s}@keyframes loadingBar{0%,100%{transform:scaleX(0) scaleY(0)}50%{transform:scaleX(1) scaleY(1);transform-origin:left}100%,51%{transform-origin:right}}input[type=range]{width:100%}input[type=range]:focus{outline:0}input[type=range]:focus::-webkit-slider-runnable-track{background:#545454}input[type=range]:focus::-ms-fill-lower{background:#424242}input[type=range]:focus::-ms-fill-upper{background:#545454}input[type=range]::-webkit-slider-runnable-track{width:100%;height:25.6px;cursor:pointer;box-shadow:1px 1px 1px #000,0 0 1px #0d0d0d;background:#424242;border-radius:0;border:0 solid #010101}input[type=range]::-webkit-slider-thumb{height:25px;width:15px;border-radius:0;cursor:pointer;margin-top:.3px}switch input{position:absolute;appearance:none;opacity:0}switch input:checked+label:after{transform:translateX(20px)}switch label{display:block;border-radius:10px;width:40px;height:20px;background-color:#dcdcdc;position:relative;cursor:pointer;padding:0}switch label:after{content:'';background-color:#ff3232;position:absolute;top:2px;left:2px;height:16px;width:16px;border-radius:10px;transition:.5s}input[type=file]{position:fixed;left:-100000vw;height:1px;width:1px}.controls{right:0;display:flex}.controls button,.menu-icon{background-color:rgba(33,33,33,.6);border:none;font-size:1.4em;border-top:4px solid #089bec;padding:1.5rem;cursor:pointer;color:#fff;transition:.5s}.controls button.active,.menu-icon.active{border-color:#ff066a}.controls button:hover,.menu-icon:hover{background-color:rgba(21,21,21,.7);border-color:#aaef22}
|
134
raw/gui/sphere.json
Normal file
134
raw/gui/sphere.json
Normal file
|
@ -0,0 +1,134 @@
|
|||
[
|
||||
{
|
||||
"group": "rotation",
|
||||
"name": [
|
||||
"X",
|
||||
"Y",
|
||||
"Z"
|
||||
],
|
||||
"props": [
|
||||
0,
|
||||
1,
|
||||
2
|
||||
],
|
||||
"type": "slider",
|
||||
"max": 360,
|
||||
"min": 0
|
||||
},
|
||||
{
|
||||
"group": "rotation",
|
||||
"name": [
|
||||
"X-Inc",
|
||||
"Y-Inc",
|
||||
"Z-Inc"
|
||||
],
|
||||
"props": [
|
||||
0,
|
||||
1,
|
||||
2
|
||||
],
|
||||
"type": "slider",
|
||||
"max": 1,
|
||||
"min": 0,
|
||||
"stepSize": 0.01
|
||||
},
|
||||
{
|
||||
"group": "rotation",
|
||||
"name": "by-Beat",
|
||||
"type": "checkbox",
|
||||
"value": true,
|
||||
"tooltip": "Rotate the Sphere based by Beat <br> Low-Freq = Y, Mid-Freq = Z, High-Freq = X"
|
||||
},
|
||||
{
|
||||
"group": "color",
|
||||
"name": [
|
||||
"R",
|
||||
"G",
|
||||
"B"
|
||||
],
|
||||
"props": [
|
||||
"r",
|
||||
"g",
|
||||
"b"
|
||||
],
|
||||
"type": "slider",
|
||||
"max": 255,
|
||||
"min": 0
|
||||
},
|
||||
{
|
||||
"group": "light",
|
||||
"name": [
|
||||
"X",
|
||||
"Y",
|
||||
"Z"
|
||||
],
|
||||
"props": [
|
||||
0,
|
||||
1,
|
||||
2
|
||||
],
|
||||
"type": "slider",
|
||||
"max": 1,
|
||||
"min": -1,
|
||||
"value": 0,
|
||||
"stepSize": 0.1
|
||||
},
|
||||
{
|
||||
"group": "light",
|
||||
"name": "Light",
|
||||
"type": "slider",
|
||||
"max": 1,
|
||||
"min": 0,
|
||||
"stepSize": 0.05
|
||||
},
|
||||
{
|
||||
"group": "color",
|
||||
"name": "by-Beat",
|
||||
"type": "checkbox",
|
||||
"value": true,
|
||||
"tooltip": "Draw The Color Strength based on the Low-Freq"
|
||||
},
|
||||
{
|
||||
"group": "draw",
|
||||
"name": "DrawMode",
|
||||
"type": "slider",
|
||||
"max": 6,
|
||||
"min": 0
|
||||
},
|
||||
{
|
||||
"group": "draw",
|
||||
"name": "Form",
|
||||
"type": "slider",
|
||||
"max": 4,
|
||||
"min": 0
|
||||
},
|
||||
{
|
||||
"group": "draw",
|
||||
"name": "Radius",
|
||||
"type": "slider",
|
||||
"max": 1500,
|
||||
"min": 20
|
||||
},
|
||||
{
|
||||
"group": "draw",
|
||||
"name": "Total",
|
||||
"type": "slider",
|
||||
"max": 200,
|
||||
"min": 20
|
||||
},
|
||||
{
|
||||
"group": "draw",
|
||||
"name": "PointSize",
|
||||
"type": "slider",
|
||||
"max": 10,
|
||||
"min": 1,
|
||||
"stepSize": 0.2
|
||||
},
|
||||
{
|
||||
"group": "draw",
|
||||
"name": "Dirty",
|
||||
"type": "checkbox",
|
||||
"value": false,
|
||||
"tooltip": "Full Draw or with less Points"
|
||||
}
|
||||
]
|
0
raw/icons/.gitkeep
Normal file
0
raw/icons/.gitkeep
Normal file
24
raw/javascript/app.js
Normal file
24
raw/javascript/app.js
Normal file
|
@ -0,0 +1,24 @@
|
|||
const shaderHandler = new ShaderHandler(null),
|
||||
audioHandler = new AudioHandler(),
|
||||
gui = new GUI(),
|
||||
player = new Player();
|
||||
|
||||
async function startUP() {
|
||||
let c = document.body.querySelector('#c'),
|
||||
gl = c.getContext("webgl2");
|
||||
if (!gl) {
|
||||
alert("SORRY THE BROWSER DOESN'T SUPPORT WEBGL2");
|
||||
return false;
|
||||
}
|
||||
shaderHandler.setGL(gl)
|
||||
await shaderHandler.loadArray(["wave", "sphere"], 'shaders/');
|
||||
await audioHandler.init();
|
||||
await player.init();
|
||||
gui.init();
|
||||
}
|
||||
|
||||
startUP().then(r => {
|
||||
setTimeout(e => {
|
||||
$('.loading-screen').remove();
|
||||
}, 100)
|
||||
});
|
5
raw/javascript/audio.js
Normal file
5
raw/javascript/audio.js
Normal file
|
@ -0,0 +1,5 @@
|
|||
class AudioHandler {
|
||||
async init() {
|
||||
this.audioFile = new Audio();
|
||||
}
|
||||
}
|
5
raw/javascript/gui.js
Normal file
5
raw/javascript/gui.js
Normal file
|
@ -0,0 +1,5 @@
|
|||
class GUI {
|
||||
init() {
|
||||
|
||||
}
|
||||
}
|
95
raw/javascript/handler.js
Normal file
95
raw/javascript/handler.js
Normal file
|
@ -0,0 +1,95 @@
|
|||
class ShaderHandler {
|
||||
constructor(gl) {
|
||||
this.gl = gl;
|
||||
this.shaderNames = [];
|
||||
this.shaders = {};
|
||||
this.programs = {};
|
||||
}
|
||||
|
||||
setGL(gl) {
|
||||
this.gl = gl;
|
||||
}
|
||||
|
||||
async loadShader(name, path) {
|
||||
this.shaderNames.push(name);
|
||||
await this.load(name, path + name + ".vert", this.gl.VERTEX_SHADER);
|
||||
await this.load(name, path + name + ".frag", this.gl.FRAGMENT_SHADER);
|
||||
}
|
||||
|
||||
async load(name, url, type) {
|
||||
let realName = name + "_" + type;
|
||||
if (!this.shaders[realName]) {
|
||||
let data = await fetch(url);
|
||||
let shader = this.createShader(await data.text(), type);
|
||||
if (shader) {
|
||||
this.shaders[realName] = shader;
|
||||
}
|
||||
}
|
||||
return !!this.shaders[realName];
|
||||
}
|
||||
|
||||
getShader(name, type) {
|
||||
let realName = name + "_" + type;
|
||||
return this.shaders[realName];
|
||||
}
|
||||
|
||||
getAllShaders() {
|
||||
return this.shaderNames;
|
||||
}
|
||||
|
||||
async createProgramForEach(arr) {
|
||||
arr = arr || this.shaderNames;
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
let shader = arr[i];
|
||||
let v = await shaderHandler.createProgram(shader, [shader])
|
||||
if (!v) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
createShader(source, type) {
|
||||
let gl = this.gl;
|
||||
let shader = gl.createShader(type);
|
||||
gl.shaderSource(shader, source);
|
||||
gl.compileShader(shader);
|
||||
if (gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
||||
return shader;
|
||||
}
|
||||
console.error(gl.getShaderInfoLog(shader));
|
||||
gl.deleteShader(shader);
|
||||
return null;
|
||||
}
|
||||
|
||||
createProgram(name, shaders) {
|
||||
let gl = this.gl;
|
||||
let pro = gl.createProgram();
|
||||
for (let i = 0; i < shaders.length; i++) {
|
||||
gl.attachShader(pro, this.getShader(shaders[i], gl.VERTEX_SHADER));
|
||||
gl.attachShader(pro, this.getShader(shaders[i], gl.FRAGMENT_SHADER));
|
||||
}
|
||||
gl.linkProgram(pro);
|
||||
var success = gl.getProgramParameter(pro, gl.LINK_STATUS);
|
||||
if (success) {
|
||||
this.programs[name] = pro;
|
||||
return pro;
|
||||
}
|
||||
|
||||
console.log(gl.getProgramInfoLog(pro));
|
||||
gl.deleteProgram(pro);
|
||||
return null;
|
||||
}
|
||||
|
||||
getProgram(name) {
|
||||
return this.programs[name];
|
||||
}
|
||||
|
||||
async loadArray(list, path) {
|
||||
let self = this;
|
||||
for (const e of list) {
|
||||
await self.loadShader(e, path)
|
||||
}
|
||||
await self.createProgramForEach(list)
|
||||
}
|
||||
}
|
5
raw/javascript/player.js
Normal file
5
raw/javascript/player.js
Normal file
|
@ -0,0 +1,5 @@
|
|||
class Player {
|
||||
async init() {
|
||||
|
||||
}
|
||||
}
|
275
raw/javascript/utils.js
Normal file
275
raw/javascript/utils.js
Normal file
|
@ -0,0 +1,275 @@
|
|||
class VTUtils {
|
||||
static random(min, max) {
|
||||
let rand = Math.random();
|
||||
if (typeof min === 'undefined') {
|
||||
return rand;
|
||||
} else if (typeof max === 'undefined') {
|
||||
if (min instanceof Array) {
|
||||
return min[Math.floor(rand * min.length)];
|
||||
} else {
|
||||
return rand * min;
|
||||
}
|
||||
} else {
|
||||
if (min > max) {
|
||||
let tmp = min;
|
||||
min = max;
|
||||
max = tmp;
|
||||
}
|
||||
return rand * (max - min) + min;
|
||||
}
|
||||
};
|
||||
|
||||
static randomInt(min, max) {
|
||||
return Math.floor(VTUtils.random(min, max));
|
||||
}
|
||||
|
||||
static normalize(val, max, min) {
|
||||
return (val - min) / (max - min);
|
||||
};
|
||||
|
||||
static distance(x, y, x2, y2) {
|
||||
let a = x - x2;
|
||||
let b = y - y2;
|
||||
|
||||
return Math.sqrt(a * a + b * b);
|
||||
}
|
||||
|
||||
static map(n, start1, stop1, start2, stop2, withinBounds) {
|
||||
let newVal = (n - start1) / (stop1 - start1) * (stop2 - start2) + start2;
|
||||
if (!withinBounds) {
|
||||
return newVal;
|
||||
}
|
||||
if (start2 < stop2) {
|
||||
return this.constrain(newVal, start2, stop2);
|
||||
} else {
|
||||
return this.constrain(newVal, stop2, start2);
|
||||
}
|
||||
};
|
||||
|
||||
static constrain(n, low, high) {
|
||||
return Math.max(Math.min(n, high), low);
|
||||
}
|
||||
|
||||
static hsvToRgb(h, s, v) {
|
||||
var r, g, b;
|
||||
|
||||
var i = Math.floor(h * 6);
|
||||
var f = h * 6 - i;
|
||||
var p = v * (1 - s);
|
||||
var q = v * (1 - f * s);
|
||||
var t = v * (1 - (1 - f) * s);
|
||||
|
||||
switch (i % 6) {
|
||||
case 0:
|
||||
r = v, g = t, b = p;
|
||||
break;
|
||||
case 1:
|
||||
r = q, g = v, b = p;
|
||||
break;
|
||||
case 2:
|
||||
r = p, g = v, b = t;
|
||||
break;
|
||||
case 3:
|
||||
r = p, g = q, b = v;
|
||||
break;
|
||||
case 4:
|
||||
r = t, g = p, b = v;
|
||||
break;
|
||||
case 5:
|
||||
r = v, g = p, b = q;
|
||||
break;
|
||||
}
|
||||
|
||||
return {r: r, g: g, b: b};
|
||||
}
|
||||
|
||||
static peakRGB(peak) {
|
||||
return {
|
||||
r: peak,
|
||||
g: 1 - peak,
|
||||
b: 0
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class VTVector {
|
||||
constructor(x, y, z) {
|
||||
this.x = x || 0;
|
||||
this.y = y || 0;
|
||||
this.z = z || 0;
|
||||
}
|
||||
|
||||
//helper
|
||||
static createRandom(x, y, z) {
|
||||
x = x || 1;
|
||||
y = y || 1;
|
||||
z = z || 0;
|
||||
return new VTVector(VTUtils.random(-x, x), VTUtils.random(-y, y), VTUtils.random(-z, z));
|
||||
}
|
||||
|
||||
mult(times) {
|
||||
this.x *= times;
|
||||
this.y *= times;
|
||||
this.z *= times;
|
||||
}
|
||||
|
||||
set(vector) {
|
||||
this.x = vector.x;
|
||||
this.y = vector.y;
|
||||
this.z = vector.z;
|
||||
}
|
||||
|
||||
add(vector) {
|
||||
this.x = this.x + vector.x;
|
||||
this.y = this.y + vector.y;
|
||||
this.z = this.z + vector.z;
|
||||
}
|
||||
|
||||
addXYZ(x, y, z) {
|
||||
this.x += x;
|
||||
this.y += y;
|
||||
this.z += z;
|
||||
}
|
||||
|
||||
setXYZ(x, y, z) {
|
||||
this.x = x || 0;
|
||||
this.y = y || 0;
|
||||
this.z = z || 0;
|
||||
}
|
||||
|
||||
clone() {
|
||||
return new VTVector(this.x, this.y, this.z);
|
||||
}
|
||||
}
|
||||
|
||||
class TDUtils {
|
||||
static multiply(a, b) {
|
||||
let b00 = b[0 * 4 + 0];
|
||||
let b01 = b[0 * 4 + 1];
|
||||
let b02 = b[0 * 4 + 2];
|
||||
let b03 = b[0 * 4 + 3];
|
||||
let b10 = b[1 * 4 + 0];
|
||||
let b11 = b[1 * 4 + 1];
|
||||
let b12 = b[1 * 4 + 2];
|
||||
let b13 = b[1 * 4 + 3];
|
||||
let b20 = b[2 * 4 + 0];
|
||||
let b21 = b[2 * 4 + 1];
|
||||
let b22 = b[2 * 4 + 2];
|
||||
let b23 = b[2 * 4 + 3];
|
||||
let b30 = b[3 * 4 + 0];
|
||||
let b31 = b[3 * 4 + 1];
|
||||
let b32 = b[3 * 4 + 2];
|
||||
let b33 = b[3 * 4 + 3];
|
||||
let a00 = a[0 * 4 + 0];
|
||||
let a01 = a[0 * 4 + 1];
|
||||
let a02 = a[0 * 4 + 2];
|
||||
let a03 = a[0 * 4 + 3];
|
||||
let a10 = a[1 * 4 + 0];
|
||||
let a11 = a[1 * 4 + 1];
|
||||
let a12 = a[1 * 4 + 2];
|
||||
let a13 = a[1 * 4 + 3];
|
||||
let a20 = a[2 * 4 + 0];
|
||||
let a21 = a[2 * 4 + 1];
|
||||
let a22 = a[2 * 4 + 2];
|
||||
let a23 = a[2 * 4 + 3];
|
||||
let a30 = a[3 * 4 + 0];
|
||||
let a31 = a[3 * 4 + 1];
|
||||
let a32 = a[3 * 4 + 2];
|
||||
let a33 = a[3 * 4 + 3];
|
||||
let dst = [];
|
||||
dst[0] = b00 * a00 + b01 * a10 + b02 * a20 + b03 * a30;
|
||||
dst[1] = b00 * a01 + b01 * a11 + b02 * a21 + b03 * a31;
|
||||
dst[2] = b00 * a02 + b01 * a12 + b02 * a22 + b03 * a32;
|
||||
dst[3] = b00 * a03 + b01 * a13 + b02 * a23 + b03 * a33;
|
||||
dst[4] = b10 * a00 + b11 * a10 + b12 * a20 + b13 * a30;
|
||||
dst[5] = b10 * a01 + b11 * a11 + b12 * a21 + b13 * a31;
|
||||
dst[6] = b10 * a02 + b11 * a12 + b12 * a22 + b13 * a32;
|
||||
dst[7] = b10 * a03 + b11 * a13 + b12 * a23 + b13 * a33;
|
||||
dst[8] = b20 * a00 + b21 * a10 + b22 * a20 + b23 * a30;
|
||||
dst[9] = b20 * a01 + b21 * a11 + b22 * a21 + b23 * a31;
|
||||
dst[10] = b20 * a02 + b21 * a12 + b22 * a22 + b23 * a32;
|
||||
dst[11] = b20 * a03 + b21 * a13 + b22 * a23 + b23 * a33;
|
||||
dst[12] = b30 * a00 + b31 * a10 + b32 * a20 + b33 * a30;
|
||||
dst[13] = b30 * a01 + b31 * a11 + b32 * a21 + b33 * a31;
|
||||
dst[14] = b30 * a02 + b31 * a12 + b32 * a22 + b33 * a32;
|
||||
dst[15] = b30 * a03 + b31 * a13 + b32 * a23 + b33 * a33;
|
||||
return dst;
|
||||
}
|
||||
|
||||
static xRotation(angleInRadians) {
|
||||
let c = Math.cos(angleInRadians);
|
||||
let s = Math.sin(angleInRadians);
|
||||
|
||||
return [
|
||||
1, 0, 0, 0,
|
||||
0, c, s, 0,
|
||||
0, -s, c, 0,
|
||||
0, 0, 0, 1,
|
||||
];
|
||||
}
|
||||
|
||||
static yRotation(angleInRadians) {
|
||||
let c = Math.cos(angleInRadians);
|
||||
let s = Math.sin(angleInRadians);
|
||||
|
||||
return [
|
||||
c, 0, -s, 0,
|
||||
0, 1, 0, 0,
|
||||
s, 0, c, 0,
|
||||
0, 0, 0, 1,
|
||||
];
|
||||
}
|
||||
|
||||
static zRotation(angleInRadians) {
|
||||
let c = Math.cos(angleInRadians);
|
||||
let s = Math.sin(angleInRadians);
|
||||
|
||||
return [
|
||||
c, s, 0, 0,
|
||||
-s, c, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, 0, 0, 1,
|
||||
];
|
||||
}
|
||||
|
||||
static degToRad(d) {
|
||||
return d * Math.PI / 180;
|
||||
}
|
||||
}
|
||||
|
||||
function $(sel, s) {
|
||||
return $$(sel, s)[0];
|
||||
}
|
||||
|
||||
function $$(sel, s) {
|
||||
s = s || document;
|
||||
return s.querySelectorAll(sel);
|
||||
}
|
||||
|
||||
Node.prototype.addDelegatedEventListener = function (type, aim, cb) {
|
||||
this.addEventListener(type, (event) => {
|
||||
let target = event.target;
|
||||
if (target.matches(aim)) {
|
||||
cb(event, target);
|
||||
} else {
|
||||
let parent = target.closest(aim);
|
||||
if (parent) {
|
||||
cb(event, parent);
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
function create(name, content) {
|
||||
let d = document.createElement(name);
|
||||
if (content) {
|
||||
d.innerHTML = content;
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
function append(to, array) {
|
||||
for (let item in array) {
|
||||
to.appendChild(array[item]);
|
||||
}
|
||||
}
|
15
raw/javascript/visual.js
Normal file
15
raw/javascript/visual.js
Normal file
|
@ -0,0 +1,15 @@
|
|||
class Visual {
|
||||
constructor() {
|
||||
this.data = []; //for drawing
|
||||
this.dataArray = [];
|
||||
}
|
||||
draw() {
|
||||
}
|
||||
|
||||
setup() {
|
||||
}
|
||||
}
|
||||
|
||||
class VisualDrawer {
|
||||
|
||||
}
|
7
raw/javascript/visuals/sphere.js
Normal file
7
raw/javascript/visuals/sphere.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
class Sphere extends Visual {
|
||||
draw() {
|
||||
}
|
||||
|
||||
setup() {
|
||||
}
|
||||
}
|
24
raw/scss/_controls.scss
Normal file
24
raw/scss/_controls.scss
Normal file
|
@ -0,0 +1,24 @@
|
|||
.controls {
|
||||
right: 0;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.controls button, .menu-icon {
|
||||
background-color: rgba(33, 33, 33, .6);
|
||||
border: none;
|
||||
font-size: 1.4em;
|
||||
border-top: 4px solid #089bec;
|
||||
padding: 1.5rem;
|
||||
cursor: pointer;
|
||||
color: #fff;
|
||||
transition: .5s;
|
||||
|
||||
&.active {
|
||||
border-color: #ff066a;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(21, 21, 21, .7);
|
||||
border-color: #aaef22;
|
||||
}
|
||||
}
|
108
raw/scss/_gui.scss
Normal file
108
raw/scss/_gui.scss
Normal file
|
@ -0,0 +1,108 @@
|
|||
#c {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
group {
|
||||
display: block;
|
||||
padding-bottom: 10px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
group-label {
|
||||
display: block;
|
||||
border-bottom: 1px solid #fff;
|
||||
font-size: 21px;
|
||||
font-weight: 500;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
group-input {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 5px;
|
||||
user-select: none;
|
||||
|
||||
label {
|
||||
padding-right: 10px;
|
||||
user-select: none;
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
input {
|
||||
flex-grow: 1;
|
||||
user-select: none;
|
||||
max-width: 150px;
|
||||
}
|
||||
|
||||
button {
|
||||
border: 1px solid #dcdcdc;
|
||||
background-color: transparent;
|
||||
color: #fff;
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.closed {
|
||||
transform: translateX(-350px);
|
||||
transition: all .5s;
|
||||
}
|
||||
|
||||
.top-menu-left {
|
||||
display: flex;
|
||||
div {
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
.loading-screen {
|
||||
z-index: 100;
|
||||
background-color: #000;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
|
||||
span {
|
||||
font-family: monospace;
|
||||
font-size: 4vw;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
loader {
|
||||
position: absolute;
|
||||
top: calc(6vw + 10px);
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
margin: auto;
|
||||
display: block;
|
||||
width: 30vw;
|
||||
height: 6px;
|
||||
transform: scaleX(0);
|
||||
transform-origin: left;
|
||||
background-color: #006ea8;
|
||||
animation: loadingBar 2s infinite;
|
||||
|
||||
&.delay {
|
||||
background-color: rgba(0, 110, 168, 0.24);
|
||||
filter: blur(1px);
|
||||
animation-delay: .05s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes loadingBar {
|
||||
0%, 100% {
|
||||
transform: scaleX(0) scaleY(0);
|
||||
}
|
||||
50% {
|
||||
transform: scaleX(1) scaleY(1);
|
||||
transform-origin: left;
|
||||
}
|
||||
51%, 100% {
|
||||
transform-origin: right;
|
||||
}
|
||||
}
|
79
raw/scss/_input.scss
Normal file
79
raw/scss/_input.scss
Normal file
|
@ -0,0 +1,79 @@
|
|||
input[type=range] {
|
||||
width: 100%;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
&:focus::-webkit-slider-runnable-track {
|
||||
background: #545454;
|
||||
}
|
||||
|
||||
&:focus::-ms-fill-lower {
|
||||
background: #424242;
|
||||
}
|
||||
|
||||
&:focus::-ms-fill-upper {
|
||||
background: #545454;
|
||||
}
|
||||
}
|
||||
|
||||
input[type=range]::-webkit-slider-runnable-track {
|
||||
width: 100%;
|
||||
height: 25.6px;
|
||||
cursor: pointer;
|
||||
box-shadow: 1px 1px 1px #000, 0 0 1px #0d0d0d;
|
||||
background: #424242;
|
||||
border-radius: 0;
|
||||
border: 0 solid #010101;
|
||||
}
|
||||
|
||||
input[type=range]::-webkit-slider-thumb {
|
||||
height: 25px;
|
||||
width: 15px;
|
||||
border-radius: 0;
|
||||
cursor: pointer;
|
||||
margin-top: 0.3px;
|
||||
}
|
||||
|
||||
switch {
|
||||
input {
|
||||
position: absolute;
|
||||
appearance: none;
|
||||
opacity: 0;
|
||||
|
||||
&:checked + label:after {
|
||||
transform: translateX(20px);
|
||||
}
|
||||
}
|
||||
|
||||
label {
|
||||
display: block;
|
||||
border-radius: 10px;
|
||||
width: 40px;
|
||||
height: 20px;
|
||||
background-color: #dcdcdc;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
|
||||
&:after {
|
||||
content: '';
|
||||
background-color: #ff3232;
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
left: 2px;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
border-radius: 10px;
|
||||
transition: .5s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
input[type="file"] {
|
||||
position: fixed;
|
||||
left: -100000vw;
|
||||
height: 1px;
|
||||
width: 1px;
|
||||
}
|
43
raw/scss/style.scss
Normal file
43
raw/scss/style.scss
Normal file
|
@ -0,0 +1,43 @@
|
|||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
*:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
html, body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
font-size: 16px;
|
||||
font-family: sans-serif;
|
||||
background-color: #000000;
|
||||
}
|
||||
|
||||
div {
|
||||
position: fixed;
|
||||
color: #fff;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
.hide {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.icon {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
vertical-align: middle;
|
||||
font-size: 1em;
|
||||
shape-rendering: geometricPrecision;
|
||||
transition: transform .5s cubic-bezier(.22, .61, .36, 1);
|
||||
stroke-width: 5px;
|
||||
text-align: center;
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
@import "gui";
|
||||
@import "input";
|
||||
@import "controls";
|
|
@ -3,17 +3,17 @@
|
|||
// fragment shaders don't have a default precision so we need
|
||||
// to pick one. mediump is a good default. It means "medium precision"
|
||||
precision highp float;
|
||||
|
||||
in vec4 fragNormal;
|
||||
in vec3 v_surfaceToLight;
|
||||
|
||||
uniform vec4 u_color;
|
||||
uniform vec3 u_light;
|
||||
uniform vec3 u_lightPos;
|
||||
|
||||
out vec4 outColor;
|
||||
|
||||
void main() {
|
||||
vec3 surfaceToLightDirection = normalize(v_surfaceToLight);
|
||||
float light = max(dot(fragNormal.xyz, normalize(v_surfaceToLight).xyz), u_light.x);
|
||||
outColor = u_color;
|
||||
float light = 1.0;
|
||||
//outColor.rgb *= surfaceToLightDirection;
|
||||
outColor.rgb *= light;
|
||||
}
|
|
@ -1,12 +1,11 @@
|
|||
#version 300 es
|
||||
|
||||
in vec4 a_position;
|
||||
uniform mat4 u_world;
|
||||
uniform mat4 u_matrix;
|
||||
uniform vec3 u_lightPos;
|
||||
uniform vec3 u_light;
|
||||
uniform float u_pointSize;
|
||||
|
||||
out vec4 fragNormal;
|
||||
out vec3 v_surfaceToLight;
|
||||
|
||||
void main() {
|
||||
|
@ -14,8 +13,7 @@ void main() {
|
|||
vec4 pos = a_position * u_matrix;
|
||||
gl_Position = pos;
|
||||
gl_PointSize = u_pointSize;
|
||||
|
||||
vec3 surfaceWorldPosition = (u_world * pos).xyz;
|
||||
|
||||
fragNormal = normalize(pos);
|
||||
vec3 surfaceWorldPosition = (u_matrix * pos).xyz;
|
||||
v_surfaceToLight = u_lightPos - surfaceWorldPosition;
|
||||
}
|
215
style.css
215
style.css
|
@ -1,215 +0,0 @@
|
|||
html, body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
font-size: 16px;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
div {
|
||||
position: fixed;
|
||||
color: #fff;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
#c {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.settings-icon {
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
font-size: 1.5em;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.settings-icon:hover {
|
||||
color: #0199ff;
|
||||
}
|
||||
|
||||
.off-can {
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 300px;
|
||||
background-color: rgba(33, 33, 33, 0.6);
|
||||
height: 100vh;
|
||||
transition: all .5s;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
group {
|
||||
display: block;
|
||||
padding-bottom: 10px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
group-label {
|
||||
display: block;
|
||||
border-bottom: 1px solid #ffffff;
|
||||
font-size: 21px;
|
||||
font-weight: 500;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
group-input {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 5px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
group-input label {
|
||||
padding-right: 10px;
|
||||
user-select: none;
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
|
||||
group-input input {
|
||||
flex-grow: 1;
|
||||
user-select: none;
|
||||
max-width: 150px;
|
||||
}
|
||||
|
||||
group-input button {
|
||||
border: 1px solid #dcdcdc;
|
||||
background-color: transparent;
|
||||
color: #fff;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.closed {
|
||||
transform: translateX(-350px);
|
||||
transition: all .5s;
|
||||
}
|
||||
|
||||
input[type=range] {
|
||||
-webkit-appearance: none;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
input[type=range]:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
input[type=range]::-webkit-slider-runnable-track {
|
||||
width: 100%;
|
||||
height: 25.6px;
|
||||
cursor: pointer;
|
||||
box-shadow: 1px 1px 1px #000000, 0 0 1px #0d0d0d;
|
||||
background: #424242;
|
||||
border-radius: 0;
|
||||
border: 0 solid #010101;
|
||||
}
|
||||
|
||||
input[type=range]::-webkit-slider-thumb {
|
||||
box-shadow: 0 0 0 #470000, 0 0 0 #610000;
|
||||
border: 0 solid #ff0000;
|
||||
height: 25px;
|
||||
width: 15px;
|
||||
border-radius: 0;
|
||||
background: #a8c64e;
|
||||
cursor: pointer;
|
||||
-webkit-appearance: none;
|
||||
margin-top: 0.3px;
|
||||
}
|
||||
|
||||
input[type=range]:focus::-webkit-slider-runnable-track {
|
||||
background: #545454;
|
||||
}
|
||||
|
||||
input[type=range]::-moz-range-track {
|
||||
width: 100%;
|
||||
height: 25.6px;
|
||||
cursor: pointer;
|
||||
box-shadow: 1px 1px 1px #000000, 0 0 1px #0d0d0d;
|
||||
background: #424242;
|
||||
border-radius: 0;
|
||||
border: 0 solid #010101;
|
||||
}
|
||||
|
||||
input[type=range]::-moz-range-thumb {
|
||||
box-shadow: 0 0 0 #470000, 0 0 0 #610000;
|
||||
border: 0 solid #ff0000;
|
||||
height: 25px;
|
||||
width: 15px;
|
||||
border-radius: 0;
|
||||
background: #a8c64e;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
input[type=range]::-ms-track {
|
||||
width: 100%;
|
||||
height: 25.6px;
|
||||
cursor: pointer;
|
||||
background: transparent;
|
||||
border-color: transparent;
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
input[type=range]::-ms-fill-lower {
|
||||
background: #303030;
|
||||
border: 0 solid #010101;
|
||||
border-radius: 0;
|
||||
box-shadow: 1px 1px 1px #000000, 0 0 1px #0d0d0d;
|
||||
}
|
||||
|
||||
input[type=range]::-ms-fill-upper {
|
||||
background: #424242;
|
||||
border: 0 solid #010101;
|
||||
border-radius: 0;
|
||||
box-shadow: 1px 1px 1px #000000, 0 0 1px #0d0d0d;
|
||||
}
|
||||
|
||||
input[type=range]::-ms-thumb {
|
||||
box-shadow: 0 0 0 #470000, 0 0 0 #610000;
|
||||
border: 0 solid #ff0000;
|
||||
width: 15px;
|
||||
border-radius: 0;
|
||||
background: #a8c64e;
|
||||
cursor: pointer;
|
||||
height: 25px;
|
||||
}
|
||||
|
||||
input[type=range]:focus::-ms-fill-lower {
|
||||
background: #424242;
|
||||
}
|
||||
|
||||
input[type=range]:focus::-ms-fill-upper {
|
||||
background: #545454;
|
||||
}
|
||||
|
||||
switch input {
|
||||
position: absolute;
|
||||
appearance: none;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
switch label {
|
||||
display: block;
|
||||
border-radius: 10px;
|
||||
width: 40px;
|
||||
height: 20px;
|
||||
background-color: #dcdcdc;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
switch label:after {
|
||||
content: '';
|
||||
background-color: #ff3232;
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
left: 2px;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
border-radius: 10px;
|
||||
transition: .5s;
|
||||
}
|
||||
|
||||
switch input:checked + label:after {
|
||||
transform: translateX(20px);
|
||||
}
|
||||
|
Loading…
Reference in a new issue