Jump to content
  • Advertisement
Sign in to follow this  
MalmodirMurin

Porting XNA to DX9 - Blurry Textures

This topic is 2788 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi,

I am currently encountering a strange problem while porting my XNA application to DX9. The terrain textures appear blurred. The shader takes 2 textures (shore and high ground, both 1024*1024 px, *.dds filetype and pre-generated mipmaps) and fades between them. The base colors are visible, but the details get blurred out. I expect some flags, render states or other settings are missing, which are enabled by default in XNA, but that's just my assumption....

http://img130.images.../3013/texdy.jpg

Texture Loading Code
D3DXCreateTextureFromFile(device, options.TextureLowAsset, &texlow);

Shader Texture Sampler
MinFilter = Linear;
MagFilter = Linear;
MipFilter = Linear;
AddressU = Wrap;
AddressV = Wrap;


I tested several different settings (filter settings in device and shader...), but it is hard to find the problem because my knowledge is not that wide.

Cheers, Malmodir

Share this post


Link to post
Share on other sites
Advertisement
Guess I'll start posting some more code...

Initializing
void CIsland::InitHeightData()
{
LPDIRECT3DTEXTURE9 texHM = 0;
D3DSURFACE_DESC descHM;
D3DLOCKED_RECT rctData;

// load height map texture
D3DXCreateTextureFromFile(device, options.HeightAsset, &texHM);

// store image size as island size
texHM->GetLevelDesc(0, &descHM);
options.MapWidth = descHM.Width;
options.MapDepth = descHM.Height;

// allocate field structures
options.HeightData = new CField[options.MapWidth * options.MapDepth];

// provide access to image data
texHM->LockRect(0, &rctData, 0, 0);
BYTE* lpHeights = (BYTE*) rctData.pBits;

// iterate over each pixel and retrieve information
for (int z = 0; z < options.MapDepth; z++)
for (int x = 0; x < options.MapWidth; x++)
{
int index = z + x * options.MapWidth;
int curHeight = ((int) (*((LPDWORD)rctData.pBits + x + z * (rctData.Pitch / 4)) & 0x000000ff));

// read height from pixel
options.HeightData[index].Height = curHeight;
}

// release access
texHM->UnlockRect(0);

// free further unused resources
texHM->Release();
}

void CIsland::InitVertices()
{
//prepare vertex buffer
device->CreateVertexBuffer(options.MapWidth * options.MapDepth * sizeof(IslandVertex), 0, IslandFVF, D3DPOOL_MANAGED, &vbuffer, NULL);

// initialize randomizer
srand((unsigned int)time(NULL));

// calculate absolute offset
D3DXVECTOR3 absOff = D3DXVECTOR3(-options.MapWidth * options.Stride * 0.5f, 0, options.MapDepth * options.Stride * 0.5f);

// store default extrema
options.HeightMin = 0;
options.HeightMax = 0;

// provide access to vertex buffer
IslandVertex* sv;
vbuffer->Lock(0, 0, (void**)&sv, 0);

// iterate over each field
for (int x = 0; x < options.MapWidth; x++)
for (int z = 0; z < options.MapDepth; z++)
{
// calculate current index
int index = z + x * options.MapWidth;

// calculate final y-position
float curHeight = options.HeightData[index].Height * options.ScaleY;

// compare and eventually store new minimum height
if (curHeight < options.HeightMin)
options.HeightMax = curHeight;

// compare and eventually store new maximum height
if (curHeight > options.HeightMax)
options.HeightMax = curHeight;

// calculate relative offset
D3DXVECTOR3 relOff = D3DXVECTOR3(x * options.Stride, curHeight, -z * options.Stride);

// calculate final vertex position
sv[index].Position = options.Position + absOff + relOff;

// calculate texture coordinates linearly
sv[index].TexCoord.x = (float)x / (float)options.MapWidth;
sv[index].TexCoord.y = (float)z / (float)options.MapDepth;


// calculate tree propability on that vertex
options.HeightData[index].Palm.IsAvailable = (curHeight > options.PalmHeightMin && (rand() % 100) < options.PalmPropability);

// resolve model index for that tree
options.HeightData[index].Palm.ModelIndex = (rand() % options.PalmModelCount);

// calculate world matrix with random parameters
float scaleOfTree = (float)(rand() % options.PalmScaleMax + options.PalmScaleMin);
D3DXMATRIX scale; D3DXMatrixScaling(&scale, scaleOfTree, scaleOfTree, scaleOfTree);
D3DXMATRIX rotation; D3DXMatrixRotationY(&rotation, DEGTORAD(rand() % 90));
D3DXMATRIX translation; D3DXMatrixTranslation(&translation, sv[index].Position.x, sv[index].Position.y, sv[index].Position.z);
options.HeightData[index].Palm.World = scale * rotation * translation;
}

// unlock vertex buffer
vbuffer->Unlock();

// retrieve description
D3DVERTEXBUFFER_DESC vbdesc;
vbuffer->GetDesc(&vbdesc);
trianglenum = vbdesc.Size / sizeof(IslandVertex);
}

void CIsland::InitIndices()
{
// fill index-buffer
device->CreateIndexBuffer(options.MapWidth * options.MapDepth * 2 * 3 * sizeof(int), 0, D3DFMT_INDEX32, D3DPOOL_MANAGED, &ibuffer, NULL);

// provide access to index buffer
int* indices;
ibuffer->Lock(0, 0, (void**)&indices, 0);

// iterate over each field
long counter = 0;
for (int z = 0; z < options.MapDepth - 1; z++)
for (int x = 0; x < options.MapWidth - 1; x++)
{
// assign upper triangle
indices[counter] = (z + 0) * options.MapDepth + x + 0; counter++;
indices[counter] = (z + 0) * options.MapDepth + x + 1; counter++;
indices[counter] = (z + 1) * options.MapDepth + x + 0; counter++;

// assign lower triangle
indices[counter] = (z + 1) * options.MapDepth + x + 0; counter++;
indices[counter] = (z + 0) * options.MapDepth + x + 1; counter++;
indices[counter] = (z + 1) * options.MapDepth + x + 1; counter++;
}

// unlock index buffer
ibuffer->Unlock();

// retrieve description
D3DINDEXBUFFER_DESC ibdesc;
ibuffer->GetDesc(&ibdesc);
trianglenum = ibdesc.Size / (sizeof(int) * 3);
}

void CIsland::InitEffect()
{
// load terrain resources
effect = 0;
Utilities::LoadShader(device, options.ShaderAsset, effect);
texlow = 0;
D3DXCreateTextureFromFile(device, options.TextureLowAsset, &texlow);
texhigh = 0;
D3DXCreateTextureFromFile(device, options.TextureHighAsset, &texhigh);

// setup shader parameters
effect->SetFloat("TexScale", options.TextureScale);
effect->SetTexture("GroundTexLow", texlow);
effect->SetTexture("GroundTexTop", texhigh);
effect->SetFloat("WaterPosY", options.WaterPositionY);
effect->SetFloat("MaxHeight", options.HeightMax);
}


Draw-Method
void CIsland::Draw(float elapsedTime, D3DXMATRIX view, D3DXMATRIX projection, D3DXMATRIX world)
{
// cull no triangles
device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);

// set camera state on shader
effect->SetValue("WorldViewProj", world * view * projection, sizeof(D3DXMATRIX));

device->SetFVF(IslandFVF);
device->SetStreamSource(0, vbuffer, 0, sizeof(IslandVertex));
device->SetIndices(ibuffer);

UINT totalPasses;
D3DXHANDLE hTechnique = effect->GetTechnique(0);

if (SUCCEEDED(effect->SetTechnique(hTechnique)))
{
if (SUCCEEDED(effect->Begin(&totalPasses, 0)))
{
for (UINT pass = 0; pass < totalPasses; ++pass)
{
if (SUCCEEDED(effect->BeginPass(pass)))
{
device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, vertexnum, 0, trianglenum);
effect->EndPass();
}
}

effect->End();
}
}
}


Shader-Code:
float4x4 WorldViewProj;
float WaterPosY;
float MaxHeight;
float TexScale;
texture GroundTexLow;
texture GroundTexTop;

sampler TexLowSampler = sampler_state
{
Texture = (GroundTexLow);
MinFilter = Linear;
MagFilter = Linear;
MipFilter = Linear;
AddressU = Wrap;
AddressV = Wrap;
};

sampler TexTopSampler = sampler_state
{
Texture = (GroundTexTop);
MinFilter = Linear;
MagFilter = Linear;
MipFilter = Linear;
AddressU = Wrap;
AddressV = Wrap;
};

struct VSIn
{
float4 Position : POSITION0;
float2 TexCoord : TEXCOORD0;
};

struct VSOut
{
float4 Position : POSITION0;
float3 PosUnit : TEXCOORD1;
float2 TexCoord : TEXCOORD2;
};

VSOut VSTerrainGeneral(VSIn input)
{
VSOut output;

output.Position = mul(input.Position, WorldViewProj);
output.PosUnit = input.Position.xyz;
output.TexCoord = input.TexCoord;

return output;
}

float4 PSTerrainGeneral(VSOut input) : COLOR0
{
if (input.PosUnit.y < WaterPosY)
return float4(0, 0, 0, 0);

float4 clr = float4(0, 0, 0, 1);
clr.rgb += tex2D(TexLowSampler, input.TexCoord * TexScale).rgb * (1 - input.PosUnit.y / MaxHeight);
clr.rgb += tex2D(TexTopSampler, input.TexCoord * TexScale).rgb * (0 + input.PosUnit.y / MaxHeight);
return clr;
}

technique TerrainGeneral
{
pass Pass1
{
VertexShader = compile vs_2_0 VSTerrainGeneral();
PixelShader = compile ps_2_0 PSTerrainGeneral();
}
}


It is a very basic shader, mapping the texture to the pixels in a repeating manner. The texture coordinates are calculated linearly (x/totalX and y/totalY). The strange thing is that this completely works in XNA, I used it for prototyping and now want to port it. I already double-checked all members of the options-instance, but they get set correctly.

A few values:
HeightMap = 256*256
Textures = 1024*1024
Stride = 4
Y-Scale = 0.5f
TextureScale = 5
Position = (0; -20; 0)

Share this post


Link to post
Share on other sites
.... DOH!

Solved it, your assumption was right. The texture coords did not get used, because of a formal issue. My FVF was (D3DFVF_XYZ|D3DFVF_TEX0) instead of TEX1.
Thank you (calculate cursor distance to next up rate button) :)

Share this post


Link to post
Share on other sites
If you're used to XNA, I would suggest using vertex declarations instead of FVF codes. They're just all-around better.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!