The latest RAD Studio / C++ Builder 12 comes with a lot of new features, one of which is Skia graphics library support in C++. Skia is an open-source graphic library that provides to support a variety of hardware and software platforms. One of Skia’s amazing features is its support for the shader graphics SkSL Shading Language. That means you can use GPU Shaders with Skia in C++ Builder 12. In this post, we explain what a shader is, what is the SkSL Shading language, how you can create Skia shader code, and how you can run animations based on SkSL code in C++ Builder.
Table of Contents
What is Skia in modern C++?
Skia is an open-source graphic library that provides support variety of hardware and software platforms. Skia is sponsored and managed by Google but is available for use by anyone under the BSD Free Software License. Mainly designed for Google Chrome and ChromeOS, Android, Flutter, Mozilla Firefox and Firefox OS, and many other products. The core components are done by the Skia development team but they consider contributions from any source.
What is a Shader?
In modern graphics, a Shader is a GPU based program that calculates pixel colors by using Shader tasks in GPU, such as levels of light, darkness, and color during the rendering of a 3D scene. This process is known as a shading process, and it is a GPU based computation. Modern graphic cards have evolved to perform a variety of specialized functions in computer graphics, and shaders can be used for special effects and video post-processing, as well as general-purpose computing on graphics processing units. They can be used in some GPU based multi-threaded operations. Here is a good example how your graphics are improved by shaders.
For example, the latest NVidia GPU RTX 4090 has 16384 shading units that have a total of 83 TFLOPS performance in its shader cores. In other words, shaders are power to graphical calculations, and in the last decade, they are very popular by 2D and 3D mathematicians, and computer programmers.
If you want to know what Shader examples are visit https://shaders.skia.org The Shadertoy website also has thousands of shader examples that you can modify for Skia SkSL code. You can find ShaderToy here: https://www.shadertoy.com
What is the SKSL Shading Language in C++?
SkSL codes are very similar to C/C++ code, and it is Skia’s shading language. SkRuntimeEffect is a Skia C++ object that can be used to create SkShader
, SkColorFilter
, and SkBlender
objects with behavior controlled by SkSL code. Here are some SkSL code examples at Skia’s official page https://shaders.skia.org
The syntax of SkSL is very similar to GLSL. When using SkSL effects in your Skia application, there are important differences (from GLSL) to remember. Most of these differences are because of one basic fact: With GPU shading languages, you are programming a stage of the GPU pipeline. With SkSL, you are programming a stage of the Skia pipeline. Please see here for more details about https://skia.org/docs/user/sksl/
Here is a very simple SkSL code that changes the color of a pixel over time. Here we have vec2 fragCoord input which is the coordinates of x and y, and we have vec4 output which returns the color of pixel in ARGB form. This is how a shader works,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
uniform float iTime; uniform float2 iResolution; vec4 main(vec2 fragCoord ) { // Normalized pixel coordinates (from 0 to 1) vec2 uv = fragCoord/iResolution.xy; // Time varying pixel color vec3 col = 0.5 + 0.5*cos(iTime+uv.xyx+vec3(0,2,4)); // Output to screen return vec4(col,1.0); } |
As you see it is very similar to C++ codes, so you can use and create more mathematical functions there.
How to use Skia shader sksl shading language code in C++ Builder?
1. Add a SkAnimatedPaintBox to your form
If you want to use Skia Shaders, first you need to drag TSkAnimatedPaintBox on your form, this will refresh drawing in a given duration. You can set it’s animation properties as below,
2. Declare some Skia globals in your form header
In your form header you can add these our Skia variables,
1 2 3 4 5 6 |
public: // User declarations _di_ISkRuntimeEffect LEffect; _di_ISkRuntimeShaderBuilder LShaderBuilder ; _di_ISkShader LShader; |
3. Create your simple SkSL code to be used as a text
Here is a very simple SkSL code that changes color of pixels by time (iTime), in its resolution (iResolution). Here we have vec2 input which is coordinates of x and y, and we have vec4 output which is color of pixel in ARGB form. This is how a shader works,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
uniform float iTime; uniform float2 iResolution; vec4 main(vec2 fragCoord ) { // Normalized pixel coordinates (from 0 to 1) vec2 uv = fragCoord/iResolution.xy; // Time varying pixel color vec3 col = 0.5 + 0.5*cos(iTime+uv.xyx+vec3(0,2,4)); // Output to screen return vec4(col,1.0); } |
Or you can use SkSL codes from https://shaders.skia.org/. Or you can modify https://www.shadertoy.com/
I made some simple example in there too. https://www.shadertoy.com/user/yyoru
4. Load SkSL Shader Language codes and make shader in C++ Builder
Now we can add a button to start doing effects from a text which is a SkSL code, this text can be obtained from a String, from a file, or a component such as from a Memo1->Text. We can use this SKSL code to create the Skia Runtime Effect by using the TSkRuntimeEffect::MakeForShader() method, and we can create Runtime Shader Builder by using the SkRuntimeShaderBuilder() method, and finally, we can make a shader by using MakeShader() method. Before these, we should stop animation and then we should start animation. If we sum up all, a Button1Click() can be as below,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
void __fastcall TForm1::Button1Click(TObject *Sender) { SkAnimatedPaintBox1->Animation->StopAtCurrent(); SkAnimatedPaintBox1->Animation->Enabled = false; LEffect = TSkRuntimeEffect::MakeForShader(Memo1->Text, Error); LShaderBuilder = SkRuntimeShaderBuilder(LEffect); LShader = LShaderBuilder->MakeShader(); SkAnimatedPaintBox1->Animation->Enabled = true; SkAnimatedPaintBox1->Animation->Start(); } |
5. Configure animation drawing event in C++ Builder
Now, select this SkAnimatePaintBox1 object, and double click to OnAnimationDraw() event on its Events tab section.
Here if LShaderBuilder is created we can update Shader by using some SkSL globals, such as iResolution, iTime, iMouse if your SkSL code uses these globals. Then we create a new SkPaint() and we draw this to the current ACanvas of this AnimationPaintBox by using ACanvas->DrawPaint(LPaint);
. Here is how we can do this,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
void __fastcall TForm1::SkAnimatedPaintBox1AnimationDraw(TObject *ASender, ISkCanvas * const ACanvas, const TRectF &ADest, const double AProgress, const float AOpacity) { if(LShaderBuilder) { if(LEffect->UniformExists("iResolution")) LShaderBuilder->SetUniform("iResolution", PointF(SkAnimatedPaintBox1->Width, SkAnimatedPaintBox1->Height)); if(LEffect->UniformExists("iTime")) LShaderBuilder->SetUniform("iTime", (float) SkAnimatedPaintBox1->Animation->CurrentTime); if(LEffect->UniformExists("iMouse")) LShaderBuilder->SetUniform("iMouse", PointF( MX, MY) ); LShader = LShaderBuilder->MakeShader(); auto LPaint = SkPaint(); LPaint->Shader = LShader; ACanvas->Save(); try { ACanvas->ClipRect(ADest); ACanvas->DrawPaint(LPaint); } __finally { ACanvas->Restore(); } } } |
How can I use more advanced Shaders in C++ Builder?
Shader codes are little brain burning codes while they are close to C++ codes, 3D operations in math are mind blowing. If you still say its okay, I can watch an example, here is a wonderful code example that runs 3D funny creature on the ground. You can find many shader examples on Youtube.
or you can try this,
If you want to see more examples, please install the latest RAD Studio / C++ Builder12.1 full or trial version and check this sample in Samples folder:C:\Users\Public\Documents\Embarcadero\Studio\23.0\Samples\CPP\Multi-Device Samples\Skia4Delphi
project. It has many examples that runs different Skia graphical examples.
C++ Builder is the easiest and fastest C and C++ compiler and IDE for building simple or professional applications on the Windows operating system. It is also easy for beginners to learn with its wide range of samples, tutorials, help files, and LSP support for code. RAD Studio’s C++ Builder version comes with the award-winning VCL framework for high-performance native Windows apps and the powerful FireMonkey (FMX) framework for UIs.
There is a free C++ Builder Community Edition for students, beginners, and startups; it can be downloaded from here. For professional developers, there are Professional, Architect, or Enterprise versions of C++ Builder and there is a trial version you can download from here.