Added follow cam
Added "Controlled" mesh classes Added Global Lighting Class Added Gamepad controls Split terrain nodes into Height and Perlin classes Fixed Splitmesh node stuff
This commit is contained in:
@ -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<ObjectNode> 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));
|
||||
|
@ -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<ObjectNode> nodeFollowed, XMFLOAT3 followOffset, bool positionOnly);
|
||||
|
||||
private:
|
||||
XMFLOAT4 _cameraPosition;
|
||||
@ -37,5 +41,8 @@ private:
|
||||
float _cameraPitch;
|
||||
float _cameraRoll;
|
||||
|
||||
shared_ptr<ObjectNode> _nodeFollowed;
|
||||
XMFLOAT3 _followOffset;
|
||||
bool _followPositionOnly;
|
||||
};
|
||||
|
||||
|
@ -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<float>(pointValue * 1.5f, 0.0f, 1.0f);
|
||||
|
||||
// Lerp the color values for each channel between the steps
|
||||
unsigned int currentRed = (unsigned int)SharedMethods::Lerp<unsigned int>(a.red, b.red, pointValue);
|
||||
unsigned int currentGreen = (unsigned int)SharedMethods::Lerp<unsigned int>(a.green, b.green, pointValue);
|
||||
unsigned int currentBlue = (unsigned int)SharedMethods::Lerp<unsigned int>(a.blue, b.blue, pointValue);
|
||||
unsigned int currentAlpha = (unsigned int)SharedMethods::Lerp<unsigned int>(a.alpha, b.alpha, pointValue);
|
||||
|
||||
return RGBA{ currentRed, currentGreen, currentBlue, currentAlpha };
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include "SharedMethods.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
24
Graphics2/ControlledMeshNode.cpp
Normal file
24
Graphics2/ControlledMeshNode.cpp
Normal file
@ -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);
|
||||
}
|
18
Graphics2/ControlledMeshNode.h
Normal file
18
Graphics2/ControlledMeshNode.h
Normal file
@ -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:
|
||||
|
||||
};
|
||||
|
25
Graphics2/ControlledSplitMeshNode.cpp
Normal file
25
Graphics2/ControlledSplitMeshNode.cpp
Normal file
@ -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);
|
||||
}
|
20
Graphics2/ControlledSplitMeshNode.h
Normal file
20
Graphics2/ControlledSplitMeshNode.h
Normal file
@ -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:
|
||||
|
||||
};
|
||||
|
@ -67,6 +67,7 @@ bool DirectXFramework::Initialise()
|
||||
_resourceManager = make_shared<ResourceManager>();
|
||||
_sceneGraph = make_shared<SceneGraph>();
|
||||
_camera = make_shared<Camera>();
|
||||
_globalLighting = make_shared<GlobalLighting>();
|
||||
CreateSceneGraph();
|
||||
|
||||
return _sceneGraph->Initialise();
|
||||
|
@ -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<Camera> GetCamera() { return _camera; }
|
||||
inline shared_ptr<GlobalLighting> GetGlobalLighting() { return _globalLighting; }
|
||||
|
||||
private:
|
||||
ComPtr<ID3D11Device> _device;
|
||||
@ -60,5 +62,6 @@ private:
|
||||
|
||||
shared_ptr<ResourceManager> _resourceManager;
|
||||
shared_ptr<Camera> _camera;
|
||||
shared_ptr<GlobalLighting> _globalLighting;
|
||||
};
|
||||
|
||||
|
@ -11,7 +11,7 @@ GamePadController::~GamePadController(void)
|
||||
{
|
||||
}
|
||||
|
||||
void GamePadController::ProcessGameController()
|
||||
void GamePadController::ProcessGameController(set<ControlInputs>& 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:
|
||||
|
@ -1,15 +1,18 @@
|
||||
#pragma once
|
||||
#include <set>
|
||||
#include "Core.h"
|
||||
#include "DirectXCore.h"
|
||||
#include <XInput.h>
|
||||
#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<ControlInputs>& currentInputs, bool &boostHit);
|
||||
|
||||
private:
|
||||
XINPUT_STATE _controllerState;
|
||||
|
38
Graphics2/GlobalLighting.cpp
Normal file
38
Graphics2/GlobalLighting.cpp
Normal file
@ -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;
|
||||
}
|
21
Graphics2/GlobalLighting.h
Normal file
21
Graphics2/GlobalLighting.h
Normal file
@ -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;
|
||||
};
|
@ -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<TexturedCubeNode> cube = make_shared<TexturedCubeNode>(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<SkyNode> skyDome = make_shared<SkyNode>(L"SkyDome", L"Textures\\SkyWater.dds", 30.0f);
|
||||
sceneGraph->Add(skyDome);
|
||||
|
||||
shared_ptr<TerrainNode> terrainNode = make_shared<TerrainNode>(L"MainTerrain", L"Textures\\Example_HeightMap.raw", L"lovelycat");
|
||||
terrainNode->SetAmbientLight(XMFLOAT4(0.7f, 0.7f, 0.7f, 1.0f));
|
||||
terrainNode->SetDirectionalLight(XMVectorSet(0.5f, -1.0f, -1.0f, 0.0f), XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
terrainNode->SetWaterColor(XMFLOAT4(SharedMethods::RGBValueToIntensity(0xA4), SharedMethods::RGBValueToIntensity(0xC1), SharedMethods::RGBValueToIntensity(0xF9), 1.0f));
|
||||
//shared_ptr<HeightMapTerrainNode> terrainNode = make_shared<HeightMapTerrainNode>(L"MainTerrain", L"Textures\\Example_HeightMap.raw", L"RandomWords");
|
||||
shared_ptr<PerlinTerrainNode> terrainNode = make_shared<PerlinTerrainNode>(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<SplitMeshNode> node = make_shared<SplitMeshNode>(L"Plane1", L"Models\\Plane\\Bonanza.3DS");
|
||||
//shared_ptr<MeshNode> node = make_shared<MeshNode>(L"Plane1", L"Models\\Plane\\Bonanza.3DS");
|
||||
node->SetWorldTransform(XMMatrixTranslation(-30.0f, 520.0f, 0));
|
||||
sceneGraph->Add(node);
|
||||
shared_ptr<SceneGraph> treeGroupA = make_shared<SceneGraph>(L"TreeGroupA");
|
||||
|
||||
shared_ptr<MeshNode> treeNode1 = make_shared<MeshNode>(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<MeshNode> treeNode2 = make_shared<MeshNode>(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<MeshNode> treeNode3 = make_shared<MeshNode>(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<MeshNode> treeNode4 = make_shared<MeshNode>(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<ControlledSplitMeshNode> plane1Node = make_shared<ControlledSplitMeshNode>(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<ControlledSplitMeshNode> plane1 = dynamic_pointer_cast<ControlledSplitMeshNode>(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<TerrainNode> mainTerrain = dynamic_pointer_cast<TerrainNode>(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<float>(_boostMultiplier + _boostStep, 1, _boostMax);
|
||||
}
|
||||
else
|
||||
{
|
||||
_boostMultiplier = 1;
|
||||
_boostMultiplier = SharedMethods::Clamp<float>(_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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 <ctime>
|
||||
|
||||
enum class ControlInputs {Forward, Back, TurnLeft, TurnRight, StrafeLeft, StrafeRight, Up, Down, Fire1, Fire2};
|
||||
#include <set>
|
||||
|
||||
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<ControlInputs> _currentInputs;
|
||||
GamePadController _currentController;
|
||||
|
||||
// Changed from a vector to a set because sets only allow for unique values and thats all i want
|
||||
set<ControlInputs> _currentInputs;
|
||||
|
||||
shared_ptr<ObjectNode> _currentPlayerObject;
|
||||
|
||||
void GetCurrentControlInputs();
|
||||
void ResetCurrentControlInputs();
|
||||
|
@ -82,6 +82,7 @@
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);..\Assimp\include;$(IncludePath);</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
@ -128,7 +129,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
@ -146,18 +147,22 @@
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Camera.h" />
|
||||
<ClInclude Include="ColorGradient.h" />
|
||||
<ClInclude Include="ControlledMeshNode.h" />
|
||||
<ClInclude Include="ControlledSplitMeshNode.h" />
|
||||
<ClInclude Include="Core.h" />
|
||||
<ClInclude Include="DDSTextureLoader.h" />
|
||||
<ClInclude Include="DirectXCore.h" />
|
||||
<ClInclude Include="Framework.h" />
|
||||
<ClInclude Include="DirectXFramework.h" />
|
||||
<ClInclude Include="GamePadController.h" />
|
||||
<ClInclude Include="GlobalLighting.h" />
|
||||
<ClInclude Include="Graphics2.h" />
|
||||
<ClInclude Include="HeightMapTerrainNode.h" />
|
||||
<ClInclude Include="HelperFunctions.h" />
|
||||
<ClInclude Include="Mesh.h" />
|
||||
<ClInclude Include="MeshNode.h" />
|
||||
<ClInclude Include="MeshRenderer.h" />
|
||||
<ClInclude Include="ObjectNode.h" />
|
||||
<ClInclude Include="PerlinTerrainNode.h" />
|
||||
<ClInclude Include="Renderer.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
@ -165,6 +170,7 @@
|
||||
<ClInclude Include="SceneGraph.h" />
|
||||
<ClInclude Include="SceneNode.h" />
|
||||
<ClInclude Include="SharedMethods.h" />
|
||||
<ClInclude Include="SkyNode.h" />
|
||||
<ClInclude Include="SplitMeshNode.h" />
|
||||
<ClInclude Include="SubMeshNode.h" />
|
||||
<ClInclude Include="SubMeshRenderer.h" />
|
||||
@ -188,19 +194,24 @@
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Camera.cpp" />
|
||||
<ClCompile Include="ColorGradient.cpp" />
|
||||
<ClCompile Include="ControlledMeshNode.cpp" />
|
||||
<ClCompile Include="ControlledSplitMeshNode.cpp" />
|
||||
<ClCompile Include="DDSTextureLoader.cpp" />
|
||||
<ClCompile Include="Framework.cpp" />
|
||||
<ClCompile Include="DirectXFramework.cpp" />
|
||||
<ClCompile Include="GamePadController.cpp" />
|
||||
<ClCompile Include="GlobalLighting.cpp" />
|
||||
<ClCompile Include="Graphics2.cpp" />
|
||||
<ClCompile Include="HeightMapTerrainNode.cpp" />
|
||||
<ClCompile Include="Mesh.cpp" />
|
||||
<ClCompile Include="MeshNode.cpp" />
|
||||
<ClCompile Include="MeshRenderer.cpp" />
|
||||
<ClCompile Include="ObjectNode.cpp" />
|
||||
<ClCompile Include="PerlinTerrainNode.cpp" />
|
||||
<ClCompile Include="ResourceManager.cpp" />
|
||||
<ClCompile Include="SceneGraph.cpp" />
|
||||
<ClCompile Include="SharedMethods.cpp" />
|
||||
<ClCompile Include="SkyNode.cpp" />
|
||||
<ClCompile Include="SplitMeshNode.cpp" />
|
||||
<ClCompile Include="SubMeshNode.cpp" />
|
||||
<ClCompile Include="SubMeshRenderer.cpp" />
|
||||
@ -232,6 +243,11 @@
|
||||
<FileType>Document</FileType>
|
||||
</Text>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="SkyShader.hlsl">
|
||||
<FileType>Document</FileType>
|
||||
</Text>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
|
@ -102,6 +102,21 @@
|
||||
<ClInclude Include="HeightMapTerrainNode.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SkyNode.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ControlledSplitMeshNode.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ObjectNode.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ControlledMeshNode.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="GlobalLighting.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="Graphics2.rc">
|
||||
@ -195,6 +210,21 @@
|
||||
<ClCompile Include="HeightMapTerrainNode.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SkyNode.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ControlledSplitMeshNode.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ObjectNode.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ControlledMeshNode.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GlobalLighting.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="shader.hlsl">
|
||||
@ -209,6 +239,9 @@
|
||||
<Text Include="TerrainShadersNoBlend.hlsl">
|
||||
<Filter>Shaders</Filter>
|
||||
</Text>
|
||||
<Text Include="SkyShader.hlsl">
|
||||
<Filter>Shaders</Filter>
|
||||
</Text>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="assimp-vc140-mt.dll" />
|
||||
|
36
Graphics2/HeightMapTerrainNode.cpp
Normal file
36
Graphics2/HeightMapTerrainNode.cpp
Normal file
@ -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;
|
||||
}
|
16
Graphics2/HeightMapTerrainNode.h
Normal file
16
Graphics2/HeightMapTerrainNode.h
Normal file
@ -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);
|
||||
};
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
BIN
Graphics2/Models/Tree/COLOR.JPG
Normal file
BIN
Graphics2/Models/Tree/COLOR.JPG
Normal file
Binary file not shown.
After Width: | Height: | Size: 134 KiB |
BIN
Graphics2/Models/Tree/Kashtan.jpg
Normal file
BIN
Graphics2/Models/Tree/Kashtan.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 111 KiB |
BIN
Graphics2/Models/Tree/Tree1.3ds
Normal file
BIN
Graphics2/Models/Tree/Tree1.3ds
Normal file
Binary file not shown.
132
Graphics2/ObjectNode.cpp
Normal file
132
Graphics2/ObjectNode.cpp
Normal file
@ -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);
|
||||
}
|
40
Graphics2/ObjectNode.h
Normal file
40
Graphics2/ObjectNode.h
Normal file
@ -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;
|
||||
};
|
||||
|
135
Graphics2/PerlinTerrainNode.cpp
Normal file
135
Graphics2/PerlinTerrainNode.cpp
Normal file
@ -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;
|
||||
}
|
29
Graphics2/PerlinTerrainNode.h
Normal file
29
Graphics2/PerlinTerrainNode.h
Normal file
@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
#include "DirectXFramework.h"
|
||||
#include <vector>
|
||||
#include <numeric>
|
||||
#include <random>
|
||||
#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<int> 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();
|
||||
};
|
||||
|
@ -87,4 +87,9 @@ SceneNodePointer SceneGraph::GetFirstChild()
|
||||
firstChild = _children.front();
|
||||
}
|
||||
return firstChild;
|
||||
}
|
||||
|
||||
list<SceneNodePointer>& SceneGraph::GetChildren()
|
||||
{
|
||||
return _children;
|
||||
}
|
@ -21,7 +21,9 @@ public:
|
||||
SceneNodePointer GetParent();
|
||||
SceneNodePointer GetFirstChild();
|
||||
|
||||
private:
|
||||
list<SceneNodePointer>& GetChildren();
|
||||
|
||||
protected:
|
||||
// Here you need to add whatever collection you are going to
|
||||
// use to store the children of this scene graph
|
||||
list<SceneNodePointer> _children;
|
||||
|
@ -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>((float)(rand() % (int)(max * 100.0f)) * 0.01f, (float)min, (float)max);
|
||||
}
|
@ -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 <typename T = float> 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 <typename T = float> float Lerp(const T a, const T b, const float p)
|
||||
{
|
||||
return (float)a + p * ((float)b - (float)a);
|
||||
}
|
||||
|
||||
template <typename T = float> 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);
|
||||
};
|
||||
|
||||
|
291
Graphics2/SkyNode.cpp
Normal file
291
Graphics2/SkyNode.cpp
Normal file
@ -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<ID3DBlob> 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()));
|
||||
}
|
67
Graphics2/SkyNode.h
Normal file
67
Graphics2/SkyNode.h
Normal file
@ -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<SkyVertex> _skyDomeVerts;
|
||||
vector<int> _indices;
|
||||
|
||||
ComPtr<ID3D11Device> _device;
|
||||
ComPtr<ID3D11DeviceContext> _deviceContext;
|
||||
|
||||
ComPtr<ID3D11Buffer> _vertexBuffer;
|
||||
ComPtr<ID3D11Buffer> _indexBuffer;
|
||||
|
||||
ComPtr<ID3DBlob> _vertexShaderByteCode = nullptr;
|
||||
ComPtr<ID3DBlob> _pixelShaderByteCode = nullptr;
|
||||
ComPtr<ID3D11VertexShader> _vertexShader;
|
||||
ComPtr<ID3D11PixelShader> _pixelShader;
|
||||
ComPtr<ID3D11InputLayout> _layout;
|
||||
ComPtr<ID3D11Buffer> _constantBuffer;
|
||||
|
||||
ComPtr<ID3D11RasterizerState> _defaultRasteriserState;
|
||||
ComPtr<ID3D11RasterizerState> _noCullRasteriserState;
|
||||
|
||||
ComPtr<ID3D11DepthStencilState> _stencilState;
|
||||
|
||||
ComPtr<ID3D11ShaderResourceView> _skyCubeTexture;
|
||||
wstring _skyCubeTextureName;
|
||||
|
||||
void CreateSphere(float radius, size_t tessellation);
|
||||
void GenerateBuffers();
|
||||
void BuildShaders();
|
||||
void BuildVertexLayout();
|
||||
void BuildConstantBuffer();
|
||||
void BuildRendererStates();
|
||||
void BuildDepthStencilState();
|
||||
|
||||
void LoadSkyboxTexture();
|
||||
};
|
||||
|
36
Graphics2/SkyShader.hlsl
Normal file
36
Graphics2/SkyShader.hlsl
Normal file
@ -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);
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ bool SplitMeshNode::Initialise()
|
||||
bool currentStatus = true;
|
||||
|
||||
_resourceManager = DirectXFramework::GetDXFramework()->GetResourceManager();
|
||||
_renderer = dynamic_pointer_cast<SubMeshRenderer>(_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> node)
|
||||
{
|
||||
unsigned int subMeshCount = (unsigned int)node->GetMeshCount();
|
||||
@ -41,7 +62,14 @@ SceneNodePointer SplitMeshNode::AddMeshNode(shared_ptr<Node> node)
|
||||
{
|
||||
unsigned int meshIndex = node->GetMesh(i);
|
||||
shared_ptr<SubMesh> subMesh = _mesh->GetSubMesh(meshIndex);
|
||||
shared_ptr<SubMeshNode> subNode = make_shared<SubMeshNode>(node->GetName() + L"_" + to_wstring(i), subMesh);
|
||||
shared_ptr<Material> material = subMesh->GetMaterial();
|
||||
float opacity = material->GetOpacity();
|
||||
bool transparent = false;
|
||||
if (opacity < 1.0f)
|
||||
{
|
||||
transparent = true;
|
||||
}
|
||||
shared_ptr<SubMeshNode> subNode = make_shared<SubMeshNode>(node->GetName() + L"_" + to_wstring(i), subMesh, transparent);
|
||||
currentNodeGraph->Add(subNode);
|
||||
}
|
||||
|
||||
|
@ -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> node);
|
||||
|
||||
private:
|
||||
|
@ -1,26 +1,33 @@
|
||||
#include "SubMeshNode.h"
|
||||
|
||||
bool SubMeshNode::Initialise()
|
||||
{
|
||||
_resourceManager = DirectXFramework::GetDXFramework()->GetResourceManager();
|
||||
_renderer = dynamic_pointer_cast<SubMeshRenderer>(_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<SubMesh> SubMeshNode::GetSubMesh() const
|
||||
{
|
||||
return _subMesh;
|
||||
}
|
||||
|
||||
XMFLOAT4X4 SubMeshNode::GetCurrentTransform() const
|
||||
{
|
||||
return _combinedWorldTransformation;
|
||||
}
|
||||
|
@ -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> subMesh) : SceneNode(name) { _subMesh = subMesh; }
|
||||
SubMeshNode(wstring name, shared_ptr<SubMesh> subMesh, bool transparent = false) : SceneNode(name) { _subMesh = subMesh; _transparent = transparent; }
|
||||
|
||||
bool Initialise();
|
||||
void Render();
|
||||
void Shutdown();
|
||||
|
||||
private:
|
||||
shared_ptr<SubMeshRenderer> _renderer;
|
||||
|
||||
shared_ptr<ResourceManager> _resourceManager;
|
||||
bool IsTransparent() const;
|
||||
shared_ptr<SubMesh> GetSubMesh() const;
|
||||
XMFLOAT4X4 GetCurrentTransform() const;
|
||||
|
||||
private:
|
||||
shared_ptr<SubMesh> _subMesh;
|
||||
|
||||
bool _transparent;
|
||||
};
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
#include "SubMeshRenderer.h"
|
||||
|
||||
void SubMeshRenderer::SetSubMesh(shared_ptr<SubMesh> subMesh)
|
||||
void SubMeshRenderer::SetRootChildren(list<SceneNodePointer>& 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<SubMeshNode> currentMeshNode = dynamic_pointer_cast<SubMeshNode>(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> subMesh = currentMeshNode->GetSubMesh();
|
||||
shared_ptr<Material> 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<UINT>(subMesh->GetIndexCount()), 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
shared_ptr<SceneGraph> currentGraphNode = dynamic_pointer_cast<SceneGraph>(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> 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<UINT>(_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()));
|
||||
}
|
||||
|
||||
|
@ -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> subMesh);
|
||||
public:
|
||||
void SetRootChildren(list<SceneNodePointer>& 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<SceneNodePointer>* _rootGraph;
|
||||
|
||||
shared_ptr<SubMesh> _subMesh;
|
||||
XMFLOAT4X4 _worldTransformation;
|
||||
XMFLOAT4 _ambientLight;
|
||||
@ -44,10 +46,14 @@ private:
|
||||
ComPtr<ID3D11RasterizerState> _defaultRasteriserState;
|
||||
ComPtr<ID3D11RasterizerState> _noCullRasteriserState;
|
||||
|
||||
CBUFFER _cBuffer;
|
||||
|
||||
void BuildShaders();
|
||||
void BuildVertexLayout();
|
||||
void BuildConstantBuffer();
|
||||
void BuildBlendState();
|
||||
void BuildRendererState();
|
||||
|
||||
void RenderChild(SceneNodePointer node, bool renderTransparent);
|
||||
};
|
||||
|
||||
|
@ -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<wstring>{}(_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<RGBA> 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;
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
#include "DirectXFramework.h"
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <ctime>
|
||||
#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<TerrainVertex> _terrainVerts;
|
||||
vector<int> _indices;
|
||||
vector<int> _indices;
|
||||
vector<float> _heightValues;
|
||||
|
||||
XMFLOAT4 _ambientLight;
|
||||
@ -86,12 +107,12 @@ private:
|
||||
ComPtr<ID3D11RasterizerState> _defaultRasteriserState;
|
||||
ComPtr<ID3D11RasterizerState> _wireframeRasteriserState;
|
||||
|
||||
ComPtr<ID3D11ShaderResourceView> _rngNoiseMap;
|
||||
ComPtr<ID3D11ShaderResourceView> _snowTest;
|
||||
ComPtr<ID3D11ShaderResourceView> _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();
|
||||
|
@ -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);
|
||||
|
@ -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<ID3DBlob> 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,
|
||||
|
BIN
Graphics2/Textures/SkyDawn.dds
Normal file
BIN
Graphics2/Textures/SkyDawn.dds
Normal file
Binary file not shown.
BIN
Graphics2/Textures/SkyWater.dds
Normal file
BIN
Graphics2/Textures/SkyWater.dds
Normal file
Binary file not shown.
BIN
Graphics2/Textures/cloudySky.dds
Normal file
BIN
Graphics2/Textures/cloudySky.dds
Normal file
Binary file not shown.
BIN
Graphics2/Textures/darkdirtB.dds
Normal file
BIN
Graphics2/Textures/darkdirtB.dds
Normal file
Binary file not shown.
BIN
Graphics2/Textures/grassB.dds
Normal file
BIN
Graphics2/Textures/grassB.dds
Normal file
Binary file not shown.
BIN
Graphics2/Textures/lightdirtB.dds
Normal file
BIN
Graphics2/Textures/lightdirtB.dds
Normal file
Binary file not shown.
BIN
Graphics2/Textures/skymap.dds
Normal file
BIN
Graphics2/Textures/skymap.dds
Normal file
Binary file not shown.
BIN
Graphics2/Textures/snowB.dds
Normal file
BIN
Graphics2/Textures/snowB.dds
Normal file
Binary file not shown.
BIN
Graphics2/Textures/stoneB.dds
Normal file
BIN
Graphics2/Textures/stoneB.dds
Normal file
Binary file not shown.
Binary file not shown.
BIN
Graphics2/Textures/waterNormalsB.dds
Normal file
BIN
Graphics2/Textures/waterNormalsB.dds
Normal file
Binary file not shown.
BIN
Graphics2/Textures/waterNormalsB.jpg
Normal file
BIN
Graphics2/Textures/waterNormalsB.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 44 KiB |
Reference in New Issue
Block a user