Added color gradient for the terrain blend maps
Added terrainBuffer struct Added shared methods to genereate random UV's and intensities Added water to the terrain Added random UV's to the shader Removed the vector3d class since DX can deal with that stuff...
This commit is contained in:
@ -1,10 +1,14 @@
|
||||
#include "TerrainNode.h"
|
||||
|
||||
#define WORLD_HEIGHT 512
|
||||
#define WORLD_HEIGHT 1024
|
||||
|
||||
TerrainNode::TerrainNode(wstring name, wstring heightMap, int widthX, int widthZ, int cellSizeX, int cellSizeZ) : SceneNode(name)
|
||||
TerrainNode::TerrainNode(wstring name, wstring heightMap, wstring seed, float waterHeight, wstring waterNormalMap, int widthX, int widthZ, int cellSizeX, int cellSizeZ) : SceneNode(name)
|
||||
{
|
||||
_heightMap = heightMap;
|
||||
_seedString = seed;
|
||||
_seedHash = std::hash<wstring>{}(_seedString);
|
||||
|
||||
srand(_seedHash);
|
||||
|
||||
_widthX = widthX;
|
||||
_widthZ = widthZ;
|
||||
@ -15,16 +19,45 @@ TerrainNode::TerrainNode(wstring name, wstring heightMap, int widthX, int widthZ
|
||||
_cellSizeX = cellSizeX;
|
||||
_cellSizeZ = cellSizeZ;
|
||||
|
||||
_waterHeight = waterHeight;
|
||||
_waterNormalMapName = waterNormalMap;
|
||||
|
||||
_polygonsCount = (_gridCols * _gridRows) * 2;
|
||||
_vertexCount = _polygonsCount * 2;
|
||||
_indiciesCount = _polygonsCount * 3;
|
||||
}
|
||||
|
||||
void TerrainNode::SetAmbientLight(XMFLOAT4 ambientLight)
|
||||
{
|
||||
_ambientLight = ambientLight;
|
||||
}
|
||||
|
||||
void TerrainNode::SetWaterColor(XMFLOAT4 waterColor)
|
||||
{
|
||||
_waterColor = waterColor;
|
||||
}
|
||||
|
||||
void TerrainNode::SetDirectionalLight(FXMVECTOR lightVector, XMFLOAT4 lightColor)
|
||||
{
|
||||
_directionalLightColor = lightColor;
|
||||
XMStoreFloat4(&_directionalLightVector, lightVector);
|
||||
}
|
||||
|
||||
void TerrainNode::SetCameraPosition(XMFLOAT4 cameraPosition)
|
||||
{
|
||||
_cameraPosition = cameraPosition;
|
||||
}
|
||||
|
||||
bool TerrainNode::Initialise()
|
||||
{
|
||||
_device = DirectXFramework::GetDXFramework()->GetDevice();
|
||||
_deviceContext = DirectXFramework::GetDXFramework()->GetDeviceContext();
|
||||
|
||||
if (_device.Get() == nullptr || _deviceContext.Get() == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_heightMap.length() > 0)
|
||||
{
|
||||
if (LoadHeightMap(_heightMap))
|
||||
@ -42,12 +75,15 @@ bool TerrainNode::Initialise()
|
||||
}
|
||||
|
||||
GenerateTerrainData();
|
||||
LoadTerrainTextures();
|
||||
GenerateBlendMap();
|
||||
BuildExtraMaps();
|
||||
|
||||
GenerateBuffers();
|
||||
|
||||
BuildShaders();
|
||||
BuildVertexLayout();
|
||||
BuildConstantBuffer();
|
||||
|
||||
BuildBlendState();
|
||||
BuildRendererStates();
|
||||
return true;
|
||||
}
|
||||
@ -60,6 +96,14 @@ void TerrainNode::GenerateTerrainData()
|
||||
float centerWidth = totalWidth * -0.5f;
|
||||
float centerDepth = totalDepth * 0.5f;
|
||||
|
||||
_terrainStartX = centerWidth;
|
||||
_terrainStartZ = centerDepth;
|
||||
_terrainEndX = centerWidth + totalWidth - 1;
|
||||
_terrainEndZ = centerDepth - totalDepth + 1;
|
||||
|
||||
float bu = 1.0f / (float)(_gridCols - 1u);
|
||||
float bv = 1.0f / (float)(_gridRows - 1u);
|
||||
|
||||
int currentVertexCount = 0;
|
||||
for (int z = 0; z < _gridRows; z++)
|
||||
{
|
||||
@ -77,35 +121,56 @@ void TerrainNode::GenerateTerrainData()
|
||||
offsetIndexZ = 0;
|
||||
}
|
||||
|
||||
Vector3D polygonNormal = Vector3D(0.0f, 0.0f, 0.0f);
|
||||
float rUA = 0.0f;
|
||||
float rVA = rUA; // 0.0f;
|
||||
float rUB = 1.0f;
|
||||
float rVB = rUB;
|
||||
|
||||
VERTEX vertex;
|
||||
|
||||
/*int tumbleAmount = rand() % 10;
|
||||
|
||||
float prevUV = 0.0f;
|
||||
bool firstTumble = true;
|
||||
for (int ti = 0; ti < tumbleAmount; ti++)
|
||||
{
|
||||
prevUV = rVB;
|
||||
rVB = rUB;
|
||||
rUB = rVA;
|
||||
rVA = rUA;
|
||||
rUA = prevUV;
|
||||
}*/
|
||||
|
||||
// TL
|
||||
TerrainVertex vertex{};
|
||||
vertex.Position = XMFLOAT3(x * _cellSizeX + centerWidth, GetHeightMapValueAt(currentIndex), (-z + 1) * _cellSizeZ + centerDepth);
|
||||
vertex.Normal = XMFLOAT3(0.0f, 0.0f, 0.0f);
|
||||
vertex.TexCoord = XMFLOAT2(0.0f, 1.0f);
|
||||
vertex.TexCoord = XMFLOAT2(rUA, rVA);
|
||||
vertex.BlendMapTexCoord = XMFLOAT2((bu * x), (bv * z));
|
||||
_terrainVerts.push_back(vertex);
|
||||
_terrainNormals.push_back(polygonNormal);
|
||||
|
||||
vertex = VERTEX();
|
||||
// TR
|
||||
vertex = TerrainVertex();
|
||||
vertex.Position = XMFLOAT3((x + 1) * _cellSizeX + centerWidth, GetHeightMapValueAt(currentIndex + offsetIndexX), (-z + 1) * _cellSizeZ + centerDepth);
|
||||
vertex.Normal = XMFLOAT3(0.0f, 0.0f, 0.0f);
|
||||
vertex.TexCoord = XMFLOAT2(1.0f, 1.0f);
|
||||
vertex.TexCoord = XMFLOAT2(rUB, rVA);
|
||||
vertex.BlendMapTexCoord = XMFLOAT2((bu * (x + 1)), (bv * z));
|
||||
_terrainVerts.push_back(vertex);
|
||||
_terrainNormals.push_back(polygonNormal);
|
||||
|
||||
vertex = VERTEX();
|
||||
// BL
|
||||
vertex = TerrainVertex();
|
||||
vertex.Position = XMFLOAT3(x * _cellSizeX + centerWidth, GetHeightMapValueAt(currentIndex + offsetIndexZ), -z * _cellSizeZ + centerDepth);
|
||||
vertex.Normal = XMFLOAT3(0.0f, 0.0f, 0.0f);
|
||||
vertex.TexCoord = XMFLOAT2(0.0f, 0.0f);
|
||||
vertex.TexCoord = XMFLOAT2(rUA, rVB);
|
||||
vertex.BlendMapTexCoord = XMFLOAT2((bu * x), (bv * (z + 1)));
|
||||
_terrainVerts.push_back(vertex);
|
||||
_terrainNormals.push_back(polygonNormal);
|
||||
|
||||
vertex = VERTEX();
|
||||
// BR
|
||||
vertex = TerrainVertex();
|
||||
vertex.Position = XMFLOAT3((x + 1) * _cellSizeX + centerWidth, GetHeightMapValueAt(currentIndex + offsetIndexZ + offsetIndexX), -z * _cellSizeZ + centerDepth);
|
||||
vertex.Normal = XMFLOAT3(0.0f, 0.0f, 0.0f);
|
||||
vertex.TexCoord = XMFLOAT2(1.0f, 0.0f);
|
||||
vertex.TexCoord = XMFLOAT2(rUB, rVB);
|
||||
vertex.BlendMapTexCoord = XMFLOAT2((bu * (x + 1)), (bv * (z + 1)));
|
||||
_terrainVerts.push_back(vertex);
|
||||
_terrainNormals.push_back(polygonNormal);
|
||||
|
||||
_indices.push_back(currentVertexCount);
|
||||
_indices.push_back(currentVertexCount + 1);
|
||||
@ -123,19 +188,27 @@ void TerrainNode::GenerateTerrainData()
|
||||
{
|
||||
for (int x = 0; x < _gridCols; x++)
|
||||
{
|
||||
Vector3D vectorA = Vector3D(_terrainVerts[currentNormalIndex + 1].Position, _terrainVerts[currentNormalIndex].Position);
|
||||
Vector3D vectorB = Vector3D(_terrainVerts[currentNormalIndex + 2].Position, _terrainVerts[currentNormalIndex].Position);
|
||||
Vector3D polygonNormal = Vector3D::CrossProduct(vectorA, vectorB);
|
||||
XMVECTOR v1 = XMVectorSet(_terrainVerts[currentNormalIndex + 1].Position.x - _terrainVerts[currentNormalIndex].Position.x,
|
||||
_terrainVerts[currentNormalIndex + 1].Position.y - _terrainVerts[currentNormalIndex].Position.y,
|
||||
_terrainVerts[currentNormalIndex + 1].Position.z - _terrainVerts[currentNormalIndex].Position.z,
|
||||
0.0f);
|
||||
XMVECTOR v2 = XMVectorSet(_terrainVerts[currentNormalIndex + 2].Position.x - _terrainVerts[currentNormalIndex].Position.x,
|
||||
_terrainVerts[currentNormalIndex + 2].Position.y - _terrainVerts[currentNormalIndex].Position.y,
|
||||
_terrainVerts[currentNormalIndex + 2].Position.z - _terrainVerts[currentNormalIndex].Position.z,
|
||||
0.0f);
|
||||
|
||||
_terrainNormals[currentNormalIndex] += polygonNormal;
|
||||
_terrainNormals[currentNormalIndex + 1] += polygonNormal;
|
||||
_terrainNormals[currentNormalIndex + 2] += polygonNormal;
|
||||
_terrainNormals[currentNormalIndex + 3] += polygonNormal;
|
||||
XMVECTOR polygonNormal = XMVector3Cross(v1, v2);
|
||||
|
||||
XMStoreFloat3(&_terrainVerts[currentNormalIndex].Normal, XMVectorAdd(XMLoadFloat3(&_terrainVerts[currentNormalIndex].Normal), polygonNormal));
|
||||
XMStoreFloat3(&_terrainVerts[currentNormalIndex + 1].Normal, XMVectorAdd(XMLoadFloat3(&_terrainVerts[currentNormalIndex + 1].Normal), polygonNormal));
|
||||
XMStoreFloat3(&_terrainVerts[currentNormalIndex + 2].Normal, XMVectorAdd(XMLoadFloat3(&_terrainVerts[currentNormalIndex + 2].Normal), polygonNormal));
|
||||
XMStoreFloat3(&_terrainVerts[currentNormalIndex + 3].Normal, XMVectorAdd(XMLoadFloat3(&_terrainVerts[currentNormalIndex + 3].Normal), polygonNormal));
|
||||
|
||||
AddNormalToVertex(z - 1, x - 1, 3, polygonNormal);
|
||||
AddNormalToVertex(z - 1, x, 2, polygonNormal);
|
||||
AddNormalToVertex(z - 1, x, 3, polygonNormal);
|
||||
AddNormalToVertex(z - 1, x + 1, 2, polygonNormal);
|
||||
|
||||
AddNormalToVertex(z, x - 1, 1, polygonNormal);
|
||||
AddNormalToVertex(z, x - 1, 3, polygonNormal);
|
||||
AddNormalToVertex(z, x + 1, 0, polygonNormal);
|
||||
@ -149,29 +222,24 @@ void TerrainNode::GenerateTerrainData()
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < _terrainNormals.size(); i++)
|
||||
for (int i = 0; i < _terrainVerts.size(); i++)
|
||||
{
|
||||
_terrainNormals[i].Normalize();
|
||||
_terrainVerts[i].Normal = _terrainNormals[i].Get();
|
||||
XMVECTOR currentNormal = XMLoadFloat3(&_terrainVerts[i].Normal);
|
||||
//XMVECTOR normalised = XMVector3Normalize(currentNormal);
|
||||
XMStoreFloat3(&_terrainVerts[i].Normal, XMVector3Normalize(currentNormal));
|
||||
}
|
||||
|
||||
_terrainNormals.clear();
|
||||
}
|
||||
|
||||
void TerrainNode::AddNormalToVertex(int row, int col, int vertexIndex, Vector3D normal)
|
||||
void TerrainNode::AddNormalToVertex(int row, int col, int vertexIndex, XMVECTOR normal)
|
||||
{
|
||||
int rowIndexOffset = row * _gridCols;
|
||||
int colIndexOffset = col;
|
||||
|
||||
int finalIndex = vertexIndex + ((rowIndexOffset + colIndexOffset) * 4);
|
||||
|
||||
if (row >= 0 && row < _gridRows && col >= 0 && col < _gridCols)
|
||||
if (row >= 0 && row < (int)_gridRows && col >= 0 && col < (int)_gridCols)
|
||||
{
|
||||
_terrainNormals[finalIndex] += normal;
|
||||
}
|
||||
if (row == _gridRows)
|
||||
{
|
||||
int test = 1;
|
||||
XMStoreFloat3(&_terrainVerts[finalIndex].Normal, XMVectorAdd(XMLoadFloat3(&_terrainVerts[finalIndex].Normal), normal));
|
||||
}
|
||||
}
|
||||
|
||||
@ -181,7 +249,7 @@ void TerrainNode::GenerateBuffers()
|
||||
// buffer should be
|
||||
D3D11_BUFFER_DESC vertexBufferDescriptor;
|
||||
vertexBufferDescriptor.Usage = D3D11_USAGE_IMMUTABLE;
|
||||
vertexBufferDescriptor.ByteWidth = sizeof(VERTEX) * _vertexCount;
|
||||
vertexBufferDescriptor.ByteWidth = sizeof(TerrainVertex) * _vertexCount;
|
||||
vertexBufferDescriptor.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||
vertexBufferDescriptor.CPUAccessFlags = 0;
|
||||
vertexBufferDescriptor.MiscFlags = 0;
|
||||
@ -219,51 +287,50 @@ void TerrainNode::Render()
|
||||
XMMATRIX projectionTransformation = DirectXFramework::GetDXFramework()->GetProjectionTransformation();
|
||||
XMMATRIX viewTransformation = DirectXFramework::GetDXFramework()->GetCamera()->GetViewMatrix();
|
||||
|
||||
XMMATRIX completeTransformation = XMLoadFloat4x4(&_worldTransformation) * viewTransformation * projectionTransformation;
|
||||
XMMATRIX completeTransformation = XMLoadFloat4x4(&_combinedWorldTransformation) * viewTransformation * projectionTransformation;
|
||||
|
||||
// Draw the first cube
|
||||
CBUFFER cBuffer;
|
||||
TCBUFFER cBuffer;
|
||||
cBuffer.completeTransformation = completeTransformation;
|
||||
cBuffer.worldTransformation = XMLoadFloat4x4(&_worldTransformation);
|
||||
cBuffer.ambientColor = XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f);
|
||||
cBuffer.ambientColor = _ambientLight; // XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f);
|
||||
//cBuffer.AmbientColor = XMFLOAT4(SharedMethods::RGBValueToIntensity(0xfd), 0.0f, 1.0f, 1.0f); //XMFLOAT4(1, 1, 1, 1); //_ambientLight;
|
||||
cBuffer.lightVector = XMVector4Normalize(XMLoadFloat4(&_directionalLightVector));
|
||||
cBuffer.lightColor = XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f);
|
||||
//cBuffer.LightColor = XMFLOAT4(SharedMethods::RGBValueToIntensity(0x89), 0.0f, 5.0f, 5.0f);
|
||||
//cBuffer.LightColor = _directionalLightColor;
|
||||
cBuffer.cameraPosition = DirectXFramework::GetDXFramework()->GetCamera()->GetRawCameraPosition();
|
||||
//cBuffer.lightColor = XMFLOAT4(0.5f, 0.5f, 0.5f, 0.5f);
|
||||
//cBuffer.LightColor = XMFLOAT4(SharedMethods::RGBValueToIntensity(0x89), 0.0f, 5.0f, 5.0f);
|
||||
cBuffer.lightColor = _directionalLightColor;
|
||||
XMStoreFloat4(&cBuffer.cameraPosition, DirectXFramework::GetDXFramework()->GetCamera()->GetCameraPosition());
|
||||
|
||||
cBuffer.waterHeight = _waterHeight;
|
||||
cBuffer.waterShininess = 15.0f;
|
||||
cBuffer.waterColor = _waterColor;
|
||||
|
||||
_deviceContext->PSSetShaderResources(0, 1, _blendMapResourceView.GetAddressOf());
|
||||
_deviceContext->PSSetShaderResources(1, 1, _texturesResourceView.GetAddressOf());
|
||||
_deviceContext->PSSetShaderResources(2, 1, _waterNormalMap.GetAddressOf());
|
||||
_deviceContext->PSSetShaderResources(3, 1, _rngNoiseMap.GetAddressOf());
|
||||
|
||||
_deviceContext->VSSetShader(_vertexShader.Get(), 0, 0);
|
||||
_deviceContext->PSSetShader(_pixelShader.Get(), 0, 0);
|
||||
_deviceContext->IASetInputLayout(_layout.Get());
|
||||
|
||||
// Update the constant buffer
|
||||
_deviceContext->VSSetConstantBuffers(0, 1, _constantBuffer.GetAddressOf());
|
||||
_deviceContext->UpdateSubresource(_constantBuffer.Get(), 0, 0, &cBuffer, 0, 0);
|
||||
|
||||
// Set the texture to be used by the pixel shader
|
||||
_deviceContext->PSSetShaderResources(0, 1, _texture.GetAddressOf());
|
||||
|
||||
UINT stride = sizeof(VERTEX);
|
||||
UINT stride = sizeof(TerrainVertex);
|
||||
UINT offset = 0;
|
||||
_deviceContext->IASetVertexBuffers(0, 1, _vertexBuffer.GetAddressOf(), &stride, &offset);
|
||||
_deviceContext->IASetIndexBuffer(_indexBuffer.Get(), DXGI_FORMAT_R32_UINT, 0);
|
||||
cBuffer.diffuseCoefficient = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
cBuffer.diffuseCoefficient = XMFLOAT4(0.8f, 0.8f, 0.8f, 1.0f);
|
||||
cBuffer.specularCoefficient = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
cBuffer.shininess = 1.0f;
|
||||
cBuffer.opacity = 1.0f;
|
||||
cBuffer.shininess = 10.0f;
|
||||
cBuffer.opacity = 1.0f;
|
||||
|
||||
// Update the constant buffer
|
||||
_deviceContext->VSSetConstantBuffers(0, 1, _constantBuffer.GetAddressOf());
|
||||
_deviceContext->UpdateSubresource(_constantBuffer.Get(), 0, 0, &cBuffer, 0, 0);
|
||||
_deviceContext->PSSetShaderResources(0, 1, _texture.GetAddressOf());
|
||||
_deviceContext->PSSetConstantBuffers(0, 1, _constantBuffer.GetAddressOf());
|
||||
_deviceContext->UpdateSubresource(_constantBuffer.Get(), 0, 0, &cBuffer, 0, 0);
|
||||
_deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
|
||||
//_deviceContext->RSSetState(_wireframeRasteriserState.Get());
|
||||
_deviceContext->DrawIndexed(_indiciesCount, 0, 0);
|
||||
|
||||
// Turn back face culling back on in case another renderer
|
||||
// relies on it
|
||||
_deviceContext->RSSetState(_defaultRasteriserState.Get());
|
||||
}
|
||||
|
||||
void TerrainNode::Shutdown(void)
|
||||
@ -280,7 +347,7 @@ void TerrainNode::BuildShaders()
|
||||
ComPtr<ID3DBlob> compilationMessages = nullptr;
|
||||
|
||||
//Compile vertex shader
|
||||
HRESULT hr = D3DCompileFromFile(L"TerrainShadersNoBlend.hlsl",
|
||||
HRESULT hr = D3DCompileFromFile(L"TerrainShaders.hlsl",
|
||||
nullptr, D3D_COMPILE_STANDARD_FILE_INCLUDE,
|
||||
"VShader", "vs_5_0",
|
||||
shaderCompileFlags, 0,
|
||||
@ -297,7 +364,7 @@ void TerrainNode::BuildShaders()
|
||||
ThrowIfFailed(_device->CreateVertexShader(_vertexShaderByteCode->GetBufferPointer(), _vertexShaderByteCode->GetBufferSize(), NULL, _vertexShader.GetAddressOf()));
|
||||
|
||||
// Compile pixel shader
|
||||
hr = D3DCompileFromFile(L"TerrainShadersNoBlend.hlsl",
|
||||
hr = D3DCompileFromFile(L"TerrainShaders.hlsl",
|
||||
nullptr, D3D_COMPILE_STANDARD_FILE_INCLUDE,
|
||||
"PShader", "ps_5_0",
|
||||
shaderCompileFlags, 0,
|
||||
@ -334,27 +401,11 @@ void TerrainNode::BuildConstantBuffer()
|
||||
D3D11_BUFFER_DESC bufferDesc;
|
||||
ZeroMemory(&bufferDesc, sizeof(bufferDesc));
|
||||
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
bufferDesc.ByteWidth = sizeof(CBUFFER);
|
||||
bufferDesc.ByteWidth = sizeof(TCBUFFER);
|
||||
bufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||
ThrowIfFailed(_device->CreateBuffer(&bufferDesc, NULL, _constantBuffer.GetAddressOf()));
|
||||
}
|
||||
|
||||
void TerrainNode::BuildBlendState()
|
||||
{
|
||||
D3D11_BLEND_DESC transparentDesc = { 0 };
|
||||
transparentDesc.AlphaToCoverageEnable = false;
|
||||
transparentDesc.IndependentBlendEnable = false;
|
||||
transparentDesc.RenderTarget[0].BlendEnable = true;
|
||||
transparentDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
|
||||
transparentDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
|
||||
transparentDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
|
||||
transparentDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ZERO;
|
||||
transparentDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
|
||||
transparentDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
|
||||
transparentDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
|
||||
ThrowIfFailed(_device->CreateBlendState(&transparentDesc, _transparentBlendState.GetAddressOf()));
|
||||
}
|
||||
|
||||
void TerrainNode::BuildRendererStates()
|
||||
{
|
||||
// Set default and wireframe rasteriser states
|
||||
@ -403,8 +454,198 @@ float TerrainNode::GetHeightMapValueAt(int index)
|
||||
float result = 0;
|
||||
if (_usedHeightMap)
|
||||
{
|
||||
result = _heightValues[index] * WORLD_HEIGHT; // +(rand() % 10);
|
||||
result = _heightValues[index] * WORLD_HEIGHT; // +(rand() % 10);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void TerrainNode::LoadTerrainTextures()
|
||||
{
|
||||
// Change the paths below as appropriate for your use
|
||||
wstring terrainTextureNames[5] = { L"Textures\\grass.dds", L"Textures\\darkdirt.dds", L"Textures\\stone.dds", L"Textures\\lightdirt.dds", L"Textures\\snow.dds" };
|
||||
|
||||
// Load the textures from the files
|
||||
ComPtr<ID3D11Resource> terrainTextures[5];
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
ThrowIfFailed(CreateDDSTextureFromFileEx(_device.Get(),
|
||||
_deviceContext.Get(),
|
||||
terrainTextureNames[i].c_str(),
|
||||
0,
|
||||
D3D11_USAGE_IMMUTABLE,
|
||||
D3D11_BIND_SHADER_RESOURCE,
|
||||
0,
|
||||
0,
|
||||
false,
|
||||
terrainTextures[i].GetAddressOf(),
|
||||
nullptr
|
||||
));
|
||||
}
|
||||
// Now create the Texture2D arrary. We assume all textures in the
|
||||
// array have the same format and dimensions
|
||||
|
||||
D3D11_TEXTURE2D_DESC textureDescription;
|
||||
ComPtr<ID3D11Texture2D> textureInterface;
|
||||
terrainTextures[0].As<ID3D11Texture2D>(&textureInterface);
|
||||
textureInterface->GetDesc(&textureDescription);
|
||||
|
||||
D3D11_TEXTURE2D_DESC textureArrayDescription;
|
||||
textureArrayDescription.Width = textureDescription.Width;
|
||||
textureArrayDescription.Height = textureDescription.Height;
|
||||
textureArrayDescription.MipLevels = textureDescription.MipLevels;
|
||||
textureArrayDescription.ArraySize = 5;
|
||||
textureArrayDescription.Format = textureDescription.Format;
|
||||
textureArrayDescription.SampleDesc.Count = 1;
|
||||
textureArrayDescription.SampleDesc.Quality = 0;
|
||||
textureArrayDescription.Usage = D3D11_USAGE_DEFAULT;
|
||||
textureArrayDescription.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
textureArrayDescription.CPUAccessFlags = 0;
|
||||
textureArrayDescription.MiscFlags = 0;
|
||||
|
||||
ComPtr<ID3D11Texture2D> textureArray = 0;
|
||||
ThrowIfFailed(_device->CreateTexture2D(&textureArrayDescription, 0, textureArray.GetAddressOf()));
|
||||
|
||||
// Copy individual texture elements into texture array.
|
||||
|
||||
for (UINT i = 0; i < 5; i++)
|
||||
{
|
||||
// For each mipmap level...
|
||||
for (UINT mipLevel = 0; mipLevel < textureDescription.MipLevels; mipLevel++)
|
||||
{
|
||||
_deviceContext->CopySubresourceRegion(textureArray.Get(),
|
||||
D3D11CalcSubresource(mipLevel, i, textureDescription.MipLevels),
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
terrainTextures[i].Get(),
|
||||
mipLevel,
|
||||
nullptr
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Create a resource view to the texture array.
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC viewDescription;
|
||||
viewDescription.Format = textureArrayDescription.Format;
|
||||
viewDescription.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
|
||||
viewDescription.Texture2DArray.MostDetailedMip = 0;
|
||||
viewDescription.Texture2DArray.MipLevels = textureArrayDescription.MipLevels;
|
||||
viewDescription.Texture2DArray.FirstArraySlice = 0;
|
||||
viewDescription.Texture2DArray.ArraySize = 5;
|
||||
|
||||
ThrowIfFailed(_device->CreateShaderResourceView(textureArray.Get(), &viewDescription, _texturesResourceView.GetAddressOf()));
|
||||
}
|
||||
|
||||
void TerrainNode::GenerateBlendMap()
|
||||
{
|
||||
RGBA snowTops = RGBA{ 0u, 0u, 0u, 255u };
|
||||
RGBA grassLand = RGBA{ 0u, 0u, 50u, 0u };
|
||||
RGBA lightDirt = RGBA{ 50u, 0u, 255u, 0u };
|
||||
RGBA darkDirt = RGBA{ 255u, 0u, 0u, 0u };
|
||||
|
||||
vector<RGBA> colorSteps = {darkDirt, lightDirt, grassLand, grassLand, grassLand, snowTops};
|
||||
|
||||
ColorGradient terrainBlendGradient = ColorGradient(30.0f, 650.0f, colorSteps);
|
||||
|
||||
// Note that _numberOfRows and _numberOfColumns need to be setup
|
||||
// to the number of rows and columns in your grid in order for this
|
||||
// to work.
|
||||
DWORD* blendMap = new DWORD[_gridCols * _gridRows];
|
||||
DWORD* blendMapPtr = blendMap;
|
||||
BYTE r;
|
||||
BYTE g;
|
||||
BYTE b;
|
||||
BYTE a;
|
||||
|
||||
DWORD index = 0;
|
||||
for (DWORD i = 0; i < _gridRows; i++)
|
||||
{
|
||||
for (DWORD j = 0; j < _gridCols; j++)
|
||||
{
|
||||
|
||||
// Calculate the appropriate blend colour for the
|
||||
// current location in the blend map. This has been
|
||||
// left as an exercise for you. You need to calculate
|
||||
// appropriate values for the r, g, b and a values (each
|
||||
// between 0 and 255). The code below combines these
|
||||
// into a DWORD (32-bit value) and stores it in the blend map.
|
||||
|
||||
int currentIndex = ((i * _gridCols) + j) * 4;
|
||||
|
||||
float totalHeights = 0.0f;
|
||||
float biggestSlope = 0.0f;
|
||||
|
||||
for (int si = 0; si < 4; si++)
|
||||
{
|
||||
totalHeights += _terrainVerts[currentIndex + si].Position.y;
|
||||
if (_terrainVerts[currentIndex + si].Normal.y > biggestSlope)
|
||||
{
|
||||
biggestSlope = _terrainVerts[currentIndex + si].Normal.y;
|
||||
}
|
||||
}
|
||||
|
||||
float avgHeight = totalHeights / 4.0f;
|
||||
|
||||
RGBA currentBlend = terrainBlendGradient.GetRGBAValue(avgHeight);
|
||||
r = currentBlend.red;
|
||||
g = currentBlend.green;
|
||||
b = currentBlend.blue;
|
||||
a = currentBlend.alpha;
|
||||
|
||||
DWORD mapValue = (a << 24) + (b << 16) + (g << 8) + r;
|
||||
*blendMapPtr++ = mapValue;
|
||||
}
|
||||
}
|
||||
D3D11_TEXTURE2D_DESC blendMapDescription;
|
||||
blendMapDescription.Width = _gridCols;
|
||||
blendMapDescription.Height = _gridRows;
|
||||
blendMapDescription.MipLevels = 1;
|
||||
blendMapDescription.ArraySize = 1;
|
||||
blendMapDescription.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
blendMapDescription.SampleDesc.Count = 1;
|
||||
blendMapDescription.SampleDesc.Quality = 0;
|
||||
blendMapDescription.Usage = D3D11_USAGE_DEFAULT;
|
||||
blendMapDescription.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
blendMapDescription.CPUAccessFlags = 0;
|
||||
blendMapDescription.MiscFlags = 0;
|
||||
|
||||
D3D11_SUBRESOURCE_DATA blendMapInitialisationData;
|
||||
blendMapInitialisationData.pSysMem = blendMap;
|
||||
blendMapInitialisationData.SysMemPitch = 4 * _gridCols;
|
||||
|
||||
ComPtr<ID3D11Texture2D> blendMapTexture;
|
||||
ThrowIfFailed(_device->CreateTexture2D(&blendMapDescription, &blendMapInitialisationData, blendMapTexture.GetAddressOf()));
|
||||
|
||||
// Create a resource view to the texture array.
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC viewDescription;
|
||||
viewDescription.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
viewDescription.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||
viewDescription.Texture2D.MostDetailedMip = 0;
|
||||
viewDescription.Texture2D.MipLevels = 1;
|
||||
|
||||
ThrowIfFailed(_device->CreateShaderResourceView(blendMapTexture.Get(), &viewDescription, _blendMapResourceView.GetAddressOf()));
|
||||
delete[] blendMap;
|
||||
}
|
||||
|
||||
void TerrainNode::BuildExtraMaps()
|
||||
{
|
||||
// Note that in order to use CreateWICTextureFromFile, we
|
||||
// need to ensure we make a call to CoInitializeEx in our
|
||||
// Initialise method (and make the corresponding call to
|
||||
// CoUninitialize in the Shutdown method). Otherwise,
|
||||
// the following call will throw an exception
|
||||
ThrowIfFailed(CreateWICTextureFromFile(_device.Get(),
|
||||
_deviceContext.Get(),
|
||||
_waterNormalMapName.c_str(),
|
||||
nullptr,
|
||||
_waterNormalMap.GetAddressOf()
|
||||
));
|
||||
|
||||
ThrowIfFailed(CreateWICTextureFromFile(_device.Get(),
|
||||
_deviceContext.Get(),
|
||||
L"Textures\\noiseMap.png",
|
||||
nullptr,
|
||||
_rngNoiseMap.GetAddressOf()
|
||||
));
|
||||
}
|
Reference in New Issue
Block a user