Merge remote-tracking branch 'old_a/master'
|
@ -0,0 +1,121 @@
|
||||||
|
# Jekyll
|
||||||
|
_site/
|
||||||
|
.sass-cache/
|
||||||
|
.jekyll-cache/
|
||||||
|
.jekyll-metadata
|
||||||
|
|
||||||
|
# Bundler
|
||||||
|
vendor/bundle/
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||||
|
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
*.pid.lock
|
||||||
|
|
||||||
|
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||||
|
lib-cov
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
|
|
||||||
|
# nyc test coverage
|
||||||
|
.nyc_output
|
||||||
|
|
||||||
|
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||||
|
.grunt
|
||||||
|
|
||||||
|
# Bower dependency directory (https://bower.io/)
|
||||||
|
bower_components
|
||||||
|
|
||||||
|
# node-waf configuration
|
||||||
|
.lock-wscript
|
||||||
|
|
||||||
|
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||||
|
build/Release
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
node_modules/
|
||||||
|
jspm_packages/
|
||||||
|
|
||||||
|
# TypeScript v1 declaration files
|
||||||
|
typings/
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional eslint cache
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Optional REPL history
|
||||||
|
.node_repl_history
|
||||||
|
|
||||||
|
# Output of 'npm pack'
|
||||||
|
*.tgz
|
||||||
|
|
||||||
|
# Yarn Integrity file
|
||||||
|
.yarn-integrity
|
||||||
|
|
||||||
|
# dotenv environment variables file
|
||||||
|
.env
|
||||||
|
.env.test
|
||||||
|
|
||||||
|
# parcel-bundler cache (https://parceljs.org/)
|
||||||
|
.cache
|
||||||
|
|
||||||
|
# next.js build output
|
||||||
|
.next
|
||||||
|
|
||||||
|
# nuxt.js build output
|
||||||
|
.nuxt
|
||||||
|
|
||||||
|
# vuepress build output
|
||||||
|
.vuepress/dist
|
||||||
|
|
||||||
|
# Serverless directories
|
||||||
|
.serverless/
|
||||||
|
|
||||||
|
# FuseBox cache
|
||||||
|
.fusebox/
|
||||||
|
|
||||||
|
# DynamoDB Local files
|
||||||
|
.dynamodb/
|
||||||
|
|
||||||
|
# Mac OS
|
||||||
|
# General
|
||||||
|
.DS_Store
|
||||||
|
.AppleDouble
|
||||||
|
.LSOverride
|
||||||
|
|
||||||
|
# Icon must end with two \r
|
||||||
|
Icon
|
||||||
|
|
||||||
|
# Thumbnails
|
||||||
|
._*
|
||||||
|
|
||||||
|
# Files that might appear in the root of a volume
|
||||||
|
.DocumentRevisions-V100
|
||||||
|
.fseventsd
|
||||||
|
.Spotlight-V100
|
||||||
|
.TemporaryItems
|
||||||
|
.Trashes
|
||||||
|
.VolumeIcon.icns
|
||||||
|
.com.apple.timemachine.donotpresent
|
||||||
|
|
||||||
|
# Directories potentially created on remote AFP share
|
||||||
|
.AppleDB
|
||||||
|
.AppleDesktop
|
||||||
|
Network Trash Folder
|
||||||
|
Temporary Items
|
||||||
|
.apdisk
|
|
@ -0,0 +1 @@
|
||||||
|
2.6.3
|
|
@ -0,0 +1,24 @@
|
||||||
|
---
|
||||||
|
layout: default
|
||||||
|
---
|
||||||
|
|
||||||
|
<style type="text/css" media="screen">
|
||||||
|
.container {
|
||||||
|
margin: 10px auto;
|
||||||
|
max-width: 600px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
margin: 30px 0;
|
||||||
|
font-size: 4em;
|
||||||
|
line-height: 1;
|
||||||
|
letter-spacing: -1px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<h1>404</h1>
|
||||||
|
|
||||||
|
<p><strong>Page not found :(</strong></p>
|
||||||
|
<p>The requested page could not be found.</p>
|
||||||
|
</div>
|
|
@ -0,0 +1,37 @@
|
||||||
|
source "https://rubygems.org"
|
||||||
|
|
||||||
|
# Hello! This is where you manage which Jekyll version is used to run.
|
||||||
|
# When you want to use a different version, change it below, save the
|
||||||
|
# file and run `bundle install`. Run Jekyll with `bundle exec`, like so:
|
||||||
|
#
|
||||||
|
# bundle exec jekyll serve
|
||||||
|
#
|
||||||
|
# This will help ensure the proper Jekyll version is running.
|
||||||
|
# Happy Jekylling!
|
||||||
|
gem "jekyll", "~> 3.8.5"
|
||||||
|
|
||||||
|
# If you want to use GitHub Pages, remove the "gem "jekyll"" above and
|
||||||
|
# uncomment the line below. To upgrade, run `bundle update github-pages`.
|
||||||
|
# gem "github-pages", group: :jekyll_plugins
|
||||||
|
|
||||||
|
# If you have any plugins, put them here!
|
||||||
|
group :jekyll_plugins do
|
||||||
|
gem "jekyll-feed", "~> 0.6"
|
||||||
|
gem "jekyll-assets", "~> 3.0"
|
||||||
|
end
|
||||||
|
|
||||||
|
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
|
||||||
|
gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw, :jruby]
|
||||||
|
|
||||||
|
# Performance-booster for watching directories on Windows
|
||||||
|
gem "wdm", "~> 0.1.0" if Gem.win_platform?
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
gem "autoprefixer-rails", "~> 9.5"
|
||||||
|
|
||||||
|
gem "image_optim", "~> 0.26.3"
|
||||||
|
|
||||||
|
gem "image_optim_pack", "~> 0.5.2"
|
||||||
|
|
||||||
|
gem "coffee-script", "~> 2.4"
|
|
@ -0,0 +1,128 @@
|
||||||
|
GEM
|
||||||
|
remote: https://rubygems.org/
|
||||||
|
specs:
|
||||||
|
activesupport (5.2.3)
|
||||||
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||||
|
i18n (>= 0.7, < 2)
|
||||||
|
minitest (~> 5.1)
|
||||||
|
tzinfo (~> 1.1)
|
||||||
|
addressable (2.6.0)
|
||||||
|
public_suffix (>= 2.0.2, < 4.0)
|
||||||
|
autoprefixer-rails (9.5.1.1)
|
||||||
|
execjs
|
||||||
|
coffee-script (2.4.1)
|
||||||
|
coffee-script-source
|
||||||
|
execjs
|
||||||
|
coffee-script-source (1.12.2)
|
||||||
|
colorator (1.1.0)
|
||||||
|
concurrent-ruby (1.1.5)
|
||||||
|
em-websocket (0.5.1)
|
||||||
|
eventmachine (>= 0.12.9)
|
||||||
|
http_parser.rb (~> 0.6.0)
|
||||||
|
eventmachine (1.2.7)
|
||||||
|
execjs (2.7.0)
|
||||||
|
exifr (1.3.6)
|
||||||
|
extras (0.3.0)
|
||||||
|
forwardable-extended (~> 2.5)
|
||||||
|
fastimage (2.1.5)
|
||||||
|
ffi (1.10.0)
|
||||||
|
forwardable-extended (2.6.0)
|
||||||
|
fspath (3.1.0)
|
||||||
|
http_parser.rb (0.6.0)
|
||||||
|
i18n (0.9.5)
|
||||||
|
concurrent-ruby (~> 1.0)
|
||||||
|
image_optim (0.26.3)
|
||||||
|
exifr (~> 1.2, >= 1.2.2)
|
||||||
|
fspath (~> 3.0)
|
||||||
|
image_size (>= 1.5, < 3)
|
||||||
|
in_threads (~> 1.3)
|
||||||
|
progress (~> 3.0, >= 3.0.1)
|
||||||
|
image_optim_pack (0.5.2.20190428)
|
||||||
|
fspath (>= 2.1, < 4)
|
||||||
|
image_optim (~> 0.19)
|
||||||
|
image_size (2.0.0)
|
||||||
|
in_threads (1.5.1)
|
||||||
|
jekyll (3.8.5)
|
||||||
|
addressable (~> 2.4)
|
||||||
|
colorator (~> 1.0)
|
||||||
|
em-websocket (~> 0.5)
|
||||||
|
i18n (~> 0.7)
|
||||||
|
jekyll-sass-converter (~> 1.0)
|
||||||
|
jekyll-watch (~> 2.0)
|
||||||
|
kramdown (~> 1.14)
|
||||||
|
liquid (~> 4.0)
|
||||||
|
mercenary (~> 0.3.3)
|
||||||
|
pathutil (~> 0.9)
|
||||||
|
rouge (>= 1.7, < 4)
|
||||||
|
safe_yaml (~> 1.0)
|
||||||
|
jekyll-assets (3.0.12)
|
||||||
|
activesupport (~> 5.0)
|
||||||
|
execjs (~> 2.7)
|
||||||
|
extras (~> 0.2)
|
||||||
|
fastimage (~> 2.0, >= 1.8)
|
||||||
|
jekyll (>= 3.5, < 4.0)
|
||||||
|
jekyll-sanity (~> 1.2)
|
||||||
|
liquid-tag-parser (~> 1.0)
|
||||||
|
nokogiri (~> 1.8)
|
||||||
|
pathutil (~> 0.16)
|
||||||
|
sprockets (>= 3.3, < 4.1.beta)
|
||||||
|
jekyll-feed (0.12.1)
|
||||||
|
jekyll (>= 3.7, < 5.0)
|
||||||
|
jekyll-sanity (1.2.0)
|
||||||
|
jekyll (~> 3.1)
|
||||||
|
jekyll-sass-converter (1.5.2)
|
||||||
|
sass (~> 3.4)
|
||||||
|
jekyll-watch (2.2.1)
|
||||||
|
listen (~> 3.0)
|
||||||
|
kramdown (1.17.0)
|
||||||
|
liquid (4.0.3)
|
||||||
|
liquid-tag-parser (1.9.0)
|
||||||
|
extras (~> 0.3)
|
||||||
|
liquid (>= 3.0, < 5.0)
|
||||||
|
listen (3.1.5)
|
||||||
|
rb-fsevent (~> 0.9, >= 0.9.4)
|
||||||
|
rb-inotify (~> 0.9, >= 0.9.7)
|
||||||
|
ruby_dep (~> 1.2)
|
||||||
|
mercenary (0.3.6)
|
||||||
|
mini_portile2 (2.4.0)
|
||||||
|
minitest (5.11.3)
|
||||||
|
nokogiri (1.10.3)
|
||||||
|
mini_portile2 (~> 2.4.0)
|
||||||
|
pathutil (0.16.2)
|
||||||
|
forwardable-extended (~> 2.6)
|
||||||
|
progress (3.5.0)
|
||||||
|
public_suffix (3.0.3)
|
||||||
|
rack (2.0.7)
|
||||||
|
rb-fsevent (0.10.3)
|
||||||
|
rb-inotify (0.10.0)
|
||||||
|
ffi (~> 1.0)
|
||||||
|
rouge (3.3.0)
|
||||||
|
ruby_dep (1.5.0)
|
||||||
|
safe_yaml (1.0.5)
|
||||||
|
sass (3.7.4)
|
||||||
|
sass-listen (~> 4.0.0)
|
||||||
|
sass-listen (4.0.0)
|
||||||
|
rb-fsevent (~> 0.9, >= 0.9.4)
|
||||||
|
rb-inotify (~> 0.9, >= 0.9.7)
|
||||||
|
sprockets (3.7.2)
|
||||||
|
concurrent-ruby (~> 1.0)
|
||||||
|
rack (> 1, < 3)
|
||||||
|
thread_safe (0.3.6)
|
||||||
|
tzinfo (1.2.5)
|
||||||
|
thread_safe (~> 0.1)
|
||||||
|
|
||||||
|
PLATFORMS
|
||||||
|
ruby
|
||||||
|
|
||||||
|
DEPENDENCIES
|
||||||
|
autoprefixer-rails (~> 9.5)
|
||||||
|
coffee-script (~> 2.4)
|
||||||
|
image_optim (~> 0.26.3)
|
||||||
|
image_optim_pack (~> 0.5.2)
|
||||||
|
jekyll (~> 3.8.5)
|
||||||
|
jekyll-assets (~> 3.0)
|
||||||
|
jekyll-feed (~> 0.6)
|
||||||
|
tzinfo-data
|
||||||
|
|
||||||
|
BUNDLED WITH
|
||||||
|
2.0.1
|
After Width: | Height: | Size: 231 KiB |
After Width: | Height: | Size: 63 KiB |
After Width: | Height: | Size: 96 KiB |
After Width: | Height: | Size: 75 KiB |
After Width: | Height: | Size: 71 KiB |
After Width: | Height: | Size: 56 KiB |
After Width: | Height: | Size: 60 KiB |
After Width: | Height: | Size: 101 KiB |
After Width: | Height: | Size: 516 KiB |
After Width: | Height: | Size: 111 KiB |
After Width: | Height: | Size: 94 KiB |
After Width: | Height: | Size: 42 KiB |
After Width: | Height: | Size: 5.0 KiB |
|
@ -0,0 +1,38 @@
|
||||||
|
#= require jquery-3.4.1.slim.js
|
||||||
|
|
||||||
|
$(document).data( "tempo", 80)
|
||||||
|
$(document).data( "sides", 3)
|
||||||
|
|
||||||
|
$(document).ready ->
|
||||||
|
current_col = 0
|
||||||
|
|
||||||
|
# append audio elements to buttons:
|
||||||
|
$(".sequencer-button").data( "side", 1 )
|
||||||
|
for row in [1..4]
|
||||||
|
for side in [1..$(document).data("sides")]
|
||||||
|
$("audio#row" + row ).clone().attr("id","").appendTo(".sequencer-button[row=" + row + "]")
|
||||||
|
|
||||||
|
setInterval =>
|
||||||
|
playCol(current_col)
|
||||||
|
if (current_col <= 6)
|
||||||
|
current_col++
|
||||||
|
else
|
||||||
|
current_col = 0
|
||||||
|
, 15000 / $(document).data("tempo")
|
||||||
|
|
||||||
|
playCol = (col) ->
|
||||||
|
$('.sequencer-button').removeClass('activated')
|
||||||
|
for row in [1..4]
|
||||||
|
current_button = $('.sequencer-button').eq(col + ( row - 1) * 8)
|
||||||
|
current_button.addClass('activated')
|
||||||
|
if ( current_button.prop('checked') )
|
||||||
|
side = current_button.data("side")
|
||||||
|
try
|
||||||
|
current_button.children(":eq(" + (side - 1) + ")")[0].play()
|
||||||
|
catch e
|
||||||
|
console.log "Error playing sound."
|
||||||
|
if (side >= $(document).data("sides"))
|
||||||
|
current_button.data("side", 1)
|
||||||
|
side = 1
|
||||||
|
else
|
||||||
|
current_button.data("side", side + 1)
|
|
@ -0,0 +1,50 @@
|
||||||
|
// STEP 1: Prepare the canvas and get WebGL context
|
||||||
|
var vertShaderSource = document.getElementById("vertex-shader").text;
|
||||||
|
var fragShaderSource = document.getElementById("fragment-shader").text;
|
||||||
|
var canvas = document.getElementById('shader-canvas');
|
||||||
|
var gl = canvas.getContext('webgl', {
|
||||||
|
antialias: false,
|
||||||
|
depth: false
|
||||||
|
});
|
||||||
|
// STEP 2: define geometry and store it in buffer objects
|
||||||
|
var verticies = [-1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0];
|
||||||
|
var vertex_buffer = gl.createBuffer();
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
|
||||||
|
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verticies), gl.STATIC_DRAW);
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, null)
|
||||||
|
// STEP 3: Create and compile shader programs
|
||||||
|
// Vert shader:
|
||||||
|
//var vertCode =
|
||||||
|
// 'attribute vec2 coordinates;' +
|
||||||
|
// 'void main(void) {' +
|
||||||
|
// ' gl_Position = vec4(coordinates, 0.0, 1.0);' +
|
||||||
|
// '}';
|
||||||
|
var vertCode = vertShaderSource;
|
||||||
|
var vertShader = gl.createShader(gl.VERTEX_SHADER);
|
||||||
|
gl.shaderSource(vertShader, vertCode);
|
||||||
|
gl.compileShader(vertShader);
|
||||||
|
// Frag shader:
|
||||||
|
// var fragCode = 'void main(void) {' +
|
||||||
|
// 'gl_FragColor = vec4(0.0, 0.3, 0.5, 1.0);' +
|
||||||
|
// '}';
|
||||||
|
var fragCode = fragShaderSource;
|
||||||
|
var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
|
||||||
|
gl.shaderSource(fragShader, fragCode);
|
||||||
|
gl.compileShader(fragShader);
|
||||||
|
// combine shaders:
|
||||||
|
var shaderProgram = gl.createProgram();
|
||||||
|
gl.attachShader(shaderProgram, vertShader);
|
||||||
|
gl.attachShader(shaderProgram, fragShader);
|
||||||
|
gl.linkProgram(shaderProgram);
|
||||||
|
gl.useProgram(shaderProgram);
|
||||||
|
// STEP 4: Associate the shader program to buffer objects
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
|
||||||
|
var coord = gl.getAttribLocation(shaderProgram, "coordinates");
|
||||||
|
gl.vertexAttribPointer(coord, 2, gl.FLOAT, false, 0, 0);
|
||||||
|
gl.enableVertexAttribArray(coord);
|
||||||
|
// STEP 5: Draw the object:
|
||||||
|
gl.clearColor(0.0, 0.0, 0.0, 1.0);
|
||||||
|
gl.enable(gl.DEPTH_TEST);
|
||||||
|
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||||
|
gl.viewport(0, 0, canvas.width, canvas.height);
|
||||||
|
gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);
|
|
@ -0,0 +1,760 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012, Gregg Tavares.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above
|
||||||
|
* copyright notice, this list of conditions and the following disclaimer
|
||||||
|
* in the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* * Neither the name of Gregg Tavares. nor the names of his
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/** @module webgl-utils */
|
||||||
|
// These funcitions are meant solely to help unclutter the tutorials.
|
||||||
|
// They are not meant as production type functions.
|
||||||
|
|
||||||
|
//(function() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapped logging function.
|
||||||
|
* @param {string} msg The message to log.
|
||||||
|
*/
|
||||||
|
var log = function(msg) {
|
||||||
|
if (window.console && window.console.log) {
|
||||||
|
window.console.log(msg);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapped logging function.
|
||||||
|
* @param {string} msg The message to log.
|
||||||
|
*/
|
||||||
|
var error = function(msg) {
|
||||||
|
if (window.console) {
|
||||||
|
if (window.console.error) {
|
||||||
|
window.console.error(msg);
|
||||||
|
}
|
||||||
|
else if (window.console.log) {
|
||||||
|
window.console.log(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turn off all logging.
|
||||||
|
*/
|
||||||
|
var loggingOff = function() {
|
||||||
|
log = function() {};
|
||||||
|
error = function() {};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the page is embedded.
|
||||||
|
* @return {boolean} True of we are in an iframe
|
||||||
|
*/
|
||||||
|
var isInIFrame = function() {
|
||||||
|
return window != window.top;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a WebGL enum to a string
|
||||||
|
* @param {WebGLRenderingContext} gl The WebGLRenderingContext to use.
|
||||||
|
* @param {number} value The enum value.
|
||||||
|
* @return {string} The enum as a string.
|
||||||
|
*/
|
||||||
|
var glEnumToString = function(gl, value) {
|
||||||
|
for (var p in gl) {
|
||||||
|
if (gl[p] == value) {
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "0x" + value.toString(16);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the HTLM for a failure message
|
||||||
|
* @param {string} canvasContainerId id of container of th
|
||||||
|
* canvas.
|
||||||
|
* @return {string} The html.
|
||||||
|
*/
|
||||||
|
var makeFailHTML = function(msg) {
|
||||||
|
return '' +
|
||||||
|
'<table style="background-color: #8CE; width: 100%; height: 100%;"><tr>' +
|
||||||
|
'<td align="center">' +
|
||||||
|
'<div style="display: table-cell; vertical-align: middle;">' +
|
||||||
|
'<div style="">' + msg + '</div>' +
|
||||||
|
'</div>' +
|
||||||
|
'</td></tr></table>';
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mesasge for getting a webgl browser
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
var GET_A_WEBGL_BROWSER = '' +
|
||||||
|
'This page requires a browser that supports WebGL.<br/>' +
|
||||||
|
'<a href="http://get.webgl.org">Click here to upgrade your browser.</a>';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mesasge for need better hardware
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
var OTHER_PROBLEM = '' +
|
||||||
|
"It doesn't appear your computer can support WebGL.<br/>" +
|
||||||
|
'<a href="http://get.webgl.org/troubleshooting/">Click here for more information.</a>';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a webgl context. If creation fails it will
|
||||||
|
* change the contents of the container of the <canvas>
|
||||||
|
* tag to an error message with the correct links for WebGL.
|
||||||
|
* @param {HTMLCanvasElement} canvas. The canvas element to
|
||||||
|
* create a context from.
|
||||||
|
* @param {WebGLContextCreationAttirbutes} opt_attribs Any
|
||||||
|
* creation attributes you want to pass in.
|
||||||
|
* @return {WebGLRenderingContext} The created context.
|
||||||
|
*/
|
||||||
|
var setupWebGL = function(canvas, opt_attribs) {
|
||||||
|
function showLink(str) {
|
||||||
|
var container = canvas.parentNode;
|
||||||
|
if (container) {
|
||||||
|
container.innerHTML = makeFailHTML(str);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!window.WebGLRenderingContext) {
|
||||||
|
showLink(GET_A_WEBGL_BROWSER);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var context = create3DContext(canvas, opt_attribs);
|
||||||
|
if (!context) {
|
||||||
|
showLink(OTHER_PROBLEM);
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a webgl context.
|
||||||
|
* @param {HTMLCanvasElement} canvas The canvas tag to get
|
||||||
|
* context from. If one is not passed in one will be
|
||||||
|
* created.
|
||||||
|
* @return {WebGLRenderingContext} The created context.
|
||||||
|
*/
|
||||||
|
var create3DContext = function(canvas, opt_attribs) {
|
||||||
|
var names = ["webgl", "experimental-webgl"];
|
||||||
|
var context = null;
|
||||||
|
for (var ii = 0; ii < names.length; ++ii) {
|
||||||
|
try {
|
||||||
|
context = canvas.getContext(names[ii], opt_attribs);
|
||||||
|
} catch(e) {}
|
||||||
|
if (context) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
var updateCSSIfInIFrame = function() {
|
||||||
|
if (isInIFrame()) {
|
||||||
|
document.body.className = "iframe";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a WebGL context.
|
||||||
|
* makes its backing store the size it is displayed.
|
||||||
|
*/
|
||||||
|
var getWebGLContext = function(canvas, opt_attribs, opt_options) {
|
||||||
|
var options = opt_options || {}
|
||||||
|
|
||||||
|
if (isInIFrame()) {
|
||||||
|
updateCSSIfInIFrame();
|
||||||
|
|
||||||
|
// make the canvas backing store the size it's displayed.
|
||||||
|
if (!options.dontResize) {
|
||||||
|
var width = canvas.clientWidth;
|
||||||
|
var height = canvas.clientHeight;
|
||||||
|
canvas.width = width;
|
||||||
|
canvas.height = height;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var title = document.title;
|
||||||
|
var h1 = document.createElement("h1");
|
||||||
|
h1.innerText = title;
|
||||||
|
document.body.insertBefore(h1, document.body.children[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
var gl = setupWebGL(canvas, opt_attribs);
|
||||||
|
return gl;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads a shader.
|
||||||
|
* @param {WebGLRenderingContext} gl The WebGLRenderingContext to use.
|
||||||
|
* @param {string} shaderSource The shader source.
|
||||||
|
* @param {number} shaderType The type of shader.
|
||||||
|
* @param {function(string): void) opt_errorCallback callback for errors.
|
||||||
|
* @return {WebGLShader} The created shader.
|
||||||
|
*/
|
||||||
|
var loadShader = function(gl, shaderSource, shaderType, opt_errorCallback) {
|
||||||
|
var errFn = opt_errorCallback || error;
|
||||||
|
// Create the shader object
|
||||||
|
var shader = gl.createShader(shaderType);
|
||||||
|
|
||||||
|
// Load the shader source
|
||||||
|
gl.shaderSource(shader, shaderSource);
|
||||||
|
|
||||||
|
// Compile the shader
|
||||||
|
gl.compileShader(shader);
|
||||||
|
|
||||||
|
// Check the compile status
|
||||||
|
var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
|
||||||
|
if (!compiled) {
|
||||||
|
// Something went wrong during compilation; get the error
|
||||||
|
var lastError = gl.getShaderInfoLog(shader);
|
||||||
|
errFn("*** Error compiling shader '" + shader + "':" + lastError);
|
||||||
|
gl.deleteShader(shader);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a program, attaches shaders, binds attrib locations, links the
|
||||||
|
* program and calls useProgram.
|
||||||
|
* @param {WebGLShader[]} shaders The shaders to attach
|
||||||
|
* @param {string[]?} opt_attribs The attribs names.
|
||||||
|
* @param {number[]?} opt_locations The locations for the
|
||||||
|
* attribs.
|
||||||
|
* @param {function(string): void) opt_errorCallback callback for errors.
|
||||||
|
*/
|
||||||
|
var loadProgram = function(
|
||||||
|
gl, shaders, opt_attribs, opt_locations, opt_errorCallback) {
|
||||||
|
var errFn = opt_errorCallback || error;
|
||||||
|
var program = gl.createProgram();
|
||||||
|
for (var ii = 0; ii < shaders.length; ++ii) {
|
||||||
|
gl.attachShader(program, shaders[ii]);
|
||||||
|
}
|
||||||
|
if (opt_attribs) {
|
||||||
|
for (var ii = 0; ii < opt_attribs.length; ++ii) {
|
||||||
|
gl.bindAttribLocation(
|
||||||
|
program,
|
||||||
|
opt_locations ? opt_locations[ii] : ii,
|
||||||
|
opt_attribs[ii]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gl.linkProgram(program);
|
||||||
|
|
||||||
|
// Check the link status
|
||||||
|
var linked = gl.getProgramParameter(program, gl.LINK_STATUS);
|
||||||
|
if (!linked) {
|
||||||
|
// something went wrong with the link
|
||||||
|
var lastError = gl.getProgramInfoLog (program);
|
||||||
|
errFn("Error in program linking:" + lastError);
|
||||||
|
|
||||||
|
gl.deleteProgram(program);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return program;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads a shader from a script tag.
|
||||||
|
* @param {WebGLRenderingContext} gl The WebGLRenderingContext to use.
|
||||||
|
* @param {string} scriptId The id of the script tag.
|
||||||
|
* @param {number} opt_shaderType The type of shader. If not passed in it will
|
||||||
|
* be derived from the type of the script tag.
|
||||||
|
* @param {function(string): void) opt_errorCallback callback for errors.
|
||||||
|
* @return {WebGLShader} The created shader.
|
||||||
|
*/
|
||||||
|
var createShaderFromScript = function(
|
||||||
|
gl, scriptId, opt_shaderType, opt_errorCallback) {
|
||||||
|
var shaderSource = "";
|
||||||
|
var shaderType;
|
||||||
|
var shaderScript = document.getElementById(scriptId);
|
||||||
|
if (!shaderScript) {
|
||||||
|
throw("*** Error: unknown script element" + scriptId);
|
||||||
|
}
|
||||||
|
shaderSource = shaderScript.text;
|
||||||
|
|
||||||
|
if (!opt_shaderType) {
|
||||||
|
if (shaderScript.type == "x-shader/x-vertex") {
|
||||||
|
shaderType = gl.VERTEX_SHADER;
|
||||||
|
} else if (shaderScript.type == "x-shader/x-fragment") {
|
||||||
|
shaderType = gl.FRAGMENT_SHADER;
|
||||||
|
} else if (shaderType != gl.VERTEX_SHADER && shaderType != gl.FRAGMENT_SHADER) {
|
||||||
|
throw("*** Error: unknown shader type");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return loadShader(
|
||||||
|
gl, shaderSource, opt_shaderType ? opt_shaderType : shaderType,
|
||||||
|
opt_errorCallback);
|
||||||
|
};
|
||||||
|
|
||||||
|
var defaultShaderType = [
|
||||||
|
"VERTEX_SHADER",
|
||||||
|
"FRAGMENT_SHADER"
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a program from 2 script tags.
|
||||||
|
*
|
||||||
|
* @param {WebGLRenderingContext} gl The WebGLRenderingContext
|
||||||
|
* to use.
|
||||||
|
* @param {string[]} shaderScriptIds Array of ids of the script
|
||||||
|
* tags for the shaders. The first is assumed to be the
|
||||||
|
* vertex shader, the second the fragment shader.
|
||||||
|
* @param {string[]?} opt_attribs The attribs names.
|
||||||
|
* @param {number[]?} opt_locations The locations for the
|
||||||
|
* attribs.
|
||||||
|
* @param {function(string): void) opt_errorCallback callback for errors.
|
||||||
|
* @return {WebGLProgram} The created program.
|
||||||
|
*/
|
||||||
|
var createProgramFromScripts = function(
|
||||||
|
gl, shaderScriptIds, opt_attribs, opt_locations, opt_errorCallback) {
|
||||||
|
var shaders = [];
|
||||||
|
for (var ii = 0; ii < shaderScriptIds.length; ++ii) {
|
||||||
|
shaders.push(createShaderFromScript(
|
||||||
|
gl, shaderScriptIds[ii], gl[defaultShaderType[ii]], opt_errorCallback));
|
||||||
|
}
|
||||||
|
return loadProgram(gl, shaders, opt_attribs, opt_locations, opt_errorCallback);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a program from 2 sources.
|
||||||
|
*
|
||||||
|
* @param {WebGLRenderingContext} gl The WebGLRenderingContext
|
||||||
|
* to use.
|
||||||
|
* @param {string[]} shaderSourcess Array of sources for the
|
||||||
|
* shaders. The first is assumed to be the vertex shader,
|
||||||
|
* the second the fragment shader.
|
||||||
|
* @param {string[]?} opt_attribs The attribs names.
|
||||||
|
* @param {number[]?} opt_locations The locations for the
|
||||||
|
* attribs.
|
||||||
|
* @param {function(string): void) opt_errorCallback callback for errors.
|
||||||
|
* @return {WebGLProgram} The created program.
|
||||||
|
*/
|
||||||
|
var createProgramFromSources = function(
|
||||||
|
gl, shaderSources, opt_attribs, opt_locations, opt_errorCallback) {
|
||||||
|
var shaders = [];
|
||||||
|
for (var ii = 0; ii < shaderSources.length; ++ii) {
|
||||||
|
shaders.push(loadShader(
|
||||||
|
gl, shaderSources[ii], gl[defaultShaderType[ii]], opt_errorCallback));
|
||||||
|
}
|
||||||
|
return loadProgram(gl, shaders, opt_attribs, opt_locations, opt_errorCallback);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the corresponding bind point for a given sampler type
|
||||||
|
*/
|
||||||
|
var getBindPointForSamplerType = function(gl, type) {
|
||||||
|
if (type == gl.SAMPLER_2D) return gl.TEXTURE_2D;
|
||||||
|
if (type == gl.SAMPLER_CUBE) return gl.TEXTURE_CUBE_MAP;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object.<string, function>} Setters
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates setter functions for all uniforms of a shader
|
||||||
|
* program.
|
||||||
|
*
|
||||||
|
* @see setUniforms for example
|
||||||
|
*
|
||||||
|
* @param {WebGLProgram} program the program to create setters
|
||||||
|
* for.
|
||||||
|
* @returns {Setters} an object with a setter for each uniform
|
||||||
|
* by name.
|
||||||
|
*/
|
||||||
|
var createUniformSetters = function(gl, program) {
|
||||||
|
var textureUnit = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a setter for a uniform of the given program with it's
|
||||||
|
* location embedded in the setter.
|
||||||
|
* @param {WebGLProgram} program
|
||||||
|
* @param {WebGLUniformInfo} uniformInfo
|
||||||
|
* @returns {function} the created setter.
|
||||||
|
*/
|
||||||
|
var createUniformSetter = function(program, uniformInfo) {
|
||||||
|
var location = gl.getUniformLocation(program, uniformInfo.name);
|
||||||
|
var type = uniformInfo.type;
|
||||||
|
// Check if this uniform is an array
|
||||||
|
var isArray = (uniformInfo.size > 1 && uniformInfo.name.substr(-3) == "[0]");
|
||||||
|
if (type == gl.FLOAT && isArray)
|
||||||
|
return function(v) { gl.uniform1fv(location, v); };
|
||||||
|
if (type == gl.FLOAT)
|
||||||
|
return function(v) { gl.uniform1f(location, v); };
|
||||||
|
if (type == gl.FLOAT_VEC2)
|
||||||
|
return function(v) { gl.uniform2fv(location, v); };
|
||||||
|
if (type == gl.FLOAT_VEC3)
|
||||||
|
return function(v) { gl.uniform3fv(location, v); };
|
||||||
|
if (type == gl.FLOAT_VEC4)
|
||||||
|
return function(v) { gl.uniform4fv(location, v); };
|
||||||
|
if (type == gl.INT && isArray)
|
||||||
|
return function(v) { gl.uniform1iv(location, v); };
|
||||||
|
if (type == gl.INT)
|
||||||
|
return function(v) { gl.uniform1i(location, v); };
|
||||||
|
if (type == gl.INT_VEC2)
|
||||||
|
return function(v) { gl.uniform2iv(location, v); };
|
||||||
|
if (type == gl.INT_VEC3)
|
||||||
|
return function(v) { gl.uniform3iv(location, v); };
|
||||||
|
if (type == gl.INT_VEC4)
|
||||||
|
return function(v) { gl.uniform4iv(location, v); };
|
||||||
|
if (type == gl.BOOL)
|
||||||
|
return function(v) { gl.uniform1iv(location, v); };
|
||||||
|
if (type == gl.BOOL_VEC2)
|
||||||
|
return function(v) { gl.uniform2iv(location, v); };
|
||||||
|
if (type == gl.BOOL_VEC3)
|
||||||
|
return function(v) { gl.uniform3iv(location, v); };
|
||||||
|
if (type == gl.BOOL_VEC4)
|
||||||
|
return function(v) { gl.uniform4iv(location, v); };
|
||||||
|
if (type == gl.FLOAT_MAT2)
|
||||||
|
return function(v) { gl.uniformMatrix2fv(location, false, v); };
|
||||||
|
if (type == gl.FLOAT_MAT3)
|
||||||
|
return function(v) { gl.uniformMatrix3fv(location, false, v); };
|
||||||
|
if (type == gl.FLOAT_MAT4)
|
||||||
|
return function(v) { gl.uniformMatrix4fv(location, false, v); };
|
||||||
|
if ((type == gl.SAMPLER_2D || type == gl.SAMPLER_CUBE) && isArray) {
|
||||||
|
var units = [];
|
||||||
|
for (var ii = 0; ii < info.size; ++ii) {
|
||||||
|
units.push(textureUnit++);
|
||||||
|
}
|
||||||
|
return function(bindPoint, units) {
|
||||||
|
return function(textures) {
|
||||||
|
gl.uniform1iv(location, units);
|
||||||
|
textures.forEach(function(texture, index) {
|
||||||
|
gl.activeTexture(gl.TEXTURE0 + units[index]);
|
||||||
|
gl.bindTexture(bindPoint, tetxure);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}(getBindPointForSamplerType(gl, type), units);
|
||||||
|
}
|
||||||
|
if (type == gl.SAMPLER_2D || type == gl.SAMPLER_CUBE)
|
||||||
|
return function(bindPoint, unit) {
|
||||||
|
return function(texture) {
|
||||||
|
gl.uniform1i(location, unit);
|
||||||
|
gl.activeTexture(gl.TEXTURE0 + unit);
|
||||||
|
gl.bindTexture(bindPoint, texture);
|
||||||
|
};
|
||||||
|
}(getBindPointForSamplerType(gl, type), textureUnit++);
|
||||||
|
throw ("unknown type: 0x" + type.toString(16)); // we should never get here.
|
||||||
|
};
|
||||||
|
|
||||||
|
var uniformSetters = { };
|
||||||
|
var numUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
|
||||||
|
|
||||||
|
for (var ii = 0; ii < numUniforms; ++ii) {
|
||||||
|
var uniformInfo = gl.getActiveUniform(program, ii);
|
||||||
|
if (!uniformInfo) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
var name = uniformInfo.name;
|
||||||
|
// remove the array suffix.
|
||||||
|
if (name.substr(-3) == "[0]") {
|
||||||
|
name = name.substr(0, name.length - 3);
|
||||||
|
}
|
||||||
|
var setter = createUniformSetter(program, uniformInfo);
|
||||||
|
uniformSetters[name] = setter;
|
||||||
|
}
|
||||||
|
return uniformSetters;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set uniforms and binds related textures.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* var program = createProgramFromScripts(
|
||||||
|
* gl, ["some-vs", "some-fs");
|
||||||
|
*
|
||||||
|
* var uniformSetters = createUniformSetters(program);
|
||||||
|
*
|
||||||
|
* var tex1 = gl.createTexture();
|
||||||
|
* var tex2 = gl.createTexture();
|
||||||
|
*
|
||||||
|
* ... assume we setup the textures with data ...
|
||||||
|
*
|
||||||
|
* var uniforms = {
|
||||||
|
* u_someSampler: tex1,
|
||||||
|
* u_someOtherSampler: tex2,
|
||||||
|
* u_someColor: [1,0,0,1],
|
||||||
|
* u_somePosition: [0,1,1],
|
||||||
|
* u_someMatrix: [
|
||||||
|
* 1,0,0,0,
|
||||||
|
* 0,1,0,0,
|
||||||
|
* 0,0,1,0,
|
||||||
|
* 0,0,0,0,
|
||||||
|
* ],
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* gl.useProgram(program);
|
||||||
|
*
|
||||||
|
* This will automatically bind the textures AND set the
|
||||||
|
* uniforms.
|
||||||
|
*
|
||||||
|
* setUniforms(uniformSetters, uniforms);
|
||||||
|
*
|
||||||
|
* @param {Setters} setters the setters returned from
|
||||||
|
* createUniformSettersForProgram
|
||||||
|
* @param {Object.<string, value>} an object with values for the
|
||||||
|
* uniforms.
|
||||||
|
*/
|
||||||
|
var setUniforms = function(setters, values) {
|
||||||
|
Object.keys(values).forEach(function(name) {
|
||||||
|
var setter = setters[name];
|
||||||
|
if (setter) {
|
||||||
|
setter(values[name]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates setter functions for all attributes of a shader
|
||||||
|
* program
|
||||||
|
*
|
||||||
|
* @see setAttributes for example
|
||||||
|
*
|
||||||
|
* @param {WebGLProgram} program the program to create setters
|
||||||
|
* for.
|
||||||
|
* @returns {Setters} an object with a setter for each uniform
|
||||||
|
* by name.
|
||||||
|
*/
|
||||||
|
var createAttributeSetters = function(gl, program) {
|
||||||
|
var attribSetters = {
|
||||||
|
};
|
||||||
|
|
||||||
|
function createAttribSetter(index) {
|
||||||
|
return function(b) {
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, b.buffer);
|
||||||
|
gl.enableVertexAttribArray(index);
|
||||||
|
gl.vertexAttribPointer(
|
||||||
|
index, b.numComponents || b.size, b.type || gl.FLOAT, b.normalize || false, b.stride || 0, b.offset || 0);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var numAttribs = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
|
||||||
|
for (var ii = 0; ii < numAttribs; ++ii) {
|
||||||
|
var attribInfo = gl.getActiveAttrib(program, ii);
|
||||||
|
if (!attribInfo) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
var index = gl.getAttribLocation(program, attribInfo.name);
|
||||||
|
attribSetters[attribInfo.name] = createAttribSetter(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
return attribSetters;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets attributes and binds buffers.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* var program = createProgramFromScripts(
|
||||||
|
* gl, ["some-vs", "some-fs");
|
||||||
|
*
|
||||||
|
* var attribSetters = createAttributeSetters(program);
|
||||||
|
*
|
||||||
|
* var positionBuffer = gl.createBuffer();
|
||||||
|
* var texcoordBuffer = gl.createBuffer();
|
||||||
|
*
|
||||||
|
* var attribs = {
|
||||||
|
* a_position: {buffer: positionBuffer, numComponents: 3},
|
||||||
|
* a_texcoord: {buffer: texcoordBuffer, numComponents: 2},
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
* gl.useProgram(program);
|
||||||
|
*
|
||||||
|
* This will automatically bind the buffers AND set the
|
||||||
|
* attributes.
|
||||||
|
*
|
||||||
|
* setAttributes(attribSetters, attribs);
|
||||||
|
*
|
||||||
|
* Properties of attribs. For each attrib you can add
|
||||||
|
* properties:
|
||||||
|
*
|
||||||
|
* type: the type of data in the buffer. Default = gl.FLOAT
|
||||||
|
* normalize: whether or not to normalize the data. Default =
|
||||||
|
* false
|
||||||
|
* stride: the stride. Default = 0
|
||||||
|
* offset: offset into the buffer. Default = 0
|
||||||
|
*
|
||||||
|
* For example if you had 3 value float positions, 2 value
|
||||||
|
* float texcoord and 4 value uint8 colors you'd setup your
|
||||||
|
* attribs like this
|
||||||
|
*
|
||||||
|
* var attribs = {
|
||||||
|
* a_position: {buffer: positionBuffer, numComponents: 3},
|
||||||
|
* a_texcoord: {buffer: texcoordBuffer, numComponents: 2},
|
||||||
|
* a_color: {
|
||||||
|
* buffer: colorBuffer,
|
||||||
|
* numComponents: 4,
|
||||||
|
* type: gl.UNSIGNED_BYTE,
|
||||||
|
* normalize: true,
|
||||||
|
* },
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
var setAttributes = function(setters, buffers) {
|
||||||
|
Object.keys(buffers).forEach(function(name) {
|
||||||
|
var setter = setters[name];
|
||||||
|
if (setter) {
|
||||||
|
setter(buffers[name]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add your prefix here.
|
||||||
|
var browserPrefixes = [
|
||||||
|
"",
|
||||||
|
"MOZ_",
|
||||||
|
"OP_",
|
||||||
|
"WEBKIT_"
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given an extension name like WEBGL_compressed_texture_s3tc
|
||||||
|
* returns the supported version extension, like
|
||||||
|
* WEBKIT_WEBGL_compressed_teture_s3tc
|
||||||
|
* @param {string} name Name of extension to look for
|
||||||
|
* @return {WebGLExtension} The extension or undefined if not
|
||||||
|
* found.
|
||||||
|
*/
|
||||||
|
var getExtensionWithKnownPrefixes = function(gl, name) {
|
||||||
|
for (var ii = 0; ii < browserPrefixes.length; ++ii) {
|
||||||
|
var prefixedName = browserPrefixes[ii] + name;
|
||||||
|
var ext = gl.getExtension(prefixedName);
|
||||||
|
if (ext) {
|
||||||
|
return ext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resize a canvas to match the size it's displayed.
|
||||||
|
* @param {HTMLCanvasElement} canvas The canvas to resize.
|
||||||
|
* @param {boolean} true if the canvas was resized.
|
||||||
|
*/
|
||||||
|
var resizeCanvasToDisplaySize = function(canvas) {
|
||||||
|
var width = canvas.clientWidth;
|
||||||
|
var height = canvas.clientHeight;
|
||||||
|
if (canvas.width != width ||
|
||||||
|
canvas.height != height) {
|
||||||
|
canvas.width = width;
|
||||||
|
canvas.height = height;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* export functions */
|
||||||
|
window.createAttributeSetters = createAttributeSetters;
|
||||||
|
window.createProgram = loadProgram;
|
||||||
|
window.createProgramFromScripts = createProgramFromScripts;
|
||||||
|
window.createProgramFromSources = createProgramFromSources;
|
||||||
|
window.createShaderFromScriptElement = createShaderFromScript;
|
||||||
|
window.createUniformSetters = createUniformSetters;
|
||||||
|
window.getWebGLContext = getWebGLContext;
|
||||||
|
window.updateCSSIfInIFrame = updateCSSIfInIFrame;
|
||||||
|
window.getExtensionWithKnownPrefixes = getExtensionWithKnownPrefixes;
|
||||||
|
window.resizeCanvasToDisplaySize = resizeCanvasToDisplaySize;
|
||||||
|
window.setAttributes = setAttributes;
|
||||||
|
window.setUniforms = setUniforms;
|
||||||
|
window.setupWebGL = setupWebGL;
|
||||||
|
|
||||||
|
// All browsers that support WebGL support requestAnimationFrame
|
||||||
|
window.requestAnimFrame = window.requestAnimationFrame; // just to stay backward compatible.
|
||||||
|
window.cancelRequestAnimFrame = window.cancelAnimationFrame; // just to stay backward compatible.
|
||||||
|
|
||||||
|
//}());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function onLoad () {
|
||||||
|
var canvas = document.getElementById("canvas");
|
||||||
|
var gl = canvas.getContext("experimental-webgl");
|
||||||
|
|
||||||
|
var vertexShaderNode = createShaderFromScriptElement(gl, "node-vertex-shader");
|
||||||
|
var fragmentShaderNode = createShaderFromScriptElement(gl, "node-fragment-shader");
|
||||||
|
var programNode = createProgram(gl, [vertexShaderNode, fragmentShaderNode]);
|
||||||
|
gl.useProgram(programNode);
|
||||||
|
|
||||||
|
|
||||||
|
var ATTRIBUTES = 5;
|
||||||
|
var j = 0;
|
||||||
|
var data = [];
|
||||||
|
var circle = {x: 50, y: 50, r: 45};
|
||||||
|
|
||||||
|
data[j++] = (circle.x - circle.r);
|
||||||
|
data[j++] = (circle.y - circle.r);
|
||||||
|
data[j++] = circle.x;
|
||||||
|
data[j++] = circle.y;
|
||||||
|
data[j++] = circle.r;
|
||||||
|
|
||||||
|
data[j++] = (circle.x + (1 + Math.sqrt(2)) * circle.r);
|
||||||
|
data[j++] = circle.y - circle.r;
|
||||||
|
data[j++] = circle.x;
|
||||||
|
data[j++] = circle.y;
|
||||||
|
data[j++] = circle.r;
|
||||||
|
|
||||||
|
data[j++] = (circle.x - circle.r);
|
||||||
|
data[j++] = (circle.y + (1 + Math.sqrt(2)) * circle.r);
|
||||||
|
data[j++] = circle.x;
|
||||||
|
data[j++] = circle.y;
|
||||||
|
data[j++] = circle.r;
|
||||||
|
|
||||||
|
var dataBuffer = new Float32Array(data);
|
||||||
|
|
||||||
|
var buffer = gl.createBuffer();
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
||||||
|
gl.bufferData(
|
||||||
|
gl.ARRAY_BUFFER,
|
||||||
|
dataBuffer,
|
||||||
|
gl.STATIC_DRAW);
|
||||||
|
|
||||||
|
var resolutionLocation = gl.getUniformLocation(programNode, "u_resolution");
|
||||||
|
gl.uniform2f(resolutionLocation, canvas.width, canvas.height);
|
||||||
|
|
||||||
|
var positionLocation = gl.getAttribLocation(programNode, "a_position");
|
||||||
|
var centerLocation = gl.getAttribLocation(programNode, "a_center");
|
||||||
|
var radiusLocation = gl.getAttribLocation(programNode, "a_radius");
|
||||||
|
|
||||||
|
|
||||||
|
gl.enableVertexAttribArray(positionLocation);
|
||||||
|
gl.enableVertexAttribArray(centerLocation);
|
||||||
|
gl.enableVertexAttribArray(radiusLocation);
|
||||||
|
|
||||||
|
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 0);
|
||||||
|
gl.vertexAttribPointer(centerLocation, 2, gl.FLOAT, false, ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 8);
|
||||||
|
gl.vertexAttribPointer(radiusLocation, 1, gl.FLOAT, false, ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 16);
|
||||||
|
|
||||||
|
gl.drawArrays(gl.TRIANGLES, 0, data.length/ATTRIBUTES);
|
||||||
|
}
|
||||||
|
onLoad();
|
|
@ -0,0 +1,301 @@
|
||||||
|
var squareRotation = 0.0;
|
||||||
|
|
||||||
|
//main();
|
||||||
|
window.addEventListener("load", main);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Start here
|
||||||
|
//
|
||||||
|
function main() {
|
||||||
|
const canvas = document.querySelector('#canvas');
|
||||||
|
const gl = canvas.getContext('webgl');
|
||||||
|
|
||||||
|
// If we don't have a GL context, give up now
|
||||||
|
|
||||||
|
if (!gl) {
|
||||||
|
alert('Unable to initialize WebGL. Your browser or machine may not support it.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vertex shader program
|
||||||
|
|
||||||
|
const vsSource = `
|
||||||
|
attribute vec4 aVertexPosition;
|
||||||
|
attribute vec4 aVertexColor;
|
||||||
|
|
||||||
|
uniform mat4 uModelViewMatrix;
|
||||||
|
uniform mat4 uProjectionMatrix;
|
||||||
|
|
||||||
|
varying lowp vec4 vColor;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition;
|
||||||
|
vColor = aVertexColor;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
// Fragment shader program
|
||||||
|
|
||||||
|
const fsSource = `
|
||||||
|
varying lowp vec4 vColor;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
gl_FragColor = vColor;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
// Initialize a shader program; this is where all the lighting
|
||||||
|
// for the vertices and so forth is established.
|
||||||
|
const shaderProgram = initShaderProgram(gl, vsSource, fsSource);
|
||||||
|
|
||||||
|
// Collect all the info needed to use the shader program.
|
||||||
|
// Look up which attributes our shader program is using
|
||||||
|
// for aVertexPosition, aVevrtexColor and also
|
||||||
|
// look up uniform locations.
|
||||||
|
const programInfo = {
|
||||||
|
program: shaderProgram,
|
||||||
|
attribLocations: {
|
||||||
|
vertexPosition: gl.getAttribLocation(shaderProgram, 'aVertexPosition'),
|
||||||
|
vertexColor: gl.getAttribLocation(shaderProgram, 'aVertexColor'),
|
||||||
|
},
|
||||||
|
uniformLocations: {
|
||||||
|
projectionMatrix: gl.getUniformLocation(shaderProgram, 'uProjectionMatrix'),
|
||||||
|
modelViewMatrix: gl.getUniformLocation(shaderProgram, 'uModelViewMatrix'),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Here's where we call the routine that builds all the
|
||||||
|
// objects we'll be drawing.
|
||||||
|
const buffers = initBuffers(gl);
|
||||||
|
|
||||||
|
var then = 0;
|
||||||
|
|
||||||
|
// Draw the scene repeatedly
|
||||||
|
function render(now) {
|
||||||
|
now *= 0.001; // convert to seconds
|
||||||
|
const deltaTime = now - then;
|
||||||
|
then = now;
|
||||||
|
|
||||||
|
drawScene(gl, programInfo, buffers, deltaTime);
|
||||||
|
|
||||||
|
requestAnimationFrame(render);
|
||||||
|
}
|
||||||
|
requestAnimationFrame(render);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// initBuffers
|
||||||
|
//
|
||||||
|
// Initialize the buffers we'll need. For this demo, we just
|
||||||
|
// have one object -- a simple two-dimensional square.
|
||||||
|
//
|
||||||
|
function initBuffers(gl) {
|
||||||
|
|
||||||
|
// Create a buffer for the square's positions.
|
||||||
|
|
||||||
|
const positionBuffer = gl.createBuffer();
|
||||||
|
|
||||||
|
// Select the positionBuffer as the one to apply buffer
|
||||||
|
// operations to from here out.
|
||||||
|
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
|
||||||
|
|
||||||
|
// Now create an array of positions for the square.
|
||||||
|
|
||||||
|
const positions = [
|
||||||
|
1.0, 1.0,
|
||||||
|
-1.0, 1.0,
|
||||||
|
1.0, -1.0,
|
||||||
|
-1.0, -1.0,
|
||||||
|
];
|
||||||
|
|
||||||
|
// Now pass the list of positions into WebGL to build the
|
||||||
|
// shape. We do this by creating a Float32Array from the
|
||||||
|
// JavaScript array, then use it to fill the current buffer.
|
||||||
|
|
||||||
|
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
|
||||||
|
|
||||||
|
// Now set up the colors for the vertices
|
||||||
|
|
||||||
|
const colors = [
|
||||||
|
1.0, 0.5, 1.0, 1.0, // white
|
||||||
|
1.0, 0.6, 1.0, 1.0, // red
|
||||||
|
1.0, 0.7, 1.0, 1.0, // green
|
||||||
|
1.0, 0.3, 1.0, 1.0, // blue
|
||||||
|
];
|
||||||
|
|
||||||
|
const colorBuffer = gl.createBuffer();
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
|
||||||
|
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
|
||||||
|
|
||||||
|
return {
|
||||||
|
position: positionBuffer,
|
||||||
|
color: colorBuffer,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Draw the scene.
|
||||||
|
//
|
||||||
|
function drawScene(gl, programInfo, buffers, deltaTime) {
|
||||||
|
gl.clearColor(0.0, 0.0, 0.0, 1.0); // Clear to black, fully opaque
|
||||||
|
gl.clearDepth(1.0); // Clear everything
|
||||||
|
gl.enable(gl.DEPTH_TEST); // Enable depth testing
|
||||||
|
gl.depthFunc(gl.LEQUAL); // Near things obscure far things
|
||||||
|
|
||||||
|
// Clear the canvas before we start drawing on it.
|
||||||
|
|
||||||
|
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
// Create a perspective matrix, a special matrix that is
|
||||||
|
// used to simulate the distortion of perspective in a camera.
|
||||||
|
// Our field of view is 45 degrees, with a width/height
|
||||||
|
// ratio that matches the display size of the canvas
|
||||||
|
// and we only want to see objects between 0.1 units
|
||||||
|
// and 100 units away from the camera.
|
||||||
|
|
||||||
|
const fieldOfView = 45 * Math.PI / 180; // in radians
|
||||||
|
const aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;
|
||||||
|
const zNear = 0.1;
|
||||||
|
const zFar = 100.0;
|
||||||
|
const projectionMatrix = mat4.create();
|
||||||
|
|
||||||
|
// note: glmatrix.js always has the first argument
|
||||||
|
// as the destination to receive the result.
|
||||||
|
mat4.perspective(projectionMatrix,
|
||||||
|
fieldOfView,
|
||||||
|
aspect,
|
||||||
|
zNear,
|
||||||
|
zFar);
|
||||||
|
|
||||||
|
// Set the drawing position to the "identity" point, which is
|
||||||
|
// the center of the scene.
|
||||||
|
const modelViewMatrix = mat4.create();
|
||||||
|
|
||||||
|
// Now move the drawing position a bit to where we want to
|
||||||
|
// start drawing the square.
|
||||||
|
|
||||||
|
mat4.translate(modelViewMatrix, // destination matrix
|
||||||
|
modelViewMatrix, // matrix to translate
|
||||||
|
[-0.0, 0.0, -6.0]); // amount to translate
|
||||||
|
mat4.rotate(modelViewMatrix, // destination matrix
|
||||||
|
modelViewMatrix, // matrix to rotate
|
||||||
|
squareRotation, // amount to rotate in radians
|
||||||
|
[0, 0, 1]); // axis to rotate around
|
||||||
|
|
||||||
|
// Tell WebGL how to pull out the positions from the position
|
||||||
|
// buffer into the vertexPosition attribute
|
||||||
|
{
|
||||||
|
const numComponents = 2;
|
||||||
|
const type = gl.FLOAT;
|
||||||
|
const normalize = false;
|
||||||
|
const stride = 0;
|
||||||
|
const offset = 0;
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, buffers.position);
|
||||||
|
gl.vertexAttribPointer(
|
||||||
|
programInfo.attribLocations.vertexPosition,
|
||||||
|
numComponents,
|
||||||
|
type,
|
||||||
|
normalize,
|
||||||
|
stride,
|
||||||
|
offset);
|
||||||
|
gl.enableVertexAttribArray(
|
||||||
|
programInfo.attribLocations.vertexPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tell WebGL how to pull out the colors from the color buffer
|
||||||
|
// into the vertexColor attribute.
|
||||||
|
{
|
||||||
|
const numComponents = 4;
|
||||||
|
const type = gl.FLOAT;
|
||||||
|
const normalize = false;
|
||||||
|
const stride = 0;
|
||||||
|
const offset = 0;
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, buffers.color);
|
||||||
|
gl.vertexAttribPointer(
|
||||||
|
programInfo.attribLocations.vertexColor,
|
||||||
|
numComponents,
|
||||||
|
type,
|
||||||
|
normalize,
|
||||||
|
stride,
|
||||||
|
offset);
|
||||||
|
gl.enableVertexAttribArray(
|
||||||
|
programInfo.attribLocations.vertexColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tell WebGL to use our program when drawing
|
||||||
|
|
||||||
|
gl.useProgram(programInfo.program);
|
||||||
|
|
||||||
|
// Set the shader uniforms
|
||||||
|
|
||||||
|
gl.uniformMatrix4fv(
|
||||||
|
programInfo.uniformLocations.projectionMatrix,
|
||||||
|
false,
|
||||||
|
projectionMatrix);
|
||||||
|
gl.uniformMatrix4fv(
|
||||||
|
programInfo.uniformLocations.modelViewMatrix,
|
||||||
|
false,
|
||||||
|
modelViewMatrix);
|
||||||
|
|
||||||
|
{
|
||||||
|
const offset = 0;
|
||||||
|
const vertexCount = 4;
|
||||||
|
gl.drawArrays(gl.TRIANGLE_STRIP, offset, vertexCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the rotation for the next draw
|
||||||
|
|
||||||
|
squareRotation += deltaTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Initialize a shader program, so WebGL knows how to draw our data
|
||||||
|
//
|
||||||
|
function initShaderProgram(gl, vsSource, fsSource) {
|
||||||
|
const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource);
|
||||||
|
const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource);
|
||||||
|
|
||||||
|
// Create the shader program
|
||||||
|
|
||||||
|
const shaderProgram = gl.createProgram();
|
||||||
|
gl.attachShader(shaderProgram, vertexShader);
|
||||||
|
gl.attachShader(shaderProgram, fragmentShader);
|
||||||
|
gl.linkProgram(shaderProgram);
|
||||||
|
|
||||||
|
// If creating the shader program failed, alert
|
||||||
|
|
||||||
|
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
|
||||||
|
alert('Unable to initialize the shader program: ' + gl.getProgramInfoLog(shaderProgram));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return shaderProgram;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// creates a shader of the given type, uploads the source and
|
||||||
|
// compiles it.
|
||||||
|
//
|
||||||
|
function loadShader(gl, type, source) {
|
||||||
|
const shader = gl.createShader(type);
|
||||||
|
|
||||||
|
// Send the source to the shader object
|
||||||
|
|
||||||
|
gl.shaderSource(shader, source);
|
||||||
|
|
||||||
|
// Compile the shader program
|
||||||
|
|
||||||
|
gl.compileShader(shader);
|
||||||
|
|
||||||
|
// See if it compiled successfully
|
||||||
|
|
||||||
|
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
||||||
|
alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader));
|
||||||
|
gl.deleteShader(shader);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return shader;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,196 @@
|
||||||
|
var shader_time = 0.0;
|
||||||
|
var canvas_size = new Array(2);
|
||||||
|
|
||||||
|
window.addEventListener("load", main);
|
||||||
|
function main() {
|
||||||
|
var canvas = document.querySelector('#webgl-canvas');
|
||||||
|
const canvasses = document.querySelectorAll('.webgl-shader-canvas');
|
||||||
|
if (canvasses.length == 0) {
|
||||||
|
console.log("WebGL script requires at least one canvas with class 'webgl-shader-canvas''");
|
||||||
|
return
|
||||||
|
}
|
||||||
|
canvasses.forEach(function(canvas){
|
||||||
|
if (!canvas.getAttributeNames().includes("data-fs-source") || !canvas.getAttributeNames().includes("data-fs-source")) {
|
||||||
|
console.log("WebGL script requires a canvas with data-fs-source and data-vs-source attributes.");
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// load vertex shader
|
||||||
|
const vsxhttp = new XMLHttpRequest();
|
||||||
|
vsxhttp.onreadystatechange = function() {
|
||||||
|
if (this.readyState == 4 && this.status == 200) {
|
||||||
|
const vsSource = vsxhttp.responseText;
|
||||||
|
// load fragment shader
|
||||||
|
const fsxhttp = new XMLHttpRequest();
|
||||||
|
fsxhttp.onreadystatechange = function() {
|
||||||
|
if (this.readyState == 4 && this.status == 200) {
|
||||||
|
const fsSource = fsxhttp.responseText;
|
||||||
|
// console.log(fsSource);
|
||||||
|
// console.log(fsSource);
|
||||||
|
// Shaders loaded, begin the webgl render:
|
||||||
|
webglRender(canvas, vsSource, fsSource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fsxhttp.open('GET',canvas.getAttribute('data-fs-source'));
|
||||||
|
fsxhttp.send();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vsxhttp.open('GET',canvas.getAttribute('data-vs-source'));
|
||||||
|
vsxhttp.send();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function webglRender(canvas, vsSource, fsSource) {
|
||||||
|
const gl = canvas.getContext('webgl');
|
||||||
|
// If we don't have a GL context, give up now
|
||||||
|
if (!gl) {
|
||||||
|
alert('Unable to initialize WebGL. Your browser or machine may not support it.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
canvas_size[0] = canvas.width; canvas_size[1] = canvas.height;
|
||||||
|
const shaderProgram = initShaderProgram(gl, vsSource, fsSource);
|
||||||
|
// Collect all the info needed to use the shader program.
|
||||||
|
// Look up which attributes our shader program is using
|
||||||
|
// for aVertexPosition, aVevrtexColor and also
|
||||||
|
// look up uniform locations.
|
||||||
|
const programInfo = {
|
||||||
|
program: shaderProgram,
|
||||||
|
attribLocations: {
|
||||||
|
vertexPosition: gl.getAttribLocation(shaderProgram, 'aVertexPosition'),
|
||||||
|
},
|
||||||
|
uniformLocations: {
|
||||||
|
projectionMatrix: gl.getUniformLocation(shaderProgram, 'uProjectionMatrix'),
|
||||||
|
modelViewMatrix: gl.getUniformLocation(shaderProgram, 'uModelViewMatrix'),
|
||||||
|
uResolution: gl.getUniformLocation(shaderProgram, 'uResolution'),
|
||||||
|
uTime: gl.getUniformLocation(shaderProgram, 'uTime'),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
// Here's where we call the routine that builds all the
|
||||||
|
// objects we'll be drawing.
|
||||||
|
const buffers = initBuffers(gl);
|
||||||
|
var then = 0;
|
||||||
|
// Draw the scene repeatedly
|
||||||
|
function render(now) {
|
||||||
|
now *= 0.001; // convert to seconds
|
||||||
|
const deltaTime = now - then;
|
||||||
|
then = now;
|
||||||
|
drawScene(gl, programInfo, buffers, deltaTime);
|
||||||
|
window.requestAnimationFrame(render);
|
||||||
|
}
|
||||||
|
window.requestAnimationFrame(render);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// initBuffers
|
||||||
|
//
|
||||||
|
// Initialize the buffers we'll need. For this demo, we just
|
||||||
|
// have one object -- a simple two-dimensional square.
|
||||||
|
//
|
||||||
|
function initBuffers(gl) {
|
||||||
|
// Create a buffer for the square's positions.
|
||||||
|
const positionBuffer = gl.createBuffer();
|
||||||
|
// Select the positionBuffer as the one to apply buffer operations to from here out.
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
|
||||||
|
// Now create an array of positions for the square.
|
||||||
|
const positions = [
|
||||||
|
1.0, 1.0,
|
||||||
|
-1.0, 1.0,
|
||||||
|
1.0, -1.0,
|
||||||
|
-1.0, -1.0,
|
||||||
|
];
|
||||||
|
// Now pass the list of positions into WebGL to build the
|
||||||
|
// shape. We do this by creating a Float32Array from the
|
||||||
|
// JavaScript array, then use it to fill the current buffer.
|
||||||
|
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
|
||||||
|
return {
|
||||||
|
position: positionBuffer,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Draw the scene.
|
||||||
|
//
|
||||||
|
function drawScene(gl, programInfo, buffers, deltaTime) {
|
||||||
|
gl.clearColor(0.0, 0.0, 0.0, 1.0); // Clear to black, fully opaque
|
||||||
|
gl.clearDepth(1.0); // Clear everything
|
||||||
|
gl.enable(gl.DEPTH_TEST); // Enable depth testing
|
||||||
|
gl.depthFunc(gl.LEQUAL); // Near things obscure far things
|
||||||
|
|
||||||
|
// Clear the canvas before we start drawing on it.
|
||||||
|
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
// Create a orthographic matrix
|
||||||
|
const aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;
|
||||||
|
const zNear = 0.0;
|
||||||
|
const zFar = 100.0;
|
||||||
|
const projectionMatrix = mat4.create();
|
||||||
|
|
||||||
|
// note: glmatrix.js always has the first argument as the destination to receive the result.
|
||||||
|
mat4.ortho(projectionMatrix, -1.0, 1.0, -1.0, 1.0, zNear, zFar);
|
||||||
|
// Set the drawing position to the "identity" point, which is
|
||||||
|
// the center of the scene.
|
||||||
|
const modelViewMatrix = mat4.create();
|
||||||
|
// Tell WebGL how to pull out the positions from the position
|
||||||
|
// buffer into the vertexPosition attribute
|
||||||
|
{
|
||||||
|
const numComponents = 2;
|
||||||
|
const type = gl.FLOAT;
|
||||||
|
const normalize = false;
|
||||||
|
const stride = 0;
|
||||||
|
const offset = 0;
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, buffers.position);
|
||||||
|
gl.vertexAttribPointer(programInfo.attribLocations.vertexPosition, numComponents, type, normalize, stride, offset);
|
||||||
|
gl.enableVertexAttribArray(programInfo.attribLocations.vertexPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tell WebGL to use our program when drawing
|
||||||
|
gl.useProgram(programInfo.program);
|
||||||
|
|
||||||
|
// Set the shader uniforms
|
||||||
|
gl.uniformMatrix4fv(programInfo.uniformLocations.projectionMatrix, false, projectionMatrix);
|
||||||
|
gl.uniformMatrix4fv(programInfo.uniformLocations.modelViewMatrix, false, modelViewMatrix);
|
||||||
|
gl.uniform2f(programInfo.uniformLocations.uResolution, canvas_size[0], canvas_size[1]);
|
||||||
|
gl.uniform1f(programInfo.uniformLocations.uTime, shader_time);
|
||||||
|
{
|
||||||
|
const offset = 0;
|
||||||
|
const vertexCount = 4;
|
||||||
|
gl.drawArrays(gl.TRIANGLE_STRIP, offset, vertexCount);
|
||||||
|
}
|
||||||
|
// Update time:
|
||||||
|
shader_time += deltaTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Initialize a shader program, so WebGL knows how to draw our data
|
||||||
|
//
|
||||||
|
function initShaderProgram(gl, vsSource, fsSource) {
|
||||||
|
const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource);
|
||||||
|
const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource);
|
||||||
|
// Create the shader program
|
||||||
|
const shaderProgram = gl.createProgram();
|
||||||
|
gl.attachShader(shaderProgram, vertexShader);
|
||||||
|
gl.attachShader(shaderProgram, fragmentShader);
|
||||||
|
gl.linkProgram(shaderProgram);
|
||||||
|
// If creating the shader program failed, alert
|
||||||
|
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
|
||||||
|
alert('Unable to initialize the shader program: ' + gl.getProgramInfoLog(shaderProgram));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return shaderProgram;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// creates a shader of the given type, uploads the source and compiles it.
|
||||||
|
//
|
||||||
|
function loadShader(gl, type, source) {
|
||||||
|
const shader = gl.createShader(type);
|
||||||
|
gl.shaderSource(shader, source); // Send the source to the shader object
|
||||||
|
gl.compileShader(shader); // Compile the shader program
|
||||||
|
// See if it compiled successfully
|
||||||
|
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
||||||
|
alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader));
|
||||||
|
gl.deleteShader(shader);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return shader;
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
.sequencer-baseline {
|
||||||
|
position:relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sequencer-wrapper {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 12%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sequencer {
|
||||||
|
display: grid;
|
||||||
|
margin: 0 auto;
|
||||||
|
grid-template-columns: repeat(8, 1fr);
|
||||||
|
transform: rotate(30deg) skew(-30deg);
|
||||||
|
left: 25%;
|
||||||
|
width: 60%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sequencer-button {
|
||||||
|
-moz-appearance: none;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
transform: skew(30deg) rotate(-30deg);
|
||||||
|
background-image: asset_url("Neon_Cube_01_200209_v02-02.png");
|
||||||
|
padding-bottom: 78%;
|
||||||
|
margin: 12% -10%;
|
||||||
|
background-size: cover;
|
||||||
|
background-position: 0 100%;
|
||||||
|
&:checked {
|
||||||
|
background-position: 0 33.33%;
|
||||||
|
&.activated {
|
||||||
|
background-position: 0 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.activated {
|
||||||
|
background-position: 0 66.66%;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
@charset "utf-8";
|
||||||
|
|
||||||
|
// Define defaults for each variable.
|
||||||
|
|
||||||
|
$base-font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol" !default;
|
||||||
|
$base-font-size: 0.7rem !default;
|
||||||
|
$base-font-weight: 400 !default;
|
||||||
|
$small-font-size: $base-font-size * 0.875 !default;
|
||||||
|
$base-line-height: 1.5 !default;
|
||||||
|
|
||||||
|
$spacing-unit: 30px !default;
|
||||||
|
|
||||||
|
$text-color: #fdfdfd !default;
|
||||||
|
$background-color: #111 !default;
|
||||||
|
$brand-color: #b3b3b3 !default;
|
||||||
|
|
||||||
|
$grey-color: #b3b3b3 !default;
|
||||||
|
$grey-color-light: lighten($grey-color, 20%) !default;
|
||||||
|
$grey-color-dark: darken($grey-color, 60%) !default;
|
||||||
|
|
||||||
|
$table-text-align: left !default;
|
||||||
|
|
||||||
|
// Width of the content area
|
||||||
|
$content-width: 800px !default;
|
||||||
|
|
||||||
|
$on-palm: 600px !default;
|
||||||
|
$on-laptop: 800px !default;
|
||||||
|
|
||||||
|
// Use media queries like this:
|
||||||
|
// @include media-query($on-palm) {
|
||||||
|
// .wrapper {
|
||||||
|
// padding-right: $spacing-unit / 2;
|
||||||
|
// padding-left: $spacing-unit / 2;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
@mixin media-query($device) {
|
||||||
|
@media screen and (max-width: $device) {
|
||||||
|
@content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin relative-font-size($ratio) {
|
||||||
|
font-size: $base-font-size * $ratio;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Import partials.
|
||||||
|
@import
|
||||||
|
"theme/base",
|
||||||
|
"theme/layout",
|
||||||
|
"theme/syntax-highlighting",
|
||||||
|
"theme/typography"
|
||||||
|
;
|
|
@ -0,0 +1,258 @@
|
||||||
|
/**
|
||||||
|
* Reset some basic elements
|
||||||
|
*/
|
||||||
|
body, h1, h2, h3, h4, h5, h6,
|
||||||
|
p, blockquote, pre, hr,
|
||||||
|
dl, dd, ol, ul, figure {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basic styling
|
||||||
|
*/
|
||||||
|
body {
|
||||||
|
font: $base-font-weight #{$base-font-size}/#{$base-line-height} $base-font-family;
|
||||||
|
color: $text-color;
|
||||||
|
background-color: $background-color;
|
||||||
|
-webkit-text-size-adjust: 100%;
|
||||||
|
-webkit-font-feature-settings: "kern" 1;
|
||||||
|
-moz-font-feature-settings: "kern" 1;
|
||||||
|
-o-font-feature-settings: "kern" 1;
|
||||||
|
font-feature-settings: "kern" 1;
|
||||||
|
font-kerning: normal;
|
||||||
|
display: flex;
|
||||||
|
min-height: 100vh;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set `margin-bottom` to maintain vertical rhythm
|
||||||
|
*/
|
||||||
|
h1, h2, h3, h4, h5, h6,
|
||||||
|
p, blockquote, pre,
|
||||||
|
ul, ol, dl, figure,
|
||||||
|
%vertical-rhythm {
|
||||||
|
margin-bottom: $spacing-unit / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* `main` element
|
||||||
|
*/
|
||||||
|
main {
|
||||||
|
display: block; /* Default value of `display` of `main` element is 'inline' in IE 11. */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Images
|
||||||
|
*/
|
||||||
|
img {
|
||||||
|
max-width: 100%;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Figures
|
||||||
|
*/
|
||||||
|
figure > img {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
figcaption {
|
||||||
|
font-size: $small-font-size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lists
|
||||||
|
*/
|
||||||
|
ul, ol {
|
||||||
|
margin-left: $spacing-unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
> ul,
|
||||||
|
> ol {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Headings
|
||||||
|
*/
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
font-weight: $base-font-weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Links
|
||||||
|
*/
|
||||||
|
a {
|
||||||
|
color: $brand-color;
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
|
&:visited {
|
||||||
|
color: darken($brand-color, 10%);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: $text-color;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.social-media-list &:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
|
.username {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blockquotes
|
||||||
|
*/
|
||||||
|
blockquote {
|
||||||
|
color: $grey-color;
|
||||||
|
border-left: 4px solid $grey-color-light;
|
||||||
|
padding-left: $spacing-unit / 2;
|
||||||
|
@include relative-font-size(1.125);
|
||||||
|
letter-spacing: -1px;
|
||||||
|
font-style: italic;
|
||||||
|
|
||||||
|
> :last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Code formatting
|
||||||
|
*/
|
||||||
|
pre,
|
||||||
|
code {
|
||||||
|
@include relative-font-size(0.9375);
|
||||||
|
border: 1px solid $grey-color-light;
|
||||||
|
border-radius: 3px;
|
||||||
|
background-color: #eef;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
padding: 1px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
padding: 8px 12px;
|
||||||
|
overflow-x: auto;
|
||||||
|
|
||||||
|
> code {
|
||||||
|
border: 0;
|
||||||
|
padding-right: 0;
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper
|
||||||
|
*/
|
||||||
|
.wrapper {
|
||||||
|
max-width: -webkit-calc(#{$content-width} - (#{$spacing-unit} * 2));
|
||||||
|
max-width: calc(#{$content-width} - (#{$spacing-unit} * 2));
|
||||||
|
margin-right: auto;
|
||||||
|
margin-left: auto;
|
||||||
|
padding-right: $spacing-unit;
|
||||||
|
padding-left: $spacing-unit;
|
||||||
|
@extend %clearfix;
|
||||||
|
|
||||||
|
@include media-query($on-laptop) {
|
||||||
|
max-width: -webkit-calc(#{$content-width} - (#{$spacing-unit}));
|
||||||
|
max-width: calc(#{$content-width} - (#{$spacing-unit}));
|
||||||
|
padding-right: $spacing-unit / 2;
|
||||||
|
padding-left: $spacing-unit / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clearfix
|
||||||
|
*/
|
||||||
|
%clearfix:after {
|
||||||
|
content: "";
|
||||||
|
display: table;
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Icons
|
||||||
|
*/
|
||||||
|
|
||||||
|
.svg-icon {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
display: inline-block;
|
||||||
|
fill: #{$grey-color};
|
||||||
|
padding-right: 5px;
|
||||||
|
vertical-align: text-top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.social-media-list {
|
||||||
|
li + li {
|
||||||
|
padding-top: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tables
|
||||||
|
*/
|
||||||
|
table {
|
||||||
|
margin-bottom: $spacing-unit;
|
||||||
|
width: 100%;
|
||||||
|
text-align: $table-text-align;
|
||||||
|
color: lighten($text-color, 18%);
|
||||||
|
border-collapse: collapse;
|
||||||
|
border: 1px solid $grey-color-light;
|
||||||
|
tr {
|
||||||
|
&:nth-child(even) {
|
||||||
|
background-color: lighten($grey-color-light, 6%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
th, td {
|
||||||
|
padding: ($spacing-unit / 3) ($spacing-unit / 2);
|
||||||
|
}
|
||||||
|
th {
|
||||||
|
background-color: lighten($grey-color-light, 3%);
|
||||||
|
border: 1px solid darken($grey-color-light, 4%);
|
||||||
|
border-bottom-color: darken($grey-color-light, 12%);
|
||||||
|
}
|
||||||
|
td {
|
||||||
|
border: 1px solid $grey-color-light;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.site-nav .menu-icon > svg {
|
||||||
|
fill: #fff !important
|
||||||
|
}
|
|
@ -0,0 +1,268 @@
|
||||||
|
/**
|
||||||
|
* Site header
|
||||||
|
*/
|
||||||
|
.site-header {
|
||||||
|
border-top: 5px solid $grey-color-dark;
|
||||||
|
min-height: $spacing-unit * 1.865;
|
||||||
|
|
||||||
|
// Positioning context for the mobile navigation icon
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.site-title {
|
||||||
|
@include relative-font-size(1.625);
|
||||||
|
font-weight: 300;
|
||||||
|
line-height: $base-line-height * $base-font-size * 2.25;
|
||||||
|
letter-spacing: -1px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
float: left;
|
||||||
|
color: $text-color;
|
||||||
|
|
||||||
|
&,
|
||||||
|
&:visited {
|
||||||
|
color: $text-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.site-nav {
|
||||||
|
float: right;
|
||||||
|
line-height: $base-line-height * $base-font-size * 2.25;
|
||||||
|
|
||||||
|
.nav-trigger {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-icon {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-link {
|
||||||
|
color: $text-color;
|
||||||
|
line-height: $base-line-height;
|
||||||
|
|
||||||
|
// Gaps between nav items, but not on the last one
|
||||||
|
&:not(:last-child) {
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-query($on-palm) {
|
||||||
|
position: absolute;
|
||||||
|
top: 9px;
|
||||||
|
right: $spacing-unit / 2;
|
||||||
|
background-color: $background-color;
|
||||||
|
border: 1px solid $grey-color-light;
|
||||||
|
border-radius: 5px;
|
||||||
|
text-align: right;
|
||||||
|
|
||||||
|
label[for="nav-trigger"] {
|
||||||
|
display: block;
|
||||||
|
float: right;
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
z-index: 2;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-icon {
|
||||||
|
display: block;
|
||||||
|
float: right;
|
||||||
|
width: 36px;
|
||||||
|
height: 26px;
|
||||||
|
line-height: 0;
|
||||||
|
padding-top: 10px;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
> svg {
|
||||||
|
fill: $grey-color-dark;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input ~ .trigger {
|
||||||
|
clear: both;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
input:checked ~ .trigger {
|
||||||
|
display: block;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-link {
|
||||||
|
display: block;
|
||||||
|
padding: 5px 10px;
|
||||||
|
|
||||||
|
&:not(:last-child) {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Site footer
|
||||||
|
*/
|
||||||
|
.site-footer {
|
||||||
|
border-top: 1px solid $grey-color-dark;
|
||||||
|
padding: $spacing-unit 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-heading {
|
||||||
|
@include relative-font-size(1.125);
|
||||||
|
margin-bottom: $spacing-unit / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-list,
|
||||||
|
.social-media-list {
|
||||||
|
list-style: none;
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-col-wrapper {
|
||||||
|
@include relative-font-size(0.9375);
|
||||||
|
color: $grey-color;
|
||||||
|
margin-left: -$spacing-unit / 2;
|
||||||
|
@extend %clearfix;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-col {
|
||||||
|
float: left;
|
||||||
|
margin-bottom: $spacing-unit / 2;
|
||||||
|
padding-left: $spacing-unit / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-col-1 {
|
||||||
|
width: -webkit-calc(35% - (#{$spacing-unit} / 2));
|
||||||
|
width: calc(35% - (#{$spacing-unit} / 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-col-2 {
|
||||||
|
width: -webkit-calc(20% - (#{$spacing-unit} / 2));
|
||||||
|
width: calc(20% - (#{$spacing-unit} / 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-col-3 {
|
||||||
|
width: -webkit-calc(45% - (#{$spacing-unit} / 2));
|
||||||
|
width: calc(45% - (#{$spacing-unit} / 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-query($on-laptop) {
|
||||||
|
.footer-col-1,
|
||||||
|
.footer-col-2 {
|
||||||
|
width: -webkit-calc(50% - (#{$spacing-unit} / 2));
|
||||||
|
width: calc(50% - (#{$spacing-unit} / 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-col-3 {
|
||||||
|
width: -webkit-calc(100% - (#{$spacing-unit} / 2));
|
||||||
|
width: calc(100% - (#{$spacing-unit} / 2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-query($on-palm) {
|
||||||
|
.footer-col {
|
||||||
|
float: none;
|
||||||
|
width: -webkit-calc(100% - (#{$spacing-unit} / 2));
|
||||||
|
width: calc(100% - (#{$spacing-unit} / 2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tilde-ring {
|
||||||
|
ul {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
display: inline;
|
||||||
|
&::after {
|
||||||
|
content: " /";
|
||||||
|
color: $grey-color-dark;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page content
|
||||||
|
*/
|
||||||
|
.page-content {
|
||||||
|
padding: $spacing-unit 0;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-heading {
|
||||||
|
@include relative-font-size(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-list-heading {
|
||||||
|
margin-top: $spacing-unit * 2;
|
||||||
|
@include relative-font-size(1.75);
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-list {
|
||||||
|
margin-left: 0;
|
||||||
|
list-style: none;
|
||||||
|
|
||||||
|
> li {
|
||||||
|
margin-bottom: $spacing-unit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-meta {
|
||||||
|
font-size: $small-font-size;
|
||||||
|
color: $grey-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-link {
|
||||||
|
display: block;
|
||||||
|
@include relative-font-size(1.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Posts
|
||||||
|
*/
|
||||||
|
.post-header {
|
||||||
|
margin-bottom: $spacing-unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-title {
|
||||||
|
@include relative-font-size(2.625);
|
||||||
|
letter-spacing: -1px;
|
||||||
|
line-height: 1;
|
||||||
|
|
||||||
|
@include media-query($on-laptop) {
|
||||||
|
@include relative-font-size(2.25);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-content {
|
||||||
|
margin-bottom: $spacing-unit;
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
@include relative-font-size(2);
|
||||||
|
|
||||||
|
@include media-query($on-laptop) {
|
||||||
|
@include relative-font-size(1.75);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
@include relative-font-size(1.625);
|
||||||
|
|
||||||
|
@include media-query($on-laptop) {
|
||||||
|
@include relative-font-size(1.375);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
@include relative-font-size(1.25);
|
||||||
|
|
||||||
|
@include media-query($on-laptop) {
|
||||||
|
@include relative-font-size(1.125);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
/**
|
||||||
|
* Syntax highlighting styles
|
||||||
|
*/
|
||||||
|
.highlight {
|
||||||
|
background: #fff;
|
||||||
|
@extend %vertical-rhythm;
|
||||||
|
|
||||||
|
.highlighter-rouge & {
|
||||||
|
background: #eef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.c { color: #998; font-style: italic } // Comment
|
||||||
|
.err { color: #a61717; background-color: #e3d2d2 } // Error
|
||||||
|
.k { font-weight: bold } // Keyword
|
||||||
|
.o { font-weight: bold } // Operator
|
||||||
|
.cm { color: #998; font-style: italic } // Comment.Multiline
|
||||||
|
.cp { color: #999; font-weight: bold } // Comment.Preproc
|
||||||
|
.c1 { color: #998; font-style: italic } // Comment.Single
|
||||||
|
.cs { color: #999; font-weight: bold; font-style: italic } // Comment.Special
|
||||||
|
.gd { color: #000; background-color: #fdd } // Generic.Deleted
|
||||||
|
.gd .x { color: #000; background-color: #faa } // Generic.Deleted.Specific
|
||||||
|
.ge { font-style: italic } // Generic.Emph
|
||||||
|
.gr { color: #a00 } // Generic.Error
|
||||||
|
.gh { color: #999 } // Generic.Heading
|
||||||
|
.gi { color: #000; background-color: #dfd } // Generic.Inserted
|
||||||
|
.gi .x { color: #000; background-color: #afa } // Generic.Inserted.Specific
|
||||||
|
.go { color: #888 } // Generic.Output
|
||||||
|
.gp { color: #555 } // Generic.Prompt
|
||||||
|
.gs { font-weight: bold } // Generic.Strong
|
||||||
|
.gu { color: #aaa } // Generic.Subheading
|
||||||
|
.gt { color: #a00 } // Generic.Traceback
|
||||||
|
.kc { font-weight: bold } // Keyword.Constant
|
||||||
|
.kd { font-weight: bold } // Keyword.Declaration
|
||||||
|
.kp { font-weight: bold } // Keyword.Pseudo
|
||||||
|
.kr { font-weight: bold } // Keyword.Reserved
|
||||||
|
.kt { color: #458; font-weight: bold } // Keyword.Type
|
||||||
|
.m { color: #099 } // Literal.Number
|
||||||
|
.s { color: #d14 } // Literal.String
|
||||||
|
.na { color: #008080 } // Name.Attribute
|
||||||
|
.nb { color: #0086B3 } // Name.Builtin
|
||||||
|
.nc { color: #458; font-weight: bold } // Name.Class
|
||||||
|
.no { color: #008080 } // Name.Constant
|
||||||
|
.ni { color: #800080 } // Name.Entity
|
||||||
|
.ne { color: #900; font-weight: bold } // Name.Exception
|
||||||
|
.nf { color: #900; font-weight: bold } // Name.Function
|
||||||
|
.nn { color: #555 } // Name.Namespace
|
||||||
|
.nt { color: #000080 } // Name.Tag
|
||||||
|
.nv { color: #008080 } // Name.Variable
|
||||||
|
.ow { font-weight: bold } // Operator.Word
|
||||||
|
.w { color: #bbb } // Text.Whitespace
|
||||||
|
.mf { color: #099 } // Literal.Number.Float
|
||||||
|
.mh { color: #099 } // Literal.Number.Hex
|
||||||
|
.mi { color: #099 } // Literal.Number.Integer
|
||||||
|
.mo { color: #099 } // Literal.Number.Oct
|
||||||
|
.sb { color: #d14 } // Literal.String.Backtick
|
||||||
|
.sc { color: #d14 } // Literal.String.Char
|
||||||
|
.sd { color: #d14 } // Literal.String.Doc
|
||||||
|
.s2 { color: #d14 } // Literal.String.Double
|
||||||
|
.se { color: #d14 } // Literal.String.Escape
|
||||||
|
.sh { color: #d14 } // Literal.String.Heredoc
|
||||||
|
.si { color: #d14 } // Literal.String.Interpol
|
||||||
|
.sx { color: #d14 } // Literal.String.Other
|
||||||
|
.sr { color: #009926 } // Literal.String.Regex
|
||||||
|
.s1 { color: #d14 } // Literal.String.Single
|
||||||
|
.ss { color: #990073 } // Literal.String.Symbol
|
||||||
|
.bp { color: #999 } // Name.Builtin.Pseudo
|
||||||
|
.vc { color: #008080 } // Name.Variable.Class
|
||||||
|
.vg { color: #008080 } // Name.Variable.Global
|
||||||
|
.vi { color: #008080 } // Name.Variable.Instance
|
||||||
|
.il { color: #099 } // Literal.Number.Integer.Long
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
.post-content, .entry-content {
|
||||||
|
p,code {
|
||||||
|
font-size: $base-font-size * 2;
|
||||||
|
}
|
||||||
|
code {
|
||||||
|
color: $grey-color-dark;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,118 @@
|
||||||
|
# Welcome to Jekyll!
|
||||||
|
#
|
||||||
|
# This config file is meant for settings that affect your whole blog, values
|
||||||
|
# which you are expected to set up once and rarely edit after that. If you find
|
||||||
|
# yourself editing this file very often, consider using Jekyll's data files
|
||||||
|
# feature for the data you need to update frequently.
|
||||||
|
#
|
||||||
|
# For technical reasons, this file is *NOT* reloaded automatically when you use
|
||||||
|
# 'bundle exec jekyll serve'. If you change this file, please restart the server process.
|
||||||
|
|
||||||
|
# Site settings
|
||||||
|
# These are used to personalize your new site. If you look in the HTML files,
|
||||||
|
# you will see them accessed via {{ site.title }}, {{ site.email }}, and so on.
|
||||||
|
# You can create any custom variable you would like, and they will be accessible
|
||||||
|
# in the templates via {{ site.myvariable }}.
|
||||||
|
title: ~jahnertz
|
||||||
|
email: ~jahnertz@tilde.town
|
||||||
|
description: >- # this means to ignore newlines until "baseurl:"
|
||||||
|
Welcome to ~jahnertz
|
||||||
|
baseurl: "/~jahnertz" # the subpath of your site, e.g. /blog
|
||||||
|
url: "http://tilde.town" # the base hostname & protocol for your site, e.g. http://example.com
|
||||||
|
twitter_username: jahnertz
|
||||||
|
github_username: jahnertz
|
||||||
|
mastodon: jahnertz@mastodon.social
|
||||||
|
|
||||||
|
# Build settings
|
||||||
|
markdown: kramdown
|
||||||
|
# theme: minima
|
||||||
|
plugins:
|
||||||
|
- jekyll-feed
|
||||||
|
- jekyll-assets
|
||||||
|
|
||||||
|
# Exclude from processing.
|
||||||
|
# The following items will not be processed, by default. Create a custom list
|
||||||
|
# to override the default setting.
|
||||||
|
# exclude:
|
||||||
|
# - Gemfile
|
||||||
|
# - Gemfile.lock
|
||||||
|
# - node_modules
|
||||||
|
# - vendor/bundle/
|
||||||
|
# - vendor/cache/
|
||||||
|
# - vendor/gems/
|
||||||
|
# - vendor/ruby/
|
||||||
|
|
||||||
|
assets:
|
||||||
|
source_maps: true # false on JEKYLL_ENV=production
|
||||||
|
destination: "/assets"
|
||||||
|
compression: false # true on JEKYLL_ENV=production
|
||||||
|
gzip: false
|
||||||
|
caching:
|
||||||
|
path: ".jekyll-cache/assets"
|
||||||
|
type: file # Possible values: memory, file
|
||||||
|
enabled: true
|
||||||
|
# --
|
||||||
|
# Assets you wish to always have compiled.
|
||||||
|
# This can also be combined with raw_precompile which
|
||||||
|
# copies assets without running through the pipeline
|
||||||
|
# making them ultra fast.
|
||||||
|
# --
|
||||||
|
precompile: []
|
||||||
|
raw_precompile: []
|
||||||
|
# --
|
||||||
|
# baseurl: whether or not to append site.baseurl
|
||||||
|
# destination: the folder you store them in on the CDN.
|
||||||
|
# url: the CDN url (fqdn, or w/ identifier).
|
||||||
|
# --
|
||||||
|
cdn:
|
||||||
|
baseurl: false
|
||||||
|
destination: false
|
||||||
|
url: null
|
||||||
|
# --
|
||||||
|
# These are all default. No need to add them
|
||||||
|
# Only use this if you have more.
|
||||||
|
# --
|
||||||
|
sources:
|
||||||
|
- assets/styles
|
||||||
|
- assets/css
|
||||||
|
- assets/fonts
|
||||||
|
- assets/images
|
||||||
|
- assets/videos
|
||||||
|
- assets/javascript
|
||||||
|
- assets/video
|
||||||
|
- assets/image
|
||||||
|
- assets/img
|
||||||
|
- assets/js
|
||||||
|
- assets/audio
|
||||||
|
- assets/models
|
||||||
|
- _assets/styles
|
||||||
|
- _assets/css
|
||||||
|
- _assets/fonts
|
||||||
|
- _assets/images
|
||||||
|
- _assets/videos
|
||||||
|
- _assets/javascript
|
||||||
|
- _assets/video
|
||||||
|
- _assets/image
|
||||||
|
- _assets/img
|
||||||
|
- _assets/js
|
||||||
|
- _assets/audio
|
||||||
|
- _assets/models
|
||||||
|
- styles
|
||||||
|
- css
|
||||||
|
- fonts
|
||||||
|
- images
|
||||||
|
- videos
|
||||||
|
- javascript
|
||||||
|
- video
|
||||||
|
- image
|
||||||
|
- img
|
||||||
|
- js
|
||||||
|
- models
|
||||||
|
plugins:
|
||||||
|
css: { autoprefixer: {}}
|
||||||
|
img: { optim: {}}
|
||||||
|
autoprefixer:
|
||||||
|
browsers:
|
||||||
|
- "last 2 versions"
|
||||||
|
- "IE > 9"
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
{%- if page.comments != false and jekyll.environment == "production" -%}
|
||||||
|
|
||||||
|
<div id="disqus_thread"></div>
|
||||||
|
<script>
|
||||||
|
var disqus_config = function () {
|
||||||
|
this.page.url = '{{ page.url | absolute_url }}';
|
||||||
|
this.page.identifier = '{{ page.url | absolute_url }}';
|
||||||
|
};
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
var d = document, s = d.createElement('script');
|
||||||
|
|
||||||
|
s.src = 'https://{{ site.disqus.shortname }}.disqus.com/embed.js';
|
||||||
|
|
||||||
|
s.setAttribute('data-timestamp', +new Date());
|
||||||
|
(d.head || d.body).appendChild(s);
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
<noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript" rel="nofollow">comments powered by Disqus.</a></noscript>
|
||||||
|
{%- endif -%}
|
|
@ -0,0 +1,25 @@
|
||||||
|
<footer class="site-footer h-card">
|
||||||
|
<data class="u-url" href="{{ "/" | relative_url }}"></data>
|
||||||
|
|
||||||
|
<div class="wrapper">
|
||||||
|
|
||||||
|
<div class="footer-col-wrapper">
|
||||||
|
<div class="footer-col footer-col-1">
|
||||||
|
<ul class="contact-list">
|
||||||
|
{%- if site.email -%}
|
||||||
|
<li><a class="u-email" href="mailto:{{ site.email }}">{{ site.email }}</a></li>
|
||||||
|
{%- endif -%}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer-col footer-col-2">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer-col footer-col-3">
|
||||||
|
{%- include ring.html -%}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</footer>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<script>
|
||||||
|
if(!(window.doNotTrack === "1" || navigator.doNotTrack === "1" || navigator.doNotTrack === "yes" || navigator.msDoNotTrack === "1")) {
|
||||||
|
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||||
|
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||||
|
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||||
|
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
|
||||||
|
|
||||||
|
ga('create', '{{ site.google_analytics }}', 'auto');
|
||||||
|
ga('send', 'pageview');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>{{ site.title }}{% if page.title %} - {{ page.title }}{% endif %}</title>
|
||||||
|
{%- asset styles.css -%}
|
||||||
|
{%- feed_meta -%}
|
||||||
|
{%- if jekyll.environment == 'production' and site.google_analytics -%}
|
||||||
|
{%- include google-analytics.html -%}
|
||||||
|
{%- endif -%}
|
||||||
|
</head>
|
|
@ -0,0 +1,30 @@
|
||||||
|
<header class="site-header" role="banner">
|
||||||
|
|
||||||
|
<div class="wrapper">
|
||||||
|
{%- assign default_paths = site.pages | map: "path" -%}
|
||||||
|
{%- assign page_paths = site.header_pages | default: default_paths -%}
|
||||||
|
<a class="site-title" rel="author" href="{{ "/" | relative_url }}">{{ site.title | escape }}</a>
|
||||||
|
|
||||||
|
{%- if page_paths -%}
|
||||||
|
<nav class="site-nav">
|
||||||
|
<input type="checkbox" id="nav-trigger" class="nav-trigger" />
|
||||||
|
<label for="nav-trigger">
|
||||||
|
<span class="menu-icon">
|
||||||
|
<svg viewBox="0 0 18 15" width="18px" height="15px">
|
||||||
|
<path d="M18,1.484c0,0.82-0.665,1.484-1.484,1.484H1.484C0.665,2.969,0,2.304,0,1.484l0,0C0,0.665,0.665,0,1.484,0 h15.032C17.335,0,18,0.665,18,1.484L18,1.484z M18,7.516C18,8.335,17.335,9,16.516,9H1.484C0.665,9,0,8.335,0,7.516l0,0 c0-0.82,0.665-1.484,1.484-1.484h15.032C17.335,6.031,18,6.696,18,7.516L18,7.516z M18,13.516C18,14.335,17.335,15,16.516,15H1.484 C0.665,15,0,14.335,0,13.516l0,0c0-0.82,0.665-1.483,1.484-1.483h15.032C17.335,12.031,18,12.695,18,13.516L18,13.516z"/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div class="trigger">
|
||||||
|
{%- for path in page_paths -%}
|
||||||
|
{%- assign my_page = site.pages | where: "path", path | first -%}
|
||||||
|
{%- if my_page.title -%}
|
||||||
|
<a class="page-link" href="{{ my_page.url | relative_url }}">{{ my_page.title | escape }}</a>
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endfor -%}
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
{%- endif -%}
|
||||||
|
</div>
|
||||||
|
</header>
|
|
@ -0,0 +1 @@
|
||||||
|
<a href="https://github.com/{{ include.username }}"><span class="icon icon--github">{% include icon-github.svg %}</span><span class="username">{{ include.username }}</span></a>
|
|
@ -0,0 +1 @@
|
||||||
|
<svg viewBox="0 0 16 16" width="16px" height="16px"><path fill="#828282" d="M7.999,0.431c-4.285,0-7.76,3.474-7.76,7.761 c0,3.428,2.223,6.337,5.307,7.363c0.388,0.071,0.53-0.168,0.53-0.374c0-0.184-0.007-0.672-0.01-1.32 c-2.159,0.469-2.614-1.04-2.614-1.04c-0.353-0.896-0.862-1.135-0.862-1.135c-0.705-0.481,0.053-0.472,0.053-0.472 c0.779,0.055,1.189,0.8,1.189,0.8c0.692,1.186,1.816,0.843,2.258,0.645c0.071-0.502,0.271-0.843,0.493-1.037 C4.86,11.425,3.049,10.76,3.049,7.786c0-0.847,0.302-1.54,0.799-2.082C3.768,5.507,3.501,4.718,3.924,3.65 c0,0,0.652-0.209,2.134,0.796C6.677,4.273,7.34,4.187,8,4.184c0.659,0.003,1.323,0.089,1.943,0.261 c1.482-1.004,2.132-0.796,2.132-0.796c0.423,1.068,0.157,1.857,0.077,2.054c0.497,0.542,0.798,1.235,0.798,2.082 c0,2.981-1.814,3.637-3.543,3.829c0.279,0.24,0.527,0.713,0.527,1.437c0,1.037-0.01,1.874-0.01,2.129 c0,0.208,0.14,0.449,0.534,0.373c3.081-1.028,5.302-3.935,5.302-7.362C15.76,3.906,12.285,0.431,7.999,0.431z"/></svg>
|
After Width: | Height: | Size: 953 B |
|
@ -0,0 +1 @@
|
||||||
|
<a href="https://twitter.com/{{ include.username }}"><span class="icon icon--twitter">{% include icon-twitter.svg %}</span><span class="username">{{ include.username }}</span></a>
|
|
@ -0,0 +1 @@
|
||||||
|
<svg viewBox="0 0 16 16" width="16px" height="16px"><path fill="#828282" d="M15.969,3.058c-0.586,0.26-1.217,0.436-1.878,0.515c0.675-0.405,1.194-1.045,1.438-1.809c-0.632,0.375-1.332,0.647-2.076,0.793c-0.596-0.636-1.446-1.033-2.387-1.033c-1.806,0-3.27,1.464-3.27,3.27 c0,0.256,0.029,0.506,0.085,0.745C5.163,5.404,2.753,4.102,1.14,2.124C0.859,2.607,0.698,3.168,0.698,3.767 c0,1.134,0.577,2.135,1.455,2.722C1.616,6.472,1.112,6.325,0.671,6.08c0,0.014,0,0.027,0,0.041c0,1.584,1.127,2.906,2.623,3.206 C3.02,9.402,2.731,9.442,2.433,9.442c-0.211,0-0.416-0.021-0.615-0.059c0.416,1.299,1.624,2.245,3.055,2.271 c-1.119,0.877-2.529,1.4-4.061,1.4c-0.264,0-0.524-0.015-0.78-0.046c1.447,0.928,3.166,1.469,5.013,1.469 c6.015,0,9.304-4.983,9.304-9.304c0-0.142-0.003-0.283-0.009-0.423C14.976,4.29,15.531,3.714,15.969,3.058z"/></svg>
|
After Width: | Height: | Size: 814 B |
|
@ -0,0 +1,9 @@
|
||||||
|
<!-- Loads <model-viewer> for modern browsers: -->
|
||||||
|
<script type="module"
|
||||||
|
src="https://unpkg.com/@google/model-viewer/dist/model-viewer.js">
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- Loads <model-viewer> for old browsers like IE11: -->
|
||||||
|
<script nomodule
|
||||||
|
src="https://unpkg.com/@google/model-viewer/dist/model-viewer-legacy.js">
|
||||||
|
</script>
|
|
@ -0,0 +1 @@
|
||||||
|
<div class="entry-content">{{ content }}</div
|
|
@ -0,0 +1,7 @@
|
||||||
|
<div id="tilde_ring" class="tilde-ring" > <p><em>a member of the tilde.town ~ring</em></p> <ul>
|
||||||
|
<li><a id="tilde_town_ring" class="tilde_ring_link" href="">random ~user</a></li>
|
||||||
|
<li><a id="random_tildebox" class="tilde_ring_link" href="">random ~box</a></li>
|
||||||
|
<li><a id="tilde_town_ring_next" class="tilde_ring_link" href="">next ~user</a></li>
|
||||||
|
<li><a href="https://tilde.town/~um/tilde_ring/join.html">join</a></li>
|
||||||
|
</ul>
|
||||||
|
<script type="text/javascript"> var ringjs = document.createElement('script'); ringjs.src = document.location.protocol + '//tilde.town/~um/tilde_ring/tilde_ring.js'; document.getElementById('tilde_ring').appendChild(ringjs) </script> </div>
|
|
@ -0,0 +1,14 @@
|
||||||
|
<ul class="social-media-list">
|
||||||
|
{%- if site.dribbble_username -%}<li><a href="https://dribbble.com/{{ site.dribbble_username| cgi_escape | escape }}"><svg class="svg-icon"><use xlink:href="{{ '/assets/minima-social-icons.svg#dribbble' | relative_url }}"></use></svg> <span class="username">{{ site.dribbble_username| escape }}</span></a></li>{%- endif -%}
|
||||||
|
{%- if site.facebook_username -%}<li><a href="https://www.facebook.com/{{ site.facebook_username| cgi_escape | escape }}"><svg class="svg-icon"><use xlink:href="{{ '/assets/minima-social-icons.svg#facebook' | relative_url }}"></use></svg> <span class="username">{{ site.facebook_username| escape }}</span></a></li>{%- endif -%}
|
||||||
|
{%- if site.flickr_username -%}<li><a href="https://www.flickr.com/photos/{{ site.flickr_username| cgi_escape | escape }}"><svg class="svg-icon"><use xlink:href="{{ '/assets/minima-social-icons.svg#flickr' | relative_url }}"></use></svg> <span class="username">{{ site.flickr_username| escape }}</span></a></li>{%- endif -%}
|
||||||
|
{%- if site.github_username -%}<li><a href="https://github.com/{{ site.github_username| cgi_escape | escape }}"><svg class="svg-icon"><use xlink:href="{{ '/assets/minima-social-icons.svg#github' | relative_url }}"></use></svg> <span class="username">{{ site.github_username| escape }}</span></a></li>{%- endif -%}
|
||||||
|
{%- if site.instagram_username -%}<li><a href="https://instagram.com/{{ site.instagram_username| cgi_escape | escape }}"><svg class="svg-icon"><use xlink:href="{{ '/assets/minima-social-icons.svg#instagram' | relative_url }}"></use></svg> <span class="username">{{ site.instagram_username| escape }}</span></a></li>{%- endif -%}
|
||||||
|
{%- if site.linkedin_username -%}<li><a href="https://www.linkedin.com/in/{{ site.linkedin_username| cgi_escape | escape }}"><svg class="svg-icon"><use xlink:href="{{ '/assets/minima-social-icons.svg#linkedin' | relative_url }}"></use></svg> <span class="username">{{ site.linkedin_username| escape }}</span></a></li>{%- endif -%}
|
||||||
|
{%- if site.pinterest_username -%}<li><a href="https://www.pinterest.com/{{ site.pinterest_username| cgi_escape | escape }}"><svg class="svg-icon"><use xlink:href="{{ '/assets/minima-social-icons.svg#pinterest' | relative_url }}"></use></svg> <span class="username">{{ site.pinterest_username| escape }}</span></a></li>{%- endif -%}
|
||||||
|
{%- for mst in site.mastodon -%}{%- if mst.username and mst.instance -%}<li><a href="https://{{ mst.instance| cgi_escape | escape}}/@{{mst.username}}"><svg class="svg-icon"><use xlink:href="{{ '/assets/minima-social-icons.svg#mastodon' | relative_url }}"></use></svg> <span class="username">{{ mst.username|escape }}</span></a></li>{%- endif -%}{%- endfor -%}
|
||||||
|
{%- if site.twitter_username -%}<li><a href="https://www.twitter.com/{{ site.twitter_username| cgi_escape | escape }}"><svg class="svg-icon"><use xlink:href="{{ '/assets/minima-social-icons.svg#twitter' | relative_url }}"></use></svg> <span class="username">{{ site.twitter_username| escape }}</span></a></li>{%- endif -%}
|
||||||
|
{%- if site.youtube_username -%}<li><a href="https://youtube.com/{{ site.youtube_username| cgi_escape | escape }}"><svg class="svg-icon"><use xlink:href="{{ '/assets/minima-social-icons.svg#youtube' | relative_url }}"></use></svg> <span class="username">{{ site.youtube_username| escape }}</span></a></li>{%- endif -%}
|
||||||
|
{%- if site.googleplus_username -%}<li><a href="https://plus.google.com/{{ site.googleplus_username| escape }}"><svg class="svg-icon"><use xlink:href="{{ '/assets/minima-social-icons.svg#googleplus' | relative_url }}"></use></svg> <span class="username">{{ site.googleplus_username| escape }}</span></a></li>{%- endif -%}
|
||||||
|
{%- if site.rss -%}<li><a href="{{ 'feed.xml' | relative_url }}"><svg class="svg-icon"><use xlink:href="{{ '/assets/minima-social-icons.svg#rss' | relative_url }}"></use></svg> <span>{{ site.rss | escape }}</span></a></li>{%- endif -%}
|
||||||
|
</ul>
|
|
@ -0,0 +1,3 @@
|
||||||
|
<div class="test">
|
||||||
|
<h1>This is a test</h1>
|
||||||
|
</div>
|
|
@ -0,0 +1,22 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="{{ page.lang | default: site.lang | default: "en" }}">
|
||||||
|
|
||||||
|
{%- include head.html -%}
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
{%- include header.html -%}
|
||||||
|
|
||||||
|
<main class="page-content" aria-label="Content">
|
||||||
|
<div class="wrapper">
|
||||||
|
{{ content }}
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
{%- include footer.html -%}
|
||||||
|
{%- if jekyll.environment != "production" -%}
|
||||||
|
<script src="http://localhost:35729/livereload.js"></script>
|
||||||
|
{%- endif -%}
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
|
@ -0,0 +1,43 @@
|
||||||
|
---
|
||||||
|
layout: default
|
||||||
|
---
|
||||||
|
|
||||||
|
<div class="home">
|
||||||
|
{%- if page.title -%}
|
||||||
|
<h1 class="page-heading">{{ page.title }}</h1>
|
||||||
|
{%- endif -%}
|
||||||
|
|
||||||
|
{{ content }}
|
||||||
|
|
||||||
|
{% assign post = site.posts.first %}
|
||||||
|
<header class="post-header">
|
||||||
|
<h6 class="post-title p-name" itemprop="name headline">{{ post.title | escape }}</h1>
|
||||||
|
</header>
|
||||||
|
{% assign content = post.content %}
|
||||||
|
{% include post_detail.html %}
|
||||||
|
|
||||||
|
{%- if site.posts.size > 0 -%}
|
||||||
|
<div class="post-list-wrapper">
|
||||||
|
<h2 class="post-list-heading" >{{ page.list_title | default: "Posts" }}</h2>
|
||||||
|
<ul class="post-list">
|
||||||
|
{%- for post in site.posts -%}
|
||||||
|
<li>
|
||||||
|
{%- assign date_format = site.minima.date_format | default: "%b %-d, %Y" -%}
|
||||||
|
<span class="post-meta">{{ post.date | date: date_format }}</span>
|
||||||
|
<h3>
|
||||||
|
<a class="post-link" href="{{ post.url | relative_url }}">
|
||||||
|
{{ post.title | escape }}
|
||||||
|
</a>
|
||||||
|
</h3>
|
||||||
|
{%- if site.show_excerpts -%}
|
||||||
|
{{ post.excerpt }}
|
||||||
|
{%- endif -%}
|
||||||
|
</li>
|
||||||
|
{%- endfor -%}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="rss-subscribe">subscribe <a href="{{ "/feed.xml" | relative_url }}">via RSS</a></p>
|
||||||
|
{%- endif -%}
|
||||||
|
|
||||||
|
</div>
|
|
@ -0,0 +1,14 @@
|
||||||
|
---
|
||||||
|
layout: default
|
||||||
|
---
|
||||||
|
<article class="post">
|
||||||
|
|
||||||
|
<header class="post-header">
|
||||||
|
<h1 class="post-title">{{ page.title | escape }}</h1>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="post-content">
|
||||||
|
{{ content }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</article>
|
|
@ -0,0 +1,19 @@
|
||||||
|
---
|
||||||
|
layout: default
|
||||||
|
---
|
||||||
|
<article class="post h-entry" itemscope itemtype="http://schema.org/BlogPosting">
|
||||||
|
|
||||||
|
<header class="post-header">
|
||||||
|
<h6 class="post-title p-name" itemprop="name headline">{{ page.title | escape }}</h1>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="post-content e-content" itemprop="articleBody">
|
||||||
|
{{ content }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{%- if site.disqus.shortname -%}
|
||||||
|
{%- include disqus_comments.html -%}
|
||||||
|
{%- endif -%}
|
||||||
|
|
||||||
|
<a class="u-url" href="{{ page.url | relative_url }}" hidden></a>
|
||||||
|
</article>
|
|
@ -0,0 +1,27 @@
|
||||||
|
---
|
||||||
|
layout: default
|
||||||
|
---
|
||||||
|
<article class="post h-entry" itemscope itemtype="http://schema.org/BlogPosting">
|
||||||
|
|
||||||
|
<header class="post-header">
|
||||||
|
<h1 class="post-title p-name" itemprop="name headline">{{ page.title | escape }}</h1>
|
||||||
|
<p class="post-meta">
|
||||||
|
<time class="dt-published" datetime="{{ page.date | date_to_xmlschema }}" itemprop="datePublished">
|
||||||
|
{%- assign date_format = site.minima.date_format | default: "%b %-d, %Y" -%}
|
||||||
|
{{ page.date | date: date_format }}
|
||||||
|
</time>
|
||||||
|
{%- if page.author -%}
|
||||||
|
• <span itemprop="author" itemscope itemtype="http://schema.org/Person"><span class="p-author h-card" itemprop="name">{{ page.author }}</span></span>
|
||||||
|
{%- endif -%}</p>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="post-content e-content" itemprop="articleBody">
|
||||||
|
{{ content }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{%- if site.disqus.shortname -%}
|
||||||
|
{%- include disqus_comments.html -%}
|
||||||
|
{%- endif -%}
|
||||||
|
|
||||||
|
<a class="u-url" href="{{ page.url | relative_url }}" hidden></a>
|
||||||
|
</article>
|
|
@ -0,0 +1,37 @@
|
||||||
|
---
|
||||||
|
layout: post-plain
|
||||||
|
title: "Aquamacs - An Emacs for MacOS"
|
||||||
|
date: 2020-10-22 10:00 +0800
|
||||||
|
categories: design
|
||||||
|
---
|
||||||
|
<div style="margin-bottom: 4em">{% asset "Aquamacs_PostHeader_201117_v01-02.png"
|
||||||
|
@optim
|
||||||
|
srcset:width=900
|
||||||
|
srcset:width=500
|
||||||
|
srcset:width=300
|
||||||
|
%}</div>
|
||||||
|
|
||||||
|
> **EDIT:** Syke! I now use [emacs-mac](https://bitbucket.org/mituharu/emacs-mac) because it plays better with the tiling window manager, [Yabai](https://github.com/koekeishiya/yabai).
|
||||||
|
|
||||||
|
Emacs is great. After using the MacOS carbon version of Emacs for about a year, I've come to depend on Org-mode as a second brain. It's become the place where I store notes, plan work and track my progress toward personal goals. Why would you want to use a text editor as an organizer? I'm by no means a coder. I do however, tinker and take things apart (without intending to put them back together). Emacs feels like its built for this purpose, not like it's pushing me toward publishing code.
|
||||||
|
|
||||||
|
I came to Emacs via Vim and though the keys aren't nearly as natural, I was surprised to find that emacs editing keys are usable in most regular text editing in MacOS. After figuring out the standard bindings, the speed of all my text editing increased, not just when working in Emacs.
|
||||||
|
|
||||||
|
[Aquamacs](http://aquamacs.org/) is coming from the other direction - building in better integration with MacOS's keybindings and playing nicely with MacOS's Finder. There is, however one major issue - it is an ugly child. Aquamacs isn't so pretty out of the box. The garish toolbar and tabs can be easily hidden with `(tool-bar-mode 0)` and `(tabbar-mode 0)` in the config file, and I hastily installed the [sanityinc-tomorrow themes](https://github.com/purcell/color-theme-sanityinc-tomorrow) to sooth my burning eyes, but It's goofy gnu icon still stared into me with it's sad black eyes whenever I hit ⌘-Tab.
|
||||||
|
|
||||||
|
{% asset "Aquamacs_Dock_02_201022.png" %}
|
||||||
|
|
||||||
|
I had a few free minutes the next morning to mock up an alternative icon which sits a bit nicer next to its friends:
|
||||||
|
|
||||||
|
{% asset "Aquamacs_Dock_01_201022.png" %}
|
||||||
|
|
||||||
|
I originally planned to recreate the 'Gnu in water' icon in a cleaner style but it was easier to follow Andrew Zhilin's stylized Gnu horns. The icons are available as .png images below. How to change an application icon on mac is [explained here](https://www.howtogeek.com/677739/how-to-change-app-file-and-folder-icons-on-mac/).
|
||||||
|
|
||||||
|
<div style="display: flex;">
|
||||||
|
<a href="{% asset "Aquamacs_AltLogo_201117_v02-03.png" @path %}">{% asset "Aquamacs_AltLogo_201117_v02-03.png" %}</a>
|
||||||
|
<a href="{% asset "Aquamacs_AltLogo_201117_v02-02.png" @path %}">{% asset "Aquamacs_AltLogo_201117_v02-02.png" %}</a>
|
||||||
|
<a href="{% asset "Aquamacs_AltLogo_201117_v02-04.png" @path %}">{% asset "Aquamacs_AltLogo_201117_v02-04.png" %}</a>
|
||||||
|
<a href="{% asset "Aquamacs_AltLogo_201117_v02-01.png" @path %}">{% asset "Aquamacs_AltLogo_201117_v02-01.png" %}</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
If you're a townie or other tilde user who wants some small graphics for a project, or you want to collaborate, send me a message on irc or tilde.town email!
|
|
@ -0,0 +1,17 @@
|
||||||
|
---
|
||||||
|
layout: post-plain
|
||||||
|
title: "WebGL and Shader Experiments - Part 1"
|
||||||
|
date: 2020-12-28
|
||||||
|
categories: design coding
|
||||||
|
---
|
||||||
|
I spent a bit of time trying out WebGL today. I'd like to be able to use shaders for website elements like backgrounds because it seems like the most efficient way to get cool graphics on a screen. Shaders are some of the most elegant examples of code, able to describe complex, evolving visuals in just a few lines.
|
||||||
|
|
||||||
|
Realistically I won't be making anything really beautiful in the near future, but I'd like to understand how shaders in WebGL work. At least I will be able to pay someone more experienced to produce what I want.
|
||||||
|
|
||||||
|
The program below should show a spinning pink square and is based on Mozilla's WebGL tutorial. The shape is created using an array of points, defined before the shader programs are called.
|
||||||
|
|
||||||
|
<canvas id="canvas" width="1080" height="1080" style="border:1px solid white;
|
||||||
|
width:100%;"></canvas>
|
||||||
|
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.8.1/gl-matrix-min.js" integrity="sha512-zhHQR0/H5SEBL3Wn6yYSaTTZej12z0hVZKOv3TwCUXT1z5qeqGcXJLLrbERYRScEDDpYIJhPC1fk31gqR783iQ==" crossorigin="anonymous" defer=""></script>
|
||||||
|
{% asset shaderCanvas3.js %}
|
|
@ -0,0 +1,12 @@
|
||||||
|
---
|
||||||
|
layout: post-plain
|
||||||
|
title: "More Shaders"
|
||||||
|
date: 2021-06-02
|
||||||
|
categories: design coding
|
||||||
|
---
|
||||||
|
<canvas class="webgl-shader-canvas" width="720" height="720" style="border:1px solid white; width:100%;" data-fs-source="assets/circleShader.glsl" data-vs-source="assets/vertShader.glsl"></canvas>
|
||||||
|
|
||||||
|
<canvas class="webgl-shader-canvas" width="720" height="720" style="border:1px solid white; width:100%;" data-fs-source="assets/testShader.glsl" data-vs-source="assets/vertShader.glsl"></canvas>
|
||||||
|
|
||||||
|
{% asset gl-matrix-min-2.8.1.js %}
|
||||||
|
{% asset shaderCanvas4.js %}
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
layout: post-plain
|
||||||
|
title: "椰奶"
|
||||||
|
date: 2019-06-08 18:00 +0800
|
||||||
|
categories: toys
|
||||||
|
---
|
||||||
|
{%- include model-viewer.html -%}
|
||||||
|
<model-viewer src="{% asset CoconutCan_190608_v04.glb @path %}" alt="A coconut milk drink can" auto-rotate camera-controls background-color="#111111" style="height: 720px; width: 100%; --poster-color: #000;"></model-viewer>
|
|
@ -0,0 +1,33 @@
|
||||||
|
---
|
||||||
|
layout: post-plain
|
||||||
|
title: "Sequencer"
|
||||||
|
date: 2020-02-09 09:16 +0800
|
||||||
|
categories: toys
|
||||||
|
---
|
||||||
|
{% asset sequencer.css %}
|
||||||
|
{% asset sequencer.coffee %}
|
||||||
|
|
||||||
|
<audio>This browser does not support audio</audio>
|
||||||
|
<audio id="row1" src="{% asset CB.WAV @path %}" type="audio/wav" preload="auto"></audio>
|
||||||
|
<audio id="row2" src="{% asset CH.WAV @path %}" type="audio/wav" preload="auto"></audio>
|
||||||
|
<audio id="row3" src="{% asset CL.WAV @path %}" type="audio/wav" preload="auto"></audio>
|
||||||
|
<audio id="row4" src="{% asset CP.WAV @path %}" type="audio/wav" preload="auto"></audio>
|
||||||
|
|
||||||
|
<div class="sequencer-baseline" >
|
||||||
|
<div class="sequencer-wrapper" >
|
||||||
|
<div class="sequencer" >
|
||||||
|
{% for y in (1..4) %}
|
||||||
|
{% for x in (1..8) %}
|
||||||
|
<input class="sequencer-button" row="{{y}}" col="{{x}}" type="checkbox"/>
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% asset "Neon_Cube_01_190513_v01-01.jpg"
|
||||||
|
@optim
|
||||||
|
srcset:width=900
|
||||||
|
srcset:width=500
|
||||||
|
srcset:width=300
|
||||||
|
%}
|
||||||
|
<div style="display: none">{% asset "Neon_Cube_01_200209_v02-02.png" %}</div>
|
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
layout: page
|
||||||
|
title: About
|
||||||
|
permalink: /about/
|
||||||
|
---
|
||||||
|
|
||||||
|
{% asset jordanhan_portrait_180808_v2_white.svg %}
|
||||||
|
|
||||||
|
Welcome to my net-art playground in ~town. Message me on [Mastodon](https://mastodon.social/@jahnertz) or on IRC in [tilde.town](irc://irc.tilde.town) (#design) and [tilde.chat](irc://irc.tilde.chat) (#meta).
|
After Width: | Height: | Size: 231 KiB |
|
@ -0,0 +1,46 @@
|
||||||
|
#version 100
|
||||||
|
#define PI 3.1415926538
|
||||||
|
#define TAO 6.2831853076
|
||||||
|
#define GRID_SCALE 10.0
|
||||||
|
precision mediump float;
|
||||||
|
uniform float uTime;
|
||||||
|
uniform vec2 uResolution;
|
||||||
|
uniform vec4 uFragColor;
|
||||||
|
|
||||||
|
vec3 rgb(float r, float g, float b) {
|
||||||
|
// normalize rgb
|
||||||
|
return vec3(r/255.0, g/255.0, b/255.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 circle (vec2 uv, vec2 pos, float rad, vec3 color) {
|
||||||
|
float d = length(pos - uv) - rad;
|
||||||
|
float t = clamp(d, 0.0, 1.0);
|
||||||
|
return vec4(color, 1.0 - t);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec2 uv = gl_FragCoord.xy;
|
||||||
|
vec2 sp = gl_FragCoord.xy / uResolution.xy;
|
||||||
|
vec2 center = uResolution.xy * 0.5;
|
||||||
|
float radius = 0.25 * uResolution.y;
|
||||||
|
|
||||||
|
// vec4 layer1 = vec4(rgb(x/uResolution.x, uv.y/uResolution.y, sin(uTime)), 1.0);
|
||||||
|
//vec4 layer1 = vec4(rgb(60.0, 20.0, 60.0), 1.0);
|
||||||
|
// vec4 layer1 = vec4(uv.x / uResolution.x, uv.y / uResolution.y, 0.0, 1.0);
|
||||||
|
//vec4 layer1 = vec4(vec3(floor(mod(sp.x * 10.0, 1.0) * 2.0)) + vec3(floor(mod(sp.y * 10.0, 1.0) * 2.0)) , 1.0);
|
||||||
|
vec2 grid = floor(GRID_SCALE * uv.xy * vec2(uResolution.x/uResolution.y, 1.0) / uResolution.x);
|
||||||
|
vec4 layer1 = vec4(vec3(mod(grid.x + grid.y, 2.0)), 1.0);
|
||||||
|
|
||||||
|
vec3 red = rgb(255.0, 95.0, 60.0);
|
||||||
|
vec3 blue = rgb(60.0, 95.0, 255.0);
|
||||||
|
vec3 green = rgb(60.0, 255.0, 95.0);
|
||||||
|
vec3 white = rgb(255.0, 255.0, 255.0);
|
||||||
|
|
||||||
|
vec4 layer2 = circle(vec2(uv.x + sin(uTime) * 100.0, uv.y - cos(uTime) * 100.0), center, radius, green);
|
||||||
|
vec4 layer3 = circle(vec2(uv.x + sin(uTime * 1.1 + (0.01 * TAO)) * 100.0, uv.y - cos(uTime * 1.1 + (0.01 * TAO)) * 100.0), center, radius, blue);
|
||||||
|
vec4 layer4 = circle(vec2(uv.x + sin(uTime * 1.2 + (0.02 * TAO)) * 100.0, uv.y - cos(uTime * 1.2 + (0.02 * TAO)) * 100.0), center, radius, red);
|
||||||
|
|
||||||
|
// gl_FragColor = vec4(uv.x, uv.y, sin(uTime * 1.0), 1.0);
|
||||||
|
//gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
|
||||||
|
gl_FragColor = mix(mix(mix(layer1, layer2, layer2.a), layer3, layer3.a), layer4, layer4.a);
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
|
||||||
|
<symbol id="dribbble" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414"><path d="M8 16c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm6.747-6.905c-.234-.074-2.115-.635-4.257-.292.894 2.456 1.258 4.456 1.328 4.872 1.533-1.037 2.624-2.68 2.93-4.58zM10.67 14.3c-.102-.6-.5-2.688-1.46-5.18l-.044.014C5.312 10.477 3.93 13.15 3.806 13.4c1.158.905 2.614 1.444 4.194 1.444.947 0 1.85-.194 2.67-.543zm-7.747-1.72c.155-.266 2.03-3.37 5.555-4.51.09-.03.18-.056.27-.08-.173-.39-.36-.778-.555-1.16-3.413 1.02-6.723.977-7.023.97l-.003.208c0 1.755.665 3.358 1.756 4.57zM1.31 6.61c.307.005 3.122.017 6.318-.832-1.132-2.012-2.353-3.705-2.533-3.952-1.912.902-3.34 2.664-3.784 4.785zM6.4 1.368c.188.253 1.43 1.943 2.548 4 2.43-.91 3.46-2.293 3.582-2.468C11.323 1.827 9.736 1.176 8 1.176c-.55 0-1.087.066-1.6.19zm6.89 2.322c-.145.194-1.29 1.662-3.816 2.694.16.325.31.656.453.99.05.117.1.235.147.352 2.274-.286 4.533.172 4.758.22-.015-1.613-.59-3.094-1.543-4.257z"/></symbol>
|
||||||
|
|
||||||
|
<symbol id="facebook" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414"><path d="M15.117 0H.883C.395 0 0 .395 0 .883v14.234c0 .488.395.883.883.883h7.663V9.804H6.46V7.39h2.086V5.607c0-2.066 1.262-3.19 3.106-3.19.883 0 1.642.064 1.863.094v2.16h-1.28c-1 0-1.195.48-1.195 1.18v1.54h2.39l-.31 2.42h-2.08V16h4.077c.488 0 .883-.395.883-.883V.883C16 .395 15.605 0 15.117 0" fill-rule="nonzero"/></symbol>
|
||||||
|
|
||||||
|
<symbol id="flickr" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414"><path d="M0 8c0 2.05 1.662 3.71 3.71 3.71 2.05 0 3.713-1.66 3.713-3.71S5.76 4.29 3.71 4.29C1.663 4.29 0 5.95 0 8zm8.577 0c0 2.05 1.662 3.71 3.712 3.71C14.33 11.71 16 10.05 16 8s-1.662-3.71-3.71-3.71c-2.05 0-3.713 1.66-3.713 3.71z"/></symbol>
|
||||||
|
|
||||||
|
<symbol id="github" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414"><path d="M8 0C3.58 0 0 3.582 0 8c0 3.535 2.292 6.533 5.47 7.59.4.075.547-.172.547-.385 0-.19-.007-.693-.01-1.36-2.226.483-2.695-1.073-2.695-1.073-.364-.924-.89-1.17-.89-1.17-.725-.496.056-.486.056-.486.803.056 1.225.824 1.225.824.714 1.223 1.873.87 2.33.665.072-.517.278-.87.507-1.07-1.777-.2-3.644-.888-3.644-3.953 0-.873.31-1.587.823-2.147-.09-.202-.36-1.015.07-2.117 0 0 .67-.215 2.2.82.64-.178 1.32-.266 2-.27.68.004 1.36.092 2 .27 1.52-1.035 2.19-.82 2.19-.82.43 1.102.16 1.915.08 2.117.51.56.82 1.274.82 2.147 0 3.073-1.87 3.75-3.65 3.947.28.24.54.73.54 1.48 0 1.07-.01 1.93-.01 2.19 0 .21.14.46.55.38C13.71 14.53 16 11.53 16 8c0-4.418-3.582-8-8-8"/></symbol>
|
||||||
|
|
||||||
|
<symbol id="googleplus" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414"><path d="M5.09 7.273v1.745h2.89c-.116.75-.873 2.197-2.887 2.197-1.737 0-3.155-1.44-3.155-3.215S3.353 4.785 5.09 4.785c.99 0 1.652.422 2.03.786l1.382-1.33c-.887-.83-2.037-1.33-3.41-1.33C2.275 2.91 0 5.19 0 8s2.276 5.09 5.09 5.09c2.94 0 4.888-2.065 4.888-4.974 0-.334-.036-.59-.08-.843H5.09zm10.91 0h-1.455V5.818H13.09v1.455h-1.454v1.454h1.455v1.455h1.46V8.727H16"/></symbol>
|
||||||
|
|
||||||
|
<symbol id="instagram" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414"><path d="M8 0C5.827 0 5.555.01 4.702.048 3.85.088 3.27.222 2.76.42c-.526.204-.973.478-1.417.923-.445.444-.72.89-.923 1.417-.198.51-.333 1.09-.372 1.942C.008 5.555 0 5.827 0 8s.01 2.445.048 3.298c.04.852.174 1.433.372 1.942.204.526.478.973.923 1.417.444.445.89.72 1.417.923.51.198 1.09.333 1.942.372.853.04 1.125.048 3.298.048s2.445-.01 3.298-.048c.852-.04 1.433-.174 1.942-.372.526-.204.973-.478 1.417-.923.445-.444.72-.89.923-1.417.198-.51.333-1.09.372-1.942.04-.853.048-1.125.048-3.298s-.01-2.445-.048-3.298c-.04-.852-.174-1.433-.372-1.942-.204-.526-.478-.973-.923-1.417-.444-.445-.89-.72-1.417-.923-.51-.198-1.09-.333-1.942-.372C10.445.008 10.173 0 8 0zm0 1.44c2.136 0 2.39.01 3.233.048.78.036 1.203.166 1.485.276.374.145.64.318.92.598.28.28.453.546.598.92.11.282.24.705.276 1.485.038.844.047 1.097.047 3.233s-.01 2.39-.05 3.233c-.04.78-.17 1.203-.28 1.485-.15.374-.32.64-.6.92-.28.28-.55.453-.92.598-.28.11-.71.24-1.49.276-.85.038-1.1.047-3.24.047s-2.39-.01-3.24-.05c-.78-.04-1.21-.17-1.49-.28-.38-.15-.64-.32-.92-.6-.28-.28-.46-.55-.6-.92-.11-.28-.24-.71-.28-1.49-.03-.84-.04-1.1-.04-3.23s.01-2.39.04-3.24c.04-.78.17-1.21.28-1.49.14-.38.32-.64.6-.92.28-.28.54-.46.92-.6.28-.11.7-.24 1.48-.28.85-.03 1.1-.04 3.24-.04zm0 2.452c-2.27 0-4.108 1.84-4.108 4.108 0 2.27 1.84 4.108 4.108 4.108 2.27 0 4.108-1.84 4.108-4.108 0-2.27-1.84-4.108-4.108-4.108zm0 6.775c-1.473 0-2.667-1.194-2.667-2.667 0-1.473 1.194-2.667 2.667-2.667 1.473 0 2.667 1.194 2.667 2.667 0 1.473-1.194 2.667-2.667 2.667zm5.23-6.937c0 .53-.43.96-.96.96s-.96-.43-.96-.96.43-.96.96-.96.96.43.96.96z"/></symbol>
|
||||||
|
|
||||||
|
<symbol id="linkedin" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414"><path d="M13.632 13.635h-2.37V9.922c0-.886-.018-2.025-1.234-2.025-1.235 0-1.424.964-1.424 1.96v3.778h-2.37V6H8.51v1.04h.03c.318-.6 1.092-1.233 2.247-1.233 2.4 0 2.845 1.58 2.845 3.637v4.188zM3.558 4.955c-.762 0-1.376-.617-1.376-1.377 0-.758.614-1.375 1.376-1.375.76 0 1.376.617 1.376 1.375 0 .76-.617 1.377-1.376 1.377zm1.188 8.68H2.37V6h2.376v7.635zM14.816 0H1.18C.528 0 0 .516 0 1.153v13.694C0 15.484.528 16 1.18 16h13.635c.652 0 1.185-.516 1.185-1.153V1.153C16 .516 15.467 0 14.815 0z" fill-rule="nonzero"/></symbol>
|
||||||
|
|
||||||
|
<symbol id="pinterest" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414"><path d="M8 0C3.582 0 0 3.582 0 8c0 3.39 2.108 6.285 5.084 7.45-.07-.633-.133-1.604.028-2.295.146-.625.938-3.977.938-3.977s-.24-.48-.24-1.188c0-1.11.646-1.943 1.448-1.943.683 0 1.012.513 1.012 1.127 0 .687-.436 1.713-.662 2.664-.19.797.4 1.445 1.185 1.445 1.42 0 2.514-1.498 2.514-3.662 0-1.91-1.376-3.25-3.342-3.25-2.276 0-3.61 1.71-3.61 3.47 0 .69.263 1.43.593 1.83.066.08.075.15.057.23-.06.25-.196.8-.223.91-.035.15-.115.18-.268.11C3.516 10.46 2.89 9 2.89 7.82c0-2.52 1.834-4.84 5.287-4.84 2.774 0 4.932 1.98 4.932 4.62 0 2.76-1.74 4.98-4.16 4.98-.81 0-1.57-.42-1.84-.92l-.5 1.9c-.18.698-.67 1.57-1 2.1.75.23 1.54.357 2.37.357 4.41 0 8-3.58 8-8s-3.59-8-8-8z" fill-rule="nonzero"/></symbol>
|
||||||
|
|
||||||
|
<symbol id="rss" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414"><path d="M12.8 16C12.8 8.978 7.022 3.2 0 3.2V0c8.777 0 16 7.223 16 16h-3.2zM2.194 11.61c1.21 0 2.195.985 2.195 2.196 0 1.21-.99 2.194-2.2 2.194C.98 16 0 15.017 0 13.806c0-1.21.983-2.195 2.194-2.195zM10.606 16h-3.11c0-4.113-3.383-7.497-7.496-7.497v-3.11c5.818 0 10.606 4.79 10.606 10.607z"/></symbol>
|
||||||
|
|
||||||
|
<symbol id="stackoverflow" class="svg-icon" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414"><path d="M12.658 14.577v-4.27h1.423V16H1.23v-5.693h1.42v4.27h10.006zm-8.583-1.423h7.16V11.73h-7.16v1.424zm.173-3.235l6.987 1.46.3-1.38L4.55 8.54l-.302 1.38zm.906-3.37l6.47 3.02.602-1.3-6.47-3.02-.602 1.29zm1.81-3.19l5.478 4.57.906-1.08L7.87 2.28l-.9 1.078zM10.502 0L9.338.863l4.27 5.735 1.164-.862L10.5 0z"/></symbol>
|
||||||
|
|
||||||
|
<symbol id="twitter" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414"><path d="M16 3.038c-.59.26-1.22.437-1.885.517.677-.407 1.198-1.05 1.443-1.816-.634.37-1.337.64-2.085.79-.598-.64-1.45-1.04-2.396-1.04-1.812 0-3.282 1.47-3.282 3.28 0 .26.03.51.085.75-2.728-.13-5.147-1.44-6.766-3.42C.83 2.58.67 3.14.67 3.75c0 1.14.58 2.143 1.46 2.732-.538-.017-1.045-.165-1.487-.41v.04c0 1.59 1.13 2.918 2.633 3.22-.276.074-.566.114-.865.114-.21 0-.41-.02-.61-.058.42 1.304 1.63 2.253 3.07 2.28-1.12.88-2.54 1.404-4.07 1.404-.26 0-.52-.015-.78-.045 1.46.93 3.18 1.474 5.04 1.474 6.04 0 9.34-5 9.34-9.33 0-.14 0-.28-.01-.42.64-.46 1.2-1.04 1.64-1.7z" fill-rule="nonzero"/></symbol>
|
||||||
|
|
||||||
|
<symbol id="youtube" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414"><path d="M0 7.345c0-1.294.16-2.59.16-2.59s.156-1.1.636-1.587c.608-.637 1.408-.617 1.764-.684C3.84 2.36 8 2.324 8 2.324s3.362.004 5.6.166c.314.038.996.04 1.604.678.48.486.636 1.588.636 1.588S16 6.05 16 7.346v1.258c0 1.296-.16 2.59-.16 2.59s-.156 1.102-.636 1.588c-.608.638-1.29.64-1.604.678-2.238.162-5.6.166-5.6.166s-4.16-.037-5.44-.16c-.356-.067-1.156-.047-1.764-.684-.48-.487-.636-1.587-.636-1.587S0 9.9 0 8.605v-1.26zm6.348 2.73V5.58l4.323 2.255-4.32 2.24z"/></symbol>
|
||||||
|
|
||||||
|
<symbol id="mastodon" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414">
|
||||||
|
<path transform="scale(0.07)" d="M211.80734 139.0875c-3.18125 16.36625-28.4925 34.2775-57.5625 37.74875-15.15875 1.80875-30.08375 3.47125-45.99875 2.74125-26.0275-1.1925-46.565-6.2125-46.565-6.2125 0 2.53375.15625 4.94625.46875 7.2025 3.38375 25.68625 25.47 27.225 46.39125 27.9425 21.11625.7225 39.91875-5.20625 39.91875-5.20625l.8675 19.09s-14.77 7.93125-41.08125 9.39c-14.50875.7975-32.52375-.365-53.50625-5.91875C9.23234 213.82 1.40609 165.31125.20859 116.09125c-.365-14.61375-.14-28.39375-.14-39.91875 0-50.33 32.97625-65.0825 32.97625-65.0825C49.67234 3.45375 78.20359.2425 107.86484 0h.72875c29.66125.2425 58.21125 3.45375 74.8375 11.09 0 0 32.975 14.7525 32.975 65.0825 0 0 .41375 37.13375-4.59875 62.915"/>
|
||||||
|
<path transform="scale(0.07)" fill="#FFF" d="M177.50984 80.077v60.94125h-24.14375v-59.15c0-12.46875-5.24625-18.7975-15.74-18.7975-11.6025 0-17.4175 7.5075-17.4175 22.3525v32.37625H96.20734V85.42325c0-14.845-5.81625-22.3525-17.41875-22.3525-10.49375 0-15.74 6.32875-15.74 18.7975v59.15H38.90484V80.077c0-12.455 3.17125-22.3525 9.54125-29.675 6.56875-7.3225 15.17125-11.07625 25.85-11.07625 12.355 0 21.71125 4.74875 27.8975 14.2475l6.01375 10.08125 6.015-10.08125c6.185-9.49875 15.54125-14.2475 27.8975-14.2475 10.6775 0 19.28 3.75375 25.85 11.07625 6.36875 7.3225 9.54 17.22 9.54 29.675"/>
|
||||||
|
</symbol>
|
||||||
|
|
||||||
|
|
||||||
|
</svg>
|
After Width: | Height: | Size: 9.7 KiB |
|
@ -0,0 +1,3 @@
|
||||||
|
void main(void) {
|
||||||
|
gl_FragColor = vec4(0.5, 0.3, 0.0, 1.0);
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
#version 100
|
||||||
|
precision mediump float;
|
||||||
|
uniform float uTime;
|
||||||
|
uniform vec2 uResolution;
|
||||||
|
uniform vec4 uFragColor;
|
||||||
|
void main() {
|
||||||
|
vec2 uv = gl_FragCoord.xy / uResolution.xy;
|
||||||
|
gl_FragColor = vec4(uv.x, uv.y, sin(uTime * 1.0), 1.0);
|
||||||
|
//gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
#version 100
|
||||||
|
precision highp float;
|
||||||
|
attribute vec4 aVertexPosition;
|
||||||
|
uniform mat4 uModelViewMatrix;
|
||||||
|
uniform mat4 uProjectionMatrix;
|
||||||
|
void main(void) {
|
||||||
|
gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition;
|
||||||
|
}
|