I have a platformer game, which is drawn using vector art. That is, I do not use any bitmaps of arbitrary size, but draw everything using draw.rectangle('fill', ...) and draw.polygon('fill', ...) (mainly for triangles).
However, I have run into performance issues. When I have about 80 blocks, platforms and spikes the framerate drops to 35 FPS, what is rather unpleasant to play. When don't render them, my FPS is about 110.
My blocks generally doesn't move, so I thought about using something like VertexArray in SFML, but Love2d hasn't anything like that. I found love.graphics.SpriteBatch, but it doesn't seem to support rectangles and triangles without texture.
In summary, how can I quickly draw lots of simple, static shapes in Love2d?
Well, it turns out it is just called a Mesh in Love2d, not vertex array.
Anyway, thanks for all your attention (4 views, that was sarcastic).
Related
I am trying to understand the whole 2D accelerated rendering process using SDL 2.0.
So my question is which would be the most efficient way to draw circles in the screen and why?
Some ways would be:
First to create a software surface and then draw the necessary pixels on that surface then create a texture out of that surface and lastly copy that texture to the rendering target.
Also another implementation would be to draw a circle using multiple times SDL_RenderDrawLine.And I think this is the way it is being implemented in SDL 2.0 gfx
Or there is a more efficient way to do all of this?
Take this question more generally in means of if I would wanted to draw other shapes manually, which probably, couldn't be rendered easily with the 2D rendering API that SDL provides(using draw line or rectangle).
With the example of circles this is a fairly complicated question, it is more based on the visual quality you wish to achieve which will drive performance. Drawing lots of short lines will vary vastly based on how close to a circle you wish to get, if you are happy to use say, 60 lines, which will work on small shapes nearly seamlessly but if scaled up will begin to appear not to be a circle, the performance will likely be better (depending on the user's hardware). Note also SDL_RenderDrawLines will be much much faster for many lines as it avoids lots of context switches for rendering calls.
However if you need a very accurate circle with thousands of lines to get a good approximation it will be faster to simply use a bitmap and scale and blit it. This will also give you a 'smoother' feel to the circle.
In my personal opinion I do not think the hardware accelerated render API has much use outside of some special uses such as graph rendering and perhaps very simple GUI drawing. For anything more complex I would usually use bitmap based drawing.
With regards to the second part, it again depends on the accuracy of any arcs you need to draw. If you can easily approximate the shape into a few tens of lines it will be fast, otherwise the pixel method is better.
it's my first question here so I hope it conforms to the guidelines. Also please excuse my bad English.
I'm currently working on a WebGL application based on three.js that displays thousands of cubes and lines between those cubes. I have several performance issues so I decided to merge all the cubes to one geometry. That helped a little but actually the performance is slowed down by those thousands of lines (all having their own geometry (based on the NURBSCurve example of three.js) and shader materials (shader blends two colors from the start to the end of the line and controls opacity). My biggest data includes over 9000 lines and over 5000 cubes. Without the lines the FPS rate is between 45 - 50 (DirectX) or 20 FPS (OpenGL) but with the lines the performance drops to 5 FPS. I only have an Intel HD Graphics (5th Gen) graphic card so the maximum FPS seems to be restricted to 60 FPS but that is totally enough in my case.
As I said before the lines are NURBS curves and they range from short curves to long, complex curves. Another requirement (which gives me a little headache ;-)) is that each line differs in width, so I actually have to use OpenGL, which is slower in my case and also causes some other problems.
Anyway I have tried several approaches but none of them really helped me to solve the problem.
1) Create pipes for each line and merge the geometries. -> This slowed down the creation of the scene from 1 second to several minutes. Besides FPS rate couldn't be improved. This is actually expected due to the mass amount of vertices and faces produced by this approach.
2) Reduce points of curve. -> Reduced from 200 to 50 points which helped to improve FPS a little. A reduction to 25 points didn't bring any more improvements. I was thinking to write a method to reduce unneeded points (like in straight curves, 2 instead of 50 points are enough) but I don't know how to achieve this so I thought about other ways first. Maybe I will come back to this.
3) Use BufferGeometry. -> It seems like BufferGeometry cannot be used together with shader material. At least in my case I didn't get it to work so that none of my tries displayed anything. By the way I used THREE.BufferGeometryUtils to create the buffer geometries from my NURBS curves. I tried to set THREE.VertexColors as a parameter to the function and colorsNeedUpdate in the geometry but still no display. Actually, I also tried buffergeometry with the curbes geometry and didn't get any improvements in performance.
4) Use splines instead of NURBS curves. ->The paths of the curves were not like I would like them to be and there wasn't any improvements.
5) Merge lines to one line with THREE.LinePieces. -> Well, although I had to double the number of vertices, this actually helped a lot. In case of DirectX, performance improved from 5 FPS to 25 FPS (OpenGL still at 4 FPS) but this solution is not appropriate in my case. The reason is that the lines cannot differ in width, which is in case of DirectX restricted to 1 anyway. I was wondering how other people solved the issue of line width restriction and found out that some are creating thicker lines via Geometry Shader. So my new hope was this Geometry Shader. But then I found out that Geometry shaders are not supported by WebGL.
Sorry for the really long explanation of my approaches so far. After trying out all that I cannot come up with any new ideas. Now I would like to know from the experts if I should just live with the FPS drop or if there is still another way which I could try out?
I came up with the idea to bundle lines by width and then merge these bundles using THREE.LinePieces. In the best case I could reduce about 860 lines to just 2. Of course the effectiveness of this solution depends on the data. Besides, I still have the problem that DirectX is much faster than OpenGL (e.g. 50 FPS instead of 8 FPS) but I need the latter one in order to support thicker lines. So if anyone comes up with a solution for my problem supporting DirectX I would highly appreciate it :-).
Recently started learning webGL and decided to use the Three.js library.
Currently, in addition to, rendering over 100K of cubes, I'm also trying to render lines between those cubes (over 100K).
The problem with rendering occurs when I try to draw lines, NOT cubes. Rendering 100k cubes was relatively fast. Even rendering those 100K+ lines is relatively fast but when I try to zoom/pan using the TrackballControls, the FPS goes down to almost 0.
I've searched StackOverflow and various other sites in order to improve the performance of my application. I've used the merging geometries technique, the delayed rendering of lines ( basically x number of cubes/lines at a time using a timeout in js), and adjusting the appearance of the lines to require the most minimal rendering time.
Are there any other methods in constructing the lines so that the rendering/fps aren't affected? I'm building a group of lines and THEN adding it to the scene. But is there a way that merging is possible with lines? Should I be constructing my lines using different objects?
I just find it strange that I can easily render/pan/zoom/maintain a high fps with over 100k cubes but with lines (which is the most basic form of geometry besides a point), everything crashes.
You have found out (the hard way) where do graphics chip vendors put their focus on their devise drivers. But that is to be expected in 3D graphics as lines (yes the most basic geometry) are not used my many games so they do not receive much attention as polygons do. You can take a look at the example webgl_buffergeometry_lines.html which is probably the faster way to draw lines.
I am creating a tile-based 2D game as a way of learning basic "modern" OpenGL concepts. I'm using shaders with OpenGL 2.1., and am familiar with the rendering pipeline and how to actually draw geometry on-screen. What I'm wondering is the best way to organize a tilemap to render quickly and efficiently. I have thought of several potential methods:
1.) Store the quad representing a single tile (vertices and texture coordinates) in a VBO and render each tile with a separate draw* call, translating it to the correct position onscreen and using uniform2i to give the location in the texture atlas for that particular tile;
2.) Keep a VBO containing every tile onscreen (already-computed screen coordinates and texture atlas coordinates), using BufferSubData to update the tiles every frame but using a single draw* call;
3.) Keep VBOs containing static NxN "chunks" of tiles, drawing however many chunks of tiles are at least partially visible onscreen and translating them each into position.
*I'd like to stay away from the last option if possible unless rendering chunks of 64x64 is not too inefficient. Tiles are loaded into memory in blocks of that size, and even though only about 20x40 tiles are visible onscreen at a time, I would have to render up to four chunks at once. This method would also complicate my code in several other ways.
So, which of these is the most efficient way to render a screen of tiles? Are there any better methods?
You could do any one of these and they would probably be fine; what you're proposing to render is very, very simple.
#1 will definitely be worse in principle than the other options, because you would be drawing many extremely simple “models” rather than letting the GPU do a whole lot of batch work on one draw call. However, if you have only 20×40 = 800 tiles visible on screen at once, then this is a trivial amount of work for any modern CPU and GPU (unless you're doing some crazy fragment shader).
I recommend you go with whichever is simplest to program for you, so that you can continue work on your game. I imagine this would be #1, or possibly #2. If and when you find yourself with a performance problem, do whichever of #2 or #3 (64×64 sounds like a fine chunk size) lets you spend the least CPU time on your program's part of drawing (i.e. updating the buffer(s)).
I've been recently learning modern OpenGL myself, through OpenGL ES 2.0 on Android. The OpenGL ES 2.0 Programming Guide recommends an "array of structures", that is,
"Store vertex attributes together in a single buffer. The structure represents all attributes of a vertex and we have an array of these attributes per vertex."
While this may seem like it would initially consume a lot of space, it allows for efficient rendering using VBOs and flexibility in texture mapping each tile. I recently did a tiled hex grid using interleaved arrays containing vertex, normals, color, and texture data for a 20x20 tile hex grid on a Droid 2. So far things are running smoothly.
I'm trying to create a platformer game, and I am taking various sprite blocks, and piecing them together in order to draw the level. This requires drawing a large number of sprites on the screen every single frame. A good computer has no problem handling drawing all the sprites, but it starts to impact performance on older computers. Since this is NOT a big game, I want it to be able to run on almost any computer. Right now, I am using the following DirectX function to draw my sprites:
D3DXVECTOR3 center(0.0f, 0.0f, 0.0f);
D3DXVECTOR3 position(static_cast<float>(x), static_cast<float>(y), z);
(my LPD3DXSPRITE object)->Draw((sprite texture pointer), NULL, ¢er, &position, D3DCOLOR_ARGB(a, r, g, b));
Is there a more efficient way to draw these pictures on the screen? Is there a way that I can use less complex picture files (I'm using regular png's right now) to speed things up?
To sum it up: What is the most performance friendly way to draw sprites in DirectX? thanks!
The ID3DXSPRITE interface you are using is already pretty efficient. Make sure all your sprite draw calls happen in one batch if possible between the sprite begin and end calls. This allows the sprite interface to arrange the draws in the most efficient way.
For extra performance you can load multiple smaller textures in to one larger texture and use texture coordinates to get them out. This makes it so textures don't have to be swapped as frequently. See:
http://nexe.gamedev.net/directknowledge/default.asp?p=ID3DXSprite
The file type you are using for the textures does not matter as long as they are are preloaded into textures. Make sure you load them all in to textures once when the game/level is loading. Once you have loaded them in to textures it does not matter what format they were originally in.
If you still are not getting the performance you want, try using PIX to profile your application and find where the bottlenecks really are.
Edit:
This is too long to fit in a comment, so I will edit this post.
When I say swapping textures I mean binding them to a texture stage with SetTexture. Each time SetTexture is called there is a small performance hit as it changes the state of the texture stage. Normally this delay is fairly small, but can be bad if DirectX has to pull the texture from system memory to video memory.
ID3DXsprite will reorder the draws that are between begin and end calls for you. This means SetTexture will typically only be called once for each texture regardless of the order you draw them in.
It is often worth loading small textures into a large one. For example if it were possible to fit all small textures in to one large one, then the texture stage could just stay bound to that texture for all draws. Normally this will give a noticeable improvement, but testing is the only way to know for sure how much it will help. It would look terrible, but you could just throw in any large texture and pretend it is the combined one to test what performance difference there would be.
I agree with dschaeffer, but would like to add that if you are using a large number different textures, it may better to smush them together on a single (or few) larger textures and adjust the texture coordinates for different sprites accordingly. Texturing state changes cost a lot and this may speed things up on older systems.