
Security News
/Research
Popular node-ipc npm Package Infected with Credential Stealer
Socket detected malicious node-ipc versions with obfuscated stealer/backdoor behavior in a developing npm supply chain attack.
GLea is a low-level WebGL library with a minimal footprint. It provides helper functions for creating a WebGL program, compiling shaders and passing data from JavaScript to the shader language.
There are several options to embed GLea into your project. You can load GLea directly via script tag:
<script src="https://unpkg.com/glea@latest/dist/glea.umd.min.js"></script>
Inside a JavaScript ES module:
import GLea from 'https://cdn.skypack.dev/glea';
Or via NPM, you can install GLea via npm i glea and import it like this:
import GLea from 'glea';
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.
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. Also, a buffers property, which contains the data that is passed as attributes to the vertex shader.
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.
GLea provides several helper functions to set uniforms to pass data from JavaScript to GLSL. These are:
// set uniform float
glea.uni('pi', Math.PI);
// set uniform int
glea.uniI('width', innerWidth);
// set uniform float vector (supported types are vec2, vec3, vec4)
glea.uniV('vector', [Math.sqrt(2), Math.sqrt(3)]);
// set uniform int vector
glea.uniIV('resolution', [innerWidth, innerHeight]);
// set uniform matrix
// HEADS UP: it is the other way round as you would write it down on paper
// prettier-ignore
glea.uniM('translateMatrix', [
1, 0, 0, 0, // column 1
0, 1, 0, 0, // column 2
0, 0, 1, 0, // column 3
x, y, z, 1, // column 4
]);
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 automatically from the buffers.
const { gl } = glea;
glea.drawArrays(gl.TRIANGLE_STRIP);
// The same as:
const numVertices = 4;
glea.gl.drawArrays(gl.TRIANGLE_STRIP, 0, numVertices);
GLea supports multiple programs.
const prg1 = new GLea({
shaders: [GLea.vertexShader(vert), GLea.fragmentShader(frag)],
}).create();
const prg2 = prg1.add({
shaders: [GLea.vertexShader(vert2), GLea.fragmentShader(frag2)],
buffers: {
position: GLea.buffer(3, Ella.Geometry.sphere(0.25, 32, 16).toTriangles()),
},
});
The the main instance prg1 and its child prg2 use the same underlying WebGLRenderingContext.
In the example prg1 renders a plane geometry (GLea provides a position attribute with a plane geometry by default),
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
prg1.gl.disable(gl.DEPTH_TEST);
prg1.enableAttribs();
prg1.uniV('resolution', [width, height]);
prg1.uni('time', time * 1e-3);
prg1.drawArrays(gl.TRIANGLE_STRIP);
prg1.disableAttribs();
// Shader 2 renders a sphere
gl.enable(gl.DEPTH_TEST);
prg2.enableAttribs();
prg2.uniV('resolution', [width, height]);
prg2.uni('time', time * 1e-3);
prg2.uniM('uPM', this.projectionMat.toArray());
prg2.uniM('uVM', this.viewMat.toArray());
prg2.drawArrays(gl.TRIANGLES);
prg2.disableAttribs();
I'm using a loadImage helper function that wraps img.onload into a Promise:
function loadImage(url) {
return new Promise((resolve, reject) => {
const img = new Image();
img.crossOrigin = 'Anonymous';
img.src = url;
img.onload = () => {
resolve(img);
};
img.onerror = () => {
reject(img);
};
});
}
async function setup() {
const img = await loadImage('https://placekitten.com/256/256/');
const textureIndex = 0;
glea.createTexture(textureIndex);
glea.gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
glea.uniI('texture0', textureIndex);
}
setup();
In GLSL, you can access the texture like this:
uniform sampler2D texture0;
void main() {
vec2 coord = 1.0 - gl_FragCoord.xy / vec2(width, height);
gl_FragColor = texture2D(texture1, coord);
}
import GLea from 'https://cdn.skypack.dev/glea';
const vert = `
precision highp float;
attribute vec2 position;
void main() {
gl_Position = vec4(position, 0, 1.0);
}
`;
const frag = `
precision highp float;
uniform float time;
uniform vec2 resolution;
void main() {
float vmin = min(resolution.y, resolution.x);
vec2 p = (gl_FragCoord.xy - .5 * resolution) / vmin;
float r = .5 + .5 * sin(5. * log(length(p)) - time * 1.2);
float g = .5 + .5 * sin(5. * log(length(p)) + sin(time + 2. * p.x));
float b = .5 + .5 * sin(.2 + 5. * log(length(p)) + sin(time * .4 + 4. * p.y));
gl_FragColor = vec4(r, g, b, 1.);
}
`;
const glea = new GLea({
shaders: [GLea.fragmentShader(frag), GLea.vertexShader(vert)],
buffers: {
// create a position attribute bound
// to a buffer with 4 2D coordinates
// this is what GLea provides by default if you omit buffers in the constructor
position: GLea.buffer(2, [1, 1, -1, 1, 1, -1, -1, -1]),
},
}).create();
function loop(time) {
const { gl, width, height } = glea;
glea.clear();
glea.uniV('resolution', [width, height]);
glea.uni('time', time * 1e-3);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
requestAnimationFrame(loop);
}
function setup() {
const { gl } = glea;
window.addEventListener('resize', () => {
glea.resize();
});
loop(0);
}
setup();
FAQs
GL experience artistry
The npm package glea receives a total of 65 weekly downloads. As such, glea popularity was classified as not popular.
We found that glea demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
/Research
Socket detected malicious node-ipc versions with obfuscated stealer/backdoor behavior in a developing npm supply chain attack.

Security News
TeamPCP and BreachForums are promoting a Shai-Hulud supply chain attack contest with a $1,000 prize for the biggest package compromise.

Security News
Packagist urges PHP projects to update Composer after a GitHub token format change exposed some GitHub Actions tokens in CI logs.