quelles sont les informations nécessaires ? la position du point, la normale de la surface portant le point, et la position de la source de lumière.
dans quels repères connait-on ces valeurs ?
position du point, normale à la surface : a priori, on connait les valeurs dans le repere local de l'objet
position de la camera : c'est l'origine (0, 0, 0) dans le repère camera...
position de la source de lumière : à choisir, mais a priori ce sera une position dans le repère du monde.
de quelles transformations a-t-on besoin ? (pour les passer dans le repère du monde)
passage repère local de l'objet vers monde : matrice model
passage repère camera vers monde : inverse de la matrice camera / view. (pourquoi l'inverse ?)
passage repère local de l'objet vers camera : matrice (view * model). (pourquoi pas model * view ?)
d'ou viennent les valeurs ?
position du point : c'est un attribut de sommet, déclaré comme entrée du vertex shader, cf Mesh::vertex()
normale de la surface : c'est aussi un attribut de sommet, déclaré comme entrée du vertex shader, cf Mesh::normal()
position de la source de lumière : c'est un paramètre uniform du shader, déclaré comme une variable globale. c'est l'application qui fixe sa valeur. cf program_uniform()
matrice de transformation : c'est aussi un paramètre uniform du shader, déclaré comme une variable globale. c'est l'application qui fixe sa valeur. cf program_uniform()
#version 330
#ifdef VERTEX_SHADER
layout(location= 0) in vec3 position; // attribut de sommet
layout(location= 2) in vec3 normal; // attribut de sommet
uniform mat4 mvpMatrix; // matrice passage du repere local au repere projectif homogene de la camera
uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 viewInvMatrix;
void main( )
{
// obligation du vertex shader : calculer les coordonnées du sommet dans le repère projectif homogene de la camera
gl_Position= mvpMatrix * vec4(position, 1);
// normale de la surface, dans le repere monde
vec3 n=
mat3(modelMatrix) * normal;
// position de la camera dans le repere du monde
vec4 sourceh= xxxMatrix * vec4(0, 0, 0, 1);
// rappel : mat4 * vec4 = vec4 homogne, pour retrouver le point / la direction reelle, il faut diviser par la 4ieme composante
vec3 source= sourceh.xyz / sourceh.w;
// direction entre le sommet et la source de lumiere
vec3 l= source - position;
// calculer le cosinus de l'angle entre les 2 directions, a verifier...
float cos_theta= dot(n, l);
// transmettre l'orientation au fragment shader...
a completer
}
#endif
#ifdef FRAGMENT_SHADER
// recuperer l'orientation calculee dans le vertex shader... a completer
out vec4 fragment_color;
void main( )
{
// utiliser l'orientation pour modifier la couleur de base...
a completer
fragment_color= vec4(1, 0.5, 0, 1); // orange opaque
}
#endif
Les attributs de sommets viennent de Mesh::texcoord( ) et la texture doit d'abord etre chargée avec read_texture(0, fichier ) (cf texture.h) et utilisee lors de l'affichage avec program_use_texture( ) (cf uniforms.h).layout(location= 1) in vec2 texcoord; // uniquement dans un vertex shader
uniform sampler2D texture0;
// dans n'importe quel shader
Mesh grid= Mesh(GL_TRIANGLES);
for(int z= 0; z < 100; z++)
for(int x= 0; x < 100; x++)
{
grid.vertex(x, 0, z);
grid.vertex(x+1, 0, z);
grid.vertex(x+1, 0, z+1);
grid.vertex(x, 0, z);
grid.vertex(x+1, 0, z+1);
grid.vertex(x, 0, z+1);
}
uniform float time;
dans le
shader et de lui donner une valeur dans l'application avec program_uniform(program,
"time", (float) global_time());
floor(cos_theta
* 5) / 5