From ff9e729529f09751096d2232a2903b0e84a21f74 Mon Sep 17 00:00:00 2001 From: StratiX0 Date: Fri, 29 Mar 2024 14:45:44 +0100 Subject: [PATCH] ajouts des fonts (texte) --- enginecustom/applicationclass.cpp | 131 +++++++++- enginecustom/applicationclass.h | 6 + enginecustom/d3dclass.cpp | 80 +++++- enginecustom/d3dclass.h | 12 +- enginecustom/enginecustom.vcxproj | 10 + enginecustom/font.ps | 47 ++++ enginecustom/font.vs | 48 ++++ enginecustom/font01.tga | Bin 0 -> 131116 bytes enginecustom/font01.txt | 95 +++++++ enginecustom/fontclass.cpp | 252 ++++++++++++++++++ enginecustom/fontclass.h | 64 +++++ enginecustom/fontshaderclass.cpp | 408 ++++++++++++++++++++++++++++++ enginecustom/fontshaderclass.h | 60 +++++ enginecustom/textclass.cpp | 250 ++++++++++++++++++ enginecustom/textclass.h | 48 ++++ 15 files changed, 1506 insertions(+), 5 deletions(-) create mode 100644 enginecustom/font.ps create mode 100644 enginecustom/font.vs create mode 100644 enginecustom/font01.tga create mode 100644 enginecustom/font01.txt create mode 100644 enginecustom/fontclass.cpp create mode 100644 enginecustom/fontclass.h create mode 100644 enginecustom/fontshaderclass.cpp create mode 100644 enginecustom/fontshaderclass.h create mode 100644 enginecustom/textclass.cpp create mode 100644 enginecustom/textclass.h diff --git a/enginecustom/applicationclass.cpp b/enginecustom/applicationclass.cpp index a4d57a4..8da9425 100644 --- a/enginecustom/applicationclass.cpp +++ b/enginecustom/applicationclass.cpp @@ -13,6 +13,11 @@ ApplicationClass::ApplicationClass() m_Sprite = 0; m_Timer = 0; m_Lights = 0; + m_FontShader = 0; + m_Font = 0; + m_TextString1 = 0; + m_TextString2 = 0; + m_TextString3 = 0; } @@ -28,6 +33,7 @@ ApplicationClass::~ApplicationClass() bool ApplicationClass::Initialize(int screenWidth, int screenHeight, HWND hwnd) { + char testString1[32], testString2[32], testString3[32]; char modelFilename[128]; char textureFilename1[128], textureFilename2[128]; char bitmapFilename[128]; @@ -61,6 +67,57 @@ bool ApplicationClass::Initialize(int screenWidth, int screenHeight, HWND hwnd) m_Camera->SetPosition(0.0f, 0.0f, -12.0f); m_Camera->SetRotation(0.0f, 0.0f, 0.0f); + // 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 strings we want to display. + strcpy_s(testString1, "Yo"); + strcpy_s(testString2, "Les"); + strcpy_s(testString3, "Noobs !"); + + // Create and initialize the first text object. + m_TextString1 = new TextClass; + + result = m_TextString1->Initialize(m_Direct3D->GetDevice(), m_Direct3D->GetDeviceContext(), screenWidth, screenHeight, 32, m_Font, testString1, 25, screenHeight / 2 - m_Font->GetFontHeight(), 1.0f, 1.0f, 1.0f); + if (!result) + { + return false; + } + + // Create and initialize the second text object. + m_TextString2 = new TextClass; + + result = m_TextString2->Initialize(m_Direct3D->GetDevice(), m_Direct3D->GetDeviceContext(), screenWidth, screenHeight, 32, m_Font, testString2, 250, screenHeight / 2 - m_Font->GetFontHeight(), 0.0f, 1.0f, 1.0f); + if (!result) + { + return false; + } + + // Create and initialize the second text object. + m_TextString3 = new TextClass; + + result = m_TextString3->Initialize(m_Direct3D->GetDevice(), m_Direct3D->GetDeviceContext(), screenWidth, screenHeight, 32, m_Font, testString3, screenWidth / 2 - m_Font->GetSentencePixelLength(testString3), screenHeight / 2 - m_Font->GetFontHeight(), 1.0f, 1.0f, 0.0f); + if (!result) + { + return false; + } + // Create and initialize the texture shader object. m_TextureShader = new TextureShaderClass; @@ -167,6 +224,44 @@ bool ApplicationClass::Initialize(int screenWidth, int screenHeight, HWND hwnd) void ApplicationClass::Shutdown() { + // Release the text string objects. + if (m_TextString3) + { + m_TextString3->Shutdown(); + delete m_TextString3; + m_TextString3 = 0; + } + + if (m_TextString2) + { + m_TextString2->Shutdown(); + delete m_TextString2; + m_TextString2 = 0; + } + + if (m_TextString1) + { + m_TextString1->Shutdown(); + delete m_TextString1; + m_TextString1 = 0; + } + + // Release the font object. + if (m_Font) + { + m_Font->Shutdown(); + delete m_Font; + m_Font = 0; + } + + // Release the font shader object. + if (m_FontShader) + { + m_FontShader->Shutdown(); + delete m_FontShader; + m_FontShader = 0; + } + // Release the timer object. if (m_Timer) { @@ -319,8 +414,39 @@ bool ApplicationClass::Render(float rotation, float x, float y, float z) m_Direct3D->GetProjectionMatrix(projectionMatrix); m_Direct3D->GetOrthoMatrix(orthoMatrix); - // Turn off the Z buffer to begin all 2D rendering. + // Disable the Z buffer and enable alpha blending for 2D rendering. m_Direct3D->TurnZBufferOff(); + m_Direct3D->EnableAlphaBlending(); + + // 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, + m_Font->GetTexture(), m_TextString1->GetPixelColor()); + if (!result) + { + return false; + } + + // 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, + m_Font->GetTexture(), m_TextString2->GetPixelColor()); + if (!result) + { + return false; + } + + // 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, + m_Font->GetTexture(), m_TextString3->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()); @@ -398,8 +524,9 @@ bool ApplicationClass::Render(float rotation, float x, float y, float z) result = m_MultiTextureShader->Render(m_Direct3D->GetDeviceContext(), m_Model->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, m_Model->GetTexture(0), m_Model->GetTexture(1)); - // Turn the Z buffer back on now that all 2D rendering has completed. + // Enable the Z buffer and disable alpha blending now that 2D rendering is complete. m_Direct3D->TurnZBufferOn(); + m_Direct3D->DisableAlphaBlending(); // Present the rendered scene to the screen. m_Direct3D->EndScene(); diff --git a/enginecustom/applicationclass.h b/enginecustom/applicationclass.h index 13719f0..fe7a529 100644 --- a/enginecustom/applicationclass.h +++ b/enginecustom/applicationclass.h @@ -15,6 +15,9 @@ #include "textureshaderclass.h" #include "spriteclass.h" #include "timerclass.h" +#include "fontshaderclass.h" +#include "fontclass.h" +#include "textclass.h" ///////////// // GLOBALS // @@ -54,6 +57,9 @@ private: TimerClass* m_Timer; LightClass* m_Lights; int m_numLights; + FontShaderClass* m_FontShader; + FontClass* m_Font; + TextClass *m_TextString1, *m_TextString2, *m_TextString3; }; #endif diff --git a/enginecustom/d3dclass.cpp b/enginecustom/d3dclass.cpp index e91e8c7..53022f5 100644 --- a/enginecustom/d3dclass.cpp +++ b/enginecustom/d3dclass.cpp @@ -15,6 +15,8 @@ D3DClass::D3DClass() m_depthStencilView = 0; m_rasterState = 0; m_depthDisabledStencilState = 0; + m_alphaEnableBlendingState = 0; + m_alphaDisableBlendingState = 0; } @@ -48,6 +50,7 @@ bool D3DClass::Initialize(int screenWidth, int screenHeight, bool vsync, HWND hw D3D11_RASTERIZER_DESC rasterDesc; float fieldOfView, screenAspect; D3D11_DEPTH_STENCIL_DESC depthDisabledStencilDesc; + D3D11_BLEND_DESC blendStateDescription; // Store the vsync setting. m_vsync_enabled = vsync; @@ -373,6 +376,35 @@ bool D3DClass::Initialize(int screenWidth, int screenHeight, bool vsync, HWND hw return false; } + // Clear the blend state description. + ZeroMemory(&blendStateDescription, sizeof(D3D11_BLEND_DESC)); + + // Create an alpha enabled blend state description. + blendStateDescription.RenderTarget[0].BlendEnable = TRUE; + blendStateDescription.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE; + blendStateDescription.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; + blendStateDescription.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; + blendStateDescription.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; + blendStateDescription.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; + blendStateDescription.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; + blendStateDescription.RenderTarget[0].RenderTargetWriteMask = 0x0f; + + // Create the blend state using the description. + result = m_device->CreateBlendState(&blendStateDescription, &m_alphaEnableBlendingState); + if (FAILED(result)) + { + return false; + } + + // Modify the description to create an alpha disabled blend state description. + blendStateDescription.RenderTarget[0].BlendEnable = FALSE; + + // Create the blend state using the description. + result = m_device->CreateBlendState(&blendStateDescription, &m_alphaDisableBlendingState); + if (FAILED(result)) + { + return false; + } return true; } @@ -386,6 +418,18 @@ void D3DClass::Shutdown() m_swapChain->SetFullscreenState(false, NULL); } + if (m_alphaEnableBlendingState) + { + m_alphaEnableBlendingState->Release(); + m_alphaEnableBlendingState = 0; + } + + if (m_alphaDisableBlendingState) + { + m_alphaDisableBlendingState->Release(); + m_alphaDisableBlendingState = 0; + } + if (m_depthDisabledStencilState) { m_depthDisabledStencilState->Release(); @@ -552,4 +596,38 @@ void D3DClass::TurnZBufferOff() { m_deviceContext->OMSetDepthStencilState(m_depthDisabledStencilState, 1); return; -} \ No newline at end of file +} + +void D3DClass::EnableAlphaBlending() +{ + float blendFactor[4]; + + + // Setup the blend factor. + blendFactor[0] = 0.0f; + blendFactor[1] = 0.0f; + blendFactor[2] = 0.0f; + blendFactor[3] = 0.0f; + + // Turn on the alpha blending. + m_deviceContext->OMSetBlendState(m_alphaEnableBlendingState, blendFactor, 0xffffffff); + + return; +} + +void D3DClass::DisableAlphaBlending() +{ + float blendFactor[4]; + + + // Setup the blend factor. + blendFactor[0] = 0.0f; + blendFactor[1] = 0.0f; + blendFactor[2] = 0.0f; + blendFactor[3] = 0.0f; + + // Turn off the alpha blending. + m_deviceContext->OMSetBlendState(m_alphaDisableBlendingState, blendFactor, 0xffffffff); + + return; +} diff --git a/enginecustom/d3dclass.h b/enginecustom/d3dclass.h index bb3c0ce..c6b64fd 100644 --- a/enginecustom/d3dclass.h +++ b/enginecustom/d3dclass.h @@ -16,8 +16,11 @@ ////////////// // INCLUDES // ////////////// -#include -#include +#include "d3d11.h" +#include "directxmath.h" +#include "fontshaderclass.h" +#include "fontclass.h" +#include "textclass.h" using namespace DirectX; @@ -52,6 +55,9 @@ public: void TurnZBufferOn(); void TurnZBufferOff(); + void EnableAlphaBlending(); + void DisableAlphaBlending(); + private: bool m_vsync_enabled; int m_videoCardMemory; @@ -69,6 +75,8 @@ private: XMMATRIX m_orthoMatrix; D3D11_VIEWPORT m_viewport; ID3D11DepthStencilState* m_depthDisabledStencilState; + ID3D11BlendState* m_alphaEnableBlendingState; + ID3D11BlendState* m_alphaDisableBlendingState; }; #endif \ No newline at end of file diff --git a/enginecustom/enginecustom.vcxproj b/enginecustom/enginecustom.vcxproj index f7ce25d..0628418 100644 --- a/enginecustom/enginecustom.vcxproj +++ b/enginecustom/enginecustom.vcxproj @@ -25,6 +25,8 @@ + + @@ -33,6 +35,7 @@ + @@ -43,6 +46,8 @@ + + @@ -50,11 +55,14 @@ + + + @@ -82,6 +90,7 @@ + @@ -89,6 +98,7 @@ + diff --git a/enginecustom/font.ps b/enginecustom/font.ps new file mode 100644 index 0000000..7de7ce3 --- /dev/null +++ b/enginecustom/font.ps @@ -0,0 +1,47 @@ +///////////// +// GLOBALS // +///////////// +Texture2D shaderTexture : register(t0); +SamplerState SampleType : register(s0); + +cbuffer PixelBuffer +{ + float4 pixelColor; +}; + + +////////////// +// TYPEDEFS // +////////////// +struct PixelInputType +{ + float4 position : SV_POSITION; + float2 tex : TEXCOORD0; +}; + +//////////////////////////////////////////////////////////////////////////////// +// Pixel Shader +//////////////////////////////////////////////////////////////////////////////// +float4 FontPixelShader(PixelInputType input) : SV_TARGET +{ + float4 color; + + + // Sample the texture pixel at this location. + color = shaderTexture.Sample(SampleType, input.tex); + + // If the color is black on the texture then treat this pixel as transparent. + if(color.r == 0.0f) + { + color.a = 0.0f; + } + + // If the color is other than black on the texture then this is a pixel in the font so draw it using the font pixel color. + else + { + color.a = 1.0f; + color = color * pixelColor; + } + + return color; +} diff --git a/enginecustom/font.vs b/enginecustom/font.vs new file mode 100644 index 0000000..0b71af3 --- /dev/null +++ b/enginecustom/font.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 FontVertexShader(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/font01.tga b/enginecustom/font01.tga new file mode 100644 index 0000000000000000000000000000000000000000..042989de2e962d69cde1fe74d07bf1a5b5120c8c GIT binary patch literal 131116 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 N*I)g&fBrAu{9jo_mEQmW literal 0 HcmV?d00001 diff --git a/enginecustom/font01.txt b/enginecustom/font01.txt new file mode 100644 index 0000000..b96a96f --- /dev/null +++ b/enginecustom/font01.txt @@ -0,0 +1,95 @@ +32 0.0 0.0 0 +33 ! 0.0 0.00390625 4 +34 " 0.0048828125 0.0107421875 6 +35 # 0.01171875 0.025390625 14 +36 $ 0.0263671875 0.0390625 13 +37 % 0.0400390625 0.0546875 15 +38 & 0.0556640625 0.0693359375 14 +39 ' 0.0703125 0.0732421875 3 +40 ( 0.07421875 0.0791015625 5 +41 ) 0.080078125 0.0849609375 5 +42 * 0.0859375 0.091796875 6 +43 + 0.0927734375 0.103515625 11 +44 , 0.1044921875 0.107421875 3 +45 - 0.1083984375 0.1142578125 6 +46 . 0.115234375 0.1181640625 3 +47 / 0.119140625 0.126953125 8 +48 0 0.1279296875 0.1416015625 14 +49 1 0.142578125 0.146484375 4 +50 2 0.1474609375 0.1591796875 12 +51 3 0.16015625 0.1708984375 11 +52 4 0.171875 0.1845703125 13 +53 5 0.185546875 0.1962890625 11 +54 6 0.197265625 0.2099609375 13 +55 7 0.2109375 0.22265625 12 +56 8 0.2236328125 0.236328125 13 +57 9 0.2373046875 0.2490234375 12 +58 : 0.25 0.2529296875 3 +59 ; 0.25390625 0.2568359375 3 +60 < 0.2578125 0.267578125 10 +61 = 0.2685546875 0.279296875 11 +62 > 0.2802734375 0.2900390625 10 +63 ? 0.291015625 0.302734375 12 +64 @ 0.3037109375 0.3173828125 14 +65 A 0.318359375 0.33203125 14 +66 B 0.3330078125 0.3447265625 12 +67 C 0.345703125 0.3564453125 11 +68 D 0.357421875 0.3701171875 13 +69 E 0.37109375 0.3818359375 11 +70 F 0.3828125 0.3935546875 11 +71 G 0.39453125 0.40625 12 +72 H 0.4072265625 0.41796875 11 +73 I 0.4189453125 0.421875 3 +74 J 0.4228515625 0.4326171875 10 +75 K 0.43359375 0.4443359375 11 +76 L 0.4453125 0.4541015625 9 +77 M 0.455078125 0.4697265625 15 +78 N 0.470703125 0.482421875 12 +79 O 0.4833984375 0.49609375 13 +80 P 0.4970703125 0.5078125 12 +81 Q 0.509765625 0.5224609375 13 +82 R 0.5234375 0.53515625 12 +83 S 0.5361328125 0.548828125 13 +84 T 0.5498046875 0.5615234375 12 +85 U 0.5625 0.57421875 12 +86 V 0.5751953125 0.5888671875 14 +87 W 0.58984375 0.609375 20 +88 X 0.6103515625 0.6220703125 12 +89 Y 0.623046875 0.6357421875 13 +90 Z 0.63671875 0.6474609375 11 +91 [ 0.6484375 0.654296875 6 +92 \ 0.6552734375 0.6630859375 8 +93 ] 0.6640625 0.6689453125 5 +94 ^ 0.669921875 0.6806640625 11 +95 _ 0.681640625 0.6904296875 9 +96 ` 0.69140625 0.6962890625 5 +97 a 0.697265625 0.70703125 10 +98 b 0.7080078125 0.7177734375 10 +99 c 0.71875 0.7275390625 9 +100 d 0.728515625 0.73828125 10 +101 e 0.7392578125 0.748046875 9 +102 f 0.7490234375 0.755859375 7 +103 g 0.7568359375 0.7666015625 10 +104 h 0.767578125 0.7763671875 9 +105 i 0.77734375 0.7802734375 3 +106 j 0.78125 0.7861328125 5 +107 k 0.787109375 0.796875 10 +108 l 0.7978515625 0.80078125 3 +109 m 0.8017578125 0.8154296875 14 +110 n 0.81640625 0.826171875 10 +111 o 0.8271484375 0.8369140625 10 +112 p 0.837890625 0.84765625 10 +113 q 0.8486328125 0.8583984375 10 +114 r 0.859375 0.8671875 8 +115 s 0.8681640625 0.8779296875 10 +116 t 0.87890625 0.8857421875 7 +117 u 0.88671875 0.8955078125 9 +118 v 0.896484375 0.908203125 12 +119 w 0.9091796875 0.9248046875 16 +120 x 0.92578125 0.935546875 10 +121 y 0.9365234375 0.9453125 9 +122 z 0.9462890625 0.9560546875 10 +123 { 0.95703125 0.9638671875 7 +124 | 0.96484375 0.966796875 2 +125 } 0.9677734375 0.974609375 7 +126 ~ 0.9755859375 0.986328125 11 diff --git a/enginecustom/fontclass.cpp b/enginecustom/fontclass.cpp new file mode 100644 index 0000000..68b4f4b --- /dev/null +++ b/enginecustom/fontclass.cpp @@ -0,0 +1,252 @@ +#include "fontclass.h" + +FontClass::FontClass() +{ + m_Font = 0; + m_Texture = 0; +} + + +FontClass::FontClass(const FontClass& other) +{ +} + + +FontClass::~FontClass() +{ +} + +bool FontClass::Initialize(ID3D11Device* device, ID3D11DeviceContext* deviceContext, int fontChoice) +{ + char fontFilename[128]; + char fontTextureFilename[128]; + bool result; + + // Choose one of the available fonts, and default to the first font otherwise. + switch (fontChoice) + { + case 0: + { + strcpy_s(fontFilename, "font01.txt"); + strcpy_s(fontTextureFilename, "font01.tga"); + m_fontHeight = 32.0f; + m_spaceSize = 3; + break; + } + default: + { + strcpy_s(fontFilename, "font01.txt"); + strcpy_s(fontTextureFilename, "font01.tga"); + m_fontHeight = 32.0f; + m_spaceSize = 3; + break; + } + } + + // Load in the text file containing the font data. + result = LoadFontData(fontFilename); + if (!result) + { + return false; + } + + // Load the texture that has the font characters on it. + result = LoadTexture(device, deviceContext, fontTextureFilename); + if (!result) + { + return false; + } + + return true; +} + +void FontClass::Shutdown() +{ + // Release the font texture. + ReleaseTexture(); + + // Release the font data. + ReleaseFontData(); + + return; +} + +bool FontClass::LoadFontData(char* filename) +{ + std::ifstream fin; + int i; + char temp; + + // Create the font spacing buffer. + m_Font = new FontType[95]; + + // Read in the font size and spacing between chars. + fin.open(filename); + if (fin.fail()) + { + return false; + } + + // Read in the 95 used ascii characters for text. + for (i = 0; i < 95; i++) + { + fin.get(temp); + while (temp != ' ') + { + fin.get(temp); + } + fin.get(temp); + while (temp != ' ') + { + fin.get(temp); + } + + fin >> m_Font[i].left; + fin >> m_Font[i].right; + fin >> m_Font[i].size; + } + + // Close the file. + fin.close(); + + return true; +} + +void FontClass::ReleaseFontData() +{ + // Release the font data array. + if (m_Font) + { + delete[] m_Font; + m_Font = 0; + } + + return; +} + +bool FontClass::LoadTexture(ID3D11Device* device, ID3D11DeviceContext* deviceContext, char* filename) +{ + bool result; + + + // Create and initialize the font texture object. + m_Texture = new TextureClass; + + result = m_Texture->Initialize(device, deviceContext, filename); + if (!result) + { + return false; + } + + return true; +} + +void FontClass::ReleaseTexture() +{ + // Release the texture object. + if (m_Texture) + { + m_Texture->Shutdown(); + delete m_Texture; + m_Texture = 0; + } + + return; +} + +ID3D11ShaderResourceView* FontClass::GetTexture() +{ + return m_Texture->GetTexture(); +} + +void FontClass::BuildVertexArray(void* vertices, char* sentence, float drawX, float drawY) +{ + VertexType* vertexPtr; + int numLetters, index, i, letter; + + + // Coerce the input vertices into a VertexType structure. + vertexPtr = (VertexType*)vertices; + + // Get the number of letters in the sentence. + numLetters = (int)strlen(sentence); + + // Initialize the index to the vertex array. + index = 0; + + // Draw each letter onto a quad. + for (i = 0; i < numLetters; i++) + { + letter = ((int)sentence[i]) - 32; + + // If the letter is a space then just move over three pixels. + if (letter == 0) + { + drawX = drawX + m_spaceSize; + } + else + { + // First triangle in quad. + vertexPtr[index].position = XMFLOAT3(drawX, drawY, 0.0f); // Top left. + vertexPtr[index].texture = XMFLOAT2(m_Font[letter].left, 0.0f); + index++; + + vertexPtr[index].position = XMFLOAT3((drawX + m_Font[letter].size), (drawY - m_fontHeight), 0.0f); // Bottom right. + vertexPtr[index].texture = XMFLOAT2(m_Font[letter].right, 1.0f); + index++; + + vertexPtr[index].position = XMFLOAT3(drawX, (drawY - m_fontHeight), 0.0f); // Bottom left. + vertexPtr[index].texture = XMFLOAT2(m_Font[letter].left, 1.0f); + index++; + + // Second triangle in quad. + vertexPtr[index].position = XMFLOAT3(drawX, drawY, 0.0f); // Top left. + vertexPtr[index].texture = XMFLOAT2(m_Font[letter].left, 0.0f); + index++; + + vertexPtr[index].position = XMFLOAT3(drawX + m_Font[letter].size, drawY, 0.0f); // Top right. + vertexPtr[index].texture = XMFLOAT2(m_Font[letter].right, 0.0f); + index++; + + vertexPtr[index].position = XMFLOAT3((drawX + m_Font[letter].size), (drawY - m_fontHeight), 0.0f); // Bottom right. + vertexPtr[index].texture = XMFLOAT2(m_Font[letter].right, 1.0f); + index++; + + // Update the x location for drawing by the size of the letter and one pixel. + drawX = drawX + m_Font[letter].size + 1.0f; + } + } + + return; +} + +int FontClass::GetSentencePixelLength(char* sentence) +{ + int pixelLength, numLetters, i, letter; + + + pixelLength = 0; + numLetters = (int)strlen(sentence); + + for (i = 0; i < numLetters; i++) + { + letter = ((int)sentence[i]) - 32; + + // If the letter is a space then count it as three pixels. + if (letter == 0) + { + pixelLength += m_spaceSize; + } + else + { + pixelLength += (m_Font[letter].size + 1); + } + } + + return pixelLength; +} + +int FontClass::GetFontHeight() +{ + return (int)m_fontHeight; +} diff --git a/enginecustom/fontclass.h b/enginecustom/fontclass.h new file mode 100644 index 0000000..cd5a11e --- /dev/null +++ b/enginecustom/fontclass.h @@ -0,0 +1,64 @@ +#ifndef _FONTCLASS_H_ +#define _FONTCLASS_H_ + + +////////////// +// INCLUDES // +////////////// +#include +#include +using namespace DirectX; + + +/////////////////////// +// MY CLASS INCLUDES // +/////////////////////// +#include "textureclass.h" + + +//////////////////////////////////////////////////////////////////////////////// +// Class name: FontClass +//////////////////////////////////////////////////////////////////////////////// +class FontClass +{ +private: + struct FontType + { + float left, right; + int size; + }; + + struct VertexType + { + XMFLOAT3 position; + XMFLOAT2 texture; + }; + +public: + FontClass(); + FontClass(const FontClass&); + ~FontClass(); + + bool Initialize(ID3D11Device*, ID3D11DeviceContext*, int); + void Shutdown(); + + ID3D11ShaderResourceView* GetTexture(); + + void BuildVertexArray(void*, char*, float, float); + int GetSentencePixelLength(char*); + int GetFontHeight(); + +private: + bool LoadFontData(char*); + void ReleaseFontData(); + bool LoadTexture(ID3D11Device*, ID3D11DeviceContext*, char*); + void ReleaseTexture(); + +private: + FontType* m_Font; + TextureClass* m_Texture; + float m_fontHeight; + int m_spaceSize; +}; + +#endif \ No newline at end of file diff --git a/enginecustom/fontshaderclass.cpp b/enginecustom/fontshaderclass.cpp new file mode 100644 index 0000000..21978f1 --- /dev/null +++ b/enginecustom/fontshaderclass.cpp @@ -0,0 +1,408 @@ +#include "fontshaderclass.h" + + +FontShaderClass::FontShaderClass() +{ + m_vertexShader = 0; + m_pixelShader = 0; + m_layout = 0; + m_matrixBuffer = 0; + m_sampleState = 0; + m_pixelBuffer = 0; +} + + +FontShaderClass::FontShaderClass(const FontShaderClass& other) +{ +} + + +FontShaderClass::~FontShaderClass() +{ +} + + +bool FontShaderClass::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"font.vs"); + if (error != 0) + { + return false; + } + + // Set the filename of the pixel shader. + error = wcscpy_s(psFilename, 128, L"font.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 FontShaderClass::Shutdown() +{ + // Shutdown the vertex and pixel shaders as well as the related objects. + ShutdownShader(); + + return; +} + +bool FontShaderClass::Render(ID3D11DeviceContext* deviceContext, int indexCount, XMMATRIX worldMatrix, XMMATRIX viewMatrix, + XMMATRIX projectionMatrix, ID3D11ShaderResourceView* texture, XMFLOAT4 pixelColor) +{ + bool result; + + + // Set the shader parameters that it will use for rendering. + result = SetShaderParameters(deviceContext, worldMatrix, viewMatrix, projectionMatrix, texture, pixelColor); + if (!result) + { + return false; + } + + // Now render the prepared buffers with the shader. + RenderShader(deviceContext, indexCount); + + return true; +} + +bool FontShaderClass::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 pixelBufferDesc; + + + // 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, "FontVertexShader", "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, "FontPixelShader", "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 dynamic pixel constant buffer that is in the pixel shader. + pixelBufferDesc.Usage = D3D11_USAGE_DYNAMIC; + pixelBufferDesc.ByteWidth = sizeof(PixelBufferType); + pixelBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + pixelBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + pixelBufferDesc.MiscFlags = 0; + pixelBufferDesc.StructureByteStride = 0; + + // Create the pixel constant buffer pointer so we can access the pixel shader constant buffer from within this class. + result = device->CreateBuffer(&pixelBufferDesc, NULL, &m_pixelBuffer); + if (FAILED(result)) + { + return false; + } + + return true; +} + +void FontShaderClass::ShutdownShader() +{ + // Release the pixel constant buffer. + if (m_pixelBuffer) + { + m_pixelBuffer->Release(); + m_pixelBuffer = 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 FontShaderClass::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 FontShaderClass::SetShaderParameters(ID3D11DeviceContext* deviceContext, XMMATRIX worldMatrix, XMMATRIX viewMatrix, + XMMATRIX projectionMatrix, ID3D11ShaderResourceView* texture, XMFLOAT4 pixelColor) +{ + HRESULT result; + D3D11_MAPPED_SUBRESOURCE mappedResource; + MatrixBufferType* dataPtr; + unsigned int bufferNumber; + PixelBufferType* 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 pixel constant buffer so it can be written to. + result = deviceContext->Map(m_pixelBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + return false; + } + + // Get a pointer to the data in the pixel constant buffer. + dataPtr2 = (PixelBufferType*)mappedResource.pData; + + // Copy the pixel color into the pixel constant buffer. + dataPtr2->pixelColor = pixelColor; + + // Unlock the pixel constant buffer. + deviceContext->Unmap(m_pixelBuffer, 0); + + // Set the position of the pixel constant buffer in the pixel shader. + bufferNumber = 0; + + // Now set the pixel constant buffer in the pixel shader with the updated value. + deviceContext->PSSetConstantBuffers(bufferNumber, 1, &m_pixelBuffer); + + return true; +} + +void FontShaderClass::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/fontshaderclass.h b/enginecustom/fontshaderclass.h new file mode 100644 index 0000000..8a0221d --- /dev/null +++ b/enginecustom/fontshaderclass.h @@ -0,0 +1,60 @@ +#ifndef _FONTSHADERCLASS_H_ +#define _FONTSHADERCLASS_H_ + + +////////////// +// INCLUDES // +////////////// +#include +#include +#include +#include +using namespace DirectX; +using namespace std; + + +//////////////////////////////////////////////////////////////////////////////// +// Class name: FontShaderClass +//////////////////////////////////////////////////////////////////////////////// +class FontShaderClass +{ +private: + struct MatrixBufferType + { + XMMATRIX world; + XMMATRIX view; + XMMATRIX projection; + }; + + struct PixelBufferType + { + XMFLOAT4 pixelColor; + }; + +public: + FontShaderClass(); + FontShaderClass(const FontShaderClass&); + ~FontShaderClass(); + + bool Initialize(ID3D11Device*, HWND); + void Shutdown(); + bool Render(ID3D11DeviceContext*, int, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, XMFLOAT4); + +private: + bool InitializeShader(ID3D11Device*, HWND, WCHAR*, WCHAR*); + void ShutdownShader(); + void OutputShaderErrorMessage(ID3D10Blob*, HWND, WCHAR*); + + bool SetShaderParameters(ID3D11DeviceContext*, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, XMFLOAT4); + void RenderShader(ID3D11DeviceContext*, int); + +private: + ID3D11VertexShader* m_vertexShader; + ID3D11PixelShader* m_pixelShader; + ID3D11InputLayout* m_layout; + ID3D11Buffer* m_matrixBuffer; + ID3D11SamplerState* m_sampleState; + ID3D11Buffer* m_pixelBuffer; +}; + +#endif \ No newline at end of file diff --git a/enginecustom/textclass.cpp b/enginecustom/textclass.cpp new file mode 100644 index 0000000..33df17a --- /dev/null +++ b/enginecustom/textclass.cpp @@ -0,0 +1,250 @@ +#include "textclass.h" + + +TextClass::TextClass() +{ + m_vertexBuffer = 0; + m_indexBuffer = 0; +} + + +TextClass::TextClass(const TextClass& other) +{ +} + + +TextClass::~TextClass() +{ +} + +bool TextClass::Initialize(ID3D11Device* device, ID3D11DeviceContext* deviceContext, int screenWidth, int screenHeight, int maxLength, FontClass* Font, char* text, + int positionX, int positionY, float red, float green, float blue) +{ + bool result; + + + // Store the screen width and height. + m_screenWidth = screenWidth; + m_screenHeight = screenHeight; + + // Store the maximum length of the sentence. + m_maxLength = maxLength; + + // Initalize the sentence. + result = InitializeBuffers(device, deviceContext, Font, text, positionX, positionY, red, green, blue); + if (!result) + { + return false; + } + + return true; +} + +void TextClass::Shutdown() +{ + // Release the vertex and index buffers. + ShutdownBuffers(); + + return; +} + +void TextClass::Render(ID3D11DeviceContext* deviceContext) +{ + // Put the vertex and index buffers on the graphics pipeline to prepare them for drawing. + RenderBuffers(deviceContext); + + return; +} + +int TextClass::GetIndexCount() +{ + return m_indexCount; +} + +bool TextClass::InitializeBuffers(ID3D11Device* device, ID3D11DeviceContext* deviceContext, FontClass* Font, char* text, int positionX, int positionY, float red, float green, float blue) +{ + VertexType* vertices; + unsigned long* indices; + D3D11_BUFFER_DESC vertexBufferDesc, indexBufferDesc; + D3D11_SUBRESOURCE_DATA vertexData, indexData; + HRESULT result; + int i; + + // Set the vertex and index count. + m_vertexCount = 6 * m_maxLength; + 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)); + + // Initialize the index array. + 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; + + // Create the vertex buffer. + result = device->CreateBuffer(&vertexBufferDesc, &vertexData, &m_vertexBuffer); + if (FAILED(result)) + { + return false; + } + + // Set up the description of the static 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 vertex array as it is no longer needed. + delete[] vertices; + vertices = 0; + + // Release the index array as it is no longer needed. + delete[] indices; + indices = 0; + + // Now add the text data to the sentence buffers. + result = UpdateText(deviceContext, Font, text, positionX, positionY, red, green, blue); + if (!result) + { + return false; + } + + return true; +} + +void TextClass::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 TextClass::UpdateText(ID3D11DeviceContext* deviceContext, FontClass* Font, char* text, int positionX, int positionY, float red, float green, float blue) +{ + int numLetters; + VertexType* vertices; + float drawX, drawY; + HRESULT result; + D3D11_MAPPED_SUBRESOURCE mappedResource; + VertexType* verticesPtr; + + // Store the color of the sentence. + m_pixelColor = XMFLOAT4(red, green, blue, 1.0f); + + // Get the number of letters in the sentence. + numLetters = (int)strlen(text); + + // Check for possible buffer overflow. + if (numLetters > m_maxLength) + { + return false; + } + + // Create the vertex array. + vertices = new VertexType[m_vertexCount]; + + // Initialize vertex array to zeros at first. + memset(vertices, 0, (sizeof(VertexType) * m_vertexCount)); + + // Calculate the X and Y pixel position on the screen to start drawing to. + drawX = (float)(((m_screenWidth / 2) * -1) + positionX); + drawY = (float)((m_screenHeight / 2) - positionY); + + // Use the font class to build the vertex array from the sentence text and sentence draw location. + Font->BuildVertexArray((void*)vertices, text, drawX, drawY); + + // Lock the vertex buffer so it can be written to. + result = deviceContext->Map(m_vertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + return false; + } + + // Get a pointer to the data in the vertex buffer. + verticesPtr = (VertexType*)mappedResource.pData; + + // Copy the data into the vertex buffer. + memcpy(verticesPtr, (void*)vertices, (sizeof(VertexType) * m_vertexCount)); + + // Unlock the vertex buffer. + deviceContext->Unmap(m_vertexBuffer, 0); + + // Release the vertex array as it is no longer needed. + delete[] vertices; + vertices = 0; + + return true; +} + +void TextClass::RenderBuffers(ID3D11DeviceContext* deviceContext) +{ + unsigned int stride, 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; +} + +XMFLOAT4 TextClass::GetPixelColor() +{ + return m_pixelColor; +} diff --git a/enginecustom/textclass.h b/enginecustom/textclass.h new file mode 100644 index 0000000..643631a --- /dev/null +++ b/enginecustom/textclass.h @@ -0,0 +1,48 @@ +#ifndef _TEXTCLASS_H_ +#define _TEXTCLASS_H_ + + +/////////////////////// +// MY CLASS INCLUDES // +/////////////////////// +#include "fontclass.h" + + +//////////////////////////////////////////////////////////////////////////////// +// Class name: TextClass +//////////////////////////////////////////////////////////////////////////////// +class TextClass +{ +private: + struct VertexType + { + XMFLOAT3 position; + XMFLOAT2 texture; + }; + +public: + TextClass(); + TextClass(const TextClass&); + ~TextClass(); + + bool Initialize(ID3D11Device*, ID3D11DeviceContext*, int, int, int, FontClass*, char*, int, int, float, float, float); + void Shutdown(); + void Render(ID3D11DeviceContext*); + + int GetIndexCount(); + + bool UpdateText(ID3D11DeviceContext*, FontClass*, char*, int, int, float, float, float); + XMFLOAT4 GetPixelColor(); + +private: + bool InitializeBuffers(ID3D11Device*, ID3D11DeviceContext*, FontClass*, char*, int, int, float, float, float); + void ShutdownBuffers(); + void RenderBuffers(ID3D11DeviceContext*); + +private: + ID3D11Buffer* m_vertexBuffer, * m_indexBuffer; + int m_screenWidth, m_screenHeight, m_maxLength, m_vertexCount, m_indexCount; + XMFLOAT4 m_pixelColor; +}; + +#endif \ No newline at end of file