diff --git a/enginecustom/Modellistclass.cpp b/enginecustom/Modellistclass.cpp new file mode 100644 index 0000000..ae3b3f2 --- /dev/null +++ b/enginecustom/Modellistclass.cpp @@ -0,0 +1,68 @@ +#include "modellistclass.h" + + +ModelListClass::ModelListClass() +{ + m_ModelInfoList = 0; +} + + +ModelListClass::ModelListClass(const ModelListClass& other) +{ +} + + +ModelListClass::~ModelListClass() +{ +} + + +void ModelListClass::Initialize(int numModels) +{ + int i; + + // Store the number of models. + m_modelCount = numModels; + + // Create a list array of the model information. + m_ModelInfoList = new ModelInfoType[m_modelCount]; + + // Seed the random generator with the current time. + srand((unsigned int)time(NULL)); + + // Go through all the models and randomly generate the position. + for (i = 0; i < m_modelCount; i++) + { + // Generate a random position in front of the viewer for the mode. + m_ModelInfoList[i].positionX = (((float)rand() - (float)rand()) / RAND_MAX) * 10.0f; + m_ModelInfoList[i].positionY = (((float)rand() - (float)rand()) / RAND_MAX) * 10.0f; + m_ModelInfoList[i].positionZ = ((((float)rand() - (float)rand()) / RAND_MAX) * 10.0f) + 5.0f; + } + + return; +} + +void ModelListClass::Shutdown() +{ + // Release the model information list. + if (m_ModelInfoList) + { + delete[] m_ModelInfoList; + m_ModelInfoList = 0; + } + + return; +} + +int ModelListClass::GetModelCount() +{ + return m_modelCount; +} + +void ModelListClass::GetData(int index, float& positionX, float& positionY, float& positionZ) +{ + positionX = m_ModelInfoList[index].positionX; + positionY = m_ModelInfoList[index].positionY; + positionZ = m_ModelInfoList[index].positionZ; + return; +} \ No newline at end of file diff --git a/enginecustom/Modellistclass.h b/enginecustom/Modellistclass.h new file mode 100644 index 0000000..17dcf10 --- /dev/null +++ b/enginecustom/Modellistclass.h @@ -0,0 +1,39 @@ +#ifndef _MODELLISTCLASS_H_ +#define _MODELLISTCLASS_H_ + + +////////////// +// INCLUDES // +////////////// +#include +#include + + +/////////////////////////////////////////////////////////////////////////////// +// Class name: ModelListClass +/////////////////////////////////////////////////////////////////////////////// +class ModelListClass +{ +private: + struct ModelInfoType + { + float positionX, positionY, positionZ; + }; + +public: + ModelListClass(); + ModelListClass(const ModelListClass&); + ~ModelListClass(); + + void Initialize(int); + void Shutdown(); + + int GetModelCount(); + void GetData(int, float&, float&, float&); + +private: + int m_modelCount; + ModelInfoType* m_ModelInfoList; +}; + +#endif diff --git a/enginecustom/Positionclass.cpp b/enginecustom/Positionclass.cpp new file mode 100644 index 0000000..1e66b88 --- /dev/null +++ b/enginecustom/Positionclass.cpp @@ -0,0 +1,202 @@ +#include "positionclass.h" + +PositionClass::PositionClass() +{ + m_frameTime = 0.0f; + m_rotationY = 0.0f; + m_rotationX = 0.0f; + m_positionX = 0.0f; + m_positionY = 0.0f; + m_positionZ = 0.0f; + m_leftTurnSpeed = 0.0f; + m_rightTurnSpeed = 0.0f; +} + + +PositionClass::PositionClass(const PositionClass& other) +{ +} + + +PositionClass::~PositionClass() +{ +} + +void PositionClass::SetFrameTime(float time) +{ + m_frameTime = time; + return; +} + +void PositionClass::GetRotation(float& y, float& x) +{ + y = m_rotationY; + x = m_rotationX; + return; +} + +void PositionClass::GetPosition(float& x, float& y, float& z) +{ + x = m_positionX; + y = m_positionY; + z = m_positionZ; + return; +} + +void PositionClass::TurnLeft(bool keydown) +{ + // If the key is pressed increase the speed at which the camera turns left. If not slow down the turn speed. + if (keydown) + { + m_leftTurnSpeed += m_frameTime * 1.5f; + + if (m_leftTurnSpeed > (m_frameTime * 200.0f)) + { + m_leftTurnSpeed = m_frameTime * 200.0f; + } + } + else + { + m_leftTurnSpeed -= m_frameTime * 1.0f; + + if (m_leftTurnSpeed < 0.0f) + { + m_leftTurnSpeed = 0.0f; + } + } + + // Update the rotation using the turning speed. + m_rotationY -= m_leftTurnSpeed; + if (m_rotationY < 0.0f) + { + m_rotationY += 360.0f; + } + + return; +} + + +void PositionClass::TurnRight(bool keydown) +{ + // If the key is pressed increase the speed at which the camera turns right. If not slow down the turn speed. + if (keydown) + { + m_rightTurnSpeed += m_frameTime * 1.5f; + + if (m_rightTurnSpeed > (m_frameTime * 200.0f)) + { + m_rightTurnSpeed = m_frameTime * 200.0f; + } + } + else + { + m_rightTurnSpeed -= m_frameTime * 1.0f; + + if (m_rightTurnSpeed < 0.0f) + { + m_rightTurnSpeed = 0.0f; + } + } + + // Update the rotation using the turning speed. + m_rotationY += m_rightTurnSpeed; + if (m_rotationY > 360.0f) + { + m_rotationY -= 360.0f; + } + + return; +} + +void PositionClass::TurnMouse(float deltaX, float deltaY) +{ + float speed = 0.1f; + // The turning speed is proportional to the horizontal mouse movement + m_horizontalTurnSpeed = deltaX * speed; + + // Update the rotation using the turning speed + m_rotationY += m_horizontalTurnSpeed; + if (m_rotationY < 0.0f) + { + m_rotationY += 360.0f; + } + else if (m_rotationY > 360.0f) + { + m_rotationY -= 360.0f; + } + + // The turning speed is proportional to the vertical mouse movement + m_verticalTurnSpeed = deltaY * speed; + + // Update the rotation using the turning speed + m_rotationX += m_verticalTurnSpeed; + if (m_rotationX < -90.0f) + { + m_rotationX = -90.0f; + } + else if (m_rotationX > 90.0f) + { + m_rotationX = 90.0f; + } + + return; +} + +void PositionClass::MoveCamera(bool forward, bool backward, bool left, bool right, bool up, bool down) +{ + float radiansY, radiansX; + float speed; + + // Set the speed of the camera. + speed = 2.0f * m_frameTime; + + // Convert degrees to radians. + radiansY = m_rotationY * 0.0174532925f; + radiansX = m_rotationX * 0.0174532925f; + + // Update the position. + + // If moving forward, the position moves in the direction of the camera and accordingly to its angle. + if (forward) + { + m_positionX += sinf(radiansY) * cosf(radiansX) * speed; + m_positionZ += cosf(radiansY) * cosf(radiansX) * speed; + m_positionY -= sinf(radiansX) * speed; + } + + // If moving backward, the position moves in the opposite direction of the camera and accordingly to its angle. + if (backward) + { + m_positionX -= sinf(radiansY) * cosf(radiansX) * speed; + m_positionZ -= cosf(radiansY) * cosf(radiansX) * speed; + m_positionY += sinf(radiansX) * speed; + } + + // If moving left, the position moves to the left of the camera and accordingly to its angle. + if (left) + { + m_positionX -= cosf(radiansY) * speed; + m_positionZ += sinf(radiansY) * speed; + } + + // If moving right, the position moves to the right of the camera and accordingly to its angle. + if (right) + { + m_positionX += cosf(radiansY) * speed; + m_positionZ -= sinf(radiansY) * speed; + } + + // If moving up, the position moves up. + if (up) + { + m_positionY += speed; + } + + // If moving down, the position moves down. + if (down) + { + m_positionY -= speed; + } + + return; +} \ No newline at end of file diff --git a/enginecustom/Positionclass.h b/enginecustom/Positionclass.h new file mode 100644 index 0000000..5048610 --- /dev/null +++ b/enginecustom/Positionclass.h @@ -0,0 +1,37 @@ +#ifndef _POSITIONCLASS_H_ +#define _POSITIONCLASS_H_ + + +////////////// +// INCLUDES // +////////////// +#include + + +//////////////////////////////////////////////////////////////////////////////// +// Class name: PositionClass +//////////////////////////////////////////////////////////////////////////////// +class PositionClass +{ +public: + PositionClass(); + PositionClass(const PositionClass&); + ~PositionClass(); + + void SetFrameTime(float); + void GetRotation(float&, float&); + void GetPosition(float&, float&, float&); + + void TurnLeft(bool); + void TurnRight(bool); + void TurnMouse(float, float); + void MoveCamera(bool, bool, bool, bool, bool, bool); + +private: + float m_frameTime; + float m_rotationY, m_rotationX; + float m_positionX, m_positionY, m_positionZ; + float m_leftTurnSpeed, m_rightTurnSpeed, m_horizontalTurnSpeed, m_verticalTurnSpeed; +}; + +#endif \ No newline at end of file diff --git a/enginecustom/Systemclass.cpp b/enginecustom/Systemclass.cpp index df7f983..3ecf75c 100644 --- a/enginecustom/Systemclass.cpp +++ b/enginecustom/Systemclass.cpp @@ -39,7 +39,12 @@ bool SystemClass::Initialize() // Create and initialize the input object. This object will be used to handle reading the keyboard input from the user. m_Input = new InputClass; - m_Input->Initialize(); + + result = m_Input->Initialize(m_hinstance, m_hwnd, screenWidth, screenHeight); + if (!result) + { + return false; + } // Create and initialize the application class object. This object will handle rendering all the graphics for this application. m_Application = new ApplicationClass; @@ -140,15 +145,15 @@ bool SystemClass::Frame() { bool result; - - // Check if the user pressed escape and wants to exit the application. - if (m_Input->IsKeyDown(VK_ESCAPE)) + // Do the input frame processing. + result = m_Input->Frame(); + if (!result) { return false; } // Do the frame processing for the application class object. - result = m_Application->Frame(); + result = m_Application->Frame(m_Input); if (!result) { return false; diff --git a/enginecustom/Translate.xaml b/enginecustom/Translate.xaml new file mode 100644 index 0000000..0780d74 --- /dev/null +++ b/enginecustom/Translate.xaml @@ -0,0 +1,13 @@ + + + + + + diff --git a/enginecustom/alpha01.tga b/enginecustom/alpha01.tga new file mode 100644 index 0000000..74b7943 Binary files /dev/null and b/enginecustom/alpha01.tga differ diff --git a/enginecustom/alphamap.ps b/enginecustom/alphamap.ps new file mode 100644 index 0000000..ee2f6bc --- /dev/null +++ b/enginecustom/alphamap.ps @@ -0,0 +1,45 @@ +///////////// +// GLOBALS // +///////////// +Texture2D shaderTexture1 : register(t0); +Texture2D shaderTexture2 : register(t1); +Texture2D shaderTexture3 : register(t2); +SamplerState SampleType : register(s0); + +////////////// +// TYPEDEFS // +////////////// +struct PixelInputType +{ + float4 position : SV_POSITION; + float2 tex : TEXCOORD0; +}; + +//////////////////////////////////////////////////////////////////////////////// +// Pixel Shader +//////////////////////////////////////////////////////////////////////////////// +float4 AlphaMapPixelShader(PixelInputType input) : SV_TARGET +{ + float4 color1; + float4 color2; + float4 alphaValue; + float4 blendColor; + + + // Get the pixel color from the first texture. + color1 = shaderTexture1.Sample(SampleType, input.tex); + + // Get the pixel color from the second texture. + color2 = shaderTexture2.Sample(SampleType, input.tex); + + // Get the pixel color from the alpha texture. + alphaValue = shaderTexture3.Sample(SampleType, input.tex); + + // Combine the two textures based on the alpha value. + blendColor = (alphaValue * color1) + ((1.0 - alphaValue) * color2); + + // Saturate the final color value. + blendColor = saturate(blendColor); + + return blendColor; +} \ No newline at end of file diff --git a/enginecustom/alphamap.vs b/enginecustom/alphamap.vs new file mode 100644 index 0000000..1885da1 --- /dev/null +++ b/enginecustom/alphamap.vs @@ -0,0 +1,49 @@ +///////////// +// GLOBALS // +///////////// +cbuffer MatrixBuffer +{ + matrix worldMatrix; + matrix viewMatrix; + matrix projectionMatrix; +}; + + +////////////// +// TYPEDEFS // +////////////// +struct VertexInputType +{ + float4 position : POSITION; + float2 tex : TEXCOORD0; + float3 normal : NORMAL; +}; + +struct PixelInputType +{ + float4 position : SV_POSITION; + float2 tex : TEXCOORD0; +}; + + +//////////////////////////////////////////////////////////////////////////////// +// Vertex Shader +//////////////////////////////////////////////////////////////////////////////// +PixelInputType AlphaMapVertexShader(VertexInputType input) +{ + PixelInputType output; + + + // Change the position vector to be 4 units for proper matrix calculations. + input.position.w = 1.0f; + + // Calculate the position of the vertex against the world, view, and projection matrices. + output.position = mul(input.position, worldMatrix); + output.position = mul(output.position, viewMatrix); + output.position = mul(output.position, projectionMatrix); + + // Store the texture coordinates for the pixel shader. + output.tex = input.tex; + + return output; +} diff --git a/enginecustom/alphamapshaderclass.cpp b/enginecustom/alphamapshaderclass.cpp new file mode 100644 index 0000000..a1d9b70 --- /dev/null +++ b/enginecustom/alphamapshaderclass.cpp @@ -0,0 +1,378 @@ +#include "alphamapshaderclass.h" + + +AlphaMapShaderClass::AlphaMapShaderClass() +{ + m_vertexShader = 0; + m_pixelShader = 0; + m_layout = 0; + m_matrixBuffer = 0; + m_sampleState = 0; +} + + +AlphaMapShaderClass::AlphaMapShaderClass(const AlphaMapShaderClass& other) +{ +} + + +AlphaMapShaderClass::~AlphaMapShaderClass() +{ +} + + +bool AlphaMapShaderClass::Initialize(ID3D11Device* device, HWND hwnd) +{ + bool result; + wchar_t vsFilename[128]; + wchar_t psFilename[128]; + int error; + + // Set the filename of the vertex shader. + error = wcscpy_s(vsFilename, 128, L"alphamap.vs"); + if (error != 0) + { + return false; + } + + // Set the filename of the pixel shader. + error = wcscpy_s(psFilename, 128, L"alphamap.ps"); + if (error != 0) + { + return false; + } + + // Initialize the vertex and pixel shaders. + result = InitializeShader(device, hwnd, vsFilename, psFilename); + if (!result) + { + return false; + } + + return true; +} + + +void AlphaMapShaderClass::Shutdown() +{ + // Shutdown the vertex and pixel shaders as well as the related objects. + ShutdownShader(); + + return; +} + + +bool AlphaMapShaderClass::Render(ID3D11DeviceContext* deviceContext, int indexCount, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix, + ID3D11ShaderResourceView* texture1, ID3D11ShaderResourceView* texture2, ID3D11ShaderResourceView* texture3) +{ + bool result; + + + // Set the shader parameters that it will use for rendering. + result = SetShaderParameters(deviceContext, worldMatrix, viewMatrix, projectionMatrix, texture1, texture2, texture3); + if (!result) + { + return false; + } + + // Now render the prepared buffers with the shader. + RenderShader(deviceContext, indexCount); + + return true; +} + + +bool AlphaMapShaderClass::InitializeShader(ID3D11Device* device, HWND hwnd, WCHAR* vsFilename, WCHAR* psFilename) +{ + HRESULT result; + ID3D10Blob* errorMessage; + ID3D10Blob* vertexShaderBuffer; + ID3D10Blob* pixelShaderBuffer; + D3D11_INPUT_ELEMENT_DESC polygonLayout[3]; + unsigned int numElements; + D3D11_BUFFER_DESC matrixBufferDesc; + D3D11_SAMPLER_DESC samplerDesc; + + + // Initialize the pointers this function will use to null. + errorMessage = 0; + vertexShaderBuffer = 0; + pixelShaderBuffer = 0; + + // Compile the vertex shader code. + result = D3DCompileFromFile(vsFilename, NULL, NULL, "AlphaMapVertexShader", "vs_5_0", D3D10_SHADER_ENABLE_STRICTNESS, 0, + &vertexShaderBuffer, &errorMessage); + if (FAILED(result)) + { + // If the shader failed to compile it should have writen something to the error message. + if (errorMessage) + { + OutputShaderErrorMessage(errorMessage, hwnd, vsFilename); + } + // If there was nothing in the error message then it simply could not find the shader file itself. + else + { + MessageBox(hwnd, vsFilename, L"Missing Shader File", MB_OK); + } + + return false; + } + + // Compile the pixel shader code. + result = D3DCompileFromFile(psFilename, NULL, NULL, "AlphaMapPixelShader", "ps_5_0", D3D10_SHADER_ENABLE_STRICTNESS, 0, + &pixelShaderBuffer, &errorMessage); + if (FAILED(result)) + { + // If the shader failed to compile it should have writen something to the error message. + if (errorMessage) + { + OutputShaderErrorMessage(errorMessage, hwnd, psFilename); + } + // If there was nothing in the error message then it simply could not find the file itself. + else + { + MessageBox(hwnd, psFilename, L"Missing Shader File", MB_OK); + } + + return false; + } + + // Create the vertex shader from the buffer. + result = device->CreateVertexShader(vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), NULL, &m_vertexShader); + if (FAILED(result)) + { + return false; + } + + // Create the pixel shader from the buffer. + result = device->CreatePixelShader(pixelShaderBuffer->GetBufferPointer(), pixelShaderBuffer->GetBufferSize(), NULL, &m_pixelShader); + if (FAILED(result)) + { + return false; + } + + // Create the vertex input layout description. + polygonLayout[0].SemanticName = "POSITION"; + polygonLayout[0].SemanticIndex = 0; + polygonLayout[0].Format = DXGI_FORMAT_R32G32B32_FLOAT; + polygonLayout[0].InputSlot = 0; + polygonLayout[0].AlignedByteOffset = 0; + polygonLayout[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + polygonLayout[0].InstanceDataStepRate = 0; + + polygonLayout[1].SemanticName = "TEXCOORD"; + polygonLayout[1].SemanticIndex = 0; + polygonLayout[1].Format = DXGI_FORMAT_R32G32_FLOAT; + polygonLayout[1].InputSlot = 0; + polygonLayout[1].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT; + polygonLayout[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + polygonLayout[1].InstanceDataStepRate = 0; + + polygonLayout[2].SemanticName = "NORMAL"; + polygonLayout[2].SemanticIndex = 0; + polygonLayout[2].Format = DXGI_FORMAT_R32G32B32_FLOAT; + polygonLayout[2].InputSlot = 0; + polygonLayout[2].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT; + polygonLayout[2].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + polygonLayout[2].InstanceDataStepRate = 0; + + // Get a count of the elements in the layout. + numElements = sizeof(polygonLayout) / sizeof(polygonLayout[0]); + + // Create the vertex input layout. + result = device->CreateInputLayout(polygonLayout, numElements, vertexShaderBuffer->GetBufferPointer(), + vertexShaderBuffer->GetBufferSize(), &m_layout); + if (FAILED(result)) + { + return false; + } + + // Release the vertex shader buffer and pixel shader buffer since they are no longer needed. + vertexShaderBuffer->Release(); + vertexShaderBuffer = 0; + + pixelShaderBuffer->Release(); + pixelShaderBuffer = 0; + + // Setup the description of the dynamic matrix constant buffer that is in the vertex shader. + matrixBufferDesc.Usage = D3D11_USAGE_DYNAMIC; + matrixBufferDesc.ByteWidth = sizeof(MatrixBufferType); + matrixBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + matrixBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + matrixBufferDesc.MiscFlags = 0; + matrixBufferDesc.StructureByteStride = 0; + + // Create the constant buffer pointer so we can access the vertex shader constant buffer from within this class. + result = device->CreateBuffer(&matrixBufferDesc, NULL, &m_matrixBuffer); + if (FAILED(result)) + { + return false; + } + + // Create a texture sampler state description. + samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + samplerDesc.MipLODBias = 0.0f; + samplerDesc.MaxAnisotropy = 1; + samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + samplerDesc.BorderColor[0] = 0; + samplerDesc.BorderColor[1] = 0; + samplerDesc.BorderColor[2] = 0; + samplerDesc.BorderColor[3] = 0; + samplerDesc.MinLOD = 0; + samplerDesc.MaxLOD = D3D11_FLOAT32_MAX; + + // Create the texture sampler state. + result = device->CreateSamplerState(&samplerDesc, &m_sampleState); + if (FAILED(result)) + { + return false; + } + + return true; +} + + +void AlphaMapShaderClass::ShutdownShader() +{ + // Release the sampler state. + if (m_sampleState) + { + m_sampleState->Release(); + m_sampleState = 0; + } + + // Release the matrix constant buffer. + if (m_matrixBuffer) + { + m_matrixBuffer->Release(); + m_matrixBuffer = 0; + } + + // Release the layout. + if (m_layout) + { + m_layout->Release(); + m_layout = 0; + } + + // Release the pixel shader. + if (m_pixelShader) + { + m_pixelShader->Release(); + m_pixelShader = 0; + } + + // Release the vertex shader. + if (m_vertexShader) + { + m_vertexShader->Release(); + m_vertexShader = 0; + } + + return; +} + + +void AlphaMapShaderClass::OutputShaderErrorMessage(ID3D10Blob* errorMessage, HWND hwnd, WCHAR* shaderFilename) +{ + char* compileErrors; + unsigned long long bufferSize, i; + ofstream fout; + + + // Get a pointer to the error message text buffer. + compileErrors = (char*)(errorMessage->GetBufferPointer()); + + // Get the length of the message. + bufferSize = errorMessage->GetBufferSize(); + + // Open a file to write the error message to. + fout.open("shader-error.txt"); + + // Write out the error message. + for (i = 0; i < bufferSize; i++) + { + fout << compileErrors[i]; + } + + // Close the file. + fout.close(); + + // Release the error message. + errorMessage->Release(); + errorMessage = 0; + + // Pop a message up on the screen to notify the user to check the text file for compile errors. + MessageBox(hwnd, L"Error compiling shader. Check shader-error.txt for message.", shaderFilename, MB_OK); + + return; +} + + +bool AlphaMapShaderClass::SetShaderParameters(ID3D11DeviceContext* deviceContext, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix, + ID3D11ShaderResourceView* texture1, ID3D11ShaderResourceView* texture2, ID3D11ShaderResourceView* texture3) +{ + HRESULT result; + D3D11_MAPPED_SUBRESOURCE mappedResource; + MatrixBufferType* dataPtr; + unsigned int bufferNumber; + + + // Transpose the matrices to prepare them for the shader. + worldMatrix = XMMatrixTranspose(worldMatrix); + viewMatrix = XMMatrixTranspose(viewMatrix); + projectionMatrix = XMMatrixTranspose(projectionMatrix); + + // Lock the constant buffer so it can be written to. + result = deviceContext->Map(m_matrixBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + return false; + } + + // Get a pointer to the data in the constant buffer. + dataPtr = (MatrixBufferType*)mappedResource.pData; + + // Copy the matrices into the constant buffer. + dataPtr->world = worldMatrix; + dataPtr->view = viewMatrix; + dataPtr->projection = projectionMatrix; + + // Unlock the constant buffer. + deviceContext->Unmap(m_matrixBuffer, 0); + + // Set the position of the constant buffer in the vertex shader. + bufferNumber = 0; + + // Finally set the constant buffer in the vertex shader with the updated values. + deviceContext->VSSetConstantBuffers(bufferNumber, 1, &m_matrixBuffer); + + // Set shader texture resources in the pixel shader. + deviceContext->PSSetShaderResources(0, 1, &texture1); + deviceContext->PSSetShaderResources(1, 1, &texture2); + deviceContext->PSSetShaderResources(2, 1, &texture3); + + return true; +} + + +void AlphaMapShaderClass::RenderShader(ID3D11DeviceContext* deviceContext, int indexCount) +{ + // Set the vertex input layout. + deviceContext->IASetInputLayout(m_layout); + + // Set the vertex and pixel shaders that will be used to render this triangle. + deviceContext->VSSetShader(m_vertexShader, NULL, 0); + deviceContext->PSSetShader(m_pixelShader, NULL, 0); + + // Set the sampler state in the pixel shader. + deviceContext->PSSetSamplers(0, 1, &m_sampleState); + + // Render the triangle. + deviceContext->DrawIndexed(indexCount, 0, 0); + + return; +} \ No newline at end of file diff --git a/enginecustom/alphamapshaderclass.h b/enginecustom/alphamapshaderclass.h new file mode 100644 index 0000000..ff4e4e7 --- /dev/null +++ b/enginecustom/alphamapshaderclass.h @@ -0,0 +1,54 @@ +#ifndef _ALPHAMAPSHADERCLASS_H_ +#define _ALPHAMAPSHADERCLASS_H_ + + +////////////// +// INCLUDES // +////////////// +#include +#include +#include +#include +using namespace DirectX; +using namespace std; + + +//////////////////////////////////////////////////////////////////////////////// +// Class name: AlphaMapShaderClass +//////////////////////////////////////////////////////////////////////////////// +class AlphaMapShaderClass +{ +private: + struct MatrixBufferType + { + XMMATRIX world; + XMMATRIX view; + XMMATRIX projection; + }; + +public: + AlphaMapShaderClass(); + AlphaMapShaderClass(const AlphaMapShaderClass&); + ~AlphaMapShaderClass(); + + bool Initialize(ID3D11Device*, HWND); + void Shutdown(); + bool Render(ID3D11DeviceContext*, int, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, ID3D11ShaderResourceView*, ID3D11ShaderResourceView*); + +private: + bool InitializeShader(ID3D11Device*, HWND, WCHAR*, WCHAR*); + void ShutdownShader(); + void OutputShaderErrorMessage(ID3D10Blob*, HWND, WCHAR*); + + bool SetShaderParameters(ID3D11DeviceContext*, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, ID3D11ShaderResourceView*, ID3D11ShaderResourceView*); + void RenderShader(ID3D11DeviceContext*, int); + +private: + ID3D11VertexShader* m_vertexShader; + ID3D11PixelShader* m_pixelShader; + ID3D11InputLayout* m_layout; + ID3D11Buffer* m_matrixBuffer; + ID3D11SamplerState* m_sampleState; +}; + +#endif \ No newline at end of file diff --git a/enginecustom/applicationclass.cpp b/enginecustom/applicationclass.cpp index b6f1941..292b283 100644 --- a/enginecustom/applicationclass.cpp +++ b/enginecustom/applicationclass.cpp @@ -5,14 +5,16 @@ ApplicationClass::ApplicationClass() m_Direct3D = 0; m_Camera = 0; m_MultiTextureShader = 0; + m_AlphaMapShader = 0; m_Model = 0; m_LightShader = 0; + m_LightMapShader = 0; m_Light = 0; m_TextureShader = 0; m_Bitmap = 0; m_Sprite = 0; m_Timer = 0; - m_Lights = 0; + m_MouseStrings = 0; m_FontShader = 0; m_Font = 0; m_TextString1 = 0; @@ -20,6 +22,13 @@ ApplicationClass::ApplicationClass() m_TextString3 = 0; m_Fps = 0; m_FpsString = 0; + m_NormalMapShader = 0; + m_SpecMapShader = 0; + m_RenderCountString = 0; + m_ModelList = 0; + m_Position = 0; + m_Frustum = 0; + m_DisplayPlane = 0; } @@ -35,14 +44,17 @@ ApplicationClass::~ApplicationClass() bool ApplicationClass::Initialize(int screenWidth, int screenHeight, HWND hwnd) { + char mouseString1[32], mouseString2[32], mouseString3[32]; char testString1[32], testString2[32], testString3[32]; - char modelFilename[128]; - char textureFilename1[128], textureFilename2[128]; + char modelFilename[128], textureFilename1[128], textureFilename2[128], textureFilename3[128], renderString[32]; char bitmapFilename[128]; char spriteFilename[128]; char fpsString[32]; bool result; + m_screenWidth = screenWidth; + m_screenHeight = screenHeight; + // Create the Direct3D object. m_Direct3D = new D3DClass; if (!m_Direct3D) @@ -69,6 +81,28 @@ bool ApplicationClass::Initialize(int screenWidth, int screenHeight, HWND hwnd) // Set the initial position of the camera. m_Camera->SetPosition(0.0f, 0.0f, -12.0f); m_Camera->SetRotation(0.0f, 0.0f, 0.0f); + m_Camera->Render(); + m_Camera->GetViewMatrix(m_baseViewMatrix); + + // Create and initialize the specular map shader object. + m_SpecMapShader = new SpecMapShaderClass; + + result = m_SpecMapShader->Initialize(m_Direct3D->GetDevice(), hwnd); + if (!result) + { + MessageBox(hwnd, L"Could not initialize the specular map shader object.", L"Error", MB_OK); + return false; + } + + // Create and initialize the normal map shader object. + m_NormalMapShader = new NormalMapShaderClass; + + result = m_NormalMapShader->Initialize(m_Direct3D->GetDevice(), hwnd); + if (!result) + { + MessageBox(hwnd, L"Could not initialize the normal map shader object.", L"Error", MB_OK); + return false; + } // Create and initialize the font shader object. m_FontShader = new FontShaderClass; @@ -131,6 +165,25 @@ bool ApplicationClass::Initialize(int screenWidth, int screenHeight, HWND hwnd) return false; } + // Create and initialize the render to texture object. + m_RenderTexture = new RenderTextureClass; + + result = m_RenderTexture->Initialize(m_Direct3D->GetDevice(), 256, 256, SCREEN_DEPTH, SCREEN_NEAR, 1); + if (!result) + { + return false; + } + + // Create and initialize the display plane object. + m_DisplayPlane = new DisplayPlaneClass; + + result = m_DisplayPlane->Initialize(m_Direct3D->GetDevice(), 1.0f, 1.0f); + if (!result) + { + return false; + } + + // Set the sprite info file we will be using. strcpy_s(spriteFilename, "sprite_data_01.txt"); @@ -143,10 +196,27 @@ bool ApplicationClass::Initialize(int screenWidth, int screenHeight, HWND hwnd) return false; } - // Create and initialize the timer object. - m_Timer = new TimerClass; + // Set the initial mouse strings. + strcpy_s(mouseString1, "Mouse X: 0"); + strcpy_s(mouseString2, "Mouse Y: 0"); + strcpy_s(mouseString3, "Mouse Button: No"); - result = m_Timer->Initialize(); + // Create and initialize the text objects for the mouse strings. + m_MouseStrings = new TextClass[3]; + + result = m_MouseStrings[0].Initialize(m_Direct3D->GetDevice(), m_Direct3D->GetDeviceContext(), screenWidth, screenHeight, 32, m_Font, mouseString1, 10, 10, 1.0f, 1.0f, 1.0f); + if (!result) + { + return false; + } + + result = m_MouseStrings[1].Initialize(m_Direct3D->GetDevice(), m_Direct3D->GetDeviceContext(), screenWidth, screenHeight, 32, m_Font, mouseString1, 10, 35, 1.0f, 1.0f, 1.0f); + if (!result) + { + return false; + } + + result = m_MouseStrings[2].Initialize(m_Direct3D->GetDevice(), m_Direct3D->GetDeviceContext(), screenWidth, screenHeight, 32, m_Font, mouseString1, 10, 60, 1.0f, 1.0f, 1.0f); if (!result) { return false; @@ -179,12 +249,14 @@ bool ApplicationClass::Initialize(int screenWidth, int screenHeight, HWND hwnd) // Set the file name of the textures. strcpy_s(textureFilename1, "stone01.tga"); - strcpy_s(textureFilename2, "moss01.tga"); + strcpy_s(textureFilename2, "normal01.tga"); + strcpy_s(textureFilename3, "alpha01.tga"); + // A FAIRE: Ajouter une nouvelle texture pour le multitexturing // Create and initialize the model object. m_Model = new ModelClass; - result = m_Model->Initialize(m_Direct3D->GetDevice(), m_Direct3D->GetDeviceContext(), modelFilename, textureFilename1, textureFilename2); + result = m_Model->Initialize(m_Direct3D->GetDevice(), m_Direct3D->GetDeviceContext(), modelFilename, textureFilename1, textureFilename2, textureFilename3); if (!result) { MessageBox(hwnd, L"Could not initialize the model object.", L"Error", MB_OK); @@ -202,6 +274,14 @@ bool ApplicationClass::Initialize(int screenWidth, int screenHeight, HWND hwnd) return false; } + // Create and initialize the light object. + m_Light = new LightClass; + + m_Light->SetDiffuseColor(1.0f, 1.0f, 1.0f, 1.0f); + m_Light->SetDirection(0.0f, 0.0f, 1.0f); + m_Light->SetSpecularColor(1.0f, 1.0f, 1.0f, 1.0f); + m_Light->SetSpecularPower(16.0f); + // Set the number of lights we will use. m_numLights = 4; @@ -221,6 +301,76 @@ bool ApplicationClass::Initialize(int screenWidth, int screenHeight, HWND hwnd) m_Lights[3].SetDiffuseColor(1.0f, 1.0f, 1.0f, 1.0f); // White m_Lights[3].SetPosition(3.0f, 1.0f, -3.0f); + // Create and initialize the light map shader object. + m_LightMapShader = new LightMapShaderClass; + + result = m_LightMapShader->Initialize(m_Direct3D->GetDevice(), hwnd); + if (!result) + { + MessageBox(hwnd, L"Could not initialize the light map shader object.", L"Error", MB_OK); + return false; + } + + // Create and initialize the alpha map shader object. + m_AlphaMapShader = new AlphaMapShaderClass; + + result = m_AlphaMapShader->Initialize(m_Direct3D->GetDevice(), hwnd); + if (!result) + { + MessageBox(hwnd, L"Could not initialize the alpha map shader object.", L"Error", MB_OK); + return false; + } + + // Create and initialize the font shader object. + m_FontShader = new FontShaderClass; + + result = m_FontShader->Initialize(m_Direct3D->GetDevice(), hwnd); + if (!result) + { + MessageBox(hwnd, L"Could not initialize the font shader object.", L"Error", MB_OK); + return false; + } + + // Create and initialize the font object. + m_Font = new FontClass; + + result = m_Font->Initialize(m_Direct3D->GetDevice(), m_Direct3D->GetDeviceContext(), 0); + if (!result) + { + return false; + } + + // Set the initial render count string. + strcpy_s(renderString, "Render Count: 0"); + + // Create and initialize the text object for the render count string. + m_RenderCountString = new TextClass; + + result = m_RenderCountString->Initialize(m_Direct3D->GetDevice(), m_Direct3D->GetDeviceContext(), screenWidth, screenHeight, 32, m_Font, renderString, 10, 10, 1.0f, 1.0f, 1.0f); + if (!result) + { + return false; + } + + // Create and initialize the model list object. + m_ModelList = new ModelListClass; + m_ModelList->Initialize(25); + + // Create and initialize the timer object. + m_Timer = new TimerClass; + + result = m_Timer->Initialize(); + if (!result) + { + return false; + } + + // Create the position class object. + m_Position = new PositionClass; + + // Create the frustum class object. + m_Frustum = new FrustumClass; + // Create and initialize the fps object. m_Fps = new FpsClass(); @@ -246,6 +396,54 @@ bool ApplicationClass::Initialize(int screenWidth, int screenHeight, HWND hwnd) void ApplicationClass::Shutdown() { + // Release the frustum class object. + if (m_Frustum) + { + delete m_Frustum; + m_Frustum = 0; + } + + // Release the display plane object. + if (m_DisplayPlane) + { + m_DisplayPlane->Shutdown(); + delete m_DisplayPlane; + m_DisplayPlane = 0; + } + + // Release the position object. + if (m_Position) + { + delete m_Position; + m_Position = 0; + } + + // Release the model list object. + if (m_ModelList) + { + m_ModelList->Shutdown(); + delete m_ModelList; + m_ModelList = 0; + } + + // Release the text objects for the render count string. + if (m_RenderCountString) + { + m_RenderCountString->Shutdown(); + delete m_RenderCountString; + m_RenderCountString = 0; + } + + // Release the text objects for the mouse strings. + if (m_MouseStrings) + { + m_MouseStrings[0].Shutdown(); + m_MouseStrings[1].Shutdown(); + m_MouseStrings[2].Shutdown(); + + delete[] m_MouseStrings; + m_MouseStrings = 0; + } // Release the text object for the fps string. if (m_FpsString) { @@ -261,7 +459,6 @@ void ApplicationClass::Shutdown() m_Fps = 0; } - // Release the text string objects. if (m_TextString3) { @@ -330,20 +527,20 @@ void ApplicationClass::Shutdown() m_LightShader = 0; } - // Release the light shader object. - if (m_LightShader) + // Release the specular map shader object. + if (m_SpecMapShader) { - m_LightShader->Shutdown(); - delete m_LightShader; - m_LightShader = 0; + m_SpecMapShader->Shutdown(); + delete m_SpecMapShader; + m_SpecMapShader = 0; } - // Release the model object. - if (m_Model) + // Release the normal map shader object. + if (m_NormalMapShader) { - m_Model->Shutdown(); - delete m_Model; - m_Model = 0; + m_NormalMapShader->Shutdown(); + delete m_NormalMapShader; + m_NormalMapShader = 0; } // Liberez la memoire pour chaque cube @@ -408,17 +605,93 @@ void ApplicationClass::Shutdown() return; } + + // Release the alpha map shader object. + if (m_AlphaMapShader) + { + m_AlphaMapShader->Shutdown(); + delete m_AlphaMapShader; + m_AlphaMapShader = 0; + } } -bool ApplicationClass::Frame() +bool ApplicationClass::Frame(InputClass* Input) { + int mouseX, mouseY, currentMouseX, currentMouseY; + bool result, mouseDown, keyDown, buttonQ, buttonD, buttonZ, buttonS, buttonA, buttonE; + float rotationY, rotationX, positionX, positionY, positionZ; + float frameTime; - static float rotation = 0.0f; - static float x = 2.f; - static float y = 0.f; + + static int lastMouseX = 0, lastMouseY = 0; + + static float rotation = 360.0f; + static float x = 6.f; + static float y = 3.f; static float z = 0.f; - bool result; + + // Update the system stats. + m_Timer->Frame(); + + // Get the current frame time. + frameTime = m_Timer->GetTime(); + + // Check if the user pressed escape and wants to exit the application. + if (Input->IsEscapePressed()) + { + return false; + } + + // Get the location of the mouse from the input object, + Input->GetMouseLocation(mouseX, mouseY); + + currentMouseX = mouseX; + + float deltaX = currentMouseX - lastMouseX; // Calculez le d�placement de la souris + lastMouseX = currentMouseX; // Mettez � jour la derni�re position de la souris pour la prochaine image + + currentMouseY = mouseY; + + float deltaY = currentMouseY - lastMouseY; // Calculez le d�placement de la souris + lastMouseY = currentMouseY; // Mettez � jour la derni�re position de la souris pour la prochaine image + + // Set the frame time for calculating the updated position. + m_Position->SetFrameTime(m_Timer->GetTime()); + + // Check if the left or right arrow key has been pressed, if so rotate the camera accordingly. + keyDown = Input->IsLeftArrowPressed(); + m_Position->TurnLeft(keyDown); + + keyDown = Input->IsRightArrowPressed(); + m_Position->TurnRight(keyDown); + + m_Position->TurnMouse(deltaX, deltaY); + + // Get the current view point rotation. + m_Position->GetRotation(rotationY, rotationX); + + // Check if the a(q), d, w(z), s, q(a), e have been pressed, if so move the camera accordingly. + buttonQ = Input->IsAPressed(); + buttonD = Input->IsDPressed(); + buttonZ = Input->IsWPressed(); + buttonS = Input->IsSPressed(); + buttonA = Input->IsQPressed(); + buttonE = Input->IsEPressed(); + m_Position->MoveCamera(buttonZ, buttonS, buttonQ, buttonD, buttonE, buttonA); + m_Position->GetPosition(positionX, positionY, positionZ); + + // Set the postion and rotation of the camera. + m_Camera->SetPosition(positionX, positionY, positionZ); + m_Camera->SetRotation(rotationX, rotationY, 0.0f); + m_Camera->Render(); + + // Render the graphics scene. + result = Render(rotation, x, y, z); + if (!result) + { + return false; + } // Update the frames per second each frame. result = UpdateFps(); @@ -435,13 +708,19 @@ bool ApplicationClass::Frame() } // Update the x position variable each frame. - x -= 0.0174532925f * 0.54672f; + x -= 0.0174532925f * 0.6f; - y -= 0.0174532925f * 0.8972f; + y -= 0.0174532925f * 0.2f; // Update the z position variable each frame. - z -= 0.0174532925f * 0.8972f; + z -= 0.0174532925f * 0.2f; + // Render the scene to a render texture. + result = RenderSceneToTexture(rotation); + if (!result) + { + return false; + } // Render the graphics scene. result = Render(rotation, x, y, z); @@ -450,11 +729,15 @@ bool ApplicationClass::Frame() return false; } - // Update the system stats. - m_Timer->Frame(); + // Check if the mouse has been pressed. + mouseDown = Input->IsMousePressed(); - // Get the current frame time. - frameTime = m_Timer->GetTime(); + // Update the mouse strings each frame. + result = UpdateMouseStrings(mouseX, mouseY, mouseDown); + if (!result) + { + return false; + } // Update the sprite object using the frame time. m_Sprite->Update(frameTime); @@ -462,34 +745,180 @@ bool ApplicationClass::Frame() return true; } +bool ApplicationClass::RenderSceneToTexture(float rotation) +{ + XMMATRIX worldMatrix, viewMatrix, projectionMatrix; + bool result; + + // Set the render target to be the render texture and clear it. + m_RenderTexture->SetRenderTarget(m_Direct3D->GetDeviceContext()); + m_RenderTexture->ClearRenderTarget(m_Direct3D->GetDeviceContext(), 0.0f, 0.5f, 1.0f, 1.0f); + + // Set the position of the camera for viewing the cube. + m_Camera->SetPosition(0.0f, 0.0f, -5.0f); + m_Camera->Render(); + + // Get the matrices. + m_Direct3D->GetWorldMatrix(worldMatrix); + m_Camera->GetViewMatrix(viewMatrix); + m_RenderTexture->GetProjectionMatrix(projectionMatrix); + + // Rotate the world matrix by the rotation value so that the cube will spin. + worldMatrix = XMMatrixRotationY(rotation); + + // Render the model using the texture shader. + m_Model->Render(m_Direct3D->GetDeviceContext()); + + result = m_TextureShader->Render(m_Direct3D->GetDeviceContext(), m_Model->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, m_Model->GetTexture(1)); + if (!result) + { + return false; + } + + // Reset the render target back to the original back buffer and not the render to texture anymore. And reset the viewport back to the original. + m_Direct3D->SetBackBufferRenderTarget(); + m_Direct3D->ResetViewport(); + + return true; +} bool ApplicationClass::Render(float rotation, float x, float y, float z) { XMMATRIX worldMatrix, viewMatrix, orthoMatrix, projectionMatrix, rotateMatrix, translateMatrix, scaleMatrix, srMatrix; + float positionX, positionY, positionZ, radius; XMFLOAT4 diffuseColor[4], lightPosition[4]; - int i; - bool result; + int modelCount, renderCount, i; + bool result, renderModel; // Clear the buffers to begin the scene. m_Direct3D->BeginScene(0.0f, 0.0f, 0.0f, 1.0f); // Generate the view matrix based on the camera's position. + m_Camera->SetPosition(0.0f, 0.0f, -10.0f); m_Camera->Render(); // Get the world, view, and projection matrices from the camera and d3d objects. m_Direct3D->GetWorldMatrix(worldMatrix); - viewMatrix = m_Camera->GetViewMatrix(); + m_Camera->GetViewMatrix(viewMatrix); m_Direct3D->GetProjectionMatrix(projectionMatrix); m_Direct3D->GetOrthoMatrix(orthoMatrix); + // Setup matrices - Top display plane. + worldMatrix = XMMatrixTranslation(0.0f, 1.5f, 0.0f); + + // Render the display plane using the texture shader and the render texture resource. + m_DisplayPlane->Render(m_Direct3D->GetDeviceContext()); + + result = m_TextureShader->Render(m_Direct3D->GetDeviceContext(), m_DisplayPlane->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, m_RenderTexture->GetShaderResourceView()); + if (!result) + { + return false; + } + + // Setup matrices - Bottom left display plane. + worldMatrix = XMMatrixTranslation(-1.5f, -1.5f, 0.0f); + + // Render the display plane using the texture shader and the render texture resource. + m_DisplayPlane->Render(m_Direct3D->GetDeviceContext()); + + result = m_TextureShader->Render(m_Direct3D->GetDeviceContext(), m_DisplayPlane->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, m_RenderTexture->GetShaderResourceView()); + if (!result) + { + return false; + } + + // Setup matrices - Bottom right display plane. + worldMatrix = XMMatrixTranslation(1.5f, -1.5f, 0.0f); + + // Render the display plane using the texture shader and the render texture resource. + m_DisplayPlane->Render(m_Direct3D->GetDeviceContext()); + + result = m_TextureShader->Render(m_Direct3D->GetDeviceContext(), m_DisplayPlane->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, m_RenderTexture->GetShaderResourceView()); + if (!result) + { + return false; + } + + // Get the light properties. + for (i = 0; i < m_numLights; i++) + { + // Create the diffuse color array from the four light colors. + diffuseColor[i] = m_Lights[i].GetDiffuseColor(); + + // Create the light position array from the four light positions. + lightPosition[i] = m_Lights[i].GetPosition(); + } + + // Construct the frustum. + m_Frustum->ConstructFrustum(viewMatrix, projectionMatrix, SCREEN_DEPTH); + + // Get the number of models that will be rendered. + modelCount = m_ModelList->GetModelCount(); + + // Initialize the count of models that have been rendered. + renderCount = 0; + + // Go through all the models and render them only if they can be seen by the camera view. + for (i = 0; i < modelCount; i++) + { + // Get the position and color of the sphere model at this index. + m_ModelList->GetData(i, positionX, positionY, positionZ); + + // Set the radius of the sphere to 1.0 since this is already known. + radius = 1.0f; + + // Check if the sphere model is in the view frustum. + renderModel = m_Frustum->CheckSphere(positionX, positionY, positionZ, radius); + + // If it can be seen then render it, if not skip this model and check the next sphere. + if (renderModel) + { + // Move the model to the location it should be rendered at. + worldMatrix = XMMatrixTranslation(positionX, positionY, positionZ); + + // Render the model using the light shader. + m_Model->Render(m_Direct3D->GetDeviceContext()); + + result = m_LightShader->Render(m_Direct3D->GetDeviceContext(), m_Model->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, + m_Model->GetTexture(0), diffuseColor, lightPosition); + if (!result) + { + return false; + } + + // Since this model was rendered then increase the count for this frame. + renderCount++; + } + } + + // Update the render count text. + result = UpdateRenderCountString(renderCount); + if (!result) + { + return false; + } + // Disable the Z buffer and enable alpha blending for 2D rendering. m_Direct3D->TurnZBufferOff(); m_Direct3D->EnableAlphaBlending(); + // Reset the world matrix. + m_Direct3D->GetWorldMatrix(worldMatrix); + + // Render the render count text string using the font shader. + m_RenderCountString->Render(m_Direct3D->GetDeviceContext()); + + result = m_FontShader->Render(m_Direct3D->GetDeviceContext(), m_RenderCountString->GetIndexCount(), worldMatrix, m_baseViewMatrix, orthoMatrix, + m_Font->GetTexture(), m_RenderCountString->GetPixelColor()); + if (!result) + { + return false; + } + // Render the fps text string using the font shader. m_FpsString->Render(m_Direct3D->GetDeviceContext()); - result = m_FontShader->Render(m_Direct3D->GetDeviceContext(), m_FpsString->GetIndexCount(), worldMatrix, viewMatrix, orthoMatrix, + result = m_FontShader->Render(m_Direct3D->GetDeviceContext(), m_FpsString->GetIndexCount(), worldMatrix, m_baseViewMatrix, orthoMatrix, m_Font->GetTexture(), m_FpsString->GetPixelColor()); if (!result) { @@ -499,7 +928,7 @@ bool ApplicationClass::Render(float rotation, float x, float y, float z) // Render the first text string using the font shader. m_TextString1->Render(m_Direct3D->GetDeviceContext()); - result = m_FontShader->Render(m_Direct3D->GetDeviceContext(), m_TextString1->GetIndexCount(), worldMatrix, viewMatrix, orthoMatrix, + result = m_FontShader->Render(m_Direct3D->GetDeviceContext(), m_TextString1->GetIndexCount(), worldMatrix, m_baseViewMatrix, orthoMatrix, m_Font->GetTexture(), m_TextString1->GetPixelColor()); if (!result) { @@ -509,7 +938,7 @@ bool ApplicationClass::Render(float rotation, float x, float y, float z) // Render the second text string using the font shader. m_TextString2->Render(m_Direct3D->GetDeviceContext()); - result = m_FontShader->Render(m_Direct3D->GetDeviceContext(), m_TextString2->GetIndexCount(), worldMatrix, viewMatrix, orthoMatrix, + result = m_FontShader->Render(m_Direct3D->GetDeviceContext(), m_TextString2->GetIndexCount(), worldMatrix, m_baseViewMatrix, orthoMatrix, m_Font->GetTexture(), m_TextString2->GetPixelColor()); if (!result) { @@ -519,13 +948,26 @@ bool ApplicationClass::Render(float rotation, float x, float y, float z) // Render the second text string using the font shader. m_TextString3->Render(m_Direct3D->GetDeviceContext()); - result = m_FontShader->Render(m_Direct3D->GetDeviceContext(), m_TextString3->GetIndexCount(), worldMatrix, viewMatrix, orthoMatrix, + result = m_FontShader->Render(m_Direct3D->GetDeviceContext(), m_TextString3->GetIndexCount(), worldMatrix, m_baseViewMatrix, orthoMatrix, m_Font->GetTexture(), m_TextString3->GetPixelColor()); if (!result) { return false; } + // Render the mouse text strings using the font shader. + for (i = 0; i < 3; i++) + { + m_MouseStrings[i].Render(m_Direct3D->GetDeviceContext()); + + result = m_FontShader->Render(m_Direct3D->GetDeviceContext(), m_MouseStrings[i].GetIndexCount(), worldMatrix, m_baseViewMatrix, orthoMatrix, + m_Font->GetTexture(), m_MouseStrings[i].GetPixelColor()); + if (!result) + { + return false; + } + } + // Put the sprite vertex and index buffers on the graphics pipeline to prepare them for drawing. result = m_Sprite->Render(m_Direct3D->GetDeviceContext()); if (!result) @@ -556,15 +998,13 @@ bool ApplicationClass::Render(float rotation, float x, float y, float z) return false; } - // Get the light properties. - for (i = 0; i < m_numLights; i++) - { - // Create the diffuse color array from the four light colors. - diffuseColor[i] = m_Lights[i].GetDiffuseColor(); + //scaleMatrix = XMMatrixScaling(0.75f, 0.75f, 0.75f); // Build the scaling matrix. + //rotateMatrix = XMMatrixRotationY(rotation); // Build the rotation matrix. + //translateMatrix = XMMatrixTranslation(x, y, z); // Build the translation matrix. - // Create the light position array from the four light positions. - lightPosition[i] = m_Lights[i].GetPosition(); - } + //// Multiply the scale, rotation, and translation matrices together to create the final world transformation matrix. + //srMatrix = XMMatrixMultiply(scaleMatrix, rotateMatrix); + //worldMatrix = XMMatrixMultiply(srMatrix, translateMatrix); // Render the model using the multitexture shader. m_Model->Render(m_Direct3D->GetDeviceContext()); @@ -674,23 +1114,44 @@ bool ApplicationClass::Render(float rotation, float x, float y, float z) } } - - // Render the model using the multitexture shader. //result = m_MultiTextureShader->Render(m_Direct3D->GetDeviceContext(), m_Model->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, // m_Model->GetTexture(0), m_Model->GetTexture(1)); + //// Render the model using the multitexture shader. + //m_Model->Render(m_Direct3D->GetDeviceContext()); + + // Lighting, utilise plusieurs lights donc Multiple Points Lighting + //result = m_LightShader->Render(m_Direct3D->GetDeviceContext(), m_Model->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, m_Model->GetTexture(0), + // diffuseColor, lightPosition); + //if (!result) + //{ + // return false; + //} + + // Lightmapping, utiliser light01.tga en deuxieme texture + //result = m_LightMapShader->Render(m_Direct3D->GetDeviceContext(), m_Model->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, + // m_Model->GetTexture(0), m_Model->GetTexture(1)); + //if (!result) + //{ + // return false; + //} + + // MultiTexturing + //result = m_MultiTextureShader->Render(m_Direct3D->GetDeviceContext(), m_Model->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, + // m_Model->GetTexture(0), m_Model->GetTexture(1)); + //if (!result) + //{ + // return false; + //} + + // Alphamapping + /*result = m_AlphaMapShader->Render(m_Direct3D->GetDeviceContext(), m_Model->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, + m_Model->GetTexture(0), m_Model->GetTexture(1), m_Model->GetTexture(2)); if (!result) { return false; - } - - - - if (!result) - { - return false; - } + }*/ // Enable the Z buffer and disable alpha blending now that 2D rendering is complete. m_Direct3D->TurnZBufferOn(); @@ -722,10 +1183,12 @@ void ApplicationClass::GenerateTerrain() char modelFilename[128]; char textureFilename[128]; char textureFilename2[128]; + char textureFilename3[128]; // Set the file name of the model. strcpy_s(modelFilename, "plane.txt"); strcpy_s(textureFilename, "stone01.tga"); strcpy_s(textureFilename2, "moss01.tga"); + strcpy_s(textureFilename3, "alpha01.tga"); // for loop to generate terrain chunks for a 10x10 grid for (int i = -5; i < 5; i++) @@ -733,7 +1196,7 @@ void ApplicationClass::GenerateTerrain() for (int j = -5; j < 5; j++) { Object* newTerrain = new Object(); - newTerrain->Initialize(m_Direct3D->GetDevice(), m_Direct3D->GetDeviceContext(), modelFilename, textureFilename, textureFilename2); + newTerrain->Initialize(m_Direct3D->GetDevice(), m_Direct3D->GetDeviceContext(), modelFilename, textureFilename, textureFilename2, textureFilename3); newTerrain->SetTranslateMatrix(XMMatrixTranslation(i*10, -5.0f, j*10)); @@ -749,6 +1212,7 @@ void ApplicationClass::AddKobject(WCHAR* filepath) char modelFilename[128]; char textureFilename[128]; char textureFilename2[128]; + char textureFilename3[128]; filesystem::path p(filepath); string filename = p.stem().string(); @@ -759,9 +1223,10 @@ void ApplicationClass::AddKobject(WCHAR* filepath) // Set the name of the texture file that we will be loading. strcpy_s(textureFilename, "stone01.tga"); strcpy_s(textureFilename2, "moss01.tga"); + strcpy_s(textureFilename3, "alpha01.tga"); Object* newObject = new Object(); - newObject->Initialize(m_Direct3D->GetDevice(), m_Direct3D->GetDeviceContext(), modelFilename, textureFilename, textureFilename2); + newObject->Initialize(m_Direct3D->GetDevice(), m_Direct3D->GetDeviceContext(), modelFilename, textureFilename, textureFilename2, textureFilename3); newObject->SetTranslateMatrix(XMMatrixTranslation(0.0f, 0.0f, 0.0f)); newObject->SetName(filename); @@ -774,6 +1239,7 @@ void ApplicationClass::AddCube() char modelFilename[128]; char textureFilename[128]; char textureFilename2[128]; + char textureFilename3[128]; // Set the file name of the model. strcpy_s(modelFilename, "cube.txt"); @@ -781,10 +1247,11 @@ void ApplicationClass::AddCube() // Set the name of the texture file that we will be loading. strcpy_s(textureFilename, "stone01.tga"); strcpy_s(textureFilename2, "moss01.tga"); + strcpy_s(textureFilename3, "alpha01.tga"); static int cubeCount = 0; float position = cubeCount * 2.0f; Object* newCube = new Object(); - newCube->Initialize(m_Direct3D->GetDevice(), m_Direct3D->GetDeviceContext(), modelFilename, textureFilename, textureFilename2); + newCube->Initialize(m_Direct3D->GetDevice(), m_Direct3D->GetDeviceContext(), modelFilename, textureFilename, textureFilename2, textureFilename3); newCube->SetTranslateMatrix(XMMatrixTranslation(position, 0.0f, 0.0f)); @@ -809,7 +1276,54 @@ void ApplicationClass::DeleteTerrain() delete cube; } m_terrainChunk.clear(); +} +bool ApplicationClass::UpdateMouseStrings(int mouseX, int mouseY, bool mouseDown) +{ + char tempString[16], finalString[32]; + bool result; + + + // Convert the mouse X integer to string format. + sprintf_s(tempString, "%d", mouseX); + + // Setup the mouse X string. + strcpy_s(finalString, "Mouse X: "); + strcat_s(finalString, tempString); + + // Update the sentence vertex buffer with the new string information. + result = m_MouseStrings[0].UpdateText(m_Direct3D->GetDeviceContext(), m_Font, finalString, 10, 50, 1.0f, 1.0f, 1.0f); + if (!result) + { + return false; + } + + // Convert the mouse Y integer to string format. + sprintf_s(tempString, "%d", mouseY); + + // Setup the mouse Y string. + strcpy_s(finalString, "Mouse Y: "); + strcat_s(finalString, tempString); + + // Update the sentence vertex buffer with the new string information. + result = m_MouseStrings[1].UpdateText(m_Direct3D->GetDeviceContext(), m_Font, finalString, 10, 75, 1.0f, 1.0f, 1.0f); + if (!result) + { + return false; + } + + // Setup the mouse button string. + if (mouseDown) + { + strcpy_s(finalString, "Mouse Button: Yes"); + } + else + { + strcpy_s(finalString, "Mouse Button: No"); + } + + // Update the sentence vertex buffer with the new string information. + result = m_MouseStrings[2].UpdateText(m_Direct3D->GetDeviceContext(), m_Font, finalString, 10, 100, 1.0f, 1.0f, 1.0f); } bool ApplicationClass::UpdateFps() @@ -879,5 +1393,28 @@ bool ApplicationClass::UpdateFps() return false; } + return true; +} + +bool ApplicationClass::UpdateRenderCountString(int renderCount) +{ + char tempString[16], finalString[32]; + bool result; + + + // Convert the render count integer to string format. + sprintf_s(tempString, "%d", renderCount); + + // Setup the render count string. + strcpy_s(finalString, "Render Count: "); + strcat_s(finalString, tempString); + + // Update the sentence vertex buffer with the new string information. + result = m_RenderCountString->UpdateText(m_Direct3D->GetDeviceContext(), m_Font, finalString, 10, 30, 1.0f, 1.0f, 1.0f); + if (!result) + { + return false; + } + return true; } \ No newline at end of file diff --git a/enginecustom/applicationclass.h b/enginecustom/applicationclass.h index ce0e501..6ff1ee2 100644 --- a/enginecustom/applicationclass.h +++ b/enginecustom/applicationclass.h @@ -13,7 +13,9 @@ #include #include +#include "lightmapshaderclass.h" #include "multitextureshaderclass.h" +#include "alphamapshaderclass.h" #include "bitmapclass.h" #include "textureshaderclass.h" #include "spriteclass.h" @@ -22,6 +24,16 @@ #include "fontclass.h" #include "textclass.h" #include "fpsclass.h" +#include "inputclass.h" +#include "normalmapshaderclass.h" +#include "specmapshaderclass.h" +#include "modellistclass.h" +#include "positionclass.h" +#include "frustumclass.h" +#include "rendertextureclass.h" +#include "displayplaneclass.h" +#include "translateshaderclass.h" + ///////////// // GLOBALS // @@ -45,7 +57,7 @@ public: bool Initialize(int, int, HWND); void Shutdown(); - bool Frame(); + bool Frame(InputClass*); int GetScreenWidth() const; int GetScreenHeight() const; @@ -67,7 +79,11 @@ public: private: bool Render(float, float, float, float); + bool UpdateMouseStrings(int, int, bool); bool UpdateFps(); + bool UpdateRenderCountString(int); + bool RenderSceneToTexture(float); + private: D3DClass* m_Direct3D; CameraClass* m_Camera; @@ -78,21 +94,35 @@ private: std::vector m_terrainChunk; LightShaderClass* m_LightShader; LightClass* m_Light; + LightMapShaderClass* m_LightMapShader; MultiTextureShaderClass* m_MultiTextureShader; + AlphaMapShaderClass* m_AlphaMapShader; ModelClass* m_Model; TextureShaderClass* m_TextureShader; BitmapClass* m_Bitmap; SpriteClass* m_Sprite; TimerClass* m_Timer; + TextClass* m_MouseStrings; LightClass* m_Lights; int m_numLights; FontShaderClass* m_FontShader; + TextClass* m_RenderCountString; FontClass* m_Font; TextClass *m_TextString1, *m_TextString2, *m_TextString3; FpsClass* m_Fps; TextClass* m_FpsString; int m_previousFps; std::vector m_object; + NormalMapShaderClass* m_NormalMapShader; + SpecMapShaderClass* m_SpecMapShader; + ModelListClass* m_ModelList; + PositionClass* m_Position; + FrustumClass* m_Frustum; + XMMATRIX m_baseViewMatrix; + RenderTextureClass* m_RenderTexture; + DisplayPlaneClass* m_DisplayPlane; + float m_screenWidth, m_screenHeight; + TranslateShaderClass* m_TranslateShader; }; #endif \ No newline at end of file diff --git a/enginecustom/dirt01.tga b/enginecustom/dirt01.tga new file mode 100644 index 0000000..453fd8d Binary files /dev/null and b/enginecustom/dirt01.tga differ diff --git a/enginecustom/displayplaneclass.cpp b/enginecustom/displayplaneclass.cpp new file mode 100644 index 0000000..798489b --- /dev/null +++ b/enginecustom/displayplaneclass.cpp @@ -0,0 +1,199 @@ +#include "displayplaneclass.h" + + +DisplayPlaneClass::DisplayPlaneClass() +{ + m_vertexBuffer = 0; + m_indexBuffer = 0; +} + + +DisplayPlaneClass::DisplayPlaneClass(const DisplayPlaneClass& other) +{ +} + + +DisplayPlaneClass::~DisplayPlaneClass() +{ +} + +bool DisplayPlaneClass::Initialize(ID3D11Device* device, float width, float height) +{ + bool result; + + + // Initialize the vertex and index buffer that hold the geometry for the button. + result = InitializeBuffers(device, width, height); + if (!result) + { + return false; + } + + return true; +} + + +void DisplayPlaneClass::Shutdown() +{ + // Release the vertex and index buffers. + ShutdownBuffers(); + + return; +} + + +void DisplayPlaneClass::Render(ID3D11DeviceContext* deviceContext) +{ + // Put the vertex and index buffers on the graphics pipeline to prepare them for drawing. + RenderBuffers(deviceContext); + + return; +} + + +int DisplayPlaneClass::GetIndexCount() +{ + return m_indexCount; +} + +bool DisplayPlaneClass::InitializeBuffers(ID3D11Device* device, float width, float height) +{ + VertexType* vertices; + unsigned long* indices; + D3D11_BUFFER_DESC vertexBufferDesc, indexBufferDesc; + D3D11_SUBRESOURCE_DATA vertexData, indexData; + HRESULT result; + int i; + + + // Set the number of vertices in the vertex array. + m_vertexCount = 6; + + // Set the number of indices in the index array. + m_indexCount = m_vertexCount; + + // Create the vertex array. + vertices = new VertexType[m_vertexCount]; + + // Create the index array. + indices = new unsigned long[m_indexCount]; + + // Load the vertex array with data. + // First triangle. + vertices[0].position = XMFLOAT3(-width, height, 0.0f); // Top left. + vertices[0].texture = XMFLOAT2(0.0f, 0.0f); + + vertices[1].position = XMFLOAT3(width, -height, 0.0f); // Bottom right. + vertices[1].texture = XMFLOAT2(1.0f, 1.0f); + + vertices[2].position = XMFLOAT3(-width, -height, 0.0f); // Bottom left. + vertices[2].texture = XMFLOAT2(0.0f, 1.0f); + + // Second triangle. + vertices[3].position = XMFLOAT3(-width, height, 0.0f); // Top left. + vertices[3].texture = XMFLOAT2(0.0f, 0.0f); + + vertices[4].position = XMFLOAT3(width, height, 0.0f); // Top right. + vertices[4].texture = XMFLOAT2(1.0f, 0.0f); + + vertices[5].position = XMFLOAT3(width, -height, 0.0f); // Bottom right. + vertices[5].texture = XMFLOAT2(1.0f, 1.0f); + + // Load the index array with data. + for (i = 0; i < m_indexCount; i++) + { + indices[i] = i; + } + + // Set up the description of the vertex buffer. + vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT; + vertexBufferDesc.ByteWidth = sizeof(VertexType) * m_vertexCount; + vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + vertexBufferDesc.CPUAccessFlags = 0; + vertexBufferDesc.MiscFlags = 0; + vertexBufferDesc.StructureByteStride = 0; + + // Give the subresource structure a pointer to the vertex data. + vertexData.pSysMem = vertices; + vertexData.SysMemPitch = 0; + vertexData.SysMemSlicePitch = 0; + + // Now finally create the vertex buffer. + result = device->CreateBuffer(&vertexBufferDesc, &vertexData, &m_vertexBuffer); + if (FAILED(result)) + { + return false; + } + + // Set up the description of the index buffer. + indexBufferDesc.Usage = D3D11_USAGE_DEFAULT; + indexBufferDesc.ByteWidth = sizeof(unsigned long) * m_indexCount; + indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; + indexBufferDesc.CPUAccessFlags = 0; + indexBufferDesc.MiscFlags = 0; + indexBufferDesc.StructureByteStride = 0; + + // Give the subresource structure a pointer to the index data. + indexData.pSysMem = indices; + indexData.SysMemPitch = 0; + indexData.SysMemSlicePitch = 0; + + // Create the index buffer. + result = device->CreateBuffer(&indexBufferDesc, &indexData, &m_indexBuffer); + if (FAILED(result)) + { + return false; + } + + // Release the arrays now that the vertex and index buffers have been created and loaded. + delete[] vertices; + vertices = 0; + + delete[] indices; + indices = 0; + + return true; +} + + +void DisplayPlaneClass::ShutdownBuffers() +{ + // Release the index buffer. + if (m_indexBuffer) + { + m_indexBuffer->Release(); + m_indexBuffer = 0; + } + + // Release the vertex buffer. + if (m_vertexBuffer) + { + m_vertexBuffer->Release(); + m_vertexBuffer = 0; + } + + return; +} + + +void DisplayPlaneClass::RenderBuffers(ID3D11DeviceContext* deviceContext) +{ + unsigned int stride; + unsigned int offset; + + + // Set vertex buffer stride and offset. + stride = sizeof(VertexType); + offset = 0; + + // Set the vertex buffer to active in the input assembler so it can be rendered. + deviceContext->IASetVertexBuffers(0, 1, &m_vertexBuffer, &stride, &offset); + + // Set the index buffer to active in the input assembler so it can be rendered. + deviceContext->IASetIndexBuffer(m_indexBuffer, DXGI_FORMAT_R32_UINT, 0); + + // Set the type of primitive that should be rendered from this vertex buffer, in this case triangles. + deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + + return; +} \ No newline at end of file diff --git a/enginecustom/displayplaneclass.h b/enginecustom/displayplaneclass.h new file mode 100644 index 0000000..7d91023 --- /dev/null +++ b/enginecustom/displayplaneclass.h @@ -0,0 +1,44 @@ +#ifndef _DISPLAYPLANECLASS_H_ +#define _DISPLAYPLANECLASS_H_ + + +/////////////////////// +// MY CLASS INCLUDES // +/////////////////////// +#include "d3dclass.h" + + +//////////////////////////////////////////////////////////////////////////////// +// Class name: DisplayPlaneClass +//////////////////////////////////////////////////////////////////////////////// +class DisplayPlaneClass +{ +private: + struct VertexType + { + XMFLOAT3 position; + XMFLOAT2 texture; + }; + +public: + DisplayPlaneClass(); + DisplayPlaneClass(const DisplayPlaneClass&); + ~DisplayPlaneClass(); + + bool Initialize(ID3D11Device*, float, float); + void Shutdown(); + void Render(ID3D11DeviceContext*); + + int GetIndexCount(); + +private: + bool InitializeBuffers(ID3D11Device*, float, float); + void ShutdownBuffers(); + void RenderBuffers(ID3D11DeviceContext*); + +private: + ID3D11Buffer* m_vertexBuffer, * m_indexBuffer; + int m_vertexCount, m_indexCount; +}; + +#endif diff --git a/enginecustom/enginecustom.vcxproj b/enginecustom/enginecustom.vcxproj index 626a022..1da4132 100644 --- a/enginecustom/enginecustom.vcxproj +++ b/enginecustom/enginecustom.vcxproj @@ -20,6 +20,7 @@ + @@ -33,24 +34,38 @@ + + + + + + + + + + translate.vs + Code + + + @@ -65,30 +80,51 @@ + + + + + + + + + + translate.vs + Code + + + + + + + + + + @@ -112,8 +148,12 @@ + + + + @@ -124,6 +164,17 @@ + + + + + Designer + Document + + + Designer + Document + 17.0 diff --git a/enginecustom/enginecustom.vcxproj.filters b/enginecustom/enginecustom.vcxproj.filters index 4f52a15..cec0456 100644 --- a/enginecustom/enginecustom.vcxproj.filters +++ b/enginecustom/enginecustom.vcxproj.filters @@ -120,6 +120,39 @@ Fichiers sources + + Fichiers sources + + + Fichiers sources + + + Fichiers sources + + + Fichiers sources + + + Fichiers sources + + + Fichiers sources + + + Fichiers sources + + + Fichiers sources + + + Fichiers sources + + + Fichiers sources + + + Fichiers sources + @@ -209,6 +242,71 @@ Fichiers d%27en-tête + + Fichiers d%27en-tête + + + Fichiers d%27en-tête + + + Fichiers d%27en-tête + + + Fichiers d%27en-tête + + + Fichiers d%27en-tête + + + Fichiers d%27en-tête + + + Fichiers d%27en-tête + + + Fichiers d%27en-tête + + + Fichiers d%27en-tête + + + Fichiers d%27en-tête + + + Fichiers d%27en-tête + + + + + fonts + + + assets + + + assets + + + assets + + + assets + + + assets + + + assets + + + assets + + + assets + + + Assets + @@ -230,11 +328,29 @@ shader - - Texture + + shader - - Texture + + shader + + + texture + + + texture + + + shader + + + shader + + + shader + + + shader Texture @@ -242,26 +358,18 @@ Texture - - - - Fonts - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - + + Texture + + + Texture + + + shader + + + shader + @@ -279,5 +387,8 @@ Assets + + assets + \ No newline at end of file diff --git a/enginecustom/frustumclass.cpp b/enginecustom/frustumclass.cpp new file mode 100644 index 0000000..7f3f2ab --- /dev/null +++ b/enginecustom/frustumclass.cpp @@ -0,0 +1,296 @@ +#include "frustumclass.h" + + +FrustumClass::FrustumClass() +{ +} + + +FrustumClass::FrustumClass(const FrustumClass& other) +{ +} + + +FrustumClass::~FrustumClass() +{ +} + +void FrustumClass::ConstructFrustum(XMMATRIX viewMatrix, XMMATRIX projectionMatrix, float screenDepth) +{ + XMMATRIX finalMatrix; + XMFLOAT4X4 projMatrix, matrix; + float zMinimum, r, t; + + // Load the projection matrix into a XMFLOAT4X4 structure. + XMStoreFloat4x4(&projMatrix, projectionMatrix); + + // Calculate the minimum Z distance in the frustum. + zMinimum = -projMatrix._43 / projMatrix._33; + r = screenDepth / (screenDepth - zMinimum); + projMatrix._33 = r; + projMatrix._43 = -r * zMinimum; + + // Load the updated XMFLOAT4X4 back into the original projection matrix. + projectionMatrix = XMLoadFloat4x4(&projMatrix); + + // Create the frustum matrix from the view matrix and updated projection matrix. + finalMatrix = XMMatrixMultiply(viewMatrix, projectionMatrix); + + // Load the final matrix into a XMFLOAT4X4 structure. + XMStoreFloat4x4(&matrix, finalMatrix); + + // Get the near plane of the frustum. + m_planes[0].x = matrix._13; + m_planes[0].y = matrix._23; + m_planes[0].z = matrix._33; + m_planes[0].w = matrix._43; + + // Normalize it. + t = (float)sqrt((m_planes[0].x * m_planes[0].x) + (m_planes[0].y * m_planes[0].y) + (m_planes[0].z * m_planes[0].z)); + m_planes[0].x /= t; + m_planes[0].y /= t; + m_planes[0].z /= t; + m_planes[0].w /= t; + + // Calculate the far plane of frustum. + m_planes[1].x = matrix._14 - matrix._13; + m_planes[1].y = matrix._24 - matrix._23; + m_planes[1].z = matrix._34 - matrix._33; + m_planes[1].w = matrix._44 - matrix._43; + + // Normalize it. + t = (float)sqrt((m_planes[1].x * m_planes[1].x) + (m_planes[1].y * m_planes[1].y) + (m_planes[1].z * m_planes[1].z)); + m_planes[1].x /= t; + m_planes[1].y /= t; + m_planes[1].z /= t; + m_planes[1].w /= t; + + // Calculate the left plane of frustum. + m_planes[2].x = matrix._14 + matrix._11; + m_planes[2].y = matrix._24 + matrix._21; + m_planes[2].z = matrix._34 + matrix._31; + m_planes[2].w = matrix._44 + matrix._41; + + // Normalize it. + t = (float)sqrt((m_planes[2].x * m_planes[2].x) + (m_planes[2].y * m_planes[2].y) + (m_planes[2].z * m_planes[2].z)); + m_planes[2].x /= t; + m_planes[2].y /= t; + m_planes[2].z /= t; + m_planes[2].w /= t; + + // Calculate the right plane of frustum. + m_planes[3].x = matrix._14 - matrix._11; + m_planes[3].y = matrix._24 - matrix._21; + m_planes[3].z = matrix._34 - matrix._31; + m_planes[3].w = matrix._44 - matrix._41; + + // Normalize it. + t = (float)sqrt((m_planes[3].x * m_planes[3].x) + (m_planes[3].y * m_planes[3].y) + (m_planes[3].z * m_planes[3].z)); + m_planes[3].x /= t; + m_planes[3].y /= t; + m_planes[3].z /= t; + m_planes[3].w /= t; + + // Calculate the top plane of frustum. + m_planes[4].x = matrix._14 - matrix._12; + m_planes[4].y = matrix._24 - matrix._22; + m_planes[4].z = matrix._34 - matrix._32; + m_planes[4].w = matrix._44 - matrix._42; + + // Normalize it. + t = (float)sqrt((m_planes[4].x * m_planes[4].x) + (m_planes[4].y * m_planes[4].y) + (m_planes[4].z * m_planes[4].z)); + m_planes[4].x /= t; + m_planes[4].y /= t; + m_planes[4].z /= t; + m_planes[4].w /= t; + + // Calculate the bottom plane of frustum. + m_planes[5].x = matrix._14 + matrix._12; + m_planes[5].y = matrix._24 + matrix._22; + m_planes[5].z = matrix._34 + matrix._32; + m_planes[5].w = matrix._44 + matrix._42; + + // Normalize it. + t = (float)sqrt((m_planes[5].x * m_planes[5].x) + (m_planes[5].y * m_planes[5].y) + (m_planes[5].z * m_planes[5].z)); + m_planes[5].x /= t; + m_planes[5].y /= t; + m_planes[5].z /= t; + m_planes[5].w /= t; + + return; +} + +bool FrustumClass::CheckPoint(float x, float y, float z) +{ + int i; + + + // Check if the point is inside all six planes of the view frustum. + for (i = 0; i < 6; i++) + { + if (((m_planes[i].x * x) + (m_planes[i].y * y) + (m_planes[i].z * z) + m_planes[i].w) < 0.0f) + { + return false; + } + } + + return true; +} + +bool FrustumClass::CheckCube(float xCenter, float yCenter, float zCenter, float radius) +{ + int i; + + + // Check if any one point of the cube is in the view frustum. + for (i = 0; i < 6; i++) + { + if (m_planes[i].x * (xCenter - radius) + + m_planes[i].y * (yCenter - radius) + + m_planes[i].z * (zCenter - radius) + m_planes[i].w >= 0.0f) + { + continue; + } + + if (m_planes[i].x * (xCenter + radius) + + m_planes[i].y * (yCenter - radius) + + m_planes[i].z * (zCenter - radius) + m_planes[i].w >= 0.0f) + { + continue; + } + + if (m_planes[i].x * (xCenter - radius) + + m_planes[i].y * (yCenter + radius) + + m_planes[i].z * (zCenter - radius) + m_planes[i].w >= 0.0f) + { + continue; + } + + if (m_planes[i].x * (xCenter + radius) + + m_planes[i].y * (yCenter + radius) + + m_planes[i].z * (zCenter - radius) + m_planes[i].w >= 0.0f) + { + continue; + } + + if (m_planes[i].x * (xCenter - radius) + + m_planes[i].y * (yCenter - radius) + + m_planes[i].z * (zCenter + radius) + m_planes[i].w >= 0.0f) + { + continue; + } + + if (m_planes[i].x * (xCenter + radius) + + m_planes[i].y * (yCenter - radius) + + m_planes[i].z * (zCenter + radius) + m_planes[i].w >= 0.0f) + { + continue; + } + + if (m_planes[i].x * (xCenter - radius) + + m_planes[i].y * (yCenter + radius) + + m_planes[i].z * (zCenter + radius) + m_planes[i].w >= 0.0f) + { + continue; + } + + if (m_planes[i].x * (xCenter + radius) + + m_planes[i].y * (yCenter + radius) + + m_planes[i].z * (zCenter + radius) + m_planes[i].w >= 0.0f) + { + continue; + } + + return false; + } + + return true; +} + +bool FrustumClass::CheckSphere(float xCenter, float yCenter, float zCenter, float radius) +{ + int i; + + + // Check if the radius of the sphere is inside the view frustum. + for (i = 0; i < 6; i++) + { + if (((m_planes[i].x * xCenter) + (m_planes[i].y * yCenter) + (m_planes[i].z * zCenter) + m_planes[i].w) < -radius) + { + return false; + } + } + + return true; +} + +bool FrustumClass::CheckRectangle(float xCenter, float yCenter, float zCenter, float xSize, float ySize, float zSize) +{ + int i; + + + // Check if any of the 6 planes of the rectangle are inside the view frustum. + for (i = 0; i < 6; i++) + { + if (m_planes[i].x * (xCenter - xSize) + + m_planes[i].y * (yCenter - ySize) + + m_planes[i].z * (zCenter - zSize) + m_planes[i].w >= 0.0f) + { + continue; + } + + if (m_planes[i].x * (xCenter + xSize) + + m_planes[i].y * (yCenter - ySize) + + m_planes[i].z * (zCenter - zSize) + m_planes[i].w >= 0.0f) + { + continue; + } + + if (m_planes[i].x * (xCenter - xSize) + + m_planes[i].y * (yCenter + ySize) + + m_planes[i].z * (zCenter - zSize) + m_planes[i].w >= 0.0f) + { + continue; + } + + if (m_planes[i].x * (xCenter - xSize) + + m_planes[i].y * (yCenter - ySize) + + m_planes[i].z * (zCenter + zSize) + m_planes[i].w >= 0.0f) + { + continue; + } + + if (m_planes[i].x * (xCenter + xSize) + + m_planes[i].y * (yCenter + ySize) + + m_planes[i].z * (zCenter - zSize) + m_planes[i].w >= 0.0f) + { + continue; + } + + if (m_planes[i].x * (xCenter + xSize) + + m_planes[i].y * (yCenter - ySize) + + m_planes[i].z * (zCenter + zSize) + m_planes[i].w >= 0.0f) + { + continue; + } + + if (m_planes[i].x * (xCenter - xSize) + + m_planes[i].y * (yCenter + ySize) + + m_planes[i].z * (zCenter + zSize) + m_planes[i].w >= 0.0f) + { + continue; + } + + if (m_planes[i].x * (xCenter + xSize) + + m_planes[i].y * (yCenter + ySize) + + m_planes[i].z * (zCenter + zSize) + m_planes[i].w >= 0.0f) + { + continue; + } + + return false; + } + + return true; +} + diff --git a/enginecustom/frustumclass.h b/enginecustom/frustumclass.h new file mode 100644 index 0000000..6d3e3d0 --- /dev/null +++ b/enginecustom/frustumclass.h @@ -0,0 +1,33 @@ +#ifndef _FRUSTUMCLASS_H_ +#define _FRUSTUMCLASS_H_ + + +////////////// +// INCLUDES // +////////////// +#include +using namespace DirectX; + + +//////////////////////////////////////////////////////////////////////////////// +// Class name: FrustumClass +//////////////////////////////////////////////////////////////////////////////// +class FrustumClass +{ +public: + FrustumClass(); + FrustumClass(const FrustumClass&); + ~FrustumClass(); + + void ConstructFrustum(XMMATRIX, XMMATRIX, float); + + bool CheckPoint(float, float, float); + bool CheckCube(float, float, float, float); + bool CheckSphere(float, float, float, float); + bool CheckRectangle(float, float, float, float, float, float); + +private: + XMFLOAT4 m_planes[6]; +}; + +#endif \ No newline at end of file diff --git a/enginecustom/inputclass.cpp b/enginecustom/inputclass.cpp index 77c1cba..2a2c91f 100644 --- a/enginecustom/inputclass.cpp +++ b/enginecustom/inputclass.cpp @@ -3,6 +3,9 @@ InputClass::InputClass() { + m_directInput = 0; + m_keyboard = 0; + m_mouse = 0; } @@ -15,9 +18,9 @@ InputClass::~InputClass() { } - -void InputClass::Initialize() +bool InputClass::Initialize(HINSTANCE hinstance, HWND hwnd, int screenWidth, int screenHeight) { + HRESULT result; int i; @@ -27,10 +30,83 @@ void InputClass::Initialize() m_keys[i] = false; } - return; + // Store the screen size which will be used for positioning the mouse cursor. + m_screenWidth = screenWidth; + m_screenHeight = screenHeight; + + // Initialize the location of the mouse on the screen. + m_mouseX = 0; + m_mouseY = 0; + + // Initialize the main direct input interface. + result = DirectInput8Create(hinstance, DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&m_directInput, NULL); + if (FAILED(result)) + { + return false; + } + + // Initialize the direct input interface for the keyboard. + result = m_directInput->CreateDevice(GUID_SysKeyboard, &m_keyboard, NULL); + if (FAILED(result)) + { + return false; + } + + // Set the data format. In this case since it is a keyboard we can use the predefined data format. + result = m_keyboard->SetDataFormat(&c_dfDIKeyboard); + if (FAILED(result)) + { + return false; + } + + // Set the cooperative level of the keyboard to not share with other programs. + result = m_keyboard->SetCooperativeLevel(hwnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE); + if (FAILED(result)) + { + return false; + } + + // Now acquire the keyboard. + result = m_keyboard->Acquire(); + if (FAILED(result)) + { + return false; + } + + // Initialize the direct input interface for the mouse. + result = m_directInput->CreateDevice(GUID_SysMouse, &m_mouse, NULL); + if (FAILED(result)) + { + return false; + } + + // Set the data format for the mouse using the pre-defined mouse data format. + result = m_mouse->SetDataFormat(&c_dfDIMouse); + if (FAILED(result)) + { + return false; + } + + // Set the cooperative level of the mouse to share with other programs. + result = m_mouse->SetCooperativeLevel(hwnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE); + if (FAILED(result)) + { + return false; + } + + // Acquire the mouse. + result = m_mouse->Acquire(); + if (FAILED(result)) + { + return false; + } + + return true; } + + void InputClass::KeyDown(unsigned int input) { // If a key is pressed then save that state in the key array. @@ -51,4 +127,236 @@ bool InputClass::IsKeyDown(unsigned int key) { // Return what state the key is in (pressed/not pressed). return m_keys[key]; -} \ No newline at end of file +} + +void InputClass::Shutdown() +{ + // Release the mouse. + if (m_mouse) + { + m_mouse->Unacquire(); + m_mouse->Release(); + m_mouse = 0; + } + + // Release the keyboard. + if (m_keyboard) + { + m_keyboard->Unacquire(); + m_keyboard->Release(); + m_keyboard = 0; + } + + // Release the main interface to direct input. + if (m_directInput) + { + m_directInput->Release(); + m_directInput = 0; + } + + return; +} + +bool InputClass::Frame() +{ + bool result; + + + // Read the current state of the keyboard. + result = ReadKeyboard(); + if (!result) + { + return false; + } + + // Read the current state of the mouse. + result = ReadMouse(); + if (!result) + { + return false; + } + + // Process the changes in the mouse and keyboard. + ProcessInput(); + + return true; +} + +bool InputClass::ReadKeyboard() +{ + HRESULT result; + + + // Read the keyboard device. + result = m_keyboard->GetDeviceState(sizeof(m_keyboardState), (LPVOID)&m_keyboardState); + if (FAILED(result)) + { + // If the keyboard lost focus or was not acquired then try to get control back. + if ((result == DIERR_INPUTLOST) || (result == DIERR_NOTACQUIRED)) + { + m_keyboard->Acquire(); + } + else + { + return false; + } + } + + return true; +} + +bool InputClass::ReadMouse() +{ + HRESULT result; + + + // Read the mouse device. + result = m_mouse->GetDeviceState(sizeof(DIMOUSESTATE), (LPVOID)&m_mouseState); + if (FAILED(result)) + { + // If the mouse lost focus or was not acquired then try to get control back. + if ((result == DIERR_INPUTLOST) || (result == DIERR_NOTACQUIRED)) + { + m_mouse->Acquire(); + } + else + { + return false; + } + } + + return true; +} + +void InputClass::ProcessInput() +{ + // Update the location of the mouse cursor based on the change of the mouse location during the frame. + m_mouseX += m_mouseState.lX; + m_mouseY += m_mouseState.lY; + + //// Ensure the mouse location doesn't exceed the screen width or height. + //if (m_mouseX < 0) { m_mouseX = 0; } + if (m_mouseY < -m_screenHeight) { m_mouseY = -m_screenHeight; } + + //if (m_mouseX > m_screenWidth) { m_mouseX = m_screenWidth; } + if (m_mouseY > m_screenHeight) { m_mouseY = m_screenHeight; } + + return; +} + +bool InputClass::IsEscapePressed() +{ + // Do a bitwise and on the keyboard state to check if the escape key is currently being pressed. + if (m_keyboardState[DIK_ESCAPE] & 0x80) + { + return true; + } + + return false; +} + +bool InputClass::IsLeftArrowPressed() +{ + if (m_keyboardState[DIK_LEFT] & 0x80) + { + return true; + } + + return false; +} + + +bool InputClass::IsRightArrowPressed() +{ + if (m_keyboardState[DIK_RIGHT] & 0x80) + { + return true; + } + + return false; +} + +/////////////////////////////////////////////////// +// Les touches correspondent aux claviers QWERTY // +/////////////////////////////////////////////////// + +bool InputClass::IsAPressed() +{ + // Touche A sur QWERTY, Q sur AZERTY + if (m_keyboardState[DIK_A] & 0x80) + { + return true; + } + + return false; +} + +bool InputClass::IsDPressed() +{ + if (m_keyboardState[DIK_D] & 0x80) + { + return true; + } + + return false; +} + +bool InputClass::IsWPressed() +{ + // Touche W sur QWERTY, Z sur AZERTY + if (m_keyboardState[DIK_W] & 0x80) + { + return true; + } + + return false; +} + +bool InputClass::IsSPressed() +{ + if (m_keyboardState[DIK_S] & 0x80) + { + return true; + } + + return false; +} + +bool InputClass::IsQPressed() +{ + // Touche Q sur QWERTY, A sur AZERTY + if (m_keyboardState[DIK_Q] & 0x80) + { + return true; + } + + return false; +} + +bool InputClass::IsEPressed() +{ + if (m_keyboardState[DIK_E] & 0x80) + { + return true; + } + + return false; +} + +void InputClass::GetMouseLocation(int& mouseX, int& mouseY) +{ + mouseX = m_mouseX; + mouseY = m_mouseY; + return; +} + +bool InputClass::IsMousePressed() +{ + // Check the left mouse button state. + if (m_mouseState.rgbButtons[0] & 0x80) + { + return true; + } + + return false; +} diff --git a/enginecustom/inputclass.h b/enginecustom/inputclass.h index c079281..d559872 100644 --- a/enginecustom/inputclass.h +++ b/enginecustom/inputclass.h @@ -1,6 +1,21 @@ #ifndef _INPUTCLASS_H_ #define _INPUTCLASS_H_ +/////////////////////////////// +// PRE-PROCESSING DIRECTIVES // +/////////////////////////////// +#define DIRECTINPUT_VERSION 0x0800 + +///////////// +// LINKING // +///////////// +#pragma comment(lib, "dinput8.lib") +#pragma comment(lib, "dxguid.lib") + +////////////// +// INCLUDES // +////////////// +#include //////////////////////////////////////////////////////////////////////////////// // Class name: InputClass @@ -12,15 +27,42 @@ public: InputClass(const InputClass&); ~InputClass(); - void Initialize(); + bool Initialize(HINSTANCE, HWND, int, int); + void Shutdown(); + bool Frame(); + bool IsEscapePressed(); + void GetMouseLocation(int&, int&); + bool IsMousePressed(); void KeyDown(unsigned int); void KeyUp(unsigned int); + bool IsLeftArrowPressed(); + bool IsRightArrowPressed(); + bool IsAPressed(); + bool IsDPressed(); + bool IsWPressed(); + bool IsSPressed(); + bool IsQPressed(); + bool IsEPressed(); bool IsKeyDown(unsigned int); private: bool m_keys[256]; + + bool ReadKeyboard(); + bool ReadMouse(); + void ProcessInput(); + +private: + IDirectInput8* m_directInput; + IDirectInputDevice8* m_keyboard; + IDirectInputDevice8* m_mouse; + + unsigned char m_keyboardState[256]; + DIMOUSESTATE m_mouseState; + + int m_screenWidth, m_screenHeight, m_mouseX, m_mouseY; }; #endif \ No newline at end of file diff --git a/enginecustom/light01.tga b/enginecustom/light01.tga new file mode 100644 index 0000000..7aa0f52 Binary files /dev/null and b/enginecustom/light01.tga differ diff --git a/enginecustom/lightmap.ps b/enginecustom/lightmap.ps new file mode 100644 index 0000000..3984d43 --- /dev/null +++ b/enginecustom/lightmap.ps @@ -0,0 +1,38 @@ +///////////// +// GLOBALS // +///////////// +Texture2D shaderTexture1 : register(t0); +Texture2D shaderTexture2 : register(t1); +SamplerState SampleType : register(s0); + + +////////////// +// TYPEDEFS // +////////////// +struct PixelInputType +{ + float4 position : SV_POSITION; + float2 tex : TEXCOORD0; +}; + +//////////////////////////////////////////////////////////////////////////////// +// Pixel Shader +//////////////////////////////////////////////////////////////////////////////// +float4 LightMapPixelShader(PixelInputType input) : SV_TARGET +{ + float4 color; + float4 lightColor; + float4 finalColor; + + + // Get the pixel color from the color texture. + color = shaderTexture1.Sample(SampleType, input.tex); + + // Get the pixel color from the light map. + lightColor = shaderTexture2.Sample(SampleType, input.tex); + + // Blend the two pixels together. + finalColor = color * lightColor; + + return finalColor; +} diff --git a/enginecustom/lightmap.vs b/enginecustom/lightmap.vs new file mode 100644 index 0000000..4a6190b --- /dev/null +++ b/enginecustom/lightmap.vs @@ -0,0 +1,49 @@ +///////////// +// GLOBALS // +///////////// +cbuffer MatrixBuffer +{ + matrix worldMatrix; + matrix viewMatrix; + matrix projectionMatrix; +}; + + +////////////// +// TYPEDEFS // +////////////// +struct VertexInputType +{ + float4 position : POSITION; + float2 tex : TEXCOORD0; + float3 normal : NORMAL; +}; + +struct PixelInputType +{ + float4 position : SV_POSITION; + float2 tex : TEXCOORD0; +}; + + +//////////////////////////////////////////////////////////////////////////////// +// Vertex Shader +//////////////////////////////////////////////////////////////////////////////// +PixelInputType LightMapVertexShader(VertexInputType input) +{ + PixelInputType output; + + + // Change the position vector to be 4 units for proper matrix calculations. + input.position.w = 1.0f; + + // Calculate the position of the vertex against the world, view, and projection matrices. + output.position = mul(input.position, worldMatrix); + output.position = mul(output.position, viewMatrix); + output.position = mul(output.position, projectionMatrix); + + // Store the texture coordinates for the pixel shader. + output.tex = input.tex; + + return output; +} \ No newline at end of file diff --git a/enginecustom/lightmapshaderclass.cpp b/enginecustom/lightmapshaderclass.cpp new file mode 100644 index 0000000..82d6ed8 --- /dev/null +++ b/enginecustom/lightmapshaderclass.cpp @@ -0,0 +1,377 @@ +#include "lightmapshaderclass.h" + + +LightMapShaderClass::LightMapShaderClass() +{ + m_vertexShader = 0; + m_pixelShader = 0; + m_layout = 0; + m_matrixBuffer = 0; + m_sampleState = 0; +} + + +LightMapShaderClass::LightMapShaderClass(const LightMapShaderClass& other) +{ +} + + +LightMapShaderClass::~LightMapShaderClass() +{ +} + + +bool LightMapShaderClass::Initialize(ID3D11Device* device, HWND hwnd) +{ + bool result; + wchar_t vsFilename[128]; + wchar_t psFilename[128]; + int error; + + // Set the filename of the vertex shader. + error = wcscpy_s(vsFilename, 128, L"lightmap.vs"); + if (error != 0) + { + return false; + } + + // Set the filename of the pixel shader. + error = wcscpy_s(psFilename, 128, L"lightmap.ps"); + if (error != 0) + { + return false; + } + + // Initialize the vertex and pixel shaders. + result = InitializeShader(device, hwnd, vsFilename, psFilename); + if (!result) + { + return false; + } + + return true; +} + + +void LightMapShaderClass::Shutdown() +{ + // Shutdown the vertex and pixel shaders as well as the related objects. + ShutdownShader(); + + return; +} + + +bool LightMapShaderClass::Render(ID3D11DeviceContext* deviceContext, int indexCount, XMMATRIX worldMatrix, XMMATRIX viewMatrix, + XMMATRIX projectionMatrix, ID3D11ShaderResourceView* texture1, ID3D11ShaderResourceView* texture2) +{ + bool result; + + + // Set the shader parameters that it will use for rendering. + result = SetShaderParameters(deviceContext, worldMatrix, viewMatrix, projectionMatrix, texture1, texture2); + if (!result) + { + return false; + } + + // Now render the prepared buffers with the shader. + RenderShader(deviceContext, indexCount); + + return true; +} + + +bool LightMapShaderClass::InitializeShader(ID3D11Device* device, HWND hwnd, WCHAR* vsFilename, WCHAR* psFilename) +{ + HRESULT result; + ID3D10Blob* errorMessage; + ID3D10Blob* vertexShaderBuffer; + ID3D10Blob* pixelShaderBuffer; + D3D11_INPUT_ELEMENT_DESC polygonLayout[3]; + unsigned int numElements; + D3D11_BUFFER_DESC matrixBufferDesc; + D3D11_SAMPLER_DESC samplerDesc; + + + // Initialize the pointers this function will use to null. + errorMessage = 0; + vertexShaderBuffer = 0; + pixelShaderBuffer = 0; + + // Compile the vertex shader code. + result = D3DCompileFromFile(vsFilename, NULL, NULL, "LightMapVertexShader", "vs_5_0", D3D10_SHADER_ENABLE_STRICTNESS, 0, + &vertexShaderBuffer, &errorMessage); + if (FAILED(result)) + { + // If the shader failed to compile it should have writen something to the error message. + if (errorMessage) + { + OutputShaderErrorMessage(errorMessage, hwnd, vsFilename); + } + // If there was nothing in the error message then it simply could not find the shader file itself. + else + { + MessageBox(hwnd, vsFilename, L"Missing Shader File", MB_OK); + } + + return false; + } + + // Compile the pixel shader code. + result = D3DCompileFromFile(psFilename, NULL, NULL, "LightMapPixelShader", "ps_5_0", D3D10_SHADER_ENABLE_STRICTNESS, 0, + &pixelShaderBuffer, &errorMessage); + if (FAILED(result)) + { + // If the shader failed to compile it should have writen something to the error message. + if (errorMessage) + { + OutputShaderErrorMessage(errorMessage, hwnd, psFilename); + } + // If there was nothing in the error message then it simply could not find the file itself. + else + { + MessageBox(hwnd, psFilename, L"Missing Shader File", MB_OK); + } + + return false; + } + + // Create the vertex shader from the buffer. + result = device->CreateVertexShader(vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), NULL, &m_vertexShader); + if (FAILED(result)) + { + return false; + } + + // Create the pixel shader from the buffer. + result = device->CreatePixelShader(pixelShaderBuffer->GetBufferPointer(), pixelShaderBuffer->GetBufferSize(), NULL, &m_pixelShader); + if (FAILED(result)) + { + return false; + } + + // Create the vertex input layout description. + polygonLayout[0].SemanticName = "POSITION"; + polygonLayout[0].SemanticIndex = 0; + polygonLayout[0].Format = DXGI_FORMAT_R32G32B32_FLOAT; + polygonLayout[0].InputSlot = 0; + polygonLayout[0].AlignedByteOffset = 0; + polygonLayout[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + polygonLayout[0].InstanceDataStepRate = 0; + + polygonLayout[1].SemanticName = "TEXCOORD"; + polygonLayout[1].SemanticIndex = 0; + polygonLayout[1].Format = DXGI_FORMAT_R32G32_FLOAT; + polygonLayout[1].InputSlot = 0; + polygonLayout[1].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT; + polygonLayout[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + polygonLayout[1].InstanceDataStepRate = 0; + + polygonLayout[2].SemanticName = "NORMAL"; + polygonLayout[2].SemanticIndex = 0; + polygonLayout[2].Format = DXGI_FORMAT_R32G32B32_FLOAT; + polygonLayout[2].InputSlot = 0; + polygonLayout[2].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT; + polygonLayout[2].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + polygonLayout[2].InstanceDataStepRate = 0; + + // Get a count of the elements in the layout. + numElements = sizeof(polygonLayout) / sizeof(polygonLayout[0]); + + // Create the vertex input layout. + result = device->CreateInputLayout(polygonLayout, numElements, vertexShaderBuffer->GetBufferPointer(), + vertexShaderBuffer->GetBufferSize(), &m_layout); + if (FAILED(result)) + { + return false; + } + + // Release the vertex shader buffer and pixel shader buffer since they are no longer needed. + vertexShaderBuffer->Release(); + vertexShaderBuffer = 0; + + pixelShaderBuffer->Release(); + pixelShaderBuffer = 0; + + // Setup the description of the dynamic matrix constant buffer that is in the vertex shader. + matrixBufferDesc.Usage = D3D11_USAGE_DYNAMIC; + matrixBufferDesc.ByteWidth = sizeof(MatrixBufferType); + matrixBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + matrixBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + matrixBufferDesc.MiscFlags = 0; + matrixBufferDesc.StructureByteStride = 0; + + // Create the constant buffer pointer so we can access the vertex shader constant buffer from within this class. + result = device->CreateBuffer(&matrixBufferDesc, NULL, &m_matrixBuffer); + if (FAILED(result)) + { + return false; + } + + // Create a texture sampler state description. + samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + samplerDesc.MipLODBias = 0.0f; + samplerDesc.MaxAnisotropy = 1; + samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + samplerDesc.BorderColor[0] = 0; + samplerDesc.BorderColor[1] = 0; + samplerDesc.BorderColor[2] = 0; + samplerDesc.BorderColor[3] = 0; + samplerDesc.MinLOD = 0; + samplerDesc.MaxLOD = D3D11_FLOAT32_MAX; + + // Create the texture sampler state. + result = device->CreateSamplerState(&samplerDesc, &m_sampleState); + if (FAILED(result)) + { + return false; + } + + return true; +} + + +void LightMapShaderClass::ShutdownShader() +{ + // Release the sampler state. + if (m_sampleState) + { + m_sampleState->Release(); + m_sampleState = 0; + } + + // Release the matrix constant buffer. + if (m_matrixBuffer) + { + m_matrixBuffer->Release(); + m_matrixBuffer = 0; + } + + // Release the layout. + if (m_layout) + { + m_layout->Release(); + m_layout = 0; + } + + // Release the pixel shader. + if (m_pixelShader) + { + m_pixelShader->Release(); + m_pixelShader = 0; + } + + // Release the vertex shader. + if (m_vertexShader) + { + m_vertexShader->Release(); + m_vertexShader = 0; + } + + return; +} + + +void LightMapShaderClass::OutputShaderErrorMessage(ID3D10Blob* errorMessage, HWND hwnd, WCHAR* shaderFilename) +{ + char* compileErrors; + unsigned long long bufferSize, i; + ofstream fout; + + + // Get a pointer to the error message text buffer. + compileErrors = (char*)(errorMessage->GetBufferPointer()); + + // Get the length of the message. + bufferSize = errorMessage->GetBufferSize(); + + // Open a file to write the error message to. + fout.open("shader-error.txt"); + + // Write out the error message. + for (i = 0; i < bufferSize; i++) + { + fout << compileErrors[i]; + } + + // Close the file. + fout.close(); + + // Release the error message. + errorMessage->Release(); + errorMessage = 0; + + // Pop a message up on the screen to notify the user to check the text file for compile errors. + MessageBox(hwnd, L"Error compiling shader. Check shader-error.txt for message.", shaderFilename, MB_OK); + + return; +} + + +bool LightMapShaderClass::SetShaderParameters(ID3D11DeviceContext* deviceContext, XMMATRIX worldMatrix, XMMATRIX viewMatrix, + XMMATRIX projectionMatrix, ID3D11ShaderResourceView* texture1, ID3D11ShaderResourceView* texture2) +{ + HRESULT result; + D3D11_MAPPED_SUBRESOURCE mappedResource; + MatrixBufferType* dataPtr; + unsigned int bufferNumber; + + + // Transpose the matrices to prepare them for the shader. + worldMatrix = XMMatrixTranspose(worldMatrix); + viewMatrix = XMMatrixTranspose(viewMatrix); + projectionMatrix = XMMatrixTranspose(projectionMatrix); + + // Lock the constant buffer so it can be written to. + result = deviceContext->Map(m_matrixBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + return false; + } + + // Get a pointer to the data in the constant buffer. + dataPtr = (MatrixBufferType*)mappedResource.pData; + + // Copy the matrices into the constant buffer. + dataPtr->world = worldMatrix; + dataPtr->view = viewMatrix; + dataPtr->projection = projectionMatrix; + + // Unlock the constant buffer. + deviceContext->Unmap(m_matrixBuffer, 0); + + // Set the position of the constant buffer in the vertex shader. + bufferNumber = 0; + + // Finally set the constant buffer in the vertex shader with the updated values. + deviceContext->VSSetConstantBuffers(bufferNumber, 1, &m_matrixBuffer); + + // Set shader texture resources in the pixel shader. + deviceContext->PSSetShaderResources(0, 1, &texture1); + deviceContext->PSSetShaderResources(1, 1, &texture2); + + return true; +} + + +void LightMapShaderClass::RenderShader(ID3D11DeviceContext* deviceContext, int indexCount) +{ + // Set the vertex input layout. + deviceContext->IASetInputLayout(m_layout); + + // Set the vertex and pixel shaders that will be used to render this triangle. + deviceContext->VSSetShader(m_vertexShader, NULL, 0); + deviceContext->PSSetShader(m_pixelShader, NULL, 0); + + // Set the sampler state in the pixel shader. + deviceContext->PSSetSamplers(0, 1, &m_sampleState); + + // Render the triangle. + deviceContext->DrawIndexed(indexCount, 0, 0); + + return; +} diff --git a/enginecustom/lightmapshaderclass.h b/enginecustom/lightmapshaderclass.h new file mode 100644 index 0000000..0e3d32b --- /dev/null +++ b/enginecustom/lightmapshaderclass.h @@ -0,0 +1,55 @@ +//////////////////////////////////////////////////////////////////////////////// +#ifndef _LIGHTMAPSHADERCLASS_H_ +#define _LIGHTMAPSHADERCLASS_H_ + + +////////////// +// INCLUDES // +////////////// +#include +#include +#include +#include +using namespace DirectX; +using namespace std; + + +//////////////////////////////////////////////////////////////////////////////// +// Class name: LightMapShaderClass +//////////////////////////////////////////////////////////////////////////////// +class LightMapShaderClass +{ +private: + struct MatrixBufferType + { + XMMATRIX world; + XMMATRIX view; + XMMATRIX projection; + }; + +public: + LightMapShaderClass(); + LightMapShaderClass(const LightMapShaderClass&); + ~LightMapShaderClass(); + + bool Initialize(ID3D11Device*, HWND); + void Shutdown(); + bool Render(ID3D11DeviceContext*, int, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, ID3D11ShaderResourceView*); + +private: + bool InitializeShader(ID3D11Device*, HWND, WCHAR*, WCHAR*); + void ShutdownShader(); + void OutputShaderErrorMessage(ID3D10Blob*, HWND, WCHAR*); + + bool SetShaderParameters(ID3D11DeviceContext*, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, ID3D11ShaderResourceView*); + void RenderShader(ID3D11DeviceContext*, int); + +private: + ID3D11VertexShader* m_vertexShader; + ID3D11PixelShader* m_pixelShader; + ID3D11InputLayout* m_layout; + ID3D11Buffer* m_matrixBuffer; + ID3D11SamplerState* m_sampleState; +}; + +#endif \ No newline at end of file diff --git a/enginecustom/modelclass.cpp b/enginecustom/modelclass.cpp index b67841f..38dcfa7 100644 --- a/enginecustom/modelclass.cpp +++ b/enginecustom/modelclass.cpp @@ -19,7 +19,7 @@ ModelClass::~ModelClass() { } -bool ModelClass::Initialize(ID3D11Device* device, ID3D11DeviceContext* deviceContext,char* modelFilename,char* textureFilename1,char* textureFilename2) +bool ModelClass::Initialize(ID3D11Device* device, ID3D11DeviceContext* deviceContext, char* modelFilename, char* textureFilename1, char* textureFilename2, char* textureFilename3) { bool result; @@ -30,6 +30,9 @@ bool ModelClass::Initialize(ID3D11Device* device, ID3D11DeviceContext* deviceCon return false; } + // Calculate the tangent and binormal vectors for the model. + CalculateModelVectors(); + // Initialize the vertex and index buffers. result = InitializeBuffers(device); if (!result) @@ -37,7 +40,7 @@ bool ModelClass::Initialize(ID3D11Device* device, ID3D11DeviceContext* deviceCon return false; } // Load the textures for this model. - result = LoadTextures(device, deviceContext, textureFilename1, textureFilename2); + result = LoadTextures(device, deviceContext, textureFilename1, textureFilename2, textureFilename3); if (!result) { return false; @@ -103,6 +106,8 @@ bool ModelClass::InitializeBuffers(ID3D11Device* device) vertices[i].position = XMFLOAT3(m_model[i].x, m_model[i].y, m_model[i].z); vertices[i].texture = XMFLOAT2(m_model[i].tu, m_model[i].tv); vertices[i].normal = XMFLOAT3(m_model[i].nx, m_model[i].ny, m_model[i].nz); + vertices[i].tangent = XMFLOAT3(m_model[i].tx, m_model[i].ty, m_model[i].tz); + vertices[i].binormal = XMFLOAT3(m_model[i].bx, m_model[i].by, m_model[i].bz); indices[i] = i; } @@ -200,13 +205,14 @@ void ModelClass::RenderBuffers(ID3D11DeviceContext* deviceContext) return; } -bool ModelClass::LoadTextures(ID3D11Device* device, ID3D11DeviceContext* deviceContext, char* filename1, char* filename2) + +bool ModelClass::LoadTextures(ID3D11Device* device, ID3D11DeviceContext* deviceContext, char* filename1, char* filename2, char* filename3) { bool result; // Create and initialize the texture object array. - m_Textures = new TextureClass[2]; + m_Textures = new TextureClass[3]; result = m_Textures[0].Initialize(device, deviceContext, filename1); if (!result) @@ -220,6 +226,13 @@ bool ModelClass::LoadTextures(ID3D11Device* device, ID3D11DeviceContext* deviceC return false; } + result = m_Textures[2].Initialize(device, deviceContext, filename3); + if (!result) + { + return false; + } + + return true; } @@ -230,6 +243,7 @@ void ModelClass::ReleaseTextures() { m_Textures[0].Shutdown(); m_Textures[1].Shutdown(); + m_Textures[2].Shutdown(); delete[] m_Textures; m_Textures = 0; @@ -293,6 +307,128 @@ bool ModelClass::LoadModel(char* filename) return true; } +void ModelClass::CalculateModelVectors() +{ + int faceCount, i, index; + TempVertexType vertex1, vertex2, vertex3; + VectorType tangent, binormal; + + + // Calculate the number of faces in the model. + faceCount = m_vertexCount / 3; + + // Initialize the index to the model data. + index = 0; + + // Go through all the faces and calculate the the tangent and binormal vectors. + for (i = 0; i < faceCount; i++) + { + // Get the three vertices for this face from the model. + vertex1.x = m_model[index].x; + vertex1.y = m_model[index].y; + vertex1.z = m_model[index].z; + vertex1.tu = m_model[index].tu; + vertex1.tv = m_model[index].tv; + index++; + + vertex2.x = m_model[index].x; + vertex2.y = m_model[index].y; + vertex2.z = m_model[index].z; + vertex2.tu = m_model[index].tu; + vertex2.tv = m_model[index].tv; + index++; + + vertex3.x = m_model[index].x; + vertex3.y = m_model[index].y; + vertex3.z = m_model[index].z; + vertex3.tu = m_model[index].tu; + vertex3.tv = m_model[index].tv; + index++; + + // Calculate the tangent and binormal of that face. + CalculateTangentBinormal(vertex1, vertex2, vertex3, tangent, binormal); + + // Store the tangent and binormal for this face back in the model structure. + m_model[index - 1].tx = tangent.x; + m_model[index - 1].ty = tangent.y; + m_model[index - 1].tz = tangent.z; + m_model[index - 1].bx = binormal.x; + m_model[index - 1].by = binormal.y; + m_model[index - 1].bz = binormal.z; + + m_model[index - 2].tx = tangent.x; + m_model[index - 2].ty = tangent.y; + m_model[index - 2].tz = tangent.z; + m_model[index - 2].bx = binormal.x; + m_model[index - 2].by = binormal.y; + m_model[index - 2].bz = binormal.z; + + m_model[index - 3].tx = tangent.x; + m_model[index - 3].ty = tangent.y; + m_model[index - 3].tz = tangent.z; + m_model[index - 3].bx = binormal.x; + m_model[index - 3].by = binormal.y; + m_model[index - 3].bz = binormal.z; + } + + return; +} + +void ModelClass::CalculateTangentBinormal(TempVertexType vertex1, TempVertexType vertex2, TempVertexType vertex3, VectorType& tangent, VectorType& binormal) +{ + float vector1[3], vector2[3]; + float tuVector[2], tvVector[2]; + float den; + float length; + + + // Calculate the two vectors for this face. + vector1[0] = vertex2.x - vertex1.x; + vector1[1] = vertex2.y - vertex1.y; + vector1[2] = vertex2.z - vertex1.z; + + vector2[0] = vertex3.x - vertex1.x; + vector2[1] = vertex3.y - vertex1.y; + vector2[2] = vertex3.z - vertex1.z; + + // Calculate the tu and tv texture space vectors. + tuVector[0] = vertex2.tu - vertex1.tu; + tvVector[0] = vertex2.tv - vertex1.tv; + + tuVector[1] = vertex3.tu - vertex1.tu; + tvVector[1] = vertex3.tv - vertex1.tv; + + // Calculate the denominator of the tangent/binormal equation. + den = 1.0f / (tuVector[0] * tvVector[1] - tuVector[1] * tvVector[0]); + + // Calculate the cross products and multiply by the coefficient to get the tangent and binormal. + tangent.x = (tvVector[1] * vector1[0] - tvVector[0] * vector2[0]) * den; + tangent.y = (tvVector[1] * vector1[1] - tvVector[0] * vector2[1]) * den; + tangent.z = (tvVector[1] * vector1[2] - tvVector[0] * vector2[2]) * den; + + binormal.x = (tuVector[0] * vector2[0] - tuVector[1] * vector1[0]) * den; + binormal.y = (tuVector[0] * vector2[1] - tuVector[1] * vector1[1]) * den; + binormal.z = (tuVector[0] * vector2[2] - tuVector[1] * vector1[2]) * den; + + // Calculate the length of this normal. + length = sqrt((tangent.x * tangent.x) + (tangent.y * tangent.y) + (tangent.z * tangent.z)); + + // Normalize the normal and then store it + tangent.x = tangent.x / length; + tangent.y = tangent.y / length; + tangent.z = tangent.z / length; + + // Calculate the length of this normal. + length = sqrt((binormal.x * binormal.x) + (binormal.y * binormal.y) + (binormal.z * binormal.z)); + + // Normalize the normal and then store it + binormal.x = binormal.x / length; + binormal.y = binormal.y / length; + binormal.z = binormal.z / length; + + return; +} + void ModelClass::ReleaseModel() { if (m_model) diff --git a/enginecustom/modelclass.h b/enginecustom/modelclass.h index 9ae525d..70eed55 100644 --- a/enginecustom/modelclass.h +++ b/enginecustom/modelclass.h @@ -32,6 +32,8 @@ protected: XMFLOAT3 position; XMFLOAT2 texture; XMFLOAT3 normal; + XMFLOAT3 tangent; + XMFLOAT3 binormal; }; struct ModelType @@ -39,6 +41,8 @@ protected: float x, y, z; float tu, tv; float nx, ny, nz; + float tx, ty, tz; + float bx, by, bz; }; struct Vertex { @@ -53,6 +57,18 @@ protected: float nx, ny, nz; }; + struct TempVertexType + { + float x, y, z; + float tu, tv; + float nx, ny, nz; + }; + + struct VectorType + { + float x, y, z; + }; + struct Face { int v1, v2, v3; int t1, t2, t3; @@ -64,7 +80,7 @@ public: ModelClass(const ModelClass&); ~ModelClass(); - bool Initialize(ID3D11Device*, ID3D11DeviceContext*, char*, char*, char*); + bool Initialize(ID3D11Device*, ID3D11DeviceContext*, char*, char*, char*, char*); void Shutdown(); void Render(ID3D11DeviceContext*); @@ -75,12 +91,15 @@ private: bool InitializeBuffers(ID3D11Device*); void ShutdownBuffers(); void RenderBuffers(ID3D11DeviceContext*); - bool LoadTextures(ID3D11Device*, ID3D11DeviceContext*, char*, char*); + bool LoadTextures(ID3D11Device*, ID3D11DeviceContext*, char*, char*, char*); void ReleaseTextures(); bool LoadModel(char*); void ReleaseModel(); + void CalculateModelVectors(); + void CalculateTangentBinormal(TempVertexType, TempVertexType, TempVertexType, VectorType&, VectorType&); + private: ID3D11Buffer* m_vertexBuffer, * m_indexBuffer; int m_vertexCount, m_indexCount; diff --git a/enginecustom/normal01.tga b/enginecustom/normal01.tga new file mode 100644 index 0000000..dbcd466 Binary files /dev/null and b/enginecustom/normal01.tga differ diff --git a/enginecustom/normalmap.ps b/enginecustom/normalmap.ps new file mode 100644 index 0000000..1b6ecc3 --- /dev/null +++ b/enginecustom/normalmap.ps @@ -0,0 +1,71 @@ +///////////// +// GLOBALS // +///////////// + +Texture2D shaderTexture1 : register(t0); +Texture2D shaderTexture2 : register(t1); +SamplerState SampleType : register(s0); + +cbuffer LightBuffer +{ + float4 diffuseColor; + float3 lightDirection; + float padding; +}; + + +////////////// +// TYPEDEFS // +////////////// + +struct PixelInputType +{ + float4 position : SV_POSITION; + float2 tex : TEXCOORD0; + float3 normal : NORMAL; + float3 tangent : TANGENT; + float3 binormal : BINORMAL; +}; + +//////////////////////////////////////////////////////////////////////////////// +// Pixel Shader +//////////////////////////////////////////////////////////////////////////////// +float4 NormalMapPixelShader(PixelInputType input) : SV_TARGET +{ + float4 textureColor; + float4 bumpMap; + float3 bumpNormal; + float3 lightDir; + float lightIntensity; + float4 color; + + + // Sample the pixel color from the color texture at this location. + textureColor = shaderTexture1.Sample(SampleType, input.tex); + + // Sample the pixel from the normal map. + bumpMap = shaderTexture2.Sample(SampleType, input.tex); + + // Expand the range of the normal value from (0, +1) to (-1, +1). + bumpMap = (bumpMap * 2.0f) - 1.0f; + + // Calculate the normal from the data in the normal map. + bumpNormal = (bumpMap.x * input.tangent) + (bumpMap.y * input.binormal) + (bumpMap.z * input.normal); + + // Normalize the resulting bump normal. + bumpNormal = normalize(bumpNormal); + + // Invert the light direction for calculations. + lightDir = -lightDirection; + + // Calculate the amount of light on this pixel based on the normal map value. + lightIntensity = saturate(dot(bumpNormal, lightDir)); + + // Determine the final amount of diffuse color based on the diffuse color combined with the light intensity. + color = saturate(diffuseColor * lightIntensity); + + // Combine the final light color with the texture color. + color = color * textureColor; + + return color; +} \ No newline at end of file diff --git a/enginecustom/normalmap.vs b/enginecustom/normalmap.vs new file mode 100644 index 0000000..4a16cd2 --- /dev/null +++ b/enginecustom/normalmap.vs @@ -0,0 +1,65 @@ +///////////// +// GLOBALS // +///////////// +cbuffer MatrixBuffer +{ + matrix worldMatrix; + matrix viewMatrix; + matrix projectionMatrix; +}; + +////////////// +// TYPEDEFS // +////////////// +struct VertexInputType +{ + float4 position : POSITION; + float2 tex : TEXCOORD0; + float3 normal : NORMAL; + float3 tangent : TANGENT; + float3 binormal : BINORMAL; +}; + +struct PixelInputType +{ + float4 position : SV_POSITION; + float2 tex : TEXCOORD0; + float3 normal : NORMAL; + float3 tangent : TANGENT; + float3 binormal : BINORMAL; +}; + + +//////////////////////////////////////////////////////////////////////////////// +// Vertex Shader +//////////////////////////////////////////////////////////////////////////////// +PixelInputType NormalMapVertexShader(VertexInputType input) +{ + PixelInputType output; + + + // Change the position vector to be 4 units for proper matrix calculations. + input.position.w = 1.0f; + + // Calculate the position of the vertex against the world, view, and projection matrices. + output.position = mul(input.position, worldMatrix); + output.position = mul(output.position, viewMatrix); + output.position = mul(output.position, projectionMatrix); + + // Store the texture coordinates for the pixel shader. + output.tex = input.tex; + + // Calculate the normal vector against the world matrix only and then normalize the final value. + output.normal = mul(input.normal, (float3x3)worldMatrix); + output.normal = normalize(output.normal); + + // Calculate the tangent vector against the world matrix only and then normalize the final value. + output.tangent = mul(input.tangent, (float3x3)worldMatrix); + output.tangent = normalize(output.tangent); + + // Calculate the binormal vector against the world matrix only and then normalize the final value. + output.binormal = mul(input.binormal, (float3x3)worldMatrix); + output.binormal = normalize(output.binormal); + + return output; +} \ No newline at end of file diff --git a/enginecustom/normalmapshaderclass.cpp b/enginecustom/normalmapshaderclass.cpp new file mode 100644 index 0000000..dbd365c --- /dev/null +++ b/enginecustom/normalmapshaderclass.cpp @@ -0,0 +1,441 @@ +#include "normalmapshaderclass.h" + + +NormalMapShaderClass::NormalMapShaderClass() +{ + m_vertexShader = 0; + m_pixelShader = 0; + m_layout = 0; + m_matrixBuffer = 0; + m_sampleState = 0; + m_lightBuffer = 0; +} + + +NormalMapShaderClass::NormalMapShaderClass(const NormalMapShaderClass& other) +{ +} + + +NormalMapShaderClass::~NormalMapShaderClass() +{ +} + + +bool NormalMapShaderClass::Initialize(ID3D11Device* device, HWND hwnd) +{ + bool result; + wchar_t vsFilename[128]; + wchar_t psFilename[128]; + int error; + + // Set the filename of the vertex shader. + error = wcscpy_s(vsFilename, 128, L"normalmap.vs"); + if (error != 0) + { + return false; + } + + // Set the filename of the pixel shader. + error = wcscpy_s(psFilename, 128, L"normalmap.ps"); + if (error != 0) + { + return false; + } + + // Initialize the vertex and pixel shaders. + result = InitializeShader(device, hwnd, vsFilename, psFilename); + if (!result) + { + return false; + } + + return true; +} + + +void NormalMapShaderClass::Shutdown() +{ + // Shutdown the vertex and pixel shaders as well as the related objects. + ShutdownShader(); + + return; +} + +bool NormalMapShaderClass::Render(ID3D11DeviceContext* deviceContext, int indexCount, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix, + ID3D11ShaderResourceView* texture1, ID3D11ShaderResourceView* texture2, XMFLOAT3 lightDirection, XMFLOAT4 diffuseColor) +{ + bool result; + + + // Set the shader parameters that it will use for rendering. + result = SetShaderParameters(deviceContext, worldMatrix, viewMatrix, projectionMatrix, texture1, texture2, lightDirection, diffuseColor); + if (!result) + { + return false; + } + + // Now render the prepared buffers with the shader. + RenderShader(deviceContext, indexCount); + + return true; +} + + +bool NormalMapShaderClass::InitializeShader(ID3D11Device* device, HWND hwnd, WCHAR* vsFilename, WCHAR* psFilename) +{ + HRESULT result; + ID3D10Blob* errorMessage; + ID3D10Blob* vertexShaderBuffer; + ID3D10Blob* pixelShaderBuffer; + D3D11_INPUT_ELEMENT_DESC polygonLayout[5]; + unsigned int numElements; + D3D11_BUFFER_DESC matrixBufferDesc; + D3D11_SAMPLER_DESC samplerDesc; + D3D11_BUFFER_DESC lightBufferDesc; + + + // Initialize the pointers this function will use to null. + errorMessage = 0; + vertexShaderBuffer = 0; + pixelShaderBuffer = 0; + + // Compile the vertex shader code. + result = D3DCompileFromFile(vsFilename, NULL, NULL, "NormalMapVertexShader", "vs_5_0", D3D10_SHADER_ENABLE_STRICTNESS, 0, + &vertexShaderBuffer, &errorMessage); + if (FAILED(result)) + { + // If the shader failed to compile it should have writen something to the error message. + if (errorMessage) + { + OutputShaderErrorMessage(errorMessage, hwnd, vsFilename); + } + // If there was nothing in the error message then it simply could not find the shader file itself. + else + { + MessageBox(hwnd, vsFilename, L"Missing Shader File", MB_OK); + } + + return false; + } + + // Compile the pixel shader code. + result = D3DCompileFromFile(psFilename, NULL, NULL, "NormalMapPixelShader", "ps_5_0", D3D10_SHADER_ENABLE_STRICTNESS, 0, + &pixelShaderBuffer, &errorMessage); + if (FAILED(result)) + { + // If the shader failed to compile it should have writen something to the error message. + if (errorMessage) + { + OutputShaderErrorMessage(errorMessage, hwnd, psFilename); + } + // If there was nothing in the error message then it simply could not find the file itself. + else + { + MessageBox(hwnd, psFilename, L"Missing Shader File", MB_OK); + } + + return false; + } + + // Create the vertex shader from the buffer. + result = device->CreateVertexShader(vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), NULL, &m_vertexShader); + if (FAILED(result)) + { + return false; + } + + // Create the pixel shader from the buffer. + result = device->CreatePixelShader(pixelShaderBuffer->GetBufferPointer(), pixelShaderBuffer->GetBufferSize(), NULL, &m_pixelShader); + if (FAILED(result)) + { + return false; + } + + // Create the vertex input layout description. + polygonLayout[0].SemanticName = "POSITION"; + polygonLayout[0].SemanticIndex = 0; + polygonLayout[0].Format = DXGI_FORMAT_R32G32B32_FLOAT; + polygonLayout[0].InputSlot = 0; + polygonLayout[0].AlignedByteOffset = 0; + polygonLayout[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + polygonLayout[0].InstanceDataStepRate = 0; + + polygonLayout[1].SemanticName = "TEXCOORD"; + polygonLayout[1].SemanticIndex = 0; + polygonLayout[1].Format = DXGI_FORMAT_R32G32_FLOAT; + polygonLayout[1].InputSlot = 0; + polygonLayout[1].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT; + polygonLayout[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + polygonLayout[1].InstanceDataStepRate = 0; + + polygonLayout[2].SemanticName = "NORMAL"; + polygonLayout[2].SemanticIndex = 0; + polygonLayout[2].Format = DXGI_FORMAT_R32G32B32_FLOAT; + polygonLayout[2].InputSlot = 0; + polygonLayout[2].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT; + polygonLayout[2].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + polygonLayout[2].InstanceDataStepRate = 0; + + polygonLayout[3].SemanticName = "TANGENT"; + polygonLayout[3].SemanticIndex = 0; + polygonLayout[3].Format = DXGI_FORMAT_R32G32B32_FLOAT; + polygonLayout[3].InputSlot = 0; + polygonLayout[3].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT; + polygonLayout[3].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + polygonLayout[3].InstanceDataStepRate = 0; + + polygonLayout[4].SemanticName = "BINORMAL"; + polygonLayout[4].SemanticIndex = 0; + polygonLayout[4].Format = DXGI_FORMAT_R32G32B32_FLOAT; + polygonLayout[4].InputSlot = 0; + polygonLayout[4].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT; + polygonLayout[4].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + polygonLayout[4].InstanceDataStepRate = 0; + + // Get a count of the elements in the layout. + numElements = sizeof(polygonLayout) / sizeof(polygonLayout[0]); + + // Create the vertex input layout. + result = device->CreateInputLayout(polygonLayout, numElements, vertexShaderBuffer->GetBufferPointer(), + vertexShaderBuffer->GetBufferSize(), &m_layout); + if (FAILED(result)) + { + return false; + } + + // Release the vertex shader buffer and pixel shader buffer since they are no longer needed. + vertexShaderBuffer->Release(); + vertexShaderBuffer = 0; + + pixelShaderBuffer->Release(); + pixelShaderBuffer = 0; + + // Setup the description of the dynamic matrix constant buffer that is in the vertex shader. + matrixBufferDesc.Usage = D3D11_USAGE_DYNAMIC; + matrixBufferDesc.ByteWidth = sizeof(MatrixBufferType); + matrixBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + matrixBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + matrixBufferDesc.MiscFlags = 0; + matrixBufferDesc.StructureByteStride = 0; + + // Create the constant buffer pointer so we can access the vertex shader constant buffer from within this class. + result = device->CreateBuffer(&matrixBufferDesc, NULL, &m_matrixBuffer); + if (FAILED(result)) + { + return false; + } + + // Create a texture sampler state description. + samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + samplerDesc.MipLODBias = 0.0f; + samplerDesc.MaxAnisotropy = 1; + samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + samplerDesc.BorderColor[0] = 0; + samplerDesc.BorderColor[1] = 0; + samplerDesc.BorderColor[2] = 0; + samplerDesc.BorderColor[3] = 0; + samplerDesc.MinLOD = 0; + samplerDesc.MaxLOD = D3D11_FLOAT32_MAX; + + // Create the texture sampler state. + result = device->CreateSamplerState(&samplerDesc, &m_sampleState); + if (FAILED(result)) + { + return false; + } + + // Setup the description of the light dynamic constant buffer that is in the pixel shader. + lightBufferDesc.Usage = D3D11_USAGE_DYNAMIC; + lightBufferDesc.ByteWidth = sizeof(LightBufferType); + lightBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + lightBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + lightBufferDesc.MiscFlags = 0; + lightBufferDesc.StructureByteStride = 0; + + // Create the constant buffer pointer so we can access the vertex shader constant buffer from within this class. + result = device->CreateBuffer(&lightBufferDesc, NULL, &m_lightBuffer); + if (FAILED(result)) + { + return false; + } + + return true; +} + + +void NormalMapShaderClass::ShutdownShader() +{ + // Release the light constant buffer. + if (m_lightBuffer) + { + m_lightBuffer->Release(); + m_lightBuffer = 0; + } + + // Release the sampler state. + if (m_sampleState) + { + m_sampleState->Release(); + m_sampleState = 0; + } + + // Release the matrix constant buffer. + if (m_matrixBuffer) + { + m_matrixBuffer->Release(); + m_matrixBuffer = 0; + } + + // Release the layout. + if (m_layout) + { + m_layout->Release(); + m_layout = 0; + } + + // Release the pixel shader. + if (m_pixelShader) + { + m_pixelShader->Release(); + m_pixelShader = 0; + } + + // Release the vertex shader. + if (m_vertexShader) + { + m_vertexShader->Release(); + m_vertexShader = 0; + } + + return; +} + + +void NormalMapShaderClass::OutputShaderErrorMessage(ID3D10Blob* errorMessage, HWND hwnd, WCHAR* shaderFilename) +{ + char* compileErrors; + unsigned long long bufferSize, i; + ofstream fout; + + + // Get a pointer to the error message text buffer. + compileErrors = (char*)(errorMessage->GetBufferPointer()); + + // Get the length of the message. + bufferSize = errorMessage->GetBufferSize(); + + // Open a file to write the error message to. + fout.open("shader-error.txt"); + + // Write out the error message. + for (i = 0; i < bufferSize; i++) + { + fout << compileErrors[i]; + } + + // Close the file. + fout.close(); + + // Release the error message. + errorMessage->Release(); + errorMessage = 0; + + // Pop a message up on the screen to notify the user to check the text file for compile errors. + MessageBox(hwnd, L"Error compiling shader. Check shader-error.txt for message.", shaderFilename, MB_OK); + + return; +} + + +bool NormalMapShaderClass::SetShaderParameters(ID3D11DeviceContext* deviceContext, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix, + ID3D11ShaderResourceView* texture1, ID3D11ShaderResourceView* texture2, XMFLOAT3 lightDirection, XMFLOAT4 diffuseColor) +{ + HRESULT result; + D3D11_MAPPED_SUBRESOURCE mappedResource; + MatrixBufferType* dataPtr; + unsigned int bufferNumber; + LightBufferType* dataPtr2; + + + // Transpose the matrices to prepare them for the shader. + worldMatrix = XMMatrixTranspose(worldMatrix); + viewMatrix = XMMatrixTranspose(viewMatrix); + projectionMatrix = XMMatrixTranspose(projectionMatrix); + + // Lock the constant buffer so it can be written to. + result = deviceContext->Map(m_matrixBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + return false; + } + + // Get a pointer to the data in the constant buffer. + dataPtr = (MatrixBufferType*)mappedResource.pData; + + // Copy the matrices into the constant buffer. + dataPtr->world = worldMatrix; + dataPtr->view = viewMatrix; + dataPtr->projection = projectionMatrix; + + // Unlock the constant buffer. + deviceContext->Unmap(m_matrixBuffer, 0); + + // Set the position of the constant buffer in the vertex shader. + bufferNumber = 0; + + // Finally set the constant buffer in the vertex shader with the updated values. + deviceContext->VSSetConstantBuffers(bufferNumber, 1, &m_matrixBuffer); + + // Set shader texture resources in the pixel shader. + deviceContext->PSSetShaderResources(0, 1, &texture1); + deviceContext->PSSetShaderResources(1, 1, &texture2); + + // Lock the light constant buffer so it can be written to. + result = deviceContext->Map(m_lightBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + return false; + } + + // Get a pointer to the data in the constant buffer. + dataPtr2 = (LightBufferType*)mappedResource.pData; + + // Copy the lighting variables into the constant buffer. + dataPtr2->diffuseColor = diffuseColor; + dataPtr2->lightDirection = lightDirection; + dataPtr2->padding = 0.0f; + + // Unlock the constant buffer. + deviceContext->Unmap(m_lightBuffer, 0); + + // Set the position of the light constant buffer in the pixel shader. + bufferNumber = 0; + + // Finally set the light constant buffer in the pixel shader with the updated values. + deviceContext->PSSetConstantBuffers(bufferNumber, 1, &m_lightBuffer); + + return true; +} + + +void NormalMapShaderClass::RenderShader(ID3D11DeviceContext* deviceContext, int indexCount) +{ + // Set the vertex input layout. + deviceContext->IASetInputLayout(m_layout); + + // Set the vertex and pixel shaders that will be used to render this triangle. + deviceContext->VSSetShader(m_vertexShader, NULL, 0); + deviceContext->PSSetShader(m_pixelShader, NULL, 0); + + // Set the sampler state in the pixel shader. + deviceContext->PSSetSamplers(0, 1, &m_sampleState); + + // Render the triangle. + deviceContext->DrawIndexed(indexCount, 0, 0); + + return; +} \ No newline at end of file diff --git a/enginecustom/normalmapshaderclass.h b/enginecustom/normalmapshaderclass.h new file mode 100644 index 0000000..76dec19 --- /dev/null +++ b/enginecustom/normalmapshaderclass.h @@ -0,0 +1,62 @@ +#ifndef _NORMALMAPSHADERCLASS_H_ +#define _NORMALMAPSHADERCLASS_H_ + + +////////////// +// INCLUDES // +////////////// +#include +#include +#include +#include +using namespace DirectX; +using namespace std; + + +//////////////////////////////////////////////////////////////////////////////// +// Class name: NormalMapShaderClass +//////////////////////////////////////////////////////////////////////////////// +class NormalMapShaderClass +{ +private: + struct MatrixBufferType + { + XMMATRIX world; + XMMATRIX view; + XMMATRIX projection; + }; + + struct LightBufferType + { + XMFLOAT4 diffuseColor; + XMFLOAT3 lightDirection; + float padding; + }; + +public: + NormalMapShaderClass(); + NormalMapShaderClass(const NormalMapShaderClass&); + ~NormalMapShaderClass(); + + bool Initialize(ID3D11Device*, HWND); + void Shutdown(); + bool Render(ID3D11DeviceContext*, int, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, ID3D11ShaderResourceView*, XMFLOAT3, XMFLOAT4); + +private: + bool InitializeShader(ID3D11Device*, HWND, WCHAR*, WCHAR*); + void ShutdownShader(); + void OutputShaderErrorMessage(ID3D10Blob*, HWND, WCHAR*); + + bool SetShaderParameters(ID3D11DeviceContext*, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, ID3D11ShaderResourceView*, XMFLOAT3, XMFLOAT4); + void RenderShader(ID3D11DeviceContext*, int); + +private: + ID3D11VertexShader* m_vertexShader; + ID3D11PixelShader* m_pixelShader; + ID3D11InputLayout* m_layout; + ID3D11Buffer* m_matrixBuffer; + ID3D11SamplerState* m_sampleState; + ID3D11Buffer* m_lightBuffer; +}; + +#endif \ No newline at end of file diff --git a/enginecustom/rendertextureclass.cpp b/enginecustom/rendertextureclass.cpp new file mode 100644 index 0000000..d4435a8 --- /dev/null +++ b/enginecustom/rendertextureclass.cpp @@ -0,0 +1,248 @@ +#include "rendertextureclass.h" + +RenderTextureClass::RenderTextureClass() +{ + m_renderTargetTexture = 0; + m_renderTargetView = 0; + m_shaderResourceView = 0; + m_depthStencilBuffer = 0; + m_depthStencilView = 0; +} + + +RenderTextureClass::RenderTextureClass(const RenderTextureClass& other) +{ +} + + +RenderTextureClass::~RenderTextureClass() +{ +} + +bool RenderTextureClass::Initialize(ID3D11Device * device, int textureWidth, int textureHeight, float screenDepth, float screenNear, int format) +{ + D3D11_TEXTURE2D_DESC textureDesc; + HRESULT result; + D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc; + D3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc; + D3D11_TEXTURE2D_DESC depthBufferDesc; + D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc; + DXGI_FORMAT textureFormat; + + + // Set the texture format. + switch (format) + { + case 1: + { + textureFormat = DXGI_FORMAT_R8G8B8A8_UNORM; + break; + } + default: + { + textureFormat = DXGI_FORMAT_R8G8B8A8_UNORM; + break; + } + } + + // Store the width and height of the render texture. + m_textureWidth = textureWidth; + m_textureHeight = textureHeight; + + // Initialize the render target texture description. + ZeroMemory(&textureDesc, sizeof(textureDesc)); + + // Setup the render target texture description. + textureDesc.Width = textureWidth; + textureDesc.Height = textureHeight; + textureDesc.MipLevels = 1; + textureDesc.ArraySize = 1; + textureDesc.Format = textureFormat; + textureDesc.SampleDesc.Count = 1; + textureDesc.Usage = D3D11_USAGE_DEFAULT; + textureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; + textureDesc.CPUAccessFlags = 0; + textureDesc.MiscFlags = 0; + + // Create the render target texture. + result = device->CreateTexture2D(&textureDesc, NULL, &m_renderTargetTexture); + if (FAILED(result)) + { + return false; + } + + // Setup the description of the render target view. + renderTargetViewDesc.Format = textureDesc.Format; + renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + renderTargetViewDesc.Texture2D.MipSlice = 0; + + // Create the render target view. + result = device->CreateRenderTargetView(m_renderTargetTexture, &renderTargetViewDesc, &m_renderTargetView); + if (FAILED(result)) + { + return false; + } + + // Setup the description of the shader resource view. + shaderResourceViewDesc.Format = textureDesc.Format; + shaderResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + shaderResourceViewDesc.Texture2D.MostDetailedMip = 0; + shaderResourceViewDesc.Texture2D.MipLevels = 1; + + // Create the shader resource view. + result = device->CreateShaderResourceView(m_renderTargetTexture, &shaderResourceViewDesc, &m_shaderResourceView); + if (FAILED(result)) + { + return false; + } + + // Initialize the description of the depth buffer. + ZeroMemory(&depthBufferDesc, sizeof(depthBufferDesc)); + + // Set up the description of the depth buffer. + depthBufferDesc.Width = textureWidth; + depthBufferDesc.Height = textureHeight; + depthBufferDesc.MipLevels = 1; + depthBufferDesc.ArraySize = 1; + depthBufferDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; + depthBufferDesc.SampleDesc.Count = 1; + depthBufferDesc.SampleDesc.Quality = 0; + depthBufferDesc.Usage = D3D11_USAGE_DEFAULT; + depthBufferDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; + depthBufferDesc.CPUAccessFlags = 0; + depthBufferDesc.MiscFlags = 0; + + // Create the texture for the depth buffer using the filled out description. + result = device->CreateTexture2D(&depthBufferDesc, NULL, &m_depthStencilBuffer); + if (FAILED(result)) + { + return false; + } + + // Initailze the depth stencil view description. + ZeroMemory(&depthStencilViewDesc, sizeof(depthStencilViewDesc)); + + // Set up the depth stencil view description. + depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; + depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; + depthStencilViewDesc.Texture2D.MipSlice = 0; + + // Create the depth stencil view. + result = device->CreateDepthStencilView(m_depthStencilBuffer, &depthStencilViewDesc, &m_depthStencilView); + if (FAILED(result)) + { + return false; + } + + // Setup the viewport for rendering. + m_viewport.Width = (float)textureWidth; + m_viewport.Height = (float)textureHeight; + m_viewport.MinDepth = 0.0f; + m_viewport.MaxDepth = 1.0f; + m_viewport.TopLeftX = 0; + m_viewport.TopLeftY = 0; + + // Setup the projection matrix. + m_projectionMatrix = XMMatrixPerspectiveFovLH((3.141592654f / 4.0f), ((float)textureWidth / (float)textureHeight), screenNear, screenDepth); + + // Create an orthographic projection matrix for 2D rendering. + m_orthoMatrix = XMMatrixOrthographicLH((float)textureWidth, (float)textureHeight, screenNear, screenDepth); + + return true; +} + +void RenderTextureClass::Shutdown() +{ + if (m_depthStencilView) + { + m_depthStencilView->Release(); + m_depthStencilView = 0; + } + + if (m_depthStencilBuffer) + { + m_depthStencilBuffer->Release(); + m_depthStencilBuffer = 0; + } + + if (m_shaderResourceView) + { + m_shaderResourceView->Release(); + m_shaderResourceView = 0; + } + + if (m_renderTargetView) + { + m_renderTargetView->Release(); + m_renderTargetView = 0; + } + + if (m_renderTargetTexture) + { + m_renderTargetTexture->Release(); + m_renderTargetTexture = 0; + } + + return; +} + +void RenderTextureClass::SetRenderTarget(ID3D11DeviceContext * deviceContext) +{ + // Bind the render target view and depth stencil buffer to the output render pipeline. + deviceContext->OMSetRenderTargets(1, &m_renderTargetView, m_depthStencilView); + + // Set the viewport. + deviceContext->RSSetViewports(1, &m_viewport); + + return; +} + +void RenderTextureClass::ClearRenderTarget(ID3D11DeviceContext * deviceContext, float red, float green, float blue, float alpha) +{ + float color[4]; + + + // Setup the color to clear the buffer to. + color[0] = red; + color[1] = green; + color[2] = blue; + color[3] = alpha; + + // Clear the back buffer. + deviceContext->ClearRenderTargetView(m_renderTargetView, color); + + // Clear the depth buffer. + deviceContext->ClearDepthStencilView(m_depthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0); + + return; +} + +ID3D11ShaderResourceView* RenderTextureClass::GetShaderResourceView() +{ + return m_shaderResourceView; +} + +void RenderTextureClass::GetProjectionMatrix(XMMATRIX & projectionMatrix) +{ + projectionMatrix = m_projectionMatrix; + return; +} + + +void RenderTextureClass::GetOrthoMatrix(XMMATRIX & orthoMatrix) +{ + orthoMatrix = m_orthoMatrix; + return; +} + + +int RenderTextureClass::GetTextureWidth() +{ + return m_textureWidth; +} + + +int RenderTextureClass::GetTextureHeight() +{ + return m_textureHeight; +} \ No newline at end of file diff --git a/enginecustom/rendertextureclass.h b/enginecustom/rendertextureclass.h new file mode 100644 index 0000000..ef06537 --- /dev/null +++ b/enginecustom/rendertextureclass.h @@ -0,0 +1,51 @@ +//////////////////////////////////////////////////////////////////////////////// +// Filename: rendertextureclass.h +//////////////////////////////////////////////////////////////////////////////// +#ifndef _RENDERTEXTURECLASS_H_ +#define _RENDERTEXTURECLASS_H_ + + +////////////// +// INCLUDES // +////////////// +#include +#include +using namespace DirectX; + + +//////////////////////////////////////////////////////////////////////////////// +// Class name: RenderTextureClass +//////////////////////////////////////////////////////////////////////////////// +class RenderTextureClass +{ +public: + RenderTextureClass(); + RenderTextureClass(const RenderTextureClass&); + ~RenderTextureClass(); + + bool Initialize(ID3D11Device*, int, int, float, float, int); + void Shutdown(); + + void SetRenderTarget(ID3D11DeviceContext*); + void ClearRenderTarget(ID3D11DeviceContext*, float, float, float, float); + ID3D11ShaderResourceView* GetShaderResourceView(); + + void GetProjectionMatrix(XMMATRIX&); + void GetOrthoMatrix(XMMATRIX&); + + int GetTextureWidth(); + int GetTextureHeight(); + +private: + int m_textureWidth, m_textureHeight; + ID3D11Texture2D* m_renderTargetTexture; + ID3D11RenderTargetView* m_renderTargetView; + ID3D11ShaderResourceView* m_shaderResourceView; + ID3D11Texture2D* m_depthStencilBuffer; + ID3D11DepthStencilView* m_depthStencilView; + D3D11_VIEWPORT m_viewport; + XMMATRIX m_projectionMatrix; + XMMATRIX m_orthoMatrix; +}; + +#endif diff --git a/enginecustom/specmap.ps b/enginecustom/specmap.ps new file mode 100644 index 0000000..7e49723 --- /dev/null +++ b/enginecustom/specmap.ps @@ -0,0 +1,93 @@ +///////////// +// GLOBALS // +///////////// + +Texture2D shaderTexture1 : register(t0); +Texture2D shaderTexture2 : register(t1); +Texture2D shaderTexture3 : register(t2); +SamplerState SampleType : register(s0); + +cbuffer LightBuffer +{ + float4 diffuseColor; + float4 specularColor; + float specularPower; + float3 lightDirection; +}; + +////////////// +// TYPEDEFS // +////////////// +struct PixelInputType +{ + float4 position : SV_POSITION; + float2 tex : TEXCOORD0; + float3 normal : NORMAL; + float3 tangent : TANGENT; + float3 binormal : BINORMAL; + float3 viewDirection : TEXCOORD1; +}; + + +//////////////////////////////////////////////////////////////////////////////// +// Pixel Shader +//////////////////////////////////////////////////////////////////////////////// +float4 SpecMapPixelShader(PixelInputType input) : SV_TARGET +{ + float4 textureColor; + float4 bumpMap; + float3 bumpNormal; + float3 lightDir; + float lightIntensity; + float4 color; + float4 specularIntensity; + float3 reflection; + float4 specular; + + // Sample the pixel color from the color texture at this location. + textureColor = shaderTexture1.Sample(SampleType, input.tex); + + // Sample the pixel from the normal map. + bumpMap = shaderTexture2.Sample(SampleType, input.tex); + + // Expand the range of the normal value from (0, +1) to (-1, +1). + bumpMap = (bumpMap * 2.0f) - 1.0f; + + // Calculate the normal from the data in the normal map. + bumpNormal = (bumpMap.x * input.tangent) + (bumpMap.y * input.binormal) + (bumpMap.z * input.normal); + + // Normalize the resulting bump normal. + bumpNormal = normalize(bumpNormal); + + // Invert the light direction for calculations. + lightDir = -lightDirection; + + // Calculate the amount of light on this pixel based on the normal map value. + lightIntensity = saturate(dot(bumpNormal, lightDir)); + + // Determine the final amount of diffuse color based on the diffuse color combined with the light intensity. + color = saturate(diffuseColor * lightIntensity); + + // Combine the final light color with the texture color. + color = color * textureColor; + + if(lightIntensity > 0.0f) + { + // Sample the pixel from the specular map texture. + specularIntensity = shaderTexture3.Sample(SampleType, input.tex); + + // Calculate the reflection vector based on the light intensity, normal vector, and light direction. + reflection = normalize(2 * lightIntensity * bumpNormal - lightDir); + + // Determine the amount of specular light based on the reflection vector, viewing direction, and specular power. + specular = pow(saturate(dot(reflection, input.viewDirection)), specularPower); + + // Use the specular map to determine the intensity of specular light at this pixel. + specular = specular * specularIntensity; + + // Add the specular component last to the output color. + color = saturate(color + specular); + } + + return color; +} \ No newline at end of file diff --git a/enginecustom/specmap.vs b/enginecustom/specmap.vs new file mode 100644 index 0000000..2983ab6 --- /dev/null +++ b/enginecustom/specmap.vs @@ -0,0 +1,83 @@ +///////////// +// GLOBALS // +///////////// +cbuffer MatrixBuffer +{ + matrix worldMatrix; + matrix viewMatrix; + matrix projectionMatrix; +}; + +cbuffer CameraBuffer +{ + float3 cameraPosition; + float padding; +}; + + +////////////// +// TYPEDEFS // +////////////// +struct VertexInputType +{ + float4 position : POSITION; + float2 tex : TEXCOORD0; + float3 normal : NORMAL; + float3 tangent : TANGENT; + float3 binormal : BINORMAL; +}; + +struct PixelInputType +{ + float4 position : SV_POSITION; + float2 tex : TEXCOORD0; + float3 normal : NORMAL; + float3 tangent : TANGENT; + float3 binormal : BINORMAL; + float3 viewDirection : TEXCOORD1; +}; + + +//////////////////////////////////////////////////////////////////////////////// +// Vertex Shader +//////////////////////////////////////////////////////////////////////////////// +PixelInputType SpecMapVertexShader(VertexInputType input) +{ + PixelInputType output; + float4 worldPosition; + + + // Change the position vector to be 4 units for proper matrix calculations. + input.position.w = 1.0f; + + // Calculate the position of the vertex against the world, view, and projection matrices. + output.position = mul(input.position, worldMatrix); + output.position = mul(output.position, viewMatrix); + output.position = mul(output.position, projectionMatrix); + + // Store the texture coordinates for the pixel shader. + output.tex = input.tex; + + // Calculate the normal vector against the world matrix only and then normalize the final value. + output.normal = mul(input.normal, (float3x3)worldMatrix); + output.normal = normalize(output.normal); + + // Calculate the tangent vector against the world matrix only and then normalize the final value. + output.tangent = mul(input.tangent, (float3x3)worldMatrix); + output.tangent = normalize(output.tangent); + + // Calculate the binormal vector against the world matrix only and then normalize the final value. + output.binormal = mul(input.binormal, (float3x3)worldMatrix); + output.binormal = normalize(output.binormal); + + // Calculate the position of the vertex in the world. + worldPosition = mul(input.position, worldMatrix); + + // Determine the viewing direction based on the position of the camera and the position of the vertex in the world. + output.viewDirection = cameraPosition.xyz - worldPosition.xyz; + + // Normalize the viewing direction vector. + output.viewDirection = normalize(output.viewDirection); + + return output; +} diff --git a/enginecustom/specmapshaderclass.cpp b/enginecustom/specmapshaderclass.cpp new file mode 100644 index 0000000..0d1ff07 --- /dev/null +++ b/enginecustom/specmapshaderclass.cpp @@ -0,0 +1,492 @@ +#include "specmapshaderclass.h" + + +SpecMapShaderClass::SpecMapShaderClass() +{ + m_vertexShader = 0; + m_pixelShader = 0; + m_layout = 0; + m_matrixBuffer = 0; + m_sampleState = 0; + m_lightBuffer = 0; + m_cameraBuffer = 0; +} + + +SpecMapShaderClass::SpecMapShaderClass(const SpecMapShaderClass& other) +{ +} + + +SpecMapShaderClass::~SpecMapShaderClass() +{ +} + + +bool SpecMapShaderClass::Initialize(ID3D11Device* device, HWND hwnd) +{ + bool result; + wchar_t vsFilename[128]; + wchar_t psFilename[128]; + int error; + + // Set the filename of the vertex shader. + error = wcscpy_s(vsFilename, 128, L"specmap.vs"); + if (error != 0) + { + return false; + } + + // Set the filename of the pixel shader. + error = wcscpy_s(psFilename, 128, L"specmap.ps"); + if (error != 0) + { + return false; + } + + // Initialize the vertex and pixel shaders. + result = InitializeShader(device, hwnd, vsFilename, psFilename); + if (!result) + { + return false; + } + + return true; +} + + +void SpecMapShaderClass::Shutdown() +{ + // Shutdown the vertex and pixel shaders as well as the related objects. + ShutdownShader(); + + return; +} + +bool SpecMapShaderClass::Render(ID3D11DeviceContext* deviceContext, int indexCount, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix, + ID3D11ShaderResourceView* texture1, ID3D11ShaderResourceView* texture2, ID3D11ShaderResourceView* texture3, + XMFLOAT3 lightDirection, XMFLOAT4 diffuseColor, XMFLOAT3 cameraPosition, XMFLOAT4 specularColor, float specularPower) +{ + bool result; + + + // Set the shader parameters that it will use for rendering. + result = SetShaderParameters(deviceContext, worldMatrix, viewMatrix, projectionMatrix, texture1, texture2, texture3, lightDirection, diffuseColor, + cameraPosition, specularColor, specularPower); + if (!result) + { + return false; + } + + // Now render the prepared buffers with the shader. + RenderShader(deviceContext, indexCount); + + return true; +} + + +bool SpecMapShaderClass::InitializeShader(ID3D11Device* device, HWND hwnd, WCHAR* vsFilename, WCHAR* psFilename) +{ + HRESULT result; + ID3D10Blob* errorMessage; + ID3D10Blob* vertexShaderBuffer; + ID3D10Blob* pixelShaderBuffer; + D3D11_INPUT_ELEMENT_DESC polygonLayout[5]; + unsigned int numElements; + D3D11_BUFFER_DESC matrixBufferDesc; + D3D11_SAMPLER_DESC samplerDesc; + D3D11_BUFFER_DESC lightBufferDesc; + D3D11_BUFFER_DESC cameraBufferDesc; + + + // Initialize the pointers this function will use to null. + errorMessage = 0; + vertexShaderBuffer = 0; + pixelShaderBuffer = 0; + + // Compile the vertex shader code. + result = D3DCompileFromFile(vsFilename, NULL, NULL, "SpecMapVertexShader", "vs_5_0", D3D10_SHADER_ENABLE_STRICTNESS, 0, + &vertexShaderBuffer, &errorMessage); + if (FAILED(result)) + { + // If the shader failed to compile it should have writen something to the error message. + if (errorMessage) + { + OutputShaderErrorMessage(errorMessage, hwnd, vsFilename); + } + // If there was nothing in the error message then it simply could not find the shader file itself. + else + { + MessageBox(hwnd, vsFilename, L"Missing Shader File", MB_OK); + } + + return false; + } + + // Compile the pixel shader code. + result = D3DCompileFromFile(psFilename, NULL, NULL, "SpecMapPixelShader", "ps_5_0", D3D10_SHADER_ENABLE_STRICTNESS, 0, + &pixelShaderBuffer, &errorMessage); + if (FAILED(result)) + { + // If the shader failed to compile it should have writen something to the error message. + if (errorMessage) + { + OutputShaderErrorMessage(errorMessage, hwnd, psFilename); + } + // If there was nothing in the error message then it simply could not find the file itself. + else + { + MessageBox(hwnd, psFilename, L"Missing Shader File", MB_OK); + } + + return false; + } + + // Create the vertex shader from the buffer. + result = device->CreateVertexShader(vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), NULL, &m_vertexShader); + if (FAILED(result)) + { + return false; + } + + // Create the pixel shader from the buffer. + result = device->CreatePixelShader(pixelShaderBuffer->GetBufferPointer(), pixelShaderBuffer->GetBufferSize(), NULL, &m_pixelShader); + if (FAILED(result)) + { + return false; + } + + // Create the vertex input layout description. + polygonLayout[0].SemanticName = "POSITION"; + polygonLayout[0].SemanticIndex = 0; + polygonLayout[0].Format = DXGI_FORMAT_R32G32B32_FLOAT; + polygonLayout[0].InputSlot = 0; + polygonLayout[0].AlignedByteOffset = 0; + polygonLayout[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + polygonLayout[0].InstanceDataStepRate = 0; + + polygonLayout[1].SemanticName = "TEXCOORD"; + polygonLayout[1].SemanticIndex = 0; + polygonLayout[1].Format = DXGI_FORMAT_R32G32_FLOAT; + polygonLayout[1].InputSlot = 0; + polygonLayout[1].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT; + polygonLayout[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + polygonLayout[1].InstanceDataStepRate = 0; + + polygonLayout[2].SemanticName = "NORMAL"; + polygonLayout[2].SemanticIndex = 0; + polygonLayout[2].Format = DXGI_FORMAT_R32G32B32_FLOAT; + polygonLayout[2].InputSlot = 0; + polygonLayout[2].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT; + polygonLayout[2].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + polygonLayout[2].InstanceDataStepRate = 0; + + polygonLayout[3].SemanticName = "TANGENT"; + polygonLayout[3].SemanticIndex = 0; + polygonLayout[3].Format = DXGI_FORMAT_R32G32B32_FLOAT; + polygonLayout[3].InputSlot = 0; + polygonLayout[3].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT; + polygonLayout[3].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + polygonLayout[3].InstanceDataStepRate = 0; + + polygonLayout[4].SemanticName = "BINORMAL"; + polygonLayout[4].SemanticIndex = 0; + polygonLayout[4].Format = DXGI_FORMAT_R32G32B32_FLOAT; + polygonLayout[4].InputSlot = 0; + polygonLayout[4].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT; + polygonLayout[4].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + polygonLayout[4].InstanceDataStepRate = 0; + + // Get a count of the elements in the layout. + numElements = sizeof(polygonLayout) / sizeof(polygonLayout[0]); + + // Create the vertex input layout. + result = device->CreateInputLayout(polygonLayout, numElements, vertexShaderBuffer->GetBufferPointer(), + vertexShaderBuffer->GetBufferSize(), &m_layout); + if (FAILED(result)) + { + return false; + } + + // Release the vertex shader buffer and pixel shader buffer since they are no longer needed. + vertexShaderBuffer->Release(); + vertexShaderBuffer = 0; + + pixelShaderBuffer->Release(); + pixelShaderBuffer = 0; + + // Setup the description of the dynamic matrix constant buffer that is in the vertex shader. + matrixBufferDesc.Usage = D3D11_USAGE_DYNAMIC; + matrixBufferDesc.ByteWidth = sizeof(MatrixBufferType); + matrixBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + matrixBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + matrixBufferDesc.MiscFlags = 0; + matrixBufferDesc.StructureByteStride = 0; + + // Create the constant buffer pointer so we can access the vertex shader constant buffer from within this class. + result = device->CreateBuffer(&matrixBufferDesc, NULL, &m_matrixBuffer); + if (FAILED(result)) + { + return false; + } + + // Create a texture sampler state description. + samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + samplerDesc.MipLODBias = 0.0f; + samplerDesc.MaxAnisotropy = 1; + samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + samplerDesc.BorderColor[0] = 0; + samplerDesc.BorderColor[1] = 0; + samplerDesc.BorderColor[2] = 0; + samplerDesc.BorderColor[3] = 0; + samplerDesc.MinLOD = 0; + samplerDesc.MaxLOD = D3D11_FLOAT32_MAX; + + // Create the texture sampler state. + result = device->CreateSamplerState(&samplerDesc, &m_sampleState); + if (FAILED(result)) + { + return false; + } + + // Setup the description of the light dynamic constant buffer that is in the pixel shader. + lightBufferDesc.Usage = D3D11_USAGE_DYNAMIC; + lightBufferDesc.ByteWidth = sizeof(LightBufferType); + lightBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + lightBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + lightBufferDesc.MiscFlags = 0; + lightBufferDesc.StructureByteStride = 0; + + // Create the constant buffer pointer so we can access the vertex shader constant buffer from within this class. + result = device->CreateBuffer(&lightBufferDesc, NULL, &m_lightBuffer); + if (FAILED(result)) + { + return false; + } + + // Setup the description of the camera dynamic constant buffer that is in the vertex shader. + cameraBufferDesc.Usage = D3D11_USAGE_DYNAMIC; + cameraBufferDesc.ByteWidth = sizeof(CameraBufferType); + cameraBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + cameraBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + cameraBufferDesc.MiscFlags = 0; + cameraBufferDesc.StructureByteStride = 0; + + // Create the camera constant buffer pointer so we can access the vertex shader constant buffer from within this class. + result = device->CreateBuffer(&cameraBufferDesc, NULL, &m_cameraBuffer); + if (FAILED(result)) + { + return false; + } + + return true; +} + + +void SpecMapShaderClass::ShutdownShader() +{ + // Release the camera constant buffer. + if (m_cameraBuffer) + { + m_cameraBuffer->Release(); + m_cameraBuffer = 0; + } + + // Release the light constant buffer. + if (m_lightBuffer) + { + m_lightBuffer->Release(); + m_lightBuffer = 0; + } + + // Release the sampler state. + if (m_sampleState) + { + m_sampleState->Release(); + m_sampleState = 0; + } + + // Release the matrix constant buffer. + if (m_matrixBuffer) + { + m_matrixBuffer->Release(); + m_matrixBuffer = 0; + } + + // Release the layout. + if (m_layout) + { + m_layout->Release(); + m_layout = 0; + } + + // Release the pixel shader. + if (m_pixelShader) + { + m_pixelShader->Release(); + m_pixelShader = 0; + } + + // Release the vertex shader. + if (m_vertexShader) + { + m_vertexShader->Release(); + m_vertexShader = 0; + } + + return; +} + + +void SpecMapShaderClass::OutputShaderErrorMessage(ID3D10Blob* errorMessage, HWND hwnd, WCHAR* shaderFilename) +{ + char* compileErrors; + unsigned long long bufferSize, i; + ofstream fout; + + + // Get a pointer to the error message text buffer. + compileErrors = (char*)(errorMessage->GetBufferPointer()); + + // Get the length of the message. + bufferSize = errorMessage->GetBufferSize(); + + // Open a file to write the error message to. + fout.open("shader-error.txt"); + + // Write out the error message. + for (i = 0; i < bufferSize; i++) + { + fout << compileErrors[i]; + } + + // Close the file. + fout.close(); + + // Release the error message. + errorMessage->Release(); + errorMessage = 0; + + // Pop a message up on the screen to notify the user to check the text file for compile errors. + MessageBox(hwnd, L"Error compiling shader. Check shader-error.txt for message.", shaderFilename, MB_OK); + + return; +} + +bool SpecMapShaderClass::SetShaderParameters(ID3D11DeviceContext* deviceContext, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix, + ID3D11ShaderResourceView* texture1, ID3D11ShaderResourceView* texture2, ID3D11ShaderResourceView* texture3, + XMFLOAT3 lightDirection, XMFLOAT4 diffuseColor, XMFLOAT3 cameraPosition, XMFLOAT4 specularColor, float specularPower) +{ + HRESULT result; + D3D11_MAPPED_SUBRESOURCE mappedResource; + MatrixBufferType* dataPtr; + unsigned int bufferNumber; + LightBufferType* dataPtr2; + CameraBufferType* dataPtr3; + + + // Transpose the matrices to prepare them for the shader. + worldMatrix = XMMatrixTranspose(worldMatrix); + viewMatrix = XMMatrixTranspose(viewMatrix); + projectionMatrix = XMMatrixTranspose(projectionMatrix); + + // Lock the constant buffer so it can be written to. + result = deviceContext->Map(m_matrixBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + return false; + } + + // Get a pointer to the data in the constant buffer. + dataPtr = (MatrixBufferType*)mappedResource.pData; + + // Copy the matrices into the constant buffer. + dataPtr->world = worldMatrix; + dataPtr->view = viewMatrix; + dataPtr->projection = projectionMatrix; + + // Unlock the constant buffer. + deviceContext->Unmap(m_matrixBuffer, 0); + + // Set the position of the constant buffer in the vertex shader. + bufferNumber = 0; + + // Finally set the constant buffer in the vertex shader with the updated values. + deviceContext->VSSetConstantBuffers(bufferNumber, 1, &m_matrixBuffer); + + // Set shader texture resources in the pixel shader. + deviceContext->PSSetShaderResources(0, 1, &texture1); + deviceContext->PSSetShaderResources(1, 1, &texture2); + deviceContext->PSSetShaderResources(2, 1, &texture3); + + // Lock the light constant buffer so it can be written to. + result = deviceContext->Map(m_lightBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + return false; + } + + // Get a pointer to the data in the constant buffer. + dataPtr2 = (LightBufferType*)mappedResource.pData; + + // Copy the lighting variables into the constant buffer. + dataPtr2->diffuseColor = diffuseColor; + dataPtr2->lightDirection = lightDirection; + dataPtr2->specularColor = specularColor; + dataPtr2->specularPower = specularPower; + + // Unlock the constant buffer. + deviceContext->Unmap(m_lightBuffer, 0); + + // Set the position of the light constant buffer in the pixel shader. + bufferNumber = 0; + + // Finally set the light constant buffer in the pixel shader with the updated values. + deviceContext->PSSetConstantBuffers(bufferNumber, 1, &m_lightBuffer); + + // Lock the camera constant buffer so it can be written to. + result = deviceContext->Map(m_cameraBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + return false; + } + + // Get a pointer to the data in the constant buffer. + dataPtr3 = (CameraBufferType*)mappedResource.pData; + + // Copy the camera position into the constant buffer. + dataPtr3->cameraPosition = cameraPosition; + + // Unlock the camera constant buffer. + deviceContext->Unmap(m_cameraBuffer, 0); + + // Set the position of the camera constant buffer in the vertex shader as the second buffer. + bufferNumber = 1; + + // Now set the camera constant buffer in the vertex shader with the updated values. + deviceContext->VSSetConstantBuffers(bufferNumber, 1, &m_cameraBuffer); + + return true; +} + + +void SpecMapShaderClass::RenderShader(ID3D11DeviceContext* deviceContext, int indexCount) +{ + // Set the vertex input layout. + deviceContext->IASetInputLayout(m_layout); + + // Set the vertex and pixel shaders that will be used to render this model. + deviceContext->VSSetShader(m_vertexShader, NULL, 0); + deviceContext->PSSetShader(m_pixelShader, NULL, 0); + + // Set the sampler state in the pixel shader. + deviceContext->PSSetSamplers(0, 1, &m_sampleState); + + // Render the model. + deviceContext->DrawIndexed(indexCount, 0, 0); + + return; +} \ No newline at end of file diff --git a/enginecustom/specmapshaderclass.h b/enginecustom/specmapshaderclass.h new file mode 100644 index 0000000..e076c88 --- /dev/null +++ b/enginecustom/specmapshaderclass.h @@ -0,0 +1,72 @@ +#ifndef _SPECMAPSHADERCLASS_H_ +#define _SPECMAPSHADERCLASS_H_ + + +////////////// +// INCLUDES // +////////////// +#include +#include +#include +#include +using namespace DirectX; +using namespace std; + + +//////////////////////////////////////////////////////////////////////////////// +// Class name: SpecMapShaderClass +//////////////////////////////////////////////////////////////////////////////// +class SpecMapShaderClass +{ +private: + struct MatrixBufferType + { + XMMATRIX world; + XMMATRIX view; + XMMATRIX projection; + }; + + struct LightBufferType + { + XMFLOAT4 diffuseColor; + XMFLOAT4 specularColor; + float specularPower; + XMFLOAT3 lightDirection; + }; + + struct CameraBufferType + { + XMFLOAT3 cameraPosition; + float padding; + }; + +public: + SpecMapShaderClass(); + SpecMapShaderClass(const SpecMapShaderClass&); + ~SpecMapShaderClass(); + + bool Initialize(ID3D11Device*, HWND); + void Shutdown(); + bool Render(ID3D11DeviceContext*, int, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, ID3D11ShaderResourceView*, ID3D11ShaderResourceView*, + XMFLOAT3, XMFLOAT4, XMFLOAT3, XMFLOAT4, float); + +private: + bool InitializeShader(ID3D11Device*, HWND, WCHAR*, WCHAR*); + void ShutdownShader(); + void OutputShaderErrorMessage(ID3D10Blob*, HWND, WCHAR*); + + bool SetShaderParameters(ID3D11DeviceContext*, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, ID3D11ShaderResourceView*, ID3D11ShaderResourceView*, + XMFLOAT3, XMFLOAT4, XMFLOAT3, XMFLOAT4, float); + void RenderShader(ID3D11DeviceContext*, int); + +private: + ID3D11VertexShader* m_vertexShader; + ID3D11PixelShader* m_pixelShader; + ID3D11InputLayout* m_layout; + ID3D11Buffer* m_matrixBuffer; + ID3D11SamplerState* m_sampleState; + ID3D11Buffer* m_lightBuffer; + ID3D11Buffer* m_cameraBuffer; +}; + +#endif \ No newline at end of file diff --git a/enginecustom/square.txt b/enginecustom/square.txt new file mode 100644 index 0000000..ab9a113 --- /dev/null +++ b/enginecustom/square.txt @@ -0,0 +1,10 @@ +Vertex Count: 6 + +Data: + +-1.0 1.0 0.0 0.0 0.0 0.0 0.0 -1.0 + 1.0 1.0 0.0 1.0 0.0 0.0 0.0 -1.0 +-1.0 -1.0 0.0 0.0 1.0 0.0 0.0 -1.0 +-1.0 -1.0 0.0 0.0 1.0 0.0 0.0 -1.0 + 1.0 1.0 0.0 1.0 0.0 0.0 0.0 -1.0 + 1.0 -1.0 0.0 1.0 1.0 0.0 0.0 -1.0 diff --git a/enginecustom/systemclass.h b/enginecustom/systemclass.h index b699b63..0428e34 100644 --- a/enginecustom/systemclass.h +++ b/enginecustom/systemclass.h @@ -1,5 +1,6 @@ #ifndef _SYSTEMCLASS_H_ #define _SYSTEMCLASS_H_ + #define WIN32_LEAN_AND_MEAN #include "inputclass.h" diff --git a/enginecustom/textclass.h b/enginecustom/textclass.h index 643631a..c3acffa 100644 --- a/enginecustom/textclass.h +++ b/enginecustom/textclass.h @@ -45,4 +45,4 @@ private: XMFLOAT4 m_pixelColor; }; -#endif \ No newline at end of file +#endif diff --git a/enginecustom/translate.cpp b/enginecustom/translate.cpp new file mode 100644 index 0000000..7bf765c --- /dev/null +++ b/enginecustom/translate.cpp @@ -0,0 +1,18 @@ +#include "pch.h" +#include "Translate.h" +#if __has_include("Translate.g.cpp") +#include "Translate.g.cpp" +#endif + +namespace winrt::enginecustom::implementation +{ + int32_t Translate::MyProperty() + { + throw hresult_not_implemented(); + } + + void Translate::MyProperty(int32_t /*value*/) + { + throw hresult_not_implemented(); + } +} diff --git a/enginecustom/translate.h b/enginecustom/translate.h new file mode 100644 index 0000000..5e8a544 --- /dev/null +++ b/enginecustom/translate.h @@ -0,0 +1,21 @@ +#pragma once + +#include "Translate.g.h" + +namespace winrt::enginecustom::implementation +{ + struct Translate : TranslateT + { + Translate() = default; + + int32_t MyProperty(); + void MyProperty(int32_t value); + }; +} + +namespace winrt::enginecustom::factory_implementation +{ + struct Translate : TranslateT + { + }; +} diff --git a/enginecustom/translate.ps b/enginecustom/translate.ps new file mode 100644 index 0000000..51a964b --- /dev/null +++ b/enginecustom/translate.ps @@ -0,0 +1,37 @@ +///////////// +// GLOBALS // +///////////// +Texture2D shaderTexture : register(t0); +SamplerState SampleType : register(s0); + +cbuffer TranslationBuffer +{ + float textureTranslation; +}; + + +////////////// +// TYPEDEFS // +////////////// +struct PixelInputType +{ + float4 position : SV_POSITION; + float2 tex : TEXCOORD0; +}; + +//////////////////////////////////////////////////////////////////////////////// +// Pixel Shader +//////////////////////////////////////////////////////////////////////////////// +float4 TranslatePixelShader(PixelInputType input) : SV_TARGET +{ + float4 textureColor; + + + // Translate the position where we sample the pixel from. + input.tex.x += textureTranslation; + + // Sample the pixel color from the texture using the sampler at this texture coordinate location. + textureColor = shaderTexture.Sample(SampleType, input.tex); + + return textureColor; +} diff --git a/enginecustom/translate.vs b/enginecustom/translate.vs new file mode 100644 index 0000000..847ced0 --- /dev/null +++ b/enginecustom/translate.vs @@ -0,0 +1,48 @@ +///////////// +// GLOBALS // +///////////// +cbuffer MatrixBuffer +{ + matrix worldMatrix; + matrix viewMatrix; + matrix projectionMatrix; +}; + + +////////////// +// TYPEDEFS // +////////////// +struct VertexInputType +{ + float4 position : POSITION; + float2 tex : TEXCOORD0; +}; + +struct PixelInputType +{ + float4 position : SV_POSITION; + float2 tex : TEXCOORD0; +}; + + +//////////////////////////////////////////////////////////////////////////////// +// Vertex Shader +//////////////////////////////////////////////////////////////////////////////// +PixelInputType TranslateVertexShader(VertexInputType input) +{ + PixelInputType output; + + + // Change the position vector to be 4 units for proper matrix calculations. + input.position.w = 1.0f; + + // Calculate the position of the vertex against the world, view, and projection matrices. + output.position = mul(input.position, worldMatrix); + output.position = mul(output.position, viewMatrix); + output.position = mul(output.position, projectionMatrix); + + // Store the texture coordinates for the pixel shader. + output.tex = input.tex; + + return output; +} diff --git a/enginecustom/translateshaderclass.cpp b/enginecustom/translateshaderclass.cpp new file mode 100644 index 0000000..47692f3 --- /dev/null +++ b/enginecustom/translateshaderclass.cpp @@ -0,0 +1,416 @@ +#include "translateshaderclass.h" + + +TranslateShaderClass::TranslateShaderClass() +{ + m_vertexShader = 0; + m_pixelShader = 0; + m_layout = 0; + m_matrixBuffer = 0; + m_sampleState = 0; + + m_translateBuffer = 0; +} + + +TranslateShaderClass::TranslateShaderClass(const TranslateShaderClass& other) +{ +} + + +TranslateShaderClass::~TranslateShaderClass() +{ +} + + +bool TranslateShaderClass::Initialize(ID3D11Device* device, HWND hwnd) +{ + bool result; + wchar_t vsFilename[128]; + wchar_t psFilename[128]; + int error; + + // Set the filename of the vertex shader. + error = wcscpy_s(vsFilename, 128, L"../Engine/translate.vs"); + if (error != 0) + { + return false; + } + + // Set the filename of the pixel shader. + error = wcscpy_s(psFilename, 128, L"../Engine/translate.ps"); + if (error != 0) + { + return false; + } + + // Initialize the vertex and pixel shaders. + result = InitializeShader(device, hwnd, vsFilename, psFilename); + if (!result) + { + return false; + } + + return true; +} + + +void TranslateShaderClass::Shutdown() +{ + // Shutdown the vertex and pixel shaders as well as the related objects. + ShutdownShader(); + + return; +} + +bool TranslateShaderClass::Render(ID3D11DeviceContext * deviceContext, int indexCount, XMMATRIX worldMatrix, XMMATRIX viewMatrix, + XMMATRIX projectionMatrix, ID3D11ShaderResourceView * texture, float translation) +{ + bool result; + + + // Set the shader parameters that it will use for rendering. + result = SetShaderParameters(deviceContext, worldMatrix, viewMatrix, projectionMatrix, texture, translation); + if (!result) + { + return false; + } + + // Now render the prepared buffers with the shader. + RenderShader(deviceContext, indexCount); + + return true; +} + + +bool TranslateShaderClass::InitializeShader(ID3D11Device * device, HWND hwnd, WCHAR * vsFilename, WCHAR * psFilename) +{ + HRESULT result; + ID3D10Blob* errorMessage; + ID3D10Blob* vertexShaderBuffer; + ID3D10Blob* pixelShaderBuffer; + D3D11_INPUT_ELEMENT_DESC polygonLayout[2]; + unsigned int numElements; + D3D11_BUFFER_DESC matrixBufferDesc; + D3D11_SAMPLER_DESC samplerDesc; + D3D11_BUFFER_DESC translateBufferDesc; + + + // Initialize the pointers this function will use to null. + errorMessage = 0; + vertexShaderBuffer = 0; + pixelShaderBuffer = 0; + + // Compile the vertex shader code. + result = D3DCompileFromFile(vsFilename, NULL, NULL, "TranslateVertexShader", "vs_5_0", D3D10_SHADER_ENABLE_STRICTNESS, 0, + &vertexShaderBuffer, &errorMessage); + if (FAILED(result)) + { + // If the shader failed to compile it should have writen something to the error message. + if (errorMessage) + { + OutputShaderErrorMessage(errorMessage, hwnd, vsFilename); + } + // If there was nothing in the error message then it simply could not find the shader file itself. + else + { + MessageBox(hwnd, vsFilename, L"Missing Shader File", MB_OK); + } + + return false; + } + + // Compile the pixel shader code. + result = D3DCompileFromFile(psFilename, NULL, NULL, "TranslatePixelShader", "ps_5_0", D3D10_SHADER_ENABLE_STRICTNESS, 0, + &pixelShaderBuffer, &errorMessage); + if (FAILED(result)) + { + // If the shader failed to compile it should have writen something to the error message. + if (errorMessage) + { + OutputShaderErrorMessage(errorMessage, hwnd, psFilename); + } + // If there was nothing in the error message then it simply could not find the file itself. + else + { + MessageBox(hwnd, psFilename, L"Missing Shader File", MB_OK); + } + + return false; + } + + // Create the vertex shader from the buffer. + result = device->CreateVertexShader(vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), NULL, &m_vertexShader); + if (FAILED(result)) + { + return false; + } + + // Create the pixel shader from the buffer. + result = device->CreatePixelShader(pixelShaderBuffer->GetBufferPointer(), pixelShaderBuffer->GetBufferSize(), NULL, &m_pixelShader); + if (FAILED(result)) + { + return false; + } + + // Create the vertex input layout description. + polygonLayout[0].SemanticName = "POSITION"; + polygonLayout[0].SemanticIndex = 0; + polygonLayout[0].Format = DXGI_FORMAT_R32G32B32_FLOAT; + polygonLayout[0].InputSlot = 0; + polygonLayout[0].AlignedByteOffset = 0; + polygonLayout[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + polygonLayout[0].InstanceDataStepRate = 0; + + polygonLayout[1].SemanticName = "TEXCOORD"; + polygonLayout[1].SemanticIndex = 0; + polygonLayout[1].Format = DXGI_FORMAT_R32G32_FLOAT; + polygonLayout[1].InputSlot = 0; + polygonLayout[1].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT; + polygonLayout[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + polygonLayout[1].InstanceDataStepRate = 0; + + // Get a count of the elements in the layout. + numElements = sizeof(polygonLayout) / sizeof(polygonLayout[0]); + + // Create the vertex input layout. + result = device->CreateInputLayout(polygonLayout, numElements, vertexShaderBuffer->GetBufferPointer(), + vertexShaderBuffer->GetBufferSize(), &m_layout); + if (FAILED(result)) + { + return false; + } + + // Release the vertex shader buffer and pixel shader buffer since they are no longer needed. + vertexShaderBuffer->Release(); + vertexShaderBuffer = 0; + + pixelShaderBuffer->Release(); + pixelShaderBuffer = 0; + + // Setup the description of the dynamic matrix constant buffer that is in the vertex shader. + matrixBufferDesc.Usage = D3D11_USAGE_DYNAMIC; + matrixBufferDesc.ByteWidth = sizeof(MatrixBufferType); + matrixBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + matrixBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + matrixBufferDesc.MiscFlags = 0; + matrixBufferDesc.StructureByteStride = 0; + + // Create the constant buffer pointer so we can access the vertex shader constant buffer from within this class. + result = device->CreateBuffer(&matrixBufferDesc, NULL, &m_matrixBuffer); + if (FAILED(result)) + { + return false; + } + + // Create a texture sampler state description. + samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + samplerDesc.MipLODBias = 0.0f; + samplerDesc.MaxAnisotropy = 1; + samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + samplerDesc.BorderColor[0] = 0; + samplerDesc.BorderColor[1] = 0; + samplerDesc.BorderColor[2] = 0; + samplerDesc.BorderColor[3] = 0; + samplerDesc.MinLOD = 0; + samplerDesc.MaxLOD = D3D11_FLOAT32_MAX; + + // Create the texture sampler state. + result = device->CreateSamplerState(&samplerDesc, &m_sampleState); + if (FAILED(result)) + { + return false; + } + + // Setup the description of the texture translation dynamic constant buffer that is in the pixel shader. + translateBufferDesc.Usage = D3D11_USAGE_DYNAMIC; + translateBufferDesc.ByteWidth = sizeof(TranslateBufferType); + translateBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + translateBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + translateBufferDesc.MiscFlags = 0; + translateBufferDesc.StructureByteStride = 0; + + // Create the constant buffer pointer so we can access the pixel shader constant buffer from within this class. + result = device->CreateBuffer(&translateBufferDesc, NULL, &m_translateBuffer); + if (FAILED(result)) + { + return false; + } + + return true; +} + + +void TranslateShaderClass::ShutdownShader() +{ + + // Release the texture translation constant buffer. + if (m_translateBuffer) + { + m_translateBuffer->Release(); + m_translateBuffer = 0; + } + + // Release the sampler state. + if (m_sampleState) + { + m_sampleState->Release(); + m_sampleState = 0; + } + + // Release the matrix constant buffer. + if (m_matrixBuffer) + { + m_matrixBuffer->Release(); + m_matrixBuffer = 0; + } + + // Release the layout. + if (m_layout) + { + m_layout->Release(); + m_layout = 0; + } + + // Release the pixel shader. + if (m_pixelShader) + { + m_pixelShader->Release(); + m_pixelShader = 0; + } + + // Release the vertex shader. + if (m_vertexShader) + { + m_vertexShader->Release(); + m_vertexShader = 0; + } + + return; +} + + +void TranslateShaderClass::OutputShaderErrorMessage(ID3D10Blob * errorMessage, HWND hwnd, WCHAR * shaderFilename) +{ + char* compileErrors; + unsigned long long bufferSize, i; + ofstream fout; + + + // Get a pointer to the error message text buffer. + compileErrors = (char*)(errorMessage->GetBufferPointer()); + + // Get the length of the message. + bufferSize = errorMessage->GetBufferSize(); + + // Open a file to write the error message to. + fout.open("shader-error.txt"); + + // Write out the error message. + for (i = 0; i < bufferSize; i++) + { + fout << compileErrors[i]; + } + + // Close the file. + fout.close(); + + // Release the error message. + errorMessage->Release(); + errorMessage = 0; + + // Pop a message up on the screen to notify the user to check the text file for compile errors. + MessageBox(hwnd, L"Error compiling shader. Check shader-error.txt for message.", shaderFilename, MB_OK); + + return; +} + + +bool TranslateShaderClass::SetShaderParameters(ID3D11DeviceContext * deviceContext, XMMATRIX worldMatrix, XMMATRIX viewMatrix, + XMMATRIX projectionMatrix, ID3D11ShaderResourceView * texture, float translation) +{ + HRESULT result; + D3D11_MAPPED_SUBRESOURCE mappedResource; + MatrixBufferType* dataPtr; + unsigned int bufferNumber; + TranslateBufferType* dataPtr2; + + + // Transpose the matrices to prepare them for the shader. + worldMatrix = XMMatrixTranspose(worldMatrix); + viewMatrix = XMMatrixTranspose(viewMatrix); + projectionMatrix = XMMatrixTranspose(projectionMatrix); + + // Lock the constant buffer so it can be written to. + result = deviceContext->Map(m_matrixBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + return false; + } + + // Get a pointer to the data in the constant buffer. + dataPtr = (MatrixBufferType*)mappedResource.pData; + + // Copy the matrices into the constant buffer. + dataPtr->world = worldMatrix; + dataPtr->view = viewMatrix; + dataPtr->projection = projectionMatrix; + + // Unlock the constant buffer. + deviceContext->Unmap(m_matrixBuffer, 0); + + // Set the position of the constant buffer in the vertex shader. + bufferNumber = 0; + + // Finally set the constant buffer in the vertex shader with the updated values. + deviceContext->VSSetConstantBuffers(bufferNumber, 1, &m_matrixBuffer); + + // Set shader texture resource in the pixel shader. + deviceContext->PSSetShaderResources(0, 1, &texture); + + // Lock the texture translation constant buffer so it can be written to. + result = deviceContext->Map(m_translateBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + return false; + } + + // Get a pointer to the data in the texture translation constant buffer. + dataPtr2 = (TranslateBufferType*)mappedResource.pData; + + // Copy the translation value into the texture translation constant buffer. + dataPtr2->translation = translation; + + // Unlock the buffer. + deviceContext->Unmap(m_translateBuffer, 0); + + // Set the position of the texture translation constant buffer in the pixel shader. + bufferNumber = 0; + + // Now set the texture translation constant buffer in the pixel shader with the updated values. + deviceContext->PSSetConstantBuffers(bufferNumber, 1, &m_translateBuffer); + + return true; +} + + +void TranslateShaderClass::RenderShader(ID3D11DeviceContext * deviceContext, int indexCount) +{ + // Set the vertex input layout. + deviceContext->IASetInputLayout(m_layout); + + // Set the vertex and pixel shaders that will be used to render this triangle. + deviceContext->VSSetShader(m_vertexShader, NULL, 0); + deviceContext->PSSetShader(m_pixelShader, NULL, 0); + + // Set the sampler state in the pixel shader. + deviceContext->PSSetSamplers(0, 1, &m_sampleState); + + // Render the geometry. + deviceContext->DrawIndexed(indexCount, 0, 0); + + return; +} \ No newline at end of file diff --git a/enginecustom/translateshaderclass.h b/enginecustom/translateshaderclass.h new file mode 100644 index 0000000..a51f1ab --- /dev/null +++ b/enginecustom/translateshaderclass.h @@ -0,0 +1,62 @@ +#ifndef _TRANSLATESHADERCLASS_H_ +#define _TRANSLATESHADERCLASS_H_ + + +////////////// +// INCLUDES // +////////////// +#include +#include +#include +#include +using namespace DirectX; +using namespace std; + + +//////////////////////////////////////////////////////////////////////////////// +// Class name: TranslateShaderClass +//////////////////////////////////////////////////////////////////////////////// +class TranslateShaderClass +{ +private: + struct MatrixBufferType + { + XMMATRIX world; + XMMATRIX view; + XMMATRIX projection; + }; + + struct TranslateBufferType + { + float translation; + XMFLOAT3 padding; + }; + +public: + TranslateShaderClass(); + TranslateShaderClass(const TranslateShaderClass&); + ~TranslateShaderClass(); + + bool Initialize(ID3D11Device*, HWND); + void Shutdown(); + bool Render(ID3D11DeviceContext*, int, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, float); + +private: + bool InitializeShader(ID3D11Device*, HWND, WCHAR*, WCHAR*); + void ShutdownShader(); + void OutputShaderErrorMessage(ID3D10Blob*, HWND, WCHAR*); + + bool SetShaderParameters(ID3D11DeviceContext*, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, float); + void RenderShader(ID3D11DeviceContext*, int); + +private: + ID3D11VertexShader* m_vertexShader; + ID3D11PixelShader* m_pixelShader; + ID3D11InputLayout* m_layout; + ID3D11Buffer* m_matrixBuffer; + ID3D11SamplerState* m_sampleState; + + ID3D11Buffer* m_translateBuffer; +}; + +#endif