These tips and hints derive from practical coding. They are added by the time they appear in my programs.
Rendering opaque or fully transparent (read: invisible) texels or triangles is trivial. However, rendering partly transparent texels can be quite tricky. Sorting all triangles and drawing them from back to front (known as the famous
painterīs algorithm
) will always provide a correct result, but requires the triangles to be sorted in depth order. This is not the usual way of drawing using common 3D APIs, especially if the vertex data is transformed
by the graphic hardware. Thus, other ways of correct rendering must be found.
First, it is a good idea to render only opaque data first, followed by alpha blended triangles in a second pass. This allows transparency without the need to store an alpha channel in the frame buffer or render target. Additionally, it also
prevents transparent triangles from hiding data visible behind them if z-buffering is used. But there are still problems with z-buffering if multiple alpha blended triangles occupy the same area on the screen. These can be solved
by disabling z-buffer writes while rendering alpha blended triangles. The depth comparison (z-test
) has to be left enabled, though.
Situations with overlapping partly-transparent triangles may require more work. But in most cases sorting the rendering order of the objects or using the destination alpha channel as well are still good enough to avoid the cost of z-ordering triangles.
If you are an asm-coder you may have already encountered the following situation (especially if you are creating huger 32-Bit projects): You wrote correct source code, but linking the object files failed with an error message like:
Bad object file at offset xxxx
Or you could create the executable, but it did not work correctly. Sometimes, when looking at the list file, one may discover incorrectly calculated offsets (wrong data offsets or even wrong jmp/call labels).
Up to now, I could solve the problem by setting the assembler to 4 or more passes. The default value of 2 passes was not enough to resolve all references.
You start your program after having modified the source code, it loads normally, but suddenly you are back to the GUI, without getting any error message, any blue screens or any other actions signalizing a program fault.
This is a common behaviour if a problem within a fullscreen DirectX application occurs. Changing it to windowed mode would allow the OS to present the error message (unless the problem is restricted to fullscreen mode).
This can also happen when the PUSHes onto the stack did not have matching POPs. As a result, Windows did not get back the correct stack and canceled the program.
It is a bit funny: Even if you are using DirectDraw in fullscreen without providing a windowed DirectDraw mode, you have to create a window (for getting the windows messages, etc.). Many sources I have seen only used WS_POPUP as a window style for this window. However, I prefer creating a window which includes the System Menu (WS_SYSMENU). If the user ALT-TABbed away from your code he gets the possibility to right-click on your minimized program for closing it instantly. This is useful if you want to exit the application without going through all your menus or if you need to close a locked-up program.
Another issue: Depending on your code, it may take some time between the time the window being shown up and the first writes to the screen. Displaying something in your window can make the program look more professional (I have seen enough windows being thrown onto the desktop, wondering myself if this is the way modern programs should look like).
The simplest way is to check if the value is zero and branch accordingly. But if you want to speed up things a bit (divisions are slow, but mispredicted jumps are slow, too) you should avoid it.
If you are coding in DOS and the division by zero will occur quite rarely, you may redirect INT 0h to your own routine handling this case. Attention: Be aware that the result can be either a byte, a word or a dword. And INT 0h may also happen due to a division overflow (the result was too big to fit into its register).
Another idea, if the result does not need to be an exact result, is to ADD or OR with 1. Because the value will be at least 1, a zero-division cannot happen. The accuracy can be improved by multiplying (shifting) before ADDing/ORing and to redivide (reshift) after the division. This pre- and its corresponding postcorrection can often be included in the calculations before and after the division, so they do not need any extra clock-cycles.
Generally: The best divisions are the ones removed from your code.
In order to run a single instance of a program multiple times you can create a simple .bat file with the following content:
:infloop start /wait name_of_program.exe goto infloop