wgld.orgのソースコードをWebGL2ベースに書き換えてみる まずは三角形を描画してみる。
Last active
September 1, 2024 13:34
-
-
Save sfpgmr/47c33ee5ac5199e126fa6a6b2f974f80 to your computer and use it in GitHub Desktop.
WebGL2を試す
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.vscode | |
node_modules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function () { | |
'use strict'; | |
// ------------------------------------------------------------------------------------------------ | |
// mat4.js | |
// doxasさんのminMatrix.jsをES6バージョンに改造したもの | |
// https://wgld.org/d/library/l001.html | |
// ------------------------------------------------------------------------------------------------ | |
class Mat4 { | |
constructor(m = new Float32Array(16)) { | |
this.matrix = m; | |
} | |
identity() { | |
const dest = this.matrix; | |
dest[0] = 1; dest[1] = 0; dest[2] = 0; dest[3] = 0; | |
dest[4] = 0; dest[5] = 1; dest[6] = 0; dest[7] = 0; | |
dest[8] = 0; dest[9] = 0; dest[10] = 1; dest[11] = 0; | |
dest[12] = 0; dest[13] = 0; dest[14] = 0; dest[15] = 1; | |
return this; | |
} | |
multiply(matrix, destMatrix = new Mat4()) { | |
const mat1 = this.matrix, mat2 = matrix.matrix; | |
const dest = destMatrix.matrix; | |
const a = mat1[0], b = mat1[1], c = mat1[2], d = mat1[3], | |
e = mat1[4], f = mat1[5], g = mat1[6], h = mat1[7], | |
i = mat1[8], j = mat1[9], k = mat1[10], l = mat1[11], | |
m = mat1[12], n = mat1[13], o = mat1[14], p = mat1[15], | |
A = mat2[0], B = mat2[1], C = mat2[2], D = mat2[3], | |
E = mat2[4], F = mat2[5], G = mat2[6], H = mat2[7], | |
I = mat2[8], J = mat2[9], K = mat2[10], L = mat2[11], | |
M = mat2[12], N = mat2[13], O = mat2[14], P = mat2[15]; | |
dest[0] = A * a + B * e + C * i + D * m; | |
dest[1] = A * b + B * f + C * j + D * n; | |
dest[2] = A * c + B * g + C * k + D * o; | |
dest[3] = A * d + B * h + C * l + D * p; | |
dest[4] = E * a + F * e + G * i + H * m; | |
dest[5] = E * b + F * f + G * j + H * n; | |
dest[6] = E * c + F * g + G * k + H * o; | |
dest[7] = E * d + F * h + G * l + H * p; | |
dest[8] = I * a + J * e + K * i + L * m; | |
dest[9] = I * b + J * f + K * j + L * n; | |
dest[10] = I * c + J * g + K * k + L * o; | |
dest[11] = I * d + J * h + K * l + L * p; | |
dest[12] = M * a + N * e + O * i + P * m; | |
dest[13] = M * b + N * f + O * j + P * n; | |
dest[14] = M * c + N * g + O * k + P * o; | |
dest[15] = M * d + N * h + O * l + P * p; | |
return destMatrix; | |
}; | |
scale(vec, destMatrix = new Mat4()) { | |
const mat = this.matrix; | |
const dest = destMatrix.matrix; | |
dest[0] = mat[0] * vec[0]; | |
dest[1] = mat[1] * vec[0]; | |
dest[2] = mat[2] * vec[0]; | |
dest[3] = mat[3] * vec[0]; | |
dest[4] = mat[4] * vec[1]; | |
dest[5] = mat[5] * vec[1]; | |
dest[6] = mat[6] * vec[1]; | |
dest[7] = mat[7] * vec[1]; | |
dest[8] = mat[8] * vec[2]; | |
dest[9] = mat[9] * vec[2]; | |
dest[10] = mat[10] * vec[2]; | |
dest[11] = mat[11] * vec[2]; | |
dest[12] = mat[12]; | |
dest[13] = mat[13]; | |
dest[14] = mat[14]; | |
dest[15] = mat[15]; | |
return destMatrix; | |
}; | |
translate(vec, destMatrix = new Mat4()) { | |
const mat = this.matrix; | |
const dest = destMatrix.matrix; | |
dest[0] = mat[0]; dest[1] = mat[1]; dest[2] = mat[2]; dest[3] = mat[3]; | |
dest[4] = mat[4]; dest[5] = mat[5]; dest[6] = mat[6]; dest[7] = mat[7]; | |
dest[8] = mat[8]; dest[9] = mat[9]; dest[10] = mat[10]; dest[11] = mat[11]; | |
dest[12] = mat[0] * vec[0] + mat[4] * vec[1] + mat[8] * vec[2] + mat[12]; | |
dest[13] = mat[1] * vec[0] + mat[5] * vec[1] + mat[9] * vec[2] + mat[13]; | |
dest[14] = mat[2] * vec[0] + mat[6] * vec[1] + mat[10] * vec[2] + mat[14]; | |
dest[15] = mat[3] * vec[0] + mat[7] * vec[1] + mat[11] * vec[2] + mat[15]; | |
return destMatrix; | |
}; | |
rotate(angle, axis, destMatrix = new Mat4()) { | |
const dest = destMatrix.matrix; | |
const mat = this.matrix; | |
var sq = Math.sqrt(axis[0] * axis[0] + axis[1] * axis[1] + axis[2] * axis[2]); | |
if (!sq) { return null; } | |
var a = axis[0], b = axis[1], c = axis[2]; | |
if (sq != 1) { sq = 1 / sq; a *= sq; b *= sq; c *= sq; } | |
var d = Math.sin(angle), e = Math.cos(angle), f = 1 - e, | |
g = mat[0], h = mat[1], i = mat[2], j = mat[3], | |
k = mat[4], l = mat[5], m = mat[6], n = mat[7], | |
o = mat[8], p = mat[9], q = mat[10], r = mat[11], | |
s = a * a * f + e, | |
t = b * a * f + c * d, | |
u = c * a * f - b * d, | |
v = a * b * f - c * d, | |
w = b * b * f + e, | |
x = c * b * f + a * d, | |
y = a * c * f + b * d, | |
z = b * c * f - a * d, | |
A = c * c * f + e; | |
if (angle) { | |
if (mat != dest) { | |
dest[12] = mat[12]; dest[13] = mat[13]; | |
dest[14] = mat[14]; dest[15] = mat[15]; | |
} | |
} else { | |
dest = mat; | |
} | |
dest[0] = g * s + k * t + o * u; | |
dest[1] = h * s + l * t + p * u; | |
dest[2] = i * s + m * t + q * u; | |
dest[3] = j * s + n * t + r * u; | |
dest[4] = g * v + k * w + o * x; | |
dest[5] = h * v + l * w + p * x; | |
dest[6] = i * v + m * w + q * x; | |
dest[7] = j * v + n * w + r * x; | |
dest[8] = g * y + k * z + o * A; | |
dest[9] = h * y + l * z + p * A; | |
dest[10] = i * y + m * z + q * A; | |
dest[11] = j * y + n * z + r * A; | |
return destMatrix; | |
}; | |
static createLookAt({eye, center, up, destMatrix = new Mat4()}) { | |
const dest = destMatrix.matrix; | |
const eyeX = eye[0], eyeY = eye[1], eyeZ = eye[2], | |
upX = up[0], upY = up[1], upZ = up[2], | |
centerX = center[0], centerY = center[1], centerZ = center[2]; | |
if (eyeX == centerX && eyeY == centerY && eyeZ == centerZ) | |
{ | |
return destMatrix.identity(); | |
} | |
let x0, x1, x2, y0, y1, y2, z0, z1, z2, l; | |
z0 = eyeX - center[0]; | |
z1 = eyeY - center[1]; | |
z2 = eyeZ - center[2]; | |
l = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2); | |
z0 *= l; z1 *= l; z2 *= l; | |
x0 = upY * z2 - upZ * z1; | |
x1 = upZ * z0 - upX * z2; | |
x2 = upX * z1 - upY * z0; | |
l = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2); | |
if (!l) { | |
x0 = 0; x1 = 0; x2 = 0; | |
} else { | |
l = 1 / l; | |
x0 *= l; x1 *= l; x2 *= l; | |
} | |
y0 = z1 * x2 - z2 * x1; y1 = z2 * x0 - z0 * x2; y2 = z0 * x1 - z1 * x0; | |
l = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2); | |
if (!l) { | |
y0 = 0; y1 = 0; y2 = 0; | |
} else { | |
l = 1 / l; | |
y0 *= l; y1 *= l; y2 *= l; | |
} | |
dest[0] = x0; dest[1] = y0; dest[2] = z0; dest[3] = 0; | |
dest[4] = x1; dest[5] = y1; dest[6] = z1; dest[7] = 0; | |
dest[8] = x2; dest[9] = y2; dest[10] = z2; dest[11] = 0; | |
dest[12] = -(x0 * eyeX + x1 * eyeY + x2 * eyeZ); | |
dest[13] = -(y0 * eyeX + y1 * eyeY + y2 * eyeZ); | |
dest[14] = -(z0 * eyeX + z1 * eyeY + z2 * eyeZ); | |
dest[15] = 1; | |
return destMatrix; | |
}; | |
static createPerspective({fovy, aspect, near, far, destMatrix = new Mat4()}) { | |
const dest = destMatrix.matrix; | |
const t = near * Math.tan(fovy * Math.PI / 360); | |
const r = t * aspect; | |
const a = r * 2, b = t * 2, c = far - near; | |
dest[0] = near * 2 / a; | |
dest[1] = 0; | |
dest[2] = 0; | |
dest[3] = 0; | |
dest[4] = 0; | |
dest[5] = near * 2 / b; | |
dest[6] = 0; | |
dest[7] = 0; | |
dest[8] = 0; | |
dest[9] = 0; | |
dest[10] = -(far + near) / c; | |
dest[11] = -1; | |
dest[12] = 0; | |
dest[13] = 0; | |
dest[14] = -(far * near * 2) / c; | |
dest[15] = 0; | |
return destMatrix; | |
}; | |
transpose(destMatrix = new Mat4()) { | |
const mat = this.matrix; | |
const dest = destMatrix.matrix; | |
dest[0] = mat[0]; dest[1] = mat[4]; | |
dest[2] = mat[8]; dest[3] = mat[12]; | |
dest[4] = mat[1]; dest[5] = mat[5]; | |
dest[6] = mat[9]; dest[7] = mat[13]; | |
dest[8] = mat[2]; dest[9] = mat[6]; | |
dest[10] = mat[10]; dest[11] = mat[14]; | |
dest[12] = mat[3]; dest[13] = mat[7]; | |
dest[14] = mat[11]; dest[15] = mat[15]; | |
return destMatrix; | |
}; | |
inverse(destMatrix = new Mat4()) { | |
const dest = destMatrix.matrix; | |
const mat = this.matrix; | |
const a = mat[0], b = mat[1], c = mat[2], d = mat[3], | |
e = mat[4], f = mat[5], g = mat[6], h = mat[7], | |
i = mat[8], j = mat[9], k = mat[10], l = mat[11], | |
m = mat[12], n = mat[13], o = mat[14], p = mat[15], | |
q = a * f - b * e, r = a * g - c * e, | |
s = a * h - d * e, t = b * g - c * f, | |
u = b * h - d * f, v = c * h - d * g, | |
w = i * n - j * m, x = i * o - k * m, | |
y = i * p - l * m, z = j * o - k * n, | |
A = j * p - l * n, B = k * p - l * o, | |
ivd = 1 / (q * B - r * A + s * z + t * y - u * x + v * w); | |
dest[0] = (f * B - g * A + h * z) * ivd; | |
dest[1] = (-b * B + c * A - d * z) * ivd; | |
dest[2] = (n * v - o * u + p * t) * ivd; | |
dest[3] = (-j * v + k * u - l * t) * ivd; | |
dest[4] = (-e * B + g * y - h * x) * ivd; | |
dest[5] = (a * B - c * y + d * x) * ivd; | |
dest[6] = (-m * v + o * s - p * r) * ivd; | |
dest[7] = (i * v - k * s + l * r) * ivd; | |
dest[8] = (e * A - f * y + h * w) * ivd; | |
dest[9] = (-a * A + b * y - d * w) * ivd; | |
dest[10] = (m * u - n * s + p * q) * ivd; | |
dest[11] = (-i * u + j * s - l * q) * ivd; | |
dest[12] = (-e * z + f * x - g * w) * ivd; | |
dest[13] = (a * z - b * x + c * w) * ivd; | |
dest[14] = (-m * t + n * r - o * q) * ivd; | |
dest[15] = (i * t - j * r + k * q) * ivd; | |
return destMatrix; | |
}; | |
} | |
// WebGL 2.0 APIをラッピングするクラス | |
class GL2 { | |
constructor({ width = window.innerWidth, height = window.innerHeight, elem = document.body }) { | |
// canvasエレメントを作成する | |
const canvas = document.createElement('canvas'); | |
// canvasの幅と高さを設定 | |
canvas.width = width; | |
canvas.height = height; | |
// インスタンスに幅と高さを保存 | |
this.width = width; | |
this.height = height; | |
// canvasにidを設定 | |
canvas.id = 'screen'; | |
// elemの子要素としてcanvasを追加 | |
elem.appendChild(canvas); | |
// インスタンスにWebGL2RenderingContextを保存 | |
this.context = canvas.getContext('webgl2'); | |
// WebGL2RenderingContextが獲得できない場合は例外を送出する。 | |
if (!this.context) throw new Error('このブラウザはWebcontextをサポートしていません。'); | |
} | |
// shaderSrcとtypeでWebGLShaderを作り返す | |
createShader(shaderSrc, type) { | |
// WebGL2RenderingContextコンテキスト | |
const context = this.context; | |
// WebGLShaderの生成 | |
const shader = context.createShader(type); | |
// WebGLShaderにシェーダーソースコードをセットする | |
context.shaderSource(shader, shaderSrc); | |
// シェーダーソースコードをコンパイルする | |
context.compileShader(shader); | |
// シェーダーのコンパイルが失敗した場合は例外を送出する | |
if (!context.getShaderParameter(shader, context.COMPILE_STATUS)) { | |
throw new Error(context.getShaderInfoLog(shader)); | |
} | |
return shader; | |
} | |
// 2つのWebGLShader(頂点シェーダ・フラグメントシェーダ) | |
// からWebGLProgramを作り返す | |
createProgram(vs, fs) { | |
// WebGL2RenderingContextコンテキスト | |
const context = this.context; | |
// WebGLProgramの作成 | |
const program = context.createProgram(); | |
// 頂点シェーダをアタッチする | |
context.attachShader(program, vs); | |
// フラグメントシェーダをアタッチする | |
context.attachShader(program, fs); | |
// シェーダーをリンクする | |
context.linkProgram(program); | |
// リンクが失敗したら例外を送出する | |
if (!context.getProgramParameter(program, context.LINK_STATUS)) { | |
throw new Error(context.getProgramInfoLog(program)); | |
} | |
return program; | |
} | |
// 現在のレンダリング・ステートで使用するWebGLProgramを指定する | |
useProgram(program) { | |
this.context.useProgram(program); | |
} | |
// WebGLBuffer(Vetex Buffer) を作成し、データをセットし返す | |
createBuffer(data) { | |
// WebGL2RenderingContextコンテキスト | |
const context = this.context; | |
// WebGLBufferを作成する | |
const buffer = context.createBuffer(); | |
// WebGLBufferのバインド | |
context.bindBuffer(context.ARRAY_BUFFER, buffer); | |
// dataのセット | |
context.bufferData(context.ARRAY_BUFFER, data, context.STATIC_DRAW); | |
// バインドの解除 | |
context.bindBuffer(context.ARRAY_BUFFER, null); | |
return buffer; | |
} | |
// WebGLBufferをlocationで指定したアトリビュートに割り当てる | |
setAttribute(buffer,location,size,type = this.context.FLOAT,normalize =false,byteStride = 0,byteOffset = 0){ | |
// WebGL2RenderingContextコンテキスト | |
const context = this.context; | |
context.bindBuffer(context.ARRAY_BUFFER, buffer); | |
// locationのattributeを有効にする | |
context.enableVertexAttribArray(location); | |
// locationのattributeにWebGLBufferを割り当てる | |
context.vertexAttribPointer(location, size, type, normalize, byteStride, byteOffset); | |
} | |
/// WebGLVertexArrayObjectを生成し、返す | |
createVertexArray({dataArray,dataTypes,bufferTypes, locations, sizes, indexBuffer,indexBufferType}){ | |
// WebGL2RenderingContextコンテキスト | |
const context = this.context; | |
// WebGLVertexArrayObjectを生成する | |
const vao = context.createVertexArray(); | |
// WebGLVertexArrayObjectをバインドする | |
context.bindVertexArray(vao); | |
// 配列データからWebGLBufferを作成し、attributeに割り当てる | |
for(let i = 0,e = dataArray.length;i < e;++i){ | |
// WebGLBufferの生成 | |
let vbo = context.createBuffer(); | |
// WebGLBufferのバインド | |
context.bindBuffer(context.ARRAY_BUFFER, vbo); | |
// WebGLBufferにデータを設定する | |
context.bufferData(context.ARRAY_BUFFER, dataArray[i], bufferTypes ? bufferTypes[i] : context.STATIC_DRAW); | |
// locationのattributeを有効にする | |
context.enableVertexAttribArray(locations[i]); | |
// locationのattributeにWebGLBufferを割り当てる | |
context.vertexAttribPointer(locations[i], sizes[i], dataTypes ? dataTypes[i] : context.FLOAT, false, 0, 0); | |
} | |
// インデックスバッファーの生成 | |
if(indexBuffer){ | |
// WebGLBufferの作成 | |
let ibo = context.createBuffer(); | |
// WebGLBufferのバインド | |
context.bindBuffer(context.ELEMENT_ARRAY_BUFFER, ibo); | |
// WebGLBufferにインデックスデータを引き渡す | |
context.bufferData(context.ELEMENT_ARRAY_BUFFER, new UInt32Array(iboData), indexBufferType ? indexBufferType : context.STATIC_DRAW); | |
} | |
// WebGLVertexArrayObjectのバインドを解除 | |
context.bindVertexArray(null); | |
return vao; | |
} | |
setMatrix({model,view,projection}){ | |
this.model = model ? model : this.model; | |
this.view = view ? view : this.view; | |
this.projection = projection ? projection : this.projection; | |
this.mvp = this.model.multiply(this.projection.multiply(this.view)); | |
} | |
resize(){ | |
this.width = window.innerWidth; | |
this.height = window.innerHeight; | |
this.setMatrix({projection:Mat4.createPerspective({fovy:90, aspect:this.width / this.height, near:0.1, far:100})}); | |
} | |
// uniform変数に値を設定する | |
setUniformValue(prg,attributeName,value) | |
{ | |
// uniform変数の位置を取得する | |
var uniLocation = this.context.getUniformLocation(prg, 'mvpMatrix'); | |
// uniform変数に値を設定する | |
this.context.uniformMatrix4fv(uniLocation, false, value); | |
} | |
} | |
// 4x4 行列クラス | |
// WebGL2.0 ラッパー | |
// 頂点シェーダ | |
const vertexShader = | |
`#version 300 es | |
layout (location = 0) in vec3 position; | |
layout (location = 1) in vec4 color; | |
uniform mat4 mvpMatrix; | |
out vec4 oColor; | |
void main(void){ | |
gl_Position = mvpMatrix * vec4(position,1.0); | |
oColor = color; | |
} | |
`; | |
// フラグメントシェーダ | |
const fragmentShader = | |
`#version 300 es | |
precision highp float; | |
out vec4 color; | |
in vec4 oColor; | |
void main(void){ | |
color = oColor; | |
} | |
`; | |
document.addEventListener('DOMContentLoaded', () => { | |
// ローディング中の情報表示 | |
const info = document.getElementById('info'); | |
info.innerText = 'ロード中...しばらくお待ちください。'; | |
// GL2クラスの生成 | |
let gl2; | |
try { | |
gl2 = new GL2({ elem: document.getElementById('container') }); | |
} catch (e) { | |
info = e.message; | |
return; | |
} | |
// gl2オブジェクトからコンテキストを取り出す | |
const ctx = gl2.context; | |
// 画面クリアカラーの設定 | |
ctx.clearColor(0.0 /* Red */, 0.0 /* Green */, 0.0 /* Blue */, 1.0 /* Alpha */); | |
// 深度バッファのクリア値の設定 | |
ctx.clearDepth(1.0); | |
// 画面クリア | |
ctx.clear(ctx.COLOR_BUFFER_BIT | ctx.DEPTH_BUFFER_BIT); | |
// 頂点シェーダの作成 | |
const vs = gl2.createShader(vertexShader, ctx.VERTEX_SHADER); | |
// フラグメントシェーダの作成 | |
const fs = gl2.createShader(fragmentShader, ctx.FRAGMENT_SHADER); | |
// プログラムの作成 | |
const prg = gl2.createProgram(vs, fs); | |
// 現在のレンダリングステートにプログラムを割り当てる | |
gl2.useProgram(prg); | |
// 頂点情報 | |
const vertices = new Float32Array([ | |
0.0, 1.0, 0.0, | |
1.0, 0.0, 0.0, | |
-1.0, 0.0, 0.0 | |
]); | |
// 色情報 | |
const colors = new Float32Array([ | |
0.0 /* Red */, 1.0 /* Green */, 0.0 /* Blue */, 1.0 /* Alpha */, | |
0.0, 0.0, 1.0, 1.0, | |
1.0, 0.0, 0.0, 1.0, | |
]); | |
// Vertex Array Objectの生成 | |
const vao = gl2.createVertexArray({ | |
dataArray:[vertices,colors], | |
locations:[0,1], | |
sizes:[3,4] | |
}); | |
// Vertex Array Objectのバインド | |
ctx.bindVertexArray(vao); | |
// 各種行列の生成と初期化 | |
gl2.setMatrix({ | |
model:new Mat4().identity(), | |
view:Mat4.createLookAt({eye:[0.0, 1.0, 3.0], center:[0, 0, 0], up:[0, 1, 0]}), | |
projection: Mat4.createPerspective({fovy:90, aspect:gl2.width / gl2.height, near:0.1, far:100}) | |
}); | |
gl2.setUniformValue(prg,'mvpMatrix',gl2.mvp.matrix); | |
render(); | |
// windows resize時の処理 | |
window.addEventListener('resize', () => { | |
if (gl2) { | |
gl2.resize(); | |
gl2.setUniformValue(prg,'mvpMatrix',gl2.mvp.matrix); | |
render(); | |
} | |
}); | |
info.style.display = 'none'; | |
// レンダリング処理 | |
function render() { | |
ctx.clear(ctx.COLOR_BUFFER_BIT | ctx.DEPTH_BUFFER_BIT); | |
ctx.drawArrays(ctx.TRIANGLES, 0, 3); | |
ctx.flush(); | |
} | |
// レンダリングループ | |
}); | |
}()); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function filter(f){ | |
if(f.match(/\.js/i)){ | |
if(f.match(/bundle\.js/i)) return false; | |
return true; | |
} | |
return false; | |
} | |
module.exports = filter; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Mat4 from './mat4.js'; | |
// WebGL 2.0 APIをラッピングするクラス | |
class GL2 { | |
constructor({ width = window.innerWidth, height = window.innerHeight, elem = document.body }) { | |
// canvasエレメントを作成する | |
const canvas = document.createElement('canvas'); | |
// canvasの幅と高さを設定 | |
canvas.width = width; | |
canvas.height = height; | |
// インスタンスに幅と高さを保存 | |
this.width = width; | |
this.height = height; | |
// canvasにidを設定 | |
canvas.id = 'screen'; | |
// elemの子要素としてcanvasを追加 | |
elem.appendChild(canvas); | |
// インスタンスにWebGL2RenderingContextを保存 | |
this.context = canvas.getContext('webgl2'); | |
// WebGL2RenderingContextが獲得できない場合は例外を送出する。 | |
if (!this.context) throw new Error('このブラウザはWebcontextをサポートしていません。'); | |
} | |
// shaderSrcとtypeでWebGLShaderを作り返す | |
createShader(shaderSrc, type) { | |
// WebGL2RenderingContextコンテキスト | |
const context = this.context; | |
// WebGLShaderの生成 | |
const shader = context.createShader(type); | |
// WebGLShaderにシェーダーソースコードをセットする | |
context.shaderSource(shader, shaderSrc); | |
// シェーダーソースコードをコンパイルする | |
context.compileShader(shader); | |
// シェーダーのコンパイルが失敗した場合は例外を送出する | |
if (!context.getShaderParameter(shader, context.COMPILE_STATUS)) { | |
throw new Error(context.getShaderInfoLog(shader)); | |
} | |
return shader; | |
} | |
// 2つのWebGLShader(頂点シェーダ・フラグメントシェーダ) | |
// からWebGLProgramを作り返す | |
createProgram(vs, fs) { | |
// WebGL2RenderingContextコンテキスト | |
const context = this.context; | |
// WebGLProgramの作成 | |
const program = context.createProgram(); | |
// 頂点シェーダをアタッチする | |
context.attachShader(program, vs); | |
// フラグメントシェーダをアタッチする | |
context.attachShader(program, fs); | |
// シェーダーをリンクする | |
context.linkProgram(program); | |
// リンクが失敗したら例外を送出する | |
if (!context.getProgramParameter(program, context.LINK_STATUS)) { | |
throw new Error(context.getProgramInfoLog(program)); | |
} | |
return program; | |
} | |
// 現在のレンダリング・ステートで使用するWebGLProgramを指定する | |
useProgram(program) { | |
this.context.useProgram(program); | |
} | |
// WebGLBuffer(Vetex Buffer) を作成し、データをセットし返す | |
createBuffer(data) { | |
// WebGL2RenderingContextコンテキスト | |
const context = this.context; | |
// WebGLBufferを作成する | |
const buffer = context.createBuffer(); | |
// WebGLBufferのバインド | |
context.bindBuffer(context.ARRAY_BUFFER, buffer); | |
// dataのセット | |
context.bufferData(context.ARRAY_BUFFER, data, context.STATIC_DRAW); | |
// バインドの解除 | |
context.bindBuffer(context.ARRAY_BUFFER, null); | |
return buffer; | |
} | |
// WebGLBufferをlocationで指定したアトリビュートに割り当てる | |
setAttribute(buffer,location,size,type = this.context.FLOAT,normalize =false,byteStride = 0,byteOffset = 0){ | |
// WebGL2RenderingContextコンテキスト | |
const context = this.context; | |
context.bindBuffer(context.ARRAY_BUFFER, buffer); | |
// locationのattributeを有効にする | |
context.enableVertexAttribArray(location); | |
// locationのattributeにWebGLBufferを割り当てる | |
context.vertexAttribPointer(location, size, type, normalize, byteStride, byteOffset); | |
} | |
/// WebGLVertexArrayObjectを生成し、返す | |
createVertexArray({dataArray,dataTypes,bufferTypes, locations, sizes, indexBuffer,indexBufferType}){ | |
// WebGL2RenderingContextコンテキスト | |
const context = this.context; | |
// WebGLVertexArrayObjectを生成する | |
const vao = context.createVertexArray(); | |
// WebGLVertexArrayObjectをバインドする | |
context.bindVertexArray(vao); | |
// 配列データからWebGLBufferを作成し、attributeに割り当てる | |
for(let i = 0,e = dataArray.length;i < e;++i){ | |
// WebGLBufferの生成 | |
let vbo = context.createBuffer(); | |
// WebGLBufferのバインド | |
context.bindBuffer(context.ARRAY_BUFFER, vbo); | |
// WebGLBufferにデータを設定する | |
context.bufferData(context.ARRAY_BUFFER, dataArray[i], bufferTypes ? bufferTypes[i] : context.STATIC_DRAW); | |
// locationのattributeを有効にする | |
context.enableVertexAttribArray(locations[i]); | |
// locationのattributeにWebGLBufferを割り当てる | |
context.vertexAttribPointer(locations[i], sizes[i], dataTypes ? dataTypes[i] : context.FLOAT, false, 0, 0); | |
} | |
// インデックスバッファーの生成 | |
if(indexBuffer){ | |
// WebGLBufferの作成 | |
let ibo = context.createBuffer(); | |
// WebGLBufferのバインド | |
context.bindBuffer(context.ELEMENT_ARRAY_BUFFER, ibo); | |
// WebGLBufferにインデックスデータを引き渡す | |
context.bufferData(context.ELEMENT_ARRAY_BUFFER, new UInt32Array(iboData), indexBufferType ? indexBufferType : context.STATIC_DRAW); | |
} | |
// WebGLVertexArrayObjectのバインドを解除 | |
context.bindVertexArray(null); | |
return vao; | |
} | |
setMatrix({model,view,projection}){ | |
this.model = model ? model : this.model; | |
this.view = view ? view : this.view; | |
this.projection = projection ? projection : this.projection; | |
this.mvp = this.model.multiply(this.projection.multiply(this.view)); | |
} | |
resize(){ | |
this.width = window.innerWidth; | |
this.height = window.innerHeight; | |
this.setMatrix({projection:Mat4.createPerspective({fovy:90, aspect:this.width / this.height, near:0.1, far:100})}); | |
} | |
// uniform変数に値を設定する | |
setUniformValue(prg,attributeName,value) | |
{ | |
// uniform変数の位置を取得する | |
var uniLocation = this.context.getUniformLocation(prg, 'mvpMatrix'); | |
// uniform変数に値を設定する | |
this.context.uniformMatrix4fv(uniLocation, false, value); | |
} | |
} | |
export default GL2; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html lang="ja"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>WebGL 2.0</title> | |
<link rel="stylesheet" href="./dat.gui.css" /> | |
<script src="./dat.gui.min.js"></script> | |
<script type="text/javascript" src="./bundle.js"></script> | |
<style> | |
body { | |
margin: 0; | |
padding: 0; | |
overflow: hidden; | |
} | |
#container { | |
position: relative; | |
} | |
#info { | |
left: 25vw; | |
top: 50vh; | |
width: 50vw; | |
position: absolute; | |
background: white; | |
color: black; | |
opacity: 0.5; | |
margin: auto; | |
text-align: center; | |
font-size: 3vw; | |
} | |
canvas#screen { | |
width: 100vw; | |
height: 100vh; | |
margin: 0; | |
padding: 0; | |
} | |
.error { | |
color:red; | |
font-size: 16px; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="container"> | |
<div id="info"></div> | |
</div> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use strict" | |
// 4x4 行列クラス | |
import Mat4 from './mat4.js'; | |
// WebGL2.0 ラッパー | |
import GL2 from './gl2.js'; | |
function loadTexture(src) { | |
return new Promise((resolve, reject) => { | |
const img = new Image(); | |
img.addEventListener('load', () => { | |
resolve(img); | |
}); | |
img.src = src; | |
}); | |
} | |
// 頂点シェーダ | |
const vertexShader = | |
`#version 300 es | |
layout (location = 0) in vec3 position; | |
layout (location = 1) in vec4 color; | |
uniform mat4 mvpMatrix; | |
out vec4 oColor; | |
void main(void){ | |
gl_Position = mvpMatrix * vec4(position,1.0); | |
oColor = color; | |
} | |
`; | |
// フラグメントシェーダ | |
const fragmentShader = | |
`#version 300 es | |
precision highp float; | |
out vec4 color; | |
in vec4 oColor; | |
void main(void){ | |
color = oColor; | |
} | |
`; | |
document.addEventListener('DOMContentLoaded', () => { | |
// ローディング中の情報表示 | |
const info = document.getElementById('info'); | |
info.innerText = 'ロード中...しばらくお待ちください。'; | |
// GL2クラスの生成 | |
let gl2; | |
try { | |
gl2 = new GL2({ elem: document.getElementById('container') }); | |
} catch (e) { | |
info = e.message; | |
return; | |
} | |
// gl2オブジェクトからコンテキストを取り出す | |
const ctx = gl2.context; | |
// 画面クリアカラーの設定 | |
ctx.clearColor(0.0 /* Red */, 0.0 /* Green */, 0.0 /* Blue */, 1.0 /* Alpha */); | |
// 深度バッファのクリア値の設定 | |
ctx.clearDepth(1.0); | |
// 画面クリア | |
ctx.clear(ctx.COLOR_BUFFER_BIT | ctx.DEPTH_BUFFER_BIT); | |
// 頂点シェーダの作成 | |
const vs = gl2.createShader(vertexShader, ctx.VERTEX_SHADER); | |
// フラグメントシェーダの作成 | |
const fs = gl2.createShader(fragmentShader, ctx.FRAGMENT_SHADER); | |
// プログラムの作成 | |
const prg = gl2.createProgram(vs, fs); | |
// 現在のレンダリングステートにプログラムを割り当てる | |
gl2.useProgram(prg); | |
// 頂点情報 | |
const vertices = new Float32Array([ | |
0.0, 1.0, 0.0, | |
1.0, 0.0, 0.0, | |
-1.0, 0.0, 0.0 | |
]); | |
// 色情報 | |
const colors = new Float32Array([ | |
0.0 /* Red */, 1.0 /* Green */, 0.0 /* Blue */, 1.0 /* Alpha */, | |
0.0, 0.0, 1.0, 1.0, | |
1.0, 0.0, 0.0, 1.0, | |
]); | |
// Vertex Array Objectの生成 | |
const vao = gl2.createVertexArray({ | |
dataArray:[vertices,colors], | |
locations:[0,1], | |
sizes:[3,4] | |
}); | |
// Vertex Array Objectのバインド | |
ctx.bindVertexArray(vao); | |
// 各種行列の生成と初期化 | |
gl2.setMatrix({ | |
model:new Mat4().identity(), | |
view:Mat4.createLookAt({eye:[0.0, 1.0, 3.0], center:[0, 0, 0], up:[0, 1, 0]}), | |
projection: Mat4.createPerspective({fovy:90, aspect:gl2.width / gl2.height, near:0.1, far:100}) | |
}); | |
gl2.setUniformValue(prg,'mvpMatrix',gl2.mvp.matrix); | |
render(); | |
// windows resize時の処理 | |
window.addEventListener('resize', () => { | |
if (gl2) { | |
gl2.resize(); | |
gl2.setUniformValue(prg,'mvpMatrix',gl2.mvp.matrix); | |
render(); | |
} | |
}); | |
info.style.display = 'none'; | |
// レンダリング処理 | |
function render() { | |
ctx.clear(ctx.COLOR_BUFFER_BIT | ctx.DEPTH_BUFFER_BIT); | |
ctx.drawArrays(ctx.TRIANGLES, 0, 3); | |
ctx.flush(); | |
} | |
// レンダリングループ | |
function renderLoop() { | |
render(); | |
requestAnimationFrame(renderLoop); // ループ処理 | |
} | |
}); | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ------------------------------------------------------------------------------------------------ | |
// mat4.js | |
// doxasさんのminMatrix.jsをES6バージョンに改造したもの | |
// https://wgld.org/d/library/l001.html | |
// ------------------------------------------------------------------------------------------------ | |
class Mat4 { | |
constructor(m = new Float32Array(16)) { | |
this.matrix = m; | |
} | |
identity() { | |
const dest = this.matrix; | |
dest[0] = 1; dest[1] = 0; dest[2] = 0; dest[3] = 0; | |
dest[4] = 0; dest[5] = 1; dest[6] = 0; dest[7] = 0; | |
dest[8] = 0; dest[9] = 0; dest[10] = 1; dest[11] = 0; | |
dest[12] = 0; dest[13] = 0; dest[14] = 0; dest[15] = 1; | |
return this; | |
} | |
multiply(matrix, destMatrix = new Mat4()) { | |
const mat1 = this.matrix, mat2 = matrix.matrix; | |
const dest = destMatrix.matrix; | |
const a = mat1[0], b = mat1[1], c = mat1[2], d = mat1[3], | |
e = mat1[4], f = mat1[5], g = mat1[6], h = mat1[7], | |
i = mat1[8], j = mat1[9], k = mat1[10], l = mat1[11], | |
m = mat1[12], n = mat1[13], o = mat1[14], p = mat1[15], | |
A = mat2[0], B = mat2[1], C = mat2[2], D = mat2[3], | |
E = mat2[4], F = mat2[5], G = mat2[6], H = mat2[7], | |
I = mat2[8], J = mat2[9], K = mat2[10], L = mat2[11], | |
M = mat2[12], N = mat2[13], O = mat2[14], P = mat2[15]; | |
dest[0] = A * a + B * e + C * i + D * m; | |
dest[1] = A * b + B * f + C * j + D * n; | |
dest[2] = A * c + B * g + C * k + D * o; | |
dest[3] = A * d + B * h + C * l + D * p; | |
dest[4] = E * a + F * e + G * i + H * m; | |
dest[5] = E * b + F * f + G * j + H * n; | |
dest[6] = E * c + F * g + G * k + H * o; | |
dest[7] = E * d + F * h + G * l + H * p; | |
dest[8] = I * a + J * e + K * i + L * m; | |
dest[9] = I * b + J * f + K * j + L * n; | |
dest[10] = I * c + J * g + K * k + L * o; | |
dest[11] = I * d + J * h + K * l + L * p; | |
dest[12] = M * a + N * e + O * i + P * m; | |
dest[13] = M * b + N * f + O * j + P * n; | |
dest[14] = M * c + N * g + O * k + P * o; | |
dest[15] = M * d + N * h + O * l + P * p; | |
return destMatrix; | |
}; | |
scale(vec, destMatrix = new Mat4()) { | |
const mat = this.matrix; | |
const dest = destMatrix.matrix; | |
dest[0] = mat[0] * vec[0]; | |
dest[1] = mat[1] * vec[0]; | |
dest[2] = mat[2] * vec[0]; | |
dest[3] = mat[3] * vec[0]; | |
dest[4] = mat[4] * vec[1]; | |
dest[5] = mat[5] * vec[1]; | |
dest[6] = mat[6] * vec[1]; | |
dest[7] = mat[7] * vec[1]; | |
dest[8] = mat[8] * vec[2]; | |
dest[9] = mat[9] * vec[2]; | |
dest[10] = mat[10] * vec[2]; | |
dest[11] = mat[11] * vec[2]; | |
dest[12] = mat[12]; | |
dest[13] = mat[13]; | |
dest[14] = mat[14]; | |
dest[15] = mat[15]; | |
return destMatrix; | |
}; | |
translate(vec, destMatrix = new Mat4()) { | |
const mat = this.matrix; | |
const dest = destMatrix.matrix; | |
dest[0] = mat[0]; dest[1] = mat[1]; dest[2] = mat[2]; dest[3] = mat[3]; | |
dest[4] = mat[4]; dest[5] = mat[5]; dest[6] = mat[6]; dest[7] = mat[7]; | |
dest[8] = mat[8]; dest[9] = mat[9]; dest[10] = mat[10]; dest[11] = mat[11]; | |
dest[12] = mat[0] * vec[0] + mat[4] * vec[1] + mat[8] * vec[2] + mat[12]; | |
dest[13] = mat[1] * vec[0] + mat[5] * vec[1] + mat[9] * vec[2] + mat[13]; | |
dest[14] = mat[2] * vec[0] + mat[6] * vec[1] + mat[10] * vec[2] + mat[14]; | |
dest[15] = mat[3] * vec[0] + mat[7] * vec[1] + mat[11] * vec[2] + mat[15]; | |
return destMatrix; | |
}; | |
rotate(angle, axis, destMatrix = new Mat4()) { | |
const dest = destMatrix.matrix; | |
const mat = this.matrix; | |
var sq = Math.sqrt(axis[0] * axis[0] + axis[1] * axis[1] + axis[2] * axis[2]); | |
if (!sq) { return null; } | |
var a = axis[0], b = axis[1], c = axis[2]; | |
if (sq != 1) { sq = 1 / sq; a *= sq; b *= sq; c *= sq; } | |
var d = Math.sin(angle), e = Math.cos(angle), f = 1 - e, | |
g = mat[0], h = mat[1], i = mat[2], j = mat[3], | |
k = mat[4], l = mat[5], m = mat[6], n = mat[7], | |
o = mat[8], p = mat[9], q = mat[10], r = mat[11], | |
s = a * a * f + e, | |
t = b * a * f + c * d, | |
u = c * a * f - b * d, | |
v = a * b * f - c * d, | |
w = b * b * f + e, | |
x = c * b * f + a * d, | |
y = a * c * f + b * d, | |
z = b * c * f - a * d, | |
A = c * c * f + e; | |
if (angle) { | |
if (mat != dest) { | |
dest[12] = mat[12]; dest[13] = mat[13]; | |
dest[14] = mat[14]; dest[15] = mat[15]; | |
} | |
} else { | |
dest = mat; | |
} | |
dest[0] = g * s + k * t + o * u; | |
dest[1] = h * s + l * t + p * u; | |
dest[2] = i * s + m * t + q * u; | |
dest[3] = j * s + n * t + r * u; | |
dest[4] = g * v + k * w + o * x; | |
dest[5] = h * v + l * w + p * x; | |
dest[6] = i * v + m * w + q * x; | |
dest[7] = j * v + n * w + r * x; | |
dest[8] = g * y + k * z + o * A; | |
dest[9] = h * y + l * z + p * A; | |
dest[10] = i * y + m * z + q * A; | |
dest[11] = j * y + n * z + r * A; | |
return destMatrix; | |
}; | |
static createLookAt({eye, center, up, destMatrix = new Mat4()}) { | |
const dest = destMatrix.matrix; | |
const eyeX = eye[0], eyeY = eye[1], eyeZ = eye[2], | |
upX = up[0], upY = up[1], upZ = up[2], | |
centerX = center[0], centerY = center[1], centerZ = center[2]; | |
if (eyeX == centerX && eyeY == centerY && eyeZ == centerZ) | |
{ | |
return destMatrix.identity(); | |
} | |
let x0, x1, x2, y0, y1, y2, z0, z1, z2, l; | |
z0 = eyeX - center[0]; | |
z1 = eyeY - center[1]; | |
z2 = eyeZ - center[2]; | |
l = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2); | |
z0 *= l; z1 *= l; z2 *= l; | |
x0 = upY * z2 - upZ * z1; | |
x1 = upZ * z0 - upX * z2; | |
x2 = upX * z1 - upY * z0; | |
l = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2); | |
if (!l) { | |
x0 = 0; x1 = 0; x2 = 0; | |
} else { | |
l = 1 / l; | |
x0 *= l; x1 *= l; x2 *= l; | |
} | |
y0 = z1 * x2 - z2 * x1; y1 = z2 * x0 - z0 * x2; y2 = z0 * x1 - z1 * x0; | |
l = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2); | |
if (!l) { | |
y0 = 0; y1 = 0; y2 = 0; | |
} else { | |
l = 1 / l; | |
y0 *= l; y1 *= l; y2 *= l; | |
} | |
dest[0] = x0; dest[1] = y0; dest[2] = z0; dest[3] = 0; | |
dest[4] = x1; dest[5] = y1; dest[6] = z1; dest[7] = 0; | |
dest[8] = x2; dest[9] = y2; dest[10] = z2; dest[11] = 0; | |
dest[12] = -(x0 * eyeX + x1 * eyeY + x2 * eyeZ); | |
dest[13] = -(y0 * eyeX + y1 * eyeY + y2 * eyeZ); | |
dest[14] = -(z0 * eyeX + z1 * eyeY + z2 * eyeZ); | |
dest[15] = 1; | |
return destMatrix; | |
}; | |
static createPerspective({fovy, aspect, near, far, destMatrix = new Mat4()}) { | |
const dest = destMatrix.matrix; | |
const t = near * Math.tan(fovy * Math.PI / 360); | |
const r = t * aspect; | |
const a = r * 2, b = t * 2, c = far - near; | |
dest[0] = near * 2 / a; | |
dest[1] = 0; | |
dest[2] = 0; | |
dest[3] = 0; | |
dest[4] = 0; | |
dest[5] = near * 2 / b; | |
dest[6] = 0; | |
dest[7] = 0; | |
dest[8] = 0; | |
dest[9] = 0; | |
dest[10] = -(far + near) / c; | |
dest[11] = -1; | |
dest[12] = 0; | |
dest[13] = 0; | |
dest[14] = -(far * near * 2) / c; | |
dest[15] = 0; | |
return destMatrix; | |
}; | |
transpose(destMatrix = new Mat4()) { | |
const mat = this.matrix; | |
const dest = destMatrix.matrix; | |
dest[0] = mat[0]; dest[1] = mat[4]; | |
dest[2] = mat[8]; dest[3] = mat[12]; | |
dest[4] = mat[1]; dest[5] = mat[5]; | |
dest[6] = mat[9]; dest[7] = mat[13]; | |
dest[8] = mat[2]; dest[9] = mat[6]; | |
dest[10] = mat[10]; dest[11] = mat[14]; | |
dest[12] = mat[3]; dest[13] = mat[7]; | |
dest[14] = mat[11]; dest[15] = mat[15]; | |
return destMatrix; | |
}; | |
inverse(destMatrix = new Mat4()) { | |
const dest = destMatrix.matrix; | |
const mat = this.matrix; | |
const a = mat[0], b = mat[1], c = mat[2], d = mat[3], | |
e = mat[4], f = mat[5], g = mat[6], h = mat[7], | |
i = mat[8], j = mat[9], k = mat[10], l = mat[11], | |
m = mat[12], n = mat[13], o = mat[14], p = mat[15], | |
q = a * f - b * e, r = a * g - c * e, | |
s = a * h - d * e, t = b * g - c * f, | |
u = b * h - d * f, v = c * h - d * g, | |
w = i * n - j * m, x = i * o - k * m, | |
y = i * p - l * m, z = j * o - k * n, | |
A = j * p - l * n, B = k * p - l * o, | |
ivd = 1 / (q * B - r * A + s * z + t * y - u * x + v * w); | |
dest[0] = (f * B - g * A + h * z) * ivd; | |
dest[1] = (-b * B + c * A - d * z) * ivd; | |
dest[2] = (n * v - o * u + p * t) * ivd; | |
dest[3] = (-j * v + k * u - l * t) * ivd; | |
dest[4] = (-e * B + g * y - h * x) * ivd; | |
dest[5] = (a * B - c * y + d * x) * ivd; | |
dest[6] = (-m * v + o * s - p * r) * ivd; | |
dest[7] = (i * v - k * s + l * r) * ivd; | |
dest[8] = (e * A - f * y + h * w) * ivd; | |
dest[9] = (-a * A + b * y - d * w) * ivd; | |
dest[10] = (m * u - n * s + p * q) * ivd; | |
dest[11] = (-i * u + j * s - l * q) * ivd; | |
dest[12] = (-e * z + f * x - g * w) * ivd; | |
dest[13] = (a * z - b * x + c * w) * ivd; | |
dest[14] = (-m * t + n * r - o * q) * ivd; | |
dest[15] = (i * t - j * r + k * q) * ivd; | |
return destMatrix; | |
}; | |
} | |
export default Mat4; | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "webgl2-0001", | |
"version": "1.0.0", | |
"description": "wgld.orgのソースコードをWebGL2ベースに書き換えてみる\r まずは三角形を描画してみる。", | |
"main": "main.js", | |
"scripts": { | |
"test": "browser-sync start -s -f *.html *.js", | |
"build": "rollup -c", | |
"watch": "watch \"npm run build\" ./ --filter=filter.js --wait=0 --interval=1" | |
}, | |
"repository": { | |
"type": "git", | |
"url": "git+ssh://git@gist.github.com/47c33ee5ac5199e126fa6a6b2f974f80.git" | |
}, | |
"keywords": [ | |
"WebGL2.0" | |
], | |
"author": "S.F.", | |
"license": "MIT", | |
"bugs": { | |
"url": "https://gist.github.com/47c33ee5ac5199e126fa6a6b2f974f80" | |
}, | |
"homepage": "https://gist.github.com/47c33ee5ac5199e126fa6a6b2f974f80", | |
"devDependencies": { | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// rollup.config.js | |
export default { | |
entry: 'main.js', | |
format:'iife', | |
dest: 'bundle.js' // equivalent to --output | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment