Last active
August 6, 2025 02:42
-
-
Save greggman/8d1ab3515e3c7b4498f4ae3d3103178a to your computer and use it in GitHub Desktop.
WebGL2 - Generate Mipmap Speed Test
This file contains hidden or 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 url("https://webgl2fundamentals.org/webgl/resources/webgl-tutorials.css"); | |
body { | |
margin: 0; | |
} | |
#ui { | |
width: 100px; | |
background-color: red; | |
padding: 0.25em; | |
} | |
body, document { | |
user-select: none; | |
-webkit-user-select: none; | |
-moz-user-select: none; | |
-o-user-select: none; | |
-ms-user-select: none; | |
} | |
#uiContainer { | |
left: 10px; | |
top: 130px; | |
} | |
#info { | |
position: absolute; | |
left: 0; | |
top: 0; | |
background-color: black; | |
color: white; | |
margin: 0; | |
padding: 0.5em; | |
} | |
canvas { | |
width: initial; | |
height: initial; | |
} |
This file contains hidden or 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
<canvas id="canvas"></canvas> | |
<pre id="info"></pre> | |
<!-- | |
for most samples webgl-utils only provides shader compiling/linking and | |
canvas resizing because why clutter the examples with code that's the same in every sample. | |
See https://webgl2fundamentals.org/webgl/lessons/webgl-boilerplate.html | |
and https://webgl2fundamentals.org/webgl/lessons/webgl-resizing-the-canvas.html | |
for webgl-utils, m3, m4, and webgl-lessons-ui. | |
--> | |
<script src="https://webgl2fundamentals.org/webgl/resources/webgl-utils.js"></script> | |
<script src="https://webgl2fundamentals.org/webgl/resources/m4.js"></script> |
This file contains hidden or 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
// WebGL2 - Textures - Mips - Depth | |
// from https://webgl2fundamentals.org/webgl/webgl-3d-textures-mips-tri-linear.html | |
import GUI from 'https://webgpufundamentals.org/3rdparty/muigui-0.x.module.js'; | |
import RollingAverage from 'https://webgpufundamentals.org/webgpu/resources/js/rolling-average.js'; | |
"use strict"; | |
const fpsAverage = new RollingAverage(); | |
var vertexShaderSource = `#version 300 es | |
// an attribute is an input (in) to a vertex shader. | |
// It will receive data from a buffer | |
in vec4 a_position; | |
in vec2 a_texcoord; | |
// A matrix to transform the positions by | |
uniform mat4 u_matrix; | |
// a varying to pass the texture coordinates to the fragment shader | |
out vec2 v_texcoord; | |
// all shaders have a main function | |
void main() { | |
// Multiply the position by the matrix. | |
gl_Position = u_matrix * a_position; | |
// Pass the texcoord to the fragment shader. | |
v_texcoord = a_texcoord; | |
} | |
`; | |
var fragmentShaderSource = `#version 300 es | |
precision highp float; | |
// Passed in from the vertex shader. | |
in vec2 v_texcoord; | |
// The texture. | |
uniform sampler2D u_texture; | |
// we need to declare an output for the fragment shader | |
out vec4 outColor; | |
void main() { | |
outColor = texture(u_texture, v_texcoord); | |
} | |
`; | |
const maxTextures = 250; | |
var zDepth = 50; | |
function main() { | |
// Get A WebGL context | |
/** @type {HTMLCanvasElement} */ | |
var canvas = document.querySelector("#canvas"); | |
var gl = canvas.getContext("webgl2", {antialias: false}); | |
if (!gl) { | |
return; | |
} | |
const ext = gl.getExtension('WEBGL_debug_renderer_info'); | |
if (ext) { | |
console.log(gl.getParameter(ext.UNMASKED_RENDERER_WEBGL)); | |
console.log(gl.getParameter(ext.UNMASKED_VENDOR_WEBGL)); | |
} | |
// Use our boilerplate utils to compile the shaders and link into a program | |
var program = webglUtils.createProgramFromSources(gl, | |
[vertexShaderSource, fragmentShaderSource]); | |
// look up where the vertex data needs to go. | |
var positionAttributeLocation = gl.getAttribLocation(program, "a_position"); | |
var texcoordAttributeLocation = gl.getAttribLocation(program, "a_texcoord"); | |
// look up uniform locations | |
var matrixLocation = gl.getUniformLocation(program, "u_matrix"); | |
// Create a buffer | |
var positionBuffer = gl.createBuffer(); | |
// Create a vertex array object (attribute state) | |
var vao = gl.createVertexArray(); | |
// and make it the one we're currently working with | |
gl.bindVertexArray(vao); | |
// Turn on the attribute | |
gl.enableVertexAttribArray(positionAttributeLocation); | |
// Bind it to ARRAY_BUFFER (think of it as ARRAY_BUFFER = positionBuffer) | |
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); | |
// Set Geometry. | |
setGeometry(gl); | |
// Tell the attribute how to get data out of positionBuffer (ARRAY_BUFFER) | |
{ | |
const size = 3; // 3 components per iteration | |
const type = gl.FLOAT; // the data is 32bit floats | |
const normalize = false; // don't normalize the data | |
const stride = 0; // 0 = move forward size * sizeof(type) each iteration to get the next position | |
const offset = 0; // start at the beginning of the buffer | |
gl.vertexAttribPointer( | |
positionAttributeLocation, size, type, normalize, stride, offset); | |
} | |
// create the texcoord buffer, make it the current ARRAY_BUFFER | |
// and copy in the texcoord values | |
var texcoordBuffer = gl.createBuffer(); | |
gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer); | |
setTexcoords(gl); | |
// Turn on the attribute | |
gl.enableVertexAttribArray(texcoordAttributeLocation); | |
// Tell the attribute how to get data out of texcoordBuffer (ARRAY_BUFFER) | |
{ | |
const size = 2; // 2 components per iteration | |
const type = gl.FLOAT; // the data is 32bit floating point values | |
const normalize = true; // convert from 0-255 to 0.0-1.0 | |
const stride = 0; // 0 = move forward size * sizeof(type) each iteration to get the next color | |
const offset = 0; // start at the beginning of the buffer | |
gl.vertexAttribPointer( | |
texcoordAttributeLocation, size, type, normalize, stride, offset); | |
} | |
const size = 2048; | |
const half = size / 2; | |
// Create a texture. | |
const texture = gl.createTexture(); | |
// use texture unit 0 | |
gl.activeTexture(gl.TEXTURE0 + 0); | |
// bind to the TEXTURE_2D bind point of texture unit 0 | |
gl.bindTexture(gl.TEXTURE_2D, texture); | |
// Now that the image has loaded make copy it to the texture. | |
gl.bindTexture(gl.TEXTURE_2D, texture); | |
gl.texStorage2D(gl.TEXTURE_2D, Math.log2(size) + 1, gl.RGBA8, size, size); | |
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); | |
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_NEAREST); | |
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); | |
const fb = gl.createFramebuffer(); | |
gl.bindFramebuffer(gl.FRAMEBUFFER, fb); | |
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0); | |
gl.bindFramebuffer(gl.FRAMEBUFFER, null); | |
function degToRad(d) { | |
return d * Math.PI / 180; | |
} | |
// First let's make some variables | |
// to hold the translation, | |
var fieldOfViewRadians = degToRad(60); | |
let then = 0; | |
const info = document.querySelector('#info'); | |
const params = { | |
count: 1, | |
}; | |
const gui = new GUI(); | |
gui.add(params, 'count', 1, 1000, 1); | |
function render(time) { | |
const deltaTime = time - then; | |
then = time; | |
fpsAverage.addSample(deltaTime); | |
info.textContent = `fps: ${(1000 / fpsAverage.get()).toFixed(0)}`; | |
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height); | |
gl.clearColor(time / 1000 % 1, time / 1000 % 1.234, time / 1000 % 1.567, 1); | |
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); | |
// turn on depth testing | |
gl.enable(gl.DEPTH_TEST); | |
// tell webgl to cull faces | |
gl.enable(gl.CULL_FACE); | |
// Tell it to use our program (pair of shaders) | |
gl.useProgram(program); | |
// Bind the attribute/buffer set we want. | |
gl.bindVertexArray(vao); | |
for (let i = 0; i < params.count; ++i) { | |
gl.bindFramebuffer(gl.FRAMEBUFFER, fb); | |
gl.clear(gl.COLOR_BUFFER_BIT); | |
gl.bindFramebuffer(gl.FRAMEBUFFER, null); | |
gl.bindTexture(gl.TEXTURE_2D, texture); | |
gl.generateMipmap(gl.TEXTURE_2D); | |
gl.bindTexture(gl.TEXTURE_2D, texture); | |
// Draw the geometry. | |
gl.drawArrays(gl.TRIANGLES, 0, 1 * 6); | |
} | |
requestAnimationFrame(render); | |
} | |
requestAnimationFrame(render); | |
} | |
// Fill the current ARRAY_BUFFER buffer | |
// with the values that define a plane. | |
function setGeometry(gl) { | |
var positions = new Float32Array([ | |
-0.5, 0.5, -0.5, | |
0.5, 0.5, -0.5, | |
-0.5, 0.5, 0.5, | |
-0.5, 0.5, 0.5, | |
0.5, 0.5, -0.5, | |
0.5, 0.5, 0.5, | |
]); | |
gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW); | |
} | |
// Fill the current ARRAY_BUFFER buffer | |
// with texture coordinates for a plane | |
function setTexcoords(gl) { | |
gl.bufferData( | |
gl.ARRAY_BUFFER, | |
new Float32Array([ | |
0, 0, | |
1, 0, | |
0, zDepth, | |
0, zDepth, | |
1, 0, | |
1, zDepth, | |
]), | |
gl.STATIC_DRAW); | |
} | |
main(); | |
// This is needed if the images are not on the same domain | |
// NOTE: The server providing the images must give CORS permissions | |
// in order to be able to use the image with WebGL. Most sites | |
// do NOT give permission. | |
// See: http://webgl2fundamentals.org/webgl/lessons/webgl-cors-permission.html | |
function requestCORSIfNotSameOrigin(img, url) { | |
if ((new URL(url, window.location.href)).origin !== window.location.origin) { | |
img.crossOrigin = ""; | |
} | |
} |
This file contains hidden or 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 - Generate Mipmap Speed 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