Skip to content

Instantly share code, notes, and snippets.

@greggman
Last active April 9, 2024 19:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save greggman/c80dc13401ee03a4ef74bcde8538fed9 to your computer and use it in GitHub Desktop.
Save greggman/c80dc13401ee03a4ef74bcde8538fed9 to your computer and use it in GitHub Desktop.
WebGL 1/2 Depth Texture Test
body {
font-family: monospace;
}
canvas { border: 1px solid black; }
pre { margin: 0; }
.test {
display: inline-block;
border: 1px solid #888;
padding: 1em;
margin: 5px;
}
<script src="https://greggman.github.io/webgl-lint/webgl-lint.js" crossorigin></script>
<script src="https://greggman.github.io/webgl-fundamentals/webgl/resources/webgl-utils.js"></script>
<script id="vshader" type="whatever">
attribute vec4 a_position;
varying vec2 v_texcoord;
void main() {
gl_Position = a_position;
v_texcoord = a_position.xy * 0.5 + 0.5;
}
</script>
<script id="fshader" type="whatever">
precision mediump float;
varying vec2 v_texcoord;
uniform sampler2D u_sampler;
void main() {
gl_FragColor = vec4(texture2D(u_sampler, v_texcoord).rgb, 1);
}
</script>
<script id="vshader2" type="whatever">#version 300 es
in vec4 a_position;
out vec2 v_texcoord;
void main() {
gl_Position = a_position;
v_texcoord = a_position.xy * 0.5 + 0.5;
}
</script>
<script id="fshader2" type="whatever">#version 300 es
precision mediump float;
in vec2 v_texcoord;
uniform sampler2D u_sampler;
out vec4 fragColor;
void main() {
fragColor = vec4(texture(u_sampler, v_texcoord).rgb, 1);
}
</script>
function test(version, internalFormat, filtering, wrap) {
const container = document.createElement('div');
container.className = 'test';
document.body.appendChild(container);
var canvas = document.createElement('canvas');
canvas.width = 64;
canvas.height = 64;
container.appendChild(canvas);
var gl = canvas.getContext(version);
if (!gl) {
alert("no WebGL");
}
logElem(container, `\
${version}
${glEnumToString(gl, internalFormat)}
${glEnumToString(gl, filtering)}
${glEnumToString(gl, wrap)}`);
// enable depth textures.
if (version === 'webgl') {
var depthTextureExtension = gl.getExtension("WEBGL_depth_texture");
if (!depthTextureExtension) {
alert("depth textures not supported");
return;
}
}
var w = canvas.width;
var h = canvas.height;
var program = createProgramFromScripts(
gl, version === 'webgl' ? ["vshader", "fshader"] : ["vshader2", "fshader2"], ["a_position"]);
gl.useProgram(program);
var verts = [
1, 1, 1,
-1, 1, 0,
-1, -1, -1,
1, 1, 1,
-1, -1, -1,
1, -1, 0,
];
var vertBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verts), gl.STATIC_DRAW);
gl.enableVertexAttribArray(0);
gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
// Create color texture to attach as well otherwise we might not get a valid framebuffer
var colorTex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, colorTex);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, w, h, 0,
gl.RGBA, gl.UNSIGNED_BYTE, null);
// create a depth texture.
var depthTex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, depthTex);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrap);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrap);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filtering);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filtering);
if (version === 'webgl2') {
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAX_LEVEL, 0);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAX_LOD, 0);
}
let type;
switch (internalFormat) {
case gl.DEPTH_COMPONENT:
case gl.DEPTH_COMPONENT16:
type = gl.UNSIGNED_SHORT;
break;
case gl.DEPTH_COMPONENT32F:
type = gl.FLOAT;
break;
default:
type = gl.UNSIGNED_INT;
break;
}
gl.texImage2D(gl.TEXTURE_2D, 0, internalFormat, w, h, 0,
gl.DEPTH_COMPONENT, type, null);
// Create a framebuffer and attach the textures.
var fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT,
gl.TEXTURE_2D, depthTex, 0);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
gl.TEXTURE_2D, colorTex, 0);
gl.bindTexture(gl.TEXTURE_2D, null);
if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
alert("framebuffer not complete");
}
// use a 1px texture to render with while we render to the depth texture.
const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([0, 255, 0, 255]));
// Turn on depth testing so we can write to the depth texture.
gl.enable(gl.DEPTH_TEST);
// Render to the depth texture
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES, 0, 6);
// Now draw with the texture to the canvas
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
gl.bindTexture(gl.TEXTURE_2D, depthTex);
gl.drawArrays(gl.TRIANGLES, 0, 6);
}
test('webgl', WebGLRenderingContext.DEPTH_COMPONENT, WebGLRenderingContext.LINEAR, WebGLRenderingContext.CLAMP_TO_EDGE);
for (let internalFormat of [
WebGL2RenderingContext.DEPTH_COMPONENT16,
WebGL2RenderingContext.DEPTH_COMPONENT24,
WebGL2RenderingContext.DEPTH_COMPONENT32F,
]) {
for (let filtering of [
WebGLRenderingContext.NEAREST,
WebGLRenderingContext.LINEAR,
]) {
for (let wrap of [
WebGLRenderingContext.CLAMP_TO_EDGE,
WebGLRenderingContext.REPEAT,
]) {
test('webgl2', internalFormat, filtering, wrap); //, compareMode);
}
}
}
function logElem(parent, ...args) {
const elem = document.createElement('pre');
elem.textContent = args.join(' ');
parent.appendChild(elem);
}
function glEnumToString(gl, value) {
if (value === 0) {
return 'NONE';
}
const keys = [];
for (const key in gl) {
if (gl[key] === value) {
keys.push(key);
}
}
return keys.length ? keys.join(' | ') : value === undefined ? 'undefined' : `0x${value.toString(16)}`;
}
{"name":"WebGL 1/2 Depth Texture Test","settings":{},"filenames":["index.html","index.css","index.js"]}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment