diff --git a/Graphics2/Camera.cpp b/Graphics2/Camera.cpp index fa59962..c18f52a 100644 --- a/Graphics2/Camera.cpp +++ b/Graphics2/Camera.cpp @@ -1,17 +1,16 @@ #include "Camera.h" -XMVECTOR defaultForward = XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f); -XMVECTOR defaultRight = XMVectorSet(1.0f, 0.0f, 0.0f, 0.0f); -XMVECTOR defaultUp = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f); - Camera::Camera() { + _nodeFollowed = nullptr; _cameraPosition = XMFLOAT4(0.0f, 0.0f, 0.0f, 0.0f); _moveLeftRight = 0.0f; _moveForwardBack = 0.0f; _cameraYaw = 0.0f; _cameraPitch = 0.0f; _cameraRoll = 0.0f; + _followPositionOnly = false; + _followOffset = XMFLOAT3(0.0f, 0.0f, 0.0f); } Camera::~Camera() @@ -83,14 +82,28 @@ XMVECTOR Camera::GetCameraPosition(void) return XMLoadFloat4(&_cameraPosition); } -XMFLOAT4 Camera::GetRawCameraPosition(void) -{ - return _cameraPosition; -} - void Camera::SetCameraPosition(float x, float y, float z) { - _cameraPosition = XMFLOAT4(x, y, z, 0.0f); + SetCameraPosition(XMFLOAT4(x, y, z, 0.0f)); +} + +void Camera::SetCameraPosition(XMVECTOR vectorIn) +{ + XMFLOAT4 floatIn; + XMStoreFloat4(&floatIn, vectorIn); + SetCameraPosition(floatIn); +} + +void Camera::SetCameraPosition(XMFLOAT4 floatIn) +{ + _cameraPosition = floatIn; +} + +void Camera::SetFollowNode(shared_ptr nodeFollowed, XMFLOAT3 followOffset, bool positionOnly) +{ + _nodeFollowed = nodeFollowed; + _followOffset = followOffset; + _followPositionOnly = positionOnly; } void Camera::Update(void) @@ -101,31 +114,84 @@ void Camera::Update(void) XMVECTOR cameraForward; XMVECTOR cameraUp; - // Yaw (rotation around the Y axis) will have an impact on the forward and right vectors - XMMATRIX cameraRotationYaw = XMMatrixRotationAxis(defaultUp, _cameraYaw); - cameraRight = XMVector3TransformCoord(defaultRight, cameraRotationYaw); - cameraForward = XMVector3TransformCoord(defaultForward, cameraRotationYaw); + XMVECTOR defaultForward = XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f); + XMVECTOR defaultRight = XMVectorSet(1.0f, 0.0f, 0.0f, 0.0f); + XMVECTOR defaultUp = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f); - // Pitch (rotation around the X axis) impact the up and forward vectors - XMMATRIX cameraRotationPitch = XMMatrixRotationAxis(cameraRight, _cameraPitch); - cameraUp = XMVector3TransformCoord(defaultUp, cameraRotationPitch); - cameraForward = XMVector3TransformCoord(cameraForward, cameraRotationPitch); + if (_nodeFollowed == nullptr) + { + // Yaw (rotation around the Y axis) will have an impact on the forward and right vectors + XMMATRIX cameraRotationYaw = XMMatrixRotationAxis(defaultUp, _cameraYaw); + cameraRight = XMVector3TransformCoord(defaultRight, cameraRotationYaw); + cameraForward = XMVector3TransformCoord(defaultForward, cameraRotationYaw); - // Roll (rotation around the Z axis) will impact the Up and Right vectors - XMMATRIX cameraRotationRoll = XMMatrixRotationAxis(cameraForward, _cameraRoll); - cameraUp = XMVector3TransformCoord(cameraUp, cameraRotationRoll); - cameraRight = XMVector3TransformCoord(cameraRight, cameraRotationRoll); + // Pitch (rotation around the X axis) impact the up and forward vectors + XMMATRIX cameraRotationPitch = XMMatrixRotationAxis(cameraRight, _cameraPitch); + cameraUp = XMVector3TransformCoord(defaultUp, cameraRotationPitch); + cameraForward = XMVector3TransformCoord(cameraForward, cameraRotationPitch); - // Adjust the camera position by the appropriate amount forward/back and left/right - cameraPosition = XMLoadFloat4(&_cameraPosition) + _moveLeftRight * cameraRight + _moveForwardBack * cameraForward; - XMStoreFloat4(&_cameraPosition, cameraPosition); + // Roll (rotation around the Z axis) will impact the Up and Right vectors + XMMATRIX cameraRotationRoll = XMMatrixRotationAxis(cameraForward, _cameraRoll); + cameraUp = XMVector3TransformCoord(cameraUp, cameraRotationRoll); + cameraRight = XMVector3TransformCoord(cameraRight, cameraRotationRoll); - // Reset the amount we are moving - _moveLeftRight = 0.0f; - _moveForwardBack = 0.0f; + // Adjust the camera position by the appropriate amount forward/back and left/right + cameraPosition = XMLoadFloat4(&_cameraPosition) + _moveLeftRight * cameraRight + _moveForwardBack * cameraForward; + XMStoreFloat4(&_cameraPosition, cameraPosition); - // Calculate a vector that tells us the direction the camera is looking in - cameraTarget = cameraPosition + XMVector3Normalize(cameraForward); + // Reset the amount we are moving + _moveLeftRight = 0.0f; + _moveForwardBack = 0.0f; + + // Calculate a vector that tells us the direction the camera is looking in + cameraTarget = cameraPosition + XMVector3Normalize(cameraForward); + } + else + { + if (_followPositionOnly) + { + _cameraYaw = 0.0f; + _cameraPitch = 0.0f; + _cameraRoll = 0.0f; + } + else + { + _cameraYaw = XMConvertToRadians(_nodeFollowed->GetYaw()); + _cameraPitch = XMConvertToRadians(_nodeFollowed->GetPitch()); + _cameraRoll = XMConvertToRadians(_nodeFollowed->GetRoll()); + } + + // Yaw (rotation around the Y axis) will have an impact on the forward and right vectors + XMMATRIX cameraRotationYaw = XMMatrixRotationAxis(defaultUp, _cameraYaw); + cameraRight = XMVector3TransformCoord(defaultRight, cameraRotationYaw); + cameraForward = XMVector3TransformCoord(defaultForward, cameraRotationYaw); + + // Pitch (rotation around the X axis) impact the up and forward vectors + XMMATRIX cameraRotationPitch = XMMatrixRotationAxis(cameraRight, _cameraPitch); + cameraUp = XMVector3TransformCoord(defaultUp, cameraRotationPitch); + cameraForward = XMVector3TransformCoord(cameraForward, cameraRotationPitch); + + // Roll (rotation around the Z axis) will impact the Up and Right vectors + XMMATRIX cameraRotationRoll = XMMatrixRotationAxis(cameraForward, _cameraRoll); + cameraUp = XMVector3TransformCoord(cameraUp, cameraRotationRoll); + cameraRight = XMVector3TransformCoord(cameraRight, cameraRotationRoll); + + XMFLOAT4 nodePosition; + XMStoreFloat4(&nodePosition, _nodeFollowed->GetNodePosition()); + if (_followPositionOnly) + { + cameraPosition = XMVectorSet(nodePosition.x + _followOffset.x, nodePosition.y + _followOffset.y, nodePosition.z + _followOffset.z, 1.0f); + cameraTarget = cameraPosition + XMVector3Normalize(cameraForward); + } + else + { + XMVECTOR offset = XMVectorSet(_followOffset.x, _followOffset.y, _followOffset.z, 1.0f); + cameraPosition = _nodeFollowed->GetNodePosition() + offset; + cameraTarget = XMLoadFloat4(&nodePosition) + XMVector3Normalize(cameraForward); + } + // Set the camera position + XMStoreFloat4(&_cameraPosition, cameraPosition); + } // and calculate our view matrix XMStoreFloat4x4(&_viewMatrix, XMMatrixLookAtLH(cameraPosition, cameraTarget, cameraUp)); diff --git a/Graphics2/Camera.h b/Graphics2/Camera.h index 14b9e0b..10f5f8e 100644 --- a/Graphics2/Camera.h +++ b/Graphics2/Camera.h @@ -1,6 +1,8 @@ #pragma once #include "core.h" #include "DirectXCore.h" +#include "SharedMethods.h" +#include "ObjectNode.h" class Camera { @@ -11,7 +13,8 @@ public: void Update(); XMMATRIX GetViewMatrix(); XMVECTOR GetCameraPosition(); - XMFLOAT4 GetRawCameraPosition(); + void SetCameraPosition(XMVECTOR vectorIn); + void SetCameraPosition(XMFLOAT4 floatIn); void SetCameraPosition(float x, float y, float z); void SetPitch(float pitch); void SetTotalPitch(float pitch); @@ -24,6 +27,7 @@ public: float GetRoll() const; void SetLeftRight(float leftRight); void SetForwardBack(float forwardBack); + void SetFollowNode(shared_ptr nodeFollowed, XMFLOAT3 followOffset, bool positionOnly); private: XMFLOAT4 _cameraPosition; @@ -37,5 +41,8 @@ private: float _cameraPitch; float _cameraRoll; + shared_ptr _nodeFollowed; + XMFLOAT3 _followOffset; + bool _followPositionOnly; }; diff --git a/Graphics2/ColorGradient.cpp b/Graphics2/ColorGradient.cpp index 40f8faa..8563a68 100644 --- a/Graphics2/ColorGradient.cpp +++ b/Graphics2/ColorGradient.cpp @@ -15,6 +15,7 @@ ColorGradient::~ColorGradient() // Get the RGBA value at the give point RGBA ColorGradient::GetRGBAValue(float inputValue) { + // Check if we are at the start or end, return those values if so if (inputValue <= _minValue) { return _colorSteps.front(); @@ -24,10 +25,12 @@ RGBA ColorGradient::GetRGBAValue(float inputValue) return _colorSteps.back(); } + // Get the point which the input value is at between the entire range float range = _maxValue - _minValue; float value = inputValue - _minValue; float steps = range / (float)(_colorSteps.size() - 1); + // Which gradient step are we in int colorStepInside = (int)(value / steps); float normalisedValue = (value - (colorStepInside * steps)) / steps; @@ -38,6 +41,7 @@ RGBA ColorGradient::GetRGBAValue(float inputValue) // Method for interpolating the color between each step RGBA ColorGradient::Interpolate(RGBA a, RGBA b, float pointValue) { + // Check if we are at the start or end, return those values if so if (pointValue <= 0.0f) { return a; @@ -47,10 +51,13 @@ RGBA ColorGradient::Interpolate(RGBA a, RGBA b, float pointValue) 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); + //pointValue = SharedMethods::Clamp(pointValue * 1.5f, 0.0f, 1.0f); + + // Lerp the color values for each channel between the steps + unsigned int currentRed = (unsigned int)SharedMethods::Lerp(a.red, b.red, pointValue); + unsigned int currentGreen = (unsigned int)SharedMethods::Lerp(a.green, b.green, pointValue); + unsigned int currentBlue = (unsigned int)SharedMethods::Lerp(a.blue, b.blue, pointValue); + unsigned int currentAlpha = (unsigned int)SharedMethods::Lerp(a.alpha, b.alpha, pointValue); return RGBA{ currentRed, currentGreen, currentBlue, currentAlpha }; } \ No newline at end of file diff --git a/Graphics2/ColorGradient.h b/Graphics2/ColorGradient.h index dde9b12..a697713 100644 --- a/Graphics2/ColorGradient.h +++ b/Graphics2/ColorGradient.h @@ -1,5 +1,6 @@ #pragma once #include +#include "SharedMethods.h" using namespace std; diff --git a/Graphics2/ControlledMeshNode.cpp b/Graphics2/ControlledMeshNode.cpp new file mode 100644 index 0000000..4e1bc4c --- /dev/null +++ b/Graphics2/ControlledMeshNode.cpp @@ -0,0 +1,24 @@ +#include "ControlledMeshNode.h" + +ControlledMeshNode::ControlledMeshNode(wstring name, wstring modelName) : MeshNode(name, modelName), ObjectNode() +{ +} + +void ControlledMeshNode::Update(FXMMATRIX& currentWorldTransformation) +{ + ObjectNode::Update(_worldTransformation); +} + +bool ControlledMeshNode::Initialise(void) +{ + if (!MeshNode::Initialise()) + { + return false; + } + return true; +} + +XMMATRIX ControlledMeshNode::GetWorldTransformation() const +{ + return XMLoadFloat4x4(&_combinedWorldTransformation); +} \ No newline at end of file diff --git a/Graphics2/ControlledMeshNode.h b/Graphics2/ControlledMeshNode.h new file mode 100644 index 0000000..93c131f --- /dev/null +++ b/Graphics2/ControlledMeshNode.h @@ -0,0 +1,18 @@ +#pragma once +#include "ObjectNode.h" +#include "MeshNode.h" + +class ControlledMeshNode : public MeshNode, public ObjectNode +{ +public: + ControlledMeshNode(wstring name, wstring modelName); + + void Update(FXMMATRIX& currentWorldTransformation); + bool Initialise(void); + + XMMATRIX GetWorldTransformation() const; + +private: + +}; + diff --git a/Graphics2/ControlledSplitMeshNode.cpp b/Graphics2/ControlledSplitMeshNode.cpp new file mode 100644 index 0000000..c75eda1 --- /dev/null +++ b/Graphics2/ControlledSplitMeshNode.cpp @@ -0,0 +1,25 @@ +#include "ControlledSplitMeshNode.h" + +ControlledSplitMeshNode::ControlledSplitMeshNode(wstring name, wstring modelName) : SplitMeshNode(name, modelName), ObjectNode() +{ +} + +void ControlledSplitMeshNode::Update(FXMMATRIX& currentWorldTransformation) +{ + ObjectNode::Update(_worldTransformation); + SceneGraph::Update(currentWorldTransformation); +} + +bool ControlledSplitMeshNode::Initialise(void) +{ + if (!SplitMeshNode::Initialise()) + { + return false; + } + return true; +} + +XMMATRIX ControlledSplitMeshNode::GetWorldTransformation() const +{ + return XMLoadFloat4x4(&_combinedWorldTransformation); +} \ No newline at end of file diff --git a/Graphics2/ControlledSplitMeshNode.h b/Graphics2/ControlledSplitMeshNode.h new file mode 100644 index 0000000..a9ad32a --- /dev/null +++ b/Graphics2/ControlledSplitMeshNode.h @@ -0,0 +1,20 @@ +#pragma once +#include "DirectXFramework.h" +#include "SplitMeshNode.h" +#include "ObjectNode.h" +#include "SubMeshNode.h" + +class ControlledSplitMeshNode : public SplitMeshNode, public ObjectNode +{ +public: + ControlledSplitMeshNode(wstring name, wstring modelName); + + void Update(FXMMATRIX& currentWorldTransformation); + bool Initialise(void); + + XMMATRIX GetWorldTransformation() const; + +private: + +}; + diff --git a/Graphics2/DirectXFramework.cpp b/Graphics2/DirectXFramework.cpp index 963d3f9..24b95ae 100644 --- a/Graphics2/DirectXFramework.cpp +++ b/Graphics2/DirectXFramework.cpp @@ -67,6 +67,7 @@ bool DirectXFramework::Initialise() _resourceManager = make_shared(); _sceneGraph = make_shared(); _camera = make_shared(); + _globalLighting = make_shared(); CreateSceneGraph(); return _sceneGraph->Initialise(); diff --git a/Graphics2/DirectXFramework.h b/Graphics2/DirectXFramework.h index 8a5a156..bb74d13 100644 --- a/Graphics2/DirectXFramework.h +++ b/Graphics2/DirectXFramework.h @@ -5,6 +5,7 @@ #include "ResourceManager.h" #include "SceneGraph.h" #include "Camera.h" +#include "GlobalLighting.h" class DirectXFramework : public Framework { @@ -34,6 +35,7 @@ public: void SetBackgroundColour(XMFLOAT4 backgroundColour); inline shared_ptr GetCamera() { return _camera; } + inline shared_ptr GetGlobalLighting() { return _globalLighting; } private: ComPtr _device; @@ -60,5 +62,6 @@ private: shared_ptr _resourceManager; shared_ptr _camera; + shared_ptr _globalLighting; }; diff --git a/Graphics2/GamePadController.cpp b/Graphics2/GamePadController.cpp index d93ed2a..9a3753f 100644 --- a/Graphics2/GamePadController.cpp +++ b/Graphics2/GamePadController.cpp @@ -11,7 +11,7 @@ GamePadController::~GamePadController(void) { } -void GamePadController::ProcessGameController() +void GamePadController::ProcessGameController(set& currentInputs, bool &boostHit) { DWORD magnitudeSquared; @@ -40,11 +40,29 @@ void GamePadController::ProcessGameController() // check if the controller is inside a circular dead zone. We do it this way to avoid having to // take the square root of the magnitude above. if (magnitudeSquared <= _leftThumbDeadZoneSquared) - { + { thumbLX = 0; thumbLY = 0; } + if (thumbLY > 0) + { + currentInputs.insert(ControlInputs::Forward); + } + else if (thumbLY < 0) + { + currentInputs.insert(ControlInputs::Back); + } + + if (thumbLX > 0) + { + currentInputs.insert(ControlInputs::StrafeRight); + } + else if (thumbLX < 0) + { + currentInputs.insert(ControlInputs::StrafeLeft); + } + // Deal with the right thumb stick SHORT thumbRX = _controllerState.Gamepad.sThumbRX; SHORT thumbRY = _controllerState.Gamepad.sThumbRY; @@ -59,36 +77,64 @@ void GamePadController::ProcessGameController() thumbRY = 0; } + if (thumbRY > 0) + { + currentInputs.insert(ControlInputs::Up); + } + else if (thumbRY < 0) + { + currentInputs.insert(ControlInputs::Down); + } + + if (thumbRX > 0) + { + currentInputs.insert(ControlInputs::TurnRight); + } + else if (thumbRX < 0) + { + currentInputs.insert(ControlInputs::TurnLeft); + } + // Check left and right triggers BYTE leftTrigger = _controllerState.Gamepad.bLeftTrigger; if (leftTrigger <= XINPUT_GAMEPAD_TRIGGER_THRESHOLD) - { + { leftTrigger = 0; } + if (leftTrigger > 0) + { + boostHit = true; + } + BYTE rightTrigger = _controllerState.Gamepad.bRightTrigger; if (rightTrigger <= XINPUT_GAMEPAD_TRIGGER_THRESHOLD) - { + { rightTrigger = 0; } + if (rightTrigger) + { + currentInputs.insert(ControlInputs::Fire2); + } + // Test the different digital buttons WORD buttons = _controllerState.Gamepad.wButtons; if (buttons & XINPUT_GAMEPAD_DPAD_UP) { - // Directional pad up pressed + currentInputs.insert(ControlInputs::Forward); } if (buttons & XINPUT_GAMEPAD_DPAD_DOWN) { - // Directional pad down pressed + currentInputs.insert(ControlInputs::Back); } if (buttons & XINPUT_GAMEPAD_DPAD_LEFT) { - // Directional pad left pressed + currentInputs.insert(ControlInputs::TurnLeft); } if (buttons & XINPUT_GAMEPAD_DPAD_RIGHT) { - // Directional pad right pressed + currentInputs.insert(ControlInputs::TurnRight); } // Other button mask values that can be used are: diff --git a/Graphics2/GamePadController.h b/Graphics2/GamePadController.h index 3c18b06..cde0062 100644 --- a/Graphics2/GamePadController.h +++ b/Graphics2/GamePadController.h @@ -1,15 +1,18 @@ #pragma once +#include #include "Core.h" #include "DirectXCore.h" #include #pragma comment(lib, "XInput.lib") +enum class ControlInputs { Forward, Back, TurnLeft, TurnRight, StrafeLeft, StrafeRight, Up, Down, Fire1, Fire2 }; + class GamePadController { public: GamePadController(); ~GamePadController(); - void ProcessGameController(); + void ProcessGameController(set& currentInputs, bool &boostHit); private: XINPUT_STATE _controllerState; diff --git a/Graphics2/GlobalLighting.cpp b/Graphics2/GlobalLighting.cpp new file mode 100644 index 0000000..768ccf9 --- /dev/null +++ b/Graphics2/GlobalLighting.cpp @@ -0,0 +1,38 @@ +#include "GlobalLighting.h" + +GlobalLighting::GlobalLighting() +{ + _ambientLight = XMFLOAT4(0.0f, 0.0f, 0.0f, 0.0f); + _directionalLightVector = XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f); + _directionalLightColor = XMFLOAT4(0.0f, 0.0f, 0.0f, 0.0f); +} + +GlobalLighting::~GlobalLighting() +{ +} + +void GlobalLighting::SetAmbientLight(XMFLOAT4 ambientLight) +{ + _ambientLight = ambientLight; +} + +XMFLOAT4 GlobalLighting::GetAmbientLight() const +{ + return _ambientLight; +} + +void GlobalLighting::SetDirectionalLight(FXMVECTOR direction, XMFLOAT4 lightColor) +{ + _directionalLightVector = direction; + _directionalLightColor = lightColor; +} + +XMVECTOR GlobalLighting::GetDirectionalLightDirection() const +{ + return _directionalLightVector; +} + +XMFLOAT4 GlobalLighting::GetDirectionalLightColor() const +{ + return _directionalLightColor; +} \ No newline at end of file diff --git a/Graphics2/GlobalLighting.h b/Graphics2/GlobalLighting.h new file mode 100644 index 0000000..6f65272 --- /dev/null +++ b/Graphics2/GlobalLighting.h @@ -0,0 +1,21 @@ +#pragma once +#include "DirectXCore.h" + +class GlobalLighting +{ +public: + GlobalLighting(); + ~GlobalLighting(); + + void SetAmbientLight(XMFLOAT4 ambientLight); + XMFLOAT4 GetAmbientLight() const; + void SetDirectionalLight(FXMVECTOR direction, XMFLOAT4 lightColor); + XMVECTOR GetDirectionalLightDirection() const; + XMFLOAT4 GetDirectionalLightColor() const; + + +private: + XMFLOAT4 _ambientLight; + XMVECTOR _directionalLightVector; + XMFLOAT4 _directionalLightColor; +}; \ No newline at end of file diff --git a/Graphics2/Graphics2.cpp b/Graphics2/Graphics2.cpp index 8688572..881b0f7 100644 --- a/Graphics2/Graphics2.cpp +++ b/Graphics2/Graphics2.cpp @@ -4,32 +4,65 @@ Graphics2 app; void Graphics2::CreateSceneGraph() { - _boostMultiplier = 1; + _boostMultiplier = _boostMin; _flySpeed = 1; _turnSpeed = 1; _invertPitch = -1; - GetCamera()->SetCameraPosition(0.0f, 550.0f, -80.0f); + _currentController = GamePadController(); + _currentPlayerObject = nullptr; + + GetCamera()->SetCameraPosition(0.0f, 550.0f, -80.0f); SceneGraphPointer sceneGraph = GetSceneGraph(); // This is where you add nodes to the scene graph //shared_ptr cube = make_shared(L"Body", L"Textures\\woodbox.bmp"); //cube->SetWorldTransform(XMMatrixScaling(5.0f, 8.0f, 2.5f) * XMMatrixTranslation(0, 23.0f, 0)); //sceneGraph->Add(cube); + + DirectXFramework::GetDXFramework()->GetGlobalLighting()->SetAmbientLight(XMFLOAT4(0.7f, 0.7f, 0.7f, 1.0f)); + DirectXFramework::GetDXFramework()->GetGlobalLighting()->SetDirectionalLight(XMVectorSet(0.5f, -1.0f, -1.0f, 0.0f), XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f)); + + shared_ptr skyDome = make_shared(L"SkyDome", L"Textures\\SkyWater.dds", 30.0f); + sceneGraph->Add(skyDome); - shared_ptr terrainNode = make_shared(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)); + //shared_ptr terrainNode = make_shared(L"MainTerrain", L"Textures\\Example_HeightMap.raw", L"RandomWords"); + shared_ptr terrainNode = make_shared(L"MainTerrain", L"LovelyCat", 10.0f, 20.0f, 1.0f, 1); + terrainNode->SetAmbientLight(DirectXFramework::GetDXFramework()->GetGlobalLighting()->GetAmbientLight()); + terrainNode->SetDirectionalLight(DirectXFramework::GetDXFramework()->GetGlobalLighting()->GetDirectionalLightDirection(), DirectXFramework::GetDXFramework()->GetGlobalLighting()->GetDirectionalLightColor()); + terrainNode->SetWaterColor(XMFLOAT4(SharedMethods::RGBValueToIntensity(0x84), 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 node = make_shared(L"Plane1", L"Models\\Plane\\Bonanza.3DS"); - //shared_ptr node = make_shared(L"Plane1", L"Models\\Plane\\Bonanza.3DS"); - node->SetWorldTransform(XMMatrixTranslation(-30.0f, 520.0f, 0)); - sceneGraph->Add(node); + shared_ptr treeGroupA = make_shared(L"TreeGroupA"); + + shared_ptr treeNode1 = make_shared(L"Tree1", L"Models\\Tree\\Tree1.3ds"); + treeNode1->SetWorldTransform(XMMatrixScaling(0.005f, 0.01f, 0.005f) * XMMatrixRotationAxis(XMVectorSet(1.0f, 0.0f, 1.0f, 0.0f), 0.1f * XM_PI) * XMMatrixTranslation(0.0f, 320.0f, 250.0f)); + treeGroupA->Add(treeNode1); + + shared_ptr treeNode2 = make_shared(L"Tree2", L"Models\\Tree\\Tree1.3ds"); + treeNode2->SetWorldTransform(XMMatrixScaling(0.002f, 0.002f, 0.002f) * XMMatrixTranslation(-150.0f, 380.0f, 150.0f)); + treeGroupA->Add(treeNode2); + + shared_ptr treeNode3 = make_shared(L"Tree3", L"Models\\Tree\\Tree1.3ds"); + treeNode3->SetWorldTransform(XMMatrixScaling(0.005f, 0.005f, 0.005f) * XMMatrixRotationAxis(XMVectorSet(1.0f, 0.0f, 1.0f, 0.0f), -0.1f * XM_PI) * XMMatrixTranslation(100.0f, 290.0f, 350.0f)); + treeGroupA->Add(treeNode3); + + shared_ptr treeNode4 = make_shared(L"Tree4", L"Models\\Tree\\Tree1.3ds"); + treeNode4->SetWorldTransform(XMMatrixScaling(0.005f, 0.01f, 0.005f) * XMMatrixRotationAxis(XMVectorSet(1.0f, 0.0f, 1.0f, 0.0f), 0.1f * XM_PI) * XMMatrixTranslation(0.0f, 320.0f, 250.0f)); + treeGroupA->Add(treeNode4); + + sceneGraph->Add(treeGroupA); + + shared_ptr plane1Node = make_shared(L"Plane1", L"Models\\Plane\\Bonanza.3DS"); + plane1Node->SetStartOrientation(XMMatrixRotationAxis(XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f), XM_PI) * XMMatrixRotationAxis(XMVectorSet(1.0f, 0.0f, 0.0f, 0.0f), 0.5f * XM_PI)); + plane1Node->SetNodePosition(0.0f, 550.0f, -50.0f); + sceneGraph->Add(plane1Node); + + //_currentPlayerObject = plane1Node; + //GetCamera()->SetFollowNode(plane1Node, XMFLOAT3(0.0f, 30.0f, -80.0f), false); SetBackgroundColour(XMFLOAT4(0.29f, 0.38f, 0.72f, 1.0f)); //SetBackgroundColour(XMFLOAT4(SharedMethods::RGBValueToIntensity(0x89), 0, 1, 1)); @@ -44,47 +77,103 @@ void Graphics2::UpdateSceneGraph() GetCurrentControlInputs(); SceneGraphPointer sceneGraph = GetSceneGraph(); + XMVECTOR startCameraPos = GetCamera()->GetCameraPosition(); + if (_currentPlayerObject != nullptr) + { + _currentPlayerObject->SetForwardBack(_flySpeed * _boostMultiplier); + } + for (ControlInputs currentControl : _currentInputs) { switch (currentControl) { case ControlInputs::Forward: - GetCamera()->SetForwardBack(_flySpeed * _boostMultiplier); + if (_currentPlayerObject == nullptr) + { + GetCamera()->SetForwardBack(_flySpeed * _boostMultiplier); + } break; case ControlInputs::Back: - GetCamera()->SetForwardBack(-_flySpeed * _boostMultiplier); + if (_currentPlayerObject == nullptr) + { + GetCamera()->SetForwardBack(-_flySpeed * _boostMultiplier); + } break; case ControlInputs::StrafeLeft: - GetCamera()->SetLeftRight(-_flySpeed * _boostMultiplier); + if (_currentPlayerObject != nullptr) + { + _currentPlayerObject->SetLeftRight(-_flySpeed * _boostMultiplier); + } + else + { + GetCamera()->SetLeftRight(-_flySpeed * _boostMultiplier); + } break; case ControlInputs::StrafeRight: - GetCamera()->SetLeftRight(_flySpeed * _boostMultiplier); + if (_currentPlayerObject != nullptr) + { + _currentPlayerObject->SetLeftRight(_flySpeed * _boostMultiplier); + } + else + { + GetCamera()->SetLeftRight(_flySpeed * _boostMultiplier); + } break; case ControlInputs::TurnLeft: - GetCamera()->SetYaw(-_turnSpeed); + if (_currentPlayerObject != nullptr) + { + _currentPlayerObject->SetYaw(-_turnSpeed); + } + else + { + GetCamera()->SetYaw(-_turnSpeed); + } break; case ControlInputs::TurnRight: - GetCamera()->SetYaw(_turnSpeed); + if (_currentPlayerObject != nullptr) + { + _currentPlayerObject->SetYaw(_turnSpeed); + } + else + { + GetCamera()->SetYaw(_turnSpeed); + } break; case ControlInputs::Up: - GetCamera()->SetPitch(_turnSpeed * _invertPitch); + if (_currentPlayerObject != nullptr) + { + _currentPlayerObject->SetPitch(_turnSpeed * _invertPitch); + } + else + { + GetCamera()->SetPitch(_turnSpeed * _invertPitch); + } break; case ControlInputs::Down: - GetCamera()->SetPitch(-_turnSpeed * _invertPitch); + if (_currentPlayerObject != nullptr) + { + _currentPlayerObject->SetPitch(-_turnSpeed * _invertPitch); + } + else + { + GetCamera()->SetPitch(-_turnSpeed * _invertPitch); + } break; } } - SceneNodePointer plane1 = sceneGraph->Find(L"Plane1"); + shared_ptr plane1 = dynamic_pointer_cast(sceneGraph->Find(L"Plane1")); - plane1->GetFirstChild()->SetWorldTransform(SharedMethods::RotateFromPoint(-60.0f, 0, 0, XMMatrixRotationAxis(XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f), _currentRotation * XM_PI / 180.0f))); - plane1 ->GetFirstChild()->AddToWorldTransform(XMMatrixRotationAxis(XMVectorSet(1.0f, 0.0f, 0.0f, 0.0f), 90.0f * XM_PI / 180.0f)); - //sceneGraph->Find(L"Plane1")->GetFirstChild()->GetFirstChild()->SetWorldTransform(XMMatrixRotationAxis(XMVectorSet(0.0f, -1.0f, -1.0f, 0.0f), _currentSideRotation * XM_PI / 180.0f)); + if (plane1 != nullptr) + { + //plane1->SetWorldTransform(SharedMethods::RotateFromPoint(-60.0f, 0, 0, XMMatrixRotationAxis(XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f), _currentRotation * XM_PI / 180.0f))); + //plane1->AddToWorldTransform(XMMatrixRotationAxis(XMVectorSet(1.0f, 0.0f, 0.0f, 0.0f), 90.0f * XM_PI / 180.0f)); + //sceneGraph->Find(L"Plane1")->GetFirstChild()->GetFirstChild()->SetWorldTransform(XMMatrixRotationAxis(XMVectorSet(0.0f, -1.0f, -1.0f, 0.0f), _currentSideRotation * XM_PI / 180.0f)); - //sceneGraph->Find(L"Plane1")->Update((SharedMethods::RotateFromPoint(30.0f, -20.0f, 0, XMMatrixRotationAxis(XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f), _currentSideRotation * XM_PI / 180.0f))) * XMMatrixRotationAxis(XMVectorSet(0.0f, -1.0f, 0.0f, 0.0f), _currentRotation * XM_PI / 180.0f)); - - plane1->Find(L"airscrew")->SetWorldTransform(SharedMethods::RotateFromPoint(0.0f, 15.471f, 14.5f, XMMatrixRotationAxis(XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f), _currentPropRotation * XM_PI / 180.0f))); + //sceneGraph->Find(L"Plane1")->Update((SharedMethods::RotateFromPoint(30.0f, -20.0f, 0, XMMatrixRotationAxis(XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f), _currentSideRotation * XM_PI / 180.0f))) * XMMatrixRotationAxis(XMVectorSet(0.0f, -1.0f, 0.0f, 0.0f), _currentRotation * XM_PI / 180.0f)); + plane1->Find(L"airscrew")->SetWorldTransform(SharedMethods::RotateFromPoint(0.0f, 15.471f, 14.5f, XMMatrixRotationAxis(XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f), _currentPropRotation * XM_PI / 180.0f))); + } if (_currentRotation == 360) { @@ -99,6 +188,61 @@ void Graphics2::UpdateSceneGraph() _currentPropRotation += 100; } + // Check the camera and our terrain boundaries + XMVECTOR currentCameraPos = GetCamera()->GetCameraPosition(); + shared_ptr mainTerrain = dynamic_pointer_cast(sceneGraph->Find(L"MainTerrain")); + GetCamera()->Update(); + if (mainTerrain != nullptr) + { + bool boundaryHit = false; + XMFLOAT4 cameraOffset = XMFLOAT4(XMVectorGetX(startCameraPos), XMVectorGetY(startCameraPos), XMVectorGetZ(startCameraPos), 0.0f); + + if (XMVectorGetY(currentCameraPos) < mainTerrain->GetHeightAtPoint(XMVectorGetX(currentCameraPos), XMVectorGetZ(currentCameraPos), true) + 4.0f) + { + cameraOffset.y = cameraOffset.y + 4.0f; + boundaryHit = true; + } + + float currentCameraXPos = XMVectorGetX(currentCameraPos); + float xOffset = 150.0f; + if (currentCameraXPos > 0) + { + xOffset = -xOffset; + } + + float currentCameraZPos = XMVectorGetZ(currentCameraPos); + float zOffset = 150.0f; + if (currentCameraZPos > 0) + { + zOffset = -zOffset; + } + + if (!mainTerrain->CheckXBoundary(currentCameraXPos + -xOffset)) + { + cameraOffset.x = cameraOffset.x + xOffset; + boundaryHit = true; + } + + if (!mainTerrain->CheckZBoundary(currentCameraZPos + -zOffset)) + { + cameraOffset.z = cameraOffset.z + zOffset; + boundaryHit = true; + } + + if (boundaryHit) + { + if (_currentPlayerObject != nullptr) + { + _currentPlayerObject->SetNodePosition(cameraOffset); + } + else + { + GetCamera()->SetCameraPosition(cameraOffset); + } + } + } + + // Reset the control array ready for the next frames input ResetCurrentControlInputs(); } @@ -107,61 +251,67 @@ void Graphics2::GetCurrentControlInputs() // Check if the window has focus before accepting any keypresses if (GetForegroundWindow() == Framework::GetHWnd()) { - if (GetAsyncKeyState(VK_SHIFT)) + + // Check if any connected controllers have inputs + bool boostHit = false; + _currentController.ProcessGameController(_currentInputs, boostHit); + + if (GetAsyncKeyState(VK_SHIFT) || boostHit) { - _boostMultiplier = 2; + _currentInputs.insert(ControlInputs::Fire1); + _boostMultiplier = SharedMethods::Clamp(_boostMultiplier + _boostStep, 1, _boostMax); } else { - _boostMultiplier = 1; + _boostMultiplier = SharedMethods::Clamp(_boostMultiplier - _boostStep, 1, _boostMax); } // Forward if (GetAsyncKeyState(0x57)) { - _currentInputs.push_back(ControlInputs::Forward); + _currentInputs.insert(ControlInputs::Forward); } // Back if (GetAsyncKeyState(0x53)) { - _currentInputs.push_back(ControlInputs::Back); + _currentInputs.insert(ControlInputs::Back); } // Turn Left if (GetAsyncKeyState(0x41)) { - _currentInputs.push_back(ControlInputs::TurnLeft); + _currentInputs.insert(ControlInputs::TurnLeft); } // Turn Right if (GetAsyncKeyState(0x44)) { - _currentInputs.push_back(ControlInputs::TurnRight); + _currentInputs.insert(ControlInputs::TurnRight); } // Strafe Left if (GetAsyncKeyState(0x51)) { - _currentInputs.push_back(ControlInputs::StrafeLeft); + _currentInputs.insert(ControlInputs::StrafeLeft); } // Strafe Right if (GetAsyncKeyState(0x45)) { - _currentInputs.push_back(ControlInputs::StrafeRight); + _currentInputs.insert(ControlInputs::StrafeRight); } // "Jump" if (GetAsyncKeyState(VK_SPACE)) { - _currentInputs.push_back(ControlInputs::Up); + _currentInputs.insert(ControlInputs::Up); } // "Crouch" if (GetAsyncKeyState(VK_CONTROL)) { - _currentInputs.push_back(ControlInputs::Down); + _currentInputs.insert(ControlInputs::Down); } } } diff --git a/Graphics2/Graphics2.h b/Graphics2/Graphics2.h index 2f00066..59b89b1 100644 --- a/Graphics2/Graphics2.h +++ b/Graphics2/Graphics2.h @@ -1,13 +1,16 @@ #pragma once #include "DirectXFramework.h" #include "SharedMethods.h" +#include "GamePadController.h" #include "TexturedCubeNode.h" #include "MeshNode.h" #include "SplitMeshNode.h" -#include "TerrainNode.h" +#include "ControlledSplitMeshNode.h" +#include "HeightMapTerrainNode.h" +#include "PerlinTerrainNode.h" +#include "SkyNode.h" #include - -enum class ControlInputs {Forward, Back, TurnLeft, TurnRight, StrafeLeft, StrafeRight, Up, Down, Fire1, Fire2}; +#include class Graphics2 : public DirectXFramework { @@ -16,19 +19,26 @@ public: void UpdateSceneGraph(); private: - bool _boosting; - float _boostMultiplier; + bool _boosting = false; + float _boostMultiplier = 1; + float _boostMin = 1; + float _boostStep = 0.5f; + float _boostMax = 5.0f; float _flySpeed; float _turnSpeed; int _invertPitch; - float _currentRotation = 0.0f; float _currentSideRotation = 0.0f; float _currentPropRotation = 0.0f; - vector _currentInputs; + GamePadController _currentController; + + // Changed from a vector to a set because sets only allow for unique values and thats all i want + set _currentInputs; + + shared_ptr _currentPlayerObject; void GetCurrentControlInputs(); void ResetCurrentControlInputs(); diff --git a/Graphics2/Graphics2.vcxproj b/Graphics2/Graphics2.vcxproj index 852ada0..a5269dd 100644 --- a/Graphics2/Graphics2.vcxproj +++ b/Graphics2/Graphics2.vcxproj @@ -82,6 +82,7 @@ false + $(VC_IncludePath);$(WindowsSDK_IncludePath);..\Assimp\include;$(IncludePath); @@ -128,7 +129,7 @@ - Use + NotUsing Level3 MaxSpeed true @@ -146,18 +147,22 @@ + + + + @@ -165,6 +170,7 @@ + @@ -188,19 +194,24 @@ + + + + + @@ -232,6 +243,11 @@ Document + + + Document + + diff --git a/Graphics2/Graphics2.vcxproj.filters b/Graphics2/Graphics2.vcxproj.filters index d9467f8..b31986b 100644 --- a/Graphics2/Graphics2.vcxproj.filters +++ b/Graphics2/Graphics2.vcxproj.filters @@ -102,6 +102,21 @@ Header Files + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + @@ -195,6 +210,21 @@ Source Files + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + @@ -209,6 +239,9 @@ Shaders + + Shaders + diff --git a/Graphics2/HeightMapTerrainNode.cpp b/Graphics2/HeightMapTerrainNode.cpp new file mode 100644 index 0000000..9ae9502 --- /dev/null +++ b/Graphics2/HeightMapTerrainNode.cpp @@ -0,0 +1,36 @@ +#include "HeightMapTerrainNode.h" + +#define WORLD_HEIGHT 1024 + +HeightMapTerrainNode::HeightMapTerrainNode(wstring name, wstring heightMap, wstring seed, float waterHeight, int widthX, int widthZ, int cellSizeX, int cellSizeZ) : TerrainNode(name, seed, waterHeight, widthX, widthZ, cellSizeX, cellSizeZ) +{ + _heightMap = heightMap; + if (!LoadHeightMap(_heightMap)) + { + _initError = true; + } +} + +bool HeightMapTerrainNode::LoadHeightMap(wstring heightMapFilename) +{ + unsigned int mapSize = _gridCols * _gridRows; + USHORT* rawFileValues = new USHORT[mapSize]; + + std::ifstream inputHeightMap; + inputHeightMap.open(heightMapFilename.c_str(), std::ios_base::binary); + if (!inputHeightMap) + { + return false; + } + + inputHeightMap.read((char*)rawFileValues, mapSize * 2); + inputHeightMap.close(); + + // Normalise BYTE values to the range 0.0f - 1.0f; + for (unsigned int i = 0; i < mapSize; i++) + { + _heightValues.push_back((float)rawFileValues[i] / 65536); + } + delete[] rawFileValues; + return true; +} diff --git a/Graphics2/HeightMapTerrainNode.h b/Graphics2/HeightMapTerrainNode.h new file mode 100644 index 0000000..3bd001f --- /dev/null +++ b/Graphics2/HeightMapTerrainNode.h @@ -0,0 +1,16 @@ +#pragma once +#include "DirectXFramework.h" +#include "SharedMethods.h" +#include "TerrainNode.h" + +class HeightMapTerrainNode : public TerrainNode +{ +public: + HeightMapTerrainNode(wstring name, wstring heightMap, wstring seed, float waterHeight = 150.0f, int widthX = 1023, int widthZ = 1023, int cellSizeX = 10, int cellSizeZ = 10); + +private: + wstring _heightMap; + + bool LoadHeightMap(wstring heightMapFilename); +}; + diff --git a/Graphics2/MeshNode.cpp b/Graphics2/MeshNode.cpp index d565333..cd76387 100644 --- a/Graphics2/MeshNode.cpp +++ b/Graphics2/MeshNode.cpp @@ -21,9 +21,8 @@ void MeshNode::Render() { _renderer->SetMesh(_mesh); _renderer->SetWorldTransformation(XMLoadFloat4x4(&_combinedWorldTransformation)); - _renderer->SetCameraPosition(DirectXFramework::GetDXFramework()->GetCamera()->GetRawCameraPosition()); - _renderer->SetAmbientLight(XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f)); - _renderer->SetDirectionalLight(XMVectorSet(0.0f, -1.0f, 1.0f, 0.0f), XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f)); + _renderer->SetAmbientLight(DirectXFramework::GetDXFramework()->GetGlobalLighting()->GetAmbientLight()); + _renderer->SetDirectionalLight(DirectXFramework::GetDXFramework()->GetGlobalLighting()->GetDirectionalLightDirection(), DirectXFramework::GetDXFramework()->GetGlobalLighting()->GetDirectionalLightColor()); _renderer->Render(); } diff --git a/Graphics2/MeshRenderer.cpp b/Graphics2/MeshRenderer.cpp index 178800e..5127c8f 100644 --- a/Graphics2/MeshRenderer.cpp +++ b/Graphics2/MeshRenderer.cpp @@ -101,7 +101,7 @@ void MeshRenderer::Render() _cBuffer.ambientColor = _ambientLight; _cBuffer.lightVector = XMVector4Normalize(XMLoadFloat4(&_directionalLightVector)); _cBuffer.lightColor = _directionalLightColour; - _cBuffer.cameraPosition = _cameraPosition; + XMStoreFloat4(&_cBuffer.cameraPosition, DirectXFramework::GetDXFramework()->GetCamera()->GetCameraPosition()); _deviceContext->VSSetShader(_vertexShader.Get(), 0, 0); _deviceContext->PSSetShader(_pixelShader.Get(), 0, 0); diff --git a/Graphics2/Models/Tree/COLOR.JPG b/Graphics2/Models/Tree/COLOR.JPG new file mode 100644 index 0000000..cea16ae Binary files /dev/null and b/Graphics2/Models/Tree/COLOR.JPG differ diff --git a/Graphics2/Models/Tree/Kashtan.jpg b/Graphics2/Models/Tree/Kashtan.jpg new file mode 100644 index 0000000..dbd81b7 Binary files /dev/null and b/Graphics2/Models/Tree/Kashtan.jpg differ diff --git a/Graphics2/Models/Tree/Tree1.3ds b/Graphics2/Models/Tree/Tree1.3ds new file mode 100644 index 0000000..813923a Binary files /dev/null and b/Graphics2/Models/Tree/Tree1.3ds differ diff --git a/Graphics2/ObjectNode.cpp b/Graphics2/ObjectNode.cpp new file mode 100644 index 0000000..4b3087c --- /dev/null +++ b/Graphics2/ObjectNode.cpp @@ -0,0 +1,132 @@ +#include "ObjectNode.h" + +ObjectNode::ObjectNode() +{ + _nodeRootPosition = XMFLOAT4(0.0f, 0.0f, 0.0f, 0.0f); + _moveLeftRight = 0.0f; + _moveForwardBack = 0.0f; + _nodeYaw = 0.0f; + _nodePitch = 0.0f; + _nodeRoll = 0.0f; + XMStoreFloat4x4(&_originalOrientation, XMMatrixIdentity()); +} + +void ObjectNode::Update(XMFLOAT4X4& currentWorldTransform) +{ + XMVECTOR nodePosition; + XMVECTOR nodeRight; + XMVECTOR nodeForward; + XMVECTOR nodeUp; + + XMVECTOR defaultForward = XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f); + XMVECTOR defaultRight = XMVectorSet(1.0f, 0.0f, 0.0f, 0.0f); + XMVECTOR defaultUp = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f); + + // Yaw (rotation around the Y axis) will have an impact on the forward and right vectors + XMMATRIX nodeRotationYaw = XMMatrixRotationAxis(defaultUp, _nodeYaw); + nodeRight = XMVector3TransformCoord(defaultRight, nodeRotationYaw); + nodeForward = XMVector3TransformCoord(defaultForward, nodeRotationYaw); + + // Pitch (rotation around the X axis) impact the up and forward vectors + XMMATRIX nodeRotationPitch = XMMatrixRotationAxis(nodeRight, _nodePitch); + nodeUp = XMVector3TransformCoord(defaultUp, nodeRotationPitch); + nodeForward = XMVector3TransformCoord(nodeForward, nodeRotationPitch); + + // Roll (rotation around the Z axis) will impact the Up and Right vectors + XMMATRIX nodeRotationRoll = XMMatrixRotationAxis(nodeForward, _nodeRoll); + nodeUp = XMVector3TransformCoord(nodeUp, nodeRotationRoll); + nodeRight = XMVector3TransformCoord(nodeRight, nodeRotationRoll); + + // Adjust the node position by the appropriate amount forward/back and left/right + nodePosition = XMLoadFloat4(&_nodeRootPosition) + _moveLeftRight * nodeRight + _moveForwardBack * nodeForward; + XMStoreFloat4(&_nodeRootPosition, nodePosition); + + // Reset the amount we are moving + _moveLeftRight = 0.0f; + _moveForwardBack = 0.0f; + + XMMATRIX worldTransformation = XMLoadFloat4x4(&_originalOrientation) * nodeRotationYaw * nodeRotationPitch * nodeRotationRoll * XMMatrixTranslation(_nodeRootPosition.x, _nodeRootPosition.y, _nodeRootPosition.z); + XMStoreFloat4x4(¤tWorldTransform, worldTransformation); +} + +void ObjectNode::SetPitch(float pitch) +{ + _nodePitch += XMConvertToRadians(pitch); +} + +void ObjectNode::SetTotalPitch(float pitch) +{ + _nodePitch = XMConvertToRadians(pitch); +} + +float ObjectNode::GetPitch() const +{ + return XMConvertToDegrees(_nodePitch); +} + +void ObjectNode::SetYaw(float yaw) +{ + _nodeYaw += XMConvertToRadians(yaw); +} + +void ObjectNode::SetTotalYaw(float yaw) +{ + _nodeYaw = XMConvertToRadians(yaw); +} + +float ObjectNode::GetYaw() const +{ + return XMConvertToDegrees(_nodeYaw); +} + +void ObjectNode::SetRoll(float roll) +{ + _nodeRoll += XMConvertToRadians(roll); +} + +void ObjectNode::SetTotalRoll(float roll) +{ + _nodeRoll = XMConvertToRadians(roll); +} + +float ObjectNode::GetRoll() const +{ + return XMConvertToDegrees(_nodeRoll); +} + +void ObjectNode::SetLeftRight(float leftRight) +{ + _moveLeftRight = leftRight; +} + +void ObjectNode::SetForwardBack(float forwardBack) +{ + _moveForwardBack = forwardBack; +} + +XMVECTOR ObjectNode::GetNodePosition(void) +{ + return XMLoadFloat4(&_nodeRootPosition); +} + +void ObjectNode::SetNodePosition(float x, float y, float z) +{ + SetNodePosition(XMFLOAT4(x, y, z, 0.0f)); +} + +void ObjectNode::SetNodePosition(XMVECTOR vectorIn) +{ + XMFLOAT4 floatIn; + XMStoreFloat4(&floatIn, vectorIn); + SetNodePosition(floatIn); +} + +void ObjectNode::SetNodePosition(XMFLOAT4 floatIn) +{ + _nodeRootPosition = floatIn; +} + +void ObjectNode::SetStartOrientation(FXMMATRIX originalOrientation) +{ + XMStoreFloat4x4(&_originalOrientation, originalOrientation); +} \ No newline at end of file diff --git a/Graphics2/ObjectNode.h b/Graphics2/ObjectNode.h new file mode 100644 index 0000000..103efc1 --- /dev/null +++ b/Graphics2/ObjectNode.h @@ -0,0 +1,40 @@ +#pragma once +#include "DirectXCore.h" + +class ObjectNode +{ +public: + ObjectNode(); + + void Update(XMFLOAT4X4& currentWorldTransform); + + XMVECTOR GetNodePosition(); + void SetNodePosition(XMVECTOR vectorIn); + void SetNodePosition(XMFLOAT4 floatIn); + void SetNodePosition(float x, float y, float z); + void SetPitch(float pitch); + void SetTotalPitch(float pitch); + float GetPitch() const; + void SetYaw(float yaw); + void SetTotalYaw(float yaw); + float GetYaw() const; + void SetRoll(float roll); + void SetTotalRoll(float roll); + float GetRoll() const; + void SetLeftRight(float leftRight); + void SetForwardBack(float forwardBack); + void SetStartOrientation(FXMMATRIX originalOrientation); + +protected: + XMFLOAT4 _nodeRootPosition; + + float _moveLeftRight; + float _moveForwardBack; + + float _nodeYaw; + float _nodePitch; + float _nodeRoll; + + XMFLOAT4X4 _originalOrientation; +}; + diff --git a/Graphics2/PerlinTerrainNode.cpp b/Graphics2/PerlinTerrainNode.cpp new file mode 100644 index 0000000..bd21d83 --- /dev/null +++ b/Graphics2/PerlinTerrainNode.cpp @@ -0,0 +1,135 @@ +#include "PerlinTerrainNode.h" + +PerlinTerrainNode::PerlinTerrainNode(wstring name, wstring seed, float offsetX, float offsetY, float chunkSize, int layers, int widthX, int widthZ, float waterHeight, int cellSizeX, int cellSizeZ) : TerrainNode(name, seed, waterHeight, widthX, widthZ, cellSizeX, cellSizeZ) +{ + _offsetX = offsetX; + _offsetY = offsetY; + _chunkSize = chunkSize; + _layers = layers; + + GeneratePerlinValues(); + if (!GeneratePerlinHeights()) + { + _initError = true; + } +} + +// Method for filling the height values array for the terrain generation +bool PerlinTerrainNode::GeneratePerlinHeights() +{ + for (int z = 0; z < _gridRows; z++) + { + float mapZ = ((float)z / (float)_gridRows) + 0.5f; + + for (int x = 0; x < _gridCols; x++) + { + float mapX = ((float)x / (float)_gridCols) + 0.5f; + + float currentHeightValue = GetPerlinValueAt(_offsetX + mapX, _offsetY + mapZ, 8, 0.85f) - 0.25f; + //currentHeightValue = currentHeightValue - floor(currentHeightValue); + _heightValues.push_back(currentHeightValue); + } + } + + return true; +} + +// Method for generating the permutation array needed for perlin noise +void PerlinTerrainNode::GeneratePerlinValues() +{ + // Set the permutation array length + p.resize(256); + + // Fill the permutation array with 0 to 255 + iota(p.begin(), p.end(), 0); + + default_random_engine engine(_seedHash); + + // Shuffle the array values using the seed value given + shuffle(p.begin(), p.end(), engine); + + // Duplicate the permutation results so our array is 512 + p.insert(p.end(), p.begin(), p.end()); +} + +float PerlinTerrainNode::Fade(float t) +{ + return t * t * t * (t * (t * 6 - 15) + 10); +} + +float PerlinTerrainNode::Grad(int hash, float x, float y) +{ + // Fast Grad switch check converted from a java implimentation of perlin noise + switch (hash & 0xF) + { + case 0x0: return x; + case 0x1: return x + y; + case 0x2: return y; + case 0x3: return -x + y; + case 0x4: return -x; + case 0x5: return -x - y; + case 0x6: return -y; + case 0x7: return x - y; + case 0x8: return x; + case 0x9: return x + y; + case 0xA: return y; + case 0xB: return -x + y; + case 0xC: return -x; + case 0xD: return -x - y; + case 0xE: return -y; + case 0xF: return x - y; + + default: return 0; // Never occurs + } +} + +// Method to calculate the perlin value at x/y with the given octaves and persistance values, also normalised +float PerlinTerrainNode::GetPerlinValueAt(float x, float y, int octaves, float persistance) +{ + float total = 0.0f; + float frequency = 1.0f; + float amplitude = 1.0f; + float maxValue = 0.0f; + + for (int i = 0; i < octaves; i++) + { + total += (GetNoiseValueAt(x * frequency, y * frequency) * amplitude); + maxValue += amplitude; + + amplitude *= persistance; + frequency *= 2; + } + + return total / maxValue; +} + +// Method to get the perlin noise value at x/y +float PerlinTerrainNode::GetNoiseValueAt(float x, float y) +{ + int x0 = (int)x & 255; + int y0 = (int)y & 255; + + int x1 = x0 + 1; + int y1 = y0 + 1; + + float dx = x - (float)x0; + float dy = y - (float)y0; + + float u = Fade(dx); + float v = Fade(dy); + + int aa = p[p[x0] + y0]; + int ab = p[p[x0] + y1]; + int ba = p[p[x1] + y0]; + int bb = p[p[x1] + y1]; + + float na0 = Grad(aa, dx, dy); + float na1 = Grad(ba, dx - 1.0f, dy); + float nal = SharedMethods::Lerp(na0, na1, u); + + float nb0 = Grad(ab, dx, dy - 1.0f); + float nb1 = Grad(bb, dx - 1.0f, dy - 1.0f); + float nbl = SharedMethods::Lerp(nb0, nb1, u); + + return (SharedMethods::Lerp(nal, nbl, v) + 1.0f) / 2.0f; +} \ No newline at end of file diff --git a/Graphics2/PerlinTerrainNode.h b/Graphics2/PerlinTerrainNode.h new file mode 100644 index 0000000..6eade91 --- /dev/null +++ b/Graphics2/PerlinTerrainNode.h @@ -0,0 +1,29 @@ +#pragma once +#include "DirectXFramework.h" +#include +#include +#include +#include "SharedMethods.h" +#include "TerrainNode.h" + +class PerlinTerrainNode : public TerrainNode +{ +public: + PerlinTerrainNode(wstring name, wstring seed, float offsetX, float offsetY, float chunkSize, int layers, int widthX = 1023, int widthZ = 1023, float waterHeight = 150.0f, int cellSizeX = 10, int cellSizeZ = 10); + +private: + vector p; + float _offsetX; + float _offsetY; + float _chunkSize; + int _layers; + + float Fade(float t); + float Grad(int hash, float x, float y); + + bool GeneratePerlinHeights(); + float GetPerlinValueAt(float x, float y, int octaves, float persistance); + float GetNoiseValueAt(float x, float y); + void GeneratePerlinValues(); +}; + diff --git a/Graphics2/SceneGraph.cpp b/Graphics2/SceneGraph.cpp index 69c4a76..b99b0a1 100644 --- a/Graphics2/SceneGraph.cpp +++ b/Graphics2/SceneGraph.cpp @@ -87,4 +87,9 @@ SceneNodePointer SceneGraph::GetFirstChild() firstChild = _children.front(); } return firstChild; +} + +list& SceneGraph::GetChildren() +{ + return _children; } \ No newline at end of file diff --git a/Graphics2/SceneGraph.h b/Graphics2/SceneGraph.h index 32e8c83..891ad77 100644 --- a/Graphics2/SceneGraph.h +++ b/Graphics2/SceneGraph.h @@ -21,7 +21,9 @@ public: SceneNodePointer GetParent(); SceneNodePointer GetFirstChild(); -private: + list& GetChildren(); + +protected: // Here you need to add whatever collection you are going to // use to store the children of this scene graph list _children; diff --git a/Graphics2/SharedMethods.cpp b/Graphics2/SharedMethods.cpp index 6ffee7e..d13bbb7 100644 --- a/Graphics2/SharedMethods.cpp +++ b/Graphics2/SharedMethods.cpp @@ -1,28 +1,19 @@ #include "SharedMethods.h" -XMMATRIX SharedMethods::RotateFromPoint(float x, float y, float z, XMMATRIX rotationMatrix) +XMMATRIX SharedMethods::RotateFromPoint(const float x, const float y, const float z, const XMMATRIX rotationMatrix) { // Translates a matrix to a point, rotates and then returns back to where it was return XMMatrixTranslation(x, y, z) * rotationMatrix * XMMatrixTranslation(-x, -y, -z); } // Method so i can use normal RGB values and hopefully hex values too since im use to those -float SharedMethods::RGBValueToIntensity(int value) +float SharedMethods::RGBValueToIntensity(const int value) { return (float)value / 255.0f; } -float SharedMethods::Lerp(int a, int b, int p) -{ - return 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) +// Method to generate a random intensity rating between 2 floats +float SharedMethods::GenerateRandomIntensity(const float min, const float max) { float randNo = (float)rand() / (float)RAND_MAX; float rangeDiff = max - min; @@ -31,19 +22,8 @@ float SharedMethods::GenerateRandomIntensity(float min, float max) 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; +// Method for genering random UV's, maybe get rid of this in future +float SharedMethods::GenerateRandomUV(const float min, const float max) +{ + return SharedMethods::Clamp((float)(rand() % (int)(max * 100.0f)) * 0.01f, (float)min, (float)max); } \ No newline at end of file diff --git a/Graphics2/SharedMethods.h b/Graphics2/SharedMethods.h index 3f724c4..fb098eb 100644 --- a/Graphics2/SharedMethods.h +++ b/Graphics2/SharedMethods.h @@ -1,5 +1,5 @@ #pragma once -#include "DirectXFramework.h" +#include "DirectXCore.h" struct CBUFFER { @@ -16,33 +16,45 @@ 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); + XMMATRIX RotateFromPoint(const float x, const float y, const float z, const XMMATRIX rotationMatrix); - float RGBValueToIntensity(int value); - float Lerp(int a, int b, int p); - float Lerp(float a, float b, float p); + float RGBValueToIntensity(const int value); + + template T Clamp(const T value, const T min, const T max) + { + if (value < min) + { + return min; + } + else if (value > max) + { + return max; + } + else + { + return value; + } + } - float GenerateRandomIntensity(float min, float max); - float GenerateRandomUV(int min, int max); + // Methods for lerping values + template float Lerp(const T a, const T b, const float p) + { + return (float)a + p * ((float)b - (float)a); + } + + template float CubicInterpolate(const T n0, const T n1, const T n2, const T n3, const float a) + { + float p = ((float)n3 - (float)n2) - ((float)n0 - (float)n1); + float q = ((float)n0 - (float)n1) - p; + float r = (float)n2 - (float)n0; + float s = (float)n1; + + return p * a * a * a + q * a * a + r * a + s; + } + + float GenerateRandomIntensity(const float min, const float max); + float GenerateRandomUV(const float min, const float max); }; diff --git a/Graphics2/SkyNode.cpp b/Graphics2/SkyNode.cpp new file mode 100644 index 0000000..9a14b67 --- /dev/null +++ b/Graphics2/SkyNode.cpp @@ -0,0 +1,291 @@ +#include "SkyNode.h" + +SkyNode::SkyNode(wstring name, wstring skyCubeTextureName, float skyRadius) : SceneNode(name) +{ + _skyCubeTextureName = skyCubeTextureName; + _skyRadius = skyRadius; +} + +SkyNode::~SkyNode() +{ + +} + +bool SkyNode::Initialise() +{ + _device = DirectXFramework::GetDXFramework()->GetDevice(); + _deviceContext = DirectXFramework::GetDXFramework()->GetDeviceContext(); + + if (_device.Get() == nullptr || _deviceContext.Get() == nullptr) + { + return false; + } + + CreateSphere(_skyRadius, 180); + GenerateBuffers(); + BuildShaders(); + BuildVertexLayout(); + BuildConstantBuffer(); + BuildRendererStates(); + BuildDepthStencilState(); + LoadSkyboxTexture(); + + return true; +} + +void SkyNode::CreateSphere(float radius, size_t tessellation) +{ + _skyDomeVerts.clear(); + _indices.clear(); + + size_t verticalSegments = tessellation; + size_t horizontalSegments = tessellation * 2; + + // Create rings of vertices at progressively higher latitudes. + for (size_t i = 0; i <= verticalSegments; i++) + { + float v = 1 - (float)i / verticalSegments; + + float latitude = (i * XM_PI / verticalSegments) - XM_PIDIV2; + float dy, dxz; + + XMScalarSinCos(&dy, &dxz, latitude); + + // Create a single ring of vertices at this latitude. + for (size_t j = 0; j <= horizontalSegments; j++) + { + float u = (float)j / horizontalSegments; + + float longitude = j * XM_2PI / horizontalSegments; + float dx, dz; + + XMScalarSinCos(&dx, &dz, longitude); + + dx *= dxz; + dz *= dxz; + + SkyVertex vertex; + vertex.Position.x = dx * radius; + vertex.Position.y = dy * radius; + vertex.Position.z = dz * radius; + _skyDomeVerts.push_back(vertex); + } + } + + // Fill the index buffer with triangles joining each pair of latitude rings. + size_t stride = horizontalSegments + 1; + + for (size_t i = 0; i < verticalSegments; i++) + { + for (size_t j = 0; j <= horizontalSegments; j++) + { + size_t nextI = i + 1; + size_t nextJ = (j + 1) % stride; + + _indices.push_back((UINT)(i * stride + j)); + _indices.push_back((UINT)(nextI * stride + j)); + _indices.push_back((UINT)(i * stride + nextJ)); + + _indices.push_back((UINT)(i * stride + nextJ)); + _indices.push_back((UINT)(nextI * stride + j)); + _indices.push_back((UINT)(nextI * stride + nextJ)); + } + } + _vertexCount = (unsigned int)_skyDomeVerts.size(); + _indicesCount = (unsigned int)_indices.size(); +} + +void SkyNode::GenerateBuffers() +{ + // Setup the structure that specifies how big the vertex + // buffer should be + D3D11_BUFFER_DESC vertexBufferDescriptor; + vertexBufferDescriptor.Usage = D3D11_USAGE_IMMUTABLE; + vertexBufferDescriptor.ByteWidth = sizeof(SkyVertex) * _vertexCount; + vertexBufferDescriptor.BindFlags = D3D11_BIND_VERTEX_BUFFER; + vertexBufferDescriptor.CPUAccessFlags = 0; + vertexBufferDescriptor.MiscFlags = 0; + vertexBufferDescriptor.StructureByteStride = 0; + + // Now set up a structure that tells DirectX where to get the + // data for the vertices from + D3D11_SUBRESOURCE_DATA vertexInitialisationData; + vertexInitialisationData.pSysMem = &_skyDomeVerts[0]; + + // and create the vertex buffer + ThrowIfFailed(_device->CreateBuffer(&vertexBufferDescriptor, &vertexInitialisationData, _vertexBuffer.GetAddressOf())); + + // Setup the structure that specifies how big the index + // buffer should be + D3D11_BUFFER_DESC indexBufferDescriptor; + indexBufferDescriptor.Usage = D3D11_USAGE_IMMUTABLE; + indexBufferDescriptor.ByteWidth = sizeof(UINT) * _indicesCount; + indexBufferDescriptor.BindFlags = D3D11_BIND_INDEX_BUFFER; + indexBufferDescriptor.CPUAccessFlags = 0; + indexBufferDescriptor.MiscFlags = 0; + indexBufferDescriptor.StructureByteStride = 0; + + // Now set up a structure that tells DirectX where to get the + // data for the indices from + D3D11_SUBRESOURCE_DATA indexInitialisationData; + indexInitialisationData.pSysMem = &_indices[0]; + + // and create the index buffer + ThrowIfFailed(_device->CreateBuffer(&indexBufferDescriptor, &indexInitialisationData, _indexBuffer.GetAddressOf())); +} + +void SkyNode::Render() +{ + XMMATRIX projectionTransformation = DirectXFramework::GetDXFramework()->GetProjectionTransformation(); + XMMATRIX viewTransformation = DirectXFramework::GetDXFramework()->GetCamera()->GetViewMatrix(); + + XMFLOAT4 cameraPosition; + XMStoreFloat4(&cameraPosition, DirectXFramework::GetDXFramework()->GetCamera()->GetCameraPosition()); + + XMMATRIX skyWorldTransformation = XMMatrixTranslation(cameraPosition.x, cameraPosition.y, cameraPosition.z); + XMMATRIX completeTransformation = skyWorldTransformation * viewTransformation * projectionTransformation; + + // Draw the first cube + SCBUFFER cBuffer; + cBuffer.completeTransformation = completeTransformation; + + _deviceContext->PSSetShaderResources(0, 1, _skyCubeTexture.GetAddressOf()); + + _deviceContext->VSSetShader(_vertexShader.Get(), 0, 0); + _deviceContext->PSSetShader(_pixelShader.Get(), 0, 0); + _deviceContext->IASetInputLayout(_layout.Get()); + + UINT stride = sizeof(SkyVertex); + UINT offset = 0; + _deviceContext->IASetVertexBuffers(0, 1, _vertexBuffer.GetAddressOf(), &stride, &offset); + _deviceContext->IASetIndexBuffer(_indexBuffer.Get(), DXGI_FORMAT_R32_UINT, 0); + + // Update the constant buffer + _deviceContext->VSSetConstantBuffers(0, 1, _constantBuffer.GetAddressOf()); + _deviceContext->UpdateSubresource(_constantBuffer.Get(), 0, 0, &cBuffer, 0, 0); + _deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + _deviceContext->RSSetState(_noCullRasteriserState.Get()); + _deviceContext->OMSetDepthStencilState(_stencilState.Get(), 1); + _deviceContext->DrawIndexed(_indicesCount, 0, 0); + _deviceContext->OMSetDepthStencilState(nullptr, 1); + _deviceContext->RSSetState(_defaultRasteriserState.Get()); + +} + +void SkyNode::Shutdown(void) +{ +} + +void SkyNode::BuildShaders() +{ + DWORD shaderCompileFlags = 0; +#if defined( _DEBUG ) + shaderCompileFlags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION; +#endif + + ComPtr compilationMessages = nullptr; + + //Compile vertex shader + HRESULT hr = D3DCompileFromFile(L"SkyShader.hlsl", + nullptr, D3D_COMPILE_STANDARD_FILE_INCLUDE, + "VS", "vs_5_0", + shaderCompileFlags, 0, + _vertexShaderByteCode.GetAddressOf(), + compilationMessages.GetAddressOf()); + + if (compilationMessages.Get() != nullptr) + { + // If there were any compilation messages, display them + MessageBoxA(0, (char*)compilationMessages->GetBufferPointer(), 0, 0); + } + // Even if there are no compiler messages, check to make sure there were no other errors. + ThrowIfFailed(hr); + ThrowIfFailed(_device->CreateVertexShader(_vertexShaderByteCode->GetBufferPointer(), _vertexShaderByteCode->GetBufferSize(), NULL, _vertexShader.GetAddressOf())); + + // Compile pixel shader + hr = D3DCompileFromFile(L"SkyShader.hlsl", + nullptr, D3D_COMPILE_STANDARD_FILE_INCLUDE, + "PS", "ps_5_0", + shaderCompileFlags, 0, + _pixelShaderByteCode.GetAddressOf(), + compilationMessages.GetAddressOf()); + + if (compilationMessages.Get() != nullptr) + { + // If there were any compilation messages, display them + MessageBoxA(0, (char*)compilationMessages->GetBufferPointer(), 0, 0); + } + ThrowIfFailed(hr); + ThrowIfFailed(_device->CreatePixelShader(_pixelShaderByteCode->GetBufferPointer(), _pixelShaderByteCode->GetBufferSize(), NULL, _pixelShader.GetAddressOf())); +} + + +void SkyNode::BuildVertexLayout() +{ + // Create the vertex input layout. This tells DirectX the format + // of each of the vertices we are sending to it. + + D3D11_INPUT_ELEMENT_DESC vertexDesc[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 } + }; + ThrowIfFailed(_device->CreateInputLayout(vertexDesc, ARRAYSIZE(vertexDesc), _vertexShaderByteCode->GetBufferPointer(), _vertexShaderByteCode->GetBufferSize(), _layout.GetAddressOf())); +} + +void SkyNode::BuildConstantBuffer() +{ + D3D11_BUFFER_DESC bufferDesc; + ZeroMemory(&bufferDesc, sizeof(bufferDesc)); + bufferDesc.Usage = D3D11_USAGE_DEFAULT; + bufferDesc.ByteWidth = sizeof(SCBUFFER); + bufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + ThrowIfFailed(_device->CreateBuffer(&bufferDesc, NULL, _constantBuffer.GetAddressOf())); +} + +void SkyNode::LoadSkyboxTexture() +{ + ThrowIfFailed(CreateDDSTextureFromFile(_device.Get(), + _skyCubeTextureName.c_str(), + nullptr, + _skyCubeTexture.GetAddressOf() + )); +} + +void SkyNode::BuildRendererStates() +{ + // Set default and wireframe rasteriser states + D3D11_RASTERIZER_DESC rasteriserDesc; + rasteriserDesc.FillMode = D3D11_FILL_SOLID; + rasteriserDesc.CullMode = D3D11_CULL_BACK; + rasteriserDesc.FrontCounterClockwise = false; + rasteriserDesc.DepthBias = 0; + rasteriserDesc.SlopeScaledDepthBias = 0.0f; + rasteriserDesc.DepthBiasClamp = 0.0f; + rasteriserDesc.DepthClipEnable = true; + rasteriserDesc.ScissorEnable = false; + rasteriserDesc.MultisampleEnable = false; + rasteriserDesc.AntialiasedLineEnable = false; + ThrowIfFailed(_device->CreateRasterizerState(&rasteriserDesc, _defaultRasteriserState.GetAddressOf())); + rasteriserDesc.CullMode = D3D11_CULL_NONE; + ThrowIfFailed(_device->CreateRasterizerState(&rasteriserDesc, _noCullRasteriserState.GetAddressOf())); +} + +void SkyNode::BuildDepthStencilState() +{ + D3D11_DEPTH_STENCIL_DESC stencilDesc; + stencilDesc.DepthEnable = true; + stencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; + stencilDesc.DepthFunc = D3D11_COMPARISON_LESS_EQUAL; + stencilDesc.StencilEnable = false; + stencilDesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK; + stencilDesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK; + stencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + stencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; + stencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; + stencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + stencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + stencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; + stencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; + stencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + ThrowIfFailed(_device->CreateDepthStencilState(&stencilDesc, _stencilState.GetAddressOf())); +} \ No newline at end of file diff --git a/Graphics2/SkyNode.h b/Graphics2/SkyNode.h new file mode 100644 index 0000000..940363e --- /dev/null +++ b/Graphics2/SkyNode.h @@ -0,0 +1,67 @@ +#pragma once +#include "DirectXFramework.h" +#include "DDSTextureLoader.h" +#include "SharedMethods.h" +#include "SceneNode.h" + +typedef struct SkyVertex +{ + XMFLOAT3 Position; +} SkyVertex; + +struct SCBUFFER +{ + XMMATRIX completeTransformation; +}; + +class SkyNode : public SceneNode +{ +public: + SkyNode(wstring name, wstring skyCubeTextureName, float skyRadius); + ~SkyNode(); + + bool Initialise(void); + void Render(void); + void Shutdown(void); + +private: + float _skyRadius; + + UINT _indicesCount; + UINT _vertexCount; + + vector _skyDomeVerts; + vector _indices; + + ComPtr _device; + ComPtr _deviceContext; + + ComPtr _vertexBuffer; + ComPtr _indexBuffer; + + ComPtr _vertexShaderByteCode = nullptr; + ComPtr _pixelShaderByteCode = nullptr; + ComPtr _vertexShader; + ComPtr _pixelShader; + ComPtr _layout; + ComPtr _constantBuffer; + + ComPtr _defaultRasteriserState; + ComPtr _noCullRasteriserState; + + ComPtr _stencilState; + + ComPtr _skyCubeTexture; + wstring _skyCubeTextureName; + + void CreateSphere(float radius, size_t tessellation); + void GenerateBuffers(); + void BuildShaders(); + void BuildVertexLayout(); + void BuildConstantBuffer(); + void BuildRendererStates(); + void BuildDepthStencilState(); + + void LoadSkyboxTexture(); +}; + diff --git a/Graphics2/SkyShader.hlsl b/Graphics2/SkyShader.hlsl new file mode 100644 index 0000000..70e2634 --- /dev/null +++ b/Graphics2/SkyShader.hlsl @@ -0,0 +1,36 @@ +cbuffer ConstantBuffer +{ + float4x4 completeTransformation; +}; + +TextureCube cubeMap; + +SamplerState samTriLinearSam; + +struct VertexIn +{ + float3 Position : POSITION; +}; + +struct VertexOut +{ + float4 Position : SV_POSITION; + float3 TexCoord : TEXCOORD; +}; + +VertexOut VS(VertexIn vin) +{ + VertexOut vout; + + // Set z = w so that z/w = 1 (i.e., skydome always on far plane). + vout.Position = mul(float4(vin.Position, 1.0f), completeTransformation).xyww; + + vout.TexCoord = vin.Position; + return vout; +} + +float4 PS(VertexOut pin) : SV_Target +{ + return cubeMap.Sample(samTriLinearSam, pin.TexCoord); +} + diff --git a/Graphics2/SplitMeshNode.cpp b/Graphics2/SplitMeshNode.cpp index 8388821..98c20b2 100644 --- a/Graphics2/SplitMeshNode.cpp +++ b/Graphics2/SplitMeshNode.cpp @@ -5,6 +5,7 @@ bool SplitMeshNode::Initialise() bool currentStatus = true; _resourceManager = DirectXFramework::GetDXFramework()->GetResourceManager(); + _renderer = dynamic_pointer_cast(_resourceManager->GetRenderer(L"SMR")); _mesh = _resourceManager->GetMesh(_modelName); if (_mesh == nullptr) { @@ -20,9 +21,29 @@ bool SplitMeshNode::Initialise() currentStatus = SceneGraph::Initialise(); } + if (currentStatus) + { + currentStatus = _renderer->Initialise(); + } + return currentStatus; } +void SplitMeshNode::Render(void) +{ + _renderer->SetRootChildren(GetChildren()); + _renderer->SetWorldTransformation(XMLoadFloat4x4(&_combinedWorldTransformation)); + _renderer->SetAmbientLight(DirectXFramework::GetDXFramework()->GetGlobalLighting()->GetAmbientLight()); + _renderer->SetDirectionalLight(DirectXFramework::GetDXFramework()->GetGlobalLighting()->GetDirectionalLightDirection(), DirectXFramework::GetDXFramework()->GetGlobalLighting()->GetDirectionalLightColor()); + _renderer->Render(); +} + +void SplitMeshNode::Shutdown(void) +{ + _resourceManager->ReleaseMesh(_modelName); + SceneGraph::Shutdown(); +} + SceneNodePointer SplitMeshNode::AddMeshNode(shared_ptr node) { unsigned int subMeshCount = (unsigned int)node->GetMeshCount(); @@ -41,7 +62,14 @@ SceneNodePointer SplitMeshNode::AddMeshNode(shared_ptr node) { unsigned int meshIndex = node->GetMesh(i); shared_ptr subMesh = _mesh->GetSubMesh(meshIndex); - shared_ptr subNode = make_shared(node->GetName() + L"_" + to_wstring(i), subMesh); + shared_ptr material = subMesh->GetMaterial(); + float opacity = material->GetOpacity(); + bool transparent = false; + if (opacity < 1.0f) + { + transparent = true; + } + shared_ptr subNode = make_shared(node->GetName() + L"_" + to_wstring(i), subMesh, transparent); currentNodeGraph->Add(subNode); } diff --git a/Graphics2/SplitMeshNode.h b/Graphics2/SplitMeshNode.h index 3dd47c6..2f5d5c4 100644 --- a/Graphics2/SplitMeshNode.h +++ b/Graphics2/SplitMeshNode.h @@ -1,6 +1,7 @@ #pragma once #include "DirectXFramework.h" #include "SceneGraph.h" +#include "SubMeshRenderer.h" #include "SubMeshNode.h" class SplitMeshNode : public SceneGraph @@ -8,6 +9,8 @@ class SplitMeshNode : public SceneGraph public: SplitMeshNode(wstring name, wstring modelName) : SceneGraph(name) { _modelName = modelName; } bool Initialise(void); + void Render(void); + void Shutdown(void); SceneNodePointer AddMeshNode(shared_ptr node); private: diff --git a/Graphics2/SubMeshNode.cpp b/Graphics2/SubMeshNode.cpp index 7b9c3a7..225669f 100644 --- a/Graphics2/SubMeshNode.cpp +++ b/Graphics2/SubMeshNode.cpp @@ -1,26 +1,33 @@ #include "SubMeshNode.h" bool SubMeshNode::Initialise() -{ - _resourceManager = DirectXFramework::GetDXFramework()->GetResourceManager(); - _renderer = dynamic_pointer_cast(_resourceManager->GetRenderer(L"SMR")); +{ if (_subMesh == nullptr) { return false; } - return _renderer->Initialise(); + return true; } void SubMeshNode::Shutdown() -{ +{ } void SubMeshNode::Render() -{ - _renderer->SetSubMesh(_subMesh); - _renderer->SetWorldTransformation(XMLoadFloat4x4(&_combinedWorldTransformation)); - _renderer->SetCameraPosition(DirectXFramework::GetDXFramework()->GetCamera()->GetRawCameraPosition()); - _renderer->SetAmbientLight(XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f)); - _renderer->SetDirectionalLight(XMVectorSet(0.0f, -1.0f, 1.0f, 0.0f), XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f)); - _renderer->Render(); +{ +} + +bool SubMeshNode::IsTransparent() const +{ + return _transparent; +} + +shared_ptr SubMeshNode::GetSubMesh() const +{ + return _subMesh; +} + +XMFLOAT4X4 SubMeshNode::GetCurrentTransform() const +{ + return _combinedWorldTransformation; } diff --git a/Graphics2/SubMeshNode.h b/Graphics2/SubMeshNode.h index ea93b73..fbe26a2 100644 --- a/Graphics2/SubMeshNode.h +++ b/Graphics2/SubMeshNode.h @@ -1,21 +1,23 @@ #pragma once #include "DirectXFramework.h" #include "SceneNode.h" -#include "SubMeshRenderer.h" class SubMeshNode : public SceneNode { public: - SubMeshNode(wstring name, shared_ptr subMesh) : SceneNode(name) { _subMesh = subMesh; } + SubMeshNode(wstring name, shared_ptr subMesh, bool transparent = false) : SceneNode(name) { _subMesh = subMesh; _transparent = transparent; } bool Initialise(); void Render(); void Shutdown(); -private: - shared_ptr _renderer; - - shared_ptr _resourceManager; + bool IsTransparent() const; + shared_ptr GetSubMesh() const; + XMFLOAT4X4 GetCurrentTransform() const; + +private: shared_ptr _subMesh; + + bool _transparent; }; diff --git a/Graphics2/SubMeshRenderer.cpp b/Graphics2/SubMeshRenderer.cpp index f310ce5..4fc2882 100644 --- a/Graphics2/SubMeshRenderer.cpp +++ b/Graphics2/SubMeshRenderer.cpp @@ -1,8 +1,8 @@ #include "SubMeshRenderer.h" -void SubMeshRenderer::SetSubMesh(shared_ptr subMesh) +void SubMeshRenderer::SetRootChildren(list& rootChildren) { - _subMesh = subMesh; + _rootGraph = &rootChildren; } void SubMeshRenderer::SetWorldTransformation(FXMMATRIX worldTransformation) @@ -21,11 +21,6 @@ void SubMeshRenderer::SetDirectionalLight(FXMVECTOR lightVector, XMFLOAT4 lightC XMStoreFloat4(&_directionalLightVector, lightVector); } -void SubMeshRenderer::SetCameraPosition(XMFLOAT4 cameraPosition) -{ - _cameraPosition = cameraPosition; -} - bool SubMeshRenderer::Initialise() { _device = DirectXFramework::GetDXFramework()->GetDevice(); @@ -38,6 +33,60 @@ bool SubMeshRenderer::Initialise() return true; } +void SubMeshRenderer::RenderChild(SceneNodePointer node, bool renderTransparent) +{ + shared_ptr currentMeshNode = dynamic_pointer_cast(node); + + if (currentMeshNode != nullptr) + { + XMMATRIX projectionTransformation = DirectXFramework::GetDXFramework()->GetProjectionTransformation(); + XMMATRIX viewTransformation = DirectXFramework::GetDXFramework()->GetCamera()->GetViewMatrix(); + + XMMATRIX completeTransformation = XMLoadFloat4x4(¤tMeshNode->GetCurrentTransform()) * viewTransformation * projectionTransformation; + + shared_ptr subMesh = currentMeshNode->GetSubMesh(); + shared_ptr material = subMesh->GetMaterial(); + float opacity = material->GetOpacity(); + if ((renderTransparent && opacity < 1.0f) || + (!renderTransparent && opacity == 1.0f)) + { + _cBuffer.completeTransformation = completeTransformation; + _cBuffer.worldTransformation = XMLoadFloat4x4(¤tMeshNode->GetCurrentTransform()); + + UINT stride = sizeof(VERTEX); + UINT offset = 0; + _vertexBuffer = subMesh->GetVertexBuffer(); + _deviceContext->IASetVertexBuffers(0, 1, _vertexBuffer.GetAddressOf(), &stride, &offset); + _indexBuffer = subMesh->GetIndexBuffer(); + _deviceContext->IASetIndexBuffer(_indexBuffer.Get(), DXGI_FORMAT_R32_UINT, 0); + _cBuffer.diffuseCoefficient = material->GetDiffuseColour(); + _cBuffer.specularCoefficient = material->GetSpecularColour(); + _cBuffer.shininess = material->GetShininess(); + _cBuffer.opacity = opacity; + // Update the constant buffer + _deviceContext->VSSetConstantBuffers(0, 1, _constantBuffer.GetAddressOf()); + _deviceContext->UpdateSubresource(_constantBuffer.Get(), 0, 0, &_cBuffer, 0, 0); + _texture = material->GetTexture(); + _deviceContext->PSSetShaderResources(0, 1, _texture.GetAddressOf()); + _deviceContext->PSSetConstantBuffers(0, 1, _constantBuffer.GetAddressOf()); + _deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + _deviceContext->DrawIndexed(static_cast(subMesh->GetIndexCount()), 0, 0); + } + } + + shared_ptr currentGraphNode = dynamic_pointer_cast(node); + + if (currentGraphNode != nullptr) + { + // Render the children + // Loop through all submeshes in the mesh, rendering them + for (SceneNodePointer& child : currentGraphNode->GetChildren()) + { + RenderChild(child, renderTransparent); + } + } +} + void SubMeshRenderer::Render() { // Turn off back face culling while we render a mesh. @@ -46,20 +95,12 @@ void SubMeshRenderer::Render() // back face culling, some materials do not render correctly. _deviceContext->RSSetState(_noCullRasteriserState.Get()); - XMMATRIX projectionTransformation = DirectXFramework::GetDXFramework()->GetProjectionTransformation(); - XMMATRIX viewTransformation = DirectXFramework::GetDXFramework()->GetCamera()->GetViewMatrix(); - - XMMATRIX completeTransformation = XMLoadFloat4x4(&_worldTransformation) * viewTransformation * projectionTransformation; - - // Draw the first cube - - CBUFFER cBuffer; - cBuffer.completeTransformation = completeTransformation; - cBuffer.worldTransformation = XMLoadFloat4x4(&_worldTransformation); - cBuffer.ambientColor = _ambientLight; - cBuffer.lightVector = XMVector4Normalize(XMLoadFloat4(&_directionalLightVector)); - cBuffer.lightColor = _directionalLightColour; - cBuffer.cameraPosition = _cameraPosition; + // Reset the CBUFFER since its now a class member. + _cBuffer = CBUFFER(); + _cBuffer.ambientColor = _ambientLight; + _cBuffer.lightVector = XMVector4Normalize(XMLoadFloat4(&_directionalLightVector)); + _cBuffer.lightColor = _directionalLightColour; + XMStoreFloat4(&_cBuffer.cameraPosition, DirectXFramework::GetDXFramework()->GetCamera()->GetCameraPosition()); _deviceContext->VSSetShader(_vertexShader.Get(), 0, 0); _deviceContext->PSSetShader(_pixelShader.Get(), 0, 0); @@ -69,27 +110,20 @@ void SubMeshRenderer::Render() float blendFactors[] = { 0.0f, 0.0f, 0.0f, 0.0f }; _deviceContext->OMSetBlendState(_transparentBlendState.Get(), blendFactors, 0xffffffff); - shared_ptr material = _subMesh->GetMaterial(); - float opacity = material->GetOpacity(); - - UINT stride = sizeof(VERTEX); - UINT offset = 0; - _vertexBuffer = _subMesh->GetVertexBuffer(); - _deviceContext->IASetVertexBuffers(0, 1, _vertexBuffer.GetAddressOf(), &stride, &offset); - _indexBuffer = _subMesh->GetIndexBuffer(); - _deviceContext->IASetIndexBuffer(_indexBuffer.Get(), DXGI_FORMAT_R32_UINT, 0); - cBuffer.diffuseCoefficient = material->GetDiffuseColour(); - cBuffer.specularCoefficient = material->GetSpecularColour(); - cBuffer.shininess = material->GetShininess(); - cBuffer.opacity = opacity; - // Update the constant buffer - _deviceContext->VSSetConstantBuffers(0, 1, _constantBuffer.GetAddressOf()); - _deviceContext->UpdateSubresource(_constantBuffer.Get(), 0, 0, &cBuffer, 0, 0); - _texture = material->GetTexture(); - _deviceContext->PSSetShaderResources(0, 1, _texture.GetAddressOf()); - _deviceContext->PSSetConstantBuffers(0, 1, _constantBuffer.GetAddressOf()); - _deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - _deviceContext->DrawIndexed(static_cast(_subMesh->GetIndexCount()), 0, 0); + // We do two passes through the nodes. The first time we render nodes + // that are not transparent (i.e. their opacity == 1.0f). + for (SceneNodePointer& child : *_rootGraph) + { + RenderChild(child, false); + } + // Now we render any transparent nodes + // We have to do this since blending always blends the submesh with + // whatever is in the render target. If we render a transparent node + // first, it will be opaque. + for (SceneNodePointer& child : *_rootGraph) + { + RenderChild(child, true); + } // Turn back face culling back on in case another renderer // relies on it @@ -202,3 +236,4 @@ void SubMeshRenderer::BuildRendererState() rasteriserDesc.CullMode = D3D11_CULL_NONE; ThrowIfFailed(_device->CreateRasterizerState(&rasteriserDesc, _noCullRasteriserState.GetAddressOf())); } + diff --git a/Graphics2/SubMeshRenderer.h b/Graphics2/SubMeshRenderer.h index 42f818d..7513b63 100644 --- a/Graphics2/SubMeshRenderer.h +++ b/Graphics2/SubMeshRenderer.h @@ -1,22 +1,24 @@ #pragma once #include "SharedMethods.h" #include "DirectXFramework.h" +#include "SubMeshNode.h" #include "Renderer.h" #include "Mesh.h" class SubMeshRenderer : public Renderer { -public: - void SetSubMesh(shared_ptr subMesh); +public: + void SetRootChildren(list& rootChildren); void SetWorldTransformation(FXMMATRIX worldTransformation); void SetAmbientLight(XMFLOAT4 ambientLight); void SetDirectionalLight(FXMVECTOR lightVector, XMFLOAT4 lightColour); - void SetCameraPosition(XMFLOAT4 cameraPosition); - bool Initialise(); + bool Initialise(); void Render(); void Shutdown(void); private: + list* _rootGraph; + shared_ptr _subMesh; XMFLOAT4X4 _worldTransformation; XMFLOAT4 _ambientLight; @@ -44,10 +46,14 @@ private: ComPtr _defaultRasteriserState; ComPtr _noCullRasteriserState; + CBUFFER _cBuffer; + void BuildShaders(); void BuildVertexLayout(); void BuildConstantBuffer(); void BuildBlendState(); void BuildRendererState(); + + void RenderChild(SceneNodePointer node, bool renderTransparent); }; diff --git a/Graphics2/TerrainNode.cpp b/Graphics2/TerrainNode.cpp index b5760dc..ad82dfe 100644 --- a/Graphics2/TerrainNode.cpp +++ b/Graphics2/TerrainNode.cpp @@ -2,9 +2,8 @@ #define WORLD_HEIGHT 1024 -TerrainNode::TerrainNode(wstring name, wstring heightMap, wstring seed, float waterHeight, wstring waterNormalMap, int widthX, int widthZ, int cellSizeX, int cellSizeZ) : SceneNode(name) -{ - _heightMap = heightMap; +TerrainNode::TerrainNode(wstring name, wstring seed, float waterHeight, int widthX, int widthZ, int cellSizeX, int cellSizeZ) : SceneNode(name) +{ _seedString = seed; _seedHash = std::hash{}(_seedString); @@ -20,11 +19,10 @@ TerrainNode::TerrainNode(wstring name, wstring heightMap, wstring seed, float wa _cellSizeZ = cellSizeZ; _waterHeight = waterHeight; - _waterNormalMapName = waterNormalMap; _polygonsCount = (_gridCols * _gridRows) * 2; _vertexCount = _polygonsCount * 2; - _indiciesCount = _polygonsCount * 3; + _indicesCount = _polygonsCount * 3; } void TerrainNode::SetAmbientLight(XMFLOAT4 ambientLight) @@ -43,38 +41,18 @@ void TerrainNode::SetDirectionalLight(FXMVECTOR lightVector, XMFLOAT4 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) + if (_device.Get() == nullptr || _deviceContext.Get() == nullptr || _initError) { return false; } - if (_heightMap.length() > 0) - { - if (LoadHeightMap(_heightMap)) - { - _usedHeightMap = true; - } - else - { - _usedHeightMap = false; - } - } - else - { - _usedHeightMap = false; - } - GenerateTerrainData(); + GenerateTerrainNormals(); LoadTerrainTextures(); GenerateBlendMap(); BuildExtraMaps(); @@ -89,7 +67,7 @@ bool TerrainNode::Initialise() } void TerrainNode::GenerateTerrainData() -{ +{ float totalWidth = (float)(_gridCols * _cellSizeX); float totalDepth = (float)(_gridRows * _cellSizeZ); @@ -121,16 +99,16 @@ void TerrainNode::GenerateTerrainData() offsetIndexZ = 0; } - float rUA = 0.0f; - float rVA = rUA; // 0.0f; - float rUB = 1.0f; - float rVB = rUB; + // Generate pairs of random UV's + float rUA = SharedMethods::GenerateRandomUV(0.0f, 0.25f); + float rVA = SharedMethods::GenerateRandomUV(0.0f, 0.25f); //rUA; // 0.0f; + float rUB = SharedMethods::GenerateRandomUV(0.75f, 1.0f); + float rVB = SharedMethods::GenerateRandomUV(0.75f, 1.0f); //rUB; - - /*int tumbleAmount = rand() % 10; + // Rotate the UV's around a bit to add some more variance + int tumbleAmount = rand() % 10; float prevUV = 0.0f; - bool firstTumble = true; for (int ti = 0; ti < tumbleAmount; ti++) { prevUV = rVB; @@ -138,11 +116,11 @@ void TerrainNode::GenerateTerrainData() rUB = rVA; rVA = rUA; rUA = prevUV; - }*/ + } // TL TerrainVertex vertex{}; - vertex.Position = XMFLOAT3(x * _cellSizeX + centerWidth, GetHeightMapValueAt(currentIndex), (-z + 1) * _cellSizeZ + centerDepth); + vertex.Position = XMFLOAT3(x * _cellSizeX + centerWidth, GetHeightValueAt(currentIndex), (-z + 1) * _cellSizeZ + centerDepth); vertex.Normal = XMFLOAT3(0.0f, 0.0f, 0.0f); vertex.TexCoord = XMFLOAT2(rUA, rVA); vertex.BlendMapTexCoord = XMFLOAT2((bu * x), (bv * z)); @@ -150,7 +128,7 @@ void TerrainNode::GenerateTerrainData() // TR vertex = TerrainVertex(); - vertex.Position = XMFLOAT3((x + 1) * _cellSizeX + centerWidth, GetHeightMapValueAt(currentIndex + offsetIndexX), (-z + 1) * _cellSizeZ + centerDepth); + vertex.Position = XMFLOAT3((x + 1) * _cellSizeX + centerWidth, GetHeightValueAt(currentIndex + offsetIndexX), (-z + 1) * _cellSizeZ + centerDepth); vertex.Normal = XMFLOAT3(0.0f, 0.0f, 0.0f); vertex.TexCoord = XMFLOAT2(rUB, rVA); vertex.BlendMapTexCoord = XMFLOAT2((bu * (x + 1)), (bv * z)); @@ -158,7 +136,7 @@ void TerrainNode::GenerateTerrainData() // BL vertex = TerrainVertex(); - vertex.Position = XMFLOAT3(x * _cellSizeX + centerWidth, GetHeightMapValueAt(currentIndex + offsetIndexZ), -z * _cellSizeZ + centerDepth); + vertex.Position = XMFLOAT3(x * _cellSizeX + centerWidth, GetHeightValueAt(currentIndex + offsetIndexZ), -z * _cellSizeZ + centerDepth); vertex.Normal = XMFLOAT3(0.0f, 0.0f, 0.0f); vertex.TexCoord = XMFLOAT2(rUA, rVB); vertex.BlendMapTexCoord = XMFLOAT2((bu * x), (bv * (z + 1))); @@ -166,7 +144,7 @@ void TerrainNode::GenerateTerrainData() // BR vertex = TerrainVertex(); - vertex.Position = XMFLOAT3((x + 1) * _cellSizeX + centerWidth, GetHeightMapValueAt(currentIndex + offsetIndexZ + offsetIndexX), -z * _cellSizeZ + centerDepth); + vertex.Position = XMFLOAT3((x + 1) * _cellSizeX + centerWidth, GetHeightValueAt(currentIndex + offsetIndexZ + offsetIndexX), -z * _cellSizeZ + centerDepth); vertex.Normal = XMFLOAT3(0.0f, 0.0f, 0.0f); vertex.TexCoord = XMFLOAT2(rUB, rVB); vertex.BlendMapTexCoord = XMFLOAT2((bu * (x + 1)), (bv * (z + 1))); @@ -182,7 +160,10 @@ void TerrainNode::GenerateTerrainData() currentVertexCount += 4; } } +} +void TerrainNode::GenerateTerrainNormals() +{ int currentNormalIndex = 0; for (int z = 0; z < _gridRows; z++) { @@ -243,6 +224,13 @@ void TerrainNode::AddNormalToVertex(int row, int col, int vertexIndex, XMVECTOR } } +float TerrainNode::GetHeightValueAt(int index) +{ + float result = _heightValues[index] * WORLD_HEIGHT; // +(rand() % 10); + + return result; +} + void TerrainNode::GenerateBuffers() { // Setup the structure that specifies how big the vertex @@ -267,7 +255,7 @@ void TerrainNode::GenerateBuffers() // buffer should be D3D11_BUFFER_DESC indexBufferDescriptor; indexBufferDescriptor.Usage = D3D11_USAGE_IMMUTABLE; - indexBufferDescriptor.ByteWidth = sizeof(UINT) * _indiciesCount; + indexBufferDescriptor.ByteWidth = sizeof(UINT) * _indicesCount; indexBufferDescriptor.BindFlags = D3D11_BIND_INDEX_BUFFER; indexBufferDescriptor.CPUAccessFlags = 0; indexBufferDescriptor.MiscFlags = 0; @@ -302,13 +290,13 @@ void TerrainNode::Render() XMStoreFloat4(&cBuffer.cameraPosition, DirectXFramework::GetDXFramework()->GetCamera()->GetCameraPosition()); cBuffer.waterHeight = _waterHeight; - cBuffer.waterShininess = 15.0f; + cBuffer.waterShininess = 10.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->PSSetShaderResources(3, 1, _snowTest.GetAddressOf()); _deviceContext->VSSetShader(_vertexShader.Get(), 0, 0); _deviceContext->PSSetShader(_pixelShader.Get(), 0, 0); @@ -320,7 +308,7 @@ void TerrainNode::Render() _deviceContext->IASetIndexBuffer(_indexBuffer.Get(), DXGI_FORMAT_R32_UINT, 0); cBuffer.diffuseCoefficient = XMFLOAT4(0.8f, 0.8f, 0.8f, 1.0f); cBuffer.specularCoefficient = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f); - cBuffer.shininess = 10.0f; + cBuffer.shininess = 5.0f; cBuffer.opacity = 1.0f; // Update the constant buffer @@ -330,7 +318,7 @@ void TerrainNode::Render() _deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); //_deviceContext->RSSetState(_wireframeRasteriserState.Get()); - _deviceContext->DrawIndexed(_indiciesCount, 0, 0); + _deviceContext->DrawIndexed(_indicesCount, 0, 0); } void TerrainNode::Shutdown(void) @@ -425,41 +413,6 @@ void TerrainNode::BuildRendererStates() ThrowIfFailed(_device->CreateRasterizerState(&rasteriserDesc, _wireframeRasteriserState.GetAddressOf())); } -bool TerrainNode::LoadHeightMap(wstring heightMapFilename) -{ - unsigned int mapSize = _gridCols * _gridRows; - USHORT* rawFileValues = new USHORT[mapSize]; - - std::ifstream inputHeightMap; - inputHeightMap.open(heightMapFilename.c_str(), std::ios_base::binary); - if (!inputHeightMap) - { - return false; - } - - inputHeightMap.read((char*)rawFileValues, mapSize * 2); - inputHeightMap.close(); - - // Normalise BYTE values to the range 0.0f - 1.0f; - for (unsigned int i = 0; i < mapSize; i++) - { - _heightValues.push_back((float)rawFileValues[i] / 65536); - } - delete[] rawFileValues; - return true; -} - -float TerrainNode::GetHeightMapValueAt(int index) -{ - float result = 0; - if (_usedHeightMap) - { - result = _heightValues[index] * WORLD_HEIGHT; // +(rand() % 10); - } - - return result; -} - void TerrainNode::LoadTerrainTextures() { // Change the paths below as appropriate for your use @@ -535,18 +488,26 @@ void TerrainNode::LoadTerrainTextures() viewDescription.Texture2DArray.ArraySize = 5; ThrowIfFailed(_device->CreateShaderResourceView(textureArray.Get(), &viewDescription, _texturesResourceView.GetAddressOf())); + + // Cheeky load in the snow hack to solve that weird issue + wstring snowTestName = L"Textures\\snow.dds"; + ThrowIfFailed(CreateDDSTextureFromFile(_device.Get(), + snowTestName.c_str(), + nullptr, + _snowTest.GetAddressOf() + )); } void TerrainNode::GenerateBlendMap() { RGBA snowTops = RGBA{ 0u, 0u, 0u, 255u }; - RGBA grassLand = RGBA{ 0u, 0u, 50u, 0u }; + RGBA grassLand = RGBA{ 0u, 0u, 0u, 0u }; RGBA lightDirt = RGBA{ 50u, 0u, 255u, 0u }; - RGBA darkDirt = RGBA{ 255u, 0u, 0u, 0u }; + RGBA darkDirt = RGBA{ 255u, 50u, 50u, 0u }; vector colorSteps = {darkDirt, lightDirt, grassLand, grassLand, grassLand, snowTops}; - ColorGradient terrainBlendGradient = ColorGradient(30.0f, 650.0f, colorSteps); + ColorGradient terrainBlendGradient = ColorGradient(80.0f, 620.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 @@ -563,7 +524,10 @@ void TerrainNode::GenerateBlendMap() { for (DWORD j = 0; j < _gridCols; j++) { - + r = 0u; + g = 0u; + b = 0u; + a = 0u; // 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 @@ -588,10 +552,10 @@ void TerrainNode::GenerateBlendMap() float avgHeight = totalHeights / 4.0f; RGBA currentBlend = terrainBlendGradient.GetRGBAValue(avgHeight); - r = currentBlend.red; - g = currentBlend.green; - b = currentBlend.blue; - a = currentBlend.alpha; + r = (BYTE)currentBlend.red; + g = (BYTE)currentBlend.green; + b = (BYTE)currentBlend.blue; + a = (BYTE)currentBlend.alpha; DWORD mapValue = (a << 24) + (b << 16) + (g << 8) + r; *blendMapPtr++ = mapValue; @@ -635,17 +599,71 @@ void TerrainNode::BuildExtraMaps() // Initialise method (and make the corresponding call to // CoUninitialize in the Shutdown method). Otherwise, // the following call will throw an exception + wstring waterNormalMapName = L"Textures\\waterNormals.bmp"; ThrowIfFailed(CreateWICTextureFromFile(_device.Get(), _deviceContext.Get(), - _waterNormalMapName.c_str(), + waterNormalMapName.c_str(), nullptr, _waterNormalMap.GetAddressOf() )); +} - ThrowIfFailed(CreateWICTextureFromFile(_device.Get(), - _deviceContext.Get(), - L"Textures\\noiseMap.png", - nullptr, - _rngNoiseMap.GetAddressOf() - )); +float TerrainNode::GetHeightAtPoint(float x, float z, bool waterCollide) +{ + int cellX = (int)((x - _terrainStartX) / _cellSizeX); + int cellZ = (int)((_terrainStartZ - z) / _cellSizeZ); + + int currentIndex = (cellZ * _gridCols * 4) + (cellX * 4); + + float dx = x - _terrainVerts[currentIndex].Position.x; + float dz = z - _terrainVerts[currentIndex].Position.z; + + int currentNormalIndex = ((cellZ * _gridCols) + cellX) * 6; + if (dx < dz) + { + currentNormalIndex += 3; + } + + XMVECTOR v1 = XMVectorSet(_terrainVerts[_indices[currentNormalIndex + 1]].Position.x - _terrainVerts[_indices[currentNormalIndex]].Position.x, + _terrainVerts[_indices[currentNormalIndex + 1]].Position.y - _terrainVerts[_indices[currentNormalIndex]].Position.y, + _terrainVerts[_indices[currentNormalIndex + 1]].Position.z - _terrainVerts[_indices[currentNormalIndex]].Position.z, + 0.0f); + XMVECTOR v2 = XMVectorSet(_terrainVerts[_indices[currentNormalIndex + 2]].Position.x - _terrainVerts[_indices[currentNormalIndex]].Position.x, + _terrainVerts[_indices[currentNormalIndex + 2]].Position.y - _terrainVerts[_indices[currentNormalIndex]].Position.y, + _terrainVerts[_indices[currentNormalIndex + 2]].Position.z - _terrainVerts[_indices[currentNormalIndex]].Position.z, + 0.0f); + + XMFLOAT4 normal; + XMStoreFloat4(&normal, XMVector3Normalize(XMVector3Cross(v1, v2))); + + float result = _terrainVerts[currentIndex].Position.y + (normal.x * dx + normal.z * dz) / -normal.y; + if (waterCollide) + { + if (result <= _waterHeight) + { + result = _waterHeight; + } + } + + return result; +} + +bool TerrainNode::CheckXBoundary(float x) +{ + if (!(x > _terrainStartX && x < _terrainEndX)) + { + return false; + } + + return true; +} + +bool TerrainNode::CheckZBoundary(float z) +{ + if (!(z < _terrainStartZ && z > _terrainEndZ)) + { + return false; + } + + return true; } \ No newline at end of file diff --git a/Graphics2/TerrainNode.h b/Graphics2/TerrainNode.h index 4bb700d..16ffaa2 100644 --- a/Graphics2/TerrainNode.h +++ b/Graphics2/TerrainNode.h @@ -2,6 +2,7 @@ #include "DirectXFramework.h" #include #include +#include #include "ColorGradient.h" #include "DDSTextureLoader.h" #include "WICTextureLoader.h" @@ -17,21 +18,44 @@ typedef struct TerrainVertex XMFLOAT2 BlendMapTexCoord; } TerrainVertex; +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]; +}; + class TerrainNode : public SceneNode { public: - 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); + TerrainNode(wstring name, wstring seed, float waterHeight = 150.0f, 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); + bool virtual Initialise(void); void Render(void); - void Shutdown(void); + void virtual Shutdown(void); + + float GetHeightAtPoint(float x, float z, bool waterCollide = false); + bool CheckXBoundary(float x); + bool CheckZBoundary(float z); + +protected: + bool _initError = false; -private: int _widthX; int _widthZ; @@ -41,25 +65,22 @@ private: int _cellSizeX; int _cellSizeZ; - bool _usedHeightMap; - float _waterHeight; UINT _polygonsCount; - UINT _indiciesCount; + UINT _indicesCount; UINT _vertexCount; float _terrainStartX; float _terrainStartZ; float _terrainEndX; float _terrainEndZ; - - wstring _heightMap; + wstring _seedString; unsigned int _seedHash; vector _terrainVerts; - vector _indices; + vector _indices; vector _heightValues; XMFLOAT4 _ambientLight; @@ -86,12 +107,12 @@ private: ComPtr _defaultRasteriserState; ComPtr _wireframeRasteriserState; - ComPtr _rngNoiseMap; + ComPtr _snowTest; ComPtr _waterNormalMap; - wstring _waterNormalMapName; XMFLOAT4 _waterColor; - void GenerateTerrainData(); + void virtual GenerateTerrainData(); + void GenerateTerrainNormals(); void GenerateBuffers(); void BuildShaders(); void BuildVertexLayout(); @@ -101,8 +122,7 @@ private: void LoadTerrainTextures(); void GenerateBlendMap(); - bool LoadHeightMap(wstring heightMapFilename); - float GetHeightMapValueAt(int index); + float GetHeightValueAt(int index); void AddNormalToVertex(int row, int col, int vertexIndex, XMVECTOR normal); void BuildExtraMaps(); diff --git a/Graphics2/TerrainShaders.hlsl b/Graphics2/TerrainShaders.hlsl index 9b18504..e867409 100644 --- a/Graphics2/TerrainShaders.hlsl +++ b/Graphics2/TerrainShaders.hlsl @@ -11,16 +11,19 @@ cbuffer ConstantBuffer float shininess; // The shininess factor float opacity; // The opacity (transparency) of the material. 0 = fully transparent, 1 = fully opaque + // Vars to deal with the water, also padding because the cbuffer needs to be a multiple of 16 float waterHeight; float waterShininess; float4 waterColor; + + // Padded with a float array, floats being 4 bytes each, the above just hits the multiple of 16 but added extra incase this was the issue, will remove later most likely float padding[4]; } Texture2D BlendMap : register(t0); Texture2DArray TexturesArray : register(t1); Texture2D WaterNormalMap : register(t2); -Texture2D rngNoiseMap : register(t3); +Texture2D snowTest : register(t3); SamplerState ss { @@ -42,6 +45,7 @@ struct PixelShaderInput { float4 Position : SV_POSITION; float4 PositionWS: TEXCOORD2; + float4 PositionOG: TEXCOORD4; float4 NormalWS : TEXCOORD3; float2 TexCoord : TEXCOORD0; float2 BlendMapTexCoord : TEXCOORD1; @@ -63,14 +67,17 @@ PixelShaderInput VShader(VertexShaderInput vin) { PixelShaderInput output; float3 position = vin.Position; + output.PositionOG = output.PositionWS = mul(worldTransformation, float4(position, 1.0f)); + output.TexCoord = vin.TexCoord; + // Check if the y pos is lower than the water point, and set the position to it minus a tiny offset because the textures were clipping and causing a weird effect if (position.y < waterHeight) { - position.y = waterHeight - 0.01f; + position.y = waterHeight; } 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); - output.TexCoord = vin.TexCoord; + output.BlendMapTexCoord = vin.BlendMapTexCoord; return output; } @@ -87,11 +94,15 @@ float4 PShader(PixelShaderInput input) : SV_TARGET float4 directionToLight = normalize(-lightVector); float surfaceShininess = shininess; float4 adjustedNormal = normalize(input.NormalWS); - if (input.PositionWS.y < waterHeight) + + float currentHeightPer = (waterHeight - input.PositionOG.y) / waterHeight; + + if (input.PositionOG.y < waterHeight) { - float3 n0 = (float3)WaterNormalMap.Sample(ss, input.TexCoord); + // Sample the normal from the water normal map and calculate it with the worldtransform + float3 n0 = 2.0f * (float3)WaterNormalMap.Sample(ss, input.TexCoord) - 1.0f; float4 n2 = float4(mul((float3x3)worldTransformation, n0), 1.0f); - adjustedNormal = n2; + adjustedNormal = normalize(n2); surfaceShininess = waterShininess; } @@ -110,11 +121,11 @@ float4 PShader(PixelShaderInput input) : SV_TARGET float4 ambientLight = ambientColor * diffuseCoefficient; float4 color; - float4 randSamp = rngNoiseMap.Sample(ss, input.BlendMapTexCoord); - + // Randomly rotate the UV coordinates using the noise map float2 scaleCenter = float2(0.5f, 0.5f); - float currentScale = randSamp.r; - float2 scaledUV = frac(UVRotate(input.TexCoord, scaleCenter, currentScale)); // (input.TexCoord - scaleCenter) * currentScale + scaleCenter; + // The noise map is greyscale so we only need to check 1 channel since they should all be the same value + + float2 scaledUV = frac(UVRotate(input.TexCoord, scaleCenter, input.BlendMapTexCoord.x)); // (input.TexCoord - scaleCenter) * currentScale + scaleCenter; float2 xChange = ddx(scaledUV); float2 yChange = ddy(scaledUV); @@ -133,7 +144,8 @@ float4 PShader(PixelShaderInput input) : SV_TARGET 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); + //float4 c4 = TexturesArray.SampleGrad(ss, float3(scaledUV, 4.0f), xChange, yChange); + float4 c4 = snowTest.SampleGrad(ss, float2(scaledUV), xChange, yChange); // Sample the blend map. float4 t = BlendMap.Sample(ss, input.BlendMapTexCoord); @@ -146,9 +158,10 @@ float4 PShader(PixelShaderInput input) : SV_TARGET color = lerp(color, c4, t.a); // Combine all components - if (input.PositionWS.y < waterHeight) + if (input.PositionOG.y < waterHeight) { - color = color * waterColor; + // Tint the water + color = saturate(color) * waterColor; } color = (ambientLight + diffuse) * color; color = saturate(color + specular); diff --git a/Graphics2/TexturedCubeNode.cpp b/Graphics2/TexturedCubeNode.cpp index 3090a23..9238231 100644 --- a/Graphics2/TexturedCubeNode.cpp +++ b/Graphics2/TexturedCubeNode.cpp @@ -7,15 +7,6 @@ struct Vertex XMFLOAT2 TextureCoordinate; }; -struct CBUFFER -{ - XMMATRIX CompleteTransformation; - XMMATRIX WorldTransformation; - XMVECTOR LightVector; - XMFLOAT4 LightColour; - XMFLOAT4 AmbientColour; -}; - bool TexturedCubeNode::Initialise() { _device = DirectXFramework::GetDXFramework()->GetDevice(); @@ -45,11 +36,11 @@ void TexturedCubeNode::Render() // Draw the first cube CBUFFER cBuffer; - cBuffer.CompleteTransformation = completeTransformation; - cBuffer.WorldTransformation = XMLoadFloat4x4(&_combinedWorldTransformation); - cBuffer.AmbientColour = XMFLOAT4(0.3f, 0.3f, 0.3f, 1.0f); - cBuffer.LightVector = XMVector4Normalize(XMVectorSet(0.0f, 1.0f, 1.0f, 0.0f)); - cBuffer.LightColour = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f); + cBuffer.completeTransformation = completeTransformation; + cBuffer.worldTransformation = XMLoadFloat4x4(&_combinedWorldTransformation); + cBuffer.ambientColor = XMFLOAT4(0.3f, 0.3f, 0.3f, 1.0f); + cBuffer.lightVector = XMVector4Normalize(XMVectorSet(0.0f, 1.0f, 1.0f, 0.0f)); + cBuffer.lightColor = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f); // Update the constant buffer _deviceContext->VSSetConstantBuffers(0, 1, _constantBuffer.GetAddressOf()); @@ -170,7 +161,7 @@ void TexturedCubeNode::BuildShaders() ComPtr compilationMessages = nullptr; //Compile vertex shader - HRESULT hr = D3DCompileFromFile(L"shader.hlsl", + HRESULT hr = D3DCompileFromFile(L"TexturedShaders.hlsl", nullptr, D3D_COMPILE_STANDARD_FILE_INCLUDE, "VS", "vs_5_0", shaderCompileFlags, 0, @@ -188,7 +179,7 @@ void TexturedCubeNode::BuildShaders() _deviceContext->VSSetShader(_vertexShader.Get(), 0, 0); // Compile pixel shader - hr = D3DCompileFromFile(L"shader.hlsl", + hr = D3DCompileFromFile(L"TexturedShaders.hlsl", nullptr, D3D_COMPILE_STANDARD_FILE_INCLUDE, "PS", "ps_5_0", shaderCompileFlags, 0, diff --git a/Graphics2/Textures/SkyDawn.dds b/Graphics2/Textures/SkyDawn.dds new file mode 100644 index 0000000..64b5065 Binary files /dev/null and b/Graphics2/Textures/SkyDawn.dds differ diff --git a/Graphics2/Textures/SkyWater.dds b/Graphics2/Textures/SkyWater.dds new file mode 100644 index 0000000..add1e64 Binary files /dev/null and b/Graphics2/Textures/SkyWater.dds differ diff --git a/Graphics2/Textures/cloudySky.dds b/Graphics2/Textures/cloudySky.dds new file mode 100644 index 0000000..72d080a Binary files /dev/null and b/Graphics2/Textures/cloudySky.dds differ diff --git a/Graphics2/Textures/darkdirtB.dds b/Graphics2/Textures/darkdirtB.dds new file mode 100644 index 0000000..c225b46 Binary files /dev/null and b/Graphics2/Textures/darkdirtB.dds differ diff --git a/Graphics2/Textures/grassB.dds b/Graphics2/Textures/grassB.dds new file mode 100644 index 0000000..c27c72e Binary files /dev/null and b/Graphics2/Textures/grassB.dds differ diff --git a/Graphics2/Textures/lightdirtB.dds b/Graphics2/Textures/lightdirtB.dds new file mode 100644 index 0000000..5439d2b Binary files /dev/null and b/Graphics2/Textures/lightdirtB.dds differ diff --git a/Graphics2/Textures/skymap.dds b/Graphics2/Textures/skymap.dds new file mode 100644 index 0000000..23e6437 Binary files /dev/null and b/Graphics2/Textures/skymap.dds differ diff --git a/Graphics2/Textures/snowB.dds b/Graphics2/Textures/snowB.dds new file mode 100644 index 0000000..4f1ddbe Binary files /dev/null and b/Graphics2/Textures/snowB.dds differ diff --git a/Graphics2/Textures/stoneB.dds b/Graphics2/Textures/stoneB.dds new file mode 100644 index 0000000..f2a4195 Binary files /dev/null and b/Graphics2/Textures/stoneB.dds differ diff --git a/Graphics2/Textures/testheightmap2.zip b/Graphics2/Textures/testheightmap2.zip deleted file mode 100644 index d04d23e..0000000 Binary files a/Graphics2/Textures/testheightmap2.zip and /dev/null differ diff --git a/Graphics2/Textures/waterNormalsB.dds b/Graphics2/Textures/waterNormalsB.dds new file mode 100644 index 0000000..5dcdee4 Binary files /dev/null and b/Graphics2/Textures/waterNormalsB.dds differ diff --git a/Graphics2/Textures/waterNormalsB.jpg b/Graphics2/Textures/waterNormalsB.jpg new file mode 100644 index 0000000..fbafa1f Binary files /dev/null and b/Graphics2/Textures/waterNormalsB.jpg differ