SFML community forums
Help => Graphics => Topic started by: ThePersonWithAQuestion on April 26, 2025, 01:06:13 pm
-
Hello there, I'm here again with a new question. To make it short, I want to shade text to like like what you see in this picture:
(https://romhustler.org/img/screenshots/neogeo/ingame/shocktro.png)(https://archive.org/serve/arcade_mslug/mslug_screenshot.png)(https://archive.org/serve/arcade_aof/arcade_aof_screenshot.png)
Every text is different, but what they share is that they have different coloring depending on their pixel position. I wonder what's the best strategy to achieve this. By the way, I'm using ttf fonts.
-
I don't think SFML supports this. You might be able to duplicate the effect by drawing a font like this then making something that places each letter along a specified position. You could also make an array ID list to reference the needed image IntRect in relation to the char requested. That is a bit of a hackish method but I think it is basically same to what they did in those example games anyway.
-
Presumably, the vertical gradient is to what you refer?
This effect can be done in SFML simply with two very different methods.
The first would be to use a bitmap text instead of a scalable text (like TTF, for example).
One example of this is Selba Ward's Bitmap Text (https://github.com/Hapaxia/SelbaWard/wiki/Bitmap-Text):
(https://i.imgur.com/Er0fpAZ.png)
The second would be to use a fragment shader. Fragment shaders adjust the pixel dependant on a multitude of things but included is the pixel position so you can, for example, just adjust the colour based on the y position of the fragment (pixel). Note, though, that OpenGL fragment shaders use non-inverted y axis; that is, the opposite to SFML - the y value increase as it goes up instead of down.
These can seem to be a bit complicated at first but once you get used to them, they are very powerful and flexible, and - I expect - would be the ideal approach for your situation.
EDIT:
In addition, there is another rather simple solution but adds additional overhead (cost of the simplicity):
Render the text to a render texture and the draw that render texture with a quad (vertex array). This vertex array can have different colours per vertex so each corner can have a different colour. This allows both the top corners to be the same and both the bottom ones to be the same. However, the top and bottom can be different, causing linear interpolation - vertically - causing a gradient. If you want to try this method, remember to render the text as while (on a transparent render texture) and note that you can only pick two colours (the top and bottom) so you cannot have it go from one colour to another and back again without splitting the quad into pieces (although that is relatively simple to do too!).
-
A fourth option, although I've never done this and wouldn't know how, is to use stencil testing. So the rendered text becomes a stencil to use with another texture that has the gradient.
-
I realised that gradients in texts are so common that I really should have a shader prepared for that sort of thing already but alas, I did not.
That was then (up to yesterday) and this is now!
I present to you my new shader: multiGradient (https://github.com/Hapaxia/Lens/wiki#multigradient)!
I've added it to be a part of my Lens (https://github.com/Hapaxia/Lens/tree/main) collection. All shaders are in the "Lens" folder of that directory.
For information on how to use it, you can read the short wiki entry:
https://github.com/Hapaxia/Lens/wiki#multigradient
It allows to provide multiple heights (y positions) and multiple colours to the shader. The shader then interpolates those colours based on the current y position, creating a gradient.
This can be used on textured or non-textured objects and there can be up to 16 different heights and colours!
Here are a couple of quick test examples...
3 steps (3 different colours - yellow, magenta, cyan):
(https://i.imgur.com/jmO95oT.png)
10 steps (10 different colours, yellow, magenta, cyan, white, blue, yellow, magenta, cyan, red, black):
(https://i.imgur.com/j8e9Wjw.png)