Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I've been having trouble with vertex texture fetch for a terrain system I am implementing. I'm using C++/DirectX9.

I have already implemented exactly what I want as a prototype in C#/XNA and now need to get a DirectX implementation. Ive used the same HLSL code. I thought it would be a case of finding the DirectX equivalent of the XNA function calls. The issue is the call to tex2dlod returns 0 all the time. To try and debug this I sampled the same texture in the pixel shader using tex2d and the values are correct. I see the height map on a flat plane. Obviously the vertices's should be displaced as well.

I believe it may have something to do with the texture format I am using. In XNA

Texture2D globalHeightMap = new Texture2D(device, textureSize, textureSize, 0, TextureUsage.None, SurfaceFormat.Luminance16);
globalHeightMap.SetData<ushort>(heightData);

The height map is created in the C# program as an array of ushorts. Once in the shader the values returned are in the range of 0.0 - 1.0. That value is then scaled by a modifier. This implementation works fine.

In DirectX however it does not. This is the code I use to set up the texture

HRESULT hr =D3DXCreateTextureFromFileEx(
    device,
    "heightmap.bmp",
    D3DX_DEFAULT,
    D3DX_DEFAULT,
    D3DX_DEFAULT,
    0,
    D3DFMT_L16,
    D3DPOOL_DEFAULT,
    D3DX_FILTER_POINT,
    D3DX_FILTER_POINT,
    0,
    NULL,
    NULL, 
    &heightMap
    );

The HRESULT does not contain an error. And sampling on the pixel shader returns correct values. The height map texture is that created by the other program.

EDIT: Shader Code The principle of the terrain system is to move a small piece of mesh with the camera and round the position to whole numbers. (so vertices stay snapped to the grid). The idea is that not all the terrain is rendered (only local areas).

Calculate the vertex's position by adding the Eye vector to it use that position and divide it by the terrains size to get the texture coordinates.

Again the system works perfectly in XNA.

Here is the vertex shader: There are some parameters that can be set for using different resolutions to stretch a heightmap over a greater area.

VS_OUTPUT Position_Pass_0_Vertex_Shader_vs_main( VS_INPUT Input )
{
VS_OUTPUT Output = (VS_OUTPUT)0;

int TerrainSize = ((HeightMapSize) * (HeightMapResolution)) ;

float offset = 0.5f;
float4 worldPos= mul(float4(Input.Position.xyz,1), matWorld);

float height = InterpolateHeight(GlobalHeightMapSampler, worldPos, offset, TerrainSize, HeightMapResolution);   


Output.A.x = height; // Used for debugging by outputting color in PS
height *= 8900; // scale up the height
worldPos.y += height; // modify position

float4 posView = mul(worldPos,matView); // view space
Output.Position =  mul( posView,matProjection); // proj space   

return( Output );   
}

And here is the InterpolateHeight Function

float InterpolateHeight(sampler textureSampler, float4 worldPosition, float offset, int TerrainSize, int resolution)
{
int LowerX = (int)((worldPosition.x+Eye.x) / resolution);
int LowerZ = (int)((worldPosition.z+Eye.z) / resolution);

float4 bl_coords = float4(((LowerX*resolution)+offset)/TerrainSize,((LowerZ*resolution)+offset)/TerrainSize,0,0);
    float BL = tex2Dlod(textureSampler,bl_coords ).x;

float4 br_cords = float4((((LowerX+1)*resolution)+offset)/TerrainSize,((LowerZ*resolution)+offset)/TerrainSize,0,0);
    float BR = tex2Dlod(textureSampler, br_cords).x;

float4 tl_coords =  float4(((LowerX*resolution)+offset)/TerrainSize,(((LowerZ+1)*resolution)+offset)/TerrainSize,0,0);
    float TL = tex2Dlod(textureSampler,tl_coords).x;

float4 tr_coords =float4((((LowerX+1)*resolution)+offset)/TerrainSize,(((LowerZ+1)*resolution)+offset)/TerrainSize,0,0);
    float TR = tex2Dlod(textureSampler, tr_coords).x;


float xinterp = ((worldPosition.x+Eye.x) - (LowerX*resolution))/resolution;
float b = lerp(BL,BR,xinterp );
float t = lerp(TL,TR,xinterp);

return lerp(b,t,((worldPosition.z+Eye.z) - (LowerZ*resolution))/resolution);
}

And here is the variables/sampler object

float4x4 matView : View;
float4x4 matProjection : Projection;
float4x4 matWorld : World;

float4 Eye;

int HeightMapResolution;
int HeightMapSize;
Texture GlobalHeightMap;
sampler GlobalHeightMapSampler = sampler_state 
{ 
texture = <GlobalHeightMap> ;
magfilter = point; 
minfilter = point; 
mipfilter= point; 
AddressU = clamp;
AddressV = clamp;
};

struct VS_INPUT 
{
float3 Position : POSITION0;
};

struct VS_OUTPUT 
{
float4 Position : POSITION0;
float2 A : TEXCOORD0;
};

What am I doing wrong?

share|improve this question

closed as too localized by bummzack, Byte56, Josh Petrie, Anko, Trevor Powell Apr 9 '13 at 9:02

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.If this question can be reworded to fit the rules in the help center, please edit the question.

    
if you could post your Shader code, that would help even more. it´s hard to say what it could be. It could be that your UV cords are incorrect, or that your texture object is incorrect aswell. –  Tordin Mar 25 '13 at 10:52
    
Just updated it to include shader code –  user1107837 Mar 25 '13 at 11:36
    
do thees test : 1 : Out put the uv cordinates only. i should be black in one corer and fully gree in another and red in a third. and green + red in one. if this is not your result, then you must check your vertex layout, and make sure that you get all the data to the shader. ( Or step back steps in your shader code when you generate the uv cords )<br> 2: use pix to see what your draw calls has bound. check the texture to see that it contains the data you suspect and that your vertex buffer is correct. if this fails you have some issues when creating your data. –  Tordin Mar 25 '13 at 15:59
    
Thanks. I did what you said and it was black in one corner, green, red and green/red in the other. the coordinates are correct. i even sampled them in ps on that side and the heightmap is displayed. Cant get it working in the vertex shader. Im sure the data is correct. I have done a lot of digging and many sources say tex2Dlod is strange with surface formats. This shouldnt be an issue since XNA has no problem, and that just directX under the hood. Im gonna try using a different format. –  user1107837 Mar 25 '13 at 21:02
    
If i remember corectly, you have to specify what lod to use when sampling with Lod, so it would be something like tex2DLod( blah, blah, 0 <---- the zero lod ); you should try that out and see if that works better. –  Tordin Mar 26 '13 at 7:55

Browse other questions tagged or ask your own question.