Skip to content

Instantly share code, notes, and snippets.

@strangerintheq
Last active January 24, 2022 18:34
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save strangerintheq/27b8fc4e53432d8b9284364713ce8608 to your computer and use it in GitHub Desktop.
Save strangerintheq/27b8fc4e53432d8b9284364713ce8608 to your computer and use it in GitHub Desktop.
Render full screen triangle in WebGL 2

A minimalistic method for rendering a triangle in WebGL 2 that covers the screen with no buffer inputs.

Usable for post effects or something similar to https://shadertoy.com

All vertex and texture coordinate information are generated in vertex shader from the built-in gl_VertexID variable

var canvas = document.body.appendChild(document.createElement('canvas'));
var gl = canvas.getContext('webgl2');
gl.viewport(0, 0, canvas.width = window.innerWidth, canvas.height = window.innerHeight);
var program = createProgram(glsl('shader-vertex'), glsl('shader-fragment'));
var mouse = program.createUniform('2f', 'mouse');
gl.useProgram(program);
render();
listen("mousemove");
listen("touchstart");
function listen(eventType){
window.addEventListener(eventType, function (e) {
mouse(e.x, canvas.height - e.y);
render();
});
}
function render(){
gl.drawArrays(gl.TRIANGLE_FAN, 0, 3);
}
function createShader(source, type) {
var shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS))
throw new Error(gl.getShaderInfoLog(shader));
return shader;
}
function createProgram(vertex, fragment) {
var program = gl.createProgram();
gl.attachShader(program, createShader(vertex, gl.VERTEX_SHADER));
gl.attachShader(program, createShader(fragment, gl.FRAGMENT_SHADER));
gl.linkProgram(program);
program.createUniform = function (type, name) {
var location = gl.getUniformLocation(program, name);
return function (v1, v2, v3, v4) {
gl['uniform' + type](location, v1, v2, v3, v4);
}
};
return program;
}
function glsl(name) {
var xhr = new XMLHttpRequest();
xhr.open('get', name + '.glsl', false);
xhr.send();
return xhr.responseText;
}
<!DOCTYPE html>
<html lang="en">
<body style="margin: 0; overflow: hidden;">
<script src="full-screen-triangle.js"></script>
</body>
</html>
#version 300 es
precision highp float;
uniform vec2 mouse;
in vec2 texCoord;
out vec4 fragmentColor;
void main(void) {
fragmentColor = vec4(mouse.x/1000., mouse.y/1000., 0.0, 1.0);
float x = gl_FragCoord.x - mouse.x;
float y = gl_FragCoord.y - mouse.y;
fragmentColor.a = (x*x + y*y)/500.;
}
#version 300 es
precision highp float;
out vec2 texCoord;
void main(void) {
float x = float((gl_VertexID & 1) << 2);
float y = float((gl_VertexID & 2) << 1);
texCoord.x = x * 0.5;
texCoord.y = y * 0.5;
gl_Position = vec4(x - 1.0, y - 1.0, 0, 1);
}
@clankill3r
Copy link

I just want to point out that this gives the following warning:

WebGL warning: drawArraysInstanced: Drawing without vertex attrib 0 array enabled forces the browser to do expensive emulation work when running on desktop OpenGL platforms, for example on Mac. It is preferable to always draw with vertex attrib 0 array enabled, by using bindAttribLocation to bind some always-used attribute to location 0.

For the rest it is great.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment