I’m looking for any advice or thoughts on the best ways to draw arbitrary strings of 3D text in 3D space so that it looks like it is being drawn on various meshes (for example, a hanging sign) used throughout the world. I am considering two different methods:
1: Create all the letters in Blender, export them one-by-one each as its own mesh, import them all into MGCB, then form each 3D string by combining these objects, scaling them, and orienting them in space to the right location. This seems like more work than it needs to be and it will be difficult to change fonts.
2: Use SpriteBatch DrawString to draw 2D text onto a RenderTarget, which itself is a transparent 1x1 pixel texture scaled to the correct size. Set that texture onto a thin, rectangular box / cuboid mesh and orient this mesh in front of the 3D object I want to draw the text on. This method is more flexible since I can change fonts and colors more easily. I’m not sure how this is going to look, especially at an angle, and especially with normal maps and potentially parallax mapping in place on the sign objects.
Thoughts? Are there other methods I’m missing? Has anyone done this before / is there a “best practice” for how to do this?
You can use SpriteBatch.DrawString to draw text in 3D.
Cons: This method can result in z-fighting on sharp camera angles,
you need to add some bias or offset the text from the sign object.
Another method is to create the 3d model with 2 UVs, draw the text on a texture,
and you can control more precisely how to blend the two texture in a single draw with a shader.
As a starting point you can copy DualTextureEffect.
There’s also a technique called projective texture mapping.
You draw the text on a texture and shine a spot light in front of the sign.
The text-texture is used to tint the object’s surface like a film on a projector.
The 3D calculations are similar to that of a depth buffer shader.
Awesome, thank you! I will see if I can get one of these methods working.
Most likely rendering to texture and just putting a quad in the world where you want it is sufficient for your purposes - but as you mentioned it may blend not too good with parallax mapping behind it. But it’s easy to do, so I would give it a try and see if it works well enough
the ideal approach would be to render as a decal - which requires some shader magic but will then be perfectly applied to the underlying objects surface. It requires some shader magic tho and is more like a screenspace effect. You may need screen space zbuffer and screenspace heightmap (for the parallax) to work perfectly. So it may not be viable if you’re not already using a deferred renderer of some sort
Dual texture is the easiest way.
If its going to be on a full mesh that has the u,v’s laid out on it from o 0 to 1 like a quad even if is not a smooth surface and especially in that case. The notion of drawing the text onto a render target then sending that into your shader as a second diffuse texture is easy. It’s just a couple lines in the pixel shader in fact you don’t even need a if statement you can just blend them, it’s the easiest way in my opinion. I blended video’s on spheres and other odd shaped meshes like that.
Basically you just put another texture into your shader like how your normal map and diffuse map are used in the same shader. Now you have three textures two diffuse maps and a normal map. When you render your text to the render target, just make sure the render target is cleared to black or it’s alpha is zero ect. Then in your shader when you sample the second diffuse texture if it’s r g or b values are more then zero use the second textures color instead of the regular 1st textures.
You can even blend them together if you wanted to as if it were on a glass window or add a timing value and make is sort of pulse and glow.