10.1 Introduction

Tout ce que nous venons de voir en ce qui concerne l'écriture des vertex shaders et des fragments shaders est fondamental, mais cela équivaux à écrire des fichiers sources d'un programme, avec uniquement les fichiers sources le programme n'existe pas, il va falloir le compiler.

Mais comment on compile un programme pour GPU ?

Contrairement aux programme que vous avez déjà fait, un programme pour GPU, fait avec des shaders (ce n'est pas la seul méthode, mais nous verrons l'autre plus tard... beaucoup plus tard), se compile dynamiquement, c'est à dire que c'est à l'initialisation de votre programme en C ou en C++ que vous aller demander à OpenGl de compiler les shaders sur le GPU pour faire un programme (au même titre qu'un programme de CPU) qui s'occupera du rendu de votre application.

Comme nous allons devoir faire ces manips, dans chaque programme, nous allons nous faire un fichier load_shaders.h et un fichier load_shaders.c pour y mettre tout ce que nous allons apprendre.

Voici déjà à quoi ressemble le fichier load_shaders.h :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#ifndef __LOAD_SHADERS_H__
#define __LOAD_SHADERS_H__

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define GL3_PROTOTYPES 1
#include <GL3/gl3.h>

#ifdef __cplusplus
extern "C" {
#endif

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

int linkGlProgram(GLuint programID);

#ifdef __cplusplus
}
#endif

#endif

Vous vous rappelez de :

1
2
3
4
5
6
7
8
9
#ifdef __cplusplus
extern "C" {
#endif

...

#ifdef __cplusplus
}
#endif

Pour permettre au C++ d'utiliser des fonctions écrites en C.

Comme vous pouvez le voir nous n'allons pas écrire beaucoup de fonctions, mais nous allons nous en servir à chaque programme.

Et voici le début du fichier load_shaders.c :

1
#include "load_shaders.h"

Et nous allons rajouter une fonction qui renvoie l'ensemble des caractères d'un fichier dans une chaîne :

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
char* loadSource(const char *filename){
	char *src = NULL;   /* code source de notre shader */
	FILE *fp = NULL;    /* fichier */
	long size;          /* taille du fichier */
	long i;             /* compteur */
	/* on ouvre le fichier */
	fp = fopen(filename, "r");
	/* on vérifie si l'ouverture a échoué */
	if(fp == NULL){
		fprintf(stderr, "impossible d'ouvrir le fichier '%s'\n", filename);
		return NULL;
	}
	/* on récupère la longueur du fichier */
	fseek(fp, 0, SEEK_END);
	size = ftell(fp);
	/* on se replace au début du fichier */
	rewind(fp);
	/* on alloue de la mémoire pour y placer notre code source */
	src = malloc(size+1); /* +1 pour le caractère de fin de chaîne '\0' */
	if(src == NULL){
		fclose(fp);
		fprintf(stderr, "erreur d'allocation de mémoire!\n");
		return NULL;
	}
	/* lecture du fichier */
	for(i=0; i<size; i++)
		src[i] = fgetc(fp);
	
	/* on place le dernier caractère a '\0' */
	src[size] = '\0';
	fclose(fp);
	return src;
}

Aller, on continue.