text: #include "fontshaderclass.h"
  
  FontShaderClass::FontShaderClass()
  {
      m_vertexShader = 0;
      m_pixelShader = 0;
      m_layout = 0;
      m_constantBuffer = 0;
      m_sampleState = 0;
  
      m_pixelBuffer = 0;
  }
  
  FontShaderClass::FontShaderClass(const FontShaderClass& other)
  {
  
  }
  
  FontShaderClass::~FontShaderClass()
  {
  
  }
  
  bool FontShaderClass::Initialize(ID3D11Device* device, HWND hwnd)
  {
      bool result;
  
      // Init vertex and pixel shaders
      result = InitializeShader(device, hwnd, L"../Engine/font.vs", L"../Engine/font.ps");
      if (!result)
          return false;
  
      return true;
  }
  
  void FontShaderClass::Shutdown()
  {
      ShutdownShader();
  
      return;
  }
  
  bool FontShaderClass::Render(ID3D11DeviceContext* deviceContext, int indexCount, D3DXMATRIX worldMatrix, D3DXMATRIX viewMatrix, D3DXMATRIX projectionMatrix, ID3D11ShaderResourceView* texture, D3DXVECTOR4 pixelColor)
  {
      bool result;
  
      // Set shader params that will be used for rendering
      result = SetShaderParameters(deviceContext, worldMatrix, viewMatrix, projectionMatrix, texture, pixelColor);
      if (!result)
          return false;
  
      // Render 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 constantBufferDesc;
      D3D11_SAMPLER_DESC samplerDesc;
      D3D11_BUFFER_DESC pixelBufferDesc;
  
      errorMessage = 0;
      vertexShaderBuffer = 0;
      pixelShaderBuffer = 0;
  
      // Compile vertex shader
      result = D3DX11CompileFromFile(vsFilename, NULL, NULL, "FontVertexShader", "vs_5_0", D3D10_SHADER_ENABLE_STRICTNESS, 0, NULL, &vertexShaderBuffer, &errorMessage, NULL);
      if (FAILED(result))
      {
          if (errorMessage)
          {
              OutputShaderErrorMessage(errorMessage, hwnd, vsFilename);
          }
          else
          {
              MessageBox(hwnd, vsFilename, L"Missing Shader File", MB_OK);
          }
          return false;
      }
  
      // Compile pixel shader
      result = D3DX11CompileFromFile(psFilename, NULL, NULL, "FontPixelShader", "ps_5_0", D3D10_SHADER_ENABLE_STRICTNESS, 0, NULL, &pixelShaderBuffer, &errorMessage, NULL);
      if (FAILED(result))
      {
          if (errorMessage)
          {
              OutputShaderErrorMessage(errorMessage, hwnd, psFilename);
          }
          else
          {
              MessageBox(hwnd, psFilename, L"Missing Shader File", MB_OK);
          }
          return false;
      }
  
      // Create vertex shader from the buffer
      result = device->CreateVertexShader(vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), NULL, &m_vertexShader);
      if (FAILED(result))
          return false;
  
      // Create pixel shader from the buffer
      result = device->CreatePixelShader(pixelShaderBuffer->GetBufferPointer(), pixelShaderBuffer->GetBufferSize(), NULL, &m_pixelShader);
      if (FAILED(result))
          return false;
  
      // Create 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;
  
      numElements = sizeof(polygonLayout) / sizeof(polygonLayout[0]);
  
      // Create vertex input layout
      result = device->CreateInputLayout(polygonLayout, numElements, vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), &m_layout);
      if (FAILED(result))
          return false;
  
      vertexShaderBuffer->Release();
      vertexShaderBuffer = 0;
      pixelShaderBuffer->Release();
      pixelShaderBuffer = 0;
  
      // Setup dynamic constant buffer description in the vertex shader
      constantBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
      constantBufferDesc.ByteWidth = sizeof(ConstantBufferType);
      constantBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
      constantBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
      constantBufferDesc.MiscFlags = 0;
      constantBufferDesc.StructureByteStride = 0;
  
      // Create constant buffer pointer to access vertex shader constant buffer
      result = device->CreateBuffer(&constantBufferDesc, NULL, &m_constantBuffer);
      if (FAILED(result))
          return false;
  
      // Create 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 texture sampler state
      result = device->CreateSamplerState(&samplerDesc, &m_sampleState);
      if (FAILED(result))
          return false;
  
      // Setup description of the dynamic pixel constant buffer in the pixel sahder
      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 pixel constant buffer pointer to access pixel shader constant buffer
      result = device->CreateBuffer(&pixelBufferDesc, NULL, &m_pixelBuffer);
      if (FAILED(result))
          return false;
  
      return true;
  }
  
  void FontShaderClass::ShutdownShader()
  {
      if (m_pixelBuffer)
      {
          m_pixelBuffer->Release();
          m_pixelBuffer = 0;
      }
      if (m_sampleState)
      {
          m_sampleState->Release();
          m_sampleState = 0;
      }
      if (m_constantBuffer)
      {
          m_constantBuffer->Release();
          m_constantBuffer = 0;
      }
      if (m_layout)
      {
          m_layout->Release();
          m_layout = 0;
      }
      if (m_pixelShader)
      {
          m_pixelShader->Release();
          m_pixelShader = 0;
      }
      if (m_vertexShader)
      {
          m_vertexShader->Release();
          m_vertexShader = 0;
      }
  
      return;
  }
  
  void FontShaderClass::OutputShaderErrorMessage(ID3D10Blob* errorMessage, HWND hwnd, WCHAR* shaderFilename)
  {
      char* compileErrors;
      unsigned long bufferSize, i;
      ofstream fout;
  
      compileErrors = (char*)(errorMessage->GetBufferPointer());
      bufferSize = errorMessage->GetBufferSize();
      fout.open("shader-error.txt");
  
      for (i = 0; i < bufferSize; i++)
          fout << compileErrors[i];
  
      fout.close();
  
      errorMessage->Release();
      errorMessage = 0;
  
      MessageBox(hwnd, L"Error compiling shader. Check shader-error.txt for message.", shaderFilename, MB_OK);
  
      return;
  }
  
  bool FontShaderClass::SetShaderParameters(ID3D11DeviceContext* deviceContext, D3DXMATRIX worldMatrix, D3DXMATRIX viewMatrix, D3DXMATRIX projectionMatrix, ID3D11ShaderResourceView* texture, D3DXVECTOR4 pixelColor)
  {
      HRESULT result;
      D3D11_MAPPED_SUBRESOURCE mappedResource;
      ConstantBufferType* dataPtr;
      unsigned int bufferNumber;
      PixelBufferType* dataPtr2;
  
      // Lock buffer
      result = deviceContext->Map(m_constantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
      if (FAILED(result))
          return false;
  
      dataPtr = (ConstantBufferType*)mappedResource.pData;
  
      D3DXMatrixTranspose(&worldMatrix, &worldMatrix);
      D3DXMatrixTranspose(&viewMatrix, &viewMatrix);
      D3DXMatrixTranspose(&projectionMatrix, &projectionMatrix);
  
      dataPtr->world = worldMatrix;
      dataPtr->view = viewMatrix;
      dataPtr->projection = projectionMatrix;
  
      // Unlock buffer
      deviceContext->Unmap(m_constantBuffer, 0);
  
      // Set position
      bufferNumber = 0;
  
      // Set constant buffer in vertex shader with updated values
      deviceContext->VSSetConstantBuffers(bufferNumber, 1, &m_constantBuffer);
  
      // Set shader texture resource in the pixel shader
      deviceContext->PSSetShaderResources(0, 1, &texture);
  
      // Lock pixel buffer
      result = deviceContext->Map(m_pixelBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
      if (FAILED(result))
          return false;
  
      dataPtr2 = (PixelBufferType*)mappedResource.pData;
      dataPtr2->pixelColor = pixelColor;
      
      // Unlock pixel buffer
      deviceContext->Unmap(m_pixelBuffer, 0);
  
      // Set position
      bufferNumber = 0;
  
      // Set pixel constnat buffer in pixel shader with updated value
      deviceContext->PSSetConstantBuffers(bufferNumber, 1, &m_pixelBuffer);
  
      return true;
  }
  
  void FontShaderClass::RenderShader(ID3D11DeviceContext* deviceContext, int indexCount)
  {
      // Set vertex input layout
      deviceContext->IASetInputLayout(m_layout);
  
      //Set vertex and pixel shaders
      deviceContext->VSSetShader(m_vertexShader, NULL, 0);
      deviceContext->PSSetShader(m_pixelShader, NULL, 0);
  
      // Set sampler state in pixel shader
      deviceContext->PSSetSamplers(0, 1, &m_sampleState);
  
      // Render
      deviceContext->DrawIndexed(indexCount, 0, 0);
  
      return;
  }