⚡️ Limited Black Friday Deal
Get 50% off on the React Three Fiber Ultimate Course with the promo code ULTIMATE50
Buy Now
Fundamentals
Core
Master
Shaders
Fonctions de mise en forme
La logique du shader est spéciale, elle est différente de celle à laquelle nous sommes habitués en JavaScript ou dans d'autres langages de programmation. Bien que la syntaxe soit similaire, la manière dont nous implémentons la logique est différente. C'est un peu comme une boîte noire, vous mettez des données et vous obtenez des couleurs pour le fragment shader ou des positions pour le vertex shader.
Mais comment contrĂ´lez-vous la sortie ? Comment le faire ressembler Ă ce que vous voulez ? C'est lĂ qu'interviennent les fonctions de mise en forme.
Nous nous concentrerons sur le fragment shader pour cette leçon, mais les mêmes principes s'appliquent au vertex shader.
Zone de pratique
Pour maîtriser l'art de la mise en forme, vous devrez pratiquer et expérimenter. Il faudra du temps pour s'habituer au fonctionnement du shader, mais une fois que vous en aurez pris l'habitude, vous pourrez créer des effets étonnants.
Parce que je veux vous mettre dans les meilleures conditions pour réussir, j'ai préparé cette scène de galerie d'art en 3D pour que vous puissiez visualiser vos shaders en temps réel dans un environnement agréable.
Sentez-vous votre créativité couler ? Tous ces cadres vides attendent vos chefs-d'œuvre !
Le modèle 3D utilisé est VR Gallery par Maxim Mavrichev et est sous licence Creative Commons Attribution.
J'ai utilisé <CameraControls />
pour créer une caméra à la première personne pour naviguer dans la galerie et Squoosh pour réduire la taille des textures.
SimpleShaderMaterial
Tous les cadres de la galerie sont des copies du SimpleShaderMaterial
, c'est un shader custom basique que j'ai préparé pour vous avec :
uColor
: une couleuruTime
: le temps écoulé depuis le début de l'applicationvUv
: les coordonnées UV du fragment (de 0 à 1 sur les deux axes)
Ils sont tous Ă©tendus dans le <App.jsx />
pour pouvoir les utiliser de manière déclarative dans notre scène.
Ils sont nommés en fonction de leur position dans la galerie, mais n'hésitez pas à les renommer en quelque chose de plus significatif une fois que vous aurez créé des chefs-d'œuvre avec eux !
Fonctions
Pour chaque fragment de notre shader, notre même code sera exécuté avec des entrées différentes.
Si nous voulons dessiner une ligne, nous pourrions utiliser des instructions if pour vérifier si le pixel est à l'intérieur de la ligne ou non. Mais faire des formes plus complexes serait très difficile et inefficace.
Au lieu de cela, nous utilisons des fonctions pour façonner notre sortie. Ne vous inquiétez pas, vous n'avez pas besoin d'être un expert en mathématiques pour les utiliser. Vous avez seulement besoin de comprendre quelles fonctions sont à votre disposition, et ce qu'elles font.
Pensez à une fonction comme à une machine qui prend en entrée et vous donne une sortie. Par exemple, la fonction
f(x) = x * 2
prend un nombrex
et vous donnex * 2
comme résultat.
Pour visualiser l'effet des différentes fonctions, nous utiliserons Graphtoy, c'est un outil simple pour taper des fonctions et voir leur sortie. Cela aide à valider notre compréhension des fonctions lorsque nous les expérimentons dans nos shaders.
Visualisons notre fonction f(x) = x * 2
dans Graphtoy :
Graphtoy deviendra rapidement votre meilleur ami lorsque vous expérimentez avec des shaders.
Il est temps d'expérimenter avec les différentes fonctions à notre disposition.
Step
La fonction step est une fonction simple qui renvoie 0
si l'entrée est inférieure à un seuil, et 1
si l'entrée est supérieure au seuil.
Elle prend deux paramètres :
edge
: le seuilx
: la valeur d'entrée
Essayons-la sur le shader de fragment du cadre avant ArtFront02Material.jsx
:
void main() { float pct = 1.0; pct = step(0.5, vUv.x); vec3 finalColor = pct * uColor; gl_FragColor = vec4(finalColor, 1.0); }
Nous déclarons une variable pct
pour déterminer le pourcentage de la couleur que nous voulons afficher. Nous la définissons à 1.0
par défaut, puis nous utilisons la fonction step
pour la définir à 0.0
si le vUv.x
est inférieur à 0.5
.
On peut voir que la moitié gauche du cadre est noire, et la moitié droite est la couleur définie dans l'uniforme uColor
.
Appliquons-la à l'axe vertical avec un seuil différent :
void main() { float pct = 1.0; pct = step(0.2, vUv.y); vec3 finalColor = pct * uColor; gl_FragColor = vec4(finalColor, 1.0); }
On peut voir que 20 % du bas du cadre est noir, et le reste est violet.
Les coordonnées UV ont leur origine dans le coin inférieur gauche du cadre, donc
[0, 0]
est le coin inférieur gauche, et[1, 1]
est le coin supérieur droit.
Si vous voulez inverser l'effet, vous pouvez simplement échanger les paramètres de la fonction step
:
void main() { float pct = 1.0; pct = step(vUv.y, 0.2); vec3 finalColor = pct * uColor; gl_FragColor = vec4(finalColor, 1.0); }
Nous avons maintenant l'effet opposé.
Mix
La fonction mix est une fonction simple qui renvoie une interpolation linéaire entre deux valeurs.
Elle prend trois paramètres :
x
: la première valeury
: la seconde valeura
: la valeur Ă interpoler entrex
ety
Essayons-la :
void main() { float pct = 1.0; pct = mix(0.0, 1.0, vUv.x); vec3 finalColor = pct * uColor; gl_FragColor = vec4(finalColor, 1.0); }
Nous pouvons voir un joli dégradé de noir à violet.
Comme beaucoup d'autres fonctions, vous pouvez l'utiliser sur d'autres types de données, comme les composants de vecteur. Utilisons-la pour créer un dégradé de blanc à violet sur l'axe vertical :
void main() { vec3 whiteColor = vec3(1.0); vec3 finalColor = mix(whiteColor, uColor, vUv.y); gl_FragColor = vec4(finalColor, 1.0); }
Nous pouvons voir un joli dégradé de blanc à violet.
Changeons la valeur d'interpolation en appelant la fonction mix
une première fois pour obtenir la valeur pct
, puis utilisons-la pour interpoler entre whiteColor
et uColor
:
void main() { vec3 whiteColor = vec3(1.0); float pct = mix(0.0, 0.3, vUv.y); vec3 finalColor = mix(whiteColor, uColor, pct); gl_FragColor = vec4(finalColor, 1.0); }
Le violet est très clair car la valeur maximale de pct
est 0.3
.
Utilisez Graphtoy pour expérimenter avec la fonction mix
et comprendre son fonctionnement.
3 interpolations différentes avec la fonction mix
donnent des résultats complètement différents.
Smoothstep
La fonction smoothstep est une fonction simple qui retourne une interpolation lisse entre deux valeurs.
Elle prend trois paramètres :
edge0
: la bordure inférieureedge1
: la bordure supérieurex
: la valeur Ă interpoler entreedge0
etedge1
Elle donne trois résultats différents :
0.0
six
est infĂ©rieur Ăedge0
1.0
six
est supĂ©rieur Ăedge1
- une interpolation lisse entre
0.0
et1.0
six
est entreedge0
etedge1
Utilisons-la pour changer notre valeur pct
:
void main() { vec3 whiteColor = vec3(1.0); float pct = smoothstep(0.4, 0.6, vUv.y); vec3 finalColor = mix(whiteColor, uColor, pct); gl_FragColor = vec4(finalColor, 1.0); }
La transition se fait maintenant seulement entre 0.4
et 0.6
. Tout ce qui est en dessous est blanc, et tout ce qui est au-dessus est violet.
Min & Max
min
et max
sont des fonctions simples qui renvoient la valeur minimale ou maximale entre deux entrées. Elles fonctionnent exactement comme les fonctions Math.min
et Math.max
en JavaScript.
Utilisons-les pour affiner notre valeur pct
. D'abord, assurons-nous qu'elle ne soit jamais en dessous de 0.4
(ce qui signifie jamais totalement blanc):
void main() { vec3 whiteColor = vec3(1.0); float pct = smoothstep(0.4, 0.6, vUv.y); pct = max(pct, 0.4); vec3 finalColor = mix(whiteColor, uColor, pct); gl_FragColor = vec4(finalColor, 1.0); }
Et jamais au-dessus de 0.6
(ce qui signifie jamais totalement violet):
void main() { vec3 whiteColor = vec3(1.0); float pct = smoothstep(0.4, 0.6, vUv.y); pct = max(pct, 0.4); pct = min(pct, 0.6); vec3 finalColor = mix(whiteColor, uColor, pct); gl_FragColor = vec4(finalColor, 1.0); }
Les couleurs sont délavées, et la transition est très douce.
Visualisons-le sur Graphtoy :
Représentation de max(x, 0.4)
Représentation de min(x, 0.6)
Et si nous les combinons :
Vous pouvez voir que nos valeurs ne descendent jamais en dessous de 0.4
et ne montent jamais au-dessus de 0.6
.
Notre combinaison des fonctions
min
etmax
peut être remplacée par la fonction clamp, qui est une abréviation demin(max(x, min), max)
.
Opérations & motifs
Avant de découvrir de nombreuses autres fonctions utiles, voyons comment nous pouvons utiliser les opérations pour créer des motifs.
End of lesson preview
To get access to the entire lesson, you need to purchase the course.