0

I'm working on 3D (2.5D) application in Libgdx. I've found Decals very useful for this purpose.

In my app there should be layers, that contain dynamical text, now I'm wondering what is the best way to draw text via Decals.

Currently my implementation is based on drawing BitmapFont to FBO, then I get FBO texture and bind it to Decal before DecalBatch.flush().

I think that this is maybe not the most efficient way of doing this, but can't figure out better way.

My app can contain large number of text "layers" placed into 3D world, so maybe drawing each BitmapFont to FBO, and binding FBO texture to Decal isn't the best approach.

Do you guys have some better idea? What is the most efficient way of doing this?

Tnx in advance!

Veljko
  • 1,893
  • 6
  • 28
  • 58

3 Answers3

2

You can draw directly into 3D space with SpriteBatch by assigning your projection matrix appropriately.

First, have a Matrix4 that determines the position and rotation of each of your strings of text. The reason you need this is that SpriteBatch and BitmapFont do not have arguments for Z offset.

Since you can put all your translation into the Matrix4, when you call the draw method, just draw to 0,0.

You can then use the Matrix4 of each mesh to multiply with the camera's combined matrix before submitting it to the SpriteBatch. So you will want a separate Matrix4 for doing your calculations.

textTransform.idt().scl(0.2f).rotate(0, 0, 1, 45).translate(-50, 2, 25f);
//Probably need to scale it down. Scale before moving or rotating.

spriteBatch.setProjectionMatrix(tmpMat4.set(camera.combined).mul(textTransform));
spriteBatch.begin();
font.draw(spriteBatch, "Testing 1 2 3", 0, 0);
spriteBatch.end();
Tenfour04
  • 83,111
  • 11
  • 94
  • 154
  • Note that this still results in a separate draw call for each mesh so if you have a lot of them, your Decals might actually be better for performance, provided you draw all of your text to a single FBO atlas and use multiple TextureRegions on that FBO texture to apply to all your decals. This will result in only two draw calls for all of your text, but obviously will be difficult to set up correctly. You could save some GPU time by turning off blending when drawing the text to the FBO. – Tenfour04 Jun 24 '14 at 14:34
  • Hey, can you provide code for creating TextureAtlas with FBO? This will be extreamlly useful. Can't manage to find any document on that. I'm familiar with drawing to FBO and getting Texture from it, not the TextureAtlas. – Veljko Jun 26 '14 at 08:37
  • It's by no means automatic. You would have to figure out how you want to break up the 2D space of the texture surface and carefully draw to within those regions, and create TextureRegions from the regions you set up using standard constructors. – Tenfour04 Jun 26 '14 at 11:21
  • Okey. That makes sence, I secretly wondered that there is some embedded handler for it. – Veljko Jun 26 '14 at 11:46
1

If anyone's still coming to this answer 7 years later, I found a method that's much more like what I needed. Turns out that Matrix4.rotateTowardDirection() was exactly the method I needed:

        /* best to make these static, but whatever */
        Vector3 textPosition = /* the location of the text */;
        Matrix4 projection = new Matrix4();
        Matrix4 textTransform = new Matrix4(); 

        textTransform.setToTranslation(textPosition);
        textTransform.rotateTowardDirection(new Vector3().set(cam.direction).nor(), Vector3.Y);

        projection.set(cam.combined);

        Matrix4 op = spriteBatch.getProjectionMatrix().cpy();
        Matrix4 ot = spriteBatch.getTransformMatrix().cpy();

        // push the matricies
        spriteBatch.setProjectionMatrix(projection );
        spriteBatch.setTransformMatrix(textTransform);

        spriteBatch.begin();
        myFont.draw(spriteBatch, "Testing 1 2 3", 0, 0, 0, Align.center, false);
        spriteBatch.end();

        // pop the matricies
        spriteBatch.setProjectionMatrix(op);
        spriteBatch.setTransformMatrix(ot);

zadjii
  • 529
  • 2
  • 4
0

To get the rotation behaviour of Decals you need to call translate first before rotate on the textTransform Matrix.

textTransform.idt().translate(-50, 2, 25f).rotate(0, 0, 1, 45);

I'm a little confused about this. Maybe its historically reasoned from a Matrix Stack.

fky
  • 222
  • 2
  • 11