WIP
This commit is contained in:
parent
a2522e3845
commit
208565603e
|
@ -12,6 +12,7 @@
|
||||||
/demo/client/package-lock.json
|
/demo/client/package-lock.json
|
||||||
/demo/server/target
|
/demo/server/target
|
||||||
/demo/server/Rocket.toml
|
/demo/server/Rocket.toml
|
||||||
|
/demo2/dist
|
||||||
.DS_Store
|
.DS_Store
|
||||||
target
|
target
|
||||||
node_modules
|
node_modules
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
#version 300 es
|
||||||
|
|
||||||
|
// pathfinder/demo2/cover.fs.glsl
|
||||||
|
//
|
||||||
|
// Copyright © 2018 The Pathfinder Project Developers.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
precision highp float;
|
||||||
|
|
||||||
|
out vec4 oFragColor;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
oFragColor = vec4(0.0, 0.0, 1.0, 1.0);
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
#version 300 es
|
||||||
|
|
||||||
|
// pathfinder/demo2/cover.vs.glsl
|
||||||
|
//
|
||||||
|
// Copyright © 2018 The Pathfinder Project Developers.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
precision highp float;
|
||||||
|
|
||||||
|
uniform vec2 uFramebufferSize;
|
||||||
|
uniform vec2 uTileSize;
|
||||||
|
|
||||||
|
in vec2 aTessCoord;
|
||||||
|
in vec2 aTileOrigin;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec2 position = aTileOrigin + uTileSize * aTessCoord;
|
||||||
|
gl_Position = vec4(position / uFramebufferSize * 2.0 - 1.0, 0.0, 1.0);
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
declare module "*.glsl";
|
||||||
|
declare module "*.jpg";
|
||||||
|
declare module "*.svg";
|
||||||
|
|
||||||
|
declare function require(s: string): any;
|
|
@ -0,0 +1,295 @@
|
||||||
|
{
|
||||||
|
"requires": true,
|
||||||
|
"lockfileVersion": 1,
|
||||||
|
"dependencies": {
|
||||||
|
"@choojs/findup": {
|
||||||
|
"version": "0.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@choojs/findup/-/findup-0.2.1.tgz",
|
||||||
|
"integrity": "sha512-YstAqNb0MCN8PjdLCDfRsBcGVRN41f3vgLvaI0IrIcBp4AqILRSS0DeWNGkicC+f/zRIPJLc+9RURVSepwvfBw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"commander": "2.19.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@types/webgl2": {
|
||||||
|
"version": "0.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/webgl2/-/webgl2-0.0.4.tgz",
|
||||||
|
"integrity": "sha512-PACt1xdErJbMUOUweSrbVM7gSIYm1vTncW2hF6Os/EeWi6TXYAYMPp+8v6rzHmypE5gHrxaxZNXgMkJVIdZpHw=="
|
||||||
|
},
|
||||||
|
"commander": {
|
||||||
|
"version": "2.19.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz",
|
||||||
|
"integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"core-util-is": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||||
|
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"events": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "http://registry.npmjs.org/events/-/events-1.1.1.tgz",
|
||||||
|
"integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"glsl-inject-defines": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/glsl-inject-defines/-/glsl-inject-defines-1.0.3.tgz",
|
||||||
|
"integrity": "sha1-3RqswsF/yyvT/DJBHGYz0Ne2D9Q=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"glsl-token-inject-block": "1.1.0",
|
||||||
|
"glsl-token-string": "1.0.1",
|
||||||
|
"glsl-tokenizer": "2.1.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"glsl-resolve": {
|
||||||
|
"version": "0.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/glsl-resolve/-/glsl-resolve-0.0.1.tgz",
|
||||||
|
"integrity": "sha1-iUvvc5ENeSyBtRQxgANdCnivdtM=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"resolve": "0.6.3",
|
||||||
|
"xtend": "2.2.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"resolve": {
|
||||||
|
"version": "0.6.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/resolve/-/resolve-0.6.3.tgz",
|
||||||
|
"integrity": "sha1-3ZV5gufnNt699TtYpN2RdUV13UY=",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"glsl-token-assignments": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "http://registry.npmjs.org/glsl-token-assignments/-/glsl-token-assignments-2.0.2.tgz",
|
||||||
|
"integrity": "sha1-pdgqt4SZwuimuDy2lJXm5mXOAZ8=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"glsl-token-defines": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "http://registry.npmjs.org/glsl-token-defines/-/glsl-token-defines-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-y4kqqVmTYjFyhHDU90AySJaX+p0=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"glsl-tokenizer": "2.1.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"glsl-token-depth": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "http://registry.npmjs.org/glsl-token-depth/-/glsl-token-depth-1.1.2.tgz",
|
||||||
|
"integrity": "sha1-I8XjDuK9JViEtKKLyFC495HpXYQ=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"glsl-token-descope": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "http://registry.npmjs.org/glsl-token-descope/-/glsl-token-descope-1.0.2.tgz",
|
||||||
|
"integrity": "sha1-D8kKsyYYa4L1l7LnfcniHvzTIHY=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"glsl-token-assignments": "2.0.2",
|
||||||
|
"glsl-token-depth": "1.1.2",
|
||||||
|
"glsl-token-properties": "1.0.1",
|
||||||
|
"glsl-token-scope": "1.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"glsl-token-inject-block": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/glsl-token-inject-block/-/glsl-token-inject-block-1.1.0.tgz",
|
||||||
|
"integrity": "sha1-4QFfWYDBCRgkraomJfHf3ovQADQ=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"glsl-token-properties": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "http://registry.npmjs.org/glsl-token-properties/-/glsl-token-properties-1.0.1.tgz",
|
||||||
|
"integrity": "sha1-SD3D2Dnw1LXGFx0VkfJJvlPCip4=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"glsl-token-scope": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "http://registry.npmjs.org/glsl-token-scope/-/glsl-token-scope-1.1.2.tgz",
|
||||||
|
"integrity": "sha1-oXKOeN8kRE+cuT/RjvD3VQOmQ7E=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"glsl-token-string": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "http://registry.npmjs.org/glsl-token-string/-/glsl-token-string-1.0.1.tgz",
|
||||||
|
"integrity": "sha1-WUQdL4V958NEnJRWZgIezjWOSOw=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"glsl-token-whitespace-trim": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "http://registry.npmjs.org/glsl-token-whitespace-trim/-/glsl-token-whitespace-trim-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-RtHf6Yx1vX1QTAXX0RsbPpzJOxA=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"glsl-tokenizer": {
|
||||||
|
"version": "2.1.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/glsl-tokenizer/-/glsl-tokenizer-2.1.5.tgz",
|
||||||
|
"integrity": "sha512-XSZEJ/i4dmz3Pmbnpsy3cKh7cotvFlBiZnDOwnj/05EwNp2XrhQ4XKJxT7/pDt4kp4YcpRSKz8eTV7S+mwV6MA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"through2": "0.6.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"glslify-bundle": {
|
||||||
|
"version": "5.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/glslify-bundle/-/glslify-bundle-5.1.1.tgz",
|
||||||
|
"integrity": "sha512-plaAOQPv62M1r3OsWf2UbjN0hUYAB7Aph5bfH58VxJZJhloRNbxOL9tl/7H71K7OLJoSJ2ZqWOKk3ttQ6wy24A==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"glsl-inject-defines": "1.0.3",
|
||||||
|
"glsl-token-defines": "1.0.0",
|
||||||
|
"glsl-token-depth": "1.1.2",
|
||||||
|
"glsl-token-descope": "1.0.2",
|
||||||
|
"glsl-token-scope": "1.1.2",
|
||||||
|
"glsl-token-string": "1.0.1",
|
||||||
|
"glsl-token-whitespace-trim": "1.0.0",
|
||||||
|
"glsl-tokenizer": "2.1.5",
|
||||||
|
"murmurhash-js": "1.0.0",
|
||||||
|
"shallow-copy": "0.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"glslify-deps": {
|
||||||
|
"version": "1.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/glslify-deps/-/glslify-deps-1.3.1.tgz",
|
||||||
|
"integrity": "sha512-Ogm179MCazwIRyEqs3g3EOY4Y3XIAa0yl8J5RE9rJC6QH1w8weVOp2RZu0mvnYy/2xIas1w166YR2eZdDkWQxg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@choojs/findup": "0.2.1",
|
||||||
|
"events": "1.1.1",
|
||||||
|
"glsl-resolve": "0.0.1",
|
||||||
|
"glsl-tokenizer": "2.1.5",
|
||||||
|
"graceful-fs": "4.1.15",
|
||||||
|
"inherits": "2.0.3",
|
||||||
|
"map-limit": "0.0.1",
|
||||||
|
"resolve": "1.8.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"graceful-fs": {
|
||||||
|
"version": "4.1.15",
|
||||||
|
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz",
|
||||||
|
"integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"inherits": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||||
|
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"isarray": {
|
||||||
|
"version": "0.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
|
||||||
|
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"map-limit": {
|
||||||
|
"version": "0.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/map-limit/-/map-limit-0.0.1.tgz",
|
||||||
|
"integrity": "sha1-63lhAxwPDo0AG/LVb6toXViCLzg=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"once": "1.3.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"murmurhash-js": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/murmurhash-js/-/murmurhash-js-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-sGJ44h/Gw3+lMTcysEEry2rhX1E=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"once": {
|
||||||
|
"version": "1.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz",
|
||||||
|
"integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"wrappy": "1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"path-parse": {
|
||||||
|
"version": "1.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
|
||||||
|
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"readable-stream": {
|
||||||
|
"version": "1.0.34",
|
||||||
|
"resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
|
||||||
|
"integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"core-util-is": "1.0.2",
|
||||||
|
"inherits": "2.0.3",
|
||||||
|
"isarray": "0.0.1",
|
||||||
|
"string_decoder": "0.10.31"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"resolve": {
|
||||||
|
"version": "1.8.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz",
|
||||||
|
"integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"path-parse": "1.0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"shallow-copy": {
|
||||||
|
"version": "0.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/shallow-copy/-/shallow-copy-0.0.1.tgz",
|
||||||
|
"integrity": "sha1-QV9CcC1z2BAzApLMXuhurhoRoXA=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"string_decoder": {
|
||||||
|
"version": "0.10.31",
|
||||||
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
|
||||||
|
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"svgpath": {
|
||||||
|
"version": "2.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/svgpath/-/svgpath-2.2.1.tgz",
|
||||||
|
"integrity": "sha1-CDS7Z8iadkcrK9BswQH6e1F7Iiw="
|
||||||
|
},
|
||||||
|
"through2": {
|
||||||
|
"version": "0.6.5",
|
||||||
|
"resolved": "http://registry.npmjs.org/through2/-/through2-0.6.5.tgz",
|
||||||
|
"integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"readable-stream": "1.0.34",
|
||||||
|
"xtend": "4.0.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"xtend": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
|
||||||
|
"integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"typescript": {
|
||||||
|
"version": "3.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.1.6.tgz",
|
||||||
|
"integrity": "sha512-tDMYfVtvpb96msS1lDX9MEdHrW4yOuZ4Kdc4Him9oU796XldPYF/t2+uKoX0BBa0hXXwDlqYQbXY5Rzjzc5hBA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"wrappy": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
|
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"xtend": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/xtend/-/xtend-2.2.0.tgz",
|
||||||
|
"integrity": "sha1-7vax8ZjByN6vrYsXZaBNrUoBxak=",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"devDependencies": {
|
||||||
|
"glslify-bundle": "^5.1.1",
|
||||||
|
"glslify-deps": "^1.3.1",
|
||||||
|
"typescript": "^3.1.6"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@types/webgl2": "0.0.4",
|
||||||
|
"svgpath": "^2.2.1"
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,3 +1,7 @@
|
||||||
|
html, body {
|
||||||
|
background: #e0e0e0;
|
||||||
|
}
|
||||||
|
|
||||||
.tile {
|
.tile {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
|
|
@ -8,14 +8,23 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
import COVER_VERTEX_SHADER_SOURCE from "./cover.vs.glsl";
|
||||||
|
import COVER_FRAGMENT_SHADER_SOURCE from "./cover.fs.glsl";
|
||||||
import SVG from "../resources/svg/Ghostscript_Tiger.svg";
|
import SVG from "../resources/svg/Ghostscript_Tiger.svg";
|
||||||
|
|
||||||
const SVGPath = require('svgpath');
|
const SVGPath = require('svgpath');
|
||||||
|
|
||||||
|
const SVG_NS: string = "http://www.w3.org/2000/svg";
|
||||||
|
|
||||||
const TILE_SIZE: number = 16.0;
|
const TILE_SIZE: number = 16.0;
|
||||||
const GLOBAL_OFFSET: Point2D = {x: 400.0, y: 200.0};
|
const GLOBAL_OFFSET: Point2D = {x: 400.0, y: 200.0};
|
||||||
|
|
||||||
const SVG_NS: string = "http://www.w3.org/2000/svg";
|
const QUAD_VERTEX_POSITIONS: Uint8Array = new Uint8Array([
|
||||||
|
0, 0,
|
||||||
|
1, 0,
|
||||||
|
0, 1,
|
||||||
|
1, 1,
|
||||||
|
]);
|
||||||
|
|
||||||
type Point2D = {x: number, y: number};
|
type Point2D = {x: number, y: number};
|
||||||
type Size2D = {width: number, height: number};
|
type Size2D = {width: number, height: number};
|
||||||
|
@ -27,13 +36,109 @@ type Edge = 'left' | 'top' | 'right' | 'bottom';
|
||||||
type SVGPath = any;
|
type SVGPath = any;
|
||||||
|
|
||||||
class App {
|
class App {
|
||||||
|
private canvas: HTMLCanvasElement;
|
||||||
private svg: XMLDocument;
|
private svg: XMLDocument;
|
||||||
|
|
||||||
|
private gl: WebGL2RenderingContext;
|
||||||
|
private coverProgram: Program<'FramebufferSize' | 'TileSize', 'TessCoord' | 'TileOrigin'>;
|
||||||
|
private quadVertexBuffer: WebGLBuffer;
|
||||||
|
private coverVertexBuffer: WebGLBuffer;
|
||||||
|
private coverVertexArray: WebGLVertexArrayObject;
|
||||||
|
|
||||||
constructor(svg: XMLDocument) {
|
constructor(svg: XMLDocument) {
|
||||||
|
this.canvas = staticCast(document.getElementById('canvas'), HTMLCanvasElement);
|
||||||
this.svg = svg;
|
this.svg = svg;
|
||||||
|
|
||||||
|
const gl = unwrapNull(this.canvas.getContext('webgl2'));
|
||||||
|
this.gl = gl;
|
||||||
|
|
||||||
|
const coverProgram = new Program(gl,
|
||||||
|
COVER_VERTEX_SHADER_SOURCE,
|
||||||
|
COVER_FRAGMENT_SHADER_SOURCE,
|
||||||
|
['FramebufferSize', 'TileSize'],
|
||||||
|
['TessCoord', 'TileOrigin']);
|
||||||
|
this.coverProgram = coverProgram;
|
||||||
|
|
||||||
|
this.quadVertexBuffer = unwrapNull(gl.createBuffer());
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, this.quadVertexBuffer);
|
||||||
|
gl.bufferData(gl.ARRAY_BUFFER, QUAD_VERTEX_POSITIONS, gl.STATIC_DRAW);
|
||||||
|
|
||||||
|
this.coverVertexBuffer = unwrapNull(gl.createBuffer());
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, this.coverVertexBuffer);
|
||||||
|
|
||||||
|
// Initialize cover VAO.
|
||||||
|
this.coverVertexArray = unwrapNull(gl.createVertexArray());
|
||||||
|
gl.bindVertexArray(this.coverVertexArray);
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, this.quadVertexBuffer);
|
||||||
|
gl.vertexAttribPointer(coverProgram.attributes.TessCoord,
|
||||||
|
2,
|
||||||
|
gl.UNSIGNED_BYTE,
|
||||||
|
false,
|
||||||
|
0,
|
||||||
|
0);
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, this.coverVertexBuffer);
|
||||||
|
gl.vertexAttribPointer(coverProgram.attributes.TileOrigin, 2, gl.SHORT, false, 0, 0);
|
||||||
|
gl.vertexAttribDivisor(coverProgram.attributes.TileOrigin, 1);
|
||||||
|
gl.enableVertexAttribArray(coverProgram.attributes.TessCoord);
|
||||||
|
gl.enableVertexAttribArray(coverProgram.attributes.TileOrigin);
|
||||||
|
|
||||||
|
// TODO(pcwalton)
|
||||||
}
|
}
|
||||||
|
|
||||||
run(): void {
|
run(): void {
|
||||||
|
const gl = this.gl, canvas = this.canvas;
|
||||||
|
|
||||||
|
const tiles = this.createTiles();
|
||||||
|
|
||||||
|
const coverVertexBufferData = new Int16Array(tiles.length * 2);
|
||||||
|
for (let tileIndex = 0; tileIndex < tiles.length; tileIndex++) {
|
||||||
|
coverVertexBufferData[tileIndex * 2 + 0] = Math.floor(tiles[tileIndex].origin.x);
|
||||||
|
coverVertexBufferData[tileIndex * 2 + 1] = Math.floor(tiles[tileIndex].origin.y);
|
||||||
|
}
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, this.coverVertexBuffer);
|
||||||
|
gl.bufferData(gl.ARRAY_BUFFER, coverVertexBufferData, gl.DYNAMIC_DRAW);
|
||||||
|
console.log(coverVertexBufferData);
|
||||||
|
|
||||||
|
const framebufferSize = {width: canvas.width, height: canvas.height};
|
||||||
|
gl.viewport(0, 0, framebufferSize.width, framebufferSize.height);
|
||||||
|
gl.clearColor(1.0, 1.0, 1.0, 1.0);
|
||||||
|
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
gl.bindVertexArray(this.coverVertexArray);
|
||||||
|
gl.useProgram(this.coverProgram.program);
|
||||||
|
gl.uniform2f(this.coverProgram.uniforms.FramebufferSize,
|
||||||
|
framebufferSize.width,
|
||||||
|
framebufferSize.height);
|
||||||
|
gl.uniform2f(this.coverProgram.uniforms.TileSize, TILE_SIZE, TILE_SIZE);
|
||||||
|
gl.drawArraysInstanced(gl.TRIANGLE_STRIP, 0, 4, tiles.length);
|
||||||
|
|
||||||
|
/*
|
||||||
|
for (const tile of tiles) {
|
||||||
|
const newSVG = staticCast(document.createElementNS(SVG_NS, 'svg'), SVGElement);
|
||||||
|
newSVG.setAttribute('class', "tile");
|
||||||
|
newSVG.style.left = (GLOBAL_OFFSET.x + tile.origin.x) + "px";
|
||||||
|
newSVG.style.top = (GLOBAL_OFFSET.y + tile.origin.y) + "px";
|
||||||
|
newSVG.style.width = TILE_SIZE + "px";
|
||||||
|
newSVG.style.height = TILE_SIZE + "px";
|
||||||
|
|
||||||
|
const newPath = document.createElementNS(SVG_NS, 'path');
|
||||||
|
newPath.setAttribute('d',
|
||||||
|
tile.path
|
||||||
|
.translate(-tile.origin.x, -tile.origin.y)
|
||||||
|
.toString());
|
||||||
|
|
||||||
|
let color = "#";
|
||||||
|
for (let i = 0; i < 6; i++)
|
||||||
|
color += Math.floor(Math.random() * 16).toString(16);
|
||||||
|
newPath.setAttribute('fill', color);
|
||||||
|
|
||||||
|
newSVG.appendChild(newPath);
|
||||||
|
document.body.appendChild(newSVG);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
private createTiles(): Tile[] {
|
||||||
const svgElement = unwrapNull(this.svg.documentElement).cloneNode(true);
|
const svgElement = unwrapNull(this.svg.documentElement).cloneNode(true);
|
||||||
document.body.appendChild(svgElement);
|
document.body.appendChild(svgElement);
|
||||||
|
|
||||||
|
@ -41,18 +146,22 @@ class App {
|
||||||
const tiles: Tile[] = [];
|
const tiles: Tile[] = [];
|
||||||
|
|
||||||
for (let pathElementIndex = 0;
|
for (let pathElementIndex = 0;
|
||||||
pathElementIndex < 15;
|
pathElementIndex < pathElements.length;
|
||||||
pathElementIndex++) {
|
pathElementIndex++) {
|
||||||
const pathElement = pathElements[pathElementIndex];
|
const pathElement = pathElements[pathElementIndex];
|
||||||
|
|
||||||
const path = canonicalizePath(SVGPath(unwrapNull(pathElement.getAttribute('d'))));
|
const path = canonicalizePath(SVGPath(unwrapNull(pathElement.getAttribute('d'))));
|
||||||
const boundingRect = this.boundingRectOfPath(path);
|
const boundingRect = this.boundingRectOfPath(path);
|
||||||
|
|
||||||
//console.log("path " + pathElementIndex, path.toString(), ":", boundingRect);
|
/*console.log("path " + pathElementIndex, path.toString(), ":",
|
||||||
|
boundingRect.origin.x,
|
||||||
|
boundingRect.origin.y,
|
||||||
|
boundingRect.size.width,
|
||||||
|
boundingRect.size.height);*/
|
||||||
|
|
||||||
let y = boundingRect.origin.y;
|
let y = boundingRect.origin.y - boundingRect.origin.y % TILE_SIZE;
|
||||||
while (true) {
|
while (true) {
|
||||||
let x = boundingRect.origin.x;
|
let x = boundingRect.origin.x - boundingRect.origin.x % TILE_SIZE;
|
||||||
while (true) {
|
while (true) {
|
||||||
const tileBounds = {
|
const tileBounds = {
|
||||||
origin: {x, y},
|
origin: {x, y},
|
||||||
|
@ -60,7 +169,8 @@ class App {
|
||||||
};
|
};
|
||||||
const tilePath = this.clipPathToRect(path, tileBounds);
|
const tilePath = this.clipPathToRect(path, tileBounds);
|
||||||
|
|
||||||
tiles.push(new Tile(pathElementIndex, tilePath, tileBounds.origin));
|
if (tilePath.toString().length > 0)
|
||||||
|
tiles.push(new Tile(pathElementIndex, tilePath, tileBounds.origin));
|
||||||
|
|
||||||
if (x >= boundingRect.origin.x + boundingRect.size.width)
|
if (x >= boundingRect.origin.x + boundingRect.size.width)
|
||||||
break;
|
break;
|
||||||
|
@ -71,32 +181,11 @@ class App {
|
||||||
break;
|
break;
|
||||||
y += TILE_SIZE;
|
y += TILE_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const tile of tiles) {
|
|
||||||
const newSVG = staticCast(document.createElementNS(SVG_NS, 'svg'), SVGElement);
|
|
||||||
newSVG.setAttribute('class', "tile");
|
|
||||||
newSVG.style.left = (GLOBAL_OFFSET.x + tile.origin.x) + "px";
|
|
||||||
newSVG.style.top = (GLOBAL_OFFSET.y + tile.origin.y) + "px";
|
|
||||||
newSVG.style.width = TILE_SIZE + "px";
|
|
||||||
newSVG.style.height = TILE_SIZE + "px";
|
|
||||||
|
|
||||||
const newPath = document.createElementNS(SVG_NS, 'path');
|
|
||||||
newPath.setAttribute('d',
|
|
||||||
tile.path
|
|
||||||
.translate(-tile.origin.x, -tile.origin.y)
|
|
||||||
.toString());
|
|
||||||
|
|
||||||
let color = "#";
|
|
||||||
for (let i = 0; i < 6; i++)
|
|
||||||
color += Math.floor(Math.random() * 16).toString(16);
|
|
||||||
newPath.setAttribute('fill', color);
|
|
||||||
|
|
||||||
newSVG.appendChild(newPath);
|
|
||||||
document.body.appendChild(newSVG);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
document.body.removeChild(svgElement);
|
document.body.removeChild(svgElement);
|
||||||
|
|
||||||
|
return tiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
private clipPathToRect(path: SVGPath, tileBounds: Rect): SVGPath {
|
private clipPathToRect(path: SVGPath, tileBounds: Rect): SVGPath {
|
||||||
|
@ -240,6 +329,60 @@ class Tile {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Program<U extends string, A extends string> {
|
||||||
|
program: WebGLProgram;
|
||||||
|
uniforms: {[key in U]: WebGLUniformLocation};
|
||||||
|
attributes: {[key in A]: number};
|
||||||
|
|
||||||
|
private vertexShader: WebGLShader;
|
||||||
|
private fragmentShader: WebGLShader;
|
||||||
|
|
||||||
|
constructor(gl: WebGL2RenderingContext,
|
||||||
|
vertexShaderSource: string,
|
||||||
|
fragmentShaderSource: string,
|
||||||
|
uniformNames: U[],
|
||||||
|
attributeNames: A[]) {
|
||||||
|
this.vertexShader = unwrapNull(gl.createShader(gl.VERTEX_SHADER));
|
||||||
|
gl.shaderSource(this.vertexShader, vertexShaderSource);
|
||||||
|
gl.compileShader(this.vertexShader);
|
||||||
|
if (!gl.getShaderParameter(this.vertexShader, gl.COMPILE_STATUS)) {
|
||||||
|
console.error(gl.getShaderInfoLog(this.vertexShader));
|
||||||
|
throw new Error("Vertex shader compilation failed!");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.fragmentShader = unwrapNull(gl.createShader(gl.FRAGMENT_SHADER));
|
||||||
|
gl.shaderSource(this.fragmentShader, fragmentShaderSource);
|
||||||
|
gl.compileShader(this.fragmentShader);
|
||||||
|
if (!gl.getShaderParameter(this.fragmentShader, gl.COMPILE_STATUS)) {
|
||||||
|
console.error(gl.getShaderInfoLog(this.fragmentShader));
|
||||||
|
throw new Error("Fragment shader compilation failed!");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.program = unwrapNull(gl.createProgram());
|
||||||
|
gl.attachShader(this.program, this.vertexShader);
|
||||||
|
gl.attachShader(this.program, this.fragmentShader);
|
||||||
|
gl.linkProgram(this.program);
|
||||||
|
if (!gl.getProgramParameter(this.program, gl.LINK_STATUS)) {
|
||||||
|
console.error(gl.getProgramInfoLog(this.program));
|
||||||
|
throw new Error("Program linking failed!");
|
||||||
|
}
|
||||||
|
|
||||||
|
const uniforms: {[key in U]?: WebGLUniformLocation} = {};
|
||||||
|
for (const uniformName of uniformNames) {
|
||||||
|
uniforms[uniformName] = unwrapNull(gl.getUniformLocation(this.program,
|
||||||
|
"u" + uniformName));
|
||||||
|
}
|
||||||
|
this.uniforms = uniforms as {[key in U]: WebGLUniformLocation};
|
||||||
|
|
||||||
|
const attributes: {[key in A]?: number} = {};
|
||||||
|
for (const attributeName of attributeNames) {
|
||||||
|
attributes[attributeName] = unwrapNull(gl.getAttribLocation(this.program,
|
||||||
|
"a" + attributeName));
|
||||||
|
}
|
||||||
|
this.attributes = attributes as {[key in A]: number};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function canonicalizePath(path: SVGPath): SVGPath {
|
function canonicalizePath(path: SVGPath): SVGPath {
|
||||||
return path.abs().iterate((segment: string[], index: number, x: number, y: number) => {
|
return path.abs().iterate((segment: string[], index: number, x: number, y: number) => {
|
||||||
if (segment[0] === 'H')
|
if (segment[0] === 'H')
|
||||||
|
|
Loading…
Reference in New Issue