Thread: Super fast bilinear interpolation

  1. #1
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607

    Super fast bilinear interpolation

    Looking for a way to speed up software based bilinear interpolation. I finally have a very good looking voxel engine in 32-bit color and it runs at an acceptable frame rate - and I haven't even implemeted the MMX instructions yet.

    [b]Wider vertical spans[b]
    Here is my idea. On the first stage of the renderer each vertical span is actually 2 pixels wide, then successively at set distances the vertical spans become fatter. This causes the distant mountains, hills, valleys and plains to become quite blocky, but it does allow the viewer to see very far into the distance.

    Pre-filtered maps - both height, color, and diffuse
    Now the height map and color map are pre-bilinear filtered and smoothed in a paint program so I'm not doing any of that on the fly and it looks very good. Now for distances that are extremely close to the viewer, the land still looks a bit blocky and bland. My plan is to create a diffuse texture which will represent which pixels will have their RGB's altered and how. This will create a rougher, but more realistic looking landscape.

    Need to bilinear filter the heights on close renders
    But I really need to also filter the heights of the mountains when they are close because they can get quite blocky even in 800x600x32 bit. I'm using DirectDraw and trying to do this w/o using Direct3D - Direct3D really won't help much because it is not designed for voxel graphics and it would probably just slow the main render down by calling Direct3D. Speed is very critical in the main loop.

    I need to find a very fast way to bilinear filter the height values on close renders. Currently my idea is to use fixed point math and shifts (the same for the diffuse texture u v coords). Anyone have any ideas or super fast source I might be able to look at? Most of the stuff on the web about this is either too slow or only uses 8-bit palettized modes which is so antiquated and ugly.

  2. #2
    Guilty Spark 343
    Guest
    bilinear filtering is one of the only known ways of handling pixmap magnificcation. Here is the other: Smart Filtering.

    http://www.hiend3d.com/demos.html

    I believe you can download the sourcecode from this same URL.

  3. #3
    Registered User
    Join Date
    Jun 2002
    Posts
    1
    Bilinear filter is pretty easy. You need to use fixed point math, lots of shifts and MMX.

    I've had no experience with voxel renderes so I don't know how your pipeline works, but typically in a polygon renderer you're texture coordinates are scaled from 0 to 1 to the actual dimensions of the texture. At this time, you'll want to convert them to fixed point numbers.

    Assuming you have a fixed point number in texture space, the algorithm is relatively simple.

    The following code fragment is C++ friendly and isn't necessarily fast, though it is 100% accurate. I grabbed this from an image processor I wrote for Windows. I'll leave the details of converting it into assembly language up to you.

    Code:
    DWORD GetSubTexel( int x, int y )
    {
    	const int h = (x & 0xff00) / 255;
    	const int i = (y & 0xff00) / 255;
    
    	x = x >> 16;
    	y = y >> 16;
    
    	const COLORREF cr1 = GetTexel( x + 0, y + 0 );
    	const COLORREF cr2 = GetTexel( x + 1, y + 0 );
    	const COLORREF cr3 = GetTexel( x + 1, y + 1 );
    	const COLORREF cr4 = GetTexel( x + 0, y + 1 );
    
    	const int a = (0x100 - h) * (0x100 - i);
    	const int b = (0x000 + h) * (0x100 - i);
    	const int c = (0x000 + h) * (0x000 + i);
    	const int d = 65536 - a - b - c;
    
    	const unsigned int R = 0x00ff0000 & (((cr1 >> 16)      * a) + ((cr2 >> 16)      * b) + ((cr3 >> 16)      * c) + ((cr4 >> 16)      * d));
    	const unsigned int G = 0xff000000 & (((cr1 & 0x00ff00) * a) + ((cr2 & 0x00ff00) * b) + ((cr3 & 0x00ff00) * c) + ((cr4 & 0x00ff00) * d));
    	const unsigned int B = 0x00ff0000 & (((cr1 & 0x0000ff) * a) + ((cr2 & 0x0000ff) * b) + ((cr3 & 0x0000ff) * c) + ((cr4 & 0x0000ff) * d));
    
    	return R|((G|B)>>16);    
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. bilinear interpolation
    By cboard_member in forum Game Programming
    Replies: 5
    Last Post: 03-28-2007, 10:51 PM
  2. Super fast tile rendering/scrolling in D3D
    By VirtualAce in forum Game Programming
    Replies: 7
    Last Post: 09-21-2006, 05:53 AM
  3. Interpolation in C - Help
    By finnpark in forum C Programming
    Replies: 3
    Last Post: 11-01-2005, 12:44 PM
  4. super fast question
    By kimimaro in forum C Programming
    Replies: 6
    Last Post: 03-15-2005, 09:47 AM
  5. With super powers would you:
    By Jeremy G in forum A Brief History of Cprogramming.com
    Replies: 12
    Last Post: 09-17-2003, 11:27 PM