-
Notifications
You must be signed in to change notification settings - Fork 162
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
make the rendering of the oscilloscope significantly less expensive #619
base: master
Are you sure you want to change the base?
make the rendering of the oscilloscope significantly less expensive #619
Conversation
…the more players, the bigger the impact
The number of vertices should depend on the width of the oscilloscope on the screen. Should we run a low pass filter on the audio? Can we speed up the drawing even more by letting the GPU do the translation and scaling? glPushMatrix();
glTranslatef(X, Y - MaxY/Low(Smallint), 0);
glScalef(MaxX/High(Sound.AnalysisBuffer), MaxY/Low(Smallint)), 1);
glBegin(GL_LINE_STRIP);
for SampleIndex := 0 to High(Sound.AnalysisBuffer) do
begin
glVertex2i(SampleIndex, Sound.AnalysisBuffer[SampleIndex]);
end;
glEnd;
glPopMatrix(); ? |
I also like the idea with the GPU translation. Even if the performance stays the same, it should make this kind of code way more readable without all the dividing. Also thanks for sharing that example code, I understand what it does but it's been ages since I've done anything with GL. I'll play around with your suggestions and see what works best/where the biggest gains are. Might be a week or two before I get around to it, I've since found another part of the code that I want to get a ticket opened on first before I improve this one. |
Turns out, the I usually run the game at around 1080p, and always felt that some UI elements were strangely scaled and not-quite-sharp in some way. Some notable exceptions are video/image backgrounds when singing, the timebar (with the boxes), and covers in at least Roulette mode (though there is still something off about the latter). It's probably being caused by this bit of code in
I'll continue this PR once I've figured out a way around this. |
@barbeque-squared please read more of the code. The different places always should distinguish between rendered w/h and theme w/h and make use of screen w/h as needed. |
Just to see if it was possible, I tried That's absolutely not committable right now (it's a giant hack), but I did come across some areas that would be massively improved by some cleanup PRs, even if in the end we never move away from the 800x600 rendering. But they would be a prerequisite if we ever did want to, so expect some cleanup PRs over the coming weeks/months. Since changing render size is non-trivial, would a temporary fix in the form of eg rendering only 1/4 (still more than enough for the widest oscilloscope in the default themes on 4k*) be accepted if the improvement in framerate is significant? I'll need to test how significant, but I'm only going to do those tests if the answer's 'yes'. * = there are other hardcoded numbers and textures in the code that running the game on 4k is a stretch right now anyway. Even on 1080p I'm already hitting some of them. |
From what I recall this was by far the most expensive UI element to draw, especially as the number of players increases. I'll retest it soon (6 players, no video, no background, unlimited fps) and figure out some actual numbers. |
I barely know anything about shaders, but can't we use a fragment shader that fetches the amplitude for the current x coordinate from a 1D texture, scales it to the height of the oscilloscope and then compares it to the y coordinate to determine the transparency of the fragment? Distance < 1 pixel => Distance is transparency. Distance >= 1 pixel => fully transparent. OpenGL implementations without shaders can continue to use the old code for drawing. |
I played around a bit with gprof the other day, and noticed that especially when using six players, having oscilloscope enabled had a huge impact on performance.
This patch only renders 1/32 of the (4096) data points in the microphone data, which should be a close enough approximation for the oscilloscope to be useful. I didn't notice any negative side effects by doing this, perhaps the line is a bit thinner but that's about it.
The
32
is fairly arbitrarily chosen. I tried various powers of two, 64 was too unprecise/blocky at higher frequencies (it's possible this also happens with 32, but I can't reach those frequencies) whereas with 16 it looked pretty much the same as with 32.An alternative (and probably even faster) approach would be to (also) only use only every nth sample when getting it from the microphone, but that also affects various other parts of the code, plus I don't know how 'long' those 4096 samples actually last. You'd also technically be throwing away some of the data.