├── .nojekyll ├── docs ├── .nojekyll ├── assets │ ├── images │ │ ├── icons.png │ │ ├── icons@2x.png │ │ ├── widgets.png │ │ └── widgets@2x.png │ └── js │ │ └── search.json ├── globals.html ├── index.html └── modules │ └── _glea_.html ├── .prettierignore ├── .prettierrc.yaml ├── .gitignore ├── .travis.yml ├── jest.config.js ├── server.js ├── examples ├── hello-world.html ├── multi-shaders.html ├── hello-world.mjs ├── multi-shaders.mjs └── vendor │ ├── ella.d.ts │ └── ella.esm.js ├── rollup.config.js ├── CONTRIBUTING.md ├── .github └── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── index.html ├── LICENSE ├── package.json ├── CODE_OF_CONDUCT.md ├── src ├── glea.test.ts └── glea.ts ├── tsconfig.json ├── dist ├── glea.min.js ├── glea.umd.min.js ├── glea.d.ts ├── glea.js └── glea.umd.js └── README.md /.nojekyll: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/.nojekyll: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | dist 2 | docs 3 | -------------------------------------------------------------------------------- /.prettierrc.yaml: -------------------------------------------------------------------------------- 1 | semi: true 2 | singleQuote: true 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | Thumbs.db 3 | coverage 4 | 5 | node_modules 6 | -------------------------------------------------------------------------------- /docs/assets/images/icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/learosema/glea/HEAD/docs/assets/images/icons.png -------------------------------------------------------------------------------- /docs/assets/images/icons@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/learosema/glea/HEAD/docs/assets/images/icons@2x.png -------------------------------------------------------------------------------- /docs/assets/images/widgets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/learosema/glea/HEAD/docs/assets/images/widgets.png -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '12' 4 | os: linux 5 | dist: xenial 6 | install: 7 | - npm i 8 | -------------------------------------------------------------------------------- /docs/assets/images/widgets@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/learosema/glea/HEAD/docs/assets/images/widgets@2x.png -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'ts-jest', 3 | testEnvironment: 'jsdom', 4 | setupFiles: ['jest-webgl-canvas-mock'], 5 | }; 6 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | const PORT = 1337 || process.env.PORT; 2 | const HOST = 'localhost' || process.env.HOST; 3 | const express = require('express'); 4 | const app = express(); 5 | app.use(express.static('.')); 6 | 7 | app.listen(PORT, HOST, () => 8 | console.log(`Server listening on http://${HOST}:${PORT}/`) 9 | ); 10 | -------------------------------------------------------------------------------- /examples/hello-world.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 |Generated using TypeDoc
114 |GLea is a low-level WebGL library with a minimal footprint. 71 | It provides helper functions for creating a WebGL program, compiling shaders and passing data from JavaScript to the shader language.
72 | 73 |There are several options to embed GLea into your project. You can load GLea directly via script tag:
76 |<script src="https://unpkg.com/glea@latest/dist/glea.umd.min.js"></script>
77 | Inside a JavaScript ES module:
78 |import GLea from 'https://cdn.skypack.dev/glea';
79 | Or via NPM, you can install GLea via npm i glea and import it like this:
import GLea from 'glea';
81 |
82 | By default, GLea looks for a canvas element in your HTML and uses that. If there is no canvas element existing, GLea creates one for you.
85 |If your HTML document doesn't include any CSS (neither a style nor a link tag, a minimal stylesheet is provided that sizes the canvas to the browser's viewport size.
The GLea instance expects a shaders property, containing your fragment and vertex shader. 87 | Also, a buffers property, which contains the data that is passed as attributes to the vertex shader.
88 |If no buffers are provided, GLea provides a default position attribute with a buffer containing 4 vec2 values for a triangle strip, defining a plane filling the screen.
89 | 90 |GLea provides several helper functions to set uniforms to pass data from JavaScript to GLSL. These are:
93 |// set uniform float
94 | glea.uni('pi', Math.PI);
95 |
96 | // set uniform int
97 | glea.uniI('width', innerWidth);
98 |
99 | // set uniform float vector (supported types are vec2, vec3, vec4)
100 | glea.uniV('vector', [Math.sqrt(2), Math.sqrt(3)]);
101 |
102 | // set uniform int vector
103 | glea.uniIV('resolution', [innerWidth, innerHeight]);
104 |
105 | // set uniform matrix
106 | // HEADS UP: it is the other way round as you would write it down on paper
107 | // prettier-ignore
108 | glea.uniM('translateMatrix', [
109 | 1, 0, 0, 0, // column 1
110 | 0, 1, 0, 0, // column 2
111 | 0, 0, 1, 0, // column 3
112 | x, y, z, 1, // column 4
113 | ]);
114 |
115 | GLea provides a wrapper to drawArrays from the underlying WebGLRenderingContext. It works exactly like the original drawArrays function, but if you don't provide any vertex count, it is determined 118 | automatically from the buffers.
119 |const { gl } = glea;
120 |
121 | glea.drawArrays(gl.TRIANGLE_STRIP);
122 |
123 | // The same as:
124 | const numVertices = 4;
125 | glea.gl.drawArrays(gl.TRIANGLE_STRIP, 0, numVertices);
126 |
127 | GLea supports multiple programs.
130 |const prg1 = new GLea({
131 | shaders: [GLea.vertexShader(vert), GLea.fragmentShader(frag)],
132 | }).create();
133 |
134 | const prg2 = prg1.add({
135 | shaders: [GLea.vertexShader(vert2), GLea.fragmentShader(frag2)],
136 | buffers: {
137 | position: GLea.buffer(3, Ella.Geometry.sphere(0.25, 32, 16).toTriangles()),
138 | },
139 | });
140 | The the main instance prg1 and its child prg2 use the same underlying WebGLRenderingContext.
141 | In the example prg1 renders a plane geometry (GLea provides a position attribute with a plane geometry by default),
142 | and prg2 provides a sphere geometry. The sphere geometry is provided by ella-math.
In the draw loop, the switching between programs is done via enableAttribs and disableAttribs:
// Shader 1 does the background animation
145 | prg1.gl.disable(gl.DEPTH_TEST);
146 | prg1.enableAttribs();
147 | prg1.uniV('resolution', [width, height]);
148 | prg1.uni('time', time * 1e-3);
149 | prg1.drawArrays(gl.TRIANGLE_STRIP);
150 | prg1.disableAttribs();
151 |
152 | // Shader 2 renders a sphere
153 | gl.enable(gl.DEPTH_TEST);
154 | prg2.enableAttribs();
155 | prg2.uniV('resolution', [width, height]);
156 | prg2.uni('time', time * 1e-3);
157 | prg2.uniM('uPM', this.projectionMat.toArray());
158 | prg2.uniM('uVM', this.viewMat.toArray());
159 | prg2.drawArrays(gl.TRIANGLES);
160 | prg2.disableAttribs();
161 |
162 |
163 | I'm using a loadImage helper function that wraps img.onload into a Promise:
function loadImage(url) {
167 | return new Promise((resolve, reject) => {
168 | const img = new Image();
169 | img.crossOrigin = 'Anonymous';
170 | img.src = url;
171 | img.onload = () => {
172 | resolve(img);
173 | };
174 | img.onerror = () => {
175 | reject(img);
176 | };
177 | });
178 | }
179 |
180 | async function setup() {
181 | const img = await loadImage('https://placekitten.com/256/256/');
182 | const textureIndex = 0;
183 | glea.createTexture(textureIndex);
184 | glea.gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
185 | glea.uniI('texture0', textureIndex);
186 | }
187 |
188 | setup();
189 | In GLSL, you can access the texture like this:
190 |uniform sampler2D texture0;
191 |
192 | void main() {
193 | vec2 coord = 1.0 - gl_FragCoord.xy / vec2(width, height);
194 | gl_FragColor = texture2D(texture1, coord);
195 | }
196 |
197 | import GLea from 'https://cdn.skypack.dev/glea';
200 |
201 | const vert = `
202 | precision highp float;
203 | attribute vec2 position;
204 |
205 | void main() {
206 | gl_Position = vec4(position, 0, 1.0);
207 | }
208 | `;
209 |
210 | const frag = `
211 | precision highp float;
212 | uniform float time;
213 | uniform vec2 resolution;
214 |
215 | void main() {
216 | float vmin = min(resolution.y, resolution.x);
217 | vec2 p = (gl_FragCoord.xy - .5 * resolution) / vmin;
218 | float r = .5 + .5 * sin(5. * log(length(p)) - time * 1.2);
219 | float g = .5 + .5 * sin(5. * log(length(p)) + sin(time + 2. * p.x));
220 | float b = .5 + .5 * sin(.2 + 5. * log(length(p)) + sin(time * .4 + 4. * p.y));
221 | gl_FragColor = vec4(r, g, b, 1.);
222 | }
223 | `;
224 |
225 | const glea = new GLea({
226 | shaders: [GLea.fragmentShader(frag), GLea.vertexShader(vert)],
227 | buffers: {
228 | // create a position attribute bound
229 | // to a buffer with 4 2D coordinates
230 | // this is what GLea provides by default if you omit buffers in the constructor
231 | position: GLea.buffer(2, [1, 1, -1, 1, 1, -1, -1, -1]),
232 | },
233 | }).create();
234 |
235 | function loop(time) {
236 | const { gl, width, height } = glea;
237 | glea.clear();
238 | glea.uniV('resolution', [width, height]);
239 | glea.uni('time', time * 1e-3);
240 | gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
241 | requestAnimationFrame(loop);
242 | }
243 |
244 | function setup() {
245 | const { gl } = glea;
246 | window.addEventListener('resize', () => {
247 | glea.resize();
248 | });
249 | loop(0);
250 | }
251 |
252 | setup();
253 | Generated using TypeDoc
323 |function that registers an attribute and binds a buffer to it
161 |GLea - GL experience artistry Library
239 |function that compiles a shader
259 |Generated using TypeDoc
387 |
store for an attribute and a buffer
114 |