Ombres en temps-réel

71
Ombres en temps-réel Nicolas Holzschuch Cours d’Option Majeure 2 [email protected]

description

Ombres en temps-réel. Nicolas Holzschuch Cours d’Option Majeure 2 [email protected]. Ombres en temps-réel. Pourquoi faire ? Les ombres Shadow maps Shadow volumes Ombres douces. Les ombres : pourquoi ?. Réalisme accru Positionnement spatial Information sur les objets - PowerPoint PPT Presentation

Transcript of Ombres en temps-réel

Page 1: Ombres en temps-réel

Ombres en temps-réel

Nicolas Holzschuch

Cours d’Option Majeure [email protected]

Page 2: Ombres en temps-réel

Ombres en temps-réel•Pourquoi faire ?

•Les ombres

•Shadow maps

•Shadow volumes

•Ombres douces

Page 3: Ombres en temps-réel

Les ombres : pourquoi ?•Réalisme accru

•Positionnement spatial

• Information sur les objets

• Informations sur le système graphique :– Comment ça marche, pourquoi,…– Nombreuses extensions, additions,…

Page 4: Ombres en temps-réel

Exemples+

Vidéo

Page 5: Ombres en temps-réel

Ombres dures/ombres douces•Vidéos

Page 6: Ombres en temps-réel

Techniques•2 méthodes :

– Shadow mapping• Basé image

– Shadow volumes• Basé objet

– Démos

Page 7: Ombres en temps-réel

Shadow mapping•Source lumineuse ponctuelle

•Principe :– Carte de profondeur de la scène– Vue depuis la source lumineuse

•Pour chaque pixel de l’image– Calculer position par rapport à la source– Calculer profondeur par rapport à la source– Comparer à la profondeur stockée– Égal : lumière, plus grand : ombre

Page 8: Ombres en temps-réel

Shadow volume•Source lumineuse ponctuelle

•Principe :– Silhouette des objets vus depuis la source– Plans infinis s’appuyant sur la source et sur

chaque arête– Définit « volume d’ombre »

•Pour chaque pixel de l’image :– Compter le nombre de plans entrants et sortants– Positif : ombre, nul : lumière

Page 9: Ombres en temps-réel

Et maintenant, les détails

Page 10: Ombres en temps-réel

Shadow mapping•Source lumineuse ponctuelle

•Principe :– Carte de profondeur de la scène– Vue depuis la source lumineuse

•Pour chaque pixel de l’image– Calculer position par rapport à la source– Calculer profondeur par rapport à la source– Comparer à la profondeur stockée– Égal : lumière, plus grand : ombre

Page 11: Ombres en temps-réel

Shadow mapping•A < B : ombre

lightsource

eyeposition

depth map Z = A

fragment’slight Z = B

depth map image plane

eye view image plane,aka the frame buffer

Page 12: Ombres en temps-réel

Shadow mapping•A≈B : lumière

lightsource

eyeposition

depth map Z = A

fragment’slight Z = B

depth map image plane

eye view image plane,aka the frame buffer

Page 13: Ombres en temps-réel

Carte de profondeur•Comment la générer ?

– Pourquoi c’est compliqué ?– back-buffer– pbuffers

•Précision/coût– En xy– En z

Page 14: Ombres en temps-réel

Pourquoi c’est compliqué ?

CPU

Mémoire

Disque dur

Carte-mère

Processeur graphique

Mémoire

Carte graphique

Écr

an

Page 15: Ombres en temps-réel

Comment faire ?•Le CPU ne peut pas faire le travail :

– Trop lent– Transfert trop lent

•C’est le processeur graphique qui travaille– Comment faire pour dessiner la scène sans

l’afficher ?– Deux solutions : back-buffer et pbuffers

Page 16: Ombres en temps-réel

Double-buffering•L’affichage peut être lent

•L’utilisateur voit la scène s’afficher morceau par morceau

– Gênant

• Idée : double-buffer– Deux buffers– On affiche le front-buffer– On dessine dans le back-buffer– Quand on est prêt : glutSwapBuffers();

Page 17: Ombres en temps-réel

Double-buffering•Suppose que la carte soit équipée :

– Coût mémoire supplémentaire (léger)– Automatique de nos jours

•À demander à la création du contexte OpenGL glutInitDisplayMode(GLUT_DEPTH|GLUT_RGB|GLUT_DOUBLE);

•Ne pas oublier d’échanger les buffers…

Page 18: Ombres en temps-réel

Application aux ombres•On a un endroit pour dessiner !

•On dessine la scène une première fois :– Avec la matrice de projection de la lumière– Directement dans le back-buffer– Ensuite, transfert en mémoire

•On dessine la scène une deuxième fois :– Avec la matrice de projection de la caméra– Toujours dans le back-buffer– Échange des buffers

Page 19: Ombres en temps-réel

Problème•Résolution du back-buffer limitée :

– À la résolution de la fenêtre– Problèmes d’aliasing

•Si je veux d’avantage de résolution :– pbuffers– Possibilité de rendu sur la carte, par le processeur,

dans une zone mémoire spécifique– Résolution plus grande que celle de la fenêtre– Mais pas illimitée– Pas toujours possible, dépend de la carte

Page 20: Ombres en temps-réel

Pour chaque pixel•Génération de coordonnées de texture

– Matrice de projection de la lampe + conversion– Résultat : (r,s,t) coordonnées de texture– r distance à la source– (s,t) coordonnées dans la carte de profondeur– Comparaison r / carteProfondeur(s,t)

•Extension OpenGL :– GL_ARB_SHADOW ou GL_SGIX_SHADOW

Page 21: Ombres en temps-réel

Extensions OpenGL• OpenGL :

– Spécifications (www.opengl.org)– Liste de fonctionnalités (glBegin, glEnd…)– Architecture Review Board (ARB)

• Extensions :– Nouvelles fonctionnalités– Décision par l’ARB (meetings)– Extensions « officielles » :

• http://oss.sgi.com/projects/ogl-sample/registry/• Spécifications approuvées, publiques• Nom et prototypes de fonctions publics• Différents niveaux d’intégration :

– GL_ARB_EXTENSION, GL_EXT_EXTENSION, GL_CONSTRUCTEUR_EXTENSION

Page 22: Ombres en temps-réel

Extensions OpenGL•Comment savoir si une extension est présente ?

– glxinfo– http://www.delphi3d.net/hardware/index.php

(liste cartes+drivers = extensions)– glutExtensionSupported("GL_SGIX_shadow");

•On y reviendra au prochain cours

Page 23: Ombres en temps-réel

GL_SGIX_SHADOWglTexParameteri(GL_TEXTURE_2D,

GL_TEXTURE_COMPARE_SGIX,

GL_TRUE);

glTexParameteri(GL_TEXTURE_2D,

GL_TEXTURE_COMPARE_OPERATOR_SGIX,

GL_TEXTURE_LEQUAL_R_SGIX);

• Implémentation très simple

Page 24: Ombres en temps-réel

Algorithme•Désactiver l’affichage des polygones

•Dessiner la scène

•Transférer le Z-buffer en mémoire

•Ré-activer l’affichage des polygones

•Affecter la carte de profondeur comme texture

•Activer la shadow-map

•Dessiner la scène

•Échanger les buffers

Page 25: Ombres en temps-réel

Algorithme•Désactiver l’affichage des polygones :

– glColorMask(0,0,0,0);– glDisable(GL_LIGHTING);

•Permet de gagner du temps– La carte graphique travaille moins

•Dessiner la scène

Page 26: Ombres en temps-réel

Algorithme• Récupérer le Z-buffer :

glCopyTexImage2D(GL_TEXTURE_2D,0, GL_DEPTH_COMPONENT16_SGIX,

0,0,width,height,0);

• Alternative : glReadPixels(0, 0, width, height,

GL_DEPTH_COMPONENT, taille, pointeur); glTexImage2D(GL_TEXTURE_2D, 0,

GL_DEPTH_COMPONENT16_SGIX,width, height, 0, GL_DEPTH_COMPONENT,

taille, pointeur);

• Double transfert CPU/carte graphique !

Page 27: Ombres en temps-réel

Algorithme•Ré-activer l’affichage des polygones :

glEnable(GL_LIGHTING);

glColorMask(1,1,1,1);

glViewport(0, 0, winWidth, winHeight);

•Activer la shadow map

•Dessiner la scène

•Échanger les buffers

Page 28: Ombres en temps-réel

Shadow mapping•Avantages :

– Très simple à implémenter– Code compact– Marche toujours (scène quelconque)

• Inconvénients :– Problèmes d’échantillonnage (xy et z)– Deux passes de rendu (vitesse divisée par deux)

• Ne pas regénérer systématiquement la shadow map, seulement si la source se déplace

– Besoin d’extensions OpenGL (disponibles ?)

Page 29: Ombres en temps-réel

Échantillonnage •Principal inconvénient

•Système discrétisé

•Double discrétisation : caméra et source lum.

•Conflit de précision

Page 30: Ombres en temps-réel

Précision en xy•La plus visible

•Solution : augmenter la résolution de la carte– Limite liée à la carte

•Pas toujours suffisant :– Projection de la texture depuis la source– Pixels après projection déformés et agrandis– Cas idéal : source proche de la caméra– Cas le pire : source opposée à la caméra

• Animal dans les phares (pas bon pour lui)

Page 31: Ombres en temps-réel

Cas idéal : lampe de spéléo

CaméraCaméra

SourceSource

La couleur La couleur représente l’aire représente l’aire projetée d’un projetée d’un élément de surface élément de surface

Le fantôme Le fantôme représente l’ombre représente l’ombre de l’objetde l’objet

Page 32: Ombres en temps-réel

Cas le pire : source opposée

CaméraCaméra

SourceSource

Page 33: Ombres en temps-réel

Source opposée

Page 34: Ombres en temps-réel

Résolution en xy•Principale source d’erreur

•Solutions :– Augmenter la résolution– Déformer la shadow map pour augmenter sa

résolution près de l’œil– Résolution adaptative

•Pas de solution idéale si la source est face à l’œil

Page 35: Ombres en temps-réel

Shadow mapping•A < B : ombre

lightsource

eyeposition

depth map Z = A

fragment’slight Z = B

depth map image plane

eye view image plane,aka the frame buffer

Page 36: Ombres en temps-réel

Shadow mapping•A ≈ B : lumière

lightsource

eyeposition

depth map Z = A

fragment’slight Z = B

depth map image plane

eye view image plane,aka the frame buffer

Page 37: Ombres en temps-réel

Problèmes de précision

Page 38: Ombres en temps-réel

Problème de précision•La carte de profondeur est aussi discrétisée en z•Besoin de précision : 16 bits, 24 bits…•Problèmes avec z voisins :

– Auto-ombrage des surfaces

•Solution :– Déplacer la carte de profondeur (bias)– Trouver la valeur idéale :

• Trop peu : les surfaces s’ombrent elles-mêmes• Trop : les ombres disparaissent

– glPolygonOffset();

Page 39: Ombres en temps-réel

Variantes : ID-buffer•Pour éviter les problèmes d’auto-ombrage•Une couleur par objet•Objet = ?

– Quelque chose qui ne peut pas s’ombrer– Convexes

•Ombrage si ID objet ≠ ID dans buffer•Pas de problème de précision

– Mais besoin nombreuses ID : 16 bits

•Problème si objets proches les uns des autres

Page 40: Ombres en temps-réel

Précision•La résolution effective dépend de la pyramide de vue de la lampe

– Large cône de vue : résolution gaspillée

•Plus la pyramide est proche des objets, plus on est précis

•Rapprocher la pyramide de vue – En xy : faible angle d’ouverture– En z : front plane et far plane rapprochés

Page 41: Ombres en temps-réel

Shadow Mapping : résumé• Avantages :

– Très simple à implémenter, code compact

– Marche toujours (scène quelconque)

– Prix indépendant de la complexité de la scène

– Nombreuses variantes pour améliorer la qualité

• Inconvénients :– Problèmes d’échantillonnage (xy et z)

– Deux passes de rendu

– Artefacts visibles

– Sources omni-directionnelles ?

Page 42: Ombres en temps-réel

Shadow volume•Source lumineuse ponctuelle

•Principe :– Silhouette des objets vus depuis la source– Plans infinis s’appuyant sur la source et sur

chaque arête– Définit « volume d’ombre »

•Pour chaque pixel de l’image :– Compter le nombre de plans entrants et sortants– Positif : ombre, nul : lumière

Page 43: Ombres en temps-réel

Shadow volume

Page 44: Ombres en temps-réel

Silhouette des objets•Travail sur le modèle

•Pour chaque arête du modèle :– Identifier polygones qu’elle relie– Produit scalaire normale / vecteur vers la source– Si produits scalaires de signe différent : arête de

silhouette– Besoin structure de données sur le maillage

•Sur-ensemble de la silhouette des objets

Page 45: Ombres en temps-réel

Volume d’ombre•Plans définis par (arête + source)

•Définit volume d’ombre :– En fait, plusieurs volumes imbriqués– On est à l’ombre si on est à l’intérieur d’au moins

un volume

•Principe : pour chaque pixel, on compte les plans, de l’œil jusqu’à la surface affichée

– Entrée/sortie dans le volume– Nombre total de plans croisés

Page 46: Ombres en temps-réel

Compter les plans•Stencil buffer :

– Autre fonctionnalité OpenGL– Buffer auxiliaire, jamais affiché– Opérations possibles :

• Incrémenter/décrémenter le stencil buffer

• Conditions sur le stencil buffer, actions sur l’écran

– Multiples utilisations :• Ombres, réflexions, fenêtres…

• Rendu conditionnel

• Début de programmation de la carte

Page 47: Ombres en temps-réel

Utilisation du stencil buffer•Premier rendu de la scène

– Initialise le Z-buffer

•Rendu du volume d’ombre– Pour chaque plan positif :glStencilOp(GL_KEEP,GL_KEEP,GL_INCR);

– Pour chaque plan négatif :glStencilOp(GL_KEEP,GL_KEEP,GL_DECR);

•Deuxième rendu de la scène :– glStencilFunc(GL_EQUAL, 0, ~0);

• Pour la partie éclairée

Page 48: Ombres en temps-réel

Algorithme : tracé du volumeglDisable(GL_LIGHTING);drawScene(); /* La scène, écl. ambiant */glDepthMask(0); /* Ne plus écrire ds Z-buffer */glStencilFunc(GL_ALWAYS, 0, ~0);glEnable(GL_STENCIL_TEST);glEnable(GL_CULL_FACE);glCullFace(GL_BACK);glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);glColorMask(0,0,0,0); /* pas modifier framebuffer */draw_shadow_volume(); /* plans positifs */glCullFace(GL_FRONT);glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);draw_shadow_volume(); /* plans négatifs */glColorMask(1,1,1,1);glDepthMask(1); /* On peut écrire ds Z-buffer */

Page 49: Ombres en temps-réel

Algorithme : rendu de la scène

glStencilFunc(GL_EQUAL, 0, ~0);

glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);

glEnable(GL_STENCIL_TEST);

glDepthFunc(GL_EQUAL);

glEnable(GL_LIGHTING);

drawScene();

Page 50: Ombres en temps-réel

Shadow volume•Avantages :

– Ombres précises– Positions quelconques lumière/caméra

• Inconvénients :– Calcul de la silhouette (sur CPU, év. long)– Besoin de modèles fermés, formés de convexes– Deux rendus de la scène, plus rendu du volume– fill-rate : tracé de nombreux polygones, qui

couvrent l’écran.– Carte limitée en nb. pixels/seconde

Page 51: Ombres en temps-réel

Mauvais cas pour le fill-rate

Page 52: Ombres en temps-réel

Shadow volume : améliorations•Et si la caméra est dans le volume d’ombre ?

– Le compte des plans n’est plus bon

•Système général :– Prendre un point hors du volume d’ombre– Compter les plans entre ce point et la surface– Exemple de points hors du volume : l’infini– Méthode zfail

Page 53: Ombres en temps-réel

zfail/zpass

Page 54: Ombres en temps-réel

zfailglDepthMask(0);glStencilFunc(GL_ALWAYS, 0, ~0);glEnable(GL_STENCIL_TEST);glEnable(GL_CULL_FACE);glCullFace(GL_FRONT);glStencilOp(GL_KEEP, GL_INCR, GL_KEEP);glColorMask(0,0,0,0);draw_shadow_volume();glCullFace(GL_BACK);glStencilOp(GL_KEEP, GL_DECR, GL_KEEP);draw_shadow_volume();glColorMask(1,1,1,1);glDisable(GL_CULL_FACE);glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);glDepthMask(1);

Page 55: Ombres en temps-réel

Limites du volume d’ombre•Le volume d’ombre est défini par des plans•Les plans vont de l’arête à l’infini •L’infini est difficile à gérer

– En pratique, on coupe à une certaine distance– Que se passe t-il si on voit le volume d’ombre à

cet endroit ?– Et si la source est proche de la caméra ?

• Il faut que le volume d’ombre soit fermé :– Si on coupe, on ajoute des polygones de fermeture

Page 56: Ombres en temps-réel

Limites du volume d’ombre•Applications : limiter le fill-rate

•Plus le volume est petit, plus le fill-rate est bas

•Couper les plans :– far clipping plane– Et fermer le volume :

• Sur les arêtes, par des plans

• À l’infini, par des plans

– Ça marche encore– Pyramide de vue de la source

Page 57: Ombres en temps-réel

Dark cap/light cap

Page 58: Ombres en temps-réel

Limitations du volume d’ombre

Page 59: Ombres en temps-réel

Extensions OpenGL•GL_EXT_stencil_two_side

– Pour faire les deux faces du volume d’ombre en une seule passe

•GL_NV_depth_clamp– Pour avoir des plans qui vont vraiment à l’infini

•GL_EXT_depth_bounds_test– Pour ne rasteriser que les primitives proches de la

source

Page 60: Ombres en temps-réel

Shadow volume•Avantages :

– Ombres précises– Positions quelconques lumière/caméra– Si bien programmé, robuste

• Inconvénients :– Calcul de la silhouette (sur CPU, év. long)– Scènes spécifiques : modèles fermés, formés de

convexes– Deux rendus de la scène, plus rendu du volume– fill-rate limité

Page 61: Ombres en temps-réel

Ombres douces•Algorithmiquement plus compliqué

•Problème de visibilité point-surface– Au lieu de point-point– Silhouette ?

•Ombre de la somme ≠ somme des ombres

•Plusieurs algorithmes approximatifs

Page 62: Ombres en temps-réel

Ombre/pénombre

Page 63: Ombres en temps-réel

Combinaison d’ombres

Page 64: Ombres en temps-réel

Problèmes de silhouette

Page 65: Ombres en temps-réel

Ombres douces•Accumulation d’ombres :

– Calculer plusieurs ombres ponctuelles– Additionner les résultats, moyenne– Accumulation buffer– Nombre d’échantillons élevés– Temps de calcul multiplié par # échantillons

Page 66: Ombres en temps-réel

Accumulation

4 échantillons 1024 échantillons

Page 67: Ombres en temps-réel

Ombres douces•Recherche de voisins :

– Shadow map normale– Pour chaque pixel dans la shadow map

• Rechercher frontière de l’ombre la plus proche

• Donne position + distance (source, récepteur)

• Coefficient d’atténuation fonction du rapport des distances

– Lent (recherche sur r2 pixels)– Limiter r : taille de la pénombre limitée

Page 68: Ombres en temps-réel

Ombres douces•Volume d’ombres douces :

– Shadow volume normal– Pour chaque arête de la silhouette :

• Calculer volume englobant la pénombre

• Pour chaque pixel dans ce volume

– Calculer coefficient d’atténuation

– Beau, réaliste– Problèmes de fill-rate multipliés par 2

Page 69: Ombres en temps-réel
Page 70: Ombres en temps-réel

Résumé : OpenGL• OpenGL :

– Z-buffer– Double-buffer– Pbuffers– Extensions– Stencil buffer– Accumulation buffer

• Cartes graphiques :– Rendu en plusieurs passes– Programmables (en un sens)– utilisées pour faire des choses complexes (ombres)– Ce n’est que le début

Page 71: Ombres en temps-réel

Résumé : ombres•Shadow maps :

– Stable, robuste, facile, rapide, aliasage

•Shadow volumes :– Beau, difficile, complexité algorithmique

•Ombres douces– Complexe, lent, beau