LWJGL Forum

Programming => Lightweight Java Gaming Library => Topic started by: Daslee on January 24, 2013, 19:14:24

Title: Any way to improve fps with color picking?
Post by: Daslee on January 24, 2013, 19:14:24
Hello. I added color picking in my game, looks good, but one problem... FPS too low.

Now game renders all objects two times, first time only color and checking for color picking, then clears graphics and renders normal objects with textures. Is there any way to increase fps with color picking? Here is the code where it renders all world:

glDisable(GL_TEXTURE_2D);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //clear the screen
//draw everything to the screen
for(Object obj : world.visibleCollidingObjects) obj.renderColor();
glFlush();//might be important, in order, for the drawing to finish, alternatively glFinish(), to ensure that
ByteBuffer rgb = BufferUtils.createByteBuffer(3);
//and read the current color (where the cursor is), without lighting or texturing, just the original color
glReadPixels(x, y, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, rgb);

for(Object obj : world.visibleCollidingObjects) obj.selected = false;
for(Object obj : world.visibleCollidingObjects){
for(int i=0; i<obj.sides.length; i++){
if(obj.sides[i] == null) continue;
if(obj.sides[i].r == (rgb.get(0) & 0xFF) &&
obj.sides[i].g == (rgb.get(1) & 0xFF) &&
obj.sides[i].b == (rgb.get(2) & 0xFF)){
obj.selected = true;
selectedObjectIndex = world.objects.indexOf(obj);
selectedSide = i;
break;
}
}
}
glEnable(GL_TEXTURE_2D);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //clear the screen
for(Object obj : world.visibleCollidingObjects) obj.render();


Any ideas for increasing fps? Now it's around 40-58. If I'm looking to the place where are no objects, then fps is as before 70, but when looking to the rendering objects, then lagg and fps around 40-58..
Title: Re: Any way to improve fps with color picking?
Post by: Mickelukas on January 25, 2013, 13:46:38
The best way to do color picking is to... not do it ;) Look into ray picking instead as it is way quicker and, if done correctly, almost just as easy to maintain.

The code you posted looks correct to me, color picking is quite slow. The only few things could be to create the byte buffer once and reuse it instead of creating it at each frame, store the objects in a map with the color as key to improve the time it takes to find the correct color code (if you have a lot of objects) as well as store the currently selected object somewhere globally instead of on each object.

Mike
Title: Re: Any way to improve fps with color picking?
Post by: Fool Running on January 25, 2013, 13:50:48
A couple things would help.
1) The biggest thing is to not use color picking to determine what has been clicked. If this is an option (i.e. you don't *need* the color-picking functionality), then it's better to use ray picking instead of drawing everything twice.
2) If you need this functionality, then the next thing is to not create a new ByteBuffer each frame. It's better to create one earlier (like in the constructor or initialization) and just keep reusing it.
3) I don't know how many objects you have on-screen, but getting values out of a ByteBuffer using get() is also fairly slow so you should store the values before you loop through the objects to see if they have been picked.
4) Using "foreach" versions of "for" is not recommended for games since it creates extra objects that need to be garbage collected (the enumerator). It probably won't be causing much of a slowdown, but it will cause hiccups in the smoothness of the game.

Also, looking at your object rendering code might help. You might be rendering them using immediate-mode - which is slow.

EDIT: Mickelukas beat me.  :P
Title: Re: Any way to improve fps with color picking?
Post by: Daslee on January 25, 2013, 14:23:49
Quote from: Fool Running on January 25, 2013, 13:50:48
A couple things would help.
1) The biggest thing is to not use color picking to determine what has been clicked. If this is an option (i.e. you don't *need* the color-picking functionality), then it's better to use ray picking instead of drawing everything twice.
2) If you need this functionality, then the next thing is to not create a new ByteBuffer each frame. It's better to create one earlier (like in the constructor or initialization) and just keep reusing it.
3) I don't know how many objects you have on-screen, but getting values out of a ByteBuffer using get() is also fairly slow so you should store the values before you loop through the objects to see if they have been picked.
4) Using "foreach" versions of "for" is not recommended for games since it creates extra objects that need to be garbage collected (the enumerator). It probably won't be causing much of a slowdown, but it will cause hiccups in the smoothness of the game.

Also, looking at your object rendering code might help. You might be rendering them using immediate-mode - which is slow.

EDIT: Mickelukas beat me.  :P

1) I do not wanna to do ray picking, because it's too hard for me.
2) Done
3) Still reading and trying to understand how to do that..
4) So now I should do it like this:
for(int i=0; i<world.visibleCollidingObjects.size(); i++){
world.visibleCollidingObjects.get(i)...
}


or I can do like this:

for(int i=0; i<world.visibleCollidingObjects.size(); i++){
Object obj = world.visibleCollidingObjects.get(i);
...
}


???
Title: Re: Any way to improve fps with color picking?
Post by: Mickelukas on January 26, 2013, 20:50:09
Quote from: Fool Running on January 25, 2013, 13:50:48
EDIT: Mickelukas beat me.  :P

And we seem to think exactly alike :)

Quote from: Daslee on January 25, 2013, 14:23:49
3) Still reading and trying to understand how to do that..

Instead of doing:

for(Object obj : world.visibleCollidingObjects){
for(int i=0; i<obj.sides.length; i++){
if(obj.sides[i].r == (rgb.get(0) & 0xFF) &&
obj.sides[i].g == (rgb.get(1) & 0xFF) &&
obj.sides[i].b == (rgb.get(2) & 0xFF))
}
}
}

Do something like:

Byte r=rgb.get(0);
Byte g=rgb.get(1);
Byte b=rgb.get(2);
for(Object obj : world.visibleCollidingObjects){
for(int i=0; i<obj.sides.length; i++){
if(obj.sides[i].r == (r & 0xFF) &&
obj.sides[i].g == (g & 0xFF) &&
obj.sides[i].b == (b & 0xFF))
}
}
}


You're never going to get a great performance out of it though and learning ray picking is time well spent :)

Mike
Title: Re: Any way to improve fps with color picking?
Post by: Daslee on January 27, 2013, 09:52:35
Quote from: Mickelukas on January 26, 2013, 20:50:09
Quote from: Fool Running on January 25, 2013, 13:50:48
EDIT: Mickelukas beat me.  :P

And we seem to think exactly alike :)

Quote from: Daslee on January 25, 2013, 14:23:49
3) Still reading and trying to understand how to do that..

Instead of doing:

for(Object obj : world.visibleCollidingObjects){
for(int i=0; i<obj.sides.length; i++){
if(obj.sides[i].r == (rgb.get(0) & 0xFF) &&
obj.sides[i].g == (rgb.get(1) & 0xFF) &&
obj.sides[i].b == (rgb.get(2) & 0xFF))
}
}
}

Do something like:

Byte r=rgb.get(0);
Byte g=rgb.get(1);
Byte b=rgb.get(2);
for(Object obj : world.visibleCollidingObjects){
for(int i=0; i<obj.sides.length; i++){
if(obj.sides[i].r == (r & 0xFF) &&
obj.sides[i].g == (g & 0xFF) &&
obj.sides[i].b == (b & 0xFF))
}
}
}


You're never going to get a great performance out of it though and learning ray picking is time well spent :)

Mike

Heh fps got increased per 10-15 :D I know that I'll never get great performance with color picking, but ray picking is haard. Maybe later after completing some easier things I'll try to do ray picking.

Thanks for help. :)