From f127ac3801097eb02546f2b77b6639f488e7b305 Mon Sep 17 00:00:00 2001 From: kotofyt Date: Mon, 25 May 2026 01:35:19 +0300 Subject: [PATCH] added font rendering --- build.cpp | 3 +- engine/engine.cpp | 2 + engine/kottui.cpp | 396 +++++++++++++++++- external/funnystdlib | 2 +- funnyassets/fonts/IBMPlexMono-Regular.fmd | 1 + .../fonts/IBMPlexMono-Regular.fontdata | 2 - funnyassets/fonts/IBMPlexMono-Regular.png | Bin 18198 -> 45810 bytes funnyassets/shaders/kottui.shader | 85 ++++ funnyassets/shaders/mesh_raster.shader | 3 +- game/client/assetmgr.cpp | 1 + game/client/entitysystem.cpp | 10 +- game/client/game.cpp | 18 + game/client/milmoba/player.cpp | 2 +- game/client/worldrender.cpp | 5 + game/shared/game.h | 2 + materialsystem/vulkan/commands/draw.cpp | 21 +- materialsystem/vulkan/material.cpp | 43 ++ materialsystem/vulkan/rendercommandlist.cpp | 9 + materialsystem/vulkan/rendercontext.cpp | 42 +- materialsystem/vulkan/vulkan_state.h | 13 + public/cl_entity.h | 0 public/imouseinput.h | 0 public/jsonformat.h | 0 public/kottui/kottui.h | 29 +- public/materialsystem/imaterialsystem.h | 11 + public/sv_entity.h | 0 shadercompiler/psMain | Bin 2724 -> 2688 bytes 27 files changed, 657 insertions(+), 43 deletions(-) create mode 100644 funnyassets/fonts/IBMPlexMono-Regular.fmd delete mode 100644 funnyassets/fonts/IBMPlexMono-Regular.fontdata create mode 100644 funnyassets/shaders/kottui.shader delete mode 100644 public/cl_entity.h delete mode 100644 public/imouseinput.h delete mode 100644 public/jsonformat.h delete mode 100644 public/sv_entity.h diff --git a/build.cpp b/build.cpp index ab1a675..26cc3f3 100755 --- a/build.cpp +++ b/build.cpp @@ -38,15 +38,16 @@ DECLARE_BUILD_STAGE(install_game) if ( GET_PROJECT_VALUE(config, "bundle") == "true" ) { return 0; } + filesystem2->CopyFile(szOutputDir, GET_PROJECT_OBJECT(launcher, "launcher")); filesystem2->MakeDirectory(CUtlString("%s/core/",szOutputDir.GetString())); - filesystem2->CopyFile(szOutputDir, GET_PROJECT_OBJECT(launcher, "launcher")); filesystem2->CopyDirectory(CUtlString("%s/core/",szOutputDir.GetString()), "funnyassets/maps"); filesystem2->CopyDirectory(CUtlString("%s/core/",szOutputDir.GetString()), "funnyassets/models"); filesystem2->CopyDirectory(CUtlString("%s/core/",szOutputDir.GetString()), "funnyassets/meshes"); filesystem2->CopyDirectory(CUtlString("%s/core/",szOutputDir.GetString()), "funnyassets/materials"); filesystem2->CopyDirectory(CUtlString("%s/core/",szOutputDir.GetString()), "funnyassets/textures"); filesystem2->CopyDirectory(CUtlString("%s/core/",szOutputDir.GetString()), "funnyassets/physics"); + filesystem2->CopyDirectory(CUtlString("%s/core/",szOutputDir.GetString()), "funnyassets/fonts"); filesystem2->CopyFile(CUtlString("%s/core/",szOutputDir.GetString()), "funnyassets/default.cfg"); filesystem2->CopyDirectory(CUtlString("%s/core/",szOutputDir.GetString()), "build/funnygame/assets/shaders"); if (Target_t::DefaultTarget().kernel == TARGET_KERNEL_WINDOWS) diff --git a/engine/engine.cpp b/engine/engine.cpp index ba2fb5f..17ca51f 100644 --- a/engine/engine.cpp +++ b/engine/engine.cpp @@ -158,6 +158,8 @@ extern "C" void FunnyMain( int argc, char **argv ) fCurrent = Plat_GetTime(); }; + Plat_Exit(0); + g_pClientGame->Shutdown(); g_pServerGame->Shutdown(); g_pRenderContext->Shutdown(); diff --git a/engine/kottui.cpp b/engine/kottui.cpp index 77dbd80..7f02679 100644 --- a/engine/kottui.cpp +++ b/engine/kottui.cpp @@ -1,23 +1,399 @@ #include "kottui/kottui.h" +#include "tier0/lib.h" +#include "tier0/mem.h" +#include "tier1/utlstring.h" +#include "tier2/ifilesystem.h" +#include "tier2/fileformats/json.h" +#include "trig.h" + +struct GlyphData_t +{ + uint32_t m_uCharacter; + float m_fX; + float m_fY; + float m_fWidth; + float m_fHeight; +}; + +class CKotRenderFont: public IKotRenderFont +{ +public: + virtual IImage *GetAtlas() override; + virtual bool IsLetterPresent( uint32_t letter ) override; + virtual float GetLetterX( uint32_t letter ) override; + virtual float GetLetterY( uint32_t letter ) override; + virtual float GetWidth( uint32_t letter ) override; + virtual float GetHeight( uint32_t letter ) override; + + virtual bool IsMono() override; + virtual uint32_t GetLetterWidth() override; + virtual uint32_t GetLetterHeight() override; + + GlyphData_t *m_glyphs; + uint32_t m_uGlyphCount; + IImage *m_pAtlas; +}; class CKotUIBuffer: public IKotUIBuffer { public: - virtual void SetColor( char c ) = 0; - virtual void SetPosition( int iY, int iX ) = 0; - virtual void Printf(const char *szFormat, ...) = 0; - virtual void PutChar( char c ) = 0; - virtual void Clear( char c ) = 0; + virtual void SetPosition( int iY, int iX ) override; + + virtual void Move( int iY, int iX ) override; + + virtual void SetColor( char c ) override; + virtual void Clear( char c ) override; + + virtual void PutChar( char c ) override; + virtual void Printf(const char *szFormat, ...) override; + + virtual void Draw( IImage *pImage ) override; + + virtual void SetTextSize( int iY, int iX ) override; + virtual void SetTextFont( IKotRenderFont *pFont ) override; + + uint32_t *m_buffer; + ColorAlpha *m_primaryColor; + ColorAlpha *m_secondaryColor; + int m_iWidth = 0; + int m_iHeight = 0; + IBuffer *m_pDataBuffer; + + IMaterial *m_pMaterial; + IRenderContext *m_pRenderContext; + IKotRenderFont *m_pFont; + + uint32_t m_uCursor = 0; }; class CKotUIManager: public IKotUIManager { public: - virtual void SetTextSize( int iY, int iX ) = 0; - virtual void SetTextFont( IRenderFont *pFont ) = 0; + virtual void Init() override; + virtual void Shutdown() override; + virtual void ConnectInterface( void *pIface, const char *szName ) override; - virtual void CreateBuffer( int iWidth, int iHeight, int iY, int iX ) = 0; - virtual void Draw( IRenderContext *pRenderContext ); + virtual IKotRenderFont *LoadFont( const char *szPath ) override; + + virtual IKotUIBuffer *CreateBuffer( int iWidth, int iHeight ) override; + virtual void DeleteBuffer( IKotUIBuffer *pBuffer ) override; + + + IRenderContext *m_pRenderContext; + ITextureArray *m_pFonts; }; -IKotUIManager *KotUIManager(); +static IShader *s_pShader; +static CKotUIManager s_kotUIManager; +static IVertexBuffer *s_pGlyphBuffer; + +IKotUIManager *KotUIManager() +{ + return &s_kotUIManager; +} +EXPOSE_INTERFACE_FN(KotUIManager, IKotUIManager, KOT_UI_INTEFACE_VERSION); + +IImage *CKotRenderFont::GetAtlas() +{ + return m_pAtlas; +} + +bool CKotRenderFont::IsLetterPresent( uint32_t letter ) +{ + for ( int i = 0; i < m_uGlyphCount; i++ ) + { + GlyphData_t g = m_glyphs[i]; + if (g.m_uCharacter == letter) + return true; + } + return false; +} + +float CKotRenderFont::GetLetterX( uint32_t letter ) +{ + for ( int i = 0; i < m_uGlyphCount; i++ ) + { + GlyphData_t g = m_glyphs[i]; + if (g.m_uCharacter == letter) + return g.m_fX; + } + return 0; +} + +float CKotRenderFont::GetLetterY( uint32_t letter ) +{ + for ( int i = 0; i < m_uGlyphCount; i++ ) + { + GlyphData_t g = m_glyphs[i]; + if (g.m_uCharacter == letter) + return g.m_fY; + } + return 0; +} + +float CKotRenderFont::GetWidth( uint32_t letter ) +{ + for ( int i = 0; i < m_uGlyphCount; i++ ) + { + GlyphData_t g = m_glyphs[i]; + if (g.m_uCharacter == letter) + return g.m_fWidth; + } + return 0; +} + +float CKotRenderFont::GetHeight( uint32_t letter ) +{ + for ( int i = 0; i < m_uGlyphCount; i++ ) + { + GlyphData_t g = m_glyphs[i]; + if (g.m_uCharacter == letter) + return g.m_fHeight; + } + return 0; +} + + + +void CKotUIBuffer::SetPosition( int iY, int iX ) +{ + +} + +void CKotUIBuffer::Move( int iY, int iX ) +{ + m_uCursor = iY*m_iWidth+iX; + m_uCursor = m_uCursor % (m_iWidth * m_iHeight); +} + +void CKotUIBuffer::SetColor( char c ) +{ + +} + +void CKotUIBuffer::Clear( char c ) +{ + +} + +void CKotUIBuffer::PutChar( char c ) +{ + m_buffer[m_uCursor] = c; + Move(0, m_uCursor+1); + +} + +void CKotUIBuffer::Printf(const char *szFormat, ...) +{ + + va_list vlArgs; + va_start(vlArgs, szFormat); + va_list vlArgs2; + va_copy(vlArgs2, vlArgs); + + size_t nSize = V_vsnprintf(NULL, 0, szFormat, vlArgs2); + va_end(vlArgs2); + char *psz = (char*)V_malloc(nSize+1); + va_copy(vlArgs2, vlArgs); + V_vsnprintf(psz, nSize+1, szFormat, vlArgs2); + for ( size_t u = 0, i = m_uCursor; u < nSize; u++, i = (i + 1 % (m_iWidth * m_iHeight)) ) + { + m_buffer[i] = psz[u]; + } + va_end(vlArgs2); + V_free(psz); + va_end(vlArgs); + Move(0, m_uCursor+1); + +} + +struct TextDrawData_t +{ + float m_vTexcoordOffsetX; + float m_vTexcoordOffsetY; + float m_vTexcoordSizeX; + float m_vTexcoordSizeY; + float m_fPosX; + float m_fPosY; + float m_fSizeX; + float m_fSizeY; + float m_fColor[4]; + float m_fColor2[4]; +}; + +struct ScreenData_t +{ + float m_fScreenSizeX; + float m_fScreenSizeY; +}; + +void CKotUIBuffer::Draw( IImage *pImage ) +{ + uint32_t uGlyphCount = m_iWidth*m_iHeight; + uint32_t uRealGlyphCount = 0; + + IRenderCommandList *pList = m_pRenderContext->CreateCommandList(); + pList->StartRecording(); + + m_pDataBuffer->Lock(); + TextDrawData_t *pData = (TextDrawData_t*)m_pDataBuffer->Map(); + for ( uint32_t i = 0; i < uGlyphCount; i++ ) + { + uint32_t l = m_buffer[i]; + if ( !m_pFont->IsLetterPresent(l) ) + continue; + pData[uRealGlyphCount].m_vTexcoordOffsetX = m_pFont->GetLetterX(l); + pData[uRealGlyphCount].m_vTexcoordOffsetY = m_pFont->GetLetterY(l); + pData[uRealGlyphCount].m_vTexcoordSizeX = m_pFont->GetWidth(l); + pData[uRealGlyphCount].m_vTexcoordSizeY = m_pFont->GetHeight(l); + pData[uRealGlyphCount].m_fSizeX = 16; + pData[uRealGlyphCount].m_fSizeY = 16; + pData[uRealGlyphCount].m_fPosX = i%m_iWidth*16; + pData[uRealGlyphCount].m_fPosY = i/m_iWidth*16; + uRealGlyphCount++; + } + m_pDataBuffer->Unmap(); + m_pDataBuffer->Unlock(); + + IBuffer *pScreenBuffer = m_pRenderContext->CreateConstantBuffer(sizeof(ScreenData_t)); + pScreenBuffer->Lock(); + ScreenData_t *pScreenData = (ScreenData_t*)pScreenBuffer->Map(); + pScreenData->m_fScreenSizeX = pImage->GetImageWidth(); + pScreenData->m_fScreenSizeY = pImage->GetImageHeight(); + pScreenBuffer->Unmap(); + pScreenBuffer->Unlock(); + + m_pMaterial = m_pRenderContext->CreateMaterial(s_pShader); + m_pMaterial->PSSetShaderResource(0, m_pDataBuffer); + m_pMaterial->PSSetShaderResource(1, pScreenBuffer); + m_pMaterial->PSSetTexture(2, m_pFont->GetAtlas()); + m_pMaterial->PSSetSampler(3, m_pRenderContext->GetDefaultSampler()); + + + pList->SetRenderTarget(0, pImage); + pList->SetLoadStoreModes(0, LOAD_MODE_LOAD, STORE_MODE_STORE); + pList->SetRenderResolution(pImage->GetImageWidth(), pImage->GetImageHeight()); + + pList->SetMaterial(m_pMaterial); + pList->SetVertexBuffer(0, s_pGlyphBuffer); + pList->DrawPrimitives(6, 0, uRealGlyphCount, 0); + + pList->EndRecording(); + m_pRenderContext->SubmitCommandList(pList); + +} + +void CKotUIBuffer::SetTextSize( int iY, int iX ) +{ + + +} + +void CKotUIBuffer::SetTextFont( IKotRenderFont *pFont ) +{ + m_pFont = pFont; + +} + + +void CKotUIManager::Init() +{ + s_pShader = m_pRenderContext->CreateShader("game/core/shaders/kottui.shader_c"); + s_pShader->AddLayout(0, 8); + s_pShader->AddAttribute(0, 0, VERTEX_FORMAT_XY32_SFLOAT, 0); + s_pShader->AddOutputImage(0, IMAGE_FORMAT_RGBA8_UNORM); + s_pShader->Build(); + s_pGlyphBuffer = m_pRenderContext->CreateVertexBuffer(sizeof(float)*12); + void *pBuffer = s_pGlyphBuffer->Map(); + float vertices[12] = { + 0, 0, + 0, 1, + 1, 0, + 1, 0, + 0, 1, + 1, 1, + }; + V_memcpy(pBuffer, vertices, sizeof(vertices)); + s_pGlyphBuffer->Unmap(); + + m_pFonts = m_pRenderContext->CreateTextureArray(); + + +} + +void CKotUIManager::Shutdown() +{ + +} + +void CKotUIManager::ConnectInterface( void *pFace, const char *psz ) +{ + if (!V_strcmp(psz, RENDER_CONTEXT_INTERFACE_VERSION)) + m_pRenderContext = (IRenderContext*)pFace; +} + +IKotRenderFont *CKotUIManager::LoadFont( const char *szPath ) +{ + CUtlString szAtlas = CUtlString("%s.png", szPath); + CUtlString szMeta = CUtlString("%s.fmd", szPath); + + IFileHandle *pMetadataFile = filesystem->Open(szMeta, FILEMODE_READ); + if (!pMetadataFile) + return NULL; + const char *szMetadata = filesystem->ReadString(pMetadataFile); + filesystem->Close(pMetadataFile); + + + IJSONValue *pValue = JSONManager()->ReadString(szMetadata); + IJSONArray *pGlyphs = pValue->GetObject()->GetValue("glyphs")->GetArray(); + uint32_t uAtlas = m_pFonts->LoadTexture(szAtlas); + + CKotRenderFont *pFont = new CKotRenderFont; + pFont->m_pAtlas = pFont->m_pAtlas = m_pFonts->GetTexture(uAtlas); + uint32_t atlasWidth = pValue->GetObject()->GetValue("atlas")->GetObject()->GetValue("width")->GetNumberValue(); + uint32_t atlasHeight = pValue->GetObject()->GetValue("atlas")->GetObject()->GetValue("height")->GetNumberValue(); + + pFont->m_uGlyphCount = 0; + pFont->m_glyphs = (GlyphData_t*)V_malloc(sizeof(GlyphData_t)*pGlyphs->GetCount()); + for ( uint32_t i = 0; i < pGlyphs->GetCount(); i++ ) + { + GlyphData_t glyph = {}; + IJSONObject *pGlyph = pGlyphs->GetParameter(i)->GetObject(); + if (pGlyph->GetValue("atlasBounds") == NULL) + continue; + IJSONObject *pAtlasBounds = pGlyph->GetValue("atlasBounds")->GetObject(); + glyph.m_uCharacter = pGlyph->GetValue("unicode")->GetNumberValue(); + glyph.m_fX = pAtlasBounds->GetValue("left")->GetNumberValue()/atlasWidth; + glyph.m_fY = 1-(pAtlasBounds->GetValue("bottom")->GetNumberValue()/atlasHeight); + glyph.m_fWidth = ( + pAtlasBounds->GetValue("right")->GetNumberValue() + - pAtlasBounds->GetValue("left")->GetNumberValue() + ) / atlasWidth; + glyph.m_fHeight = ( + pAtlasBounds->GetValue("bottom")->GetNumberValue() + - pAtlasBounds->GetValue("top")->GetNumberValue() + ) / atlasHeight; + pFont->m_glyphs[pFont->m_uGlyphCount++] = glyph; + } + return pFont; + +} + +IKotUIBuffer *CKotUIManager::CreateBuffer( int iWidth, int iHeight ) +{ + CKotUIBuffer *pBuffer = new CKotUIBuffer; + pBuffer->m_pRenderContext = m_pRenderContext; + pBuffer->m_buffer = (uint32_t*)V_malloc(sizeof(uint32_t)*iWidth*iHeight); + V_memset(pBuffer->m_buffer, 0, sizeof(uint32_t)*iWidth*iHeight); + pBuffer->m_iWidth = iWidth; + pBuffer->m_iHeight = iHeight; + + pBuffer->m_pDataBuffer = m_pRenderContext->CreateStorageBuffer(sizeof(TextDrawData_t)*iWidth*iHeight); + return pBuffer; +} + +void CKotUIManager::DeleteBuffer( IKotUIBuffer *pBuffer ) +{ + +} + diff --git a/external/funnystdlib b/external/funnystdlib index 8f8343e..4a2e606 160000 --- a/external/funnystdlib +++ b/external/funnystdlib @@ -1 +1 @@ -Subproject commit 8f8343e2506a7ec51b8cb644e050f789614a803e +Subproject commit 4a2e606e2bf37fb1e5da2bcc4ba1d7709eee4d08 diff --git a/funnyassets/fonts/IBMPlexMono-Regular.fmd b/funnyassets/fonts/IBMPlexMono-Regular.fmd new file mode 100644 index 0000000..32aa92c --- /dev/null +++ b/funnyassets/fonts/IBMPlexMono-Regular.fmd @@ -0,0 +1 @@ +{"atlas":{"type":"msdf","distanceRange":2,"distanceRangeMiddle":0,"size":32.25,"width":264,"height":288,"yOrigin":"bottom","grid":{"cellWidth":22,"cellHeight":36,"columns":12,"rows":8,"originY":0.26356589147286824}},"metrics":{"emSize":1,"lineHeight":1.3,"ascender":1.0249999999999999,"descender":-0.27500000000000002,"underlineY":-0.17000000000000001,"underlineThickness":0.059999999999999998},"glyphs":[{"unicode":32,"advance":0.59999999999999998},{"unicode":33,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837219,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":0.5,"bottom":252.5,"right":21.5,"top":287.5}},{"unicode":34,"advance":0.59999999999999998,"planeBounds":{"left":-0.025081395348837191,"bottom":-0.26356589147286819,"right":0.62608139534883722,"top":0.82170542635658905},"atlasBounds":{"left":22.5,"bottom":252.5,"right":43.5,"top":287.5}},{"unicode":35,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837192,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":44.5,"bottom":252.5,"right":65.5,"top":287.5}},{"unicode":36,"advance":0.59999999999999998,"planeBounds":{"left":-0.024581395348837225,"bottom":-0.26356589147286819,"right":0.62658139534883717,"top":0.82170542635658905},"atlasBounds":{"left":66.5,"bottom":252.5,"right":87.5,"top":287.5}},{"unicode":37,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837205,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":88.5,"bottom":252.5,"right":109.5,"top":287.5}},{"unicode":38,"advance":0.59999999999999998,"planeBounds":{"left":-0.0270813953488372,"bottom":-0.26356589147286819,"right":0.62408139534883722,"top":0.82170542635658905},"atlasBounds":{"left":110.5,"bottom":252.5,"right":131.5,"top":287.5}},{"unicode":39,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837192,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":132.5,"bottom":252.5,"right":153.5,"top":287.5}},{"unicode":40,"advance":0.59999999999999998,"planeBounds":{"left":0.023918604651162783,"bottom":-0.26356589147286819,"right":0.67508139534883715,"top":0.82170542635658905},"atlasBounds":{"left":154.5,"bottom":252.5,"right":175.5,"top":287.5}},{"unicode":41,"advance":0.59999999999999998,"planeBounds":{"left":-0.075081395348837218,"bottom":-0.26356589147286819,"right":0.57608139534883718,"top":0.82170542635658905},"atlasBounds":{"left":176.5,"bottom":252.5,"right":197.5,"top":287.5}},{"unicode":42,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837219,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":198.5,"bottom":252.5,"right":219.5,"top":287.5}},{"unicode":43,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837219,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":220.5,"bottom":252.5,"right":241.5,"top":287.5}},{"unicode":44,"advance":0.59999999999999998,"planeBounds":{"left":-0.030581395348837193,"bottom":-0.26356589147286819,"right":0.62058139534883716,"top":0.82170542635658905},"atlasBounds":{"left":242.5,"bottom":252.5,"right":263.5,"top":287.5}},{"unicode":45,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837192,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":0.5,"bottom":216.5,"right":21.5,"top":251.5}},{"unicode":46,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837219,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":22.5,"bottom":216.5,"right":43.5,"top":251.5}},{"unicode":47,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837205,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":44.5,"bottom":216.5,"right":65.5,"top":251.5}},{"unicode":48,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837219,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":66.5,"bottom":216.5,"right":87.5,"top":251.5}},{"unicode":49,"advance":0.59999999999999998,"planeBounds":{"left":-0.022581395348837206,"bottom":-0.26356589147286819,"right":0.62858139534883717,"top":0.82170542635658905},"atlasBounds":{"left":88.5,"bottom":216.5,"right":109.5,"top":251.5}},{"unicode":50,"advance":0.59999999999999998,"planeBounds":{"left":-0.024581395348837191,"bottom":-0.26356589147286819,"right":0.62658139534883717,"top":0.82170542635658905},"atlasBounds":{"left":110.5,"bottom":216.5,"right":131.5,"top":251.5}},{"unicode":51,"advance":0.59999999999999998,"planeBounds":{"left":-0.042581395348837217,"bottom":-0.26356589147286819,"right":0.60858139534883715,"top":0.82170542635658905},"atlasBounds":{"left":132.5,"bottom":216.5,"right":153.5,"top":251.5}},{"unicode":52,"advance":0.59999999999999998,"planeBounds":{"left":-0.027581395348837228,"bottom":-0.26356589147286819,"right":0.62358139534883716,"top":0.82170542635658905},"atlasBounds":{"left":154.5,"bottom":216.5,"right":175.5,"top":251.5}},{"unicode":53,"advance":0.59999999999999998,"planeBounds":{"left":-0.022581395348837192,"bottom":-0.26356589147286819,"right":0.62858139534883717,"top":0.82170542635658905},"atlasBounds":{"left":176.5,"bottom":216.5,"right":197.5,"top":251.5}},{"unicode":54,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837192,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":198.5,"bottom":216.5,"right":219.5,"top":251.5}},{"unicode":55,"advance":0.59999999999999998,"planeBounds":{"left":-0.02758139534883719,"bottom":-0.26356589147286819,"right":0.62358139534883716,"top":0.82170542635658905},"atlasBounds":{"left":220.5,"bottom":216.5,"right":241.5,"top":251.5}},{"unicode":56,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837178,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":242.5,"bottom":216.5,"right":263.5,"top":251.5}},{"unicode":57,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837192,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":0.5,"bottom":180.5,"right":21.5,"top":215.5}},{"unicode":58,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837219,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":22.5,"bottom":180.5,"right":43.5,"top":215.5}},{"unicode":59,"advance":0.59999999999999998,"planeBounds":{"left":-0.030581395348837193,"bottom":-0.26356589147286819,"right":0.62058139534883716,"top":0.82170542635658905},"atlasBounds":{"left":44.5,"bottom":180.5,"right":65.5,"top":215.5}},{"unicode":60,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837205,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":66.5,"bottom":180.5,"right":87.5,"top":215.5}},{"unicode":61,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837219,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":88.5,"bottom":180.5,"right":109.5,"top":215.5}},{"unicode":62,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837205,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":110.5,"bottom":180.5,"right":131.5,"top":215.5}},{"unicode":63,"advance":0.59999999999999998,"planeBounds":{"left":-0.032081395348837208,"bottom":-0.26356589147286819,"right":0.61908139534883722,"top":0.82170542635658905},"atlasBounds":{"left":132.5,"bottom":180.5,"right":153.5,"top":215.5}},{"unicode":64,"advance":0.59999999999999998,"planeBounds":{"left":-0.032081395348837194,"bottom":-0.26356589147286819,"right":0.61908139534883722,"top":0.82170542635658905},"atlasBounds":{"left":154.5,"bottom":180.5,"right":175.5,"top":215.5}},{"unicode":65,"advance":0.59999999999999998,"planeBounds":{"left":-0.025081395348837184,"bottom":-0.26356589147286819,"right":0.62608139534883722,"top":0.82170542635658905},"atlasBounds":{"left":176.5,"bottom":180.5,"right":197.5,"top":215.5}},{"unicode":66,"advance":0.59999999999999998,"planeBounds":{"left":-0.010081395348837176,"bottom":-0.26356589147286819,"right":0.64108139534883724,"top":0.82170542635658905},"atlasBounds":{"left":198.5,"bottom":180.5,"right":219.5,"top":215.5}},{"unicode":67,"advance":0.59999999999999998,"planeBounds":{"left":-0.021581395348837205,"bottom":-0.26356589147286819,"right":0.62958139534883717,"top":0.82170542635658905},"atlasBounds":{"left":220.5,"bottom":180.5,"right":241.5,"top":215.5}},{"unicode":68,"advance":0.59999999999999998,"planeBounds":{"left":-0.0060813953488371769,"bottom":-0.26356589147286819,"right":0.64508139534883724,"top":0.82170542635658905},"atlasBounds":{"left":242.5,"bottom":180.5,"right":263.5,"top":215.5}},{"unicode":69,"advance":0.59999999999999998,"planeBounds":{"left":-0.020581395348837205,"bottom":-0.26356589147286819,"right":0.63058139534883717,"top":0.82170542635658905},"atlasBounds":{"left":0.5,"bottom":144.5,"right":21.5,"top":179.5}},{"unicode":70,"advance":0.59999999999999998,"planeBounds":{"left":-0.015581395348837191,"bottom":-0.26356589147286819,"right":0.63558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":22.5,"bottom":144.5,"right":43.5,"top":179.5}},{"unicode":71,"advance":0.59999999999999998,"planeBounds":{"left":-0.036581395348837191,"bottom":-0.26356589147286819,"right":0.61458139534883716,"top":0.82170542635658905},"atlasBounds":{"left":44.5,"bottom":144.5,"right":65.5,"top":179.5}},{"unicode":72,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837192,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":66.5,"bottom":144.5,"right":87.5,"top":179.5}},{"unicode":73,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837205,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":88.5,"bottom":144.5,"right":109.5,"top":179.5}},{"unicode":74,"advance":0.59999999999999998,"planeBounds":{"left":-0.048581395348837195,"bottom":-0.26356589147286819,"right":0.60258139534883726,"top":0.82170542635658905},"atlasBounds":{"left":110.5,"bottom":144.5,"right":131.5,"top":179.5}},{"unicode":75,"advance":0.59999999999999998,"planeBounds":{"left":0.0059186046511628234,"bottom":-0.26356589147286819,"right":0.65708139534883725,"top":0.82170542635658905},"atlasBounds":{"left":132.5,"bottom":144.5,"right":153.5,"top":179.5}},{"unicode":76,"advance":0.59999999999999998,"planeBounds":{"left":0.0019186046511628092,"bottom":-0.26356589147286819,"right":0.65308139534883725,"top":0.82170542635658905},"atlasBounds":{"left":154.5,"bottom":144.5,"right":175.5,"top":179.5}},{"unicode":77,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837233,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":176.5,"bottom":144.5,"right":197.5,"top":179.5}},{"unicode":78,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837192,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":198.5,"bottom":144.5,"right":219.5,"top":179.5}},{"unicode":79,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837219,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":220.5,"bottom":144.5,"right":241.5,"top":179.5}},{"unicode":80,"advance":0.59999999999999998,"planeBounds":{"left":-0.0090813953488372186,"bottom":-0.26356589147286819,"right":0.64208139534883724,"top":0.82170542635658905},"atlasBounds":{"left":242.5,"bottom":144.5,"right":263.5,"top":179.5}},{"unicode":81,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837219,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":0.5,"bottom":108.5,"right":21.5,"top":143.5}},{"unicode":82,"advance":0.59999999999999998,"planeBounds":{"left":-0.0060813953488372055,"bottom":-0.26356589147286819,"right":0.64508139534883724,"top":0.82170542635658905},"atlasBounds":{"left":22.5,"bottom":108.5,"right":43.5,"top":143.5}},{"unicode":83,"advance":0.59999999999999998,"planeBounds":{"left":-0.032081395348837208,"bottom":-0.26356589147286819,"right":0.61908139534883722,"top":0.82170542635658905},"atlasBounds":{"left":44.5,"bottom":108.5,"right":65.5,"top":143.5}},{"unicode":84,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837199,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":66.5,"bottom":108.5,"right":87.5,"top":143.5}},{"unicode":85,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837192,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":88.5,"bottom":108.5,"right":109.5,"top":143.5}},{"unicode":86,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837226,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":110.5,"bottom":108.5,"right":131.5,"top":143.5}},{"unicode":87,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837192,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":132.5,"bottom":108.5,"right":153.5,"top":143.5}},{"unicode":88,"advance":0.59999999999999998,"planeBounds":{"left":-0.025081395348837212,"bottom":-0.26356589147286819,"right":0.62608139534883722,"top":0.82170542635658905},"atlasBounds":{"left":154.5,"bottom":108.5,"right":175.5,"top":143.5}},{"unicode":89,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837219,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":176.5,"bottom":108.5,"right":197.5,"top":143.5}},{"unicode":90,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837185,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":198.5,"bottom":108.5,"right":219.5,"top":143.5}},{"unicode":91,"advance":0.59999999999999998,"planeBounds":{"left":0.039418604651162779,"bottom":-0.26356589147286819,"right":0.69058139534883722,"top":0.82170542635658905},"atlasBounds":{"left":220.5,"bottom":108.5,"right":241.5,"top":143.5}},{"unicode":92,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837205,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":242.5,"bottom":108.5,"right":263.5,"top":143.5}},{"unicode":93,"advance":0.59999999999999998,"planeBounds":{"left":-0.090581395348837218,"bottom":-0.26356589147286819,"right":0.56058139534883722,"top":0.82170542635658905},"atlasBounds":{"left":0.5,"bottom":72.5,"right":21.5,"top":107.5}},{"unicode":94,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837185,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":22.5,"bottom":72.5,"right":43.5,"top":107.5}},{"unicode":95,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837205,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":44.5,"bottom":72.5,"right":65.5,"top":107.5}},{"unicode":96,"advance":0.59999999999999998,"planeBounds":{"left":-0.059581395348837191,"bottom":-0.26356589147286819,"right":0.59158139534883725,"top":0.82170542635658905},"atlasBounds":{"left":66.5,"bottom":72.5,"right":87.5,"top":107.5}},{"unicode":97,"advance":0.59999999999999998,"planeBounds":{"left":-0.017581395348837178,"bottom":-0.26356589147286819,"right":0.63358139534883717,"top":0.82170542635658905},"atlasBounds":{"left":88.5,"bottom":72.5,"right":109.5,"top":107.5}},{"unicode":98,"advance":0.59999999999999998,"planeBounds":{"left":-0.0080813953488372055,"bottom":-0.26356589147286819,"right":0.64308139534883724,"top":0.82170542635658905},"atlasBounds":{"left":110.5,"bottom":72.5,"right":131.5,"top":107.5}},{"unicode":99,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837205,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":132.5,"bottom":72.5,"right":153.5,"top":107.5}},{"unicode":100,"advance":0.59999999999999998,"planeBounds":{"left":-0.043081395348837204,"bottom":-0.26356589147286819,"right":0.60808139534883721,"top":0.82170542635658905},"atlasBounds":{"left":154.5,"bottom":72.5,"right":175.5,"top":107.5}},{"unicode":101,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837192,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":176.5,"bottom":72.5,"right":197.5,"top":107.5}},{"unicode":102,"advance":0.59999999999999998,"planeBounds":{"left":-0.017081395348837205,"bottom":-0.26356589147286819,"right":0.63408139534883723,"top":0.82170542635658905},"atlasBounds":{"left":198.5,"bottom":72.5,"right":219.5,"top":107.5}},{"unicode":103,"advance":0.59999999999999998,"planeBounds":{"left":-0.011581395348837212,"bottom":-0.26356589147286819,"right":0.63958139534883718,"top":0.82170542635658905},"atlasBounds":{"left":220.5,"bottom":72.5,"right":241.5,"top":107.5}},{"unicode":104,"advance":0.59999999999999998,"planeBounds":{"left":-0.022581395348837206,"bottom":-0.26356589147286819,"right":0.62858139534883717,"top":0.82170542635658905},"atlasBounds":{"left":242.5,"bottom":72.5,"right":263.5,"top":107.5}},{"unicode":105,"advance":0.59999999999999998,"planeBounds":{"left":0.00041860465116280921,"bottom":-0.26356589147286819,"right":0.65158139534883719,"top":0.82170542635658905},"atlasBounds":{"left":0.5,"bottom":36.5,"right":21.5,"top":71.5}},{"unicode":106,"advance":0.59999999999999998,"planeBounds":{"left":-0.05158139534883719,"bottom":-0.26356589147286819,"right":0.59958139534883725,"top":0.82170542635658905},"atlasBounds":{"left":22.5,"bottom":36.5,"right":43.5,"top":71.5}},{"unicode":107,"advance":0.59999999999999998,"planeBounds":{"left":0.013918604651162809,"bottom":-0.26356589147286819,"right":0.66508139534883726,"top":0.82170542635658905},"atlasBounds":{"left":44.5,"bottom":36.5,"right":65.5,"top":71.5}},{"unicode":108,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837192,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":66.5,"bottom":36.5,"right":87.5,"top":71.5}},{"unicode":109,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837192,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":88.5,"bottom":36.5,"right":109.5,"top":71.5}},{"unicode":110,"advance":0.59999999999999998,"planeBounds":{"left":-0.022581395348837206,"bottom":-0.26356589147286819,"right":0.62858139534883717,"top":0.82170542635658905},"atlasBounds":{"left":110.5,"bottom":36.5,"right":131.5,"top":71.5}},{"unicode":111,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837205,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":132.5,"bottom":36.5,"right":153.5,"top":71.5}},{"unicode":112,"advance":0.59999999999999998,"planeBounds":{"left":-0.0080813953488372055,"bottom":-0.26356589147286819,"right":0.64308139534883724,"top":0.82170542635658905},"atlasBounds":{"left":154.5,"bottom":36.5,"right":175.5,"top":71.5}},{"unicode":113,"advance":0.59999999999999998,"planeBounds":{"left":-0.043081395348837204,"bottom":-0.26356589147286819,"right":0.60808139534883721,"top":0.82170542635658905},"atlasBounds":{"left":176.5,"bottom":36.5,"right":197.5,"top":71.5}},{"unicode":114,"advance":0.59999999999999998,"planeBounds":{"left":-0.007581395348837219,"bottom":-0.26356589147286819,"right":0.64358139534883718,"top":0.82170542635658905},"atlasBounds":{"left":198.5,"bottom":36.5,"right":219.5,"top":71.5}},{"unicode":115,"advance":0.59999999999999998,"planeBounds":{"left":-0.030081395348837192,"bottom":-0.26356589147286819,"right":0.62108139534883722,"top":0.82170542635658905},"atlasBounds":{"left":220.5,"bottom":36.5,"right":241.5,"top":71.5}},{"unicode":116,"advance":0.59999999999999998,"planeBounds":{"left":-0.043081395348837176,"bottom":-0.26356589147286819,"right":0.60808139534883721,"top":0.82170542635658905},"atlasBounds":{"left":242.5,"bottom":36.5,"right":263.5,"top":71.5}},{"unicode":117,"advance":0.59999999999999998,"planeBounds":{"left":-0.028581395348837205,"bottom":-0.26356589147286819,"right":0.62258139534883716,"top":0.82170542635658905},"atlasBounds":{"left":0.5,"bottom":0.5,"right":21.5,"top":35.5}},{"unicode":118,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837192,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":22.5,"bottom":0.5,"right":43.5,"top":35.5}},{"unicode":119,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837219,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":44.5,"bottom":0.5,"right":65.5,"top":35.5}},{"unicode":120,"advance":0.59999999999999998,"planeBounds":{"left":-0.025081395348837219,"bottom":-0.26356589147286819,"right":0.62608139534883722,"top":0.82170542635658905},"atlasBounds":{"left":66.5,"bottom":0.5,"right":87.5,"top":35.5}},{"unicode":121,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837212,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":88.5,"bottom":0.5,"right":109.5,"top":35.5}},{"unicode":122,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837205,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":110.5,"bottom":0.5,"right":131.5,"top":35.5}},{"unicode":123,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837192,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":132.5,"bottom":0.5,"right":153.5,"top":35.5}},{"unicode":124,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837192,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":154.5,"bottom":0.5,"right":175.5,"top":35.5}},{"unicode":125,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837192,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":176.5,"bottom":0.5,"right":197.5,"top":35.5}},{"unicode":126,"advance":0.59999999999999998,"planeBounds":{"left":-0.025581395348837226,"bottom":-0.26356589147286819,"right":0.62558139534883717,"top":0.82170542635658905},"atlasBounds":{"left":198.5,"bottom":0.5,"right":219.5,"top":35.5}}],"kerning":[]} diff --git a/funnyassets/fonts/IBMPlexMono-Regular.fontdata b/funnyassets/fonts/IBMPlexMono-Regular.fontdata deleted file mode 100644 index c2541cb..0000000 --- a/funnyassets/fonts/IBMPlexMono-Regular.fontdata +++ /dev/null @@ -1,2 +0,0 @@ -12 8 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ - diff --git a/funnyassets/fonts/IBMPlexMono-Regular.png b/funnyassets/fonts/IBMPlexMono-Regular.png index dfef87f77c3446b6c37f2c0c870d5e332a0aac07..39753be76a3bc0f655fb3595437c91bd2b4246a8 100644 GIT binary patch literal 45810 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 SB`Sab0000gP)rfjm= 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 g_textData: register( t0 ); + cbuffer ScreenData_t: register( b1 ) + { + float2 g_vScreenSize; + } + Texture2D g_atlas: register( t2 ); + SamplerState g_atlasSampler: register(s3); +} +VS +{ + struct VS_INPUT + { + float2 m_vPosition: POSITION; + } + + + PS_INPUT vsMain( VS_INPUT input, uint uInstance: SV_InstanceID, uint uBaseInstance: SV_StartInstanceLocation ) + { + uint uInstance = uBaseInstance + uInstance; + float2 position = input.m_vPosition; + position*=g_textData[uInstance].m_vSize; + position+=g_textData[uInstance].m_vPos; + position/=g_vScreenSize; + position.y = 1-position.y; + position*=2; + position-=1; + float2 uv = input.m_vPosition; + uv.y = 1-uv.y; + uv*=g_textData[uInstance].m_vTexcoordSize; + uv+=g_textData[uInstance].m_vTexcoordOffset; + PS_INPUT output = {}; + output.m_vPosition = float4(position, 0, 1); + output.m_vUV = uv; + return output; + } + + +} +PS +{ + struct PS_OUTPUT + { + float4 m_vAlbedo: SV_Target0; + } + + float ScreenPixelRange( float2 uv ) + { + uint uWidth, uHeight; + g_atlas.GetDimensions(uWidth, uHeight); + float2 vUnitRange = 2.0/float2(uWidth, uHeight); + float2 vScreenTexSize = 1.0/fwidth(uv); + return max(0.5*dot(vUnitRange, vScreenTexSize), 1); + } + + PS_OUTPUT psMain( PS_INPUT input ) + { + PS_OUTPUT output = {}; + float4 vMsd = g_atlas.Sample(g_atlasSampler, input.m_vUV.xy); + float fSd = median3(vMsd.x, vMsd.y, vMsd.z); + float fScreenPixelDistance = ScreenPixelRange(input.m_vUV)*(fSd-0.5); + float fOpacity = clamp(fScreenPixelDistance+0.5, 0.0, 1.0); + output.m_vAlbedo = fOpacity; + return output; + } +} diff --git a/funnyassets/shaders/mesh_raster.shader b/funnyassets/shaders/mesh_raster.shader index 337cd65..c4561f0 100644 --- a/funnyassets/shaders/mesh_raster.shader +++ b/funnyassets/shaders/mesh_raster.shader @@ -90,8 +90,7 @@ PS if ( data.m_material.m_uAlbedo != -1 ) { output.m_vAlbedo = g_textures[data.m_material.m_uAlbedo] - .Sample(g_textureSampler, input.m_vTexCoord.xy) - * data.m_material.m_vAlbedoColor; + .Sample(g_textureSampler, input.m_vTexCoord.xy); } else { diff --git a/game/client/assetmgr.cpp b/game/client/assetmgr.cpp index 2d16d9d..a2369fb 100644 --- a/game/client/assetmgr.cpp +++ b/game/client/assetmgr.cpp @@ -10,6 +10,7 @@ #define MAX_SHADER_COUNT 1024 #define MAX_PHYSICS_COUNT 1024 +#define MAX_FONT_COUNT 128 template class CAssetArc diff --git a/game/client/entitysystem.cpp b/game/client/entitysystem.cpp index b3dbf33..a7f16a9 100644 --- a/game/client/entitysystem.cpp +++ b/game/client/entitysystem.cpp @@ -240,14 +240,10 @@ void CEntitySystem::NetRecvPacket( NetPacket_t *pPacket ) } break; case k_EMessage_EntityDeleted: - C_BaseEntity **ppEntities = m_pEntities; - for ( int i = 0; i < MAX_EDICTS; i++ ) - { - if (ppEntities[i] == NULL) - { - - } + { + DestroyEntityByIndex((uint32_t)pPlayerPacket->m_deleteEntity.m_uIndex); } + break; default: break; } diff --git a/game/client/game.cpp b/game/client/game.cpp index 42c8b63..6574e26 100644 --- a/game/client/game.cpp +++ b/game/client/game.cpp @@ -38,6 +38,7 @@ IEngineBridge *EngineBridge() EXPOSE_INTERFACE_FN(EngineBridge, IEngineBridge, ENGINE_BRIDGE_INTERFACE_VERSION) +static IKotUIBuffer *s_pUIBuffer; void CFunnyGameBridge::Init() { @@ -70,6 +71,22 @@ void CFunnyGameBridge::Init() g_pPhysicsWorld = g_pPhysics->CreateWorld(); g_pHumanDeviceManager->SetDefaultInput(g_pMainInput); + + CreateInterfaceFn fnEngineFactory = Sys_GetFactory("engine"); + g_pKotUI = (IKotUIManager*)fnEngineFactory(KOT_UI_INTEFACE_VERSION, NULL); + + g_pKotUI->ConnectInterface(g_pRenderContext, RENDER_CONTEXT_INTERFACE_VERSION); + g_pKotUI->Init(); + IKotRenderFont *pFont = g_pKotUI->LoadFont("game/core/fonts/IBMPlexMono-Regular"); + s_pUIBuffer = g_pKotUI->CreateBuffer(40, 30); + s_pUIBuffer->SetTextFont(pFont); + s_pUIBuffer->SetTextSize(, int iX) + s_pUIBuffer->Move(0, 0); + s_pUIBuffer->Printf("hello %f", 20.0); + s_pUIBuffer->Move(1, 0); + s_pUIBuffer->Printf("hello %f", 40.0); + s_pUIBuffer->Move(2, 0); + s_pUIBuffer->Printf("hello %f", 40.0); } void CFunnyGameBridge::Tick( float fDelta ) @@ -166,6 +183,7 @@ void CFunnyGameBridge::Frame( float fDelta ) EntitySystem()->NetSendThink(pCurrentServer); } g_pWorldRenderer->Frame(fDelta); + s_pUIBuffer->Draw(g_pMainWindow->GetOutputImage()); } void CFunnyGameBridge::Shutdown() diff --git a/game/client/milmoba/player.cpp b/game/client/milmoba/player.cpp index 25beb07..55d4cc7 100644 --- a/game/client/milmoba/player.cpp +++ b/game/client/milmoba/player.cpp @@ -32,7 +32,7 @@ void C_MOBAPlayer::Think( float fDelta ) g_pWorldRenderer->SetCameraPosition(vCameraPos); Quat vCameraRot; glm_euler_yxz_quat((vec3){m_fPitch, m_fYaw, 0}, *(versor*)&vCameraRot); - g_pWorldRenderer->SetCameraRotation(vCameraRot); + //g_pWorldRenderer->SetCameraRotation(vCameraRot); } BaseClass::Think(fDelta); }; diff --git a/game/client/worldrender.cpp b/game/client/worldrender.cpp index c13d73c..e9fa751 100644 --- a/game/client/worldrender.cpp +++ b/game/client/worldrender.cpp @@ -298,7 +298,12 @@ void CFunnyWorldRenderer::Frame( float fDelta ) m_pRasterCommandList->SetViewport(0, 0, uWidth, uHeight, 0, 1); m_pRasterCommandList->SetScissors(0, 0, uWidth, uHeight); m_pRasterCommandList->SetClearColor(0, 0, 0, 0, 0); + m_pRasterCommandList->SetClearColor(1, 0, 0, 0, 0); + m_pRasterCommandList->SetClearColor(2, 0, 0, 0, 0); m_pRasterCommandList->SetClearDepth(1); + m_pRasterCommandList->SetLoadStoreModes(0, LOAD_MODE_CLEAR, STORE_MODE_STORE); + m_pRasterCommandList->SetLoadStoreModes(1, LOAD_MODE_CLEAR, STORE_MODE_STORE); + m_pRasterCommandList->SetLoadStoreModes(2, LOAD_MODE_CLEAR, STORE_MODE_STORE); uint32_t uTotalMeshes = 0; uint32_t u = 0; for ( auto mesh: m_pMeshes) diff --git a/game/shared/game.h b/game/shared/game.h index 5c92d98..fa7c974 100644 --- a/game/shared/game.h +++ b/game/shared/game.h @@ -40,6 +40,8 @@ extern EngineConsts_t *g_pEngineConstants; extern IPhysics *g_pPhysics; extern IPhysicsWorld *g_pPhysicsWorld; +extern IKotUIManager *g_pKotUI; + #define FUNNY_SECURE_PORT 27015 #define FUNNY_QUERY_PORT 27016 diff --git a/materialsystem/vulkan/commands/draw.cpp b/materialsystem/vulkan/commands/draw.cpp index d80fefa..21833c8 100644 --- a/materialsystem/vulkan/commands/draw.cpp +++ b/materialsystem/vulkan/commands/draw.cpp @@ -38,11 +38,22 @@ DECLARE_VULKAN_COMMAND(Begin) VkRenderingAttachmentInfo a = {}; a.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO; a.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - a.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - a.clearValue.color.float32[0] = i.m_fClearColor[0]; - a.clearValue.color.float32[1] = i.m_fClearColor[1]; - a.clearValue.color.float32[2] = i.m_fClearColor[2]; - a.clearValue.color.float32[3] = i.m_fClearColor[3]; + switch( i.m_eLoadMode ) + { + case LOAD_MODE_DONT_CARE: + a.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + break; + case LOAD_MODE_LOAD: + a.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + break; + case LOAD_MODE_CLEAR: + a.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + a.clearValue.color.float32[0] = i.m_fClearColor[0]; + a.clearValue.color.float32[1] = i.m_fClearColor[1]; + a.clearValue.color.float32[2] = i.m_fClearColor[2]; + a.clearValue.color.float32[3] = i.m_fClearColor[3]; + break; + } a.storeOp = VK_ATTACHMENT_STORE_OP_STORE; a.imageView = ((CVkImage*)VulkanGetObject(i.m_stImage, iCurrentFrame))->m_imageView; attachments.AppendTail(a); diff --git a/materialsystem/vulkan/material.cpp b/materialsystem/vulkan/material.cpp index 7814f0c..ce355e2 100644 --- a/materialsystem/vulkan/material.cpp +++ b/materialsystem/vulkan/material.cpp @@ -76,6 +76,17 @@ void CVkMaterial::PSSetTextureArray( uint32_t uSet, ITextureArray *pArray ) SetShaderResource(0, uSet, pArray); } +void CVkMaterial::PSSetTexture( uint32_t uRegister, IImage *pImage ) +{ + SetShaderResource(uRegister, 0, pImage); +} + +void CVkMaterial::PSSetSampler( uint32_t uRegister, ISampler *pImage ) +{ + SetShaderResource(uRegister, 0, pImage); +} + + void CVkMaterial::SetShaderResource( uint32_t uRegister, uint32_t uSet, IRenderingObject *pObject) { if ( m_pVkShader->m_setLayouts.GetSize() == 0 ) @@ -84,6 +95,8 @@ void CVkMaterial::SetShaderResource( uint32_t uRegister, uint32_t uSet, IRenderi IRenderingObject *pVkObject; CVkBuffer *pBuffer; CVkTextureArray *pArray; + CVkImage *pImage; + CVkSampler *pSampler; }; pVkObject = pObject; if (dynamic_cast(pObject)) @@ -101,6 +114,36 @@ void CVkMaterial::SetShaderResource( uint32_t uRegister, uint32_t uSet, IRenderi stInfo.range = pBuffer->m_nSize; vkUpdateDescriptorSets(m_pVkShader->m_hDevice, 1, &write, 0, 0); } + if (dynamic_cast(pObject)) + { + VkWriteDescriptorSet write = {}; + VkDescriptorImageInfo stInfo = {}; + write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write.dstSet = m_hSets[uSet]; + write.dstBinding = uRegister; + write.dstArrayElement = 0; + write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; + write.descriptorCount = 1; + write.pImageInfo = &stInfo; + stInfo.imageView = pImage->m_imageView; + stInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL; + vkUpdateDescriptorSets(m_pVkShader->m_hDevice, 1, &write, 0, 0); + + } + if (dynamic_cast(pObject)) + { + VkWriteDescriptorSet write = {}; + VkDescriptorImageInfo stInfo = {}; + write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write.dstSet = m_hSets[uSet]; + write.dstBinding = uRegister; + write.dstArrayElement = 0; + write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER; + write.descriptorCount = 1; + write.pImageInfo = &stInfo; + stInfo.sampler = pSampler->m_sampler; + vkUpdateDescriptorSets(m_pVkShader->m_hDevice, 1, &write, 0, 0); + } if (dynamic_cast(pObject)) { VkWriteDescriptorSet writes[2] = {}; diff --git a/materialsystem/vulkan/rendercommandlist.cpp b/materialsystem/vulkan/rendercommandlist.cpp index a1dba4a..bdccb97 100644 --- a/materialsystem/vulkan/rendercommandlist.cpp +++ b/materialsystem/vulkan/rendercommandlist.cpp @@ -36,6 +36,15 @@ void CVkRenderCommandList::SetClearColor( uint32_t uIndex, float r, float g, flo pOutput->m_fClearColor[3] = a; } +void CVkRenderCommandList::SetLoadStoreModes( uint32_t uIndex, ELoadMode eLoadMode, EStoreMode eStoreMode ) +{ + SwitchRenderingStage(RENDERING_STAGE_SETUP_RASTER); + VulkanRenderOutput_t *pOutput = FindOrCreateRenderOutput(uIndex); + pOutput->m_eLoadMode = eLoadMode; + pOutput->m_eStoreMode = eStoreMode; + +} + void CVkRenderCommandList::SetDepthTarget( IImage *pDepth ) { SwitchRenderingStage(RENDERING_STAGE_SETUP_RASTER); diff --git a/materialsystem/vulkan/rendercontext.cpp b/materialsystem/vulkan/rendercontext.cpp index 9d026c0..a1de245 100644 --- a/materialsystem/vulkan/rendercontext.cpp +++ b/materialsystem/vulkan/rendercontext.cpp @@ -325,6 +325,11 @@ uint32_t CVkBuffer::GetSize() return m_nSize; } +void CVkSampler::SetDebugName( const char *szName ) +{ + +}; + CVkTextureArray::~CVkTextureArray() { @@ -357,7 +362,6 @@ void CVkTextureArray::Build() samplerInfo.mipLodBias = 0.0f; samplerInfo.minLod = 0.0f; samplerInfo.maxLod = VK_LOD_CLAMP_NONE; - vkCreateSampler(m_hDevice, &samplerInfo, nullptr, &m_hSampler); LoadTexture("game/core/textures/error.png"); @@ -427,6 +431,11 @@ uint32_t CVkTextureArray::GetTextureID( const char *szPath ) { } +IImage *CVkTextureArray::GetTexture( uint32_t uTextureID ) +{ + return m_pImages[uTextureID]; +} + void CVkTextureArray::UnloadTexture( uint32_t uTextureID ) { @@ -477,6 +486,8 @@ public: virtual ITextureArray *CreateTextureArray() override; virtual void DestroyTextureArray() override; + + virtual ISampler *GetDefaultSampler() override; private: VkPhysicalDevice SelectPhysicalDevice( CUtlVector physicalDevices ); CUtlVector GetDeviceExtensions(); @@ -498,6 +509,8 @@ private: CUtlVector m_scheduledRemovalTextureArrays; CUtlVector m_scheduledRemovalBuffers; CUtlVector m_scheduledRemovalImages; + + CVkSampler m_defaultSampler; }; EXPOSE_INTERFACE(CVkRenderContext, IRenderContext, RENDER_CONTEXT_INTERFACE_VERSION); @@ -677,12 +690,18 @@ void CVkRenderContext::DestroyTextureArray() { } +ISampler *CVkRenderContext::GetDefaultSampler() +{ + return &m_defaultSampler; + +} VkPipelineLayout g_pLibraryEmptyLayout; static IVkCommandBuffer *s_pPresentCommandBuffer; void CVkRenderContext::Init() { + VkResult r; int nExtensionCount; @@ -834,6 +853,23 @@ void CVkRenderContext::Init() m_pCommandBufferManager = (IVkCommandBufferManager*)CreateInterface(VULKAN_COMMAND_BUFFER_MANAGER_INTERFACE_NAME, NULL); m_pCommandBufferManager->SetVulkanHandlers(s_vkInstance, s_vkDevice); m_pCommandBufferManager->Init(); + + VkSamplerCreateInfo samplerInfo = {}; + samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + samplerInfo.magFilter = VK_FILTER_LINEAR; + samplerInfo.minFilter = VK_FILTER_LINEAR; + samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; + samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; + samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; + samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK; + samplerInfo.unnormalizedCoordinates = VK_FALSE; + samplerInfo.compareEnable = VK_FALSE; + samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS; + samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + samplerInfo.mipLodBias = 0.0f; + samplerInfo.minLod = 0.0f; + samplerInfo.maxLod = VK_LOD_CLAMP_NONE; + vkCreateSampler(s_vkDevice, &samplerInfo, nullptr, &m_defaultSampler.m_sampler); } void CVkRenderContext::Frame( float fDeltaTime ) @@ -1059,8 +1095,8 @@ formatPicked: pImage->m_eImageType = IMAGE_TYPE_2D; pImage->m_eMultisampleType = MULTISAMPLE_TYPE_NONE; pImage->m_eFormat = IMAGE_FORMAT_BGRA8_UNORM; - pImage->m_nHeight = 1280; - pImage->m_nWidth = 720; + pImage->m_nHeight = pWindow->GetRenderWidth(); + pImage->m_nWidth = pWindow->GetRenderHeight(); pImage->m_ePreferredLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; pImage->CreateImageView(); window.m_images[i] = pImage; diff --git a/materialsystem/vulkan/vulkan_state.h b/materialsystem/vulkan/vulkan_state.h index 3c58c19..48a580f 100644 --- a/materialsystem/vulkan/vulkan_state.h +++ b/materialsystem/vulkan/vulkan_state.h @@ -225,6 +225,13 @@ public: uint32_t m_nSize; }; +class CVkSampler: public ISampler +{ +public: + virtual void SetDebugName( const char *szName ) override; + VkSampler m_sampler; +}; + class CVkPipelineLibrary { public: @@ -349,6 +356,7 @@ public: virtual void SetDebugName( const char *szName ) override; virtual uint32_t LoadTexture( const char *szPath ) override; virtual uint32_t GetTextureID( const char *szPath ) override; + virtual IImage *GetTexture( uint32_t uTextureID ) override; virtual void UnloadTexture( uint32_t uTextureID ) override; void Frame(); @@ -374,7 +382,10 @@ public: virtual void PSSetShaderResource( uint32_t uRegister, IRenderingObject *pResource ) override; virtual void PSSetConstantsBuffer( uint32_t uRegister, IBuffer *pConstants ) override; + virtual void PSSetTextureArray( uint32_t uSet, ITextureArray *pArray ) override; + virtual void PSSetTexture( uint32_t uRegister, IImage *pImage ) override; + virtual void PSSetSampler( uint32_t uRegister, ISampler *pImage ) override; CVkShader *m_pVkShader; CUtlVector m_hSets; @@ -402,6 +413,7 @@ struct VulkanMaterialCommandBuffer_t }; + enum EVkFrameObjectType_t { FRAME_OBJECT_TYPE_SINGLE, @@ -438,6 +450,7 @@ public: virtual void SetRenderTarget( uint32_t uIndex, IImage *pImage ) override; virtual void SetClearColor( uint32_t uIndex, float r, float g, float b, float a ) override; + virtual void SetLoadStoreModes( uint32_t uIndex, ELoadMode eLoadMode, EStoreMode eStoreMode ) override; virtual void SetDepthTarget( IImage *pDepth ) override; virtual void SetClearDepth( float fVal ) override; diff --git a/public/cl_entity.h b/public/cl_entity.h deleted file mode 100644 index e69de29..0000000 diff --git a/public/imouseinput.h b/public/imouseinput.h deleted file mode 100644 index e69de29..0000000 diff --git a/public/jsonformat.h b/public/jsonformat.h deleted file mode 100644 index e69de29..0000000 diff --git a/public/kottui/kottui.h b/public/kottui/kottui.h index 1980b58..0565fa1 100644 --- a/public/kottui/kottui.h +++ b/public/kottui/kottui.h @@ -5,15 +5,19 @@ #include "../materialsystem/igamewindow.h" #include "tier2/iappsystem.h" -abstract_class IRenderFont +abstract_class IKotRenderFont { public: - virtual IImage *GetAtlas(); - virtual bool IsLetterPresent( uint32_t letter ); - virtual float GetLetterX( uint32_t letter ); - virtual float GetLetterY( uint32_t letter ); - virtual float GetWidthX( uint32_t letter ); - virtual float GetWidthY( uint32_t letter ); + virtual IImage *GetAtlas() = 0; + virtual bool IsLetterPresent( uint32_t letter ) = 0; + virtual float GetLetterX( uint32_t letter ) = 0; + virtual float GetLetterY( uint32_t letter ) = 0; + virtual float GetWidth( uint32_t letter ) = 0; + virtual float GetHeight( uint32_t letter ) = 0; + + virtual bool IsMono() = 0; + virtual uint32_t GetLetterWidth() = 0; + virtual uint32_t GetLetterHeight() = 0; }; abstract_class IKotUIBuffer @@ -29,18 +33,21 @@ public: virtual void PutChar( char c ) = 0; virtual void Printf(const char *szFormat, ...) = 0; - virtual void Draw( IRenderContext *pRenderContext ); + virtual void Draw( IImage *pImage ) = 0; virtual void SetTextSize( int iY, int iX ) = 0; - virtual void SetTextFont( IRenderFont *pFont ) = 0; + virtual void SetTextFont( IKotRenderFont *pFont ) = 0; }; -abstract_class IKotUIManager: public IAppSystem +abstract_class IKotUIManager: public IAppSystem2 { public: - virtual void CreateBuffer( int iWidth, int iHeight ) = 0; + virtual IKotRenderFont *LoadFont( const char *szPath ) = 0; + virtual IKotUIBuffer *CreateBuffer( int iWidth, int iHeight ) = 0; + virtual void DeleteBuffer( IKotUIBuffer *pBuffer ) = 0; }; + IKotUIManager *KotUIManager(); #define KOT_UI_INTEFACE_VERSION "KotUI001" diff --git a/public/materialsystem/imaterialsystem.h b/public/materialsystem/imaterialsystem.h index efd9b8c..0df4aef 100644 --- a/public/materialsystem/imaterialsystem.h +++ b/public/materialsystem/imaterialsystem.h @@ -166,12 +166,18 @@ public: virtual EMultisampleType GetMultisampleType() = 0; }; +abstract_class ISampler : public IRenderingObject +{ + +}; + abstract_class ITextureArray: public IRenderingObject { public: virtual void Build() = 0; virtual uint32_t LoadTexture( const char *szPath ) = 0; virtual uint32_t GetTextureID( const char *szPath ) = 0; + virtual IImage *GetTexture( uint32_t uTextureID ) = 0; virtual void UnloadTexture( uint32_t uTextureID ) = 0; }; @@ -250,6 +256,8 @@ public: virtual void VSSetConstantsBuffer( uint32_t uRegister, IBuffer *pImage ) = 0; virtual void PSSetConstantsBuffer( uint32_t uRegister, IBuffer *pImage ) = 0; virtual void PSSetTextureArray( uint32_t uSet, ITextureArray *pArray ) = 0; + virtual void PSSetTexture( uint32_t uRegister, IImage *pImage ) = 0; + virtual void PSSetSampler( uint32_t uRegister, ISampler *pImage ) = 0; }; abstract_class IRenderCommandList @@ -259,6 +267,7 @@ public: virtual void SetRenderTarget( uint32_t uIndex, IImage *pImage ) = 0; virtual void SetClearColor( uint32_t uIndex, float r, float g, float b, float a ) = 0; + virtual void SetLoadStoreModes( uint32_t uIndex, ELoadMode eLoadMode, EStoreMode eStoreMode ) = 0; virtual void SetDepthTarget( IImage *pDepth ) = 0; virtual void SetClearDepth( float fVal ) = 0; @@ -321,6 +330,8 @@ public: virtual ITextureArray *CreateTextureArray() = 0; virtual void DestroyTextureArray() = 0; + + virtual ISampler *GetDefaultSampler() = 0; }; #define RENDER_CONTEXT_INTERFACE_VERSION "RenderContext001" diff --git a/public/sv_entity.h b/public/sv_entity.h deleted file mode 100644 index e69de29..0000000 diff --git a/shadercompiler/psMain b/shadercompiler/psMain index b4520cf890e054e492d6aeb40b640e885ca0302a..facea721ec8fea082bd37dbd5144970cf0a02548 100644 GIT binary patch delta 461 zcmYjOyGjE=6umQJ+)QMH&5~k`B0(_m2b7>-6ANu@tSqwV772)J9q>_DrCKgx>}@S1 ze_)@#@FS8!@SLy<88~~-xv#l*_A`2pLT6intQ!&8mybNWkA|RkKn5hh1(1H{u{DW) z*&UPW%r?wWo35>OSJz+L(H`uU>r5Zrk2z)0Ho$WxYm&lJ+d}h#)i^Js<_yfwrY{v| z%|Ks+n`JWwx(J-ZvRSDI;B4jq#;MtCRcG3+9yH(J4T`K7c3kKae@^yD^uXf2R-p;WZA$82JaYvN>@8 delta 494 zcmYjOJxc>Y6nwjDyqt0|7DtLRiilwJ2WSWiRujKq4xD%Q`W2kF;1u70nw