I’m making a video which will be in an exhibition in 3 days and need urgent help on the following:
I am painting thousands of pixels according to a generative algorithm. I was using the CPU and on every frame I was calling ofDrawRectangle(x,y,1,1).
At 15FPS I was getting a maximum of 150k pixels. This was not enough. So, after some investigation I decided to move to the GPU using instance drawing and a TBO (texture buffer object). Surprisingly everything seemed to b working quite well.
But then I found out that I was not getting a 1 to 1 correlation between what I draw and the screen pixels (like I was getting in the CPU version).
It feels like there are two things happening:
- Everything is smaller
- Everything is blurred (anti-alias?)
I just want every vortex to be drawn as 1 screen pixel.
Here are the results (the upload did anti-alias on both but the original CPU version is crisp):
Can someone please suggest how this can be solved?
If it helps, the draw() code for both versions is here:
CPU version: https://github.com/nununo/ofMoldApp/blob/cpu-one2one/src/hypha/Hypha.cpp
GPU version: https://github.com/nununo/ofMoldApp/blob/gpu-one2one/src/app/Painter.cpp
I was hoping some simple GL configuration commands could solve this easily.
if you just want to draw pixels the fastest and easiest way is to simply fill an ofVboMesh with each position in a vertex and set it’s type to OF_PRIMITIVE_TYPE_POINTS
then in draw just draw the mesh and it’ll draw all the points which should be even faster than using instance drawing since you don’t have to upload the matrices or anything
Those are really great news!
But, I will have to build the ofVboMesh on every frame because the points keep moving. Do you think it will still be fast?
Not only the points keep moving… I don’t need to draw all of them every frame. That’s why I say I have to build the ofVboMesh from scratch on very frame.
Unless I find a way to… since I only need 2D… I could set the Z coordinate to 1 or 0 depending on if it is to be drawn and then use a shader to set its alpha to 1 or 0 depending on if it is to be drawn or not…
But if building it from scratch is fast… then that will probably be simpler. And the ofVboMesh will always have much less points also.
Anyway I’m already trying to build your solution. Thanks!
that’s fine it’ll still be much faster than drawing rectangles or using instanced drawing. just clear the mesh and reuse the same every frame instead of creating a new one
Ok I implemented it.
It is indeed fast. But not as fast as the instanced drawing.
Points at 15FPS:
- CPU: 140k
- Instanced drawing: 280k
- ofVboMesh: 240k
I believe you’re still right and this is related to macOS Mojave because, if when I run the vboExample which is supposed to show how ofVboMesh is faster than ofMesh, I get exactly the same results in both.
This said, this approach is still pretty fast and it solves my one-to-one issue so it’s a no brainer. I’m going for it.
Since I’ll have to reinstall my macbook for the exhibition I’ll install macOS High Sierra in the hope that this problem goes away. And that way this may become even faster, like you said.
Thank you so much Arturo!
The difference with the instanced drawing might be because you are not really drawing everything you draw in the other modes, that’s why you see a different output but drawing 1 mesh should be at least as fast than using instanced drawing.
With the vboExample do you disable vertical sync? otherwise it would be limited to 60fps in both cases
Regarding the vboExample, I was getting around 540-630fps in both cases. I just explicitely added ofSetVerticalSync(false) and nothing changed.
I just found out that drawing the ofVboMesh is still different than doing the ofDrawRectangle(x,y,1,1).
The scaling issue I was getting with the instance drawing is now solved.
But the anti-aliasing is still there:
Do you have any suggestions as to why this may still be happening?
While the scaling issue was a deal breaker, this is still very important since my drawing is very intricate and really needs the details to be crips.
If you have an integrated video card the difference between using a vbo or not might be marginal in some cases like the vboExample
I’m not really sure what those images are, so it’s hard to know what’s going on. the only difference i can imagine you could get from drawing a 1x1 rectangle and a point is that the rectangle would be actually drawing 2x2 because the interior is 1x1 so the contours become 2x2, try making the point size 2 using
Ok, for desperate needs, desperate solutions. I used my phone to take a picture of the screen in both scenarios I think it will be clearer now:
- On the left you have ofVboMesh() with glPointSize(1)
- In the middle ofVboMesh() with glPointSize(2)
- On the right is ofDrawRectangle() and, interestingly, glPointSize() doesn’t make any difference here
These are the result of drawing several times over the same points with a very low alpha:
So, as you see, oDrawRectangle() is drawing only 1 pixel while ofVboMesh() seems to be drawing 2x2. Having tweaked with
glPointSize() makes me more convinced that this is some sort of weird antialiasing because you can see that the drawn area didn’t increase when using glPointSize(2). Everything just became more white.
glPointSize(0.5f) on the ofVboMesh() version out of curiosity but the result was the same (I tried a point size of 3 and 4 just to be sure and it did draw much bigger so it was making a difference.
Any idea why this may be happening?
By the way, this is a MacBook Pro with a Retina display (the app is already configured for using it).
And regarding vboExample I checked and it is using the discrete NVidia GeForce graphics card.
you can disable antialiasing by using
ofDisableAntialiasing() but not sure if it has any relation. drawing rectangles uses triangles not points so the rendering will be different and also that’s why glPointSize doesn’t make any difference in that case,
You could use instanced drawing to draw a 1x1 rectangle mesh instead of points if that’s what you want, just create a mesh with a rectangle in it and draw it using OF_MESH_TRIANGLES instead of OF_MESH_POINTS
That was it!
ofDisableAntiAliasing() did the trick!
Not only you greatly simplified my code by suggesting ofVboMesh instead of the much more complex instance drawing, you also helped me solve all the issues I had.
Thank you again and again for all your help Arturo! You saved my day!
Moving on yeah!!!