What is it?
Black Shark Graphics Engine is a simple 2D and 3D engine written
in Pascal for developers to produce applications utilising hardware-accelerated
graphics. It supports Lazarus (v. >= 2.0) and Delphi.
It's a young, a freely available, project that currently
has a vector of development in the 2D area. Beside, if you want, you can create
3D objects (see tests example TBSTestMesh, TBSTestEarth in a unit bs.test.mesh.pas).
A main purpose of the project is creating the simplest entities for simple
access to OpenGL API abilities within of version >= ES2.
Platforms
- Windows
- Linux
- Ultibo
- Raspberry OS
Summary
-
Core:
- a renderer has been based on OpenGL ES 2.0 API; for access OpenGL context uses a library from Google project the
Angle;
- almost all events and animations have based on
observer pattern;
- no difference between 2D and 3D worlds; 2D objects are drawn over the nearest
plane of frustum; if you want to use pure 2D-world only, you can set TBlackSharkFrustum.OrtogonalProjection
in True, that allows avoid few distortions objects;
- a window system for all input events (keyboard, mouse) is based on supplied
component libraries in Delphi and Lazarus (VCL/FMX and LCL appropriately), but,
if you want, you can replace its (bs.viewport.TBlackSharkViewPort)
on own window system;
- a pure Black Shark application (see examples "/tests/delphi/BSApplication" and "/tests/lazarus/BSApplication"); it is also supported by delphi for linux target compilation;
- own system of windows (see example "bs.test.windows.TBSTestWindows" through command line parameters in "BSApplicatoin");
- it has a canvas for creating any 2D-objects;
- any graphic objects (2D or 3D) may be interactive;
- a simple rasterizator is used for load of textures and draw of primitives in RAM (for example, for fonts rasterization);
- own fonts system is not depending on OS;
- a set of visual tests for many subsystems;
-
Fonts:
- supports fonts TrueType loaded from files *.ttf, appropriately you can
load any contours TrueType, for example, smiles (emoji);
- it has own loader of TrueType fonts with accomplish of triangulation and rasterization
(without the use of external tools);
- characters output only by a mesh (allows to get good quality of big symbols);
- characters output from a texture (allows to get relative good quality of small symbols)
beforehand prepared by the rasterizator; the texture consists only of
alpha (GL_ALPHA), that is why a font can reserve very large
textures;
- supports mixed mode (with the use a special class TTrueTypeRasterFont)
allowing automaticaly for a size of font a smaller threshold to display
from a texture and if the size more threshold to display from meshes;
- for sharing between consumers and managing the lifetime fonts have automatic
reference counting;
-
Textures:
- supports tga, png (for load uses tools Delphi and FPC); it is easy to add
support for new formats;
- for sharing between consumers and managing the lifetime textures have automatic
reference counting;
-
Geometry instansing:
- implements software instancing, that is, to draw a mesh for every
instance invokes glDrawElements, because a hardware support exists
only in the GLES 3.0; in the future planned hardware implementation,
as only will be add the support to the Angle project;
-
Particle system:
- implements drawing many textured particles by single call glDrawElements
for all particles; the every particle is a quad of a texture if a property
TBlackSharkParticles.IsPoints equal false, otherwise it is a point;
-
Full screen anti-aliasing implemented with help shaders:
- Fast approXimate (FXAA);
- Multi Sampling (MSAA);
- Super Sampling x4 (SSAA) (with help to render to texture more than screen
in 2 times and further resample (on GPU, of course) to the viewport size;
in Linux works a native implementation (TODO: include property EmbeddedSSAA
to TBlackSharkViewPort for switch it);
-
Canvas:
- it has a class bs.canvas.TBCanvas that is a simple group of 2d objects
(descendants of a TCanvasObject);
- the canvas has mechanism of scaling belonging its objects relative a size of the
viewport;
- the bs.canvas unit contains the set of some primitives, so as line, circle,
arc, rectangle, triangle, curves and so on;
- the canvas has scalable mode for automatic scaling of its objects when viewport changing;
-
Misc:
- small and very usefull (IMHO) generic collections:
- a list/stack;
- a binary balanced tree (AVL-tree) that has time complexity O(log n) for
all operations: search, insert and delete; a very usefull property:
all values automatically ordered by key;
- a hash-table that has time complexity O(1) in the average case;
- a thread-safe FIFO queue (First In First Out) without using of OS objects
for synchronization;
- a bidirectional list allowing insert and delete to any position
for time complexity O(1); one has cursor for access to items by index;
- a virtual tree fits for any hierarchical data, save
and load any earlier formed structures;
- finite-state automaton (machine) presenting
Aho–Corasick algorithm, for example, allowing quickly to find all
sub-strings into an input stream of data;
Install
- download sources;
- unzip into a new directory, desirable consisting only of Latin characters;
- set paths in your IDE for search sources: root of the directory, /common, /core, /gui;
- set path for a output executable file to a directory /bin;
- for Win64 replace files libEGL.dll, libGLESv2.dll, opengl32.dll by
files from a directory /bin/Win64.
Hello world
unit uMain;
{$mode Delphi}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, ExtCtrls,
bs.basetypes,
bs.viewport,
bs.gl.context,
bs.canvas;
type
{ TFrmMain }
TFrmMain = class(TForm)
PanelScreen: TPanel;
PnlTools: TPanel;
procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
procedure FormShow(Sender: TObject);
private
ViewPort: TBlackSharkViewPort;
BCanvas: TBCanvas;
procedure AfterCreateContextEvent (Sender: TBlackSharkContext);
public
end;
var
FrmMain: TFrmMain;
implementation
{$R *.lfm}
{ TFrmMain }
procedure TFrmMain.FormShow(Sender: TObject);
begin
ViewPort := TBlackSharkViewPort.Create(PanelScreen);
{ set position right from PnlTools }
ViewPort.Left := PnlTools.Left + 1;
ViewPort.OnAfterCreateContext := AfterCreateContextEvent;
ViewPort.Align := alClient;
end;
procedure TFrmMain.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
BCanvas.Free;
end;
procedure TFrmMain.AfterCreateContextEvent(Sender: TBlackSharkContext);
var
txt: TCanvasText;
arc: TArc;
begin
BCanvas := TBCanvas.Create(ViewPort.CurrentScene, false, Self);
{ text example }
txt := TCanvasText.Create(BCanvas, nil);
txt.Text := 'Hello world!';
txt.Position2d := vec2(70, 150);
{ arc example }
arc := TArc.Create(BCanvas, nil);
arc.Radius := 100;
arc.Angle := 60;
arc.Fill := true;
arc.Color := BS_CL_ORANGE;
arc.Build;
arc.Position2d := vec2(250, 130);
end;
end.
The project sources are located in a
following folder: /tests/lazarus/Hello world/
Result: