Hey, new to LWJGL here. A question

Started by Yalpe, June 22, 2006, 11:53:42

Previous topic - Next topic

Yalpe

Hey guys,

I've failed quite a few times at writting the game I designed using C++/DX, C++/Allegro. I'm pretty good with java so I decided I'd give it a shot (big + for no language problems).

I was fiddling around with the tuts last night and something bothered me. How do you set the PixelFormat in windowed mode? The method signatures in the javadoc weren't really helpfull. What is the difference between bitperpixel and bitdepth? (Some calls has both)

PixelFormat(int bpp, int alpha, int depth, int stencil, int samples)

What is a stencil? Fonts? What about samples?

Also, how do you fetch the information back from the Display class? .getBitsPerPixel() always returned 0 for me.

Another quick one. If I want some constant timing in the game, should I set up my loop like this? :

while (running)
//update input
//update logic at 60 fps
//render

Would rendering at infinite fps and locking the logic at 60 be a good idea? My guess is that it would make the game fluid while keeping everything timed well.

Is there any way to detect if the window is active so that you can lock the rendering?

Thanks to anyone who answers.

CuppoJava

I can't comment on anything except for the game loop...
That's the game loop format that I'm currently using and it works most of the time. There's one thing to keep in mind however, and I have yet to find an elegant solution for it.

imagine it's been 0.07 seconds since you last called updateLogic(). So now you try and update the appropriate number of frames before you render. But the scene might be very complicated and it takes you 0.08 seconds to update those frames, then you'll have even more to update during the next render.
Pretty soon, your game will slow to a halt.

 -Cuppo

xindon

I woudnt set a update limit like 60fps for the logic. You just render and update as fast as possible, mostly it is limited by the video driver (vsync!).

I know what the problem is, you want a constant movement for objects and other timing.
The solution is, every frame you calculate the current fps and depending on this value you do the other calculations like movement.


float fpsFactor = 60.0f / currentFPS;

example:
player.x += player.speed * fpsFactor;

So if the current FPS are exactly 60, fpsFactor will be 1 and the movement will work in the way you defined the player speed for 60 frames per second. You can call this "expected fps" or whatever you want. It's just the value you've set up your speeds for.
If the current FPS are 100, fpsFactor will be 60.0f/100.0f = 0.6f. So the player speed will be decreased.
The logic:
- lots of frames per second   ->  moving in small steps
- less frames per second -> moving in greater steps

This way your program will run on any kind of machine without speed limit.

aldacron

Quote from: "Yalpe"Hey guys,

I was fiddling around with the tuts last night and something bothered me. How do you set the PixelFormat in windowed mode? The method signatures in the javadoc weren't really helpfull.

The pixel format is set the same way in both windowed and fullscreen modes. You call Display.create(myPixelFormat). This is independent of display mode.

QuoteWhat is the difference between bitperpixel and bitdepth? (Some calls has both)

PixelFormat(int bpp, int alpha, int depth, int stencil, int samples)

The depth argument here is not "bitDepth". It is "depth buffer".

QuoteWhat is a stencil?


In an OpenGL application you can have three different pixel buffers to manipulate: the color buffer (also known as the frame buffer) is what you normally render to and is what is displayed on screen; the depth buffer is used internally by the API to determine the color of a pixel based on z-order, though you can use it for special effects; the stencil buffer is used to mask certain pixels out of a rendering operation and is used for some special effects, such as a well-known shadow technique.

So the bpp argument controls the bit depth of the color buffer, the depth argument controls the bit depth of the depth buffer, and the stencil argument controls the bit depth of the stencil buffer. All of these values are interpreted to be the minimum you will accept and you will often wind up with higher values in actuality. A common format to request is a 32-bit color buffer, 24-bit depth buffer, and an 8-bit stencil.

Note that this is all internal to OpenGL. The bpp of the color buffer does not need to be the same value as the bpp of the display mode. They are two separate beasts, though they usually wind up being the same value for efficiency.

QuoteWhat about samples?

This controls full screen antialiasing (multisampling). If you pass a value of 2, for example, will give you what is normally referred to as 2xanti-aliasing, whereas 4 will give you 4xanti-aliasing. This is actually an extension and is not supported by all cards. Also, cards that do support it may vary in the numer of samples supported (2, 4, 8, 16).

QuoteAlso, how do you fetch the information back from the Display class? .getBitsPerPixel() always returned 0 for me.

Display.getDisplayMode.getBitsPerPixel() should do the trick. Calling this before creating the display should give you the current desktop bits per pixel. If you create a windowed mode window, it should still be returning the same value, since if you pass a display mode to setDisplayMode() in windowed mode, only the width & height are used to resize the window. The desktop bpp is not changed until you call setFullScreen(true).

If you are getting zero back from that call then there must be a bug somewhere.

Quote
Another quick one. If I want some constant timing in the game, should I set up my loop like this? :

while (running)
//update input
//update logic at 60 fps
//render

Would rendering at infinite fps and locking the logic at 60 be a good idea? My guess is that it would make the game fluid while keeping everything timed well.

Read this article. It's a great explanation of the three most common timing techniques in the game loop.

QuoteIs there any way to detect if the window is active so that you can lock the rendering?

Display.isActive()

Yalpe

Thanks for all the tips. This was very insightfull. The article is also great, though I'm not sure what he means by "prediction function". If you could explain that to me it would be very appreciated! Is it like what xindon has suggested? Anyways, great comments overall. Thank you very much.

darkprophet

Quote
the color buffer (also known as the frame buffer)

Sorry to step over your feet, but the colour buffer is not the frame buffer. The frame buffer is the collection of colour buffers, the depth buffer and stencil buffers.

As proof of this, the new extension EXT_framebuffer_object has multiple attachment points, some of which are colour attachments, stencil and depth attachments.

Otherwise, very insightful and helpful post :)

DP

aldacron

Quote from: "darkprophet"Sorry to step over your feet, but the colour buffer is not the frame buffer. The frame buffer is the collection of colour buffers, the depth buffer and stencil buffers.

As proof of this, the new extension EXT_framebuffer_object has multiple attachment points, some of which are colour attachments, stencil and depth attachments.

Ouch, my toes!  :D I suppose a little explanation is in order. The term "frame buffer" has been around for quite some time. When graphics programmers still had direct access to video memory, that's the term they bandied about when referring to video memory (also called "buffer memory"). In fact, if you have a copy of Computer Graphics: Principles and Practice (which I recommend you get if you don't), the Introduction explains many common graphics terms (raster, bitmap, pixmap, etc...) and defines "frame buffer" as just that - buffer memory. Game programmers used that term for years.

Double buffering is possible with OpenGL, but it's all done behind the scenes. So when you are rendering to the color buffer it is like
rendering directly to the screen (or frame buffer), whether double buffering is enabled or not. That's why it's not unusual for graphics programmers to use the terms "frame buffer" and "color buffer" interchangeably when using OpenGL.

I'm quite sure that the frame buffer object extension in OpenGL is named from that legacy.

Yalpe

Thanks for all the replies. This was very helpfull. I've got some books on game programming so I will read some more on the buffers.

In the article linked by aldacron, the author suggest that you should implement a prediction function in your display function.

   const int FRAMES_PER_SECOND = 25;
    const int SKIP_TICKS = 1000 / FRAMES_PER_SECOND;

    DWORD next_game_tick = GetTickCount();
    int loops;
    double interpol;

    bool game_is_running = true;
    while( game_is_running ) {

        loops = 0;
        while( GetTickCount() > next_game_tick && loops < 4) {
            update_game();

            next_game_tick += GAMETICKS;
            loops++;
        }

        interpolation = (GetTickCount() + SKIP_TICKS - next_game_tick)
                        / SKIP_TICKS;
        display_game( [b]interpolation[/b] );
    }


Can anyone clear up what he means by this? I guess it has something to do with the camera updates but I'm not sure.

Also, what value would GAMETICKS hold.

deWiTTERS

Quote from: "Yalpe"
Can anyone clear up what he means by this? I guess it has something to do with the camera updates but I'm not sure.

When I have some time I will extend the article about that (it is indeed not properly covered), but for now I'll do a quick explanation. Like I said the game code runs on it's own frames per second, so when you draw/render your frames, it is possible that it's in between 2 gameticks. Let's say you have just updated your gamestate for the 10th time, and now you are going to render the scene. This render will be inbetween the 10th and 11th game update. So it is possible that the render is at about 10.3. The 'interpolation' value then holds 0.3. Take this example: I have a car that moves every game tick like this:
posision = position + speed

If in the 10th gametick the position is 500, and the speed is 100, then in the 11th gametick the position will be 600. So where will you place your car when you render it? You can just take the position of the last gametick (in this case 500). But a better way is to predict where the car would be at exact 10.3, and this happens like this:
view_position = position + (speed * interpolation)

The car will then be rendered at position 530.

So basically the interpollation variable contains the value that is inbetween the previous gametick and the next one (previous = 0.0, next = 1.0). What you have to do then is make a "prediction" function where the car/camera/... would be placed at the render time. You can base this prediction function on for example the speed of the object.

I hope this makes it more clear.

Quote from: "Yalpe"
Also, what value would GAMETICKS hold.

This is an error and should be SKIP_TICKS. I'll update that page as soon as I can  :)

Yalpe

Thanks deWITTERS. I didn't expect a reply from the author himself :) Anyways, I've picked it up. Time to implement!

Btw, great article!