diff --git a/enginecustom/applicationclass.cpp b/enginecustom/applicationclass.cpp index edc11ad..957d5f8 100644 --- a/enginecustom/applicationclass.cpp +++ b/enginecustom/applicationclass.cpp @@ -7,6 +7,8 @@ ApplicationClass::ApplicationClass() m_Model = 0; m_LightShader = 0; m_Light = 0; + m_TextureShader = 0; + m_Bitmap = 0; } @@ -25,6 +27,7 @@ bool ApplicationClass::Initialize(int screenWidth, int screenHeight, HWND hwnd) char modelFilename[128]; char outputModelFilename[128]; char textureFilename[128]; + char bitmapFilename[128]; bool result; @@ -54,6 +57,28 @@ bool ApplicationClass::Initialize(int screenWidth, int screenHeight, HWND hwnd) m_Camera->SetPosition(0.0f, 0.0f, -10.0f); m_Camera->SetRotation(0.0f, 0.0f, 0.0f); + // Create and initialize the texture shader object. + m_TextureShader = new TextureShaderClass; + + result = m_TextureShader->Initialize(m_Direct3D->GetDevice(), hwnd); + if (!result) + { + MessageBox(hwnd, L"Could not initialize the texture shader object.", L"Error", MB_OK); + return false; + } + + // Set the file name of the bitmap file. + strcpy_s(bitmapFilename, "stone01.tga"); + + // Create and initialize the bitmap object. + m_Bitmap = new BitmapClass; + + result = m_Bitmap->Initialize(m_Direct3D->GetDevice(), m_Direct3D->GetDeviceContext(), screenWidth, screenHeight, bitmapFilename, 50, 50); + if (!result) + { + return false; + } + // Set the file name of the model. strcpy_s(modelFilename, "sphere.obj"); @@ -124,6 +149,22 @@ void ApplicationClass::Shutdown() m_Model = 0; } + // Release the bitmap object. + if (m_Bitmap) + { + m_Bitmap->Shutdown(); + delete m_Bitmap; + m_Bitmap = 0; + } + + // Release the texture shader object. + if (m_TextureShader) + { + m_TextureShader->Shutdown(); + delete m_TextureShader; + m_TextureShader = 0; + } + // Release the camera object. if (m_Camera) { @@ -180,7 +221,7 @@ bool ApplicationClass::Frame() bool ApplicationClass::Render(float rotation, float x, float y, float z) { - XMMATRIX worldMatrix, viewMatrix, projectionMatrix, rotateMatrix, translateMatrix, scaleMatrix, srMatrix; + XMMATRIX worldMatrix, viewMatrix, orthoMatrix, projectionMatrix, rotateMatrix, translateMatrix, scaleMatrix, srMatrix; bool result; @@ -194,6 +235,26 @@ bool ApplicationClass::Render(float rotation, float x, float y, float z) m_Direct3D->GetWorldMatrix(worldMatrix); m_Camera->GetViewMatrix(viewMatrix); m_Direct3D->GetProjectionMatrix(projectionMatrix); + m_Direct3D->GetOrthoMatrix(orthoMatrix); + + // Turn off the Z buffer to begin all 2D rendering. + m_Direct3D->TurnZBufferOff(); + + // Put the bitmap vertex and index buffers on the graphics pipeline to prepare them for drawing. + result = m_Bitmap->Render(m_Direct3D->GetDeviceContext()); + if (!result) + { + return false; + } + + m_Bitmap->SetRenderLocation(300, 50); + + // Render the bitmap with the texture shader. + result = m_TextureShader->Render(m_Direct3D->GetDeviceContext(), m_Bitmap->GetIndexCount(), worldMatrix, viewMatrix, orthoMatrix, m_Bitmap->GetTexture()); + if (!result) + { + return false; + } scaleMatrix = XMMatrixScaling(0.5f, 0.5f, 0.5f); // Build the scaling matrix. rotateMatrix = XMMatrixRotationY(rotation); // Build the rotation matrix. @@ -233,6 +294,9 @@ bool ApplicationClass::Render(float rotation, float x, float y, float z) return false; } + // Turn the Z buffer back on now that all 2D rendering has completed. + m_Direct3D->TurnZBufferOn(); + // Present the rendered scene to the screen. m_Direct3D->EndScene(); diff --git a/enginecustom/applicationclass.h b/enginecustom/applicationclass.h index 98344b6..d1c675c 100644 --- a/enginecustom/applicationclass.h +++ b/enginecustom/applicationclass.h @@ -10,6 +10,8 @@ #include "modelclass.h" #include "lightshaderclass.h" #include "lightclass.h" +#include "bitmapclass.h" +#include "textureshaderclass.h" ///////////// // GLOBALS // @@ -42,6 +44,8 @@ private: ModelClass* m_Model; LightShaderClass* m_LightShader; LightClass* m_Light; + TextureShaderClass* m_TextureShader; + BitmapClass* m_Bitmap; }; #endif diff --git a/enginecustom/bitmapclass.cpp b/enginecustom/bitmapclass.cpp new file mode 100644 index 0000000..ce25cb2 --- /dev/null +++ b/enginecustom/bitmapclass.cpp @@ -0,0 +1,333 @@ +#include "bitmapclass.h" + +BitmapClass::BitmapClass() +{ + m_vertexBuffer = 0; + m_indexBuffer = 0; + m_Texture = 0; +} + + +BitmapClass::BitmapClass(const BitmapClass& other) +{ +} + + +BitmapClass::~BitmapClass() +{ +} + + +bool BitmapClass::Initialize(ID3D11Device* device, ID3D11DeviceContext* deviceContext, int screenWidth, int screenHeight, char* textureFilename, int renderX, int renderY) +{ + bool result; + + // Store the screen size. + m_screenWidth = screenWidth; + m_screenHeight = screenHeight; + + // Store where the bitmap should be rendered to. + m_renderX = renderX; + m_renderY = renderY; + + // Initialize the vertex and index buffer that hold the geometry for the bitmap quad. + result = InitializeBuffers(device); + if (!result) + { + return false; + } + + // Load the texture for this bitmap. + result = LoadTexture(device, deviceContext, textureFilename); + if (!result) + { + return false; + } + + return true; +} + +void BitmapClass::Shutdown() +{ + // Release the bitmap texture. + ReleaseTexture(); + + // Release the vertex and index buffers. + ShutdownBuffers(); + + return; +} + +bool BitmapClass::Render(ID3D11DeviceContext* deviceContext) +{ + bool result; + + + // Update the buffers if the position of the bitmap has changed from its original position. + result = UpdateBuffers(deviceContext); + if (!result) + { + return false; + } + + // Put the vertex and index buffers on the graphics pipeline to prepare them for drawing. + RenderBuffers(deviceContext); + + return true; +} + +int BitmapClass::GetIndexCount() +{ + return m_indexCount; +} + +ID3D11ShaderResourceView* BitmapClass::GetTexture() +{ + return m_Texture->GetTexture(); +} + +bool BitmapClass::InitializeBuffers(ID3D11Device* device) +{ + VertexType* vertices; + unsigned long* indices; + D3D11_BUFFER_DESC vertexBufferDesc, indexBufferDesc; + D3D11_SUBRESOURCE_DATA vertexData, indexData; + HRESULT result; + int i; + + // Initialize the previous rendering position to negative one. + m_prevPosX = -1; + m_prevPosY = -1; + + // 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]; + + // Initialize vertex array to zeros at first. + memset(vertices, 0, (sizeof(VertexType) * m_vertexCount)); + + // Load the index array with data. + for (i = 0; i < m_indexCount; i++) + { + indices[i] = i; + } + + // Set up the description of the dynamic vertex buffer. + vertexBufferDesc.Usage = D3D11_USAGE_DYNAMIC; + vertexBufferDesc.ByteWidth = sizeof(VertexType) * m_vertexCount; + vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + vertexBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + 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 BitmapClass::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; +} + +bool BitmapClass::UpdateBuffers(ID3D11DeviceContext* deviceContent) +{ + float left, right, top, bottom; + VertexType* vertices; + D3D11_MAPPED_SUBRESOURCE mappedResource; + VertexType* dataPtr; + HRESULT result; + + // If the position we are rendering this bitmap to hasn't changed then don't update the vertex buffer. + if ((m_prevPosX == m_renderX) && (m_prevPosY == m_renderY)) + { + return true; + } + + // If the rendering location has changed then store the new position and update the vertex buffer. + m_prevPosX = m_renderX; + m_prevPosY = m_renderY; + + // Create the vertex array. + vertices = new VertexType[m_vertexCount]; + + // Calculate the screen coordinates of the left side of the bitmap. + left = (float)((m_screenWidth / 2) * -1) + (float)m_renderX; + + // Calculate the screen coordinates of the right side of the bitmap. + right = left + (float)m_bitmapWidth; + + // Calculate the screen coordinates of the top of the bitmap. + top = (float)(m_screenHeight / 2) - (float)m_renderY; + + // Calculate the screen coordinates of the bottom of the bitmap. + bottom = top - (float)m_bitmapHeight; + + // Load the vertex array with data. +// First triangle. + vertices[0].position = XMFLOAT3(left, top, 0.0f); // Top left. + vertices[0].texture = XMFLOAT2(0.0f, 0.0f); + + vertices[1].position = XMFLOAT3(right, bottom, 0.0f); // Bottom right. + vertices[1].texture = XMFLOAT2(1.0f, 1.0f); + + vertices[2].position = XMFLOAT3(left, bottom, 0.0f); // Bottom left. + vertices[2].texture = XMFLOAT2(0.0f, 1.0f); + + // Second triangle. + vertices[3].position = XMFLOAT3(left, top, 0.0f); // Top left. + vertices[3].texture = XMFLOAT2(0.0f, 0.0f); + + vertices[4].position = XMFLOAT3(right, top, 0.0f); // Top right. + vertices[4].texture = XMFLOAT2(1.0f, 0.0f); + + vertices[5].position = XMFLOAT3(right, bottom, 0.0f); // Bottom right. + vertices[5].texture = XMFLOAT2(1.0f, 1.0f); + + // Lock the vertex buffer. + result = deviceContent->Map(m_vertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + return false; + } + + // Get a pointer to the data in the constant buffer. + dataPtr = (VertexType*)mappedResource.pData; + + // Copy the data into the vertex buffer. + memcpy(dataPtr, (void*)vertices, (sizeof(VertexType) * m_vertexCount)); + + // Unlock the vertex buffer. + deviceContent->Unmap(m_vertexBuffer, 0); + + // Release the pointer reference. + dataPtr = 0; + + // Release the vertex array as it is no longer needed. + delete[] vertices; + vertices = 0; + + return true; +} + +void BitmapClass::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; +} + +bool BitmapClass::LoadTexture(ID3D11Device* device, ID3D11DeviceContext* deviceContext, char* filename) +{ + bool result; + + + // Create and initialize the texture object. + m_Texture = new TextureClass; + + result = m_Texture->Initialize(device, deviceContext, filename); + if (!result) + { + return false; + } + + // Store the size in pixels that this bitmap should be rendered at. + m_bitmapWidth = m_Texture->GetWidth(); + m_bitmapHeight = m_Texture->GetHeight(); + + return true; +} + +void BitmapClass::ReleaseTexture() +{ + // Release the texture object. + if (m_Texture) + { + m_Texture->Shutdown(); + delete m_Texture; + m_Texture = 0; + } + + return; +} + +void BitmapClass::SetRenderLocation(int x, int y) +{ + m_renderX = x; + m_renderY = y; + return; +} \ No newline at end of file diff --git a/enginecustom/bitmapclass.h b/enginecustom/bitmapclass.h new file mode 100644 index 0000000..9af076c --- /dev/null +++ b/enginecustom/bitmapclass.h @@ -0,0 +1,58 @@ +#ifndef _BITMAPCLASS_H_ +#define _BITMAPCLASS_H_ + + +////////////// +// INCLUDES // +////////////// +#include +using namespace DirectX; + + +/////////////////////// +// MY CLASS INCLUDES // +/////////////////////// +#include "textureclass.h" + + +//////////////////////////////////////////////////////////////////////////////// +// Class name: BitmapClass +//////////////////////////////////////////////////////////////////////////////// +class BitmapClass +{ +private: + struct VertexType + { + XMFLOAT3 position; + XMFLOAT2 texture; + }; + +public: + BitmapClass(); + BitmapClass(const BitmapClass&); + ~BitmapClass(); + + bool Initialize(ID3D11Device*, ID3D11DeviceContext*, int, int, char*, int, int); + void Shutdown(); + bool Render(ID3D11DeviceContext*); + + int GetIndexCount(); + ID3D11ShaderResourceView* GetTexture(); + + void SetRenderLocation(int, int); + +private: + bool InitializeBuffers(ID3D11Device*); + void ShutdownBuffers(); + bool UpdateBuffers(ID3D11DeviceContext*); + void RenderBuffers(ID3D11DeviceContext*); + + bool LoadTexture(ID3D11Device*, ID3D11DeviceContext*, char*); + void ReleaseTexture(); +private: + ID3D11Buffer* m_vertexBuffer, * m_indexBuffer; + int m_vertexCount, m_indexCount, m_screenWidth, m_screenHeight, m_bitmapWidth, m_bitmapHeight, m_renderX, m_renderY, m_prevPosX, m_prevPosY; + TextureClass* m_Texture; +}; + +#endif \ No newline at end of file diff --git a/enginecustom/d3dclass.cpp b/enginecustom/d3dclass.cpp index e87bc65..e91e8c7 100644 --- a/enginecustom/d3dclass.cpp +++ b/enginecustom/d3dclass.cpp @@ -14,6 +14,7 @@ D3DClass::D3DClass() m_depthStencilState = 0; m_depthStencilView = 0; m_rasterState = 0; + m_depthDisabledStencilState = 0; } @@ -46,7 +47,7 @@ bool D3DClass::Initialize(int screenWidth, int screenHeight, bool vsync, HWND hw D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc; D3D11_RASTERIZER_DESC rasterDesc; float fieldOfView, screenAspect; - + D3D11_DEPTH_STENCIL_DESC depthDisabledStencilDesc; // Store the vsync setting. m_vsync_enabled = vsync; @@ -345,6 +346,34 @@ bool D3DClass::Initialize(int screenWidth, int screenHeight, bool vsync, HWND hw // Create an orthographic projection matrix for 2D rendering. m_orthoMatrix = XMMatrixOrthographicLH((float)screenWidth, (float)screenHeight, screenNear, screenDepth); + // Clear the second depth stencil state before setting the parameters. + ZeroMemory(&depthDisabledStencilDesc, sizeof(depthDisabledStencilDesc)); + + // Now create a second depth stencil state which turns off the Z buffer for 2D rendering. The only difference is + // that DepthEnable is set to false, all other parameters are the same as the other depth stencil state. + depthDisabledStencilDesc.DepthEnable = false; + depthDisabledStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; + depthDisabledStencilDesc.DepthFunc = D3D11_COMPARISON_LESS; + depthDisabledStencilDesc.StencilEnable = true; + depthDisabledStencilDesc.StencilReadMask = 0xFF; + depthDisabledStencilDesc.StencilWriteMask = 0xFF; + depthDisabledStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; + depthDisabledStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR; + depthDisabledStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + depthDisabledStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + depthDisabledStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; + depthDisabledStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR; + depthDisabledStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + depthDisabledStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + + // Create the state using the device. + result = m_device->CreateDepthStencilState(&depthDisabledStencilDesc, &m_depthDisabledStencilState); + if (FAILED(result)) + { + return false; + } + + return true; } @@ -357,6 +386,12 @@ void D3DClass::Shutdown() m_swapChain->SetFullscreenState(false, NULL); } + if (m_depthDisabledStencilState) + { + m_depthDisabledStencilState->Release(); + m_depthDisabledStencilState = 0; + } + if (m_rasterState) { m_rasterState->Release(); @@ -503,5 +538,18 @@ void D3DClass::ResetViewport() // Set the viewport. m_deviceContext->RSSetViewports(1, &m_viewport); + return; +} + +void D3DClass::TurnZBufferOn() +{ + m_deviceContext->OMSetDepthStencilState(m_depthStencilState, 1); + return; +} + + +void D3DClass::TurnZBufferOff() +{ + m_deviceContext->OMSetDepthStencilState(m_depthDisabledStencilState, 1); return; } \ No newline at end of file diff --git a/enginecustom/d3dclass.h b/enginecustom/d3dclass.h index df75750..bb3c0ce 100644 --- a/enginecustom/d3dclass.h +++ b/enginecustom/d3dclass.h @@ -49,6 +49,9 @@ public: void SetBackBufferRenderTarget(); void ResetViewport(); + void TurnZBufferOn(); + void TurnZBufferOff(); + private: bool m_vsync_enabled; int m_videoCardMemory; @@ -65,6 +68,7 @@ private: XMMATRIX m_worldMatrix; XMMATRIX m_orthoMatrix; D3D11_VIEWPORT m_viewport; + ID3D11DepthStencilState* m_depthDisabledStencilState; }; #endif \ No newline at end of file diff --git a/enginecustom/enginecustom.vcxproj b/enginecustom/enginecustom.vcxproj index d27ec29..4bcd079 100644 --- a/enginecustom/enginecustom.vcxproj +++ b/enginecustom/enginecustom.vcxproj @@ -21,6 +21,7 @@ + @@ -31,10 +32,12 @@ + + @@ -44,11 +47,14 @@ + + + diff --git a/enginecustom/texture.ps b/enginecustom/texture.ps new file mode 100644 index 0000000..192f1fc --- /dev/null +++ b/enginecustom/texture.ps @@ -0,0 +1,28 @@ +///////////// +// GLOBALS // +///////////// +Texture2D shaderTexture : register(t0); +SamplerState SampleType : register(s0); + +////////////// +// TYPEDEFS // +////////////// +struct PixelInputType +{ + float4 position : SV_POSITION; + float2 tex : TEXCOORD0; +}; + +//////////////////////////////////////////////////////////////////////////////// +// Pixel Shader +//////////////////////////////////////////////////////////////////////////////// +float4 TexturePixelShader(PixelInputType input) : SV_TARGET +{ + float4 textureColor; + + + // Sample the pixel color from the texture using the sampler at this texture coordinate location. + textureColor = shaderTexture.Sample(SampleType, input.tex); + + return textureColor; +} \ No newline at end of file diff --git a/enginecustom/texture.vs b/enginecustom/texture.vs new file mode 100644 index 0000000..0d534ae --- /dev/null +++ b/enginecustom/texture.vs @@ -0,0 +1,47 @@ +///////////// +// 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 TextureVertexShader(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/textureshaderclass.cpp b/enginecustom/textureshaderclass.cpp new file mode 100644 index 0000000..6eed3c7 --- /dev/null +++ b/enginecustom/textureshaderclass.cpp @@ -0,0 +1,357 @@ +#include "textureshaderclass.h" + + +TextureShaderClass::TextureShaderClass() +{ + m_vertexShader = 0; + m_pixelShader = 0; + m_layout = 0; + m_matrixBuffer = 0; + m_sampleState = 0; +} + + +TextureShaderClass::TextureShaderClass(const TextureShaderClass& other) +{ +} + + +TextureShaderClass::~TextureShaderClass() +{ +} + + +bool TextureShaderClass::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"texture.vs"); + if (error != 0) + { + return false; + } + + // Set the filename of the pixel shader. + error = wcscpy_s(psFilename, 128, L"texture.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 TextureShaderClass::Shutdown() +{ + // Shutdown the vertex and pixel shaders as well as the related objects. + ShutdownShader(); + + return; +} + +bool TextureShaderClass::Render(ID3D11DeviceContext* deviceContext, int indexCount, XMMATRIX worldMatrix, XMMATRIX viewMatrix, + XMMATRIX projectionMatrix, ID3D11ShaderResourceView* texture) +{ + bool result; + + + // Set the shader parameters that it will use for rendering. + result = SetShaderParameters(deviceContext, worldMatrix, viewMatrix, projectionMatrix, texture); + if (!result) + { + return false; + } + + // Now render the prepared buffers with the shader. + RenderShader(deviceContext, indexCount); + + return true; +} + +bool TextureShaderClass::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; + + + // 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, "TextureVertexShader", "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, "TexturePixelShader", "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. + // This setup needs to match the VertexType stucture in the ModelClass and in the shader. + 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; + } + + return true; +} + +void TextureShaderClass::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 TextureShaderClass::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 TextureShaderClass::SetShaderParameters(ID3D11DeviceContext* deviceContext, XMMATRIX worldMatrix, XMMATRIX viewMatrix, + XMMATRIX projectionMatrix, ID3D11ShaderResourceView* texture) +{ + 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; + + // Finanly 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); + + return true; +} + +void TextureShaderClass::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/textureshaderclass.h b/enginecustom/textureshaderclass.h new file mode 100644 index 0000000..6c88f59 --- /dev/null +++ b/enginecustom/textureshaderclass.h @@ -0,0 +1,54 @@ +#ifndef _TEXTURESHADERCLASS_H_ +#define _TEXTURESHADERCLASS_H_ + + +////////////// +// INCLUDES // +////////////// +#include +#include +#include +#include +using namespace DirectX; +using namespace std; + + +//////////////////////////////////////////////////////////////////////////////// +// Class name: TextureShaderClass +//////////////////////////////////////////////////////////////////////////////// +class TextureShaderClass +{ +private: + struct MatrixBufferType + { + XMMATRIX world; + XMMATRIX view; + XMMATRIX projection; + }; + +public: + TextureShaderClass(); + TextureShaderClass(const TextureShaderClass&); + ~TextureShaderClass(); + + bool Initialize(ID3D11Device*, HWND); + void Shutdown(); + bool Render(ID3D11DeviceContext*, int, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*); + +private: + bool InitializeShader(ID3D11Device*, HWND, WCHAR*, WCHAR*); + void ShutdownShader(); + void OutputShaderErrorMessage(ID3D10Blob*, HWND, WCHAR*); + + bool SetShaderParameters(ID3D11DeviceContext*, XMMATRIX, XMMATRIX, XMMATRIX, 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