added ui rendering

This commit is contained in:
2025-07-14 21:56:10 +03:00
parent 7c2b65d079
commit d6100a8752
17 changed files with 254 additions and 33 deletions

View File

@@ -174,7 +174,6 @@ void IVulkan::Init()
}; };
void IVulkan::CreatePipelines() void IVulkan::CreatePipelines()
{ {
V_printf("Created %i pipelines\n",g_StepMeshRendering.GetSize());
for (auto &step: g_StepPrepass) for (auto &step: g_StepPrepass)
step.pPipeline->Init(); step.pPipeline->Init();
for (auto &step: g_StepMeshRendering) for (auto &step: g_StepMeshRendering)

View File

@@ -7,7 +7,7 @@
CUtlVector<CUtlString> fgui_CompiledFiles = { CUtlVector<CUtlString> fgui_CompiledFiles = {
"fgui/fgui.cpp", "fgui/fgui.cpp",
"fgui/widget.cpp", "fgui/widget.cpp",
"fgui/rectangle.cpp", "fgui/rect.cpp",
"fgui/label.cpp", "fgui/label.cpp",
}; };
CUtlString fgui_lib; CUtlString fgui_lib;

View File

@@ -3,10 +3,17 @@
#include "rendering.h" #include "rendering.h"
#include "tier1/utlvector.h" #include "tier1/utlvector.h"
#include "fgui/widget.h" #include "fgui/widget.h"
#include <cctype>
float fgui_fRectColor[4];
float fgui_fTextColor[4];
float fgui_fTextPosition[2];
CFont *fgui_pTextFont;
IGraphicsPipeline *fgui_RectPipeline; IGraphicsPipeline *fgui_RectPipeline;
IGraphicsPipeline *fgui_TextPipeline; IGraphicsPipeline *fgui_TextPipeline;
IVertexBuffer *fgui_pRectangleBuffer;
IVertexBuffer *fgui_pUVRectangleBuffer;
void IFGUI::Init( void ) void IFGUI::Init( void )
{ {
@@ -18,30 +25,78 @@ void IFGUI::Frame( void )
} }
//----------------------------------------------------------------------------
// Creates new widget in the world
//----------------------------------------------------------------------------
CUtlVector<CFGUI_Widget*> fgui_widgets; CUtlVector<CFGUI_Widget*> fgui_widgets;
void IFGUI::AppendWidget( CFGUI_Widget *pWidget ) void IFGUI::AppendWidget( CFGUI_Widget *pWidget )
{ {
fgui_widgets.AppendTail(pWidget); fgui_widgets.AppendTail(pWidget);
} }
//----------------------------------------------------------------------------
// Destroys widget
//----------------------------------------------------------------------------
void IFGUI::DestroyWidget( CFGUI_Widget *pWidget ) void IFGUI::DestroyWidget( CFGUI_Widget *pWidget )
{ {
size_t i = 0;
for (auto &widget: fgui_widgets)
{
if (widget == pWidget)
{
fgui_widgets.RemoveAt(i);
return;
} }
i++;
}
}
//----------------------------------------------------------------------------
//
//----------------------------------------------------------------------------
void IFGUI::SetRectColor( float r, float g, float b, float a ) void IFGUI::SetRectColor( float r, float g, float b, float a )
{ {
fgui_fRectColor[0] = r;
fgui_fRectColor[1] = g;
fgui_fRectColor[2] = b;
fgui_fRectColor[3] = a;
} }
//----------------------------------------------------------------------------
// Draws rectangle on the screen
//----------------------------------------------------------------------------
void IFGUI::DrawRect( int32_t iPosX, int32_t iPosY, uint32_t uSizeX, uint32_t uSizeY ) void IFGUI::DrawRect( int32_t iPosX, int32_t iPosY, uint32_t uSizeX, uint32_t uSizeY )
{ {
IRenderer::BindPipeline(fgui_RectPipeline);
struct RectConstants_t
{
uint32_t nResolution[2];
uint32_t nSize[2];
int32_t nPosition[2];
float offest0[2];
float fColor[4];
} constants;
constants.nResolution[0] = g_nWindowWidth;
constants.nResolution[1] = g_nWindowHeight;
constants.nPosition[0] = iPosX;
constants.nPosition[1] = iPosY;
constants.nSize[0] = uSizeX;
constants.nSize[1] = uSizeY;
for ( int i = 0; i < 4; i++ )
constants.fColor[i] = fgui_fRectColor[i];
IRenderer::SetConstants(sizeof(RectConstants_t), &constants);
IRenderer::Draw(fgui_pRectangleBuffer, NULL);
} }
CUtlVector<CFont*> fgui_fonts; CUtlVector<CFont*> fgui_fonts;
CFont *fgui_pCurrentFont; CFont *fgui_pCurrentFont;
//----------------------------------------------------------------------------
// Loads new font
//----------------------------------------------------------------------------
CFont *IFGUI::LoadFont( CUtlString szFontPath ) CFont *IFGUI::LoadFont( CUtlString szFontPath )
{ {
for (auto &font: fgui_fonts) for (auto &font: fgui_fonts)
@@ -57,31 +112,90 @@ CFont *IFGUI::LoadFont( CUtlString szFontPath )
IFileSystem::Read(f, b.GetMemory(), IFileSystem::Size(f)); IFileSystem::Read(f, b.GetMemory(), IFileSystem::Size(f));
IFileSystem::Close(f); IFileSystem::Close(f);
char cCharacterSet[256] = {}; char cCharacterSet[256] = {};
V_memset(cCharacterSet, 0, 256);
uint32_t nElementsWidth; uint32_t nElementsWidth;
uint32_t nElementsHeight; uint32_t nElementsHeight;
V_sscanf(b, "%u %u %255s", &nElementsWidth, &nElementsHeight, cCharacterSet); V_sscanf(b, "%u %u %255s", &nElementsWidth, &nElementsHeight, cCharacterSet);
V_printf("%i %i\n", nElementsWidth, nElementsHeight); uint32_t nGlyphWidth = pFont->pTexture->x / nElementsWidth;
uint32_t nGlyphHeight = pFont->pTexture->y / nElementsHeight;
for ( int i = 0; i < 255; i++ )
{
if (isprint(cCharacterSet[i]) && !isspace(cCharacterSet[i]))
pFont->cCharacterSet[cCharacterSet[i]] = i;
else
pFont->cCharacterSet[cCharacterSet[i]] = -1;
}
pFont->glyphWidth = nGlyphWidth;
pFont->glyphHeight = nGlyphHeight;
pFont->nGlyphsPerRow = nElementsWidth;
pFont->nGlyphsPerColumn = nElementsHeight;
return pFont; return pFont;
} }
void IFGUI::SetTextFont( CFont *pFont ) void IFGUI::SetTextFont( CFont *pFont )
{ {
fgui_pTextFont = pFont;
} }
void IFGUI::SetTextPos( float x, float y ) void IFGUI::SetTextPos( float x, float y )
{ {
fgui_fTextPosition[0] = x;
fgui_fTextPosition[1] = y;
} }
void IFGUI::SetTextColor( float r, float g, float b, float a ) void IFGUI::SetTextColor( float r, float g, float b, float a )
{ {
fgui_fRectColor[0] = r;
fgui_fRectColor[1] = g;
fgui_fRectColor[2] = b;
fgui_fRectColor[3] = a;
} }
void IFGUI::DrawText( CUtlString psz ) void IFGUI::DrawText( CUtlString psz )
{ {
if (fgui_pTextFont == NULL)
{
V_printf("Forgot to call IFGUI::SetTextFont()?\n");
return;
}
IRenderer::BindPipeline(fgui_TextPipeline);
struct RectConstants_t
{
uint32_t nResolution[2];
uint32_t nSize[2];
int32_t nPosition[2];
float offest0[2];
float fColor[4];
float fGlyphPos[2];
float fGlyphSize[2];
uint32_t nFont;
} constants;
constants.nResolution[0] = g_nWindowWidth;
constants.nResolution[1] = g_nWindowHeight;
constants.nPosition[0] = fgui_fTextPosition[0];
constants.nPosition[1] = fgui_fTextPosition[1];
constants.nSize[0] = fgui_pTextFont->glyphWidth;
constants.nSize[1] = fgui_pTextFont->glyphHeight;
constants.fGlyphSize[0] = 1.0 / fgui_pTextFont->nGlyphsPerRow;
constants.fGlyphSize[1] = 1.0 / fgui_pTextFont->nGlyphsPerColumn;
constants.nFont = ITextureManager::GetTextureID(fgui_pTextFont->pTexture);
for ( int i = 0; i < 4; i++ )
constants.fColor[i] = fgui_fRectColor[i];
for ( int i = 0; psz[i]; i++)
{
constants.fGlyphPos[0] = fgui_pTextFont->cCharacterSet[psz[i]] % fgui_pTextFont->nGlyphsPerRow;
constants.fGlyphPos[1] = fgui_pTextFont->cCharacterSet[psz[i]] / fgui_pTextFont->nGlyphsPerRow;
if (isprint(psz[i]) && !isspace(psz[i]))
{
IRenderer::SetConstants(sizeof(RectConstants_t), &constants);
IRenderer::PushBindings();
IRenderer::Draw(fgui_pUVRectangleBuffer, NULL);
}
constants.nPosition[0] += fgui_pTextFont->glyphWidth;
}
} }
class CFGUI_Rendering: public IRenderingPipelineStep class CFGUI_Rendering: public IRenderingPipelineStep
@@ -101,10 +215,10 @@ void CFGUI_Rendering::Init()
{"gfx/fgui_rect_frag.shader", SHADER_TYPE_FRAGMENT}, {"gfx/fgui_rect_frag.shader", SHADER_TYPE_FRAGMENT},
}, },
{}, {},
24, 48,
8, 8,
{{0,0,EVertexFormat::VERTEX_FORMAT_X32Y32}}, {{0,0,VERTEX_FORMAT_X32Y32}},
{EImageFormat::IMAGE_FORMAT_R8G8B8A8}, {IMAGE_FORMAT_R8G8B8A8},
true true
); );
fgui_TextPipeline = IRenderer::CreateGraphicsPipeline( fgui_TextPipeline = IRenderer::CreateGraphicsPipeline(
@@ -113,24 +227,75 @@ void CFGUI_Rendering::Init()
{"gfx/fgui_text_frag.shader", SHADER_TYPE_FRAGMENT}, {"gfx/fgui_text_frag.shader", SHADER_TYPE_FRAGMENT},
}, },
{ {
{SHADER_INPUT_TYPE_TEXTURES, 0}, {SHADER_INPUT_TYPE_TEXTURES, 29},
}, },
25, 80,
8, 16,
{{0,0,EVertexFormat::VERTEX_FORMAT_X32Y32}}, {{0,0, VERTEX_FORMAT_X32Y32},{8,1, VERTEX_FORMAT_X32Y32}},
{EImageFormat::IMAGE_FORMAT_R8G8B8A8}, {IMAGE_FORMAT_WINDOW},
true true
); );
{
float vertices[6*2] = {
0,0,
0,1,
1,0,
1,0,
0,1,
1,1,
};
fgui_pRectangleBuffer = IRenderer::CreateVertexBuffer(sizeof(vertices));
void *pMapping = fgui_pRectangleBuffer->Map();
V_memcpy(pMapping, vertices, sizeof(vertices));
fgui_pRectangleBuffer->Unmap();
}
{
float vertices[6*4] = {
0,0, 0,0,
0,1, 0,1,
1,0, 1,0,
1,0, 1,0,
0,1, 0,1,
1,1, 1,1,
};
fgui_pUVRectangleBuffer = IRenderer::CreateVertexBuffer(sizeof(vertices));
void *pMapping = fgui_pUVRectangleBuffer->Map();
V_memcpy(pMapping, vertices, sizeof(vertices));
fgui_pUVRectangleBuffer->Unmap();
}
}; };
void CFGUI_Rendering::Frame( float fDelta ) void CFGUI_Rendering::Frame( float fDelta )
{ {
IRenderer::Barrier(BARRIER_STAGE_TOP, BARRIER_STAGE_COLOR_OUTPUT, {}, {
{
BARRIER_MEMORY_PERMISSIONS_NONE,
BARRIER_MEMORY_PERMISSIONS_COLOR_WRITE,
IRenderer::GetOutputImage(),
}
});
IRenderer::Begin(g_nWindowWidth, g_nWindowHeight, {
{
IRenderer::GetOutputImage(),
NULL,
ATTACHMENT_LOAD_MODE_LOAD,
ATTACHMENT_STORE_MODE_STORE,
}
}, {});
IRenderer::ResetState(); IRenderer::ResetState();
IRenderer::SetDepthMode(DEPTH_MODE_LESS); IRenderer::SetDepthMode(DEPTH_MODE_LESS);
for (auto &widget: fgui_widgets) for (auto &widget: fgui_widgets)
{ {
widget->Draw(); widget->Draw();
} }
IRenderer::End();
IRenderer::Barrier(BARRIER_STAGE_COLOR_OUTPUT, BARRIER_STAGE_BOTTOM, {}, {
{
BARRIER_MEMORY_PERMISSIONS_COLOR_WRITE,
BARRIER_MEMORY_PERMISSIONS_NONE,
IRenderer::GetOutputImage(),
}
});
}; };
void CFGUI_Rendering::Deinit() void CFGUI_Rendering::Deinit()

View File

@@ -8,7 +8,7 @@ CFGUI_Label::CFGUI_Label()
void CFGUI_Label::SetFont( CUtlString font ) void CFGUI_Label::SetFont( CUtlString font )
{ {
IFGUI::LoadFont(font); m_pFont = IFGUI::LoadFont(font);
} }
void CFGUI_Label::SetLabel( CUtlString text ) void CFGUI_Label::SetLabel( CUtlString text )
@@ -28,7 +28,9 @@ void CFGUI_Label::Event( FGUI_Event_t event )
void CFGUI_Label::Draw() void CFGUI_Label::Draw()
{ {
IFGUI::SetTextFont(m_pFont);
IFGUI::SetTextColor(1, 1, 1, 1); IFGUI::SetTextColor(1, 1, 1, 1);
IFGUI::SetTextPos(m_iPosition[0], m_iPosition[1]);
IFGUI::DrawText(m_szText); IFGUI::DrawText(m_szText);
} }

21
fgui/rect.cpp Normal file
View File

@@ -0,0 +1,21 @@
#include "fgui/rect.h"
void CFGUI_Rect::SetBoxColor( float r, float g, float b, float a )
{
m_fBoxColor[0] = r;
m_fBoxColor[1] = g;
m_fBoxColor[2] = b;
m_fBoxColor[3] = a;
};
void CFGUI_Rect::Event( FGUI_Event_t event )
{
}
void CFGUI_Rect::Draw()
{
IFGUI::SetRectColor(m_fBoxColor[0],m_fBoxColor[1],m_fBoxColor[2],m_fBoxColor[3]);
IFGUI::DrawRect(m_iPosition[0],m_iPosition[1],m_iSize[0],m_iSize[1]);
}

View File

View File

@@ -1,2 +1,2 @@
12 8 !"#$&'()*+,-./0123456789:;<=>?@ABCDEFGIJKLMNOPQRSTUVWXYZ[\]^_`abcdefgijklmnopqrstuvwxyz{|}~ 12 8 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~

View File

@@ -6,6 +6,6 @@ float4 _main(
uint triid: SV_PrimitiveID, uint triid: SV_PrimitiveID,
) : SV_TARGET ) : SV_TARGET
{ {
return float4(0.2,0.2,0.2,1); return float4(color);
} }

View File

@@ -8,9 +8,10 @@ struct VertexOutput
DECLARE_CONSTANTS() DECLARE_CONSTANTS()
{ {
int2 resolution; uint2 resolution;
uint2 size; uint2 size;
int2 position; int2 position;
float4 color;
}; };

View File

@@ -6,6 +6,10 @@ float4 _main(
uint triid: SV_PrimitiveID, uint triid: SV_PrimitiveID,
) : SV_TARGET ) : SV_TARGET
{ {
return float4(0.2,0.2,0.2,1); float dist = SampleTexture(font, (input.uv+glyphPos)*glyphSize).x;
float smoothing = 0.2;
float alpha = smoothstep(0.5-smoothing, 0.5+smoothing, dist);
if (alpha<0.01) discard;
return float4(color);
} }

View File

@@ -3,6 +3,7 @@
struct VertexOutput struct VertexOutput
{ {
float4 position: SV_Position; float4 position: SV_Position;
float2 uv: TEXCOORD0;
} }
#include "shader_base.h" #include "shader_base.h"
@@ -11,8 +12,11 @@ DECLARE_CONSTANTS()
int2 resolution; int2 resolution;
uint2 size; uint2 size;
int2 position; int2 position;
int8_t character; float4 color;
float2 glyphPos;
float2 glyphSize;
uint font;
}; };
DECLARE_TEXTURES(0); DECLARE_TEXTURES(29);

View File

@@ -13,6 +13,7 @@ VertexOutput _main(
{ {
VertexOutput output; VertexOutput output;
output.position = float4((input.position*size+position)/resolution*2-1, 0, 1.0f); output.position = float4((input.position*size+position)/resolution*2-1, 0, 1.0f);
output.uv = input.uv;
FIX_VERTEX_POSITION(output.position); FIX_VERTEX_POSITION(output.position);
return output; return output;
} }

View File

@@ -41,19 +41,19 @@ SamplerState mlGetSampler()
_mlGetSampler(); _mlGetSampler();
}; };
#define DECLARE_CBUFFER(b) \ #define DECLARE_CBUFFER(n) \
[[vk::binding(b)]] cbuffer cbuffer_##b : register(t##b) [[vk::binding(n)]] cbuffer cbuffer_##b : register(b##n)
#define DECLARE_CONSTANTS() \ #define DECLARE_CONSTANTS() \
[[vk::push_constant]] \ [[vk::push_constant]] \
cbuffer cbuffer_constants : register(t29) cbuffer cbuffer_constants : register(b29)
#define FIX_VERTEX_POSITION(g) g = float4(g.x, -g.y, g.z, g.w); #define FIX_VERTEX_POSITION(g) g = float4(g.x, -g.y, g.z, g.w);
#elif defined(__SPIRV__) #elif defined(__SPIRV__)
#define DECLARE_TEXTURES(b) \ #define DECLARE_TEXTURES(n) \
[[vk::binding(b)]] \ [[vk::binding(n)]] \
Sampler2D g_textures[]; \ Sampler2D g_textures[]; \
float4 SampleTexture(uint32_t binding, float2 uv) \ float4 SampleTexture(uint32_t binding, float2 uv) \
{ \ { \

View File

@@ -5,6 +5,7 @@
#include "rendering.h" #include "rendering.h"
#include "input.h" #include "input.h"
#include "fgui/widget.h" #include "fgui/widget.h"
#include "fgui/rect.h"
#include "fgui/label.h" #include "fgui/label.h"
#include "mesh.h" #include "mesh.h"
@@ -23,14 +24,18 @@ public:
void C_MOBAPlayer::Precache() void C_MOBAPlayer::Precache()
{ {
} }
CFGUI_Rect *pRect = new CFGUI_Rect();
CFGUI_Label *pText = new CFGUI_Label(); CFGUI_Label *pText = new CFGUI_Label();
void C_MOBAPlayer::Spawn() void C_MOBAPlayer::Spawn()
{ {
pText->SetFont("fonts/IBMPlexMono-Regular"); pRect->SetPosition(0, 0);
pText->SetPosition(100, 100); pRect->SetSize(200, 200);
pText->SetLabelSize(15); pRect->SetBoxColor(0, 1, 0, 1);
pText->SetLabel("Hello, world!");
pText->SetFont("fonts/IBMPlexMono-Regular");
pText->SetPosition(0, 0);
pText->SetLabelSize(15);
pText->SetLabel("Hello world!");
float cubeVertices[] = { float cubeVertices[] = {
// Front face // Front face

View File

@@ -19,6 +19,8 @@ public:
ITexture *pTexture; ITexture *pTexture;
uint32_t glyphWidth; uint32_t glyphWidth;
uint32_t glyphHeight; uint32_t glyphHeight;
uint32_t nGlyphsPerRow;
uint32_t nGlyphsPerColumn;
char cCharacterSet[256]; char cCharacterSet[256];
}; };

View File

@@ -20,7 +20,8 @@ public:
virtual void Event( FGUI_Event_t event ) override; virtual void Event( FGUI_Event_t event ) override;
virtual void Draw() override; virtual void Draw() override;
uint32_t m_fGlyphSize[2]; private:
CFont *m_pFont;
}; };
#endif #endif

16
public/fgui/rect.h Normal file
View File

@@ -0,0 +1,16 @@
#ifndef FGUI_RECT_H
#define FGUI_RECT_H
#include "widget.h"
class CFGUI_Rect: public CFGUI_Widget
{
public:
void SetBoxColor( float r, float g, float b, float a );
virtual void Event( FGUI_Event_t event ) override;
virtual void Draw() override;
float m_fBoxColor[4];
};
#endif