-
Notifications
You must be signed in to change notification settings - Fork 36
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
Updating surfaces in "real time" for persistance #75
Comments
Hello, thanks for getting in touch. I see your point, persistence makes sense for scatter graphs. As you mentioned, the problem is with overloading. There needs to be a kind of rolling buffer so that it can retain the last 4000 points. The problem is Javascript doesn't have a native rolling buffer, and it is hard to make one because it doesn't have access to low-level memory as C/C++ does. I will do some tests to come up will a workable solution. The GPU method is better. Each object needs an id. I haven't tried removing objects in OpenGL. Again need to do some tests. |
@eniv Okay, the WebGL code was more challenging than I expected. But I managed to do it. At the moment, it is single-size, single-color squares. I plotted 1M squares with 100k square updates per frame at 60fps. I think that is beyond your 4000 sq limit! I still need to do more work to integrate it in the |
Exactly, just like a shift register. This is awesome! |
Here is an example that I made. The new version is at |
Excellent! |
Hi, These are a couple of items which I've noticed so far:
-Eyal |
Thanks. I had already made an update. There were a few bugs in the previous version, also added color now. You can see the old example updated, and also this new example. On my desktop (i7 9th gen with RTX A4000), I could go up to 6M |
Yes, I can see a way to do that temporarily. But the best is to set the
yes, this is the next priority. I am working on it. All of this will be part of the |
Updated for the "auxiliary" lines. Example here. |
Hi @danchitnis, I tried the scatter plot from your latest example here: https://codesandbox.io/s/webglscatteracc2-psutjy?file=/src/index.ts I have two issues with it:
Maybe these two issues have the same origin? Here is my drawing code. I use Tauri + SvelteKit frameworks. The version of webgl-plot is 1.0.2. <script lang="ts">
import { WebglPlot, WebglScatterAcc, WebglAux, ColorRGBA } from 'webgl-plot';
import { onMount } from 'svelte';
import { listen, emit } from '@tauri-apps/api/event';
const horizontal_resolution = 15;
const vertical_resolution = 11;
let canvas: HTMLCanvasElement;
let wglp: WebglPlot;
let aux: WebglAux;
let sqAcc: WebglScatterAcc;
const maxSquare = 165;
let screenRatio: number;
let sqSize = 0.06;
let h_scale: number;
let w_scale: number;
let h_offset: number;
let w_offset: number;
const pos = new Float32Array(horizontal_resolution * vertical_resolution * 2);
const colors = new Uint8Array(horizontal_resolution * vertical_resolution * 3);
onMount(async () => {
canvas = document.getElementById('my-canvas') as HTMLCanvasElement;
const devicePixelRatio = window.devicePixelRatio || 1;
canvas.width = canvas.clientWidth * devicePixelRatio;
canvas.height = canvas.clientHeight * devicePixelRatio;
screenRatio = canvas.width / canvas.height;
wglp = new WebglPlot(canvas);
wglp.gScaleX = screenRatio;
wglp.gScaleY = 1;
h_scale = 2 - sqSize * 2;
w_scale = 1/screenRatio * (2 - sqSize*2*screenRatio);
h_offset = (1 - sqSize);
w_offset = (1/screenRatio - sqSize);
sqAcc = new WebglScatterAcc(wglp, 1650);
sqAcc.setSquareSize(sqSize);
sqAcc.setColor(new ColorRGBA(255, 255, 0, 255));
sqAcc.setScale(1/screenRatio, screenRatio);
const unlisten = await listen('frame', (event) => {
let current_data_idx = 0;
let countX = 0;
let countY = 0;
for (let vi = 0; vi < vertical_resolution; vi++) {
for (let hi = 0; hi < horizontal_resolution; hi++) {
countX = hi / (horizontal_resolution - 1) * h_scale - h_offset;
countY = vi / (vertical_resolution - 1) * w_scale - w_offset;
pos[current_data_idx * 2] = countX;
pos[current_data_idx * 2 + 1] = countY;
colors[current_data_idx * 3] = (event.payload as Array<number>)[current_data_idx]/10;
colors[current_data_idx * 3 + 1] = (event.payload as Array<number>)[current_data_idx]/10;
colors[current_data_idx * 3 + 2] = (event.payload as Array<number>)[current_data_idx]/10;
current_data_idx++;
}
}
sqAcc.addSquare(pos, colors);
wglp.clear();
sqAcc.draw();
});
});
</script>
<div class="h-full flex items-center">
<canvas class="border-8 h-600 border-black w-818" id="my-canvas" />
</div> |
@rhard Thanks for the feedback
Correct, I need to investigate this.
This doesn't happen on my side. If you are already running at 15 fps, that means you are severely resource-limited. Reduce the buffer size in the line below until you get the frame rate of your monitor, e.g. 60 fps. Monitor your resources to see if you are not out of RAM and if GPU is below 50%. It is expected that you run this on a high-end CPU and mid-range GPU. const sqAcc = new WebglScatterAcc(wglp, 10000); |
@danchitnis Thank you for your prompt response. By 15 fps, I mean this is how fast my component receives the new data inside the event listener here, and I redraw the rectangles:
I also call How can I output the real rendering FPS? I don't feel real fps is degraded, and it looks like just the new data for drawing became lost or something. Furthermore, the slowdown happens exactly at the moment when the white rectangle in the middle disappears. |
I've also tried to reduce/increase the buffer with different numbers. I even tried to make it to be x1 with just 165 pixels needed for one single frame. This doesn't make any visible difference. |
@danchitnis I've created an example to mimic my use case here: example It woks OK, but it doesn't have the white rectangle at the beginning. Something strange. |
It is a best practice that you run the plotting function in Javascript's render loop, otherwise may have unexpected results. To check the frame rate in Chrome, follow the instructions here and then Rendering -> Frame Rendering Stats I am not familiar Svelte framework, but these usually modify the states and rendering loops, so it could be the issue is there. |
The grey square, in the beginning, is not an issue. This is a rolling buffer, which is initialized with grey squares at position (0,0). I will make an API to move it around and look nicer, but it will always be there, even if it is hidden. This has no impact on performance. Your example runs just fine in vanilla scripts, so you have to check what Svelte is doing to it. |
@danchitnis I found the issue in my code. I was using different numbers for maxSquare and the actual number of data points. When I put the same number, everything starts working. But now I can recreate the issue in the example I sent you before: I set the maxSquare to be 10x more than actual data point number (which I think is the correct use case for persistence), and it starts freezing: example |
It depends on what you want to do. None of these examples is incorrect. You are allocating a buffer size of 1650 and then, in each loop, updating 165. So, of course, it will update 10x slower! As I mentioned, this is a rolling buffer, so it may be a bit confusing if you aren't familiar with this concept. Also, you don't need to create |
@danchitnis Thank you for clarification and support! In my understanding the rolling buffer is just a normal circular or ring buffer. I was expecting I can redraw it's content as soon as I call Also, if I understand you correctly, it is better to call |
The buffer gets updated whenever you call
As compiler people say, don't try to outsmart the compiler! In your case simply use |
Correct, why then canvas do not update when I add just 165 squares to the 1650 circular buffer in the issue with “freezing” above? example. Every bunch of 165 squares has the same coordinates. I don't mean to bother you, but having 15-year programmer experience in C/C++, I still can get the full understanding. |
@rhard, when having 165 fixed positions and drawing 1650 squares, ten squares are on top of each other, and you see only the top square changing colour, not the one underneath. See this example, which slightly randomizes their position. Nothing to do with C++ experience. OpenGL implementation is complex and unclear in some situations. |
Hi, |
Thanks, I completely missed it. |
Hi, |
@eniv You do not need to reinitialise as that would disrupt the WebGL flow. Instead, re-assign the position of squares in the buffer. For example, if all are set to (0,0), they will overlap on the centre of the coordinate. If you want them to disappear from the screen once you reset, you can set the position of the squares to a location outside your |
That means that I have to keep track of all the surfaces I've already given to |
@eniv Ideally if you re-assign the
yes, this is easy, I think the function to assign the |
Thank you. This Also I think the
|
Hi,
I'm using
WebglSquare
as a surface for a dynamic xy scatter scatter plot as suggested in #72.I'm trying to create a persistence function where points from previous frames will not be cleared when a new frame is drawn.
The most naive way of doing that is holding a FIFO (first in first out) type, fixed size, buffer in CPU RAM which will hold the contents of all the points from the current frame and previous frames. This buffer can then be transferred to
webgl-plot
for rendering after all the surfaces are removed (AddingremoveSurfaces
, equivalent toremoveXXXXLines
towebgl-plot
would be nice).Using this technique I can preserve about ~4000 points before the frame rate starts dropping.
Can you recommend a better way of doing this? It seems redundant to buffer the same data to the GPU over and over again until it is removed from the FIFO.
The text was updated successfully, but these errors were encountered: