Three.js ShaderMaterial GLSL Tuto 2

ShaderMaterial et GLSL – Notre premier Shader

Cette publication est la seconde partie du thème GLSL,je vous conseille de lire la première partie si ce n’est pas déjà fait :

La classe ShaderMaterial

Constructeur

Commençons avec ShaderMaterial : On utilise cette classe pour créer un matériau de rendu avec un shader personnalisé en GLSL.

Le constructeur de ShaderMaterial accepte un paramètre : Un objet JavaScript utilisé pour configurer l’instance de classe.

Trois éléments principaux composent une instance de ShaderMaterial :

  • Une fonction Vertex Shader ( Code GLSL )
  • Une fonction Fragment Shader ( Code GLSL )
  • Uniforms ( Objet JavaScript )

Vertex et Fragment Shader – Introduction

Comme expliqué, un shader est composé de deux fonctions principales : Vertex Shader et Fragment Shader.

GLSL Vertex Fragment shader
Le code GLSL des Vertex & Fragment Shaders

Ces deux fonctions sont écrites en GLSL, et généralement manipulées en JavaScript via des chaînes de caractères formatées en Template String.

Vertex et Fragment Shader – Utilisation

Lorsque nous utiliserons ShaderMaterial en duo avec une Geometry pour créer un Mesh, le code GLSL de notre shader modifiera l’aspect visuel final de l’objet 3D.

Concrètement :

  • Le code GLSL de Vertex Shader s’exécute pour chaque sommet de la structure de l’objet 3D
  • Le code GLSL de Fragment Shader calcule la couleur de chaque pixel des faces de l’objet 3D
Vertex shader et Fragment shader
Vertex shader et Fragment shader

Ainsi, il est possible de modifier la forme de la structure 3D avec Vertex Shader, et créer des effets de couleurs avec Fragment Shader

L’objet JavaScript Uniforms

Pour finir, l’objet JavaScript Uniforms est le troisième élément composant une instance de ShaderMaterial.

C’est un élément facultatif, structuré avec un système de clé / valeur , permettant de passer des données entre le JavaScript et GLSL.

ShaderMaterials Uniforms
ShaderMaterial Uniforms

Uniforms est un élément facultatif, mais très utile dans la réalisation de shaders complexes ! Nous ne l’utiliserons pas dans cet article.

Notre premier Shader

Mise en place des bases

Créons notre premier shader avec GLSL et ShaderMaterial !

Commençons par créer un simple cube dans une scène de base :

var boxGeo = new THREE.BoxGeometry(2,2,2);
var boxMat = new THREE.MeshPhongMaterial();
boxmesh = new THREE.Mesh(boxGeo, boxMat);
scene.add(boxmesh);
Un cube de base
Un cube basique

Le shading des matériaux Three.js propose énormément d’options de personnalisations, mais imaginons que nous souhaitions créer notre propre effet visuel !

Pour cela, créons une instance de ShaderMaterial :

var myshader =  new THREE.ShaderMaterial({
  uniforms 		: uniforms,
  fragmentShader	: fragmentShader(),
  vertexShader		: vertexShader(),
});

Souvenez vous ! Une instance ShaderMaterial est composée de trois éléments :

  • Une fonction Vertex Shader ( Code GLSL )
  • Une fonction Fragment Shader ( Code GLSL )
  • Uniforms ( Objet JavaScript )

Continuons en créant une version ultra basique de ces trois éléments :

var uniforms = {};

function vertexShader()
{
    //GLSL Code
    return ` `;
}

function fragmentShader()
{
    //GLSL Code
    return ` `;
}	

Chaque fonction vertexShader et fragmentShader que nous venons de créer renvoie une chaîne de caractères formatée en Template String : C’est cette chaîne de caractères qui contiendra notre code GLSL !

Vertex Shader

Commençons par vertexShader, le code GLSL qui s’appliquera sur chaque sommet de la structure de notre objet 3D :

function vertexShader()
{
    return `
	void main()
	{
		gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
	}
    `;
}

Le GLSL est un langage particulier, je ne vais malheureusement pas pouvoir vous l’enseigner en quelques lignes haha !

Mais, nous pouvons tout de même commenter un peu ce code minimaliste :

  • La fonction main sera le point d’entrée du shader GLSL
  • La syntaxe de GLSL est basée sur le C
  • vec4 est un type de base représentant un vecteur a quatre dimensions
  • gl_Position est une variable intégrée de base au shader représentant la position du sommet (vertex) courant

Concrètement, cette ligne de code affichera simplement chaque sommet de l’objet 3D en fonction du point d’observation, sans modifier la forme globale de la structure.

Fragment Shader

Continuons avec fragmentShader, le code GLSL s’appliquant sur chaque pixel des faces de notre objet 3D :

function fragmentShader()
{
  return `
      void main()
      {
         gl_FragColor = vec4( 1.0, 1.0, 0.0, 1.0);
      }
  `;
}

Comme pour vertexShader, je vais commenter un peu ce code minimaliste :

  • gl_FragColor est une variable intégrée de base au shader représentant la couleur du pixel courant
  • La valeur de gl_FragColor est un vec4 dont les trois premières valeurs représentent la couleur RGB souhaitée
  • Chaque valeur RGB évolue entre 0.0 et 1.0 ( Dans notre cas, j’ai choisi un jaune vif )

Concrètement, ce code GLSL de base définira la couleur de chaque pixel de notre objet 3D par un jaune brut.

Résultat final

Notre shader GLSL est enfin prêt, remplaçons le Material de notre cube par notre instance de ShaderMaterial :

var myshader =  new THREE.ShaderMaterial({
  uniforms 		: uniforms,
  fragmentShader	: fragmentShader(),
  vertexShader		: vertexShader(),
});

var boxGeo = new THREE.BoxGeometry(2,2,2);
var boxMat = new THREE.MeshPhongMaterial();
boxmesh = new THREE.Mesh(boxGeo, myshader);
scene.add(boxmesh);
Notre premier ShaderMaterial
Notre premier ShaderMaterial !

Comme prévu, notre cube est teinté d’une couleur jaune brute, félicitations !

GLSL est offre des possibilités quasi-infinies, pour continuer a découvrir ce langage, je vous donne rendez-vous dans de prochaines publications !

Un commentaire

Les commentaires sont fermés.