Rewriting a simple Pygame 2D drawing function in C++ - c++

I have a 2D list of vectors (say 20x20 / 400 points) and I am drawing these points on a screen like so:
for row in grid:
for point in row:
pygame.draw.circle(window, white, (particle.x, particle.y), 2, 0)
pygame.display.flip() #redraw the screen
This works perfectly, however it's much slower then I expected.
I want to rewrite this in C++ and hopefully learn some stuff (I am doing a unit on C++ atm, so it'll help) on the way. What's the easiest way to approach this? I have looked at Direct X, and have so far followed a bunch of tutorials and have drawn some rudimentary triangles. However I can't find a simple (draw point).

DirectX doesn't have functions for drawing just one point. It operates on vertex and index buffers only. If you want simpler way to make just one point, you'll need to write a wrapper.
For drawing lists of points you'll need to use DrawPrimitive(D3DPT_POINTLIST, ...). however, there will be no easy way to just plot a point. You'll have to prepare buffer, lock it, fill with data, then draw the buffer. Or you could use dynamic vertex buffers - to optimize performance. There is a DrawPrimitiveUP call that is supposed to be able to render primitives stored in system memory (instead of using buffers), but as far as I know, it doesn't work (may silently discard primitives) with pure devices, so you'll have to use software vertex processing.
In OpenGL you have glVertex2f and glVertex3f. Your call would look like this (there might be a typo or syntax error - I didn't compiler/run it) :
glBegin(GL_POINTS);
glColor3f(1.0, 1.0, 1.0);//white
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
glVertex2f(points[y][x].x, points[y][x].y);//plot point
glEnd();
OpenGL is MUCH easier for playing around and experimenting than DirectX. I'd recommend to take a look at SDL, and use it in conjuction with OpenGL. Or you could use GLUT instead of SDL.
Or you could try using Qt 4. It has a very good 2D rendering routines.

When I first dabbled with game/graphics programming I became fond of Allegro. It's got a huge range of features and a pretty easy learning curve.

Related

Drawing large text with GLUT?

I have created a tic-tac-toe game for school, and I am basically finished. The only thing I have left is that when someone wins, I want a box to pop up on the screen and to say in big text "X Wins" or "O Wins" depending on who one.
I've found that drawing text in openGL is very complicated. Since this isn't crucial to the assignment, I'm not looking for something complicated or and don't need it to look super nice. Also, I would most likely just want to change my code. Also, I want the size of the text to be variable driven for when I re-size the window.
This is what my text drawing function currently looks like. It draws it really small.
Note: mText is an int [2] data member that holds where I want to draw the text
void FullGame::DrawText(const char *string) const
{
glColor3d(1, 1, 1);
void *font = GLUT_BITMAP_TIMES_ROMAN_24;
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
int len, i;
glRasterPos2d(mText[0], mText[1]);
len = (int)strlen(string);
for (i = 0; i < len; i++)
{
glutBitmapCharacter(font, string[i]);
}
glDisable(GL_BLEND);
}
Short answer:
You are drawing bitmap characters which cannot be resized since they are given in pixels. Try using a stroke character or string with one of the following functions: glutStrokeCharacter, glutStrokeString. Stroke fonts can be resized using glscalef.
Long answer:
Actually, instead of printing the text character by character you could have used:
glutBitmapString(GLUT_BITMAP_TIMES_ROMAN_24, "Text to appear!");
Here the font size is in pixel so scaling will not work in direct usage.
Please note that glutBitmapString is introduced in FreeGLUT, which is an open source alternative to the OpenGL Utility Toolkit (GLUT) library. For more details in font rendering: http://freeglut.sourceforge.net/docs/api.php#FontRendering
I strongly advice using FreeGlut rather than the original Glut.
1 - Glut`s last release was before the year 2000 so it has some missing features: http://www.lighthouse3d.com/cg-topics/glut-and-freeglut/
2 - Two of the most common GLUT replacements are OpenGLUT and freeGLUT, both of which are open source projects.
If you decide using FreeGlut you should have the following include:
#include < GL/freeglut.h>
Having said that all you need is scaling the text, therefore you can use glutStrokeString which is more flexible than bitmap string,e.g., it can be resized visually. You can try:
glScalef(0.005,0.005,1);
glutStrokeString(GLUT_STROKE_ROMAN, (unsigned char*)"The game over!");
Hope that helps!
The easiest way is to generate a texture for each "Win" screen and render it on a quad. It sounds like you're not concerned about printing arbitrary strings, only 2 possible messages. You can draw the textures in Paint or whatever, and if you're not that worried about quality, the textures don't even have to be that big. Easy to implement and totally resizable.

How to draw D3DXFont using D3DXSprite in DirectX 9 as fast as possible?

I have lots of text to draw. If I call D3DXFont::DrawText with first parameter being NULL I get terrible performance.
I heard that using D3DXFont with conjunction with D3DXSprites makes things much more faster.
How my application needs to draw strings?
It daraws every string with pseudo shadow. It means I draw each string 4 times in black:
x + 1, y + 1
x - 1, y + 1
x - 1, y - 1
x + 1, y - 1
and 1 time in actual color. It makes very nice looking always readable strings. I even switched to pixel fonts for faster rendering.
Now call that string with shadow (ShadowString).
Every frame I draw 256 (worst case scenario) of those ShadowStrings on screen.
I would like to know how to use sprites (or any other technique) to speed up drawing of those string as much as possible). Now I'm getting 30 FPS in app. But I target for 120 min. And problem is ONLY that text drawing thing.
Surely, you must profile your application before any optimizations, but truth to be told, D3DXFont/D3DXSprites and "fast" is mutually exclusive concepts. If they do not fit, just don't use them.
Use 3rd party libraries or make your own sprite/font renderer.
Recently I've answered about how to do it here: How to draw line and font without D3DX9 in DirectX 9?
Also, Google for "sprite font", "sprite batching", "texture atlases", "TTF rendering". It is not very difficult if you are familiar with API (notably vertex buffers and texturing), and there are plenty of examples on web. Don't hesitate to look for D3D11 or OpenGL examples, principles are the same.

Drawing big circles from scratch [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I am new to C++, but the language seems alright to me. As a learning project I have decided to make a minor 2D graphic-engine. It might seem like a hard project, but I have a good idea how to move on.
I havn't really started yet, but I am forming things in my head at the moment, when I came across this problem:
At some point I will have to make a function to draw circles on the screen. My approach to that right now would be something like this:
in a square with sides from (x-r) to (x+r) loop through x and y,
if at each point, the current distance sqr(x^2+y^2) is less than or equal to r
, then draw a pixel at that point.
This would work, if not, dont bother telling me, I'll figure it out. I would of cause only draw this circle if the x+r & y+r is on the screen.
The problem lies in that I will need to draw really big circles sometimes. If for example I need to draw a circle with radius 5000, the (if pixel loop calculations would need loop a total of 10000^2 times). So with a processor at 2Ghz, this single circle would only be able to render 2Ghz/(10000^2) which is ~22 times/s while taking up the whole core (believing it only takes one calculation per pixel, which is nowhere the truth).
Which approach is the correct one now? I guess it has something to do with using the GFX for these simple calculations. If so, can I use OpenGL for C++ for this? I'd like to learn that as well :)
My first C/C++ projects were in fact graphics libraries as well. I did not have OpenGL or DirectX and was using DOS at the time. I learned quite a lot from it, as I constantly found new and better (and faster) ways to draw to the screen.
The problem with modern operating systems is that they don't really allow you to do what I did back then. You cannot just start using the hardware directly. And frankly, these days you don't want to anymore.
You can still draw everything yourself. Have a look at SDL if you want to put your own pixels. This is a C library that you will be able to wrap into your own C++ objects. It works on different platforms (including Linux, Windows, Mac,...) and internally it will make use of things like DirectX or OpenGL.
For real-world graphics, one doesn't just go about drawing one's own pixels. That is not efficient. Or at least not on devices where you cannot use the hardware directly...
But for your purposes, I think SDL is definitely the way to go! Good luck with that.
You don't do graphics by manually drawing pixels to screen, that way madness lies.
What you want to use is either DirectX or OpenGL. I suggest you crack open google and go read, there's a lot to read out there.
Once you've downloaded the libs there's lots of sample projects to take a look at, they'll get you started.
There's two approaches at this point: there's the mathematical way of calculating the vectors that describe a shape with a very large number of sides (i.e it'll look like a circle). Or there's the 'cheating' method of just drawing a texture (i.e a picture) of a circle to the screen with an alpha channel to make the rest of the texture transparent. (The cheating method is easier to code, faster to execute, and produces a better result, although it is less flexible).
If you want to do it mathematically then both of these libraries will allow you to draw lines to screen, so you need to begin your approach from the view of start point and end point of each line, not the individual pixels. i,e you want vector graphics.
I can't do the heavy maths right now, but the vector approach might look a little like this (sudo-code):
in-param: num_of_sides, length_of_side;
float angle = 360 / num_of_sides;
float start_x = 0;
float start_y = 0;
x = startX;
y = startX;
for(int i(0); i < num_of_sides; ++i)
{
float endX, endY;
rotateOffsetByAngle(x, y, x + lenth_of_side, y, angle * i, endX, endY);
drawline(x, y, endX, endY);
x = endX;
y = endY;
}
drawline(float startX, startY, endX, endY)
{
//does code that draws line between the start and end coordinates;
}
rotateOffsetByAngle(float startX, startY, endX, endY, angle, &outX, &outY)
{
//the in-parameters startX, startY and endX, endY describe a line
//we treat this line as the offset from the starting point
//do code that rotates this line around the point startX, startY, by the angle.
//after this rotation is done endX and endY are now at the same
//distance from startX and startY that they were, but rotated.
outX = endX;
outY = endY; //pass these new coordinates back out by reference;
}
In the above code we move around the outside of the circle drawing each individual line around the outside 1 by one. For each line we have a start point and an offset, we then rotate the offset by an angle (this angle increases as we move around the circle). Then we draw the line from the start point to the offset point. Before we begin the next iteration we move the start point to the offset point so the next line starts from the end of the last.
I hope that's understandable.
That is one way to draw a filled circle. It will perform appallingly slowly, as you can see.
Modern graphics is based on abstracting away the lower-level stuff so that it can be optimised; the developer writes drawCircle(x,y,r) and the graphics libary + drivers can pass that all the way down to the chip, which can fill in the appropriate pixels.
Although you are writing in C++, you are not manipulating data closest to the core unless you use the graphics drivers. There are layers of subroutine calls between even your setPixelColour level methods and an actual binary value being passed over the wire; at almost every layer there are checks and additional calculations and routines run. The secret to faster graphics, then, is to reduce the number of these calls you make. If you can get the command drawCircle all the way to the graphics chip, do that. Don't waste a call on a single pixel, when it's as mundane as drawing a regular shape.
In a modern OS, there are layers of graphics processing taking the requests of individual applications like yours and combining them with the windowing, compositing and any other effects. So your command to 'draw to screen' is intermediated by several layers already. What you want to provide to the CPU is the minimum information necessary to offload the calculations to the graphics subsystem.
I would say if you want to learn to draw stuff on the screen, play with canvas and js, as the development cycle is easy and comparatively painless. If you want to learn C++, try project Euler, or draw stuff using existing graphics libraries. If you want to write a 2d graphics library, learn the underlying graphics technologies like DirectX and OpenGL, because they are the way that graphics is done in reality. But they seem so complex, you say? Then you need to learn more C++ first. They are the way they are for some very good reasons, however complex the result is.
As the first answer says, you shouldn't do this yourself for serious work. But if you just want to do this as an example, then could could do something like this: First define a function for drawing line segments on the screen:
void draw_line(int x1, int y1, int x2, int y2);
This should be relatively straightforward to implement: Just find the direction that is changing fastest, and iterate over that direction while using integer logic to find out how much the other dimension should change. I.e., if x is changing faster, then y = (x-x1)*(y2-y1)/(x2-x1).
Then use this function to implement a circle as piecewise line elements:
void draw_circle(int x, int y, int r)
{
double dtheta = 2*M_PI/8/r;
int x1 = x+r, x2, y1 = y, y2;
int n = 2*M_PI/dtheta;
for(int i = 1; i < n; i++)
{
double theta = i*dtheta;
x2 = int(x+r*cos(theta)); y2 = int(y+r*sin(theta));
draw_line(x1, y1, x2, y2);
x1 = x2; y1 = y2;
}
}
This uses floating point logic and trigonometric functions to figure out which line elements best approximate a circle. It is a somewhat crude implementation, but I think any implementation that wants to be efficient for very large circles has to do something like this.
If you are only allowed to use integer logic, one approach could be to first draw a low-resolution integer circle, and then subdivide each selected pixel into smaller pixels, and choose the sub-pixels you want there, and so on. This would scale as N log N, so still slower than the approach above. But you would be able to avoid sin and cos.

What is the best way to detect mouse-location/clicks on object in OpenGL?

I am creating a simple 2D OpenGL game, and I need to know when the player clicks or mouses over an OpenGL primitive. (For example, on a GL_QUADS that serves as one of the tiles...) There doesn't seems to be a simple way to do this beyond brute force or opengl.org's suggestion of using a unique color for every one of my primitives, which seems a little hacky. Am I missing something? Thanks...
My advice, don't use OpenGL's selection mode or OpenGL rendering (brute force method you are talking about), use a CPU-based ray picking algorithm if 3D. For 2D, like in your case, it should be straightforward, it's just a test to know if a 2D point is in a 2D rectangle.
I would suggest to use the hacky method if you want a quick implementation (coding time, I mean). Especially if you don't want to implement a quadtree with moving ojects. If you are using opengl immediate mode, that should be straightforward:
// Rendering part
glClearColor(0,0,0,0);
glClear(GL_COLOR_BUFFER_BIT);
for(unsigned i=0; i<tileCout; ++i){
unsigned tileId = i+1; // we inc the tile ID in order not to pick up the black
glColor3ub(tileId &0xFF, (tileId >>8)&0xFF, (tileId >>16)&0xFF);
renderTileWithoutColorNorTextures(i);
}
// Let's retrieve the tile ID
unsigned tileId = 0;
glReadPixels(mouseX, mouseY, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
(unsigned char *)&tileId);
if(tileId!=0){ // if we didn't picked the black
tileId--;
// we picked the tile number tileId
}
// We don't want to show that to the user, so we clean the screen
glClearColor(...); // the color you want
glClear(GL_COLOR_BUFFER_BIT);
// Now, render your real scene
// ...
// And we swap
whateverSwapBuffers(); // might be glutSwapBuffers, glx, ...
You can use OpenGL's glRenderMode(GL_SELECT) mode. Here is some code that uses it, and it should be easy to follow (look for the _pick method)
(and here's the same code using GL_SELECT in C)
(There have been cases - in the past - of GL_SELECT being deliberately slowed down on 'non-workstation' cards in order to discourage CAD and modeling users from buying consumer 3D cards; that ought to be a bad habit of the past that ATI and NVidia have grown out of ;) )

Slow C++ DirectX 2D Game

I'm new to C++ and DirectX, I come from XNA.
I have developed a game like Fly The Copter.
What i've done is created a class named Wall.
While the game is running I draw all the walls.
In XNA I stored the walls in a ArrayList and in C++ I've used vector.
In XNA the game just runs fast and in C++ really slow.
Here's the C++ code:
void GameScreen::Update()
{
//Update Walls
int len = walls.size();
for(int i = wallsPassed; i < len; i++)
{
walls.at(i).Update();
if (walls.at(i).pos.x <= -40)
wallsPassed += 2;
}
}
void GameScreen::Draw()
{
//Draw Walls
int len = walls.size();
for(int i = wallsPassed; i < len; i++)
{
if (walls.at(i).pos.x < 1280)
walls.at(i).Draw();
else
break;
}
}
In the Update method I decrease the X value by 4.
In the Draw method I call sprite->Draw (Direct3DXSprite).
That the only codes that runs in the game loop.
I know this is a bad code, if you have an idea to improve it please help.
Thanks and sorry about my english.
Try replacing all occurrences of at() with the [] operator. For example:
walls[i].Draw();
and then turn on all optimisations. Both [] and at() are function calls - to get the maximum performance you need to make sure that they are inlined, which is what upping the optimisation level will do.
You can also do some minimal caching of a wall object - for example:
for(int i = wallsPassed; i < len; i++)
{
Wall & w = walls[i];
w.Update();
if (w.pos.x <= -40)
wallsPassed += 2;
}
Try to narrow the cause of the performance problem (also termed profiling). I would try drawing only one object while continue updating all the objects. If its suddenly faster, then its a DirectX drawing problem.
Otherwise try drawing all the objects, but updating only one wall. If its faster then your update() function may be too expensive.
How fast is 'fast'?
How slow is'really slow'?
How many sprites are you drawing?
How big is each one as an image file, and in pixels drawn on-screen?
How does performance scale (in XNA/C++) as you change the number of sprites drawn?
What difference do you get if you draw without updating, or vice versa
Maybe you just have forgotten to turn on release mode :) I had some problems with it in the past - I thought my code was very slow because of debug mode. If it's not it, you can have a problem with rendering part, or with huge count of objects. The code you provided looks good...
Have you tried multiple buffers (a.k.a. Double Buffering) for the bitmaps?
The typical scenario is to draw in one buffer, then while the first buffer is copied to the screen, draw in a second buffer.
Another technique is to have a huge "logical" screen in memory. The portion draw in the physical display is a viewport or view into a small area in the logical screen. Moving the background (or screen) just requires a copy on the part of the graphics processor.
You can aid batching of sprite draw calls. Presumably Your draw call calls your only instance of ID3DXSprite::Draw with the relevant parameters.
You can get much improved performance by doing a call to ID3DXSprite::Begin (with the D3DXSPRITE_SORT_TEXTURE flag set) and then calling ID3DXSprite::End when you've done all your rendering. ID3DXSprite will then sort all your sprite calls by texture to decrease the number of texture switches and batch the relevant calls together. This will improve performance massively.
Its difficult to say more, however, without seeing the internals of your Update and Draw calls. The above is only a guess ...
To draw every single wall with a different draw call is a bad idea. Try to batch the data into a single vertex buffer/index buffer and send them into a single draw. That's a more sane idea.
Anyway for getting an idea of WHY it goes slowly try with some CPU and GPU (PerfHud, Intel GPA, etc...) to know first of all WHAT's the bottleneck (if the CPU or the GPU). And then you can fight to alleviate the problem.
The lookups into your list of walls are unlikely to be the source of your slowdown. The cost of drawing objects in 3D will typically be the limiting factor.
The important parts are your draw code, the flags you used to create the DirectX device, and the flags you use to create your textures. My stab in the dark... check that you initialize the device as HAL (hardware 3d) rather than REF (software 3d).
Also, how many sprites are you drawing? Each draw call has a fair amount of overhead. If you make more than couple-hundred per frame, that will be your limiting factor.