X. Tutoriel 8. Réflexion par cube mapping▲
Aussi connu sous le nom d'environment mapping, ce tutoriel montre comment réaliser la réflexion d'un environnement sur un objet. Cette technique est utilisée pour simuler une surface réfléchissante dans une scène. Nous utilisons une texture cube map comme texture de réflexion. Cette texture est découpée en fragments dans le pixel shader pour simuler cette réflexion sur l'objet.
X-A. Code de la procédure▲
Pour commencer, nous chargeons la texture cube map qui sera utilisée comme texture de réflexion :
CTextureCubeMap *
textureCubeMap =
crm.LoadTextureCube("cm.jpg"
);
Puis nous envoyons la position de la caméra au shader dans l'espace modèle, position qui sera utilisée pour déterminer le vecteur de réflexion sur la surface normale.
/* Pour trouver la position de la caméra dans l'espace modèle :
la caméra (ou œil) est située en v0(0, 0, 0), nous multiplions v0 par l'inverse de la matrice de vue (V) puis par l'inverse de la matrice modèle (M). camPos = inv(M) * inv(V) * vec4(0, 0, 0, 1); */
vec4f camera_pos =
(
m_pCamera->
GetViewMatrix
(
) *
model ).inverse
(
) *
vec4f
(
0
, 0
, 0
, 1
.f);
// Envoi de la position de la caméra au shader
m_pShaderMesh->
SetUniform4fv
(
"camPosModel"
, 1
, &
camera_pos.x);
Le vecteur de réflexion calculé dans le vexter shader doit être multiplié par le vecteur de rotation de l'objet pour obtenir une réflexion correcte. Donc nous devons envoyer la partie rotation de la matrice modèle au vexter shader pour reprojeter le vecteur réflexion dans l'espace monde.
// Extraction de la matrice de rotation
mat3f model_mat3 =
mat3f
(
model);
// Envoi au shader
m_pShaderMesh->
SetUniformMatrix3x3fv
(
"matModelToWorld"
, 1
, GL_FALSE, &
model_mat3[0
]);
En ce qui concerne le GPU, nous calculons au sein du vertex shader la direction de la caméra dans l'espace modèle en soustrayant la position de la caméra à la position du vertex.
// Obtention de la direction de la caméra dans l'espace modèle
vec4
eyeDir =
normalize
(
position -
camPosModel);
Nous calculons ensuite le vecteur de réflexion :
reflect
(
eyeDir.xyz, normal);
Nous avons besoin de ramener le vecteur de réflexion vers l'espace monde :
/* Retrouver le vecteur réflexion entre la direction de la caméra et la normale du vertex, multiplier ce vecteur par la matrice de rotation du modèle (conversion vers l'espace monde) */
v_reflectionVector =
matModelToWorld *
reflect
(
eyeDir.xyz, normal);
Finalement, au sein du pixel shader, nous échantillonnons la texture cube map en utilisant le vecteur réflexion interpolé renvoyé par le vertex shader.
gl_FragColor =
textureCube
(
textureCubeMap, v_reflectionVector);
La capture d'écran ci-dessous montre la réflexion sur une théière. Pour effectuer le rendu du skybox, décommentez la ligne suivante du fichier Tutorial.cpp :
//#define RENDER_SKYBOX