kopia lustrzana https://github.com/m1el/woscope
line rendering in webgl
commit
870af9bfa6
|
@ -0,0 +1,44 @@
|
|||
var CreateShader = function(gl, vsSource, fsSource) {
|
||||
'use strict';
|
||||
if (typeof WebGLRenderingContext !== 'function' ||
|
||||
!(gl instanceof WebGLRenderingContext)) {
|
||||
throw new Error('CreateShader: no WebGL context');
|
||||
}
|
||||
|
||||
let vs = gl.createShader(gl.VERTEX_SHADER);
|
||||
gl.shaderSource(vs, vsSource);
|
||||
gl.compileShader(vs);
|
||||
if (!gl.getShaderParameter(vs, gl.COMPILE_STATUS)) {
|
||||
let infoLog = gl.getShaderInfoLog(vs);
|
||||
gl.deleteShader(vs);
|
||||
throw new Error('CreateShader, vertex shader compilation:\n' + infoLog);
|
||||
}
|
||||
|
||||
let fs = gl.createShader(gl.FRAGMENT_SHADER);
|
||||
gl.shaderSource(fs, fsSource);
|
||||
gl.compileShader(fs);
|
||||
if (!gl.getShaderParameter(fs, gl.COMPILE_STATUS)) {
|
||||
let infoLog = gl.getShaderInfoLog(fs);
|
||||
gl.deleteShader(vs);
|
||||
gl.deleteShader(fs);
|
||||
throw new Error('CreateShader, fragment shader compilation:\n' + infoLog);
|
||||
}
|
||||
|
||||
let program = gl.createProgram();
|
||||
|
||||
gl.attachShader(program, vs);
|
||||
gl.deleteShader(vs);
|
||||
|
||||
gl.attachShader(program, fs);
|
||||
gl.deleteShader(fs);
|
||||
|
||||
gl.linkProgram(program);
|
||||
|
||||
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
||||
let infoLog = gl.getProgramInfoLog(program);
|
||||
gl.deleteProgram(program);
|
||||
throw new Error('CreateShader, linking:\n' + infoLog);
|
||||
}
|
||||
|
||||
return program;
|
||||
};
|
|
@ -0,0 +1,177 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>woscilloscope</title>
|
||||
<script src="base64.js"></script>
|
||||
<script src="algebra.js"></script>
|
||||
<script src="gl.js"></script>
|
||||
<script>
|
||||
window.onload = function() {
|
||||
'use strict';
|
||||
let canvas = $('c'),
|
||||
gl = initGl(canvas),
|
||||
shader = CreateShader(gl, getText('vshader'), getText('fshader'));
|
||||
|
||||
points = makePoints(gl);
|
||||
ilaced = makeInterlaced(gl);
|
||||
|
||||
let loop = function() {
|
||||
draw(gl, shader);
|
||||
requestAnimationFrame(loop);
|
||||
}
|
||||
loop();
|
||||
};
|
||||
|
||||
var points = null;
|
||||
var ilaced = null;
|
||||
|
||||
function initGl(canvas) {
|
||||
'use strict';
|
||||
let gl = canvas.getContext('webgl');
|
||||
gl.clearColor( 0.0, 0.0, 0.0, 1.0 );
|
||||
gl.viewport(0, 0, canvas.width, canvas.height);
|
||||
return gl;
|
||||
}
|
||||
|
||||
function makeInterlaced(gl) {
|
||||
'use strict';
|
||||
let interlaced = new Int32Array(4096/4);
|
||||
for (let i = interlaced.length; i--; ) {
|
||||
interlaced[i] = 0xFF01FF01;
|
||||
}
|
||||
let vbo = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, interlaced, gl.STATIC_DRAW);
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
||||
|
||||
return vbo;
|
||||
}
|
||||
|
||||
function makePoints(gl) {
|
||||
'use strict';
|
||||
let vertices = [],
|
||||
TAU = Math.PI*2;
|
||||
for (let i = 0; i < 100; i++) {
|
||||
let ph = i / 100 * 2 * TAU;
|
||||
let r = 0.0023 * Math.exp(0.5*ph);
|
||||
vertices.push(Math.cos(ph)*r, Math.sin(ph)*r);
|
||||
}
|
||||
vertices = vertices.map(function(e) { return (e)*32767; });
|
||||
vertices = new Int16Array(vertices);
|
||||
|
||||
let inView = new Int32Array(vertices.buffer),
|
||||
transformed = new Int16Array(vertices.length * 2),
|
||||
outView = new Int32Array(transformed.buffer);
|
||||
for (let i = inView.length; i--;) {
|
||||
outView[i*2] = outView[i*2+1] = inView[i];
|
||||
}
|
||||
|
||||
console.log(transformed);
|
||||
let vbo = gl.createBuffer();
|
||||
vbo.itemCount = transformed.length;
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, transformed, gl.STATIC_DRAW);
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
||||
|
||||
return vbo;
|
||||
}
|
||||
|
||||
function $(id) { return document.getElementById(id); }
|
||||
|
||||
function getText(id) { return $(id).innerText; }
|
||||
|
||||
function draw(gl, shader) {
|
||||
'use strict';
|
||||
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
||||
|
||||
gl.useProgram(shader);
|
||||
|
||||
let attribs = [];
|
||||
|
||||
{
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, ilaced);
|
||||
let dirAttr = gl.getAttribLocation(shader, 'aDir');
|
||||
if (dirAttr > -1) {
|
||||
gl.enableVertexAttribArray(dirAttr);
|
||||
gl.vertexAttribPointer(dirAttr, 1, gl.BYTE, false, 1, 0);
|
||||
attribs.push(dirAttr);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, points);
|
||||
let tmpPos = gl.getAttribLocation(shader, 'aPrev');
|
||||
if (tmpPos > -1) {
|
||||
gl.enableVertexAttribArray(tmpPos);
|
||||
gl.vertexAttribPointer(tmpPos, 2, gl.SHORT, false, 0, 0);
|
||||
attribs.push(tmpPos);
|
||||
}
|
||||
|
||||
tmpPos = gl.getAttribLocation(shader, 'aCurr');
|
||||
if (tmpPos > -1) {
|
||||
gl.enableVertexAttribArray(tmpPos);
|
||||
gl.vertexAttribPointer(tmpPos, 2, gl.SHORT, false, 0, 8);
|
||||
attribs.push(tmpPos);
|
||||
}
|
||||
|
||||
tmpPos = gl.getAttribLocation(shader, 'aNext');
|
||||
if (tmpPos > -1) {
|
||||
gl.enableVertexAttribArray(tmpPos);
|
||||
gl.vertexAttribPointer(tmpPos, 2, gl.SHORT, false, 0, 16);
|
||||
attribs.push(tmpPos);
|
||||
}
|
||||
}
|
||||
|
||||
gl.enable(gl.BLEND);
|
||||
gl.blendFunc(gl.SRC_ALPHA, gl.ONE);
|
||||
gl.drawArrays(gl.TRIANGLE_STRIP, 0, points.itemCount/2-6);
|
||||
|
||||
for (let a of attribs) {
|
||||
gl.disableVertexAttribArray(a);
|
||||
}
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
||||
gl.useProgram(null);
|
||||
}
|
||||
</script>
|
||||
<script language="x-shader/x-vertex" id="vshader">
|
||||
precision highp float;
|
||||
attribute vec2 aPrev, aCurr, aNext;
|
||||
attribute float aDir;
|
||||
varying vec3 uva;
|
||||
varying vec2 delta;
|
||||
float size = 100.;
|
||||
void main () {
|
||||
uva.x = aDir;
|
||||
vec2 prev = aPrev/32767.;
|
||||
vec2 curr = aCurr/32767.;
|
||||
vec2 next = aNext/32767.;
|
||||
// TODO: handle edge cases
|
||||
{
|
||||
vec2 deltaNext = next.xy - curr.xy;
|
||||
vec2 deltaPrev = curr.xy - prev.xy;
|
||||
vec2 normNext = normalize(vec2(-deltaNext.y, deltaNext.x));
|
||||
vec2 normPrev = normalize(vec2(-deltaPrev.y, deltaPrev.x));
|
||||
vec2 average = normalize(normNext + normPrev);
|
||||
delta = average / dot(average, normPrev);
|
||||
}
|
||||
delta = delta*aDir/size;
|
||||
gl_Position = vec4(curr+delta,0.0,1.0);
|
||||
}
|
||||
</script>
|
||||
<script language="x-shader/x-fragment" id="fshader">
|
||||
precision highp float;
|
||||
varying vec3 uva;
|
||||
varying vec2 delta;
|
||||
void main (void)
|
||||
{
|
||||
float color = uva.x/2.+0.5;
|
||||
gl_FragColor = vec4(color, 1.-color, 0.0, 1.0);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="c" width=800 height=800></canvas>
|
||||
</body>
|
||||
</html>
|
Ładowanie…
Reference in New Issue