mirror of
https://github.com/greggman/twgl.js.git
synced 2025-12-08 19:26:07 +00:00
228 lines
6.7 KiB
HTML
228 lines
6.7 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf8">
|
|
<!--
|
|
|
|
@license twgl.js Copyright (c) 2015, Gregg Tavares All Rights Reserved.
|
|
Available via the MIT license.
|
|
see: http://github.com/greggman/twgl.js for details
|
|
|
|
-->
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
|
|
<meta property="og:title" content="TWGL.js - transform feedback particles" />
|
|
<meta property="og:type" content="website" />
|
|
<meta property="og:image" content="http://twgljs.org/examples/screenshots/transform-feedback.png" />
|
|
<meta property="og:description" content="TWGL.js - transform feedback" />
|
|
<meta property="og:url" content="http://twgljs.org" />
|
|
|
|
<meta name="twitter:card" content="summary_large_image">
|
|
<meta name="twitter:site" content="@greggman">
|
|
<meta name="twitter:creator" content="@greggman">
|
|
<meta name="twitter:domain" content="twgljs.org">
|
|
<meta name="twitter:title" content="TWGL.js - transform feedback">
|
|
<meta name="twitter:url" content="http://twgljs.org/examples/transform-feedback.html">
|
|
<meta name="twitter:description" content="TWGL.js - transform feedback">
|
|
<meta name="twitter:image:src" content="http://twgljs.org/examples/screenshots/transform-feedback.png">
|
|
|
|
<link href="/resources/images/twgljs-icon.png" rel="shortcut icon" type="image/png">
|
|
|
|
<title>twgl.js - transform feedback</title>
|
|
<style>
|
|
html, body {
|
|
margin: 0;
|
|
font-family: monospace;
|
|
height: 100%;
|
|
}
|
|
canvas {
|
|
display: block;
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
#b {
|
|
position: absolute;
|
|
top: 10px;
|
|
width: 100%;
|
|
text-align: center;
|
|
z-index: 2;
|
|
color: white;
|
|
}
|
|
#b a {
|
|
color: lightblue;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<canvas id="c"></canvas>
|
|
<div id="b"><a href="http://twgljs.org">twgl.js</a> - transform feedback particles</div>
|
|
<div id="no-webgl2" style="display: none;">
|
|
<div>Sorry but your browser doesn't appear to support WebGL2</div>
|
|
</div>
|
|
</body>
|
|
<script src="../3rdparty/chroma.min.js"></script>
|
|
<script type="module">
|
|
import * as twgl from '../dist/7.x/twgl-full.module.js';
|
|
|
|
const tfVS = `#version 300 es
|
|
in vec2 a_positionIn;
|
|
in vec2 a_velocity;
|
|
out vec2 a_positionOut;
|
|
uniform float u_deltaTime;
|
|
uniform float u_time;
|
|
|
|
void main() {
|
|
vec2 localMult = vec2(
|
|
sin((a_positionIn.x + a_positionIn.y + float(gl_VertexID) * 0.01) * 5.127 + u_time),
|
|
cos(atan(a_positionIn.x, a_positionIn.y + float(gl_VertexID) * 0.0) * 2.713 + u_time * 0.791)) * 0.5 ;
|
|
|
|
a_positionOut = mod((a_positionIn + 3.0) + a_velocity * u_deltaTime * localMult, vec2(2)) - 1.0;
|
|
}
|
|
`;
|
|
const tfFS = `#version 300 es
|
|
precision mediump float;
|
|
out vec4 o;
|
|
void main() {
|
|
o = vec4(0);
|
|
}
|
|
`;
|
|
const vs = `#version 300 es
|
|
in vec4 a_position;
|
|
in vec4 a_color;
|
|
out vec4 v_color;
|
|
|
|
void main() {
|
|
gl_Position = a_position;
|
|
gl_PointSize = 4.0;
|
|
v_color = a_color;
|
|
}
|
|
`;
|
|
const fs = `#version 300 es
|
|
precision mediump float;
|
|
in vec4 v_color;
|
|
out vec4 fragColor;
|
|
void main() {
|
|
fragColor = v_color;
|
|
}
|
|
`;
|
|
|
|
function rand(min, max) {
|
|
return min + Math.random() * (max - min);
|
|
}
|
|
|
|
const baseHue = rand(0, 360);
|
|
function randColor32() {
|
|
return chroma.hsv((baseHue + rand(0, 60)) % 360, rand(0.4, 1), rand(0.25, 1)).gl().map(v => v * 255 | 0);
|
|
}
|
|
|
|
function main() {
|
|
const gl = document.getElementById("c").getContext("webgl2");
|
|
if (!gl) {
|
|
document.querySelector("#no-webgl2").style.display = "";
|
|
return;
|
|
}
|
|
|
|
const drawProgramInfo = twgl.createProgramInfo(gl, [vs, fs]);
|
|
const feedbackProgramInfo = twgl.createProgramInfo(gl, [tfVS, tfFS], {
|
|
transformFeedbackVaryings: [
|
|
"a_positionOut",
|
|
],
|
|
});
|
|
|
|
const numParticles = 100000;
|
|
const positions = [];
|
|
const velocities = [];
|
|
const colors = [];
|
|
for (let i = 0; i < numParticles; ++i) {
|
|
positions.push(rand(-1, 1), rand(-1, 1));
|
|
velocities.push(rand(-1, 1), rand(-1, 1));
|
|
colors.push(...randColor32());
|
|
}
|
|
|
|
const tfBufferInfo1 = twgl.createBufferInfoFromArrays(gl, {
|
|
a_positionIn: { numComponents: 2, data: new Float32Array(positions) },
|
|
a_positionOut: { numComponents: 2, data: positions.length },
|
|
a_velocity: { numComponents: 2, data: new Float32Array(velocities) },
|
|
});
|
|
|
|
const tfBufferInfo2 = twgl.createBufferInfoFromArrays(gl, {
|
|
a_positionIn: { numComponents: 2, buffer: tfBufferInfo1.attribs.a_positionOut.buffer },
|
|
a_positionOut: { numComponents: 2, buffer: tfBufferInfo1.attribs.a_positionIn.buffer },
|
|
a_velocity: { numComponents: 2, buffer: tfBufferInfo1.attribs.a_velocity.buffer },
|
|
});
|
|
|
|
const drawBufferInfo1 = twgl.createBufferInfoFromArrays(gl, {
|
|
a_position: { numComponents: 2, buffer: tfBufferInfo1.attribs.a_positionOut.buffer },
|
|
a_color: new Uint8Array(colors),
|
|
});
|
|
|
|
const drawBufferInfo2 = twgl.createBufferInfoFromArrays(gl, {
|
|
a_position: { numComponents: 2, buffer: tfBufferInfo2.attribs.a_positionOut.buffer },
|
|
a_color: { type: gl.UNSIGNED_BYTE, buffer: drawBufferInfo1.attribs.a_color.buffer },
|
|
});
|
|
|
|
const feedback1 = twgl.createTransformFeedback(gl, feedbackProgramInfo, tfBufferInfo1);
|
|
const feedback2 = twgl.createTransformFeedback(gl, feedbackProgramInfo, tfBufferInfo2);
|
|
|
|
const sets = [
|
|
{
|
|
feedback: feedback1,
|
|
tfBufferInfo: tfBufferInfo1,
|
|
drawBufferInfo: drawBufferInfo1,
|
|
},
|
|
{
|
|
feedback: feedback2,
|
|
tfBufferInfo: tfBufferInfo2,
|
|
drawBufferInfo: drawBufferInfo2,
|
|
},
|
|
];
|
|
let setNdx = 0;
|
|
let then = 0;
|
|
|
|
function render(now) {
|
|
now *= 0.001;
|
|
const deltaTime = now - then;
|
|
then = now;
|
|
|
|
|
|
twgl.resizeCanvasToDisplaySize(gl.canvas);
|
|
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
|
|
|
|
const {feedback, tfBufferInfo, drawBufferInfo} = sets[setNdx];
|
|
setNdx = 1 - setNdx;
|
|
|
|
gl.clearColor(0, 0, 0, 1);
|
|
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
|
|
|
// update
|
|
gl.enable(gl.RASTERIZER_DISCARD);
|
|
|
|
gl.useProgram(feedbackProgramInfo.program);
|
|
gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, feedback);
|
|
gl.beginTransformFeedback(gl.POINTS);
|
|
twgl.setBuffersAndAttributes(gl, feedbackProgramInfo, tfBufferInfo);
|
|
twgl.setUniforms(feedbackProgramInfo, {
|
|
u_deltaTime: deltaTime,
|
|
u_time: now,
|
|
});
|
|
twgl.drawBufferInfo(gl, tfBufferInfo, gl.POINTS);
|
|
gl.endTransformFeedback();
|
|
gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null);
|
|
|
|
gl.disable(gl.RASTERIZER_DISCARD);
|
|
|
|
// draw
|
|
gl.useProgram(drawProgramInfo.program);
|
|
twgl.setBuffersAndAttributes(gl, drawProgramInfo, drawBufferInfo);
|
|
twgl.drawBufferInfo(gl, drawBufferInfo, gl.POINTS);
|
|
|
|
requestAnimationFrame(render);
|
|
}
|
|
requestAnimationFrame(render);
|
|
}
|
|
main();
|
|
</script>
|
|
</html>
|
|
|
|
|
|
|