Overlapping overlays, using transparency...help!?

Started by mbowen89, November 20, 2012, 04:51:44 PM

Previous topic - Next topic

mbowen89

Ok, so I have tried to read up on everything I could do with this, and tried a lot of stuff but can't seem to nail this... please help.

Basically I want to create some gauges as a HUD, so for example an RPM gauge.

I made it in GIMP as a 128x128 square for example, with transparent background. I made the round gauge centered, and I also made a needle centered on transparent background, check these two images out:

Gauge:
Needle:

So if I make two overlays, both at 0,0... they overlap perfectly, I can rotate the needle overlap to correlate with RPM, awesome. BUT, I get a black background of a square instead of transparency... ok so I do rpm_gauge.setTransparency(100); for example, and the black goes away and is transparent. I do the same for needle. BUT when I set the transparency on the main gauge, the needle also disappears with it. Here is the code that does that:


                                TextureManager.getInstance().addTexture("rpm_gauge", new Texture(getResources().openRawResource(R.raw.rpm_gauge_128), true));
rpm_gauge = new Overlay(world, 0, 0, 128, 128, "rpm_gauge");
rpm_gauge.setDepth(1.1f);
rpm_gauge.setTransparency(255);
TextureManager.getInstance().addTexture("rpm_gauge_needle", new Texture(getResources().openRawResource(R.raw.rpm_gauge_needle_128), true));
rpm_gauge_needle = new Overlay(world, 0, 0, 128, 128, "rpm_gauge_needle");
rpm_gauge_needle.setDepth(1f);
rpm_gauge_needle.setTransparency(255);


If I comment out: rpm_gauge.setTransparency(255);, the needle reappears but the gauge has black for transparent areas. I've tried using different transparency values for both, changed depth, etc... am I doing something wrong?

Thanks

---------
Edit:

Ok, so I reversed the order in which I create the overlays (needle first), and of course it works now... somewhat. The needle likes to flicker quite a bit, and disappeared one time as well until I made it rotate by increasing RPM again. I'm actually doing this with a boost and speed gauge as well. Hopefully I can get a better working solution? Thanks :)

EgonOlsen

You can set the depth of an overlay. Try to set the gauge's depth to something like 1.5.

mbowen89

This code makes the gauge transparent (good) but makes the needle disappear:

                                TextureManager.getInstance().addTexture("rpm_gauge", new Texture(getResources().openRawResource(R.raw.rpm_gauge_128), true));
rpm_gauge = new Overlay(world, 0, 0, 128, 128, "rpm_gauge");
rpm_gauge.setDepth(1.5f);
rpm_gauge.setTransparency(255);
TextureManager.getInstance().addTexture("rpm_gauge_needle", new Texture(getResources().openRawResource(R.raw.rpm_gauge_needle_128), true));
rpm_gauge_needle = new Overlay(world, 0, 0, 128, 128, "rpm_gauge_needle");
rpm_gauge_needle.setDepth(1f);
rpm_gauge_needle.setTransparency(255);


This code makes the needle appear, but it flickers as vehicle and camera move down track:


TextureManager.getInstance().addTexture("rpm_gauge_needle", new Texture(getResources().openRawResource(R.raw.rpm_gauge_needle_128), true));
rpm_gauge_needle = new Overlay(world, 0, 0, 128, 128, "rpm_gauge_needle");
rpm_gauge_needle.setDepth(1f);
rpm_gauge_needle.setTransparency(255);
TextureManager.getInstance().addTexture("rpm_gauge", new Texture(getResources().openRawResource(R.raw.rpm_gauge_128), true));
rpm_gauge = new Overlay(world, 0, 0, 128, 128, "rpm_gauge");
rpm_gauge.setDepth(1.5f);
rpm_gauge.setTransparency(255);

EgonOlsen

Try some other depth....maybe 2, 5 or 10 instead of 1.5

mbowen89

#4
I added some other overlays with transparency, and they work great since I'm not trying to overlap them, however they still like to flicker. I changed their depth to 2 and that seemed to help them, though the needle still flickered.

Is this actually moving them 2 units from camera? I don't know the right terminology. What if the camera get within 2 units of something?

Edit: Made gauge depth 3, needle depth 2 and no more flicker. Sweet!

Still confused why overlay creation order trumps depth... :(

When I put the camera into the driver seat position, the overlays go partially behind part of the object frame... that's why I hate that I have to move them out so far :(

Any idea?

EgonOlsen

One source of the flickering might be the sorting of transparent objects. If they both have the same depth, rendering order is undefined. But that should have been solved by moving the gauge to 1.5. If it doesn't, the problem might be depth buffer accuracy. It's pretty low on mobile devices and it might cause this kind of problems if objects (in this Overlays) are very close to one another.

You are right about the moving...this translates the Overlay into the scene. This might be a problem if some part of the scene comes this close and overlaps with the Overlay. But depending on the scene, this might never happen.

mbowen89

#6
Ok, and that's why I wouldn't mind using blitting, because I wouldn't have to worry about all of this, correct? But the reason why using overlays is nice, is because I can make the gauge, and then place needle on top of gauge as another overlay, and rotate it. Whereas I cannot rotate a blit, unfortunately...

So do you think I am going about this the right way? Right now it is going to be a big problem where the scene is coming in front of the overlay in "cockpit" view. I'd use blitting but I can't rotate. Any ideas?

For example, how did you draw your mini map that rotates showing direction, etc for you RPG? Are you blitting that so it won't crash with the scene? But if you blit, how do you rotate?

EgonOlsen

Quote from: mbowen89 on November 20, 2012, 08:15:59 PM
For example, how did you draw your mini map that rotates showing direction, etc for you RPG? Are you blitting that so it won't crash with the scene? But if you blit, how do you rotate?
No, it's not a blit. It's actually a kind of hand coded Overlay (because i tend to ignore the Overlay class for unknown reasons). The map consists of three different objects that are stored in their own world. It's very similar to an Overlay and suffers from the same depth problems (in theory)...but whatever i tried, i wasn't able to run into that issue, so i ignore it for now.

Speaking of this, there might be another option. Try to remove the setDepth-calls and replace them with calls to overlay.getObject3D().setSortOffset(<something that reflects your draw order>); and see if that helps.


mbowen89

#8
Is it just me or can I not see a .getObject3D call for overlays? I know it's in the doc, but not showing up for me.

rpm_gauge.getObject3D....

I put the RPM gauges and needle in another world but it's still finicky... hmm

---
Edit:

This seems to be working now, hopefully it will last! :)


TextureManager.getInstance().addTexture("rpm_gauge", new Texture(res.openRawResource(R.raw.rpm_gauge_128), true));
rpm_gauge = new Overlay(overlay_world, 0, 0, 128, 128, "rpm_gauge");
rpm_gauge.setDepth(10);
rpm_gauge.setTransparency(255);
TextureManager.getInstance().addTexture("rpm_gauge_needle", new Texture(res.openRawResource(R.raw.rpm_gauge_needle_128), true));
rpm_gauge_needle = new Overlay(overlay_world, 0, 0, 128, 128, "rpm_gauge_needle");
rpm_gauge_needle.setDepth(5);
rpm_gauge_needle.setTransparency(255);

EgonOlsen

Quote from: mbowen89 on November 21, 2012, 10:57:57 PM
Is it just me or can I not see a .getObject3D call for overlays? I know it's in the doc, but not showing up for me.
Check your jPCT-AE version. It has to be there if it's the current version. It might be that you are using a version that comes with one of the example projects and i'm not 100% sure that these were current in all releases.

mbowen89

Well what do you know, I was... I will try out the zsorting now.

Another question, it seems like the colors I choose in Blender almost never come out looking that way in the game. My orange is basically red... I have a single light (sun) at 255,255,255 about 50 units above origin... any suggestions?

EgonOlsen

Quote from: mbowen89 on November 21, 2012, 11:48:19 PM
... any suggestions?
Non apart from choosing other colors then. The loader loads them as they are defined in the file. A mobile device's display usually isn't calibrated at all, so colors can turn out in any way you like. For example, my Nexus S has totally different colors on screen than are shown in screen shots takes from it and displayed on a normal monitor.

mbowen89

I thought I'd inform you of what I have gotten to work, seemingly perfectly...


//surfacechanged
overlay_world = new World();

TextureManager.getInstance().addTexture("rpm_gauge", new Texture(res.openRawResource(R.raw.rpm_gauge_128), true));
rpm_gauge = new Overlay(overlay_world, 0, 0, 128, 128, "rpm_gauge");
rpm_gauge.setDepth(10);
rpm_gauge.setTransparency(255);
TextureManager.getInstance().addTexture("rpm_gauge_needle", new Texture(res.openRawResource(R.raw.rpm_gauge_needle_128), true));
rpm_gauge_needle = new Overlay(overlay_world, 0, 0, 128, 128, "rpm_gauge_needle");
rpm_gauge_needle.setDepth(5);
rpm_gauge_needle.setTransparency(255);

//ondraw
fb.clear(back);
sb.render(world, fb);
world.renderScene(fb);
world.draw(fb);
fb.clearZBufferOnly();
overlay_world.renderScene(fb);
overlay_world.draw(fb);


The little snippet at bottom that goes into the ondraw is what made it work (specifically the fb.clearZBufferOnly(); before drawing the overlay_world)

This what you expected?