Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/#153 webgl minimal #186

Merged
merged 8 commits into from
Jan 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions Apps/frontend/src/OscilloscopeWebGl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import {
channelFragmentShader,
channelVertexShader,
} from "./shader/channelShader";
import { createShaderProgram } from "./shader/shaderHelper";
import { get } from "svelte/store";
import { LINE_COLORS_WEBGL } from "./const";
import { amplitudeAdjustment, offsetAdjustment } from "./stores";
export class OscilloscopeWebGl {
private channelProgram: WebGLProgram;
private webgl: WebGL2RenderingContext;
private channelVertexBuffer: WebGLBuffer;

constructor(webgl: WebGL2RenderingContext) {
this.webgl = webgl;
this.init();
}

init() {
this.webgl.viewport(
0,
0,
this.webgl.canvas.width,
this.webgl.canvas.height
);

this.clear();

this.channelProgram = createShaderProgram(
this.webgl,
channelVertexShader,
channelFragmentShader
);
this.channelVertexBuffer = this.webgl.createBuffer() as WebGLBuffer;
}

clear() {
this.webgl.clearColor(0.0, 0.0, 0.0, 1.0);
this.webgl.clear(this.webgl.COLOR_BUFFER_BIT);
}

drawChannels(channelSamples: number[][]) {
this.webgl.useProgram(this.channelProgram);
for (let i = 0; i < channelSamples.length; i++) {
let samples = new Float32Array(channelSamples[i]);
this.webgl.bindBuffer(this.webgl.ARRAY_BUFFER, this.channelVertexBuffer);
this.webgl.bufferData(
this.webgl.ARRAY_BUFFER,
samples,
this.webgl.DYNAMIC_DRAW
);

let sampleAttribute = this.webgl.getAttribLocation(
this.channelProgram,
"aSample"
);
this.webgl.vertexAttribPointer(
sampleAttribute,
1,
this.webgl.FLOAT,
false,
0,
0
);
this.webgl.enableVertexAttribArray(sampleAttribute);

let colors = new Float32Array(LINE_COLORS_WEBGL[i]);
let colorUniform = this.webgl.getUniformLocation(
this.channelProgram,
"u_colour"
);

this.webgl.uniform4fv(colorUniform, colors);

let offsetUniform = this.webgl.getUniformLocation(
this.channelProgram,
"u_offset"
);
let channelOffset = get(offsetAdjustment)[i];
this.webgl.uniform1f(offsetUniform, channelOffset);

let amplitudeUniform = this.webgl.getUniformLocation(
this.channelProgram,
"u_amplitude"
);
let channelAmplitude = get(amplitudeAdjustment)[i];
this.webgl.uniform1f(amplitudeUniform, channelAmplitude);

this.webgl.drawArrays(this.webgl.LINE_STRIP, 0, samples.length);
}
}
}
107 changes: 18 additions & 89 deletions Apps/frontend/src/components/Waves.svelte
Original file line number Diff line number Diff line change
@@ -1,49 +1,38 @@
<script>
PhlppKrmr marked this conversation as resolved.
Show resolved Hide resolved
import { beforeUpdate, onMount } from "svelte";
import {
ColorRGBA,
WebglPlot,
WebglSquare,
WebglThickLine,
} from "webgl-plot";
import {
CANVAS_HEIGHT,
CANVAS_WIDTH,
NUM_CHANNELS,
NUM_INTERVALS_HORIZONTAL,
LINE_COLORS,
WAVE_CURSOR_SIZE,
LINE_THICKNESS_SMALL,
LINE_THICKNESS_BIG,
} from "../const";
import {
amplitudeAdjustment,
channelActivated,
offsetAdjustment,
thicknessAdjustment,
timeSweep,
} from "../stores";
import {
OscilloscopeWebGl
} from "../OscilloscopeWebGl"
import { computeDisplayDeltaFromTimeSweep } from "../helper";

export let scalesY;

let canvasElement;
let webGLPlot;
let oscilloscopeWebGl;
/**
* @type {Number[][]}
*/
let channelSamples = Array.from(Array(NUM_CHANNELS), () =>
new Array(CANVAS_WIDTH).fill(undefined)
);
let lines = [];
let heads = [];
let xArr;
let xLast;

// ----- Svelte lifecycle hooks -----
onMount(() => {
resizeCanvas();
initializePlot();
initializeWebGl();
resetPlot();
});

Expand All @@ -63,7 +52,7 @@
xArr = new Array(NUM_CHANNELS).fill(0.0);
xLast = new Array(NUM_CHANNELS).fill(undefined);
initChannelSamples();
webGLPlot.clear();
oscilloscopeWebGl.clear();
};

export const updateBuffer = (samples, startIndex, endIndex) => {
Expand Down Expand Up @@ -92,94 +81,34 @@
}
};

// Subscribe to the offsetAdjustment store
offsetAdjustment.subscribe((newOffsets) => {
for (let i = 0; i < NUM_CHANNELS; i++) {
let line = lines[i];
if (line !== undefined) line.offsetY = newOffsets[i];
let head = heads[i];
if (head !== undefined) head.offsetY = newOffsets[i];
}
});

// Subscribe to the channelActivation store
channelActivated.subscribe((isActive) => {
for (let i = 0; i < NUM_CHANNELS; i++) {
if (lines[i] !== undefined) lines[i].visible = isActive[i];
}
});

thicknessAdjustment.subscribe((isThick) => {
for (let i = 0; i < NUM_CHANNELS; i++) {
if (lines[i] !== undefined) {
const thickness = isThick[i]
? LINE_THICKNESS_BIG
: LINE_THICKNESS_SMALL;
lines[i].setThickness(thickness);
}
}
});

amplitudeAdjustment.subscribe((amplitudes) => {
for (let i = 0; i < NUM_CHANNELS; i++) {
if (lines[i] !== undefined)
lines[i].scaleY = computeScaling(amplitudes[i]);
}
// thick lines not implemented
});

// computes the Scaling of a wave according to the voltage intervals
const computeScaling = (amplitude) => {
return (1 / (NUM_INTERVALS_HORIZONTAL / 2)) * amplitude;
};

const update = () => {
for (let i = 0; i < channelSamples.length; i++) {
for (let x = 0; x < CANVAS_WIDTH; ++x) {
lines[i].setY(x, channelSamples[i][x]);
}

const size = 0.01;
let x = (xArr[i] * 2) / CANVAS_WIDTH - 1;
let scale = lines[i].scaleY * 5;
let y = (channelSamples[i][xLast[i] - 1] * 100 * scale) / CANVAS_HEIGHT;
heads[i].setSquare(x - size / 2, y - size, x + size / 2, y + size);
}
oscilloscopeWebGl.drawChannels(channelSamples);
};

const resizeCanvas = () => {
canvasElement.width = CANVAS_WIDTH;
canvasElement.height = CANVAS_HEIGHT;
};

const initializePlot = () => {
webGLPlot = new WebglPlot(canvasElement);
initializeLines();
};
const initializeWebGl = () => {
let webgl = canvasElement.getContext("webgl2");

const initializeLines = () => {
for (let i = 0; i < NUM_CHANNELS; i++) {
const color = new ColorRGBA(
LINE_COLORS[i][0] / 255,
LINE_COLORS[i][1] / 255,
LINE_COLORS[i][2] / 255,
1
);
let line = new WebglThickLine(color, CANVAS_WIDTH, LINE_THICKNESS_SMALL);
// same thing arrangeX does, but WebglThickLine does not provide it
line.lineSpaceX(-1, 2 / CANVAS_WIDTH);
line.scaleY = computeScaling(scalesY[i]);
webGLPlot.addThickLine(line);
lines.push(line);

let head = new WebglSquare(color);
heads.push(head);
webGLPlot.addSurface(head);
}
if (webgl === null) {
alert(
"Unable to initialize WebGL. Your browser or machine may not support it."
);
return;
}

oscilloscopeWebGl = new OscilloscopeWebGl(webgl);
};

const newFrame = () => {
update();
webGLPlot.update();
window.requestAnimationFrame(newFrame);
};
</script>
Expand Down
2 changes: 1 addition & 1 deletion Apps/frontend/src/const.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,4 @@ const EXPECTED_UPDATES_PER_SECOND = 10_000;
const TIME_PER_UPDATE = 1 / EXPECTED_UPDATES_PER_SECOND;
const PIXELS_PER_DIV = CANVAS_WIDTH / NUM_INTERVALS_VERTICAL;
export const TIME_PER_DIV = PIXELS_PER_DIV * TIME_PER_UPDATE;
/* END DISPLAY SPEED */
/* END DISPLAY SPEED */
38 changes: 38 additions & 0 deletions Apps/frontend/src/shader/channelShader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { CANVAS_WIDTH, NUM_INTERVALS_HORIZONTAL } from "../const";

export const channelFragmentShader = `#version 300 es
precision highp float;

in vec4 v_colour;
out vec4 o_colour;

void main() {
o_colour = v_colour;
}
`;

export const channelVertexShader = `#version 300 es
precision highp float;
#define VOLTS_TO_NDC ${2.0 / NUM_INTERVALS_HORIZONTAL}
#define X_TO_NDC ${2.0 / CANVAS_WIDTH}
#define CANVAS_WIDTH ${CANVAS_WIDTH}
#define SCALE_Y ${(NUM_INTERVALS_HORIZONTAL / 2).toFixed(1)}
uniform vec4 u_colour;
uniform float u_offset;
uniform float u_amplitude;
in float aSample;
out vec4 v_colour;

float x_to_ndc(float x) {
return x * X_TO_NDC - 1.0;
}

void main() {
float x = float(gl_VertexID);
float y = (aSample * u_amplitude + (SCALE_Y * u_offset));
float xNDC = x_to_ndc(x);
float yNDC = y * VOLTS_TO_NDC;
gl_Position = vec4(xNDC, yNDC, 0, 1);
v_colour = u_colour;
}
`;
2 changes: 1 addition & 1 deletion Apps/frontend/src/views/Oscilloscope.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@
<CoordinateSystem scaleY={Math.max(...scalesY)} />
</div>
<div class="oscilloscope--waves">
<Waves bind:this={waveElement} {scalesY} />
<Waves bind:this={waveElement} />
</div>
</div>
<div class="indicators--text">
Expand Down