unnecessary bullshit
This commit is contained in:
parent
fec10a82f6
commit
e4dcd46478
|
@ -0,0 +1,444 @@
|
||||||
|
/* https://github.com/mrdoob/glsl-sandbox */
|
||||||
|
|
||||||
|
if (!window.requestAnimationFrame) {
|
||||||
|
|
||||||
|
window.requestAnimationFrame = (function () {
|
||||||
|
|
||||||
|
return window.webkitRequestAnimationFrame ||
|
||||||
|
window.mozRequestAnimationFrame ||
|
||||||
|
window.oRequestAnimationFrame ||
|
||||||
|
window.msRequestAnimationFrame ||
|
||||||
|
function (callback, element) {
|
||||||
|
|
||||||
|
window.setTimeout(callback, 1000 / 60);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get older browsers safely through init code, so users can read the
|
||||||
|
// message about how to download newer browsers.
|
||||||
|
if (!Date.now) {
|
||||||
|
Date.now = function () {
|
||||||
|
return +new Date();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var quality = 1, quality_levels = [0.5, 1, 2, 4, 8];
|
||||||
|
var toolbar, compileButton, fullscreenButton, compileTimer, errorLines = [];
|
||||||
|
var canvas, gl, buffer, currentProgram, vertexPosition, screenVertexPosition,
|
||||||
|
parameters = { startTime: Date.now(), time: 0, mouseX: 0.5, mouseY: 0.5, screenWidth: 0, screenHeight: 0 },
|
||||||
|
surface = { centerX: 0, centerY: 0, width: 1, height: 1, isPanning: false, isZooming: false, lastX: 0, lastY: 0 },
|
||||||
|
frontTarget, backTarget, screenProgram, getWebGL, resizer = {}, compileOnChangeCode = true;
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
|
||||||
|
console.log('initializing...');
|
||||||
|
|
||||||
|
if (!document.addEventListener) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas = document.createElement('canvas');
|
||||||
|
document.body.appendChild(canvas);
|
||||||
|
|
||||||
|
// Initialise WebGL
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
gl = canvas.getContext('experimental-webgl', { preserveDrawingBuffer: true });
|
||||||
|
|
||||||
|
} catch (error) { }
|
||||||
|
|
||||||
|
if (gl) {
|
||||||
|
|
||||||
|
// enable dFdx, dFdy, fwidth
|
||||||
|
gl.getExtension('OES_standard_derivatives');
|
||||||
|
|
||||||
|
// Create vertex buffer (2 triangles)
|
||||||
|
|
||||||
|
buffer = gl.createBuffer();
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
||||||
|
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([- 1.0, - 1.0, 1.0, - 1.0, - 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, - 1.0, 1.0]), gl.STATIC_DRAW);
|
||||||
|
|
||||||
|
// Create surface buffer (coordinates at screen corners)
|
||||||
|
|
||||||
|
surface.buffer = gl.createBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
var clientXLast, clientYLast;
|
||||||
|
|
||||||
|
document.addEventListener('mousemove', function (event) {
|
||||||
|
|
||||||
|
var clientX = event.clientX;
|
||||||
|
var clientY = event.clientY;
|
||||||
|
|
||||||
|
if (clientXLast == clientX && clientYLast == clientY)
|
||||||
|
return;
|
||||||
|
|
||||||
|
clientXLast = clientX;
|
||||||
|
clientYLast = clientY;
|
||||||
|
|
||||||
|
parameters.mouseX = clientX / window.innerWidth;
|
||||||
|
parameters.mouseY = 1 - clientY / window.innerHeight;
|
||||||
|
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
onWindowResize();
|
||||||
|
window.addEventListener('resize', onWindowResize, false);
|
||||||
|
|
||||||
|
compile();
|
||||||
|
compileScreenProgram();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function computeSurfaceCorners() {
|
||||||
|
|
||||||
|
if (gl) {
|
||||||
|
|
||||||
|
surface.width = surface.height * parameters.screenWidth / parameters.screenHeight;
|
||||||
|
|
||||||
|
var halfWidth = surface.width * 0.5, halfHeight = surface.height * 0.5;
|
||||||
|
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, surface.buffer);
|
||||||
|
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
|
||||||
|
surface.centerX - halfWidth, surface.centerY - halfHeight,
|
||||||
|
surface.centerX + halfWidth, surface.centerY - halfHeight,
|
||||||
|
surface.centerX - halfWidth, surface.centerY + halfHeight,
|
||||||
|
surface.centerX + halfWidth, surface.centerY - halfHeight,
|
||||||
|
surface.centerX + halfWidth, surface.centerY + halfHeight,
|
||||||
|
surface.centerX - halfWidth, surface.centerY + halfHeight]), gl.STATIC_DRAW);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetSurface() {
|
||||||
|
|
||||||
|
surface.centerX = surface.centerY = 0;
|
||||||
|
surface.height = 1;
|
||||||
|
computeSurfaceCorners();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function compile() {
|
||||||
|
|
||||||
|
console.log('compiling shader...');
|
||||||
|
|
||||||
|
if (!gl) {
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var program = gl.createProgram();
|
||||||
|
var fragment = document.getElementById('shaderCode').textContent;
|
||||||
|
var vertex = document.getElementById('surfaceVertexShader').textContent;
|
||||||
|
|
||||||
|
var vs = createShader(vertex, gl.VERTEX_SHADER);
|
||||||
|
var fs = createShader(fragment, gl.FRAGMENT_SHADER);
|
||||||
|
|
||||||
|
if (vs == null || fs == null) return null;
|
||||||
|
|
||||||
|
gl.attachShader(program, vs);
|
||||||
|
gl.attachShader(program, fs);
|
||||||
|
|
||||||
|
gl.deleteShader(vs);
|
||||||
|
gl.deleteShader(fs);
|
||||||
|
|
||||||
|
gl.linkProgram(program);
|
||||||
|
|
||||||
|
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
||||||
|
|
||||||
|
var error = gl.getProgramInfoLog(program);
|
||||||
|
|
||||||
|
compileButton.title = error;
|
||||||
|
console.error(error);
|
||||||
|
|
||||||
|
console.error('VALIDATE_STATUS: ' + gl.getProgramParameter(program, gl.VALIDATE_STATUS), 'ERROR: ' + gl.getError());
|
||||||
|
compileButton.style.color = '#ff0000';
|
||||||
|
compileButton.textContent = 'compiled with errors';
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentProgram) {
|
||||||
|
|
||||||
|
gl.deleteProgram(currentProgram);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
currentProgram = program;
|
||||||
|
|
||||||
|
// Cache uniforms
|
||||||
|
|
||||||
|
cacheUniformLocation(program, 'time');
|
||||||
|
cacheUniformLocation(program, 'mouse');
|
||||||
|
cacheUniformLocation(program, 'resolution');
|
||||||
|
cacheUniformLocation(program, 'backbuffer');
|
||||||
|
cacheUniformLocation(program, 'surfaceSize');
|
||||||
|
|
||||||
|
// Load program into GPU
|
||||||
|
|
||||||
|
gl.useProgram(currentProgram);
|
||||||
|
|
||||||
|
// Set up buffers
|
||||||
|
|
||||||
|
surface.positionAttribute = gl.getAttribLocation(currentProgram, "surfacePosAttrib");
|
||||||
|
gl.enableVertexAttribArray(surface.positionAttribute);
|
||||||
|
|
||||||
|
vertexPosition = gl.getAttribLocation(currentProgram, "position");
|
||||||
|
gl.enableVertexAttribArray(vertexPosition);
|
||||||
|
|
||||||
|
console.log('compilation finished');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function compileScreenProgram() {
|
||||||
|
|
||||||
|
console.log('compiling screen program...');
|
||||||
|
|
||||||
|
if (!gl) { return; }
|
||||||
|
|
||||||
|
var program = gl.createProgram();
|
||||||
|
var fragment = document.getElementById('fragmentShader').textContent;
|
||||||
|
var vertex = document.getElementById('vertexShader').textContent;
|
||||||
|
|
||||||
|
var vs = createShader(vertex, gl.VERTEX_SHADER);
|
||||||
|
var fs = createShader(fragment, gl.FRAGMENT_SHADER);
|
||||||
|
|
||||||
|
gl.attachShader(program, vs);
|
||||||
|
gl.attachShader(program, fs);
|
||||||
|
|
||||||
|
gl.deleteShader(vs);
|
||||||
|
gl.deleteShader(fs);
|
||||||
|
|
||||||
|
gl.linkProgram(program);
|
||||||
|
|
||||||
|
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
||||||
|
|
||||||
|
console.error('VALIDATE_STATUS: ' + gl.getProgramParameter(program, gl.VALIDATE_STATUS), 'ERROR: ' + gl.getError());
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
screenProgram = program;
|
||||||
|
|
||||||
|
gl.useProgram(screenProgram);
|
||||||
|
|
||||||
|
cacheUniformLocation(program, 'resolution');
|
||||||
|
cacheUniformLocation(program, 'texture');
|
||||||
|
|
||||||
|
screenVertexPosition = gl.getAttribLocation(screenProgram, "position");
|
||||||
|
gl.enableVertexAttribArray(screenVertexPosition);
|
||||||
|
|
||||||
|
console.log('compilation finished');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function cacheUniformLocation(program, label) {
|
||||||
|
|
||||||
|
if (program.uniformsCache === undefined) {
|
||||||
|
|
||||||
|
program.uniformsCache = {};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
program.uniformsCache[label] = gl.getUniformLocation(program, label);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
function createTarget(width, height) {
|
||||||
|
|
||||||
|
var target = {};
|
||||||
|
|
||||||
|
target.framebuffer = gl.createFramebuffer();
|
||||||
|
target.renderbuffer = gl.createRenderbuffer();
|
||||||
|
target.texture = gl.createTexture();
|
||||||
|
|
||||||
|
// set up framebuffer
|
||||||
|
|
||||||
|
gl.bindTexture(gl.TEXTURE_2D, target.texture);
|
||||||
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
|
||||||
|
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||||
|
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
||||||
|
|
||||||
|
gl.bindFramebuffer(gl.FRAMEBUFFER, target.framebuffer);
|
||||||
|
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, target.texture, 0);
|
||||||
|
|
||||||
|
// set up renderbuffer
|
||||||
|
|
||||||
|
gl.bindRenderbuffer(gl.RENDERBUFFER, target.renderbuffer);
|
||||||
|
|
||||||
|
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, width, height);
|
||||||
|
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, target.renderbuffer);
|
||||||
|
|
||||||
|
// clean up
|
||||||
|
|
||||||
|
gl.bindTexture(gl.TEXTURE_2D, null);
|
||||||
|
gl.bindRenderbuffer(gl.RENDERBUFFER, null);
|
||||||
|
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||||
|
|
||||||
|
return target;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function createRenderTargets() {
|
||||||
|
|
||||||
|
frontTarget = createTarget(parameters.screenWidth, parameters.screenHeight);
|
||||||
|
backTarget = createTarget(parameters.screenWidth, parameters.screenHeight);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
var dummyFunction = function () { };
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
function htmlEncode(str) {
|
||||||
|
|
||||||
|
return String(str)
|
||||||
|
.replace(/&/g, '&')
|
||||||
|
.replace(/"/g, '"')
|
||||||
|
.replace(/'/g, ''')
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/>/g, '>');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
function createShader(src, type) {
|
||||||
|
|
||||||
|
var shader = gl.createShader(type);
|
||||||
|
var line, lineNum, lineError, index = 0, indexEnd;
|
||||||
|
|
||||||
|
gl.shaderSource(shader, src);
|
||||||
|
gl.compileShader(shader);
|
||||||
|
|
||||||
|
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
||||||
|
|
||||||
|
var error = gl.getShaderInfoLog(shader);
|
||||||
|
|
||||||
|
// Remove trailing linefeed, for FireFox's benefit.
|
||||||
|
while ((error.length > 1) && (error.charCodeAt(error.length - 1) < 32)) {
|
||||||
|
error = error.substring(0, error.length - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.error(error);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return shader;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
function onWindowResize(event) {
|
||||||
|
|
||||||
|
var isMaxWidth = ((resizer.currentWidth === resizer.maxWidth) || (resizer.currentWidth === resizer.minWidth)),
|
||||||
|
isMaxHeight = ((resizer.currentHeight === resizer.maxHeight) || (resizer.currentHeight === resizer.minHeight));
|
||||||
|
|
||||||
|
canvas.width = window.innerWidth / quality;
|
||||||
|
canvas.height = window.innerHeight / quality;
|
||||||
|
|
||||||
|
canvas.style.width = window.innerWidth + 'px';
|
||||||
|
canvas.style.height = window.innerHeight + 'px';
|
||||||
|
|
||||||
|
parameters.screenWidth = canvas.width;
|
||||||
|
parameters.screenHeight = canvas.height;
|
||||||
|
|
||||||
|
computeSurfaceCorners();
|
||||||
|
|
||||||
|
if (gl) {
|
||||||
|
|
||||||
|
gl.viewport(0, 0, canvas.width, canvas.height);
|
||||||
|
|
||||||
|
createRenderTargets();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
function animate() {
|
||||||
|
|
||||||
|
requestAnimationFrame(animate);
|
||||||
|
render();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function render() {
|
||||||
|
|
||||||
|
if (!currentProgram) return;
|
||||||
|
|
||||||
|
parameters.time = Date.now() - parameters.startTime;
|
||||||
|
|
||||||
|
// Set uniforms for custom shader
|
||||||
|
|
||||||
|
gl.useProgram(currentProgram);
|
||||||
|
|
||||||
|
gl.uniform1f(currentProgram.uniformsCache['time'], parameters.time / 1000);
|
||||||
|
gl.uniform2f(currentProgram.uniformsCache['mouse'], parameters.mouseX, parameters.mouseY);
|
||||||
|
gl.uniform2f(currentProgram.uniformsCache['resolution'], parameters.screenWidth, parameters.screenHeight);
|
||||||
|
gl.uniform1i(currentProgram.uniformsCache['backbuffer'], 0);
|
||||||
|
gl.uniform2f(currentProgram.uniformsCache['surfaceSize'], surface.width, surface.height);
|
||||||
|
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, surface.buffer);
|
||||||
|
gl.vertexAttribPointer(surface.positionAttribute, 2, gl.FLOAT, false, 0, 0);
|
||||||
|
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
||||||
|
gl.vertexAttribPointer(vertexPosition, 2, gl.FLOAT, false, 0, 0);
|
||||||
|
|
||||||
|
gl.activeTexture(gl.TEXTURE0);
|
||||||
|
gl.bindTexture(gl.TEXTURE_2D, backTarget.texture);
|
||||||
|
|
||||||
|
// Render custom shader to front buffer
|
||||||
|
|
||||||
|
gl.bindFramebuffer(gl.FRAMEBUFFER, frontTarget.framebuffer);
|
||||||
|
|
||||||
|
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
||||||
|
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
||||||
|
|
||||||
|
// Set uniforms for screen shader
|
||||||
|
|
||||||
|
gl.useProgram(screenProgram);
|
||||||
|
|
||||||
|
gl.uniform2f(screenProgram.uniformsCache['resolution'], parameters.screenWidth, parameters.screenHeight);
|
||||||
|
gl.uniform1i(screenProgram.uniformsCache['texture'], 1);
|
||||||
|
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
||||||
|
gl.vertexAttribPointer(screenVertexPosition, 2, gl.FLOAT, false, 0, 0);
|
||||||
|
|
||||||
|
gl.activeTexture(gl.TEXTURE1);
|
||||||
|
gl.bindTexture(gl.TEXTURE_2D, frontTarget.texture);
|
||||||
|
|
||||||
|
// Render front buffer to screen
|
||||||
|
|
||||||
|
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||||
|
|
||||||
|
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
||||||
|
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
||||||
|
|
||||||
|
// Swap buffers
|
||||||
|
|
||||||
|
var tmp = frontTarget;
|
||||||
|
frontTarget = backTarget;
|
||||||
|
backTarget = tmp;
|
||||||
|
|
||||||
|
}
|
120
app/index.html
120
app/index.html
|
@ -17,11 +17,126 @@
|
||||||
<html>
|
<html>
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
|
|
||||||
|
<script src="glslsandbox.js"></script>
|
||||||
|
|
||||||
|
<script id="shaderCode" type="x-shader/x-fragment">
|
||||||
|
#ifdef GL_ES
|
||||||
|
precision mediump float;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uniform float time;
|
||||||
|
uniform vec2 mouse;
|
||||||
|
uniform vec2 resolution;
|
||||||
|
|
||||||
|
vec3 h() {
|
||||||
|
vec2 pos = ( gl_FragCoord.xy / resolution.xy ) - vec2(0.5,0.5);
|
||||||
|
float horizon = 0.0;
|
||||||
|
float fov = 0.5;
|
||||||
|
float scaling = 0.1;
|
||||||
|
|
||||||
|
vec3 p = vec3(pos.x, fov, pos.y - horizon);
|
||||||
|
vec2 s = vec2(p.x/p.z, p.y/p.z + 2.0 * time * sign(p.z)) * scaling;
|
||||||
|
|
||||||
|
//checkboard texture
|
||||||
|
float color = sign((mod(s.x, 0.1) - 0.05) * (mod(s.y, 0.1) - 0.05));
|
||||||
|
//fading
|
||||||
|
color *= p.z*p.z*10.0;
|
||||||
|
color = clamp(color,0.0,1.0);
|
||||||
|
color /= 2.0;
|
||||||
|
return vec3(color,0.0,color);
|
||||||
|
}
|
||||||
|
void main( void ) {
|
||||||
|
|
||||||
|
gl_FragColor = vec4( h(), 1.0 );
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script id="fragmentShader" type="x-shader/x-fragment">
|
||||||
|
|
||||||
|
#ifdef GL_ES
|
||||||
|
precision mediump float;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uniform vec2 resolution;
|
||||||
|
uniform sampler2D texture;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
|
||||||
|
vec2 uv = gl_FragCoord.xy / resolution.xy;
|
||||||
|
gl_FragColor = texture2D( texture, uv );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script id="vertexShader" type="x-shader/x-vertex">
|
||||||
|
|
||||||
|
attribute vec3 position;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
|
||||||
|
gl_Position = vec4( position, 1.0 );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script id="surfaceVertexShader" type="x-shader/x-vertex">
|
||||||
|
|
||||||
|
attribute vec3 position;
|
||||||
|
attribute vec2 surfacePosAttrib;
|
||||||
|
varying vec2 surfacePosition;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
|
||||||
|
surfacePosition = surfacePosAttrib;
|
||||||
|
gl_Position = vec4( position, 1.0 );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: sans-serif;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #2f3136;
|
||||||
|
color: #ffffff
|
||||||
|
}
|
||||||
|
|
||||||
|
div {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
background: linear-gradient(to bottom right, #0ff, #f0f);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
font-size: 96px;
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
// wait until DOM is ready so that error messages can display properly
|
// wait until DOM is ready so that error messages can display properly
|
||||||
window.onload = async () => {
|
window.onload = async () => {
|
||||||
|
|
||||||
|
init();
|
||||||
|
if (gl) animate();
|
||||||
|
|
||||||
// dont try doing anything if running in a browser
|
// dont try doing anything if running in a browser
|
||||||
if (navigator.userAgent.indexOf('discord') == -1) return;
|
if (navigator.userAgent.indexOf('discord') == -1) return;
|
||||||
|
|
||||||
|
@ -125,10 +240,11 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body style="position:absolute;top:50%;left:50%;transform:translateX(-50%) translateY(-50%);font-family:sans-serif;text-align:center;background-color:#2f3136;color:#ffffff">
|
<body>
|
||||||
<div style="background:linear-gradient(to bottom right,#0ff,#f0f);-webkit-background-clip:text;-webkit-text-fill-color:transparent;font-size:72px;">ΣndPwn³</div>
|
<div>ΣndPwn³</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
Loading…
Reference in New Issue