Small coding tips

These tips and hints derive from practical coding. They are added by the time they appear in my programs.

Overview:

PROBLEM: Incorrect display of alpha blended triangles

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.

PROBLEM: The assembler generates wrong binary output

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.

PROBLEM: My Win32 Program exits without ANY message

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.

HINT: Suitable windows for DirectX

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).

IDEAS: What to do if a division by zero can happen

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.

HINT: Running a program in an infinite loop under Windows

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
Mail the Author: webmeister@deinmeister.de

Homepage Programming Win32Asm Downloads Software Hardware Cartoons Sitemap