Using GPU and Crop Image

#1

Hi everyone :slightly_smiling_face:

I’m creating a game thanks to cinder, the problem is that I do all my calculations thanks to the CPU (collisions, ect) my game goes below 60 fps for 20 enemies, so I would like to know if c is possible to calculate only on the GPU (which I think will improve the performance of my game).

I take this opportunity to ask you the question of how to crop a picture is for hp bar, I wish that when the character lost life the HP bar decreases.

Thanks a lot for your answers ! ( A noob )

#2

Hi,

You can use libraries like Box2D or Bullet for physics simulation. Technically, you should be able to write compute shaders ( check cinder samples ) to do physics calculations on the GPU. But that might be a longer route and not really necessary.

Could you provide some sample images for the health bar that you have in your mind?

#3

With that small amount of enemies, you shouldn’t be dropping that low unless you’re doing something very wrong. First of all, make sure you’re compiling in release mode. Performance in debug mode, especially on windows, can be horrible. Next, profile your code, see where you’re spending most of your CPU time and make sure there’s not a more performant CPU side way of solving that problem. Getting the GPU involved for simulations is rarely necessary (or even beneficial) until you’re getting into the 10s or 100s of 1000s of objects.

As a concrete example, in my early days of cinder i was drawing a ci::TriMesh every frame, without realising that this object was meant to be uploaded to the GPU once via gl::VBO and then redrawn, and my performance increased 1000+x. If you want to post your code I’m happy to have a quick squizz and see if there’s anything obvious.

#4

Cropping a picture means you’re creating a copy of only a region of an image. You end up with two separate images in memory. For fast changing graphics, this is not the way to go.

Instead, you should just use a single image, but only draw a portion of it. This can be achieved by supplying texture coordinates, usually in the range (0,0) (top left) to (1,1) (bottom right). A quick way to try this is as follows:

void YourApp::draw()
{
    // Clear the main buffer.
    gl::clear();

    // Draw the texture.
    Area srcArea{ 50, 50, 250, 60 }; // portion of the image in pixels
    Rectf dstRect{ 0, 0, 200, 10 };  // in window coordinates
    gl::draw( mTexture, srcArea, dstRect );

    // Alternative: use your own shader i.c.w. drawSolidRect().
    gl::ScopedTextureBind scpTex0( mTexture, 0 );
    gl::ScopedGlslProg scpGlsl( gl::getStockShader( gl::ShaderDef().texture() ) );
    gl::drawSolidRect( dstRect, vec2( 0.2f, 0.2f ), vec2( 0.9f, 0.3f ) );
}

The alternative uses normalized coordinates instead of the absolute coordinates of the first option.

-Paul

#5

Thank you very much for your feedback!

If you want here is the url of my project: https://drive.google.com/file/d/1F2RkY5PwYX-07V1-HxbMib2c-m_O0UqM/view?usp=drivesdk

I know it should be on a gitHub but it exceeds 100 MB upload and I did not take the time to adjust it.

My project is a “video game” for my school, I’m french so sometimes there is French (even a lot), it’s my first big project so if you take the time to read it (thank you very much!) I would take all the returns even really negative!

The project is in cinder \ MyProject

About the bar Hp, I do not understand what dstRect is, if it’s the postions in the window, I could just gl :: translate (vec2 (x, y)) and draw the subregion?

My HB bar :

Again, thank you very much !

#6

Hi,

dstRect is the area of the window where you want to draw your HP bar. It allows you to draw the bar at any scale you want.

If you want to draw the current health at coordinate (20,30), you could do:

// mHealth is a float between 0 and 1
const int w = int( mTexture->getWidth() * mHealth );
const int h = mTexture->getHeight();
const float scale = 2.0f;
gl::draw( mTexture, Area{ 0, 0, w, h }, Rectf{ 20, 30, 20 + w * scale, 30 + h * scale } );

Happy to help,

~Paul

#7

Okay that works perfectly thank you Paul!

For my part I tried to optimize my code the best I could and I can display 100 enemies at 30 fps so it’s okay!

Thank you so much !

#8

Nice, that sure is good enough for now. But if you want to optimize a bit further, look into instanced rendering. See this article and this sample. It also works for 2D.

-Paul