// // Copyright (C) Pixar. All rights reserved. // // This license governs use of the accompanying software. If you // use the software, you accept this license. If you do not accept // the license, do not use the software. // // 1. Definitions // The terms "reproduce," "reproduction," "derivative works," and // "distribution" have the same meaning here as under U.S. // copyright law. A "contribution" is the original software, or // any additions or changes to the software. // A "contributor" is any person or entity that distributes its // contribution under this license. // "Licensed patents" are a contributor's patent claims that read // directly on its contribution. // // 2. Grant of Rights // (A) Copyright Grant- Subject to the terms of this license, // including the license conditions and limitations in section 3, // each contributor grants you a non-exclusive, worldwide, // royalty-free copyright license to reproduce its contribution, // prepare derivative works of its contribution, and distribute // its contribution or any derivative works that you create. // (B) Patent Grant- Subject to the terms of this license, // including the license conditions and limitations in section 3, // each contributor grants you a non-exclusive, worldwide, // royalty-free license under its licensed patents to make, have // made, use, sell, offer for sale, import, and/or otherwise // dispose of its contribution in the software or derivative works // of the contribution in the software. // // 3. Conditions and Limitations // (A) No Trademark License- This license does not grant you // rights to use any contributor's name, logo, or trademarks. // (B) If you bring a patent claim against any contributor over // patents that you claim are infringed by the software, your // patent license from such contributor to the software ends // automatically. // (C) If you distribute any portion of the software, you must // retain all copyright, patent, trademark, and attribution // notices that are present in the software. // (D) If you distribute any portion of the software in source // code form, you may do so only under this license by including a // complete copy of this license with your distribution. If you // distribute any portion of the software in compiled or object // code form, you may only do so under a license that complies // with this license. // (E) The software is licensed "as-is." You bear the risk of // using it. The contributors give no express warranties, // guarantees or conditions. You may have additional consumer // rights under your local laws which this license cannot change. // To the extent permitted under your local laws, the contributors // exclude the implied warranties of merchantability, fitness for // a particular purpose and non-infringement. // #include #include #include #include #include "d3d11_hud.h" #include "d3d11_compile.h" #include "font_image.h" #include "../common/simple_math.h" #define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } static const char *s_VS = "cbuffer cbPerFrame : register( b0 )\n" "{\n" " matrix g_mViewProjection;\n" "};\n" "struct vertexIn { float2 pos : POSITION0; float3 color : COLOR0; float2 uv : TEXCOORD0; };\n" "struct vertexOut { float4 pos : SV_POSITION; float4 color : COLOR0; float2 uv : TEXCOORD0; };\n" "vertexOut vs_main(vertexIn IN) {\n" " vertexOut vout;\n" " vout.pos = mul(float4(IN.pos.x, IN.pos.y, 0, 1), g_mViewProjection);\n" " vout.color = float4(IN.color, 1);\n" " vout.uv = IN.uv;\n" " return vout;\n" "}"; static const char *s_PS = "struct pixelIn { float4 pos : SV_POSITION; float4 color : COLOR0; float2 uv : TEXCOORD0; };\n" "Texture2D tx : register(t0); \n" "SamplerState sm : register(s0); \n" "float4 ps_main(pixelIn IN) : SV_Target {\n" " float4 c = tx.Sample(sm, IN.uv);\n" " if( c.a == 0.0 ) \n" " discard;\n" " return IN.color * c;\n" "}"; struct CB_HUD_PROJECTION { float mViewProjection[16]; }; D3D11hud::D3D11hud(ID3D11DeviceContext *deviceContext) : _deviceContext(deviceContext), _vbo(0), _staticVbo(0), _fontTexture(0), _inputLayout(0), _shaderResourceView(0), _samplerState(0), _vertexShader(0), _pixelShader(0), _rasterizerState(0) { } D3D11hud::~D3D11hud() { SAFE_RELEASE(_vbo); SAFE_RELEASE(_staticVbo); SAFE_RELEASE(_fontTexture); SAFE_RELEASE(_inputLayout); SAFE_RELEASE(_shaderResourceView); SAFE_RELEASE(_samplerState); SAFE_RELEASE(_vertexShader); SAFE_RELEASE(_pixelShader); SAFE_RELEASE(_rasterizerState); } void D3D11hud::Init(int width, int height) { Hud::Init(width, height); ID3D11Device *device = NULL; _deviceContext->GetDevice(&device); // define font texture D3D11_TEXTURE2D_DESC texDesc; texDesc.Width = FONT_TEXTURE_WIDTH; texDesc.Height = FONT_TEXTURE_HEIGHT; texDesc.MipLevels = 1; texDesc.ArraySize = 1; texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; texDesc.SampleDesc.Count = 1; texDesc.SampleDesc.Quality = 0; texDesc.Usage = D3D11_USAGE_DEFAULT; texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; texDesc.CPUAccessFlags = 0; texDesc.MiscFlags = 0; D3D11_SUBRESOURCE_DATA subData; subData.pSysMem = font_image; subData.SysMemPitch = FONT_TEXTURE_WIDTH*4; subData.SysMemSlicePitch = FONT_TEXTURE_WIDTH*FONT_TEXTURE_HEIGHT*4; HRESULT hr = device->CreateTexture2D(&texDesc, &subData, &_fontTexture); assert(_fontTexture); // shader resource view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = texDesc.Format; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; srvDesc.Texture2D.MostDetailedMip = 0; srvDesc.Texture2D.MipLevels = texDesc.MipLevels; device->CreateShaderResourceView(_fontTexture, &srvDesc, &_shaderResourceView); assert(_shaderResourceView); D3D11_SAMPLER_DESC samplerDesc; ZeroMemory(&samplerDesc, sizeof(samplerDesc)); samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; samplerDesc.AddressU = samplerDesc.AddressV = samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; samplerDesc.MaxAnisotropy = 1; samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; samplerDesc.MaxLOD = D3D11_FLOAT32_MAX; device->CreateSamplerState(&samplerDesc, &_samplerState); assert(_samplerState); ID3DBlob* pVSBlob; ID3DBlob* pPSBlob; pVSBlob = d3d11CompileShader(s_VS, "vs_main", "vs_4_0"); pPSBlob = d3d11CompileShader(s_PS, "ps_main", "ps_4_0"); assert(pVSBlob); assert(pPSBlob); D3D11_INPUT_ELEMENT_DESC inputElementDesc[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, sizeof(float)*2, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, sizeof(float)*5, D3D11_INPUT_PER_VERTEX_DATA, 0 } }; device->CreateInputLayout(inputElementDesc, ARRAYSIZE(inputElementDesc), pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), &_inputLayout); assert(_inputLayout); device->CreateVertexShader(pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), NULL, &_vertexShader); assert(_vertexShader); device->CreatePixelShader(pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), NULL, &_pixelShader); assert(_pixelShader); D3D11_RASTERIZER_DESC rasDesc; rasDesc.FillMode = D3D11_FILL_SOLID; rasDesc.CullMode = D3D11_CULL_NONE; rasDesc.FrontCounterClockwise = FALSE; rasDesc.DepthBias = 0; rasDesc.DepthBiasClamp = 0; rasDesc.SlopeScaledDepthBias = 0.0f; rasDesc.DepthClipEnable = FALSE; rasDesc.ScissorEnable = FALSE; rasDesc.MultisampleEnable = FALSE; rasDesc.AntialiasedLineEnable = FALSE; device->CreateRasterizerState(&rasDesc, &_rasterizerState); assert(_rasterizerState); // constant buffer D3D11_BUFFER_DESC cbDesc; cbDesc.Usage = D3D11_USAGE_DYNAMIC; cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; cbDesc.MiscFlags = 0; cbDesc.ByteWidth = sizeof(CB_HUD_PROJECTION); device->CreateBuffer(&cbDesc, NULL, &_constantBuffer); assert(_constantBuffer); } void D3D11hud::Rebuild(int width, int height) { Hud::Rebuild(width, height); // XXX: move this code to Hud std::vector vboSource; // add UI elements for (std::vector::const_iterator it = getRadioButtons().begin(); it != getRadioButtons().end(); ++it) { int x = it->x > 0 ? it->x : GetWidth() + it->x; int y = it->y > 0 ? it->y : GetHeight() + it->y; if (it->checked) { x = drawChar(vboSource, x, y, 1, 1, 1, FONT_RADIO_BUTTON_ON); drawString(vboSource, x, y, 1, 1, 0, it->label.c_str()); } else { x = drawChar(vboSource, x, y, 1, 1, 1, ' '); drawString(vboSource, x, y, .5f, .5f, .5f, it->label.c_str()); } } for (std::vector::const_iterator it = getCheckBoxes().begin(); it != getCheckBoxes().end(); ++it) { int x = it->x > 0 ? it->x : GetWidth() + it->x; int y = it->y > 0 ? it->y : GetHeight() + it->y; if( it->checked) { x = drawChar(vboSource, x, y, 1, 1, 1, FONT_CHECK_BOX_ON); drawString(vboSource, x, y, 1, 1, 0, it->label.c_str()); } else { x = drawChar(vboSource, x, y, 1, 1, 1, FONT_CHECK_BOX_OFF); drawString(vboSource, x, y, .5f, .5f, .5f, it->label.c_str()); } } drawString(vboSource, GetWidth()-80, GetHeight()-48, .5, .5, .5, "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"); drawString(vboSource, GetWidth()-80, GetHeight()-32, .5, .5, .5, "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"); // -------------------------------- SAFE_RELEASE(_staticVbo); if (vboSource.size()) { D3D11_BUFFER_DESC bufferDesc; bufferDesc.ByteWidth = (int)vboSource.size() * sizeof(float); bufferDesc.Usage = D3D11_USAGE_DEFAULT; bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; bufferDesc.CPUAccessFlags = 0; bufferDesc.MiscFlags = 0; bufferDesc.StructureByteStride = 4*sizeof(float); D3D11_SUBRESOURCE_DATA subData; subData.pSysMem = &vboSource[0]; subData.SysMemPitch = 0; subData.SysMemSlicePitch = 0; ID3D11Device *device = NULL; _deviceContext->GetDevice(&device); HRESULT hr = device->CreateBuffer(&bufferDesc, &subData, &_staticVbo); assert(_staticVbo); _staticVboCount = (int)vboSource.size() / 7; } } bool D3D11hud::Flush() { if (!Hud::Flush()) return false; // update dynamic text D3D11_BUFFER_DESC bufferDesc; bufferDesc.ByteWidth = (int)getVboSource().size() * sizeof(float); bufferDesc.Usage = D3D11_USAGE_DEFAULT; bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; bufferDesc.CPUAccessFlags = 0; bufferDesc.MiscFlags = 0; bufferDesc.StructureByteStride = 4*sizeof(float); D3D11_SUBRESOURCE_DATA subData; subData.pSysMem = &getVboSource()[0]; subData.SysMemPitch = 0; subData.SysMemSlicePitch = 0; SAFE_RELEASE(_vbo); ID3D11Device *device = NULL; _deviceContext->GetDevice(&device); HRESULT hr = device->CreateBuffer(&bufferDesc, &subData, &_vbo); assert(_vbo); int numVertices = (int)getVboSource().size()/7; /* (x, y, r, g, b, u, v) = 7*/ // reserved space of the vector remains for the next frame. getVboSource().clear(); D3D11_MAPPED_SUBRESOURCE MappedResource; _deviceContext->Map(_constantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource); CB_HUD_PROJECTION * pData = (CB_HUD_PROJECTION *)MappedResource.pData; ortho(pData->mViewProjection, 0, 0, (float)GetWidth(), (float)GetHeight()); transpose(pData->mViewProjection); _deviceContext->Unmap( _constantBuffer, 0 ); // setup graphics pipeline _deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); _deviceContext->IASetInputLayout(_inputLayout); _deviceContext->VSSetShader(_vertexShader, NULL, 0); _deviceContext->HSSetShader(NULL, NULL, 0); _deviceContext->DSSetShader(NULL, NULL, 0); _deviceContext->GSSetShader(NULL, NULL, 0); _deviceContext->PSSetShader(_pixelShader, NULL, 0); _deviceContext->PSSetShaderResources(0, 1, &_shaderResourceView); _deviceContext->PSSetSamplers(0, 1, &_samplerState); _deviceContext->RSSetState(_rasterizerState); _deviceContext->VSSetConstantBuffers(0, 1, &_constantBuffer); UINT strides = 7*sizeof(float); UINT offsets = 0; _deviceContext->IASetVertexBuffers(0, 1, &_vbo, &strides, &offsets); _deviceContext->Draw(numVertices, 0); _deviceContext->IASetVertexBuffers(0, 1, &_staticVbo, &strides, &offsets); _deviceContext->Draw(_staticVboCount, 0); return true; }