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:
56
Graphics2/ColorGradient.cpp
Normal file
56
Graphics2/ColorGradient.cpp
Normal file
@ -0,0 +1,56 @@
|
||||
#include "ColorGradient.h"
|
||||
|
||||
ColorGradient::ColorGradient(float min, float max, vector<RGBA> colorSteps)
|
||||
{
|
||||
_minValue = min;
|
||||
_maxValue = max;
|
||||
_colorSteps = colorSteps;
|
||||
}
|
||||
|
||||
ColorGradient::~ColorGradient()
|
||||
{
|
||||
_colorSteps.clear();
|
||||
}
|
||||
|
||||
// Get the RGBA value at the give point
|
||||
RGBA ColorGradient::GetRGBAValue(float inputValue)
|
||||
{
|
||||
if (inputValue <= _minValue)
|
||||
{
|
||||
return _colorSteps.front();
|
||||
}
|
||||
else if (inputValue >= _maxValue)
|
||||
{
|
||||
return _colorSteps.back();
|
||||
}
|
||||
|
||||
float range = _maxValue - _minValue;
|
||||
float value = inputValue - _minValue;
|
||||
float steps = range / (float)(_colorSteps.size() - 1);
|
||||
|
||||
int colorStepInside = (int)(value / steps);
|
||||
|
||||
float normalisedValue = (value - (colorStepInside * steps)) / steps;
|
||||
|
||||
return Interpolate(_colorSteps[colorStepInside], _colorSteps[colorStepInside + 1], normalisedValue);
|
||||
}
|
||||
|
||||
// Method for interpolating the color between each step
|
||||
RGBA ColorGradient::Interpolate(RGBA a, RGBA b, float pointValue)
|
||||
{
|
||||
if (pointValue <= 0.0f)
|
||||
{
|
||||
return a;
|
||||
}
|
||||
else if (pointValue >= 1.0f)
|
||||
{
|
||||
return b;
|
||||
}
|
||||
|
||||
unsigned int currentRed = (unsigned int)((1.0f - pointValue) * a.red + pointValue * b.red);
|
||||
unsigned int currentGreen = (unsigned int)((1.0f - pointValue) * a.green + pointValue * b.green);
|
||||
unsigned int currentBlue = (unsigned int)((1.0f - pointValue) * a.blue + pointValue * b.blue);
|
||||
unsigned int currentAlpha = (unsigned int)((1.0f - pointValue) * a.alpha + pointValue * b.alpha);
|
||||
|
||||
return RGBA{ currentRed, currentGreen, currentBlue, currentAlpha };
|
||||
}
|
34
Graphics2/ColorGradient.h
Normal file
34
Graphics2/ColorGradient.h
Normal file
@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
// Struct to hold the color data in
|
||||
typedef struct RGBA {
|
||||
unsigned int red;
|
||||
unsigned int green;
|
||||
unsigned int blue;
|
||||
unsigned int alpha;
|
||||
} RGBA;
|
||||
|
||||
// Class for dealing with color gradients, mainly for the terrain and blend mapping
|
||||
class ColorGradient
|
||||
{
|
||||
public:
|
||||
ColorGradient(float min, float max, vector<RGBA> colorSteps);
|
||||
~ColorGradient();
|
||||
|
||||
// Get the RGBA value at the give point
|
||||
RGBA GetRGBAValue(float inputValue);
|
||||
|
||||
private:
|
||||
float _minValue;
|
||||
float _maxValue;
|
||||
|
||||
// Method for interpolating the color between each step
|
||||
RGBA Interpolate(RGBA a, RGBA b, float pointValue);
|
||||
|
||||
// Vector to hold the color steps in for the gradient
|
||||
vector<RGBA> _colorSteps;
|
||||
};
|
||||
|
@ -9,7 +9,7 @@ void Graphics2::CreateSceneGraph()
|
||||
_turnSpeed = 1;
|
||||
_invertPitch = -1;
|
||||
|
||||
GetCamera()->SetCameraPosition(0.0f, 320.0f, -80.0f);
|
||||
GetCamera()->SetCameraPosition(0.0f, 550.0f, -80.0f);
|
||||
|
||||
SceneGraphPointer sceneGraph = GetSceneGraph();
|
||||
|
||||
@ -18,15 +18,20 @@ void Graphics2::CreateSceneGraph()
|
||||
//cube->SetWorldTransform(XMMatrixScaling(5.0f, 8.0f, 2.5f) * XMMatrixTranslation(0, 23.0f, 0));
|
||||
//sceneGraph->Add(cube);
|
||||
|
||||
shared_ptr<TerrainNode> terrainNode = make_shared<TerrainNode>(L"MainTerrain", L"Textures\\Example_HeightMap.raw", 1023, 1023, 10, 10);
|
||||
shared_ptr<TerrainNode> terrainNode = make_shared<TerrainNode>(L"MainTerrain", L"Textures\\Example_HeightMap.raw", L"lovelycat");
|
||||
terrainNode->SetAmbientLight(XMFLOAT4(0.7f, 0.7f, 0.7f, 1.0f));
|
||||
terrainNode->SetDirectionalLight(XMVectorSet(0.5f, -1.0f, -1.0f, 0.0f), XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
terrainNode->SetWaterColor(XMFLOAT4(SharedMethods::RGBValueToIntensity(0xA4), SharedMethods::RGBValueToIntensity(0xC1), SharedMethods::RGBValueToIntensity(0xF9), 1.0f));
|
||||
//terrainNode->SetWaterColor(XMFLOAT4(1.0f, 0.0f, 0.8f, 1.0f));
|
||||
//terrainNode->SetWaterColor(XMFLOAT4(0.0f, 0.0f, 1.0f, 1.0f));
|
||||
sceneGraph->Add(terrainNode);
|
||||
|
||||
shared_ptr<SplitMeshNode> node = make_shared<SplitMeshNode>(L"Plane1", L"Models\\Plane\\Bonanza.3DS");
|
||||
//shared_ptr<MeshNode> node = make_shared<MeshNode>(L"Plane1", L"Models\\Plane\\Bonanza.3DS");
|
||||
node->SetWorldTransform(XMMatrixScaling(0.5f, 0.5f, 0.5f) * XMMatrixTranslation(-30.0f, 320.0f, 0));
|
||||
node->SetWorldTransform(XMMatrixTranslation(-30.0f, 520.0f, 0));
|
||||
sceneGraph->Add(node);
|
||||
|
||||
//SetBackgroundColour(XMFLOAT4(0.29f, 0.38f, 0.72f, 1.0f));
|
||||
SetBackgroundColour(XMFLOAT4(0.29f, 0.38f, 0.72f, 1.0f));
|
||||
//SetBackgroundColour(XMFLOAT4(SharedMethods::RGBValueToIntensity(0x89), 0, 1, 1));
|
||||
|
||||
_currentRotation = 0;
|
||||
|
@ -145,6 +145,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Camera.h" />
|
||||
<ClInclude Include="ColorGradient.h" />
|
||||
<ClInclude Include="Core.h" />
|
||||
<ClInclude Include="DDSTextureLoader.h" />
|
||||
<ClInclude Include="DirectXCore.h" />
|
||||
@ -152,10 +153,12 @@
|
||||
<ClInclude Include="DirectXFramework.h" />
|
||||
<ClInclude Include="GamePadController.h" />
|
||||
<ClInclude Include="Graphics2.h" />
|
||||
<ClInclude Include="HeightMapTerrainNode.h" />
|
||||
<ClInclude Include="HelperFunctions.h" />
|
||||
<ClInclude Include="Mesh.h" />
|
||||
<ClInclude Include="MeshNode.h" />
|
||||
<ClInclude Include="MeshRenderer.h" />
|
||||
<ClInclude Include="PerlinTerrainNode.h" />
|
||||
<ClInclude Include="Renderer.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="ResourceManager.h" />
|
||||
@ -168,7 +171,6 @@
|
||||
<ClInclude Include="targetver.h" />
|
||||
<ClInclude Include="TerrainNode.h" />
|
||||
<ClInclude Include="TexturedCubeNode.h" />
|
||||
<ClInclude Include="Vector3D.h" />
|
||||
<ClInclude Include="WICTextureLoader.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@ -185,14 +187,17 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Camera.cpp" />
|
||||
<ClCompile Include="ColorGradient.cpp" />
|
||||
<ClCompile Include="DDSTextureLoader.cpp" />
|
||||
<ClCompile Include="Framework.cpp" />
|
||||
<ClCompile Include="DirectXFramework.cpp" />
|
||||
<ClCompile Include="GamePadController.cpp" />
|
||||
<ClCompile Include="Graphics2.cpp" />
|
||||
<ClCompile Include="HeightMapTerrainNode.cpp" />
|
||||
<ClCompile Include="Mesh.cpp" />
|
||||
<ClCompile Include="MeshNode.cpp" />
|
||||
<ClCompile Include="MeshRenderer.cpp" />
|
||||
<ClCompile Include="PerlinTerrainNode.cpp" />
|
||||
<ClCompile Include="ResourceManager.cpp" />
|
||||
<ClCompile Include="SceneGraph.cpp" />
|
||||
<ClCompile Include="SharedMethods.cpp" />
|
||||
@ -201,7 +206,6 @@
|
||||
<ClCompile Include="SubMeshRenderer.cpp" />
|
||||
<ClCompile Include="TerrainNode.cpp" />
|
||||
<ClCompile Include="TexturedCubeNode.cpp" />
|
||||
<ClCompile Include="Vector3D.cpp" />
|
||||
<ClCompile Include="WICTextureLoader.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@ -93,7 +93,13 @@
|
||||
<ClInclude Include="DDSTextureLoader.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Vector3D.h">
|
||||
<ClInclude Include="ColorGradient.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="PerlinTerrainNode.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="HeightMapTerrainNode.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
@ -180,7 +186,13 @@
|
||||
<ClCompile Include="DDSTextureLoader.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Vector3D.cpp">
|
||||
<ClCompile Include="ColorGradient.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="PerlinTerrainNode.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="HeightMapTerrainNode.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
|
@ -12,12 +12,38 @@ float SharedMethods::RGBValueToIntensity(int value)
|
||||
return (float)value / 255.0f;
|
||||
}
|
||||
|
||||
float SharedMethods::lerp(int a, int b, int p)
|
||||
float SharedMethods::Lerp(int a, int b, int p)
|
||||
{
|
||||
return lerp((float)a, (float)b, (float)p);
|
||||
return Lerp((float)a, (float)b, (float)p);
|
||||
}
|
||||
|
||||
float SharedMethods::lerp(float a, float b, float p)
|
||||
float SharedMethods::Lerp(float a, float b, float p)
|
||||
{
|
||||
return a + p * (b - a);
|
||||
}
|
||||
|
||||
float SharedMethods::GenerateRandomIntensity(float min, float max)
|
||||
{
|
||||
float randNo = (float)rand() / (float)RAND_MAX;
|
||||
float rangeDiff = max - min;
|
||||
float actualNo = randNo * rangeDiff;
|
||||
int roundedNo = (int)(actualNo * 100 + 0.5f);
|
||||
return (float)roundedNo * 0.01f;
|
||||
}
|
||||
|
||||
float SharedMethods::GenerateRandomUV(int min, int max)
|
||||
{
|
||||
int randNo = rand() % ((max - min) + 1) + min;
|
||||
float finalNo;
|
||||
if (randNo < max)
|
||||
{
|
||||
int randMan = rand() % 90;
|
||||
finalNo = (float)(randNo * 0.1f) + (randMan * 0.01f);
|
||||
}
|
||||
else
|
||||
{
|
||||
finalNo = (float)randNo * 0.1f;
|
||||
}
|
||||
|
||||
return finalNo;
|
||||
}
|
@ -16,13 +16,33 @@ struct CBUFFER
|
||||
float padding[2];
|
||||
};
|
||||
|
||||
struct TCBUFFER
|
||||
{
|
||||
XMMATRIX completeTransformation;
|
||||
XMMATRIX worldTransformation;
|
||||
XMFLOAT4 cameraPosition;
|
||||
XMVECTOR lightVector;
|
||||
XMFLOAT4 lightColor;
|
||||
XMFLOAT4 ambientColor;
|
||||
XMFLOAT4 diffuseCoefficient;
|
||||
XMFLOAT4 specularCoefficient;
|
||||
float shininess;
|
||||
float opacity;
|
||||
float waterHeight;
|
||||
float waterShininess;
|
||||
XMFLOAT4 waterColor;
|
||||
float padding[4];
|
||||
};
|
||||
|
||||
namespace SharedMethods
|
||||
{
|
||||
XMMATRIX RotateFromPoint(float x, float y, float z, XMMATRIX rotationMatrix);
|
||||
|
||||
float RGBValueToIntensity(int value);
|
||||
float lerp(int a, int b, int p);
|
||||
float lerp(float a, float b, float p);
|
||||
float Lerp(int a, int b, int p);
|
||||
float Lerp(float a, float b, float p);
|
||||
|
||||
float GenerateRandomIntensity(float min, float max);
|
||||
float GenerateRandomUV(int min, int max);
|
||||
};
|
||||
|
||||
|
@ -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()
|
||||
));
|
||||
}
|
@ -1,15 +1,31 @@
|
||||
#pragma once
|
||||
#include "DirectXFramework.h"
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include "ColorGradient.h"
|
||||
#include "DDSTextureLoader.h"
|
||||
#include "WICTextureLoader.h"
|
||||
#include "SharedMethods.h"
|
||||
#include "SceneNode.h"
|
||||
#include "Vector3D.h"
|
||||
|
||||
|
||||
typedef struct TerrainVertex
|
||||
{
|
||||
XMFLOAT3 Position;
|
||||
XMFLOAT3 Normal;
|
||||
XMFLOAT2 TexCoord;
|
||||
XMFLOAT2 BlendMapTexCoord;
|
||||
} TerrainVertex;
|
||||
|
||||
class TerrainNode : public SceneNode
|
||||
{
|
||||
public:
|
||||
TerrainNode(wstring name, wstring heightMap, int widthX = 1023, int widthZ = 1023, int rows = 10, int cols = 10);
|
||||
TerrainNode(wstring name, wstring heightMap, wstring seed, float waterHeight = 150.0f, wstring waterNormalMap = L"Textures\\waterNormals.bmp", int widthX = 1023, int widthZ = 1023, int cellSizeX = 10, int cellSizeZ = 10);
|
||||
|
||||
void SetAmbientLight(XMFLOAT4 ambientLight);
|
||||
void SetWaterColor(XMFLOAT4 waterColor);
|
||||
void SetDirectionalLight(FXMVECTOR lightVector, XMFLOAT4 lightColor);
|
||||
void SetCameraPosition(XMFLOAT4 cameraPosition);
|
||||
|
||||
bool Initialise(void);
|
||||
void Render(void);
|
||||
@ -19,14 +35,16 @@ private:
|
||||
int _widthX;
|
||||
int _widthZ;
|
||||
|
||||
UINT _gridRows;
|
||||
UINT _gridCols;
|
||||
unsigned int _gridRows;
|
||||
unsigned int _gridCols;
|
||||
|
||||
int _cellSizeX;
|
||||
int _cellSizeZ;
|
||||
|
||||
bool _usedHeightMap;
|
||||
|
||||
float _waterHeight;
|
||||
|
||||
UINT _polygonsCount;
|
||||
UINT _indiciesCount;
|
||||
UINT _vertexCount;
|
||||
@ -37,12 +55,12 @@ private:
|
||||
float _terrainEndZ;
|
||||
|
||||
wstring _heightMap;
|
||||
wstring _textureName;
|
||||
wstring _seedString;
|
||||
unsigned int _seedHash;
|
||||
|
||||
vector<VERTEX> _terrainVerts;
|
||||
vector<TerrainVertex> _terrainVerts;
|
||||
vector<int> _indices;
|
||||
vector<float> _heightValues;
|
||||
vector<Vector3D> _terrainNormals;
|
||||
|
||||
XMFLOAT4 _ambientLight;
|
||||
XMFLOAT4 _directionalLightVector;
|
||||
@ -62,24 +80,31 @@ private:
|
||||
ComPtr<ID3D11InputLayout> _layout;
|
||||
ComPtr<ID3D11Buffer> _constantBuffer;
|
||||
|
||||
ComPtr<ID3D11ShaderResourceView> _texture;
|
||||
|
||||
ComPtr<ID3D11BlendState> _transparentBlendState;
|
||||
ComPtr<ID3D11ShaderResourceView> _texturesResourceView;
|
||||
ComPtr<ID3D11ShaderResourceView> _blendMapResourceView;
|
||||
|
||||
ComPtr<ID3D11RasterizerState> _defaultRasteriserState;
|
||||
ComPtr<ID3D11RasterizerState> _wireframeRasteriserState;
|
||||
|
||||
ComPtr<ID3D11ShaderResourceView> _rngNoiseMap;
|
||||
ComPtr<ID3D11ShaderResourceView> _waterNormalMap;
|
||||
wstring _waterNormalMapName;
|
||||
XMFLOAT4 _waterColor;
|
||||
|
||||
void GenerateTerrainData();
|
||||
void GenerateBuffers();
|
||||
void BuildShaders();
|
||||
void BuildVertexLayout();
|
||||
void BuildConstantBuffer();
|
||||
void BuildBlendState();
|
||||
void BuildRendererStates();
|
||||
void BuildTexture();
|
||||
|
||||
void LoadTerrainTextures();
|
||||
void GenerateBlendMap();
|
||||
|
||||
bool LoadHeightMap(wstring heightMapFilename);
|
||||
float GetHeightMapValueAt(int index);
|
||||
|
||||
void AddNormalToVertex(int row, int col, int vertexIndex, Vector3D normal);
|
||||
void AddNormalToVertex(int row, int col, int vertexIndex, XMVECTOR normal);
|
||||
void BuildExtraMaps();
|
||||
};
|
||||
|
||||
|
@ -10,11 +10,17 @@ cbuffer ConstantBuffer
|
||||
float4 specularCoefficient; // The specular reflection cooefficient
|
||||
float shininess; // The shininess factor
|
||||
float opacity; // The opacity (transparency) of the material. 0 = fully transparent, 1 = fully opaque
|
||||
float2 padding;
|
||||
|
||||
float waterHeight;
|
||||
float waterShininess;
|
||||
float4 waterColor;
|
||||
float padding[4];
|
||||
}
|
||||
|
||||
Texture2D BlendMap : register(t0);
|
||||
Texture2DArray TexturesArray : register(t1);
|
||||
Texture2D WaterNormalMap : register(t2);
|
||||
Texture2D rngNoiseMap : register(t3);
|
||||
|
||||
SamplerState ss
|
||||
{
|
||||
@ -41,10 +47,26 @@ struct PixelShaderInput
|
||||
float2 BlendMapTexCoord : TEXCOORD1;
|
||||
};
|
||||
|
||||
float2 UVRotate(float2 uvCoord, float2 pivotPoint, float rotation)
|
||||
{
|
||||
float2x2 rotateMatrix = float2x2(float2(sin(rotation), -cos(rotation)), float2(cos(rotation), sin(rotation)));
|
||||
|
||||
uvCoord -= pivotPoint;
|
||||
uvCoord = mul(uvCoord, rotateMatrix);
|
||||
uvCoord += pivotPoint;
|
||||
|
||||
return uvCoord;
|
||||
|
||||
}
|
||||
|
||||
PixelShaderInput VShader(VertexShaderInput vin)
|
||||
{
|
||||
PixelShaderInput output;
|
||||
PixelShaderInput output;
|
||||
float3 position = vin.Position;
|
||||
if (position.y < waterHeight)
|
||||
{
|
||||
position.y = waterHeight - 0.01f;
|
||||
}
|
||||
output.Position = mul(completeTransformation, float4(position, 1.0f));
|
||||
output.PositionWS = mul(worldTransformation, float4(position, 1.0f));
|
||||
output.NormalWS = float4(mul((float3x3)worldTransformation, vin.Normal), 1.0f);
|
||||
@ -53,12 +75,25 @@ PixelShaderInput VShader(VertexShaderInput vin)
|
||||
return output;
|
||||
}
|
||||
|
||||
float4 hash4(float2 v)
|
||||
{
|
||||
float4 p = mul(float4x2(127.1, 311.7, 269.5, 183.3, 113.5, 271.9, 246.1, 124.6), v);
|
||||
return frac(sin(p) * 43758.5453123);
|
||||
}
|
||||
|
||||
float4 PShader(PixelShaderInput input) : SV_TARGET
|
||||
{
|
||||
float4 directionToCamera = normalize(input.PositionWS - cameraPosition);
|
||||
float4 directionToLight = normalize(-lightVector);
|
||||
float surfaceShininess = shininess;
|
||||
float4 adjustedNormal = normalize(input.NormalWS);
|
||||
if (input.PositionWS.y < waterHeight)
|
||||
{
|
||||
float3 n0 = (float3)WaterNormalMap.Sample(ss, input.TexCoord);
|
||||
float4 n2 = float4(mul((float3x3)worldTransformation, n0), 1.0f);
|
||||
adjustedNormal = n2;
|
||||
surfaceShininess = waterShininess;
|
||||
}
|
||||
|
||||
// Calculate diffuse lighting
|
||||
float NdotL = max(0, dot(adjustedNormal, directionToLight));
|
||||
@ -74,16 +109,34 @@ float4 PShader(PixelShaderInput input) : SV_TARGET
|
||||
// Calculate ambient lighting
|
||||
float4 ambientLight = ambientColor * diffuseCoefficient;
|
||||
float4 color;
|
||||
|
||||
float4 randSamp = rngNoiseMap.Sample(ss, input.BlendMapTexCoord);
|
||||
|
||||
// Sample layers in texture array.
|
||||
float4 c0 = TexturesArray.Sample(ss, float3(input.TexCoord, 0.0f));
|
||||
float4 c1 = TexturesArray.Sample(ss, float3(input.TexCoord, 1.0f));
|
||||
float4 c2 = TexturesArray.Sample(ss, float3(input.TexCoord, 2.0f));
|
||||
float4 c3 = TexturesArray.Sample(ss, float3(input.TexCoord, 3.0f));
|
||||
float4 c4 = TexturesArray.Sample(ss, float3(input.TexCoord, 4.0f));
|
||||
float2 scaleCenter = float2(0.5f, 0.5f);
|
||||
float currentScale = randSamp.r;
|
||||
float2 scaledUV = frac(UVRotate(input.TexCoord, scaleCenter, currentScale)); // (input.TexCoord - scaleCenter) * currentScale + scaleCenter;
|
||||
|
||||
float2 xChange = ddx(scaledUV);
|
||||
float2 yChange = ddy(scaledUV);
|
||||
|
||||
/*if (xChange.x < 0)
|
||||
{
|
||||
xChange = float2(0, 0);
|
||||
}
|
||||
if (yChange.y < 0)
|
||||
{
|
||||
yChange = float2(0, 0);
|
||||
}*/
|
||||
|
||||
// Sample layers in texture array.
|
||||
float4 c0 = TexturesArray.SampleGrad(ss, float3(scaledUV, 0.0f), xChange, yChange);
|
||||
float4 c1 = TexturesArray.SampleGrad(ss, float3(scaledUV, 1.0f), xChange, yChange);
|
||||
float4 c2 = TexturesArray.SampleGrad(ss, float3(scaledUV, 2.0f), xChange, yChange);
|
||||
float4 c3 = TexturesArray.SampleGrad(ss, float3(scaledUV, 3.0f), xChange, yChange);
|
||||
float4 c4 = TexturesArray.SampleGrad(ss, float3(scaledUV, 4.0f), xChange, yChange);
|
||||
|
||||
// Sample the blend map.
|
||||
float4 t = BlendMap.Sample(ss, input.BlendMapTexCoord);
|
||||
float4 t = BlendMap.Sample(ss, input.BlendMapTexCoord);
|
||||
|
||||
// Blend the layers on top of each other.
|
||||
color = c0;
|
||||
@ -93,7 +146,11 @@ float4 PShader(PixelShaderInput input) : SV_TARGET
|
||||
color = lerp(color, c4, t.a);
|
||||
|
||||
// Combine all components
|
||||
if (input.PositionWS.y < waterHeight)
|
||||
{
|
||||
color = color * waterColor;
|
||||
}
|
||||
color = (ambientLight + diffuse) * color;
|
||||
color = saturate(color + specular);
|
||||
color = saturate(color + specular);
|
||||
return color;
|
||||
}
|
BIN
Graphics2/Textures/noiseMap.bmp
Normal file
BIN
Graphics2/Textures/noiseMap.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.0 MiB |
BIN
Graphics2/Textures/noiseMap.png
Normal file
BIN
Graphics2/Textures/noiseMap.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 MiB |
BIN
Graphics2/Textures/waterNormals.bmp
Normal file
BIN
Graphics2/Textures/waterNormals.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 269 KiB |
@ -1,104 +0,0 @@
|
||||
#include "Vector3D.h"
|
||||
|
||||
Vector3D::Vector3D(float x, float y, float z)
|
||||
{
|
||||
_vector.x = x;
|
||||
_vector.y = y;
|
||||
_vector.z = z;
|
||||
}
|
||||
|
||||
Vector3D::Vector3D(XMFLOAT3 vertexA, XMFLOAT3 vertexB)
|
||||
{
|
||||
_vector.x = vertexB.x - vertexA.x;
|
||||
_vector.y = vertexB.y - vertexA.y;
|
||||
_vector.z = vertexB.z - vertexA.z;
|
||||
}
|
||||
|
||||
Vector3D::Vector3D(const Vector3D& other)
|
||||
{
|
||||
Copy(other);
|
||||
}
|
||||
|
||||
Vector3D::~Vector3D()
|
||||
{
|
||||
}
|
||||
|
||||
XMFLOAT3 Vector3D::Get() const
|
||||
{
|
||||
return _vector;
|
||||
}
|
||||
|
||||
const void Vector3D::Normalize()
|
||||
{
|
||||
float length = (float) sqrt((_vector.x * _vector.x) + (_vector.y + _vector.y) + (_vector.z * _vector.z));
|
||||
|
||||
if (length != 0)
|
||||
{
|
||||
_vector.x /= length;
|
||||
_vector.y /= length;
|
||||
_vector.z /= length;
|
||||
}
|
||||
}
|
||||
|
||||
float Vector3D::DotProduct(const Vector3D v1, const Vector3D v2)
|
||||
{
|
||||
return v1.Get().x * v2.Get().x + v1.Get().y * v2.Get().y + v1.Get().z * v2.Get().z;
|
||||
}
|
||||
|
||||
float Vector3D::Length(const Vector3D v1, const Vector3D v2)
|
||||
{
|
||||
return (float)sqrt(pow((v1.Get().x - v2.Get().x), 2) + pow((v1.Get().y - v2.Get().y), 2) + pow((v1.Get().z - v2.Get().z), 2));
|
||||
}
|
||||
|
||||
Vector3D Vector3D::CrossProduct(Vector3D v1, Vector3D v2)
|
||||
{
|
||||
// v1.GetY() * v2.GetZ() - v1.GetZ() * v2.GetY()
|
||||
float crossedX = v1.Get().y * v2.Get().z - v1.Get().z * v2.Get().y;
|
||||
|
||||
// v1.GetZ() * v2.GetX() - v1.GetX() * v2.GetZ()
|
||||
float crossedY = v1.Get().z * v2.Get().x - v1.Get().x * v2.Get().z;
|
||||
|
||||
// v1.GetX() * v2.GetY() - v1.GetY() * v2.GetX()
|
||||
float crossedZ = v1.Get().x * v2.Get().y - v1.Get().y * v2.Get().x;
|
||||
|
||||
return Vector3D(crossedX, crossedY, crossedZ);
|
||||
}
|
||||
|
||||
Vector3D& Vector3D::operator= (const Vector3D& rhs)
|
||||
{
|
||||
if (this != &rhs)
|
||||
{
|
||||
Copy(rhs);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
const Vector3D Vector3D::operator+ (const Vector3D& rhs) const
|
||||
{
|
||||
return Vector3D(_vector.x + rhs.Get().x, _vector.y + rhs.Get().y, _vector.z + rhs.Get().z);
|
||||
}
|
||||
|
||||
Vector3D& Vector3D::operator+= (const Vector3D& rhs)
|
||||
{
|
||||
_vector.x += rhs.Get().x;
|
||||
_vector.y += rhs.Get().y;
|
||||
_vector.z += rhs.Get().z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const Vector3D Vector3D::operator/ (const float rhs) const
|
||||
{
|
||||
return Vector3D(_vector.x / rhs, _vector.y / rhs, _vector.z / rhs);
|
||||
}
|
||||
|
||||
const Vector3D Vector3D::operator/ (const int rhs) const
|
||||
{
|
||||
return Vector3D(_vector.x / rhs, _vector.y / rhs, _vector.z / rhs);
|
||||
}
|
||||
|
||||
void Vector3D::Copy(const Vector3D& other)
|
||||
{
|
||||
_vector.x = other.Get().x;
|
||||
_vector.y = other.Get().y;
|
||||
_vector.z = other.Get().z;
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
#pragma once
|
||||
#include "DirectXFramework.h"
|
||||
#include "SharedMethods.h"
|
||||
|
||||
class Vector3D
|
||||
{
|
||||
public:
|
||||
Vector3D(float x, float y, float z);
|
||||
Vector3D(XMFLOAT3 vertexA, XMFLOAT3 vertexB);
|
||||
Vector3D(const Vector3D& other);
|
||||
|
||||
~Vector3D();
|
||||
|
||||
XMFLOAT3 Get() const;
|
||||
const void Normalize();
|
||||
|
||||
static float DotProduct(const Vector3D v1, const Vector3D v2);
|
||||
static float Length(const Vector3D v1, const Vector3D v2);
|
||||
static Vector3D CrossProduct(const Vector3D v1, const Vector3D v2);
|
||||
|
||||
Vector3D& operator= (const Vector3D& rhs);
|
||||
const Vector3D operator+ (const Vector3D& rhs) const;
|
||||
Vector3D& operator+= (const Vector3D& rhs);
|
||||
const Vector3D operator/ (const float rhs) const;
|
||||
const Vector3D operator/ (const int rhs) const;
|
||||
|
||||
|
||||
private:
|
||||
XMFLOAT3 _vector;
|
||||
|
||||
void Copy(const Vector3D& other);
|
||||
};
|
||||
|
Reference in New Issue
Block a user