Fr/Projet Rembrandt: Difference between revisions

From FlightGear wiki
Jump to navigation Jump to search
No edit summary
No edit summary
Line 228: Line 228:
Chaque effet attaché au plein écran définit le mélange fait entre le pass et la somme précédente de rendu.
Chaque effet attaché au plein écran définit le mélange fait entre le pass et la somme précédente de rendu.


== Running Flightgear with Rembrandt ==
== Démarrage de FlightGear avec Rembrandt ==
[[File:Rembrandt dialog.png|thumb|270px|Rembrandt dialog]]
[[File:Rembrandt dialog.png|thumb|270px|dialogue Rembrandt]]
The Rembrandt renderer is now integrated in the main repository but needs to be enabled to run. There are two ways to enable it (only one is needed!):
Le rendu Rembrandt est maintenant intégré dans le répertoire principal, mais doit être activé pour démarrer. Il y a deux façons de l'activer (une seule est nécessaire):
* <code>--enable-rembrandt</code> (when using [[FGRun]], you may add this behind the <tt>FG_EXECUTABLE</tt> on the first page).  
* <code>--enable-rembrandt</code> (lorsqu'on utilise [[FGRun]], on peut ajouter ceci derrière le <tt>FG_EXECUTABLE</tt> sur la première page).  
* <code>--prop:/sim/rendering/rembrandt/enabled=true</code> (with FGRun this can be added via <tt>Advanced > Properties</tt> on the last page).
* <code>--prop:/sim/rendering/rembrandt/enabled=true</code> (avec FGRun on peut ajouter ceci via <tt>Advanced > Properties</tt> sur la dernière page).


The <tt>View > Rendering Options > Rembrandt Options</tt> dialog allows you to toggle and adjust the various features that Rembrandt offers.
Le <tt>View > Rendering Options > Rembrandt Options</tt> dialogue vous permet de  basculer et d'ajuster les différentes options offertes par Rembrandt.


Rembrandt is quite demanding in GPU resources and may fail to run with the default options. The more frequent symptom is an OSG message in the console :
Rembrandt est très gourmand en ressources GPU et son démarrage peut échouer avec les options par défaut. Le symptome le plus fréquent est un message OSG dans la console :


  RenderStage::runCameraSetUp(), FBO setup failed, FBO status= 0x8cd6
  RenderStage::runCameraSetUp(), FBO setup failed, FBO status= 0x8cd6
  Warning: RenderStage::runCameraSetUp(State&) Pbuffer does not support multiple color outputs.
  Warning: RenderStage::runCameraSetUp(State&) Pbuffer does not support multiple color outputs.


Some card also exhibit messages like this :
On peut voir aussi :


  glLinkProgram "" FAILED
  glLinkProgram "" FAILED
Line 252: Line 252:
  0(34) : error C6013: Only arrays of texcoords may be indexed in this profile, and only with a loop index variable
  0(34) : error C6013: Only arrays of texcoords may be indexed in this profile, and only with a loop index variable


There is a number of additional options that can help to avoid these problems :
Des options additionnelles peuvent éviter ces problèmes :


{| class="wikitable"
{| class="wikitable"
|<tt>--prop:/sim/rendering/rembrandt/use-color-for-depth=true</tt>
|<tt>--prop:/sim/rendering/rembrandt/use-color-for-depth=true</tt>
|Some old NVidia cards, such as 7600GT, don't give enough resolution for depth and that result in "fog curtains" at few meters from the viewer. One trick is to encode depth in another texture and get the proper value afterward. This option enables that.
|Certaines vieilles cartes NVidia comme 7600GT, n'ont pas assez de résolution pour la profondeur, et on voit des "rideaux de brouillard" à quelques mètres devant. Une astuce consiste à encoder la profondeur dans une autre texture et donner la valeur correcte ensuite. Cette option permet cela.
|-
|-
|<tt>--prop:/sim/rendering/shadows/enabled=false</tt>
|<tt>--prop:/sim/rendering/shadows/enabled=false</tt>
|Disable shadows altogether.
|Désactive les ombres tout à fait.
|-
|-
|<tt>--prop:/sim/rendering/shadows/num-cascades=1</tt>
|<tt>--prop:/sim/rendering/shadows/num-cascades=1</tt>
|Avoid the "error C6013" message on old cards at the cost of resolution in the cockpit. Set <tt>/sim/rendering/shadows/cascade-far-m[0]</tt> to change the shadow map range. The more the range, the less the resolution (default value is 5 meters)
|Évite le message "error C6013" sur les vieilles cartes en manque de résolution dans le cockpitt. Mettez <tt>/sim/rendering/shadows/cascade-far-m[0]</tt> pour changer la taille de la carte d'ombre. Plus de taille, et moins de résolution (la valeur par défaut est 5 mètres)
|-
|-
|<tt>--prop:/sim/rendering/shadows/map-size=<power-of-two></tt>
|<tt>--prop:/sim/rendering/shadows/map-size=<power-of-two></tt>
|Set the shadow map size. Useful values are 1024, 2048, 4096 or 8192. Few cards have the resources to support 16384.
|Définnissez la taille de la carte d'ombres. Les valeurs utilles sont 1024, 2048, 4096 ou 8192. Peu de cartes supportent 16384.
|-
|-
|<tt>--prop:/sim/rendering/shadows/num-cascades</tt>
|<tt>--prop:/sim/rendering/shadows/num-cascades</tt>
|Set the shadow map cascade number. Less cascades means less time spent in shadow map generation, but also means lower shadow quality. Integer between 1 and 4.
|Définissez le nombre de cascades de la carte ombre. Moins de cascades signifie moins de temps passé à générer la carte shadow, mais aussi signifie une qualité moindre de l'ombre. Mettez entre 1 et 4.
|-
|-
|<tt>--prop:/sim/rendering/shadows/cascade-far-m[i]</tt>
|<tt>--prop:/sim/rendering/shadows/cascade-far-m[i]</tt>
(1 <= i <= <tt>/sim/rendering/shadows/num-cascades</tt> <= 4)
(1 <= i <= <tt>/sim/rendering/shadows/num-cascades</tt> <= 4)
|Set the shadow map cascade range for each cascade. Default values are 5m, 50m, 500m and 5000m for 4 cascades.
|Définissez la taille de cascade de la carte shadow pour chaque cascade. Les valeurs par défaut sont 5m, 50m, 500m et 5000m pour 4 cascades.
|-
|-
|<tt>--prop:/sim/rendering/rembrandt/no-16bit-buffer=false</tt>
|<tt>--prop:/sim/rendering/rembrandt/no-16bit-buffer=false</tt>
|By default, Rembrandt uses 8 bit buffers for normals (so the property is set to true by default). This may create banding artifacts on specular highlights. If it's unacceptable and the GPU supports it, set to false to have better precision for normals and effects relying on normal direction.
|Par défaut, Rembrandt utilise normalement des tampons de 8 bits  (ainsi, la propriété est vraiment définie par défaut). Ceci peut créer des artefacts pour les éclairages specular. Si c'est inacceptable et si le GPU le supporte, mettez false pour avoir une meilleure précision pour les normales et les effets s'appuyant sur une direction normale.
|}
|}


== Guidelines for shader writers ==
== Lignes directrices pour les écrits shader ==
=== Predefined uniforms ===
=== Uniformes prédéfinis ===
These glsl uniforms don't need to be declared in the effect file.
Ces uniformes glsl n'ont pas besoin d'être déclarés dans le fichier effet
{| class="wikitable"
{| class="wikitable"
!Name
!Name
Line 288: Line 288:
|<tt>fg_ViewMatrix</tt>
|<tt>fg_ViewMatrix</tt>
|<tt>mat4</tt>
|<tt>mat4</tt>
|In fullscreen pass only, view matrix used to transform the screen position to view direction
|En pass plein écran seulement, view matrix utilisé our transformer la position écran en direction vue
|-
|-
|<tt>fg_ViewMatrixInverse</tt>
|<tt>fg_ViewMatrixInverse</tt>
|<tt>mat4</tt>
|<tt>mat4</tt>
|In fullscreen pass only, view matrix inverse used to transform the screen position to view direction
|En pass plein écran seulement, view matrix inverse employé pour transformer la position écran en direction vue
|-
|-
|<tt>fg_ProjectionMatrixInverse</tt>
|<tt>fg_ProjectionMatrixInverse</tt>
|<tt>mat4</tt>
|<tt>mat4</tt>
|In fullscreen pass only, projection matrix inverse used to transform the screen position to view direction
|En pass plein écran seulement, projection matri inverse employé pour transformer la position écran en direction vue
|-
|-
|<tt>fg_CameraPositionCart</tt>
|<tt>fg_CameraPositionCart</tt>
|<tt>vec3</tt>
|<tt>vec3</tt>
|Position of the camera in world space, expressed in cartesian coordinates
|Position de la caméra en coordonnées cartésiennes
|-
|-
|<tt>fg_CameraPositionGeod</tt>
|<tt>fg_CameraPositionGeod</tt>
|<tt>vec3</tt>
|<tt>vec3</tt>
|Position of the camera in world space, expressed in geodesic coordinates (longitude in radians, latitude in radians, elevation in meters)
|Position de la caméra dans l'espace, exprimé en coordonnées géodésiques (longitude et latitude en radians, élévation en mètres)
|-
|-
|<tt>fg_SunAmbientColor</tt>
|<tt>fg_SunAmbientColor</tt>
Line 340: Line 340:
|<tt>fg_DepthInColor</tt>
|<tt>fg_DepthInColor</tt>
|<tt>bool</tt>
|<tt>bool</tt>
|Tells if the depth is stored in a depth texture or a color texture
|Dire si la profondeur est rangée dans une texture profondeur ou une texture couleur
|-
|-
|<tt>fg_Planes</tt>
|<tt>fg_Planes</tt>
|<tt>vec3</tt>
|<tt>vec3</tt>
|Used to convert the value of the depth buffer to a depth that can be used to compute the eye space position of the fragment
|Utilisé pour convertir la valeur du tampon profondeur en une profondeur qui peut être utilisée pour calculer la position dans l'espace du fragment.
|-
|-
|<tt>fg_BufferSize</tt>
|<tt>fg_BufferSize</tt>
|<tt>vec2</tt>
|<tt>vec2</tt>
|Dimensions of the buffer, used to convert gl_FragCoord into the range [0..1][0..1]
|Dimensions du tampon, utilisé pour convertir  gl_FragCoord dans la taille [0..1][0..1]
|-
|-
|<tt>osg_ViewMatrix</tt>
|<tt>osg_ViewMatrix</tt>
|<tt>mat4</tt>
|<tt>mat4</tt>
|Defined by OSG, used only when working on actual geometry
|Definie par OSG, employé seulement lors du travail sur la géométrie réelle
|-
|-
|<tt>osg_ViewMatrixInverse</tt>
|<tt>osg_ViewMatrixInverse</tt>
|<tt>mat4</tt>
|<tt>mat4</tt>
|Defined by OSG, used only when working on actual geometry
|Definie par OSG, employé seulement lors du travail sur la géométrie réelle
|}
|}
They still have to be declared in the fragment or the vertex shader to be used.
.Ils doivent encore être déclarés dans le fragment du vertex shader


=== Utility functions ===
=== Fonctions utilitaires ===


To ease the maintenance of shaders, several utility functions are available for the fragment shader. These functions are put together in two files : <tt>gbuffer-functions.frag</tt> and <tt>gbuffer-encode.frag</tt>.
Pour faciliter la maintenance des shaders plusieurs fonctions utilitaires sont disponibles pour le fragment shader. Ces fonctions sont placées ensemble dans deux fichiers : <tt>gbuffer-functions.frag</tt> et <tt>gbuffer-encode.frag</tt>.


==== gbuffer-encode.frag ====
==== gbuffer-encode.frag ====


;<tt>void encode_gbuffer(vec3 normal, vec3 color, int mId, float specular, float shininess, float emission, float depth)</tt>
;<tt>void encode_gbuffer(vec3 normal, vec3 color, int mId, float specular, float shininess, float emission, float depth)</tt>
:Used to encode all the values of the G-Buffer in material shaders
:Utilisé pour encoder youtes les valeurs de  G-Buffer dans material shaders


==== gbuffer-functions.frag ====
==== gbuffer-functions.frag ====


;<tt>vec2 normal_encode(vec3 n)</tt>
;<tt>vec2 normal_encode(vec3 n)</tt>
:Used to compress normals into the G-Buffer in material shaders. Normally called from <tt>encode_gbuffer()</tt>
:Employé pour compresser normals à l'intérieur de G-Buffer dans material shaders. Normalement appelé de <tt>encode_gbuffer()</tt>


;<tt>vec3 normal_decode(vec2 enc)</tt>
;<tt>vec3 normal_decode(vec2 enc)</tt>
:Reconstruct normals from the G-Buffer. Used in fullscreen shaders and light shaders
:Reconstruit normals à partir de G-Buffer. Employé dans shaders plein écran et shaders lumière


;<tt>vec3 float_to_color(in float f)</tt>
;<tt>vec3 float_to_color(in float f)</tt>
:Encode float values in the range [0..1] in the 24 bits of a color. This function is used by <tt>encode_gbuffer()</tt> if the <tt>/sim/rendering/use-color-for_depth</tt> is true, for old cards that don't provide depth information with enough resolution inside fullscreen or light shaders.
:Encode les valeurs float dans la taille [0..1] dans les  24 bits d'une couleur. cette fonction est employée par <tt>encode_gbuffer()</tt> si le <tt>/sim/rendering/use-color-for_depth</tt> est vrai, pour les vieilles cartes qui ne fournissent pas d'information profondeur avec assez de résolution dans les shaders fullscreen ou lumière.


;<tt>float color_to_float(vec3 color)</tt>
;<tt>float color_to_float(vec3 color)</tt>
:Decode float values in the range [0..1] from the 24 bits of a color. This function is used by <tt>position()</tt> if the <tt>/sim/rendering/use-color-for_depth</tt> is true, for old cards that don't provide depth information with enough resolution inside fullscreen or light shaders.
:Décode les valeurs float dans la taille [0..1] dans les  24 bits d'une couleur. cette fonction est employée par <tt>position()</tt> si le <tt>/sim/rendering/use-color-for_depth</tt> est vrai, pour les vieilles cartes qui ne fournissent pas d'information profondeur avec assez de résolution dans les shaders fullscreen ou lumière.


;<tt>vec3 position( vec3 viewDir, float depth )</tt>
;<tt>vec3 position( vec3 viewDir, float depth )</tt>
:Reconstruct eye space position from the view direction and the depth read from the depth buffer
:Reconstruit la position eye space à partir de la direction view position a partir de la view direction et la profondeur lue du tampon profondeur


;<tt>vec3 position( vec3 viewDir, vec3 depthColor )</tt>
;<tt>vec3 position( vec3 viewDir, vec3 depthColor )</tt>
:Reconstruct eye space position from the view direction and the depth encoded in a color read from the depth buffer
::Reconstruit la position eye space à partir de la direction view et la profondeur encodée dans une couleur lue du tampon profondeur


;<tt>vec3 position( vec3 viewDir, vec2 coords, sampler2D depth_tex )</tt>
;<tt>vec3 position( vec3 viewDir, vec2 coords, sampler2D depth_tex )</tt>
:Reconstruct eye space position from the view direction and the depth buffer (real depth or color, according to the value of <tt>/sim/rendering/use-color-for_depth</tt>) at a given fragment on screen, given by <tt>coords</tt>
:Reconstruit la position eye space à partir de la direction vue et du tampon profondeur (profondeur réelle ou couleur selon la valeur de <tt>/sim/rendering/use-color-for_depth</tt>) à un fragment donné sur l'écran, donné par <tt>coords</tt>


==== Usage ====
==== Usage ====

Revision as of 21:52, 18 September 2012

WIP.png Travail en cours
Dans les heures ou les jours suivants, des travaux sur cet article ou section seront effectués.
Voyez l'histoire de l'article pour les derniers développements.

Pourquoi ce nom?

Rembrandt était un peintre hollandais du XVIIème siècle, maître incontesté du "clair-obscur".

Ce projet a pour but de changer la manière de rendre les éclairages et les ombres qu'utilise FlightGear, et d'essayer d'imiter le style de Rembrandt dans FG.

De quoi s'agit-il ?

L'idée maîtresse du projet est d'implémenter le rendu différé au sein de FlightGear. Depuis le début, FlightGear utilise un moteur de rendu en avant qui affiche toutes les propriétés d'un objet en une fois (ombre, éclairage, brouillard, ...), ce qui rend difficile le rendu d'un ombrage plus sophistiqué (voir le 'Uber-shader') du fait que tous les paramètres de l'équation lumineuse doivent être traités en une seule fois.

Vue principale avec le contenu des buffers affichés dans les coins

Au contraire, le rendu différé cherche à séparer les opérations en étapes simplifiées et à collecter les résultats intermédiaires dans des buffers cachés, qui peuvent être utilisés par la prochain étape.

Le premier stade est celui de la Géométrie
nous rendons la scène entière dans 4 textures, en utilisant le rendu multi-cibles pour les traiter en un seul passage: un pour le buffer de profondeur, un pour les normales (en bas à gauche de l'image), un pour les couleurs "diffuses" (en bas à gauche) et un pour les couleurs "spéculaires" (en haut à droite).
Le stade suivant est celui de l'ombre
nous rendons encore la scène dans une texture profondeur concernant les éclairages. Il y aura une texture pour chaque lumière diffusant des ombres.
Ensuite, c'est le stade de l'éclairage, avec plusieurs sous-stades
  • Sky pass: Le ciel est dessiné d'abord selon la méthode classique.
  • Ambient pass: la mémoire-tampon "diffuse" est modulé avec la couleur ambiante de la scène, et est dessiné comme un quad texturé aligné sur l'écran
  • Sunlight pass: Un second quad aligné à l'écran est dessiné et un shader examine la position pour calculer sa couleur "diffuse" et "specular" en utilisant le "normal" stocké dans le premier stade. La couleur résultante et mélangée avec la passe précédente. Les ombres sont examinées ici par comparaison de la position du pixel avec la position du cache lumière stockée dans la carte shadows


  • stade de la lumière additionnelle: le scene graph sera traversé une autre fois pour afficher les volumes de lumière (cône ou tronc de cône pour les taches de lumière, sphère pour les lumières omni directionnelles), et leur shader ajoutera la lumière composée uniquement par les pixels éclairés.
  • stade brouillard: un nouveau quad aligné sur l'écran est dessiné, et la position du pixel est calculée pour évaluer la quantité de brouillard du pixel. La couleur du brouillard est mélangée avec le résultat du stade précédent.
  • Stade des objets transparents: les objets transparents (et les nuages) sont enfin rendus en utilisant la méthode classique.
Tous les données de lumière sont accumulées dans une seule mémoire tampon, qui sera utilisée pour le dernier stade en addition au stade Géométrie.
A la fin, le stade affichage, avec l'option effet post-traitement
Les résultats des précédents tampons sont poussés dans le tampon principal pour être affichés, optionnellement modifiés pour montrer Glow, Motion blur, HDR, redout ou blackout, occlusion ambiante de l'espace écran, anti-aliasing, etc...

Dans FG, on termine le pipeline du rendu par l'affichage du GUI et du HUD.

Tous ces phases sont plus précisément décrites dans tutorial c'est la base du code actuel, avec quelque addition ou modifications.

Avertissements

Le rendu différé n'affiche pas la transparence. Pour le moment, les nuages doivent être éclairés et ombrés par eux-mêmes. Les surfaces transparentes sont alpha-testées et non mélangées. Elles doivent être amenées dans leur propre bin sur l'image composite.

La partition profondeur ne marche pas non plus, à cause de la mémoire tampon profondeur, qui doit être gardée pour retenir la position de zone de vue, et, pour le moment, z-fighting est tout à fait visible. La partition profondeur sans rangée de profondeur superposée pourrait être la solution, et devrait être essayée.

Le passage de la lumière peut rendre certains MFD illisibles (ce qui utilisent une couleur émissive) car flous. Ils devront être traités comme transparents.


Mise en œuvre

Répertoires

Le code est la principale branche du répertoire officiel. Aucune autre localisation n'existe.

Rendu des surfaces transparentes

Surfaces transparentes desssinées d'après des objets opaques

Les surfaces transparentes sont détectées par les plugins OSG loader qui captent la nuance de rendu TRANSPARENT_BIN

In the culling pass, the cull visitor orders transparent surfaces in transparent bin. In a cull callback attached to the Geometry camera, after the scenegraph traversal, the transparent bins are removed from the render stage and saved in a temporary collection. In a cull callback attached to the Lighting camera, after the scenegraph traversal, the transparent bins saved at the previous stage, are added to the render stage of the Lighting camera with a high order num. That way, the transparent surface are drawn on top of the scene lighted from the Gbuffer.

Consommation de mémoire

Pour chaque caméra définie du groupe, il y a une carte d'ombre séparée, de telle sorte que l'utilisation de la mémoire vidéo soit:

  • G-tampon et tampon lumière: 20 bytes par pixel. Pour un écran HD (1920x1080) la mémoire requise est de 40 Mb
  • Carte d'ombre 3 x taille_carte_ombre x shadow_map_size bytes (si la taille est 8192, la taille totale de la mémoire est 192 Mb

Ne pas compter les textures, liste d'affichage ou tampons vertex pour kes modèles et terrains

3 écrans HD ont besoin de 120 Mb de mémoire pour les tampons (ombre exclue), il vous faut 3x8192x8192x3 = 576 Mb (megabytes) de mémoire pour les seuls shadows.

Si vous voyez des messages d'erreur pendant le démarrage, ou si FlightGear ne démarre pas bien, c'est probablement parceque vous n'avez pas assez de mémoire vidéo libre. Réduisez la taille de la carte d'ombre dans préférences.xml

 <map-size type="int">8192</map-size>

Et mettez 4096 ou 2048 à la place. Vous pouvez aussi utiliser un paramètre de démarrage: --prop:/sim/rendering/shadows/map-size=2048

Pipeline configurable

Le rendu Rembrandt utilise un fichier XML pour installer son pipeline pour chaque fenêtre décrite dans le groupe de cameras. Ce fichier mntre la façon dont les tampons intermédiaires sont établis, et comment les différentes étapes du rendu sont agencés. Le schéma général du fichier pipeline est le suivant :

<?xml version="1.0" encoding="utf-8"?>
<PropertyList>
	<!-- BUFFERS -->
	<buffer>
		<!-- 1ere définition de tampon -->
	</buffer>
	<buffer>
		<!-- n ème définition de tampon -->
	</buffer>
	
	<!-- STAGES -->
	<stage>
		<!-- 1ère définition d'étape -->
	</stage>
	<stage>
		<!-- n ème définition d'étape -->
	</stage>
</PropertyList>

Tampons

Un tampon est une texture utilisée comme zone de stockage dans le GPU. Sa taille est habituellement un multiple de la taille de l'écran, mais une taille fixe est prise en charge ( typique pour la carte d'ombres). La description d'un tampon suit :

	<buffer>
		<name>buffer-name</name>
		<internal-format>rgba8</internal-format> <!-- rgb8, rgba8, rgb16, rgba16, rg16, depth-component24, depth-component32 or OpenGL hex value -->
		<source-format>rgba</source-format> <!-- rg, rgb, rgba, depth-component or OpenGL hex value -->
		<source-type>unsigned-byte</source-type> <!-- unsigned-byte, unsigned-short, unsigned-int, float or OpenGL hex value -->
		<width>screen</width> <!-- screen, value or <property>/a/width/property</property> -->
		<height>screen</height> <!-- screen, value or <property>/a/height/property</property> -->
		<scale-factor>1.0</scale-factor>
		<wrap-mode>clamp-to-border</wrap-mode> <!-- clamp, clamp-to-border, clamp-to-edge, mirror, repeat or OpenGL hex value -->
		<!-- optional, for shadow map -->
		<shadow-comparison>true</shadow-comparison>
		<!-- optional condition -->
		<condition>
			<!-- Valid boolean expression -->
		</condition>
	</buffer>


Phases

Une phase est une unité de rendu d'un groupe de tampons. La plupart des phases sont pré-définies et leur type n'est pas libre. Quand un type n'est pas spécifié, le nom est utilisé? Les types de phases sont :

Stage type Purpose
geometry La phase geometry initialise la plupart des tampons et agit sur les objets réels et la géométrie. Les objets transparents sont placés à côté, et seront utilisés tels quels dans la phase lumière. Le rest e de la géométrie opaque est rendu avec les effets standard, permettant de mettre la donnée sensible dans les tampons.
ombre Dans cette phase, la géométrie est rendue dans la carte normale à partir de la perspective du soleil.
lumière Cette phase utilise les tampons remplis par les phases précédrntes pour éclairer chaque pixel de la scène. Le résultat est rendu dans un autre tampon pour permettre des effets ultérieurs.
plein écran Les phases de ce type sont utilisés pour changer la scène entière, ou transformer une donnée à partir d'un tampon particulier.
affichage Le rendu final de la scène à l'écran est jugé à l'écran, ou la texture est définie dans le groupe caméra .

Ci-dessous, une description de phase :

	<stage>
		<name>stage-name</name>
		<type>stage-type</type> <!-- optionnel si le nom est l'un des types prédéfinis sauf plein écran  -->
		<order-num>-1</order-num>
		<effect>Effects/fullscreen-effect</effect> <!-- seulement si type == fullscreen -->
		<needs-du-dv>true</needs-du-dv> <!-- seulement si type == fullscreen -->
		<scale-factor>0.25</scale-factor> <!-- seulement si type == fullscreen -->

		<!-- optional condition -->
		<condition>
			<!-- Valid boolean expression -->
		</condition>

		<attachment>
			<!-- First attachment definition -->
		</attachment>
		<attachment>
			<!-- Nth attachment definition -->
		</attachment>

		<!-- Passes only for the lighting stage -->
		<pass>
			<!-- First pass definition -->
		</pass>
		<pass>
			<!-- Nth pass definition -->
		</pass>
	</stage>

Les phases sont rendues dans les tampons (sauf pur la phase affichage). Les pièces jointes disent quels tampons sony affectés par chaque phase.

Pièces jointes

La pièce jointe décrit la liaison entre tampon et poit d'attachement :

	<attachment>
		<component>color0</component> <!-- depth, stencil, packed-depth-stencil, color0, color1, color2 or color3 -->
		<buffer>buffer-name</buffer>
		<!-- optional condition -->
		<condition>
			<!-- Valid boolean expression -->
		</condition>
	</attachment>
Permissions(passes)

Les Passes sont seulement disponibles dans la phase lighting. trois sortes de phases sont autorisées :

Pass type Purpose
sky-clouds Rendus de la voûte céleste, solei, lune, planète, étoiles et nuages
lumières Rendus des taches additionnelles et points lumineux
plein écran Le pass fullscreen analogue à une phase fullscreen sauf qu'il est rendu dans des tampons attachés à la phase lumière

Un pass est défini ci-dessous :

	<pass>
		<name>pass-name</name>
		<type>pass-type</type> <!-- optionnel si le nom est prédéfini excepté fullscreen -->
		<order-num>-1</order-num>
		<effect>Effects/fullscreen-effect</effect> <!-- seulement si type == fullscreen -->

		<!-- optional condition -->
		<condition>
			<!-- Valid boolean expression -->
		</condition>
	</pass>

Une phase lumière typique est une succession de 5 pass:

  1. sky-clouds pass
  2. fullscreen pass pour lumière ambiante
  3. fullscreen pass pour lumière solaire (et ombres)
  4. lights pass
  5. fullscreen pass pour brouillard

Chaque effet attaché au plein écran définit le mélange fait entre le pass et la somme précédente de rendu.

Démarrage de FlightGear avec Rembrandt

dialogue Rembrandt

Le rendu Rembrandt est maintenant intégré dans le répertoire principal, mais doit être activé pour démarrer. Il y a deux façons de l'activer (une seule est nécessaire):

  • --enable-rembrandt (lorsqu'on utilise FGRun, on peut ajouter ceci derrière le FG_EXECUTABLE sur la première page).
  • --prop:/sim/rendering/rembrandt/enabled=true (avec FGRun on peut ajouter ceci via Advanced > Properties sur la dernière page).

Le View > Rendering Options > Rembrandt Options dialogue vous permet de basculer et d'ajuster les différentes options offertes par Rembrandt.

Rembrandt est très gourmand en ressources GPU et son démarrage peut échouer avec les options par défaut. Le symptome le plus fréquent est un message OSG dans la console :

RenderStage::runCameraSetUp(), FBO setup failed, FBO status= 0x8cd6
Warning: RenderStage::runCameraSetUp(State&) Pbuffer does not support multiple color outputs.

On peut voir aussi :

glLinkProgram "" FAILED
Program "" infolog:
Fragment info
-------------
0(37) : error C6013: Only arrays of texcoords may be indexed in this profile, and only with a loop index variable
0(36) : error C6013: Only arrays of texcoords may be indexed in this profile, and only with a loop index variable
0(35) : error C6013: Only arrays of texcoords may be indexed in this profile, and only with a loop index variable
0(34) : error C6013: Only arrays of texcoords may be indexed in this profile, and only with a loop index variable

Des options additionnelles peuvent éviter ces problèmes :

--prop:/sim/rendering/rembrandt/use-color-for-depth=true Certaines vieilles cartes NVidia comme 7600GT, n'ont pas assez de résolution pour la profondeur, et on voit des "rideaux de brouillard" à quelques mètres devant. Une astuce consiste à encoder la profondeur dans une autre texture et donner la valeur correcte ensuite. Cette option permet cela.
--prop:/sim/rendering/shadows/enabled=false Désactive les ombres tout à fait.
--prop:/sim/rendering/shadows/num-cascades=1 Évite le message "error C6013" sur les vieilles cartes en manque de résolution dans le cockpitt. Mettez /sim/rendering/shadows/cascade-far-m[0] pour changer la taille de la carte d'ombre. Plus de taille, et moins de résolution (la valeur par défaut est 5 mètres)
--prop:/sim/rendering/shadows/map-size=<power-of-two> Définnissez la taille de la carte d'ombres. Les valeurs utilles sont 1024, 2048, 4096 ou 8192. Peu de cartes supportent 16384.
--prop:/sim/rendering/shadows/num-cascades Définissez le nombre de cascades de la carte ombre. Moins de cascades signifie moins de temps passé à générer la carte shadow, mais aussi signifie une qualité moindre de l'ombre. Mettez entre 1 et 4.
--prop:/sim/rendering/shadows/cascade-far-m[i]

(1 <= i <= /sim/rendering/shadows/num-cascades <= 4)

Définissez la taille de cascade de la carte shadow pour chaque cascade. Les valeurs par défaut sont 5m, 50m, 500m et 5000m pour 4 cascades.
--prop:/sim/rendering/rembrandt/no-16bit-buffer=false Par défaut, Rembrandt utilise normalement des tampons de 8 bits (ainsi, la propriété est vraiment définie par défaut). Ceci peut créer des artefacts pour les éclairages specular. Si c'est inacceptable et si le GPU le supporte, mettez false pour avoir une meilleure précision pour les normales et les effets s'appuyant sur une direction normale.

Lignes directrices pour les écrits shader

Uniformes prédéfinis

Ces uniformes glsl n'ont pas besoin d'être déclarés dans le fichier effet

Name Type Purpose
fg_ViewMatrix mat4 En pass plein écran seulement, view matrix utilisé our transformer la position écran en direction vue
fg_ViewMatrixInverse mat4 En pass plein écran seulement, view matrix inverse employé pour transformer la position écran en direction vue
fg_ProjectionMatrixInverse mat4 En pass plein écran seulement, projection matri inverse employé pour transformer la position écran en direction vue
fg_CameraPositionCart vec3 Position de la caméra en coordonnées cartésiennes
fg_CameraPositionGeod vec3 Position de la caméra dans l'espace, exprimé en coordonnées géodésiques (longitude et latitude en radians, élévation en mètres)
fg_SunAmbientColor vec4
fg_SunDiffuseColor vec4
fg_SunSpecularColor vec4
fg_SunDirection vec3
fg_FogColor vec4
fg_FogDensity float
fg_ShadowNumber int
fg_ShadowDistances vec4
fg_DepthInColor bool Dire si la profondeur est rangée dans une texture profondeur ou une texture couleur
fg_Planes vec3 Utilisé pour convertir la valeur du tampon profondeur en une profondeur qui peut être utilisée pour calculer la position dans l'espace du fragment.
fg_BufferSize vec2 Dimensions du tampon, utilisé pour convertir gl_FragCoord dans la taille [0..1][0..1]
osg_ViewMatrix mat4 Definie par OSG, employé seulement lors du travail sur la géométrie réelle
osg_ViewMatrixInverse mat4 Definie par OSG, employé seulement lors du travail sur la géométrie réelle

.Ils doivent encore être déclarés dans le fragment du vertex shader

Fonctions utilitaires

Pour faciliter la maintenance des shaders plusieurs fonctions utilitaires sont disponibles pour le fragment shader. Ces fonctions sont placées ensemble dans deux fichiers : gbuffer-functions.frag et gbuffer-encode.frag.

gbuffer-encode.frag

void encode_gbuffer(vec3 normal, vec3 color, int mId, float specular, float shininess, float emission, float depth)
Utilisé pour encoder youtes les valeurs de G-Buffer dans material shaders

gbuffer-functions.frag

vec2 normal_encode(vec3 n)
Employé pour compresser normals à l'intérieur de G-Buffer dans material shaders. Normalement appelé de encode_gbuffer()
vec3 normal_decode(vec2 enc)
Reconstruit normals à partir de G-Buffer. Employé dans shaders plein écran et shaders lumière
vec3 float_to_color(in float f)
Encode les valeurs float dans la taille [0..1] dans les 24 bits d'une couleur. cette fonction est employée par encode_gbuffer() si le /sim/rendering/use-color-for_depth est vrai, pour les vieilles cartes qui ne fournissent pas d'information profondeur avec assez de résolution dans les shaders fullscreen ou lumière.
float color_to_float(vec3 color)
Décode les valeurs float dans la taille [0..1] dans les 24 bits d'une couleur. cette fonction est employée par position() si le /sim/rendering/use-color-for_depth est vrai, pour les vieilles cartes qui ne fournissent pas d'information profondeur avec assez de résolution dans les shaders fullscreen ou lumière.
vec3 position( vec3 viewDir, float depth )
Reconstruit la position eye space à partir de la direction view position a partir de la view direction et la profondeur lue du tampon profondeur
vec3 position( vec3 viewDir, vec3 depthColor )
Reconstruit la position eye space à partir de la direction view et la profondeur encodée dans une couleur lue du tampon profondeur
vec3 position( vec3 viewDir, vec2 coords, sampler2D depth_tex )
Reconstruit la position eye space à partir de la direction vue et du tampon profondeur (profondeur réelle ou couleur selon la valeur de /sim/rendering/use-color-for_depth) à un fragment donné sur l'écran, donné par coords

Usage

For material shaders, it is necessary to provide both gbuffer-functions.frag and gbuffer-encode.frag in the effect file, like this :

	<program>
		<vertex-shader>Shaders/ubershader.vert</vertex-shader>
		<fragment-shader>Shaders/ubershader-gbuffer.frag</fragment-shader>
		<fragment-shader>Shaders/gbuffer-functions.frag</fragment-shader>
		<fragment-shader>Shaders/gbuffer-encode.frag</fragment-shader>
	</program>

For fullscreen passes shaders, only gbuffer-functions.frag should be provided, like this :

	<program>
		<vertex-shader>Shaders/sunlight.vert</vertex-shader>
		<fragment-shader>Shaders/sunlight.frag</fragment-shader>
		<fragment-shader>Shaders/gbuffer-functions.frag</fragment-shader>
	</program>

In the main function of the shader, the functions referenced need to be declared first. With no #include files, the whole function prototype needs to be typed :

void encode_gbuffer(vec3 normal, vec3 color, int mId, float specular, float shininess, float emission, float depth);

main() {
    vec3 normal;
    vec3 color;
    int mId;
    float specular;
    float shininess;
    float emission;
    float depth;

    // Do shader computations

    encode_gbuffer(normal, color, mId, specular, shininess, emission, depth);
}

Geometry Stage

The Geometry Stage is there to fill the G-buffer. Shading doesn't occur at this stage, so light or fog computation should not be part of the shader. The required operation in the Fragment Shader is to fill every individual buffer with sensible value :

depth (gl_FragDepth) GL_DEPTH_COMPONENT32 Fragment depth
gl_FragData[0] GL_RG16 normal.x * 0.5 + 0.5 normal.y * 0.5 + 0.5
gl_FragData[1] GL_RGBA8 diffuse.r diffuse.g diffuse.b material id * 1/255.0
gl_FragData[2] GL_RGBA8 specular.l specular.s emission.l pixel valid if != 0

This is the default layout expected by the sunlight shader. material Id can be used to detect a different layout


Additional light pass

There would be a single shader for each light type used. The plan is to create lights like animations in the model XML file. The light shader will retrieve scene geometry by combining screen space position converted in view space ray by the inverse of the projection matrix (an helper function should be provided), and the fragment depth at that screen position read from the depth buffer. With the help of the fragment normal, the diffuse and specular color and the properties of the light the shader implements, it will be possible to add to the lighting buffer the contribution of the light rendered.

Fog Pass

Using the fragment depth, it will be possible to compute any fog distribution. For the moment, the simple fog equation is implemented.

Bloom Pass

This is a two-pass effect that blurs the lighting buffer in a small texture. This texture is then added to the lighting buffer at the display stage.

Required Effects

Several pass are implemented using the effect system. For this purpose, some effects are referenced in the core code using reserved names. these effects are:

Name Kind Purpose
Effects/ssao Works on a full screen quad Compute ambient occlusion from the normal buffer and the depth buffer
Effects/ambient Works on a full screen quad Copies the diffuse color buffer multiplied by the ambient light to the lighting buffer. Ambient Occlusion can also affect ambient light.
Effects/light-spot Works on real geometry of the light volume Computes the light contribution of a spot light defined in a light animation having a light-type of spot
Effects/fog Works on a full screen quad Computes the fog from the G-buffer and the lighting parameters
Effects/display Works on a full screen quad Renders the composite final image from the G-buffer and the lighting buffer

Guidelines for modelers

Porting aircraft

  • Rembrandt computes shadows => no more fake shadows in the model
  • Rembrandt computes ambient occlusion => no ambient occlusion baked into textures
  • Rembrandt has light => static lightmap are not needed, emissive color to see models at night is not needed and would interfere
  • Rembrandt has glow => incorrectly used emissive colors may blur displays and make some text unreadable. Light size may have to be adjusted
  • Rembrandt has strict needs with shaders => shaders need to be adjusted to comply with the new framework otherwise the view will be plain wrong
  • Rembrandt can't do transparent surfaces => transparent surface need to be properly registered to render them with the classical path

Registering all translucent surfaces

Every model is, by default, rendered using the Effects/model-default effect. This effect initialize the G-buffer, ignoring transparent surfaces, by doing alpha testing and rendering all the geometry in the default bin. It is not possible to redirect rendering to transparent bins when the associated texture has alpha channel because most models use a single texture atlas and even opaque parts are rendered with texture with alpha channel.

If a model needs to have transparent or translucent surfaces, these surface objects need to be assigned a different effect that sets explicitly the render bin to "DepthSortedBin", or sets the rendering hint to "transparent". This tells the renderer to render this object using forward rendering, so lighting and fog need to be enabled, and if a shader program is used, they should be computed in the classical way. The Effects/model-transparent can be used to register simple transparent/translucent surfaces. You assign this effect to an object (or multiple objects) like:

<effect>
 <inherits-from>Effects/model-transparent</inherits-from>
 <object-name>TheObject</object-name>
</effect>

If opaque surface need to have special effect, for example to apply bump mapping, this effect should use the "RenderBin" bin, or the rendering hint set to "opaque", and the G-buffer needs to be initialized correctly in the Geometry stage.

Adding lights to a model

There are two things to consider: the appearance of the light source and the illuminated area. For the appearance of the light source (what you see when you look at the bulb), you need a model with an emissive material that will produce the glow effect and that is visible at night.

For the effect of the source on its environment (the lit area), we must have in the 3D model (the .ac file) a volume that includes the effect (Light Volume). It can be a large cone for spotlights or a sphere for point light. It's important that the light volume is closed, convex and it's normals are oriented outward.

The light volume must be part of the geometry of the model and be referenced in the animation file. No need to add a color or an effect to this volume. Light calculation is only done on the fragments covered by the light volume, but has no influence on the color or the attenuation of the light.

All available animations are possible on the light volume, except material and texture. It is not possible to change color of lights for the moment, except switching to another animation. Axis and position are in object space and are transformed by the subsequent animations.

Spotlights

<animation>
   <type>light</type>
   <light-type>spot</light-type>
   <name>LightSrcRight</name>
   <object-name>LightRight</object-name>
   <nopreview/>
   <position>
     <x>0.169</x>
     <y>0.570</y>
     <z>0.713</z>
   </position>
   <direction>
     <x>-0.9988</x>
     <y>0.0349</y>
     <z>-0.0349</z>
   </direction>
   <ambient>
     <r>0.03</r>
     <g>0.03</g>
     <b>0.03</b>
     <a>1.0</a>
   </ambient>
   <diffuse>
     <r>0.7</r>
     <g>0.7</g>
     <b>0.6</b>
     <a>1.0</a>
   </diffuse>
   <specular>
     <r>0.7</r>
     <g>0.7</g>
     <b>0.7</b>
     <a>1.0</a>
   </specular>
   <dim-factor>
      <property>dimming/property</property>
      <!-- optional begin -->
      <expression />
      <interpolation />
      <factor>1</factor>
      <offset>0</offset>
      <min>0</min>
      <max>1</max>
      <!-- optional end -->
   </dim-factor>
   <attenuation>
     <c>1.0</c>
     <l>0.002</l>
     <q>0.00005</q>
   </attenuation>
   <exponent>30.0</exponent>
   <cutoff>39</cutoff>
   <near-m>3.5</near-m>
   <far-m>39</far-m>
 </animation>
Name Purpose
type Install the light animation
light-type This is a spot light
name Name given to this animation
object-name Name of the light volume in the 3d model (typically a cone with an apex at position, along direction axis if cutoff is lesser than 90 degrees, or a sphere centered at position if cutoff is greater than 90 degrees )
nopreview Hide light volume in fgrun 3d preview
position In object space, position of the light
direction In object space, direction to the center of the spot
ambient Ambient color of the light
diffuse Diffuse color of the light
specular Specular color of the light
dim-factor Group of parameters to control a factor that is applied to ambient, diffuse and specular at the same time
attenuation Three element vector. <c> element is the constant factor, <l> element is the linear factor and element is the quadratic factor.

Attenuation of color at distance d is Spotlight attenuation.png

exponent Attenuation is multiplied by pow( dot( lightDir, <direction> ), <exponent> ), lightDir being vector from light position to point, in camera space.
cutoff Point is lit by this source if dot( lightDir, <direction> ) > <cutoff> , lightDir being vector from light position to point, in camera space.
near-m Minimum distance of influence, from position, in meters
far-m Maximum distance of influence, from position, in meters

Point lights

<animation>
   <type>light</type>
   <light-type>point</light-type>
   <name>LightSrcRight</name>
   <object-name>LightRight</object-name>
   <nopreview/>
   <position>
     <x>0.169</x>
     <y>0.570</y>
     <z>0.713</z>
   </position>
   <ambient>
     <r>0.03</r>
     <g>0.03</g>
     <b>0.03</b>
     <a>1.0</a>
   </ambient>
   <diffuse>
     <r>0.7</r>
     <g>0.7</g>
     <b>0.6</b>
     <a>1.0</a>
   </diffuse>
   <specular>
     <r>0.7</r>
     <g>0.7</g>
     <b>0.7</b>
     <a>1.0</a>
   </specular>
   <dim-factor>
      <property>dimming/property</property>
      <!-- optional begin -->
      <expression />
      <interpolation />
      <factor>1</factor>
      <offset>0</offset>
      <min>0</min>
      <max>1</max>
      <!-- optional end -->
   </dim-factor>
   <attenuation>
     <c>1.0</c>
     <l>0.002</l>
     <q>0.00005</q>
   </attenuation>
   <near-m>3.5</near-m>
   <far-m>39</far-m>
 </animation>
Name Purpose
type Install the light animation
light-type This is a point light
name Name given to this animation
object-name Name of the light volume in the 3d model (typically a sphere centered on position, with a radius of far-m)
nopreview Hide light volume in fgrun 3d preview
position In object space, position of the light
ambient Ambient color of the light
diffuse Diffuse color of the light
specular Specular color of the light
dim-factor Group of parameters to control a factor that is applied to ambient, diffuse and specular at the same time
attenuation Three element vector. <c> element is the constant factor, <l> element is the linear factor and element is the quadratic factor.

Attenuation of color at distance d is Spotlight attenuation.png

near-m Minimum distance of influence, from position, in meters
far-m Maximum distance of influence, from position, in meters

TODO List

Completed tasks

  • Fix shadow rendering when using multi threading in OSG
  • Implement Cascaded Shadow Map (need to be optimized - frustum calculation and night)
  • Honor 'noshadow' animation (done)
  • See what happens with glow in fog : unknown landclass creates white patches in the emission buffer - scenery generation problem
  • Test multi-screen (mostly done)
  • Restore splashscreen
  • Draw transparent objects with forward rendering (may need to capture the transparent bin from the geometry stage and move it in the display stage) (OK - needs model contribution)
  • Add spotlights as animations (nearly finished)
  • find a solution for ambient and emissive color of material (may need an additional buffer)
  • Provide a shader for transparent objects that could render to the emissive buffer too (using MRT) not doable. Light pass can't use MRT
  • Use stencil buffer to limit light range(no - done in light shader)
    • needed for cockpit light to implement fake shadows and avoid lighting the runway from the cabin through the airframe
  • Use effect system instead of hard-coded shaders
  • Add new animation to link a light source to a model (need to provide point light animation duplicating spot light) (done)
  • Tidy up the architecture (done)
  • Global strength of glow or ambient occlusion via slider in rendering dialog
  • Fix dim-factor in multiplayer mode (done)
  • Design and implement a configurable pipeline (done)
  • Document rendering pipeline configuration file format (done)

Near term tasks

  • Convert existing shaders to deferred rendering
  • Avoid to redraw opaque objects in the light pass. Involve OSG node mask not properly initialized.
  • take care of particles and precipitation
  • Fix fog on clouds
  • Fix shadow matrices in multi-screen
  • Implement lightfield shader

Long term ideas (unsorted)

  • implement strength of glow (in the emissive buffer alpha channel)
    • provide levels 0 to 5 - we are currently at level 5
    • level 0 should be ok for MFDs that are currenly unreadable because blurred
  • Modify shadows to allow multiple casters (limited list)
    • Implement a priority list of light sources, based on priority and distance from the viewer
  • Restore depth partitioning using depth ranges
  • Restore stereo and other options currently available in CameraGroup
  • Implement quality vs performance user control

Gallery

Appendix

References