10.3 Initialiser les shaders

Il est vrai que pour le moment vous savez écrire un shader simple, mais il faut l'initialiser. Il faut donc charger le fichier .vert, puis le fichier .frag.

Pour initialiser les shaders, nous allons créer une fonction :

1
GLuint loadShader(GLenum type, const char *filename);

Qui renverra l'identifiant du shader, type sera le type de shader :

  • GL_FRAGMENT_SHADER : pour les fragment shaders
  • GL_VERTEX_SHADER : pour les vertex shaders

Et filename sera le nom du fichier .frag ou .vert que l'on voudra charger.

L'avantage est que l'on aura qu'une seule fonction pour charger deux shaders différents.

Voilà à quoi ressemble cette fonction :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
GLuint loadShader(GLenum type, const char *filename){
	GLuint shader = 0;
	GLsizei logsize = 0;
	GLint compile_status = GL_TRUE;
	char *log = NULL;
	char *src = NULL;
	shader = glCreateShader(type); /* création d'un shader de type type */
	if(shader == 0){
		fprintf(stderr, "impossible de créer le shader\n");
		return 0;
	}
	src = loadSource(filename);           /* chargement du code source */
	if(src == NULL)	{
		glDeleteShader(shader);
		return 0;
	}
	glShaderSource(shader, 1, (const GLchar**)&src, NULL); /* assignation du code source */
	glCompileShader(shader);                               /* compilation du shader */
	free(src);                                             /* libération de la mémoire du code source */
	src = NULL;
	glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status); /* vérification du succès de la compilation */
	if(compile_status != GL_TRUE){      /* erreur a la compilation récupération du log d'erreur */
		glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logsize);  /* on récupéré la taille du message d'erreur */
		log = malloc(logsize + 1);                            /* on alloue un espace mémoire dans lequel OpenGL écrira le message */
		if(log == NULL){
			fprintf(stderr, "impossible d'allouer de la mémoire !\n");
			return 0;
		}
		memset(log, '\0', logsize + 1);                    /* initialisation du contenu */
		glGetShaderInfoLog(shader, logsize, &logsize, log);
		fprintf(stderr, "impossible de compiler le shader '%s' :\n%s", filename, log);
		free(log);                                         /* ne pas oublier de libérer la mémoire et notre shader */
		glDeleteShader(shader);
		return 0;
	}
	return shader;
}

Je ne vais pas vous décrire son fonctionnement car, il y suffisamment de commentaires pour cela. En plus, le problème n'est pas vraiment dans la compréhension de ce la fonction fait, le tout étant que savoir quand l'utiliser, patience ça viendra.