
Depuis la mise à jour 6.0.42, Unity a significativement amélioré Shader Graph, notamment pour le support des shaders destinés aux interfaces utilisateur. Ces améliorations permettent de créer des effets visuels compatibles avec le système UI (Canvas).
Dans cet article, nous allons reproduire l’effet de fond animé du jeu Balatro, en commencent par un peu de code HLSL puis l’utilisation basique d’une node Custom Function de Shader Graph.

Le code HLSL présenté ici est une adaptation d’un shader disponible sur ShaderToy (voir l’original). Il a été modifié pour être compatible avec Shader Graph, et peut être utilisé directement dans une node Custom Function, facilitant ainsi son intégration dans un shader plus complexe.
1. Création du shader
void SpinEffect_float(
float4 Color1,
float4 Color2,
float4 Color3,
float2 ScreenCoords,
float Time,
out float4 OutColor
)
{
// Configuration (identique à Shadertoy)
const float SPIN_ROTATION = -2.0;
const float SPIN_SPEED = 7.0;
const float2 OFFSET = float2(0.0, 0.0);
const float CONTRAST = 3.5;
const float LIGTHING = 0.4;
const float SPIN_AMOUNT = 0.25;
const float PIXEL_FILTER = 745.0;
const float SPIN_EASE = 1.0;
const bool IS_ROTATE = false;
const float2 ScreenSize = float2(1, 1);
float pixel_size = length(ScreenSize) / PIXEL_FILTER;
float2 uv = floor(ScreenCoords / pixel_size) * pixel_size;
uv = (uv - 0.5 * ScreenSize) / length(ScreenSize) - OFFSET;
float uv_len = length(uv);
float speed = (SPIN_ROTATION * SPIN_EASE * 0.2);
if (IS_ROTATE)
{
speed = Time * speed;
}
speed += 302.2;
float new_pixel_angle = atan2(uv.y, uv.x) + speed - SPIN_EASE * 20.0 * (1.0 * SPIN_AMOUNT * uv_len + (1.0 - 1.0 * SPIN_AMOUNT));
float2 mid = (ScreenSize.xy / length(ScreenSize.xy)) / 2.0;
uv = (float2((uv_len * cos(new_pixel_angle) + mid.x), (uv_len * sin(new_pixel_angle) + mid.y)) - mid);
uv *= 30.0;
speed = Time * (SPIN_SPEED);
float2 uv2 = float2(uv.x + uv.y, 0);
[unroll]
for (int i = 0; i < 5; i++)
{
uv2 += sin(max(uv.x, uv.y)) + uv;
uv += 0.5 * float2(cos(5.1123314 + 0.353 * uv2.y + speed * 0.131121), sin(uv2.x - 0.113 * speed));
uv -= 1.0 * cos(uv.x + uv.y) - 1.0 * sin(uv.x * 0.711 - uv.y);
}
float contrast_mod = (0.25 * CONTRAST + 0.5 * SPIN_AMOUNT + 1.2);
float paint_res = min(2.0, max(0.0, length(uv) * (0.035) * contrast_mod));
float c1p = max(0.0, 1.0 - contrast_mod * abs(1.0 - paint_res));
float c2p = max(0.0, 1.0 - contrast_mod * abs(paint_res));
float c3p = 1.0 - min(1.0, c1p + c2p);
float light = (LIGTHING - 0.2) * max(c1p * 5.0 - 4.0, 0.0) + LIGTHING * max(c2p * 5.0 - 4.0, 0.0);
OutColor = (0.3 / CONTRAST) * Color1 + (1.0 - 0.3 / CONTRAST) * (Color1 * c1p + Color2 * c2p + float4(c3p * Color3.rgb, c3p * Color1.a)) + light;
}
Enregistrez ce code dans un fichier nommé « nomdefichier.hlsl » et placez-le dans votre projet Unity.
2. Création du ShaderGraph
Faites un clic droit dans l’onglet Project, sélectionnez Create > Shader Graph > URP > Canvas Shader Graph, nommez le shader, puis double-cliquez dessus pour l’ouvrir.

3. Paramétrer la node CustomFunction
La node Custom Function doit être configuré en fonction du script HLSL utilisé. Vous pouvez également modifier votre script pour exposer d’autres variables et les rendre ajustables directement depuis Shader Graph.

4. Shader Graph
Vous pouvez maintenant manipuler votre effect comme vous le souhaitez, simplement avec les UV ou alors comme dans l’exemple avec un WorldSpace UV Projection.

5. Utilisation dans le projet
Vous êtes désormais prêt à intégrer l’effet visuel de Balatro dans votre jeu.
L’effet est très facilement adaptable grâce notamment à ShaderGraph et l’utilisation des Custom Function, n’hésitez pas à créer plusieurs Materials à partir de votre shader et à expérimenter différents paramètres.
Voici un exemple d’intégration dans un Canvas (Screen Space – Camera).

Quoi d’autre ?
Cette article fera peut-être l’object de mise à jour.
– MARTIN B.