This intermediate level tutorial involves tricks that can be used for both TV6.5 as well as 6.2.
One of the most under used, yet powerful features of any 3D engine are the RenderSurfaces. For a simple definition, a “RenderSurface” is nothing more than a texture that you can render a scene to, just as if it were a regular screen. The obvious use for something like this would be to make “televisions” such as the monitors you’ll see in most video games (Doom 3, Halflife, etc.) Another obvious use is to make a simple “Viewport” by sticking the rendered scene from an alternate angle onto a billboard. But these are the obvious uses, and honestly, how many televisions and viewports can you have in a game?
One of the obvious disadvantages to RenderSurfaces is that they require multiple renders in-game. However, most of these effects won’t require that you render the shaders and other effects that make rendering expensive. So long as you keep your poly-count reasonable, video cards now days are plenty fast enough to handle multiple simple renders each frame.
There are TONS of other uses for rendersurfaces that are all too often overlooked. Let’s look at some of them now!
First: Emissive maps. These are simple “maps” that hold “glow” information for a model. Suppose it’s a car’s headlights and taillights? The lights on a spaceship? The cities on a planet? Anything that should “glow in the dark” can be created with an emissive map. How do rendersurfaces make this happen? Simple:
First, create a rendersurface about 512×512. (”glowing” objects don’t need particularly high resoultion, though if it was that important, you could create it at 1024×1024.) Now, during your game loop, you would do this:
* All of your meshes in your scene get a “black” material. This is one with EVERY value (emissive, ambient, diffuse, etc.) set to 0,0,0,1 (RGBA) so the mesh will render as solid black. (Alternately, if you use a single light for the entire scene, you could simply turn that one light off. The idea is to render everything in the scene solid black.) * You will then take your meshes that actually use the emissive map and put the emissive texture on them. The emissive texture should be solid black with only the appropriate “glow” sections in color. * ONLY the meshes that have an emissive map get assigned a material that is, not surprisingly, set with full emissive. The specular, diffuse, and ambient are still set at 0,0,0,1, however the emissive on this material is set to 1,1,1,1. * Now do a RenderSurface.StartRender, Render the ENTIRE scene, and then RenderSurface.EndRender * Set all your models BACK to their appropriate materials/textures.
At this point, your render surface should have a solid black screen with ONLY the portions that are supposed to “glow” showing up in the scene. The reason you render ALL the meshes is because if one mesh is in “front” of the glowing portion, it needs to appropriately block the view.
Now that you have your solid black rendersurface with ONLY the “glow” portions showing, you’re ready to continue with your normal scene render.
* Call your TVEngine.Clear * Render All your meshes * Start your Screen2DImmediate Render * Render your “Glow” rendersurface by using Screen2D.Draw_Texture stretching the texture from 0,0, to the width/height of the screen. * Render your other 2D stuff (HUDs, GUIs, etc.) * End your Screen2DImmediate Render * Call TV.RenderToScreen
The end result is something like this:
Note that the “lava” effect is actually “glowing” and would still show up even if the lights were “turned out.” To see this effect in action, check out http://www.javin-inc.com/TV65/Emissive.zip [link down] to see it in action. (The model was borrowed from Doom 3.)
Also take note of the FPS. Despite all the machinations that we’ve flipped through here, the FPS really didn’t take that much of a hit. Well worth the trade-off, particularly considering that using Pixel Shaders to get the exact same effect is quite expensive.
Now, do RenderSurface uses end at emissive mapping? Hell no. Using a series of 10 render surfaces, I’ve managed to come up with a quite believeable “motion blur” effect. All I do is render my scene to one of ten rendersurfaces, and every frame, I render all 10 render surfaces with varying degrees of opacity. After 50 milliseconds or so, I switch to a different render surface to render the scene too, and so on. An example of this can be seen here:
Again, if you want to see it in action, you can see it here: http://www.javin-inc.com/TV65/MotionBlur.zip [link down]
(On some systems, these effects will run “sluggishly” because I was lazy and tried to slow it down using a sloppy frame limiting method. These are by NO means optimized, and your results should be 10 times better if you tried it with some optimization.)
As you can see, the RenderSurface is very flexible, and useful for all SORTS of “cheap” effects. Other things that can just as easily be done with them:
+ Fading from one live-action scene to another (render the “new” scene to a rendersurface, and slowly blend it into the currently running scene. Once you hit 100% alpha, you simply start rendering the new scene.)
+ Fading from color to black and white: (Just like the previous method, only one scene is rendered with black and white textures, one with color.)
+ “Depth Of Field” - This is the effect where your focus is on one object, and everything else seems to “blur” out. Could easily be accomplished with two rendersurfaces. A “far” surface and a “near” surface. Render the “far” and “near” with a lower resolution (256 x 256 for example). The mesh that gets the focus is rendered normally, while the near and far objects are rendered on the appropriate surface. You then simply render your objects in this order: Far Surface Normally rendered objects Near Surface
+ Scene “wipe” effects, like you see in the movies. Again, using a series of render surfaces, all SORTS of scene transition effects are possible. Fades/pans/splits, you name it.
The use of rendersurfaces is endless. Here’s some ideas to get ya started, let’s see what else you can come up with!