7 replies to this topic

Posted 21 October 2012 - 09:13 AM

Hi.

I am trying to use VTF, to create a terrain. I have a heightmap of 1024x1024.

I have sampled this for vertex heights on a grid that is 2048x2048, stretching the heightmap so there are 2 vertices for every pixel. I want to be able to stretch it further. For the vertices that have no pixel, they will interpolate (If I'm not mistaken, HLSL handles that when you sample a texture).

To work out my texture coordinates I am taking the vertex position and dividing by the grid size.

My problem is the 1st 2 rows of vertices along 1 axis are giving me the same heights.

In theory the texture coordinates should be:

for the 1st row 0/2048 = 0.

for the 2nd 1/2048 = 0.00048828125.

I have used PIX to try and debug it but on both rows the coordinates both are calculated as 0.000

It seems to be rounding after 3 decimal places. therefore both rows sample the same pixels and the heights are identical.

Can I use better precision or is there another way to sample using exact coordinates? rather than 0.0-1.0

I'm guessing this would occur elsewhere on the terrain also, but its harder to find. at a glance it looks like its all used correct pixel samples and interpolated the ones that are in between.

Cheers

I am trying to use VTF, to create a terrain. I have a heightmap of 1024x1024.

I have sampled this for vertex heights on a grid that is 2048x2048, stretching the heightmap so there are 2 vertices for every pixel. I want to be able to stretch it further. For the vertices that have no pixel, they will interpolate (If I'm not mistaken, HLSL handles that when you sample a texture).

To work out my texture coordinates I am taking the vertex position and dividing by the grid size.

My problem is the 1st 2 rows of vertices along 1 axis are giving me the same heights.

In theory the texture coordinates should be:

for the 1st row 0/2048 = 0.

for the 2nd 1/2048 = 0.00048828125.

I have used PIX to try and debug it but on both rows the coordinates both are calculated as 0.000

It seems to be rounding after 3 decimal places. therefore both rows sample the same pixels and the heights are identical.

Can I use better precision or is there another way to sample using exact coordinates? rather than 0.0-1.0

I'm guessing this would occur elsewhere on the terrain also, but its harder to find. at a glance it looks like its all used correct pixel samples and interpolated the ones that are in between.

Cheers

Posted 21 October 2012 - 09:45 AM

I think that DX9 VTF only supports POINT filtering

You will have to implement your own interpolation scheme

You can specify the sampling filter in HLSL like so:

[source lang="cpp"]sampler2D gSmpColor = sampler_state { Texture = <gTexColor>; MinFilter = LINEAR; MagFilter = LINEAR; }[/source]

(You can change PIX decimal places in the options)

For small in-memory terrains you can avoid VTF and use a static vertex and index buffer and some tricks with offsets

These links might be useful:

My VTF technique using interpolation:

http://skytiger.wordpress.com/2010/11/28/xna-large-terrain/

This topic includes a rough description of my non-VTF technique:

http://www.gamedev.net/topic/620084-a-good-heightmap-lod-technique-no-vtf-please/

You will have to implement your own interpolation scheme

You can specify the sampling filter in HLSL like so:

[source lang="cpp"]sampler2D gSmpColor = sampler_state { Texture = <gTexColor>; MinFilter = LINEAR; MagFilter = LINEAR; }[/source]

(You can change PIX decimal places in the options)

For small in-memory terrains you can avoid VTF and use a static vertex and index buffer and some tricks with offsets

These links might be useful:

My VTF technique using interpolation:

http://skytiger.wordpress.com/2010/11/28/xna-large-terrain/

This topic includes a rough description of my non-VTF technique:

http://www.gamedev.net/topic/620084-a-good-heightmap-lod-technique-no-vtf-please/

Posted 21 October 2012 - 02:28 PM

Hey thanks for the reply. I have actually seen your large terrain already. Kinda what inspired what I'm doing. Im taking a mesh and moving around with the camera and snapping to the grid and then just pulling the heights from a texture.

[source lang="plain"]Texture HeightMap_LowRes;sampler TextureSampler = sampler_state{ texture = <HeightMap_LowRes> ; magfilter = linear; minfilter = linear; mipfilter= linear; AddressU = clamp; AddressV = clamp;};[/source]

from the vertex shader...

[source lang="plain"]float4 VTFCoords = float4((worldPosition.x)/TerrainSize,(worldPosition.z)/TerrainSize,0,0);float height =(float)tex2Dlod(TextureSampler, VTFCoords);[/source]

When the worldPosition.x is 0 or 1. the same height occurs (when the z is constant of course).

In your method you pull the 4 nearest pixels and do your own interpolation. You must work out those 4 points as texture coordinates. You said your heightmap is over 8k in one dimension. do you not get a problem with calculating the precise pixel coordinates? My issue is at the edge. So if I were to interpolate from 4 points at the edge, they would be 2 matching pairs as the coordinates seem to be the same. (I need to recheck in PIX after changing the decimal places).

Thank you for the links.

Kinda got my heart set on VTF as I have tried other LOD methods before, but am yet to try VTF. Your "pizza" method seems quite elegant. For now Im just using a square mesh, I want to try and make it quite low res, My application doesnt require showing a terrain right to the horizon, just the immediate area around it, but it needs to support larger terrains, so when you move it will show a new area instantly (from 1 heightmap). What I have so far looks great. I just need to sort out the interpolation. But even if I do I think my samples will pick the same heights.

Feel like I am missing something obvious?

Thanks for the help, much appreciated!

I can specify LINEAR in the sampler and get different results when specifying POINT. with point there are clear "Steps" but linear produces a smooth slope.I think that DX9 VTF only supports POINT filtering

[source lang="plain"]Texture HeightMap_LowRes;sampler TextureSampler = sampler_state{ texture = <HeightMap_LowRes> ; magfilter = linear; minfilter = linear; mipfilter= linear; AddressU = clamp; AddressV = clamp;};[/source]

from the vertex shader...

[source lang="plain"]float4 VTFCoords = float4((worldPosition.x)/TerrainSize,(worldPosition.z)/TerrainSize,0,0);float height =(float)tex2Dlod(TextureSampler, VTFCoords);[/source]

When the worldPosition.x is 0 or 1. the same height occurs (when the z is constant of course).

In your method you pull the 4 nearest pixels and do your own interpolation. You must work out those 4 points as texture coordinates. You said your heightmap is over 8k in one dimension. do you not get a problem with calculating the precise pixel coordinates? My issue is at the edge. So if I were to interpolate from 4 points at the edge, they would be 2 matching pairs as the coordinates seem to be the same. (I need to recheck in PIX after changing the decimal places).

Thank you for the links.

Kinda got my heart set on VTF as I have tried other LOD methods before, but am yet to try VTF. Your "pizza" method seems quite elegant. For now Im just using a square mesh, I want to try and make it quite low res, My application doesnt require showing a terrain right to the horizon, just the immediate area around it, but it needs to support larger terrains, so when you move it will show a new area instantly (from 1 heightmap). What I have so far looks great. I just need to sort out the interpolation. But even if I do I think my samples will pick the same heights.

Feel like I am missing something obvious?

Thanks for the help, much appreciated!

Posted 21 October 2012 - 07:29 PM

DX9 might or might not support linear filtering, depending on the GPU. Actual DX9-era GPUs won't support it, but more modern ones might. You can check the caps at runtime to see if your code will work or not.

If your texture is 1024 pixels wide, then 0 is the left-hand boundary of the left-most pixel, 1/1024 is the right-hand boundary of the same pixel and 0.5/1024 is the centre of that pixel.

So, assuming you've got the "clamp" address mode set, then it's expected that 0 and 1/2048 will return the same value.

If your texture is 1024 pixels wide, then 0 is the left-hand boundary of the left-most pixel, 1/1024 is the right-hand boundary of the same pixel and 0.5/1024 is the centre of that pixel.

So, assuming you've got the "clamp" address mode set, then it's expected that 0 and 1/2048 will return the same value.

Posted 22 October 2012 - 06:04 AM

I read something about that before. Does that mean I should aim for the centre of the pixel?

So for example 234,591, I'd attempt to get 234.5, 591.5.

What happens when it comes for pixel 1024? 1024.5? the texture coordinate would be higher than 1? or are we assuming the 1st pixel is 0 and the 1024th pixel is 1023

or is 1 the right bounds of the right most pixel.

If that is so then calculating the correct pixel may be awkward. I may have to draw some diagrams.

Again thanks for the help

So for example 234,591, I'd attempt to get 234.5, 591.5.

What happens when it comes for pixel 1024? 1024.5? the texture coordinate would be higher than 1? or are we assuming the 1st pixel is 0 and the 1024th pixel is 1023

or is 1 the right bounds of the right most pixel.

If that is so then calculating the correct pixel may be awkward. I may have to draw some diagrams.

Again thanks for the help

Posted 22 October 2012 - 07:13 AM

The way texcoords work is that 0 is the left/top edge of your image, and 1 is the bottom/right edge, which is very abstract and disconnected from the notion of pixels.

If you're thinking in integer coordinates for an array of 1024 pixels, then 0 is the*index* of the leftmost pixel and 1023 is the *index* of the rightmost pixel.

To reconcile the two, we can imagine a grid of 1024 squares scaled down to be 1 unit wide total. Each cell would then be 1/1024 units wide. The offset from the edge of a squares to it's centre would be 0.5/1024 units. We can pretend that these squares are pixels, even though that's not technically true (*pixels are just points in 2d space with no pre-defined shape or size -- the filtering mode used gives them shape, e.g. nearest/point filtering makes them appear as squares*).

So to convert from an integer pixel index to a texture coordinate at the very centre of that pixel, you can use (pixel index + 0.5) / pixel count.

So, yes, 1023.5/1024 is the exact centre of the rightmost pixel.

If clamp mode is used, then 1.0 is the right hand edge of the rightmost pixel. If wrap mode is used, then 1.0/0.0 are the same -- on the edge between the first and last pixels.

If you're thinking in integer coordinates for an array of 1024 pixels, then 0 is the

To reconcile the two, we can imagine a grid of 1024 squares scaled down to be 1 unit wide total. Each cell would then be 1/1024 units wide. The offset from the edge of a squares to it's centre would be 0.5/1024 units. We can pretend that these squares are pixels, even though that's not technically true (

So to convert from an integer pixel index to a texture coordinate at the very centre of that pixel, you can use (pixel index + 0.5) / pixel count.

So, yes, 1023.5/1024 is the exact centre of the rightmost pixel.

If clamp mode is used, then 1.0 is the right hand edge of the rightmost pixel. If wrap mode is used, then 1.0/0.0 are the same -- on the edge between the first and last pixels.

**Edited by Hodgman, 22 October 2012 - 07:16 AM.**

Posted 22 October 2012 - 07:54 AM

Thank you very much, I tried that and it has solved the problem.

Posted 22 October 2012 - 01:33 PM

not get a problem with calculating the precise pixel coordinates

no because worst case 32 bit floating point precision between 0.0 and 1.0 is 1 / 16,777,216 (between 0.5 and 1.0)

and I only need precision down to 1 / 16,384 to hit the centroids

**Edited by skytiger, 22 October 2012 - 01:38 PM.**