Code:
bool cTerrain::CreateTexture()
{
IDirect3DTexture9 *Textures[NUM_TEXTURES] = {NULL, NULL, NULL, NULL, NULL};
float Widths[NUM_TEXTURES] = {0, 0, 0, 0, 0};
float Heights[NUM_TEXTURES] = {0, 0, 0, 0, 0};
int Pitchs[NUM_TEXTURES] = {0, 0, 0, 0, 0};
unsigned long *Data[NUM_TEXTURES] = {NULL, NULL, NULL, NULL, NULL};
if(FAILED(D3DXCreateTexture(D3DDevice, 1024, 1024, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &Texture)))
return false;
if(FAILED(D3DXCreateTextureFromFile(D3DDevice, TEXTURE_WATER, &Textures[0])))
return false;
if(FAILED(D3DXCreateTextureFromFile(D3DDevice, TEXTURE_SAND, &Textures[1])))
return false;
if(FAILED(D3DXCreateTextureFromFile(D3DDevice, TEXTURE_GRASS, &Textures[2])))
return false;
if(FAILED(D3DXCreateTextureFromFile(D3DDevice, TEXTURE_STONE, &Textures[3])))
return false;
if(FAILED(D3DXCreateTextureFromFile(D3DDevice, TEXTURE_SNOW, &Textures[4])))
return false;
for(unsigned char I = 0; I < NUM_TEXTURES; I++)
{
try
{
D3DSURFACE_DESC SampleDesc;
D3DLOCKED_RECT SampleRect;
Textures[I]->GetLevelDesc(0, &SampleDesc);
Widths[I] = (float)SampleDesc.Width;
Heights[I] = (float)SampleDesc.Height;
Textures[I]->LockRect(0, &SampleRect, 0, 0);
Data[I] = (unsigned long *)(SampleRect.pBits);
Pitchs[I] = SampleRect.Pitch;
Textures[I]->UnlockRect(0);
}
catch(...)
{
return false;
}
}
D3DSURFACE_DESC TextureDesc;
Texture->GetLevelDesc(0, &TextureDesc);
if(TextureDesc.Format != D3DFMT_X8R8G8B8)
return false;
D3DLOCKED_RECT LockedRect;
Texture->LockRect(0, &LockedRect, 0, 0);
unsigned long *ImageData = (unsigned long *)(LockedRect.pBits);
for(unsigned long ZPos = 0; ZPos < TextureDesc.Height; ZPos++)
{
for(unsigned long XPos = 0; XPos < TextureDesc.Width; XPos++)
{
float fX = (float)XPos / (float)TextureDesc.Width;
float fZ = (float)ZPos / (float)TextureDesc.Height;
unsigned long X = (unsigned long)(fX * (float)NumCols);
unsigned long Z = (unsigned long)(fZ * (float)NumRows);
float Height = 0.0f;
float tA = Map[GetIndex(X , Z )].Y;
float tB = Map[GetIndex(X , Z + 1)].Y;
float tC = Map[GetIndex(X + 1, Z )].Y;
float tD = Map[GetIndex(X + 1, Z + 1)].Y;
float dX = ((float)fX * (float)NumCols) - ((float)X);
float dZ = ((float)fZ * (float)NumRows) - ((float)Z);
if(dX + dZ < 1.0f)
{
float uY = tB - tA;
float vY = tC - tA;
Height = tA + uY * dZ + vY * dX;
}
else
{
float uY = tC - tD;
float vY = tB - tD;
Height = tD + uY * (1.0f - dZ) + vY * (1.0f - dX);
}
unsigned long Colour = 0;
unsigned long B = 0;
unsigned long G = 0;
unsigned long R = 0;
for(char I = (NUM_TEXTURES - 1); I >= 0; I = I - 1)
{
float dT = TERRAIN_HEIGHT / NUM_TEXTURES;
float dY = Height - ((I + 1.0f) * dT - 1.0f);
if(dY < 0.0f)
dY = dY * -1;
float Weight = (dT - dY) / dT;
if(Weight >= 0.0f)
{
if(I == 0)
{
if(B == 0 && G == 0 && R == 0)
{
Weight = 1.0f;
}
}
unsigned long T = (unsigned long)(fX * (float)Widths[I]);
unsigned long U = (unsigned long)(fZ * (float)Heights[I]);
Colour = Data[I][U * Pitchs[I] / 4 + T];
B = B + (unsigned long) ((Colour & 255) * Weight);
G = G + (unsigned long)(((Colour >> 8) & 255) * Weight);
R = R + (unsigned long)(((Colour >> 16) & 255) * Weight);
}
}
Colour = RGB(B, G, R);
ImageData[ZPos * LockedRect.Pitch / 4 + XPos] = Colour;
}
}
Texture->UnlockRect(0);
if(FAILED(D3DXFilterTexture(Texture, 0, 0, D3DX_DEFAULT)))
return false;
D3DDevice->SetTexture(0, Texture);
return true;
}
It's not commented. But. Well. If you have questions, ask away. It's roughly straightforward. There are a lot of ratio calculations going on in there though.