glcore.js 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  1. // only regular objects with no wierd stuff
  2. function clone(o) {
  3. var c = Array.isArray(o) ? [] : {};
  4. for(var p in o) {
  5. c[p] = typeof o[p] === 'object' ? clone(o[p]) : o[p];
  6. }
  7. return c;
  8. }
  9. function ajaxGet(url, cb) {
  10. var xhr = new XMLHttpRequest();
  11. xhr.open("GET", url)
  12. xhr.onreadystatechange = function () {
  13. if(xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
  14. cb(null, xhr.responseText);
  15. }
  16. };
  17. xhr.send();
  18. }
  19. function getJSON(url, cb) {
  20. ajaxGet(url, function(err, raw) {
  21. if(err) return cb(err);
  22. var js;
  23. try {
  24. js = JSON5.parse(raw);
  25. }
  26. catch(e) {
  27. return cb(e);
  28. }
  29. cb(null, js);
  30. });
  31. }
  32. function asyncParallel(list, cb) {
  33. var lookup = {};
  34. var num = list.length;
  35. var savedErr = null;
  36. for(var a in list) {
  37. var x = list[a];
  38. var fn = x[0];
  39. var args = x.slice(1);
  40. args.push((function(n) {
  41. return function(err) {
  42. if(err) savedErr = err;
  43. if(lookup[n]) return;
  44. lookup[n] = 1;
  45. num--;
  46. if(num == 0) cb(savedErr);
  47. }
  48. })(a));
  49. fn.apply(null, args);
  50. }
  51. }
  52. // don't feed this function bad values;
  53. var getGLTypeSize;
  54. (function() {
  55. getGLTypeSize = function(type) {
  56. var lookup = {};
  57. lookup[gl.BYTE] = 1;
  58. lookup[gl.UNSIGNED_BYTE] = 1;
  59. lookup[gl.SHORT] = 2;
  60. lookup[gl.UNSIGNED_SHORT] = 2;
  61. lookup[gl.INT] = 4;
  62. lookup[gl.UNSIGNED_INT] = 4;
  63. lookup[gl.HALF_FLOAT] = 2;
  64. lookup[gl.FLOAT] = 4;
  65. return lookup[type] || 999999999;
  66. }
  67. })();
  68. function Texture(target, w, h) {
  69. this.tex = gl.createTexture();
  70. this.target = target;
  71. this.w = w;
  72. this.h = h;
  73. this.depth = -1;
  74. // TODO: fix this
  75. this.format = gl.UNSIGNED_BYTE;
  76. return this;
  77. }
  78. Texture.prototype.bind = function() {
  79. gl.bindTexture(this.target, this.tex);
  80. }
  81. Texture.prototype.unbind = function() {
  82. gl.bindTexture(this.target, null);
  83. }
  84. Texture.prototype.updateLayer = function(layer, data) {
  85. if(this.depth < 2 || this.depth <= layer) {
  86. console.log("attempting to update invalid texture layer");
  87. return;
  88. }
  89. console.log(this.target, gl.TEXTURE_2D_ARRAY);
  90. this.bind();
  91. gl.texSubImage3D(this.target, 0,
  92. 0, 0, layer, // offset
  93. this.w, this.h, 1,
  94. /*this.type*/gl.RED, this.format,
  95. data
  96. );
  97. }
  98. function loadTexture(image) {
  99. var tex = gl.createTexture();
  100. gl.bindTexture(gl.TEXTURE_2D, tex);
  101. gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA,gl.UNSIGNED_BYTE, image);
  102. // gl.generateMipmap(gl.TEXTURE_2D);
  103. gl.bindTexture(gl.TEXTURE_2D, null);
  104. return {
  105. tex: tex,
  106. w: image.width,
  107. h: image.height,
  108. };
  109. }
  110. function loadTextureArray(images) {
  111. var w = images[0].width;
  112. var h = images[0].height;
  113. var tex = makeTexArray(gl.RGBA8, w, h, images.length);
  114. tex.bind();
  115. //gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, w, h, images.length);
  116. for(var i in images) {
  117. gl.texSubImage3D(gl.TEXTURE_2D_ARRAY, 0,
  118. 0, 0, i, // offset
  119. w, h, 1,
  120. gl.RGBA, gl.UNSIGNED_BYTE,
  121. images[i]
  122. );
  123. }
  124. // gl.generateMipmap(gl.TEXTURE_2D_ARRAY);
  125. tex.unbind();
  126. tex.depth = images.length;
  127. return tex;
  128. }
  129. function makeTexArray(type, w, h, d) {
  130. var tex = new Texture(gl.TEXTURE_2D_ARRAY, w, h);
  131. tex.bind();
  132. gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, type, w, h, d);
  133. tex.unbind();
  134. tex.depth = d;
  135. tex.type = type;
  136. return tex;
  137. }
  138. function loadShader(type, source) {
  139. var shader = gl.createShader(type);
  140. gl.shaderSource(shader, source);
  141. gl.compileShader(shader);
  142. var success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
  143. if (success) {
  144. return shader;
  145. }
  146. console.log(gl.getShaderInfoLog(shader));
  147. gl.deleteShader(shader);
  148. }
  149. function loadProgram2(vert, frag) {
  150. var program = gl.createProgram();
  151. gl.attachShader(program, loadShader(gl.VERTEX_SHADER, vert));
  152. gl.attachShader(program, loadShader(gl.FRAGMENT_SHADER, frag));
  153. gl.linkProgram(program);
  154. var success = gl.getProgramParameter(program, gl.LINK_STATUS);
  155. if(success) {
  156. return program;
  157. }
  158. console.log(gl.getProgramInfoLog(program));
  159. gl.deleteProgram(program);
  160. }
  161. function loadProgram(ids) {
  162. var lookup = {
  163. 'glsl-vertex': gl.VERTEX_SHADER,
  164. 'glsl-fragment': gl.FRAGMENT_SHADER,
  165. };
  166. var program = gl.createProgram();
  167. for(var i = 0; i < ids.length; i++) {
  168. var id = ids[i];
  169. var elem = document.getElementById(id);
  170. console.log(elem);
  171. gl.attachShader(program, loadShader(lookup[elem.getAttribute('type')], elem.text));
  172. }
  173. gl.linkProgram(program);
  174. var success = gl.getProgramParameter(program, gl.LINK_STATUS);
  175. if(success) {
  176. return program;
  177. }
  178. console.log(gl.getProgramInfoLog(program));
  179. gl.deleteProgram(program);
  180. }
  181. function calcVAOStride(attribs, bufIndex) {
  182. var stride = 0;
  183. for(var a of attribs) {
  184. if(bufIndex == a.buf) {
  185. stride += getGLTypeSize(a.type) * a.count;
  186. }
  187. }
  188. return stride;
  189. }
  190. /*
  191. attrib: [
  192. { name: 'pos', loc: 0, count: 3, type: gl.FLOAT, norm: false },
  193. { name: 'normal', loc: 0, count: 3, type: gl.FLOAT, norm: false },
  194. ]
  195. */
  196. function makeVAO(attribs) {
  197. var vaoInfo = {
  198. attribs: clone(attribs),
  199. // stride: stride,
  200. vao: gl.createVertexArray(),
  201. };
  202. return vaoInfo;
  203. }
  204. function configVAO(vaoInfo, bufIndex) {
  205. var off = 0;
  206. var stride = calcVAOStride(vaoInfo.attribs, bufIndex);
  207. for(var a of vaoInfo.attribs) {
  208. if(bufIndex == a.buf) {
  209. gl.enableVertexAttribArray(a.loc);
  210. // console.log(a, off, stride);
  211. gl.vertexAttribPointer(a.loc, a.count, a.type, a.norm, stride, off);
  212. if(a.divisor) gl.vertexAttribDivisor(a.loc, a.divisor);
  213. off += getGLTypeSize(a.type) * a.count;
  214. }
  215. }
  216. }
  217. function makeVBO(data, vaoInfo, bufIndex, hint) {
  218. var buf = gl.createBuffer();
  219. gl.bindBuffer(gl.ARRAY_BUFFER, buf);
  220. gl.bindVertexArray(vaoInfo.vao);
  221. if(hint == undefined) hint = gl.STATIC_DRAW;
  222. configVAO(vaoInfo, bufIndex);
  223. gl.bufferData(gl.ARRAY_BUFFER, data, hint);
  224. gl.bindBuffer(gl.ARRAY_BUFFER, null);
  225. return {
  226. vbo: buf,
  227. vaoInfo: vaoInfo,
  228. type: gl.ARRAY_BUFFER,
  229. };
  230. }
  231. function makeIBO(data, hint) {
  232. var buf = gl.createBuffer();
  233. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buf);
  234. if(hint == undefined) hint = gl.STATIC_DRAW;
  235. configVAO(vaoInfo);
  236. gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, data, hint);
  237. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, 0);
  238. return {
  239. ibo: buf,
  240. type: gl.ELEMENT_ARRAY_BUFFER,
  241. };
  242. }
  243. function makeBufferTMP() {
  244. var positionBuffer = gl.createBuffer();
  245. gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
  246. var positions = [
  247. 0, 0, 0,
  248. 0, 1, 0,
  249. 1, 0, 0,
  250. 0, 1, 0,
  251. 1, 0, 0,
  252. 1, 1, 0,
  253. ];
  254. gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
  255. var vao = gl.createVertexArray();
  256. gl.bindVertexArray(vao);
  257. var positionAttributeLocation = gl.getAttribLocation(program, "pos_in");
  258. gl.enableVertexAttribArray(positionAttributeLocation);
  259. gl.vertexAttribPointer(positionAttributeLocation, 3, gl.FLOAT, false, 0, 0);
  260. return [vao, positionBuffer];
  261. }
  262. function makeSDFChar(char, font, info, buffer, adv, z) {
  263. var ix = info.charInfoIndices;
  264. var ci = font[char];
  265. var box = {
  266. x: ci[ix.boxSize][0],
  267. y: ci[ix.boxSize][1],
  268. };
  269. var no = {
  270. x: ci[ix.normalizedOffset][0],
  271. y: ci[ix.normalizedOffset][1],
  272. };
  273. var ns = {
  274. x: ci[ix.normalizedSize][0],
  275. y: ci[ix.normalizedSize][1],
  276. };
  277. buffer.push(adv);
  278. buffer.push(0);
  279. buffer.push(z);
  280. buffer.push(ci[ix.boxOffset][0]);
  281. buffer.push(ci[ix.boxOffset][1]);
  282. buffer.push(ci[ix.boxSize][0]);
  283. buffer.push(ci[ix.boxSize][1]);
  284. buffer.push(ci[ix.normalizedOffset][0]);
  285. buffer.push(ci[ix.normalizedOffset][1]);
  286. buffer.push(ci[ix.normalizedSize][0]);
  287. buffer.push(ci[ix.normalizedSize][1]);
  288. buffer.push(1);
  289. buffer.push(.5);
  290. buffer.push(.2);
  291. buffer.push(1);
  292. return ci[ix.advance] - 1;
  293. }
  294. // TODO: optimize
  295. function makeSDFCharOld(char, font, info, buffer, adv, z) {
  296. function vert(x,y,z,u,v) {
  297. buffer.push(x);
  298. buffer.push(y);
  299. buffer.push(z);
  300. buffer.push(u);
  301. buffer.push(v);
  302. }
  303. var ix = info.charInfoIndices;
  304. var ci = font[char];
  305. var box = {
  306. x: ci[ix.boxSize][0],
  307. y: ci[ix.boxSize][1],
  308. };
  309. var no = {
  310. x: ci[ix.normalizedOffset][0],
  311. y: ci[ix.normalizedOffset][1],
  312. };
  313. var ns = {
  314. x: ci[ix.normalizedSize][0],
  315. y: ci[ix.normalizedSize][1],
  316. };
  317. vert(adv, 0, z, no.x, no.y + ns.y);
  318. vert(adv, box.y, z, no.x, no.y);
  319. vert(adv+box.x, 0, z, no.x + ns.x, no.y + ns.y);
  320. vert(adv, box.y, z, no.x, no.y);
  321. vert(adv+box.x, 0, z, no.x + ns.x, no.y + ns.y);
  322. vert(adv+box.x, box.y, z, no.x + ns.x, no.y);
  323. return ci[ix.advance];
  324. }
  325. function makeQuad(vaoInfo, bufIndex) {
  326. var quad = new Float32Array([
  327. 0, 0, 0, 0, 1,
  328. 0, 1, 0, 0, 0,
  329. 1, 0, 0, 1, 1,
  330. 1, 1, 0, 1, 0,
  331. ]);
  332. return makeVBO(quad, vaoInfo, bufIndex);
  333. }