Last active
January 31, 2024 14:56
-
-
Save bellbind/8c98bb86cfd064d944312b09b98af1b9 to your computer and use it in GitHub Desktop.
[webgl2]example for webgl2 (with glsl3)
This file contains 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
#version 300 es | |
precision highp float; | |
//invariant gl_FragCoord; | |
uniform Screen { | |
vec2 wh; | |
} screen; | |
uniform Timer { | |
int count; | |
} timer; | |
out vec4 fragColor; | |
vec4 colorSpace(vec2 coord) | |
{ | |
float other = 1.0 - (coord.x + coord.y) / 2.0; | |
return vec4(coord, other, 1.0); | |
} | |
// mandelbrot with animation | |
vec4 mandel(vec2 coord) | |
{ | |
vec2 c = 3.0 * (coord - vec2(2.0 / 3.0, 0.5)); | |
vec2 z = c; | |
const float pi = acos(-1.0); | |
int limit = int(20.0 * pow(sin(2.0 * pi * float(timer.count) / 256.0), 2.0)); | |
float color = 0.0; | |
for (int i = 0; i < limit; i++) { | |
vec2 z1 = vec2(z.x * z.x - z.y * z.y + c.x, 2.0 * z.x * z.y + c.y); | |
if (dot(z1, z1) > 4.0) { | |
color = float(i) / float(limit); | |
break; | |
} else { | |
z = z1; | |
} | |
} | |
return vec4(color, 0.0, 0.0, 1.0); | |
} | |
void main(void) | |
{ | |
vec2 coord = gl_FragCoord.xy / screen.wh; | |
//fragColor = colorSpace(coord); | |
fragColor = mandel(coord); | |
//fragColor = clamp(mandel(coord) + colorSpace(coord), vec4(0.0), vec4(1.0)); | |
} |
This file contains 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
<!doctype html> | |
<html> | |
<head> | |
<meta charset="utf-8" /> | |
<script src="script.js"></script> | |
</head> | |
<body></body> | |
</html> |
This file contains 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
"use strict"; | |
window.addEventListener("load", ev => { | |
// webgl setup | |
const canvas = document.createElement("canvas"); | |
canvas.width = 512, canvas.height = 512; | |
canvas.style.border = "solid"; | |
document.body.appendChild(canvas); | |
// webgl2 enabled default from: firefox-51, chrome-56 | |
const gl = canvas.getContext("webgl2"); | |
gl.enable(gl.CULL_FACE); | |
// drawing data (as viewport square) | |
const vert2d = [[1, 1], [-1, 1], [1, -1], [-1, -1]]; | |
const vert2dData = new Float32Array([].concat(...vert2d)); | |
const vertBuf = gl.createBuffer(); | |
gl.bindBuffer(gl.ARRAY_BUFFER, vertBuf); | |
gl.bufferData(gl.ARRAY_BUFFER, vert2dData, gl.STATIC_DRAW); | |
gl.bindBuffer(gl.ARRAY_BUFFER, null); | |
const index = [[0, 1, 2], [3, 2, 1]]; | |
const indexData = new Uint16Array([].concat(...index)); | |
const indexBuf = gl.createBuffer(); | |
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuf); | |
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indexData, gl.STATIC_DRAW); | |
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); | |
// opengl3 uniform buffer | |
// NOTE: each data attribute required 16 byte | |
const screenData = new Float32Array([canvas.width, canvas.height, 0, 0]); | |
const screenBuf = gl.createBuffer(); | |
gl.bindBuffer(gl.UNIFORM_BUFFER, screenBuf); | |
gl.bufferData(gl.UNIFORM_BUFFER, screenData, gl.DYNAMIC_DRAW); | |
gl.bindBuffer(gl.UNIFORM_BUFFER, null); | |
const timerData = new Uint32Array([0, 0, 0, 0]); | |
const timerBuf = gl.createBuffer(); | |
gl.bindBuffer(gl.UNIFORM_BUFFER, timerBuf); | |
gl.bufferData(gl.UNIFORM_BUFFER, timerData, gl.DYNAMIC_DRAW); | |
gl.bindBuffer(gl.UNIFORM_BUFFER, null); | |
// opengl3 VAO | |
const vertexArray = gl.createVertexArray(); | |
const setupVAO = (program) => { | |
// setup buffers and attributes to the VAO | |
gl.bindVertexArray(vertexArray); | |
// bind buffer data | |
gl.bindBuffer(gl.ARRAY_BUFFER, vertBuf); | |
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuf); | |
// set attribute types | |
const vert2dId = gl.getAttribLocation(program, "vert2d"); | |
const elem = gl.FLOAT, count = vert2d[0].length, normalize = false; | |
const offset = 0, stride = count * Float32Array.BYTES_PER_ELEMENT; | |
gl.enableVertexAttribArray(vert2dId); | |
gl.vertexAttribPointer( | |
vert2dId, count, elem, normalize, stride, offset); | |
gl.bindVertexArray(null); | |
//NOTE: these unbound buffers is not required; works fine if unbound | |
//gl.bindBuffer(gl.ARRAY_BUFFER, null); | |
//gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); | |
}; | |
// shader loader | |
const loadShader = (src, type) => { | |
const shader = gl.createShader(type); | |
gl.shaderSource(shader, src); | |
gl.compileShader(shader); | |
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { | |
console.log(src, gl.getShaderInfoLog(shader)); | |
} | |
return shader; | |
}; | |
const loadProgram = () => Promise.all([ | |
fetch("vertex.glsl").then(res => res.text()).then( | |
src => loadShader(src, gl.VERTEX_SHADER)), | |
fetch("fragment.glsl").then(res => res.text()).then( | |
src => loadShader(src, gl.FRAGMENT_SHADER)) | |
]).then(shaders => { | |
const program = gl.createProgram(); | |
shaders.forEach(shader => gl.attachShader(program, shader)); | |
gl.linkProgram(program); | |
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { | |
console.log(gl.getProgramInfoLog(program)); | |
}; | |
return program; | |
}); | |
// initialize data variables for the shader program | |
const initVariables = (program) => { | |
setupVAO(program); | |
return program; | |
}; | |
const render = (program, count) => { | |
// set timer variable to update the uniform buffer | |
timerData[0] = count; | |
gl.bindBuffer(gl.UNIFORM_BUFFER, timerBuf); | |
gl.bufferData(gl.UNIFORM_BUFFER, timerData, gl.DYNAMIC_DRAW); | |
gl.bindBuffer(gl.UNIFORM_BUFFER, null); | |
// uniform buffer binding | |
let uniformIndex = 0; | |
const screenId = gl.getUniformBlockIndex(program, "Screen"); | |
//console.log("screen uniform size", gl.getActiveUniformBlockParameter( | |
// program, screenId, gl.UNIFORM_BLOCK_DATA_SIZE)); //=> 4x4=16 | |
gl.uniformBlockBinding(program, screenId, ++uniformIndex); | |
gl.bindBufferBase(gl.UNIFORM_BUFFER, uniformIndex, screenBuf); | |
const timerId = gl.getUniformBlockIndex(program, "Timer"); | |
//console.log("timer uniform size", gl.getActiveUniformBlockParameter( | |
// program, timerId, gl.UNIFORM_BLOCK_DATA_SIZE)); //=> 4x4=16 | |
gl.uniformBlockBinding(program, timerId, ++uniformIndex); | |
gl.bindBufferBase(gl.UNIFORM_BUFFER, uniformIndex, timerBuf); | |
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); | |
gl.useProgram(program); | |
// draw the buffer with VAO | |
// NOTE: binding vert and index buffer is not required | |
gl.bindVertexArray(vertexArray); | |
const indexOffset = 0 * index[0].length; | |
gl.drawElements(gl.TRIANGLES, indexData.length, | |
gl.UNSIGNED_SHORT, indexOffset); | |
const error = gl.getError(); | |
if (error !== gl.NO_ERROR) console.log(error); | |
gl.bindVertexArray(null); | |
gl.useProgram(null); | |
}; | |
const startRendering = (program) => { | |
(function loop(count) { | |
requestAnimationFrame(() => { | |
render(program, count); | |
setTimeout(loop, 30, (count + 1) & 0x7fffffff); | |
}); | |
})(0); | |
}; | |
// (not used because of it runs forever) | |
const cleanupResources = (program) => { | |
gl.deleteBuffer(vertBuf); | |
gl.deleteBuffer(indexBuf); | |
gl.deleteBuffer(screenBuf); | |
gl.deleteBuffer(timerBuf); | |
gl.deleteVertexArray(vertexArray); | |
gl.deleteProgram(program); | |
}; | |
loadProgram().then(initVariables).then(startRendering); | |
}, false); |
This file contains 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
#version 300 es | |
invariant gl_Position; | |
in vec2 vert2d; | |
void main(void) { | |
gl_Position = vec4(vert2d, 0, 1); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
demo: https://gist.githack.com/bellbind/8c98bb86cfd064d944312b09b98af1b9/raw/index.html
chrome://flags/#enable-unsafe-es3-apis
true
towebgl.enable-prototype-webgl2
onabout:config