Jump to content
  • Advertisement
Josheir

Fix Your Timestep

Recommended Posts

I am trying to get the time stepping working consistently in an asteroids project.  The application runs fairly smoothly but when really looked at there are some pretty slight variances in motion.  I have looked at http://www.koonsolo.com/news/dewitters-gameloop/  and https://gafferongames.com/post/fix_your_timestep/.  I tried to write something similar to the first link but did not really notice a difference.  

Here is the first article:

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

    DWORD next_game_tick = GetTickCount();
    // GetTickCount() returns the current number of milliseconds
    // that have elapsed since the system was started

    int sleep_time = 0;

    bool game_is_running = true;

    while( game_is_running ) {
        update_game();
        display_game();

        next_game_tick += SKIP_TICKS;
        sleep_time = next_game_tick - GetTickCount();
        if( sleep_time >= 0 ) {
            Sleep( sleep_time );
        }
        else {
            // we are running behind!
        }
    }

This article said there would be no problems on computer's that are fast enough, and this does not seem to be true.  Perhaps the slight variations are as good as it is going to get?

 

Here is the second article:

 

double t = 0.0;
    double dt = 0.01;

    double currentTime = hires_time_in_seconds();
    double accumulator = 0.0;

    State previous;
    State current;

    while ( !quit )
    {
        double newTime = time();
        double frameTime = newTime - currentTime;
        if ( frameTime > 0.25 )
            frameTime = 0.25;
        currentTime = newTime;

        accumulator += frameTime;

        while ( accumulator >= dt )
        {
            previousState = currentState;
            integrate( currentState, t, dt );
            t += dt;
            accumulator -= dt;
        }

        const double alpha = accumulator / dt;

        State state = currentState * alpha + 
            previousState * ( 1.0 - alpha );

        render( state );
    }

 

As I understand it this program takes whats left over in the accumulator and blends it with an interpolation.  I have read that this is a pretty famous article.  I am wondering about the variables previousState and currentState.  I assume the passed in variable to integrate is a reference to hold the value for next time?  And in the final line before the render, the 2 states that are being multiplied by the 2 alphas are what, maybe my x and y?

 

The variable Previous is previousState and current is currentState?

 

Will this be even any better though as my understanding is I would need a previous and current x and y for every object and there is a function call for each draw.  

I would also have to run the while over and over again and and than the two lines below it over and over again.  These two procedures in themselves would seem to slow the game down more than what it is now.

 

I could really use some help, please.

 

Thank you,

Josheir

Edited by Josheir

Share this post


Link to post
Share on other sites
Advertisement

This comes down to preference depending on your requirements. I personally run my logic and input at a fixed tick rate, then render as many times as possible until the next tick is due. If the ticks take too long, I just force a draw and let the program slow down. This would rarely happen as those rates are normally under 30 per second. Interpolation becomes a requirement with this method because your render rate is not fixed.

I handle interpolation like this (You need a Prev Position, Current Position, and Draw Position - in this case spritePrevPos, spritePos, and testSprite):

In your logic update you need to have your spritePrevPos = spritePos before any updates happen to track. Then when you move your object you're updating your spritePos. In the draw phase you would interpolate the visual spot the sprite should be at to smooth out motions base on the time passed.

(This happens outside of of your logic and update loop)

interpolation = float(((mainClock.getElapsedTime().asMilliseconds() + skipTicks) - nextTick)) / (skipTicks);

testSprite.setPosition(spritePrevPos.x + ((spritePos .x - spritePrevPos.x) * interpolation), spritePrevPos.y + ((spritePos .y - spritePrevPos.y) * interpolation));

gameWindow.draw(testSprite);

Then draw testSprite to the screen. All your main collision calculations are with spritePos, while testSprite is just for interpolation of your sprite graphic.

I hope this helps! I'm also using deWitters by preference with the added interpolation.

*Edit: I corrected the formula! Sorry I was copying and pasting mine from my test source code, but mixed up the example variables in the post! Fixed!

Edited by Rutin
Fixed formula! Had wrong reference!

Share this post


Link to post
Share on other sites

Okay I'm having problems.

This is what I have :

 

interpolation = float(((float)(GetTickCount() - firstTime) + SKIP_TICKS  - (nextTime)) / (SKIP_TICKS));
 

 

shipObject.GetShipImage().setPosition(sf::Vector2f ((shipObject.prevx  + ((shipObject.GetX() - shipObject.prevx)* interpolation)),
(shipObject.prevy + ((shipObject.GetY() - shipObject.prevy) * interpolation))));

 

I am having trouble understanding what nextTime is.  I tried different solutions and I can't understand the relationship of the first interpolation statement with the second statement that uses the interpolation variable.

 

I can't really understand how an interpolation variable can work if it is seemingly always just increases or decreases with an extremely small value or just gets bigger and bigger.  That's why I think nextTime is not being correctly used by me.  To work it seems necessary that the interpolation formula should be able to give values that aren't just always increasing or always decreasing.

 

So I don't understand how to get this working, is NextTime always increasing by SKIP_TICKS each loop, and does it start with the same value as     (GetTickCount() - firstTime)     plus the first iteration of SKIP_TICKS?  And what is the range of the interpolation variable?

 

I can't really seem to get it working hopefully it's "nextTime" :)  If it's not could you help me too please?

 

Thank you all,

Josheir

 

Secondly, where is the sleep_Time condition located as compares to the rest of the code use by Rutin's preference?

 

Share this post


Link to post
Share on other sites

Hello @Josheir you have to take into context what those variables mean within the loop.

I'll break it down so you understand what values are being placed and how they're associated.

For the above:

interpolation = float(((mainClock.getElapsedTime().asMilliseconds() + skipTicks) - nextTick)) / (skipTicks);

testSprite.setPosition(spritePrevPos.x + ((spritePos .x - spritePrevPos.x) * interpolation), spritePrevPos.y + ((spritePos .y - spritePrevPos.y) * interpolation));

gameWindow.draw(testSprite);

My code is as follows before the loop even starts:

const float ticksPerSecond = 30.f;
const float skipTicks = 1000.f / ticksPerSecond;

sf::Clock mainClock;
double nextTick = mainClock.restart().asMilliseconds();

float interpolation = 0.f;

The actual loop simplified (I'm not posting everything here just enough for the example) - I do not include the loops for max frame skips for catching up in this example.

// Logic and Input
while (mainClock.getElapsedTime().asMilliseconds() > nextTick)
{
  spritePrevPos = spritePos;
  
  if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
  {
      spritePos.y -= spriteSpeed;
  }
  
  nextTick += skipTicks;
}

// Draw
interpolation = float(((mainClock.getElapsedTime().asMilliseconds() + skipTicks) - nextTick)) / (skipTicks);

testSprite.setPosition(spritePrevPos.x + ((spritePos .x - spritePrevPos.x) * interpolation), spritePrevPos.y + ((spritePos .y - spritePrevPos.y) * interpolation));

gameWindow.draw(testSprite);

 

The nextTick and skipTicks is so the loop will run one time per 0.0333 seconds, then wait until nextTick equals enough time for the next tick to be due after applying the skipTicks (time between each update call), ect... before calling the loop again, while drawing the rest of the time. (I didn't include the max update part which handles moments if you get trapped in the logic updates for too long, it will force your draw).

This will make sure the graphics are moving at a smooth rate by taking into account your Time Step variables. You can see the difference just by making a toggle (just make an event for F1 or something to toggle the boolean):

if (toggleInterpolation == true) {
  testSprite.setPosition(spritePrevPos.x + ((spritePos .x - spritePrevPos.x) * interpolation), spritePrevPos.y + ((spritePos .y - spritePrevPos.y) * interpolation));
}
else {
  testSprite.setPosition(spritePos.x, spritePos.y);
}

 

Quote

Secondly, where is the sleep_Time condition located as compares to the rest of the code use by Rutin's preference?

I don't want to say 'never' but I truly believe you should never ever use sleep commands in game loops. You can only guarantee the sleep will be called, but there is no guarantee it will come back within (x) time. Also, using any form of sleep command to wait until your loop is ready for an update goes against letting your logic run at (x) updates per second, and freeing your draw step by keeping it variable. The Time Step should be Fixed Logic/Input, Variable Draw. If you run your logic/input/draw in the same update "locked at 60 FPS" then you don't need to really worry about interpolation.

Edited by Rutin

Share this post


Link to post
Share on other sites

My honest advice to you, at this stage, is just to use a variable timestep. The awkwardness of getting a fixed update timestep to work with interpolation and all of the associated issues is probably not worth the effort.

I think Rutin has correctly covered most of the specific issues already. I concur that you shouldn't be using Sleep().

It's also very important to keep in mind that the interpolation is merely a visual improvement. You mustn't change the state of your actual game objects based on that interpolation - you just need to render them in a slightly different place.

I'd also advise you use a function like:

sf::Vector2 Lerp(const sf::Vector2& In, const sf::Vector2& Out, float alpha)
{
    return In + ((Out - In) * alpha); 
}

And this lets you simplify those complex expressions where you're having to break apart vectors, lerp the components, and then form new vectors from them.

Share this post


Link to post
Share on other sites

Well I decided to start with Rutin's advice to start with for now.  I created a fixed step with interpolation.  I benefited from the structure of the non sleep usage because there is no longer a slight variation in speed with the ship.  However after all the work when I tried the game with the ship uninterpolated I saw no difference in the now acquired smoothness.  The ship is just as smooth now using interpolation as not interpolated!  I don't know how to feel about this because I spent a while and achieved the desired effect, but it is not because of the interpolation.  I'm wondering if I should leave the interpolation in the program.

 

As far as Kylotan's advice I suppose I could now start reading up on Lerp and using Alpha with a variable timestep, but I doubt it's necessary with the movement now looking okay?  

 

The Lerp is another way to interpolate and each vector is an x and y  position?  Why are they called in and out?

 

The problem was the sleep really, so perhaps I've done what I need to do with your help.  Or maybe I need to use the Lerp to complete the project more polished in your opinion?

 

What I did was put the input and the changed the values of the x and y in the input/logic half and in the second half I checked for collisions, applied the interpolation, and drew and displayed.  The first screen has about 14 images including the bullets and there all moving fine now.

 

I still haven't learned how this works too which I think is important enough to know.  How should I learn what these two formulas and the Lerp are actually doing?  They're not terribly difficult and I have taken some college mathematics so how should I go about this?  I suppose I start by googling interpolation.  Any help would be greatly appreciated!

 

 

I didn't expect the program to work right without the interpolation so I'm still pretty surprised,

Josheir

 

 

 

Share this post


Link to post
Share on other sites
46 minutes ago, Josheir said:

Well I decided to start with Rutin's advice to start with for now.  I created a fixed step with interpolation.  I benefited from the structure of the non sleep usage because there is no longer a slight variation in speed with the ship.  However after all the work when I tried the game with the ship uninterpolated I saw no difference in the now acquired smoothness.  The ship is just as smooth now using interpolation as not interpolated!  I don't know how to feel about this because I spent a while and achieved the desired effect, but it is not because of the interpolation.  I'm wondering if I should leave the interpolation in the program.

 

As far as Kylotan's advice I suppose I could now start reading up on Lerp and using Alpha with a variable timestep, but I doubt it's necessary with the movement now looking okay?  

 

The Lerp is another way to interpolate and each vector is an x and y  position?  Why are they called in and out?

 

The problem was the sleep really, so perhaps I've done what I need to do with your help.  Or maybe I need to use the Lerp to complete the project more polished in your opinion?

 

What I did was put the input and the changed the values of the x and y in the input/logic half and in the second half I checked for collisions, applied the interpolation, and drew and displayed.  The first screen has about 14 images including the bullets and there all moving fine now.

 

I still haven't learned how this works too which I think is important enough to know.  How should I learn what these two formulas and the Lerp are actually doing?  They're not terribly difficult and I have taken some college mathematics so how should I go about this?  I suppose I start by googling interpolation.  Any help would be greatly appreciated!

 

 

I didn't expect the program to work right without the interpolation so I'm still pretty surprised,

Josheir

 

 

 

Do you mind sharing the code? It's extremely unlikely to have a limitless frame rate running at the max possible fps with smooth moving graphics, and interpolation showing no difference.

It might only be smooth if you've matched your draw step to the logic and input loop at the same refresh rate as your monitor while keeping it fixed.

Please post your entire game loop so I can break down what is happening. Or, if you can provide a project file for me to run to see. I've never seen draw rates that run as fast as possible on today's machines with smooth graphics unless you're using interpolation, or extrapolation. You normally need to run with vsync, or render graphics at the same refresh rate to get that smooth look otherwise.

Edited by Rutin

Share this post


Link to post
Share on other sites

From what I understand VSYNC is about double buffering and it is on by default with SFML.  Here is the address for the project:     https://github.com/Joshei/asteroids

The asteroids and bullets were smooth.  The Ship graphic had some very slight variation with it's motion.  This is just a simple game, but changing things around I think I now have an acceptable experience.

I tried changing the ticks per second to 50.f and it was also working well.

Look forward to hearing from you,

Josheir

Edited by Josheir

Share this post


Link to post
Share on other sites
52 minutes ago, Josheir said:

From what I understand VSYNC is about double buffering and it is on automatically with SFML.  Here is the address for the project:     https://github.com/Joshei/asteroids

The asteroids and bullets were pretty smooth.  The Ship graphic had some very slight variation with it's motion.  This is just a simple game, but changing things around I think I now have an acceptable experience.

I tried changing the ticks per second to 50.f and it was also working well.

Look forward to hearing from you,

Josheir

I use SFML a lot, and it's not on by default unless you call it. I've looked through your code and do not see it turned on unless I missed it. To turn VSYNC on you would use: window.setVerticalSyncEnabled(true); Keep in mind that your Video Card settings will override this if you have it to run all applications with VSYNC, or not.

What I've noticed so far is this:

When using pollEvent, do not use it within your logic/input update. You should be checking for events outside of that loop, and only using (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) inside the input loop. The event manager is not meant to be handled this way.

Do this:

while (mainWindow.isOpen()) {

		// Event Processing
		sf::Event event;

		while (mainWindow.pollEvent(event)) {
			// Closing Window
			if (event.type == sf::Event::Closed) {
				mainWindow.close();
			}
		}

		while (mainClock.getElapsedTime().asMilliseconds() > nextTick) {

			testSpritePosPrev = testSpritePos;

			if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) {
				testSpritePos.y -= testSpriteSpeed;
			}

			nextTick += skipTicks;
		}

		// Clear Window
		mainWindow.clear();

		// Draw to Window
		mainWindow.draw();

		// Display
		mainWindow.display();
}

After your input/logic loop you're calling checkCollisionsShipWithAsteroids(); on line 1213, and again more checks after. This should never be outside of the loop handling input and logic checks. You're also checking a lot of other logic outside of this, put it all under your input/logic loop.

Based on what I've seen if it's running smooth (I cannot fully test) it's because interpolation is already running on the draw side. I want you to try this as a test to see if you notice a difference. You'll have to use a test graphic to run it (get something 50x50 and name it a.png). You can alter the testSpriteSpeed variable to see more examples.

#include <SFML/Graphics.hpp>

void main(int argc, char** agrv[]) {

	// Create Main Window
	sf::RenderWindow mainWindow(sf::VideoMode(1024, 768), "Test Game", sf::Style::Close);

	// Timer for 30 INPUT LOGIC UPDATES PER SECOND
	const float ticksPerSecond = 30.f;
	const float skipTicks = 1000.f / ticksPerSecond;

	sf::Clock mainClock;
	double nextTick = mainClock.restart().asMilliseconds();

	float interpolation = 0.f;

	bool toggleInterpolation = false;

	// Sprite
	sf::Sprite testSprite;
	sf::Texture testTexture;
	testTexture.loadFromFile("a.png");
	testSprite.setTexture(testTexture);
	sf::Vector2f testSpritePos;
	sf::Vector2f testSpritePosPrev;
	int testSpriteSpeed = 5;

	// SET POS
	testSpritePos.x = 0;
	testSpritePos.y = 0;

	while (mainWindow.isOpen()) {

		// Event Processing
		sf::Event event;

		while (mainWindow.pollEvent(event)) {
			// Closing Window
			if (event.type == sf::Event::Closed) {
				mainWindow.close();
			}

			if (event.type == sf::Event::KeyPressed) {
				if (event.key.code == sf::Keyboard::Space) {
					toggleInterpolation = !toggleInterpolation;
				}
			}
		}
      
		while (mainClock.getElapsedTime().asMilliseconds() > nextTick) {

			// Updates - LOGIC
			testSpritePosPrev = testSpritePos;

			if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) {
				testSpritePos.y -= testSpriteSpeed;
			}

			if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) {
				testSpritePos.y += testSpriteSpeed;
			}

			if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) {
				testSpritePos.x -= testSpriteSpeed;
			}

			if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) {
				testSpritePos.x += testSpriteSpeed;
			}

			nextTick += skipTicks;
		}

		interpolation = float(((mainClock.getElapsedTime().asMilliseconds() + skipTicks) - nextTick)) / (skipTicks);

		if (toggleInterpolation == true) {
			testSprite.setPosition(testSpritePosPrev.x + ((testSpritePos.x - testSpritePosPrev.x) * interpolation), testSpritePosPrev.y + ((testSpritePos.y - testSpritePosPrev.y) * interpolation));
		}
		else {
			testSprite.setPosition(testSpritePos.x, testSpritePos.y);
		}

		// Clear Window
		mainWindow.clear();

		// Draw to Window
		mainWindow.draw(testSprite);

		// Display
		mainWindow.display();
	}
}

You can toggle interpolation with the 'SPACE BAR'. You should see a clear difference. Let me know.

Edited by Rutin

Share this post


Link to post
Share on other sites
Just now, Rutin said:

Based on what I've seen if it's running smooth (I cannot fully test) it's because interpolation is already running on the draw side. I want you to try this as a test to see if you notice a difference. You'll have to use a test graphic to run it (get something 50x50 and name it a.png). You can alter the testSpriteSpeed variable to see more examples.

Well it's interesting I think.  Both programs (mine and your sample) work smoothly.  I'm interested in why (more feedback from you.)  By running on the draw side you mean that their code for SFML drawing already uses interpolation?  Thanks also for those  great tips and the excellent code sample.

Have a super Labor Day weekend,

Josheir

 

Edited by Josheir

Share this post


Link to post
Share on other sites

  • Advertisement
  • Advertisement
  • Popular Tags

  • Popular Now

  • Advertisement
  • Similar Content

    • By BearishSun
      bs::framework is a newly released, free and open-source C++ game development framework. It aims to provide a modern C++14 API & codebase, focus on high-end technologies comparable to commercial engine offerings and a highly optimized core capable of running demanding projects. Additionally it aims to offer a clean, simple architecture with lightweight implementations that allow the framework to be easily enhanced with new features and therefore be ready for future growth.
      Some of the currently available features include a physically based renderer based on Vulkan, DirectX and OpenGL, unified shading language, systems for animation, audio, GUI, physics, scripting, heavily multi-threaded core, full API documentation + user manuals, support for Windows, Linux and macOS and more.
      The next few updates are focusing on adding support for scripting languages like C#, Python and Lua, further enhancing the rendering fidelity and adding sub-systems for particle and terrain rendering.
      A complete editor based on the framework is also in development, currently available in pre-alpha stage.
      You can find out more information on www.bsframework.io.

      View full story
    • By BearishSun
      bs::framework is a newly released, free and open-source C++ game development framework. It aims to provide a modern C++14 API & codebase, focus on high-end technologies comparable to commercial engine offerings and a highly optimized core capable of running demanding projects. Additionally it aims to offer a clean, simple architecture with lightweight implementations that allow the framework to be easily enhanced with new features and therefore be ready for future growth.
      Some of the currently available features include a physically based renderer based on Vulkan, DirectX and OpenGL, unified shading language, systems for animation, audio, GUI, physics, scripting, heavily multi-threaded core, full API documentation + user manuals, support for Windows, Linux and macOS and more.
      The next few updates are focusing on adding support for scripting languages like C#, Python and Lua, further enhancing the rendering fidelity and adding sub-systems for particle and terrain rendering.
      A complete editor based on the framework is also in development, currently available in pre-alpha stage.
      You can find out more information on www.bsframework.io.
    • By Gnollrunner
      Hi again,  After some looking around I have decided to base my game directly on Direct X rather than using an existing game engine.  Because of the nature of the stuff I'm doing it just didn't seem to fit very well and I kept running into road blocks.  At this point I have a big blob of code for doing fractal world generation and some collision code,  and I'm trying to put it into some form that resembles a game engine.  Since I've never used one before It's a bit alien to me ..... so can someone direct me to a book, website, article, whatever... that covers this?  I'm mainly looking for stuff that covers C++ library design. I'm not adverse to using 3rd party tools for stuff I can used them for.
    • By chiffre
      Introduction:
      In general my questions pertain to the differences between floating- and fixed-point data. Additionally I would like to understand when it can be advantageous to prefer fixed-point representation over floating-point representation in the context of vertex data and how the hardware deals with the different data-types. I believe I should be able to reduce the amount of data (bytes) necessary per vertex by choosing the most opportune representations for my vertex attributes. Thanks ahead of time if you, the reader, are considering the effort of reading this and helping me.
      I found an old topic that shows this is possible in principal, but I am not sure I understand what the pitfalls are when using fixed-point representation and whether there are any hardware-based performance advantages/disadvantages.
      (TLDR at bottom)
      The Actual Post:
      To my understanding HLSL/D3D11 offers not just the traditional floating point model in half-,single-, and double-precision, but also the fixed-point model in form of signed/unsigned normalized integers in 8-,10-,16-,24-, and 32-bit variants. Both models offer a finite sequence of "grid-points". The obvious difference between the two models is that the fixed-point model offers a constant spacing between values in the normalized range of [0,1] or [-1,1], while the floating point model allows for smaller "deltas" as you get closer to 0, and larger "deltas" the further you are away from 0.
      To add some context, let me define a struct as an example:
      struct VertexData { float[3] position; //3x32-bits float[2] texCoord; //2x32-bits float[3] normals; //3x32-bits } //Total of 32 bytes Every vertex gets a position, a coordinate on my texture, and a normal to do some light calculations. In this case we have 8x32=256bits per vertex. Since the texture coordinates lie in the interval [0,1] and the normal vector components are in the interval [-1,1] it would seem useful to use normalized representation as suggested in the topic linked at the top of the post. The texture coordinates might as well be represented in a fixed-point model, because it seems most useful to be able to sample the texture in a uniform manner, as the pixels don't get any "denser" as we get closer to 0. In other words the "delta" does not need to become any smaller as the texture coordinates approach (0,0). A similar argument can be made for the normal-vector, as a normal vector should be normalized anyway, and we want as many points as possible on the sphere around (0,0,0) with a radius of 1, and we don't care about precision around the origin. Even if we have large textures such as 4k by 4k (or the maximum allowed by D3D11, 16k by 16k) we only need as many grid-points on one axis, as there are pixels on one axis. An unsigned normalized 14 bit integer would be ideal, but because it is both unsupported and impractical, we will stick to an unsigned normalized 16 bit integer. The same type should take care of the normal vector coordinates, and might even be a bit overkill.
      struct VertexData { float[3] position; //3x32-bits uint16_t[2] texCoord; //2x16bits uint16_t[3] normals; //3x16bits } //Total of 22 bytes Seems like a good start, and we might even be able to take it further, but before we pursue that path, here is my first question: can the GPU even work with the data in this format, or is all I have accomplished minimizing CPU-side RAM usage? Does the GPU have to convert the texture coordinates back to a floating-point model when I hand them over to the sampler in my pixel shader? I have looked up the data types for HLSL and I am not sure I even comprehend how to declare the vertex input type in HLSL. Would the following work?
      struct VertexInputType { float3 pos; //this one is obvious unorm half2 tex; //half corresponds to a 16-bit float, so I assume this is wrong, but this the only 16-bit type I found on the linked MSDN site snorm half3 normal; //same as above } I assume this is possible somehow, as I have found input element formats such as: DXGI_FORMAT_R16G16B16A16_SNORM and DXGI_FORMAT_R16G16B16A16_UNORM (also available with a different number of components, as well as different component lengths). I might have to avoid 3-component vectors because there is no 3-component 16-bit input element format, but that is the least of my worries. The next question would be: what happens with my normals if I try to do lighting calculations with them in such a normalized-fixed-point format? Is there no issue as long as I take care not to mix floating- and fixed-point data? Or would that work as well? In general this gives rise to the question: how does the GPU handle fixed-point arithmetic? Is it the same as integer-arithmetic, and/or is it faster/slower than floating-point arithmetic?
      Assuming that we still have a valid and useful VertexData format, how far could I take this while remaining on the sensible side of what could be called optimization? Theoretically I could use the an input element format such as DXGI_FORMAT_R10G10B10A2_UNORM to pack my normal coordinates into a 10-bit fixed-point format, and my verticies (in object space) might even be representable in a 16-bit unsigned normalized fixed-point format. That way I could end up with something like the following struct:
      struct VertexData { uint16_t[3] pos; //3x16bits uint16_t[2] texCoord; //2x16bits uint32_t packedNormals; //10+10+10+2bits } //Total of 14 bytes Could I use a vertex structure like this without too much performance-loss on the GPU-side? If the GPU has to execute some sort of unpacking algorithm in the background I might as well let it be. In the end I have a functioning deferred renderer, but I would like to reduce the memory footprint of the huge amount of vertecies involved in rendering my landscape. 
      TLDR: I have a lot of vertices that I need to render and I want to reduce the RAM-usage without introducing crazy compression/decompression algorithms to the CPU or GPU. I am hoping to find a solution by involving fixed-point data-types, but I am not exactly sure how how that would work.
    • By babaliaris
      Well i found out Here what's the problem and how to solve it (Something about world coordinates and object coordinates) but i can't understand how ti works. Can you show me some examples in code on how you implement this???
       
      Scaling Matrix:
      m_Impl->scale = glm::mat4(1.0f); m_Impl->scale = glm::scale(m_Impl->scale, glm::vec3(width, height, 0)); Verticies:
      //Verticies. float verticies[] = { //Positions. //Texture Coordinates. 1.0f, 1.0f, 0.0f, 0.0f, 2.0f, 1.0f, 1.0f, 0.0f, 2.0f, 2.0f, 1.0f, 1.0f, 1.0f, 2.0f, 0.0f, 1.0f }; Rendering:
      //Projection Matrix. glm::mat4 proj = glm::ortho(0.0f, (float)window->GetWidth(), 0.0f, (float)window->GetHeight(), -1.0f, 1.0f); //Set the uniform. material->program->setUniformMat4f("u_MVP", proj * model); //model is the scale matrix from the previous code. //Draw. glDrawElements(GL_TRIANGLES, material->ibo->GetCount(), GL_UNSIGNED_INT, NULL);  
      Shader:
      #shader vertex #version 330 core layout(location = 0) in vec4 aPos; layout(location = 1) in vec2 aTexCoord; out vec2 texCoord; uniform mat4 u_MVP; void main() { gl_Position = u_MVP*aPos; texCoord = aTexCoord; } #shader fragment #version 330 core out vec4 colors; in vec2 texCoord; uniform sampler2D u_Texture; void main() { colors = texture(u_Texture, texCoord); }  
      Before Scaling (It's down there on the bottom left corner as a dot).

       
      After Scaling

       
      Problem: Why does the position also changes?? If you see my Verticies, the first position starts at 1.0f, 1.0f , so when i'm scaling it should stay at that position
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!