<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<canvas id="canvas" width="400" height="400"></canvas>
<script id="vs-update" type="x-shader/x-vertex">
precision mediump float;
in float inValue;
out float outValue;
void main(){
if (inValue>1){
outValue = 0.0;
} else {
outValue = inValue + 0.02;
}
}
</script>
<script id="vs-draw" type="x-shader/x-vertex">
precision mediump float;
in float inValue;
void main(){
gl_Position = vec4(inValue, 0.5, 0.0, 1.0);
}
</script>
<script id="fs-update" type="x-shader/x-fragment">
precision mediump float;
out vec4 o_FragColor;
void main() {
o_FragColor = vec4(0.0);
}
</script>
<script id="fs-draw" type="x-shader/x-fragment">
precision mediump float;
out vec4 o_FragColor;
void main() {
o_FragColor = vec4(0.0);
}
</script>
<script>
let programUpdate, programDraw, readBuffer, writeBuffer;
let gl = document.getElementById('canvas').getContext('webgl2')
init();
render();
function getShaderSource(id) {
return document.getElementById(id).innerHTML
}
function init() {
/* Step3: Create and compile Shader programs */
programUpdate = makeProgram(getShaderSource('vs-update'), getShaderSource('fs-update'), ['outValue']);
programDraw = makeProgram(getShaderSource('vs-draw'), getShaderSource('fs-draw'));
let vertices = [0.0, 0.0, 0.0,];
gl.bindBuffer(gl.ARRAY_BUFFER, readBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, writeBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
/* Step 4: Associate the shader programs to buffer objects */
gl.useProgram(programUpdate);
gl.bindBuffer(gl.ARRAY_BUFFER, readBuffer);
let attribLocation = gl.getAttribLocation(programUpdate, "inValue");
gl.vertexAttribPointer(attribLocation, 1, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(attribLocation);
gl.useProgram(programDraw);
gl.bindBuffer(gl.ARRAY_BUFFER, readBuffer);
attribLocation = gl.getAttribLocation(programDraw, "inValue");
gl.vertexAttribPointer(attribLocation, 1, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(attribLocation);
/* Step5: Drawing the required object (triangle) */
gl.enable(gl.DEPTH_TEST);
gl.viewport(0,0,canvas.width,canvas.height);
}
function makeProgram(vShaderCode, fShaderCode, transformFeedbackVaryings) {
let vertShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertShader, vShaderCode);
gl.compileShader(vertShader);
let fragShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragShader, fShaderCode);
gl.compileShader(fragShader);
let shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertShader);
gl.attachShader(shaderProgram, fragShader);
if (transformFeedbackVaryings) {
gl.transformFeedbackVaryings(shaderProgram, transformFeedbackVaryings, gl.INTERLEAVED_ATTRIBS);
}
gl.linkProgram(shaderProgram);
return shaderProgram;
}
function updateAndWrite() {
gl.useProgram(programUpdate);
gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, writeBuffer);
gl.enable(gl.RASTERIZER_DISCARD);
gl.beginTransformFeedback(gl.TRIANGLES);
gl.drawArrays(gl.TRIANGLES, 0, 3);
gl.endTransformFeedback();
gl.disable(gl.RASTERIZER_DISCARD);
gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, null);
}
function readAndDraw() {
gl.useProgram(programDraw);
gl.drawArrays(gl.TRIANGLES, 0, 3);
}
function render() {
gl.clearColor(0.5, 0.5, 0.5, 0.9);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.bindBuffer(gl.ARRAY_BUFFER, readBuffer);
updateAndWrite();
readAndDraw();
let tmp = readBuffer;
readBuffer = writeBuffer;
writeBuffer = tmp;
window.requestAnimationFrame(render);
}
</script>
</body>
</html>