12 GL Backend and Custom Backends - inanevin/LinaVG GitHub Wiki
LinaVG itself does not provide any kind of rendering functionality. It simply handles all kinds of buffer generation depending on what you want to draw, and sends the data in optimized batches to the custom backend you provide. Of course, example application has a custom OpenGL backend example which you can very well use in your own projects.
Creating a custom backend
First of all you can check these examples:
- LinaVG Example Project OpenGL Backend
- Lina Engine Backend for LinaVG
- Related to the second one: Lina Engine GUI Renderer
First create a new class deriving from LinaVG::Backend::BaseBackend
interface. Then before initializaing LinaVG, just call:
LinaVG::Backend::BaseBackend::SetBackend(myOwnBackendInstance);
// Inherited via BaseBackend
virtual bool Initialize() override;
virtual void Terminate() override;
virtual void StartFrame(int threadCount) override;
virtual void DrawGradient(LinaVG::GradientDrawBuffer* buf, int thread) override;
virtual void DrawTextured(LinaVG::TextureDrawBuffer* buf, int thread) override;
virtual void DrawDefault(LinaVG::DrawBuffer* buf, int thread) override;
virtual void DrawSimpleText(LinaVG::SimpleTextDrawBuffer* buf, int thread) override;
virtual void DrawSDFText(LinaVG::SDFTextDrawBuffer* buf, int thread) override;
virtual void EndFrame() override;
virtual void BufferFontTextureAtlas(int width, int height, int offsetX, int offsetY, unsigned char* data) override;
virtual void BindFontTexture(LinaVG::BackendHandle texture) override;
virtual void SaveAPIState() override;
virtual void RestoreAPIState() override;
virtual LinaVG::BackendHandle CreateFontTexture(int width, int height) override;
The functions are pretty self-explanatory, few crucial points:
Initialize
This function will be called when LinaVG::Initialize() is called. Implement your own init functionality here. The example OpenGL backend creates shaders, buffers, vaos, vbos etc. here.
StartFrame
Called when LinaVG::StartFrame
is called. threadCount
is whatever you pass inside LinaVG::StartFrame()
. Example OpenGL backend sets the draw state here, doesn't do any threading functionality. If you are multi-threading, you can resize your buffers according to the threadCount.
DrawXXX
This is where you will receive the calculated buffers from LinaVG. You can record draw commands here, or save the buffers and call custom rendering functions to dispatch draw calls all at once. Each received buffer contains:
- Vertex & index data
- Clip/scissors data
- Draw parameters for the draw type.
EndFrame
Called when LinaVG::EndFrame()
is called. Example OpenGL backend unbinds buffers and resets drawing state here.
Save/Restore API state
Called by the font loader in-between creating new texture atlases, in case you need to make state changes on your custom backend. In the case of example GL backend, it also uses to internally change API state.
CreateFontTexture
This is where you are supposed to allocate a texture with the given size in the GPU and return a handle. The texture will be used for font atlas, so care about the filters and other sampler settings.
BindFontTexture
Handle you returned on the CreateFontTexture
will be given back to you here, where you can "bind" the texture for writing. When you call LoadFont, it will either create a new texture by calling CreateFontTexture
, or use a previously created one for atlas purposes. That's why this method exists. LinaVG does not necessarily create a texture per font you load.
BufferFontTextureAtlas
Buffers custom data into the texture given in the last BindFontTexture
call by width
& height
, as well as offsetX
and offsetY
. Used to buffer individual character glyphs into a font atlas. This is where you will write data to your texture.
CreateFontTexture
, BindFontTexture
and BufferFontTextureAtlas
Some remarks about the combination of Here is an example scenario:
LoadFont(myFont0)
- No atlasses,
CreateFontTexture
- return handle myTexture0 BindFontTexture(myTexture0)
BufferFontTexture()
-- now you are supposed to be buffering into myTexture0LoadFont(myFont1)
-- slightly bigger font- Atlas size is not sufficient enough,
CreateFontTexture
- return handle myTexture1 BindFontTexture(myTexture1)
BufferFontTexture()
-- now you are supposed to be buffering into myTexture1LoadFont(myFont2)
-- small font- Atlas that was created for the first time (myTexture0) has sufficient enough size.
BindFontTexture(myTexture0)
BufferFontTexture()
-- now you are supposed to be buffering into myTexture0