Centered terrain?

Started by
7 comments, last by RobM 8 years, 8 months ago
I currently have my terrain positioned at 0,0 extending out to 1024,1024 or bigger - from a floating point accuracy point of view, would it be better to have it centered around 0,0 rather than starting there? My terrain size can be 8192x8192
Advertisement

Floats have larger precision (accuracy?) near the origin, so almost certainly it would be ideal.

o3o

Floats have larger precision (accuracy?) near the origin, so almost certainly it would be ideal.


Great, thanks
The difference is going to be only one bit. If you are so close to the precision limit that one bit makes a difference, you are going to run into problems eventually. It doesn't make sense to have more resolution in some part of the scene than another, so a fixed-point representation might be more appropriate.

The difference is going to be only one bit. If you are so close to the precision limit that one bit makes a difference, you are going to run into problems eventually. It doesn't make sense to have more resolution in some part of the scene than another, so a fixed-point representation might be more appropriate.


Would you mind explaining this a bit further please? I'm not sure I understand - what is fixed point representation?

The difference is going to be only one bit. If you are so close to the precision limit that one bit makes a difference, you are going to run into problems eventually. It doesn't make sense to have more resolution in some part of the scene than another, so a fixed-point representation might be more appropriate.


I read up on fixed point representation. Oddly, I have used that before years ago without knowing it was known as that!

How would I be able to use fixed point with things like vertex buffers and hlsl? I'm using dx9 so I don't think I can use integers in shaders yet.

How would I be able to use fixed point with things like vertex buffers and hlsl? I'm using dx9 so I don't think I can use integers in shaders yet.

In your D3DVERTEXELEMENT9 that describes the position, replace D3DDECLTYPE_FLOAT3 with something else (and then fill your vertex buffer with this other data type instead of floats). In your HLSL vertex shader, you still use floats -- the input assembler (the vertex declaration hardware) does the conversion to float for you automatically.

D3D9 supports 8bit, 10bit and 16bit fixed point. D3D11 adds support for 32bit fixed point.
The 16bit D3D9 formats are:
D3DDECLTYPE_SHORT4 -- same as short in C++ (16 bit integer). The conversion that's applied before the VS is a simple cast -- vsInput = (float)value
D3DDECLTYPE_SHORT4N -- a 16 bit integer, but the conversion is a scaling factor -- vsInput = value / 32767.0
D3DDECLTYPE_USHORT4N -- a 16 bit unsigned integer, with a scaling factor -- vsInput = value / 65535.0
Unfortunately you can't use SHORT3 as it would cause bad data alignment, so you either have to waste 16bytes, or find something useful to store in your position's W value.

D3DDECLTYPE_UDEC3 and D3DDECLTYPE_DEC3N are the 10bit formats (3x 10 bit channels packed into a 32bit integer, wasting 2 bits), which are extremely useful for storing normals/tangents.
D3D11 exposes this format as R10_G10_B10_A2, so that you can use the 2 bits for some extra small data if you like (e.g. the "binormal sign" often needs to be packed somewhere).
OpenGL exposes some slightly better packed-into-32 formats, which are basically R11_G11_B10 (I forget the actual GL name), which avoids wasting those 2 bits and gives you a tiny bit of extra precision.

D3D9 and D3D11 also support "half floats" (16bit float), which is off topic here, but is very useful as well. I usually use float16 for texture coordinates instead of float32.


My terrain size can be 8192x8192

This terrain is not big enough to cause precision problems, unless you are doing something funky.

If one were rendering realistic-scale planets, for example, then one typically is beyond the useful range of fixed point as well, and you have to take the opposite tack: store everything in local coordinates, place the camera at the origin, and transform everything relative to the camera before feeding to the GPU. You also end up scaling objects down and moving them closer to the camera, to stay within reasonable depth precision... It's a royal pain.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

How would I be able to use fixed point with things like vertex buffers and hlsl? I'm using dx9 so I don't think I can use integers in shaders yet.

In your [font='courier new', courier, monospace]D3DVERTEXELEMENT9[/font] that describes the position, replace [font='courier new', courier, monospace]D3DDECLTYPE_FLOAT3[/font] with something else (and then fill your vertex buffer with this other data type instead of floats). In your HLSL vertex shader, you still use floats -- the input assembler (the vertex declaration hardware) does the conversion to float for you automatically.

D3D9 supports 8bit, 10bit and 16bit fixed point. D3D11 adds support for 32bit fixed point.
The 16bit D3D9 formats are:[font='courier new', courier, monospace]D3DDECLTYPE_SHORT4[/font] -- same as short in C++ (16 bit integer). The conversion that's applied before the VS is a simple cast -- [font='courier new', courier, monospace]vsInput = (float)value[/font][font='courier new', courier, monospace]D3DDECLTYPE_SHORT4N[/font] -- a 16 bit integer, but the conversion is a scaling factor -- [font='courier new', courier, monospace]vsInput = value / 32767.0[/font][font='courier new', courier, monospace]D3DDECLTYPE_USHORT4N[/font] -- a 16 bit unsigned integer, with a scaling factor -- [font='courier new', courier, monospace]vsInput = value / 65535.0[/font]
Unfortunately you can't use SHORT3 as it would cause bad data alignment, so you either have to waste 16bytes, or find something useful to store in your position's W value.
[font='courier new', courier, monospace]D3DDECLTYPE_UDEC3[/font] and [font='courier new', courier, monospace]D3DDECLTYPE_DEC3N[/font] are the 10bit formats (3x 10 bit channels packed into a 32bit integer, wasting 2 bits), which are extremely useful for storing normals/tangents.
D3D11 exposes this format as [font='courier new', courier, monospace]R10_G10_B10_A2[/font], so that you can use the 2 bits for some extra small data if you like (e.g. the "binormal sign" often needs to be packed somewhere).
OpenGL exposes some slightly better packed-into-32 formats, which are basically [font='courier new', courier, monospace]R11_G11_B10[/font] (I forget the actual GL name), which avoids wasting those 2 bits and gives you a tiny bit of extra precision.

D3D9 and D3D11 also support "half floats" (16bit float), which is off topic here, but is very useful as well. I usually use float16 for texture coordinates instead of float32.

Thanks for this, I had no idea HLSL handled fixed point - very useful

This topic is closed to new replies.

Advertisement