I'm writing a game for school in OpenGL. Since there will be several more similar assignments I want to make a small framework for doing common things in OpenGL. I have made a few simple games before and I usually break it down into an IO class to handle input and drawing to the screen, Game class for the main game loop/logic, and classes for whatever objects there are in the game.
Before I was using SDL, so my question is, is this the right way of going about this in OpenGL? I've already ran into some trouble. I want my IO class to handle initializing the window, drawing the scene, and mouse clicks. So the constructor looked like this:
IO::IO()
{
currWindowSize[0] = DEF_WIDTH;
currWindowSize[1] = DEF_HEIGHT;
glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGBA );
glutInitWindowPosition( INIT_WINDOW_POSITION[0], INIT_WINDOW_POSITION[1] );
glutInitWindowSize( currWindowSize[0], currWindowSize[1] );
glutCreateWindow( "TEST" );
setUp();
glutDisplayFunc(drawScene);
glutMainLoop();
}
However, drawScene is a class method. Is there a way to pass a class method to glutDisplayFunc() without making it static?
Unfortunately the glutDisplayFunc() doesn't take a void* pointer so you could've fake an object context. You will have to make a static function that can call into the correct IO instance using a static variable.
I see some slight trouble with your pattern also, though. As far as I know, glutMainLoop() never returns until you terminate the GLUT context, therefore you have a constructor that practically never returns, so your program flow is unreasonable. You should move that call into a separate run() method in your class.
(Personally I would use GLFW, which avoids the entire callback mess with GLUT, although you have to write your mainloop.)
Two points,
First, glutMainLoop never returns, and starts dispatching messages. Because you called it from your constructor your class is potentially not properly constructed yet. Additionally glut does support more than one window, and glutModalLoop only needs to be called once.
Second, as you have noted, the method passed to glutDisplayFunc must be static. You will need a static array associating glut window id's with IO pointers. When glutCreateWindow is called by an IO instance, store the returned id and IO instance in the array. Whenever the static drawScene is called you would call glutGetWindow to get the id of the current window, and look up the associated IO pointer and call the non static drawScene implementation.
Before I was using SDL, so my question
is, is this the right way of going
about this in OpenGL?
I'd rather bypass GLUT completely (if you want to learn the inner guts of OpenGL and your OS windowing system interface). Plus GLUT is not supported on the iPhone (if you want to target this platform in the future).
So the idea would be to use WGL on Windows, GLX on Linux and CGL on OS X.
Related
I am wondering about the difference between OnDraw() and OnPaint() in MFC.
After searching the Internet for a while, I found a useful article. In summary,
WM_PAINT will trigger OnPaint(), which calls OnDraw() and passes a CDC*:
void CView::OnPaint()
{
// standard paint routine
CPaintDC dc(this);
OnPrepareDC(&dc);
OnDraw(&dc);
}
Another article mentions that when printing a document, OnPrint() also calls OnDraw() by passing a printer DC. Therefore, by overriding OnDraw(), you get screen painting and printing both in one function, which is convenient.
I tried to put my statements for drawing in either OnDraw() and OnPaint(). Either can work well. OnDraw() is a little easier because it has already gotten a pointer pDC.
Device contexts are an ancient abstraction. They have been described as early as 1982 in the first edition of Computer Graphics: Principles and Practice (probably even earlier) and seem to confuse people to this day.
The primary purpose of a device context is to abstract peculiarities of render devices (such as displays, printers, in-memory bitmaps, etc.) and provide a coherent interface. Code that's rendering into a device context generally does not need to know, which device is ultimately consuming the render commands.
The documentation entry titled Drawing in a View goes on to explain how the system is intended to work: In short, all painting should be performed in an OnDraw override that receives a device context. The system-provided OnPaint implementation then constructs a CPaintDC and calls OnDraw.
Up to this point this seems to be just an overly complex way to render the contents of a window. Things start to make sense when you implement, say, printing support. Now all you have to do is set up a printing device context and call OnDraw. Nothing in your OnDraw implementation needs to change.
I want my application to instantly draw all the data to a display. In windows there is SwapBuffers() function to do such kind of things, where you can do all the drawings to a second virtual window and then swap that virtual window with an existing one. OpenGL provides a glXSwapBuffers() function to do roughly the same. However I don't want to use it. Therefore, I am curios, what are the ways to implement this functionality in pure XLib
In X11 there are the Pixmap resources which are considered as Drawable (like Window).
Then you can draw to a Pixmap using as many steps as necessary, and finally use XCopyArea() to send the resulting drawing to a Window.
Note that a Pixmap stands on the server side, like a Window, so the final copy operation is local to the server.
There is the X Double Buffer Extension: https://www.x.org/releases/X11R7.6/doc/libXext/dbelib.html
The Double Buffer Extension (DBE) provides a standard way to utilize
double-buffering within the framework of the X Window System.
Protocol: https://www.x.org/releases/X11R7.7/doc/xextproto/dbe.html
Never seen it used in practice. Let me know if you pull it off.
I've just started learning DX so I know almost nothing about it although I do know OpenGL (to certain extent). I'm follow a tutorial (http://www.rastertek.com/tutdx11.html) and I have a working window rendering just a white background (clear).
Now - how do I actually switch from windowed mode to fullscreen and vice versa? I know there are many tutorials, some even provide a code for doing that but since I'm a newbie that's not really helpful. Why? Because every code sample is different and trying to find a pattern in all of them is apparently too difficult for me.
So I don't ask for code - instead I would like you to tell me what things I need to release/recreate/change to toggle correctly (and all of them). I know I need to change the display settings, I know I have to change something about the swap chain and release/recreate some buffers - but not really sure which exactly.
You can use SetFullScreenState on your swap chain:
swapChain->SetFullScreenState(true, NULL);
MSDN
The main thing you have to do is release all reference to the IDXGISwapChain, call ResizeBuffers, then re-create everything.
Since Win32 throws the WM_SIZE message upon window initialization, it's entirely possible to:
Clear the previous window-size-specific context
If the swap chain already exists, resize it, otherwise create one
Obtain the backbuffer for this window which will be the final 3D rendertarget.
Create a view interface on the rendertarget to use on bind.
Allocate a 2-D surface as the depth/stencil buffer and create a DepthStencil view on this surface to use on bind.
Create a viewport descriptor of the full window size.
Set the current viewport using the descriptor.
inside a static function (unless WinMain has an object from which to call), and call that function when the WM_SIZE message is triggered.
You can check out how the DirectXTK does it here:
https://directxtk.codeplex.com/
I am working on a screen manager for a miniature game engine, and so far I cannot find a proper solution to managing screen objects without using the 'blob' for each one of the screens. Is blob tolerable in such circumstances where I need a list of renderable objects in one controller?
I would consider using the MVC pattern in this situation. Otherwise, if you're not careful, it's very easy to end up with a bunch of spaghetti code where the screen code is reaching into the game code, and vice versa.
I have recently coded something you might call a "screen manager".
I started with the idea that, whatever game I make, the render system is going to be pretty much the same in terms of how to render (how to manage the hardware). The thing that changes is what is rendered, and how to draw it (do I want a box or a circle or a bitmap.. representing what... etc).
So basically the "game state" is responsible for knowing how to render itself, and should do so when given a render surface from the screen manager or graphics system (It should also be responsible for other things like knowing how input, physics, etc act upon itself).
I implemented it with a singleton for the GraphicsSystem object, which was called something like this:
GameState gs;
Graphics::System().Init(DOUBLE_BUFFER, 640, 480);
...
while(still_looping) {
...
// When it is time to render:
Graphics::System().RenderGameState(&gs);
}
And how, you ask, does the Graphics::System() singleton know how to render the game state? It knows because the game state is inherited from a listener exposed by the graphics system...
//within GraphicsSystem.h...
class BaseRenderer
{
public:
virtual void Render(BITMAP *render_surface) = 0;
};
//GameState defined with:
class GameState : public BaseRenderer
{
public:
void Render(BITMAP *render_surface);
...
You can do this with nearly all the subsystems... (probably not timing, as it is needed in the game loop).
Why singletons? Well, it is C++ and I'm assuming there is only 1 screen, or graphics subsystem to render with. I'm not sure if you are using multiple screens, or a mobile phone or a console. The other way I would do it is to have the graphics system as static global variables in a separate file, giving them file scope only, and having accessor functions in that file (my old C way of doing things).
The key though is encapsulation. Let your screen manager manage the hardware. Let your game state dictate how itself should be expressed.
If this misses the point, please clear up your question and I can edit the answer.
i just started off using OpenGL and it seems it is not easy to understand the working of the glutMainLoop() what really happens there? Does it stay there doing nothing till any of the function calls responds?
It calls your display callback over and over, calling idle between so that it can maintain a specific framerate if possible, and others if necessary (such as if you resize the window or trigger an input event).
Essentially, within this function is the main program loop, where GLUT does most of the work for you and allows you to simply set up the specific program logic in these callbacks. It's been a while since I've worked with GLUT, and it is certainly confusing at first.
In your display callback should obviously be your main logic to draw whatever it is that should be going on. In the idle callback should be some very lightweight operations to determine what the change in state should be from the last time display was called to the next time. For example, if you're animating something, this would be where you change its position or orientation.
It is exactly as StrixVaria has stated.
glutMainLoop enters the GLUT event processing loop. This routine should be called at most once in a GLUT program. Once called, this routine will never return. It will call as necessary any callbacks that have been registered.
Taken from here
Using opengl and glut together means that you would be writing a 'glut' program that uses opengl commands in the callback functions. main contains glut functions. many glut functions need a callback function to be registered. Those callback functions usually contain opengl commands.
Coming to your question, now when it is clear that you are mainly writing a glut program, it should also be taken that glutMainLoop function call actually executes the callback functions as and when required, which in return executes the opengl commands.
Well glutMainLoop is the main function the keeps calling and calling the displaying functions and which also keeps your window actually opened. You''ll find out that opengl is not that scary.