Wednesday, September 15, 2010

HDR in DirectX

HDR in DirectX isn't as simple as they make it out to be. What is HDR? HDR or high dynamic range is images with more than 256 colors (8bits) per channel (red.green,blue). Formats with 16, or 32 bits per channel are common. DirectX will even support a floating point number per channel, for a very large range of values.

So the obvious thing when working with HDR is that you cant render directly to your screen. Your screen only has 8bits per channel. DirectX allows you to render to an off screen buffer called a render target. Using a render target you can render in any format your gpu supports.

After you tell the GPU to use a render target you should be able to what ever you want in HDR right? Unfortunately this is not the experience I had. I set up my render target and drew a image and what I got back out was only an 8bit image. It didn't matter what format the render target was in, or what I drew for an image, it was always rendering to 8bits.

Turns out you need to also use a pixel shader. You need nothing more than:

texld r1, t0, s0
mov oC0, r1

All this does it get the value of the pixel in the texture and return it. This should be exactly what is happening by default without a pixel shader, but it doesn't seem to be. Using these 2 lines of pixel shader suddenly I was getting more than 8bits out.

Not sure why it works this way, maybe someone knows more than I do?

Monday, May 31, 2010

C++ gotchas

I was testing the timing of some code the other day. To make test easy to exit I used _kbhit(). This way hitting any key would exit the test. The problem is _kbhit() takes a LONG time.

while(!_kbhit())
{
do_something()
}

The problem here is that do_something was the method I needed to test, but _kbhit was adding a lot of extra time to each call and I was not meeting my timing. Spent a few hours trying to improve the do_something code just to find out all I had to do was call _kbhit less often.


Another gotcha is .LIB files. .LIB are like DLLs except they are compiled into the EXE file. That way you don't need to have lots of dlls with the program. The problem with lib files is they need to be build the exact same way your program is built. DLLs run in their own little memory space, while LIB share the memory space with your EXE. If you program uses Foo-v2.dll while the LIB file was compiled to use Foo-v1.dll you'll have a conflict. This shows up when the LIB file is compiled for RELEASE, and your EXE is compiled for debug. If the lib tries to allocate memory, it will use the release version of the C-library and allocate on its heap. You're program will use the debug version of the C-library and allocate on its heap. Now you have memory allocated on two different heaps. When the program closes, C will check all the memory to ensure their wasn't any memory leaks or what not. This is a great feature if you are in debug mode. When its checking the memory, it is expecting everything to be on the 'debug heap'. It will find memory allocated from the LIB file on the 'release heap' and throw a big warning about a possible memory leak because it found memory outside of where it should have been. Moral of the story is build your LIB files with the same memory model and linked libraries as you will build your EXE. If you are giving the LIB to someone else give them a debug and release version and make sure all the other linked libraries are the same.

Saturday, March 27, 2010

NFS in windows over putty

Setting up a NFS share in windows is simple. First you need a NFS client. Windows 7 ultimate comes with a client. Programs and Features -> Turn Windows features on or off -> Services for NFS (install all of it). Other versions of windows can use Window Services for UNIX. The nfs share needs to be setup for "insecure" ports. This means ports above 1024. To do this add 'insecure' to the list of options in /etc/exports. Once you have a NFS setup on the linux box you can mount it in windows using

mount server:/path/to/share x:

This works if you do not have a firewall between you and the server. If you do you need to tunnel some ports. You need to tunnel portmapper, mountd, and nfs. On the linux server run

rpcinfo -p | grep tcp

you should see something like

100000 4 tcp 111 portmapper
100000 3 tcp 111 portmapper
100000 2 tcp 111 portmapper
100011 1 tcp 875 rquotad
100011 2 tcp 875 rquotad
100003 2 tcp 2049 nfs
100003 3 tcp 2049 nfs
100003 4 tcp 2049 nfs
100021 1 tcp 1047 nlockmgr
100021 3 tcp 1047 nlockmgr
100021 4 tcp 1047 nlockmgr
100005 1 tcp 21050 mountd
100005 2 tcp 21050 mountd
100005 3 tcp 21050 mountd


This shows portmapper running on port 111, nfs on port 2049, and mountd on port 21050. Mountd runs on a random port so you may see a different number. If you want to tell mountd to run on a specific port, in fedora edit /etc/sysconfig/nfs. Restart NFS after editing the file.

In putty you want to tunnel ports 111, 2049, and 21050 (or whatever you set mountd up with). To do this goto settings -> Connection -> Tunnels

Source port: 2049, Desitnation: 127.0.0.1:2049 click Add. Repeat this for ports 111 and 21050.

Now when you mount the server used 127.0.0.1 for the server address. For example

mount 127.0.0.1/path/to/share x:

One thing you might notice is you connect as uid -2. This is the default value for an unknown user. You can change this in the registry.

HKLM\software\microsoft\clientfornfs\currentversion\default

add a DWORD called AnonymousGid, and AnonymousUid. Set it to any uid you like. Reboot and when you connect it will be as that user.

Saturday, February 27, 2010

MoinMoin 1.9.1 desktop edition

Here is a patch file to build MoinMoin 1.9.1 for windows as a desktop edition You'll need python , docutils, and PyXml installed. This will build everything into the dist directory. You should be able to copy this directory where you want and run wikiserver.exe. No language files have been install. You will have to install them first to have a working wiki.

  • download moinmoin 1.9.1
  • unzip the patch file into the directory.
  • Run the patch file
  • run python setup_py2exe py2exe
  • look in the dist folder for output
For those looking for a prebuilt archive, you can find it here

Friday, February 26, 2010

The number that wasn't

Signed numbers on computers are handled in a special way. Computers deal with bits (1s and 0s). Numbers are represented using a number of bits, usually 8, 16, 32. To represent a signed number one of the bits is used to tell if its positive or negative, usually the 1st bit. Usually this all works and everything goes well. Sometimes you want a number using a different number of bits, like 3, 4, or 5. Some languages allow you to do this automatically. In C this would look like

struct {
int foo : 5
int bar : 1
} my_number

This makes foo 5 bits and bar 1 bit. Both of these are defined as signed numbers. foo can represent a number from -16 to 15. The question now is what values can bar hold? Because it is signed, the 1st bit will be used to tell if its negative or positive. There are no bits left to tell what the value will be. So what values can it hold? If you were wondering it is possible to define a number in your program like this.