Free DX10 Shaders Book

I found it on recent gamedev.net news:
Merry Christmas! I'm happy to announce that Wolfgang Engel, Jack Hoxley, Ralf Kornmann, Niko Suni and Jason Zink have all worked hard and conspired to bring you Programming Vertex, Geometry, and Pixel Shaders. This book is intended for people that have some background in DirectX8 or DirectX9 programming and want to upgrade their knowledge to DirectX 10. It's also completely free and available on GDWiki!

This book can be considered a first draft, as the team of authors is working on a print revision that will focus on DirectX 11. In addition to using GDWiki to get the content of the book out to you, they also welcome comments and feedback and even Wiki edits so that they can prep the content for the printed and enhanced version. If you've ever wanted to see your name in that Acknowledgments section of a book, stop by and lend a hand!

Great job authors! You've all set a new precedent in terms of content publishing and we at GDNet are happy to have been able to support you throughout this process.

I haven't read this yet.  Being a primarily next-gen console developer, I haven't had chance to work with DX 10 yet, so I guess it's a good change for me to skim it through, at least.  However, I don't think DX 10 will ever become popular: I think DX 11 will be the next player.

No Magic Numbers Please

A Real-world Example Why Magic Numbers Are Witchcraft

We all know that magic numbers are bad, but it always surprises me whenever I found out even some programmers with several years of experience in this industry still use magic numbers. This is a code snippet that I had to debug some weeks ago.  This code was originally written by a programmer at my work.

program code:
if ( info.packageID == -1 || info.layerID == -1 )
{
    // do something
}

Okay, we all know -1 is a magic number here.  For me, it did not take long to find out packageID of -1 means invalid package. Although using the constant -1 as an invalid index is very common in programming, I personally prefer some meaningful description even for this unless it's a code for a small tool which is meant to be modified by only a handful of programmers.  But I can still live with it: we programmers all tend to get lazy time to time and it's pretty straight-forward anyways.

Then what about layerID of -1? I just assumed it would be also the invalid index, but this case invalid layer.  It is a very reasonable guess since another -1 on the same line means invalid package, right?  Wrong.  It turned out to be not the case after I wasted hours of my "expensive" work hours digging other areas to fix the bug I was trying to solve.  To my surprise, layerID of -1 means Still Loading. What? The same number on the same line means two different things?  Even in English, we get confused if one word means two different things.  Even Eminem implied "what you mean is two different things" is bad in his song, Say What You Say... Okay, maybe Eminem is not so much relevant here. Anyways, you don't wanna do that in a programming language, which tends to be more confusing!

No wonder why this is a very good, or bad, example why you don't want to use magic numbers, eh?

It's All About Coding Standards, Really

In fact, It's all about coding standards, which are pretty subjective to any programmer out there: there is no one coding standard all programmers agree with. The reason why coding standards exist is to make collaboration easier: if your code is not easily understandable by your coworkers, you are being inconsiderate, and you can't be more than a dungeon programmer.  In other words, you don't deserve to work at any place other than your own basement suite. Having that in mind, this is the rule I go by:

When Not to Use Magic Numbers:
  • when a same constant value is showing up multiple times in code. So, if packageID of -1 is used more than once in the codebase, it's better to give it a meaningful name.
  • or when the number is just too magical, thus confusing people if not explained.  layerID of -1 meaning Still Loading is out of normal usage of -1 in my opinion.
  • or when more than handful of programmers are editing the same codebase.  If it's only a small tool which is edited only by only you. Who cares?

How Not To Be Evil
These are some of good alternatives you can use to make that code look better.  All of these methods do NOT involves any run-time cost, so you should use them, if you are a programmer who cares about your coworkers.

My personal preference is the last method which uses unnamed enum in class.

1. Use #define:

You can use good old C-style #define to globally associate these magic numbers with meaningful names.

package.h:
#define INVALID_PACKAGE_ID -1

layer.h:
#define LAYER_STILL_LOADING -1

program code:
if ( info.packageID == INVALID_PACKAGE_ID
    || info.layerID == LAYER_STILL_LOADING )
{
    // do something
}

The only downside of this method is name collision and making everything globally available does not really get along with OOP.


2. Use const int in namespace
To limit the scopes of these unmagical numbers, some programmers embed const int into namespace.

package.h:

namespace pacakge
{
    const int INVALID_ID = -1;
    ...
}

layer.h:
namespace layer
{
    const int STILL_LOADING = -1;
    ...
}

program code:
if ( info.packageID == package::INVALID_ID
|| info.layerID == layer::STILL_LOADING )
{
    // do something
}

I don't particularly disagree with this method, but I have never preferred this method because it essentially stores these const ints separate from classes.

3. Use static const int in Class
Instead of wrapping const ints with namespace blocks, you can simple define the same const ints as static variable in a class.

package.h:
class pacakge
{
public:
    // something else
    static const int INVALID_ID;
}

package.cpp:
int package::INVALID_ID = -1;

layer.h:
class layer
{
    public:
        // something else
        static const int STILL_LOADING;
}

layer.cpp:
int layer::STILL_LOADING = -1;

program code:
if ( info.packageID == package::INVALID_ID
    || info.layerID == layer::STILL_LOADING )
{
    // do something
}


It's an okay way, but still having to define each variables in a separate .cpp file is not so desirable.

4. Use Unnamed enum in Class
This is my preferred way, which works pretty much same as the last method, but keeps everything in one place in a clean way.

package.h:
class pacakge
{
    public:
        // something else
        enum { INVALID_ID = -1 };
}

layer.h:
class layer
{
    public:
        // something else
        enum { STILL_LOADING = -1 };
}

program code:
if ( info.packageID == package::INVALID_ID
    || info.layerID == layer::STILL_LOADING )
{
    // do something
}



What do you think?  You feel like it is much cleaner, and hopefully less evil?

NEVER Use PIPE with Python popen

I do use Python at work time-to-time, mostly for build tools and pipelnie stuff. This is the problem I ran into a week ago, and thought I should let other people know too. (I assume a lot of game programmers use Python? Well, not in game code, though)

This is basically a short summary version of this article, which I got my answer from.
  • If you use redirect stdout of a children process through PIPE, it will hang when the size of output is bigger than 64KB. (And it does not give you any meaningful error message. You might see some deadlock deep into some file handling functinos in ntdll or so)
  • My advice is NEVER use PIPE with popen. Even if your current subprocess never outputs more than 64K, other programmers can change this shallow assumption sometime later. (This was my case)
  • Instead, always use a tempfile. (see the code example below)

Code examples:
  • Not-so-good code:

    p = Popen(cmd, stdout=PIPE)

    ...


    out_lines = p.stdout.readlines()

  • Better code:

    temp_file = tempfile.TemporaryFile()
    d = temp_file.fileno()
    p = Popen(cmd, stdout = d)

    ...

    out_lines = d.readlines()

p.s.1 You don't have to close temp_file. It'll be closed when garbage collector collects this. But still donig so would be a good practice.

p.s.2 This was done in Python 2.5.1. The reason why I'm saying this is because I just heard Python 3.0 is not backward-compatible.

New Download Page for Free ShaderX Books

This seems to be new home for free ShaderX books.  While I'm not sure if these many-years-old books are still useful, it's awesome that the series editor, Wolfgang Engel, and the publisher made them freely available.

http://tog.acm.org/resources/shaderx/