Jump to: navigation, search

Project Rembrandt

40,967 bytes added, 15:01, 17 February 2019
Status (07/2014): obsolete due to Compositor
{{WIP}}== Why this the name ? ==[{{Wikipedia|Rembrandt Rembrandt] }} was a dutch painter living in the 17th century, famous as one of the master of [ {{Wikipedia|chiaroscuro]}}.
This project is about changing the way [[FlightGear]] renders lights, [[shadows]] and shades, and aims at making Rembrandt painting style possible in FG.
{{forum|47|Effects & Shaders}}
== What is it ? ==
|Deferred {{=}} rendering a geometry pass into the geometry (g-)buffer which holds positions, normals, materials, then doing all operations (texel, light, ...) in fragment passes on that buffer (or any others).<br/>
Forward {{=}} (usually) rendering part of the shading (typically ambient and diffuse light) per vertex, extrapolate all quantities which are declared as varying across triangles and hand them via rasterizer to the fragment shader which does the rest
|{{cite web |url=
|title=<nowiki>Re: Orbital Makes the Sky Black</nowiki>
|date=<nowiki>Sun Oct 19</nowiki>
The idea driving the project is to implement [ deferred rendering] inside FlightGear.
From the beginning FlightGear had a forward renderer that tries to render all properties of an object in one pass (shading, lighting, fog, ...), making it difficult to render more sophisticated shading (see the [[FlightGear Newsletter December 2011#Shaders|'Uber-shader']]) because one have has to take into account all aspects of the [ rendering equation].
[[Image:project_rembrandt_1.png|thumb|300px|Main view with the content of buffers displayed at corners]]
On the contrary, deferred rendering is about separating operations in simplified stages and collect collecting the intermediary results in hidden buffers that can be used by the next stage.
;First stage is the Geometry Stage :
;Then comes the Lighting Stage, with several substages :
:*<u>Sky and cloud pass</u>: the sky and the clouds are is first drawn using classical method.
:*<u>Ambient pass</u>: the diffuse buffer is modulated with the ambient color of the scene and is drawn as a screen-aligned textured quad
:*<u>Sunlight pass</u>: a second screen aligned quad is drawn and a shader computes the view position of every pixel to compute its diffuse and specular color, using the normal stored in the first stage. The resulting color is blended with the previous pass. Shadows are computed here by comparing the position of the pixel with the position of the light occluder stored in the shadow map.
:*<u>Additional light pass</u> (''to be implemented''): the scene graph will be traversed another time to display light volumes (cone or frusta for spot lights, sphere for omni-directional lights) and their shader will add the light contributed by the source only on pixels receiving light.
:*<u>Fog pass</u>: a new screen aligned quad is draw and the position of the pixel is computed to evaluate the amount of fog the pixel has. The fog color is blended with the result of the previous stage.
:*<u>Additional light pass</u>: the scene graph will be traversed another time to display light volumes (cone or frusta for spot lights, sphere for omni-directional lights) and their shader will add the light contributed by the source only on pixels receiving light.
:*<u>Transparent objects pass</u>: transparent objects (and clouds) are finally rendered using classical method.
:All lighting computations are accumulated in a single buffer that will be used for the last stage, in addition of the one computed by the Geometry stage.
In FG, we end the rendering pipeline by displaying the [[Menubar|GUI]] and the [[HUD]].
All these stages are more precisely described if in this [ tutorial] that is the basis of the current code, with some addition and modifications. C++ developers interested in learning more about how Rembrandt works, will want to look at these initial $FG_SRC commits (note that the viewer related sources are now to be found in $FG_SRC/Viewer):* 94e3ae4c675463c358071e1d9da8de583cf56e15 * 6b008126b5fd99c38778c6293c15f9721a4fa509* 64e3e98069fb2310311687b9f099b338b8b375a5* bb16463d631a8d87310a54a573966eb1cca813e6
== Caveats ==
Deferred rendering is not able to display transparency. For the moment, clouds are rendered separately and should be lit and shaded by their own. Transparent surfaces are alpha-tested and not blended. They would have to be drawn in their own bin over the composited image.
Deferred rendering is not capable It also doesn't fit with depth partitioning because the depth buffer should be kept to display transparent. For retain the view space position, so for the moment, clouds are renderer separately and should be lit and shaded by their own. Transparent surfaces are alphaz-tested and not blendedfighting is quite visible. They would have to Depth partitioning with non overlapping depth range might be drawn in their own bin over the composited imagesolution and should be experimented at one point.
It also don't fit with depth partitioning The glow pass can make certain MFDs (that use emissive color) unreadable because the depth buffer should be kept to retain the view space position, so for the moment, z-fighting is quite visibleof blurring. Depth partitioning with non overlapping depth range might be the solution and should Should be experimented at one pointtreated as transparent.
== Implementation ==
=== Repositories ===
Source code and data are available in gitorious repositories :: code is in <tt>project/rembrandt</tt> the main branchof the [[FlightGear and Git|official repository]]. Any other location is not maintained anymore.
<span style="color:red;font-size== Rendering of transparent surfaces ===[[Image:1project_rembrandt_5.5em;font-weight:bold">Important: This is experimental code png|thumb|300px|Transparent surfaces drawn after opaque objects]]Transparent surfaces are detected by OSG loader plugins and was only compiled with MSVC 2008</span>their state set receive the TRANSPARENT_BIN rendering hint. In the culling pass,<br /> but should build 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 run on other systems as saved in a temporary collection. In a cull callback attached to the modifications involved Lighting camera, after the scenegraph traversal, the transparent bins saved at the previous stage, are quite basicadded 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.
<span style="color== Memory consumption ===For each camera defined in the camera group, there is a separate shadow map, so the video memory usage is :red;font* G-sizebuffer and Lighting buffer:120 bytes per pixel.5em;font-weightFor an HD screen (1920x1080) memory requirement is 40 Mb* Shadow map:bold">The code 3 x shadow_map_size x shadow_map_size bytes (if size is 8192, whole map size is not yet optimized</span><br /> 192 MbNot counting textures, display list or vertex buffers for models and may put the graphic card under pressure.terrain
3 HD screens require 120 Mb of memory for the buffers (shadow excluded), you're asking 3x8192x8192x3 =576 Mb (megabytes) of memory for the shadows alone. If you are seeing error messages during startup or FlightGear doesn't start up properly, it's probably because you don't have enough free video memory. Reduce the size of the shadow map in preferences.xml by locating  <syntaxhighlight lang="xml"><map-size type= Rendering "int">8192</map-size></syntaxhighlight> And put 4096 or 2048 instead.You can also use a startup parameter <code>--prop:/sim/rendering/shadows/map-size=2048</code> === Configurable pipeline ===The Rembrandt renderer uses an XML file to setup its pipeline for each viewport described in the camera group. This file describes the way the intermediary buffers are setup and how the different rendering stages are sequenced. The general outline of transparent surfaces a pipeline file is as follow : <syntaxhighlight lang="xml"><?xml version="1.0" encoding="utf-8"?><PropertyList> <!-- BUFFERS --> <buffer> <!-- First buffer definition --> </buffer> <buffer> <!-- nth buffer definition --> </buffer> <!-- STAGES --> <stage> <!-- First stage definition --> </stage> <stage> <!-- nth stage definition --> </stage></PropertyList></syntaxhighlight> ==== Buffers ====A buffer is a texture used as a storage area in the GPU. It's size is usually a multiple of the screen size, but fixed size is supported (typical for shadow map). The description of a buffer is described below : <syntaxhighlight lang="xml"> <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></syntaxhighlight> ==== Stages ====A stage is an unit of rendering to a group of buffer. Most stages are predefined and their type is not free. When a type is not specified, the name is used. Stage types are :{|class="wikitable"|style!align="vertical-left"| Stage type!align:top="left"|Purpose|-|geometry|The geometry stage initialize most of the buffers and works on the real objects and geometry. Transparent surfaces objects are detected by OSG loader plugins and their state set receive aside and will be used untouched in the TRANSPARENT_BIN rendering hintlighting stage. In Other opaque geometry is rendered with the culling pass, standard effects that do the cull visitor orders transparent surfaces hard work to put sensible data in transparent binthe buffers. |-|shadow|In a cull callback attached to the Geometry camerathis stage, after the scenegraph traversal, geometry is rendered in the transparent bins are removed normal map from the render stage and saved in a temporary collectionperspective of the sun. In a cull callback attached to |-|lighting|This stage uses the Lighting camera, after the scenegraph traversal, the transparent bins saved at buffers filled by the previous stage, are added stages to the render stage light every pixel of the Lighting camera with a high order numscene. That way, the transparent surface are drawn on top The result is rendered in another buffer to allow post effects.|-|fullscreen|Stages of this type are used to alter the whole scene lighted or transform data from the Gbuffera particular buffer.|[[Image:project_rembrandt_5.png-|thumbdisplay|300px|Transparent surfaces drawn after opaque objects]]Final rendering of the scene to the screen or the texture defined in the camera group.
A stage description is outlined below :<syntaxhighlight lang="xml"> <stage> <name>stage-name</name> <type>stage-type</type> <!-- optional if name is one of the predefined type except fullscreen --> <order-num>-1</order-num> <effect>Effects/fullscreen-effect</effect> <!-- only if type == Memory consumption fullscreen --> <needs-du-dv>true</needs-du-dv> <!-- only if type ==fullscreen --> <scale-factor>0.25</scale-factor> <!-- only if type == fullscreen -->
For <!-- 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></syntaxhighlight>Stages render in buffers (except for the display stage). Attachments describe which buffers are affected by each camera defined stage. ===== Attachments =====Attachment describe bindings between buffer and attachment point :<syntaxhighlight lang="xml"> <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></syntaxhighlight> ===== Passes =====Passes are only available in the camera group<tt>lighting</tt> stage. Three kind of stage are allowed : {| class="wikitable"!align="left"| Pass type!align="left"| Purpose|-|sky-clouds|Renders the skydome, sun, moon, planet, stars and clouds|-|lights|Renders additional spot and point lights|-|fullscreen|Fullscreen pass analog to a fullscreen stage except that it renders in the video memory usage buffers attached to the lighting stage|}A pass is defined like below :<syntaxhighlight lang="xml"> <pass> <name>pass-name</name> <type>pass-type</type> <!-- optional if name is one of the predefined type except fullscreen --> <order-num>-1</order-num> <effect>Effects/fullscreen-effect</effect> <!-- only if type == fullscreen -->  <!-- optional condition --> <condition> <!-- Valid boolean expression --> </condition> </pass></syntaxhighlight> A typical lighting stage is a succession of 5 passes :# <tt>sky-clouds</tt> pass# <tt>fullscreen</tt> pass for ambient light# <tt>fullscreen</tt> pass for sun light (and shadows)# <tt>lights</tt> pass# <tt>fullscreen</tt> pass for fog Each effect attached to the fullscreen passes define the way blending is done between the pass and the previous accumulation of render.  === C++ implementation === On the C++ side, Rembrandt is set up in those steps: *G''buildRenderingPipeline()'' is the last common function between forward rendering and deferred rendering. That's the point of start for specific deferred stuff. In this function we call ''buildDeferredPipeline()''** ''buildDeferredPipeline()'' is just a wrapper for ''buildCameraFromRenderingPipeline()''*** ''buildCameraFromRenderingPipeline()'' is where we initialize all buffers and create all the stages found in ''Effects/default-buffer pipeline.xml'' with the call to ''buildBuffers()'' and Lighting ''buildStage()''**** ''buildBuffers()'' is where we ask to build each bufferwith the call to ''buildDeferredBuffer()''***** ''buildDeferredBuffer()'' create a 2D texture**** ''buildStage()'' is where we ask to build each camera depending on the type of the stage (geometry, lighting, shadow, fullscreen, display) with the call to ''buildDeferred*Camera()'' (where * is the stage type)***** ''buildDeferred*Camera()''is where we build the camera, for each camera we attach the required buffers with the call to ''buildAttachments()''.****** ''buildDeferredGeometryCamera()'' c.f [http: 40 bytes per pixel//wiki. For an HD screen What is it ?]****** ''buildDeferredShadowCamera(1920x1080) memory requirement '' c.f [ What is 80 Mbit ?]*Shadow map***** ''buildDeferredLightingCamera()'' Only for the lighting camera (''buildDeferredLightingCamera()'') we have to build passes who is called with ''buildPass()'' c.f [http: 3 x shadow_map_size x shadow_map_size bytes // What is it ?]****** ''buildDeferredFullscreenCamera(if size )'' c.f [ What is 8192it ?]****** ''buildDeferredDisplayCamera()'' c.f [ What is it ?] == Running Flightgear with Rembrandt ==[[File:Rembrandt dialog.png|thumb|270px|Rembrandt dialog]]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!):* <code>--enable-rembrandt</code> (when using [[FGRun]], whole you may add this behind the <tt>FG_EXECUTABLE</tt> on the first page). * <code>--prop:/sim/rendering/rembrandt/enabled=true</code> (with FGRun this can be added via <tt>Advanced > Properties</tt> on the last page, but only the <code>/sim/rendering/rembrandt/enabled=true</code> part). The <tt>View > Rendering Options > Rembrandt Options</tt> dialog allows you to toggle and adjust the various features that Rembrandt offers. 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 :  RenderStage::runCameraSetUp(), FBO setup failed, FBO status= 0x8cd6 Warning: RenderStage::runCameraSetUp(State&) Pbuffer does not support multiple color outputs. The ssao effect provided in v2.8.0 may generate these messages, more often on Mac : <pre>FRAGMENT glCompileShader "/Users/xxxx/Desktop/" FAILEDFRAGMENT Shader "/Users/xxxx/Desktop/" infolog:ERROR: 0:20: 'array of 2-component vector of float' : constructor not supported for typeERROR: 0:20: 'array of 2-component vector of float' : no matching overloaded function foundERROR: 0:20: 'const 2-component vector of float' : cannot declare arrays of this typeERROR: 0:20: 'v' : redefinitionERROR: 0:55: 'reflect' : no matching overloaded function foundERROR: 0:55: '=' : cannot convert from 'float' to '2-component vector of float' glLinkProgram "" FAILEDProgram "" infolog:ERROR: One or more attached shaders not successfully compiled</pre>In that case, disable ambient occlusion with the command :<tt>--prop:/sim/rendering/rembrandt/ambient-occlusion-buffers=false</tt> There is a number of additional options that can help to avoid these problems : {| class="wikitable"|<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.|-|<tt>--prop:/sim/rendering/shadows/enabled=false</tt>|Disable shadows altogether.|-|<tt>--prop:/sim/rendering/shadows/num-cascades=1</tt>|Set <tt>/sim/rendering/shadows/cascade-far-m[0]</tt> to change the shadow map size range. The more the range, the less the resolution (default value is 192 Mb5 meters)Not counting textures|-|<tt>--prop:/sim/rendering/shadows/map-size=<power-of-two></tt>|Set the shadow map size. Useful values are 1024, display list 2048, 4096 or vertex 8192. Few cards have the resources to support 16384.|-|<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.|-|<tt>--prop:/sim/rendering/shadows/cascade-far-m[i]</tt>(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.|-|<tt>--prop:/sim/rendering/rembrandt/no-16bit-buffer=false</tt>|By default, Rembrandt uses 8 bit buffers for models normals (so the property is set to true by default). This may create banding artifacts on specular highlights. If it's unacceptable and terrainthe GPU supports it, set to false to have better precision for normals and effects relying on normal direction.|}
== Guidelines for shader writers ==
=== Predefined uniforms ===
These glsl uniforms don't need to be declared in the effect file.
{|borderclass="1" cellspacing="0" cellpadding="3wikitable"
|In fullscreen pass only, projection matrix inverse used to transform the screen position to view direction
|Position of the camera in world space, expressed in cartesian coordinates
|Position of the camera in world space, expressed in geodesic coordinates (longitude in radians, latitude in radians, elevation in meters)
|Tells if the depth is stored in a depth texture or a color texture
They still have to be declared in the fragment or the vertex shader to be used.
=== Utility functions ===
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>.
==== gbuffer-encode.frag ====
;<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
==== gbuffer-functions.frag ====
;<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>
;<tt>vec3 normal_decode(vec2 enc)</tt>
:Reconstruct normals from the G-Buffer. Used in fullscreen shaders and light shaders
;<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.
;<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.
;<tt>vec3 position( vec3 viewDir, float depth )</tt>
:Reconstruct eye space position from the view direction and the depth read from the depth buffer
;<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
;<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>
==== Usage ====
For material shaders, it is necessary to provide both <tt>gbuffer-functions.frag</tt> and <tt>gbuffer-encode.frag</tt> in the effect file, like this :
<syntaxhighlight lang="xml">
For fullscreen passes shaders, only <tt>gbuffer-functions.frag</tt> should be provided, like this :
<syntaxhighlight lang="xml">
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 :
<syntaxhighlight lang="glsl">
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 : {| class="wikitable" style="text-align: center;"|depth (gl_FragDepth)||GL_DEPTH_COMPONENT32||colspan="4"|Fragment depth|-|gl_FragData[0]||GL_RG16||colspan="2"|normal.x * 0.5 + 0.5||colspan="2"|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 <!--
#Depth buffer, modified with gl_FragDepth, will record the distance between the fragment and the camera. Default behavior is to avoid to touch it, living the GPU rasterizer doing sensible things by interpolating vertex gl_Position from the Vertex or the Geometry Shader. If altering the computed depth is required, like in the Urban shader, the value of gl_FragDepth should be set.
#Normal buffer, modified with gl_FragData[0].xyz, will record the normal of the fragment in eye coordinates. gl_FragData[0].w is reserved for future use. The interpolated normal is usually simply stored but bump mapping or relief mapping affecting the normal can be computed here.
#Diffuse color buffer, modified with gl_FragData[1].rgb, will hold the unshaded color of the fragment, usually modulating the material diffuse+ambient color with the texture map. Diffuse color from environment mapping should also go here.
#Specular color, modified with gl_FragData[2].rgb, and specular shininess in gl_FragData[2].a, will retain the specular color of the fragment.
#Emission color, modified with gl_FragData[3].rgbIn anyway, don't use gl_FragColor as it is incompatible with MRT (Multi Render Target) and would affect the three four last buffers with the same value.In that case, the model will glow (emission buffer initialized) and parts will disappear at certain view angles because normals are not initialized properly. <span style="color:red;font-size:1.5em;font-weight:bold">This layout is going to change in the official repository when the merge will be done. The goal of this change is to fill more useful data into less texture memory and get rid of a stupid IP issue on float textures</span> -->
=== Additional light pass ===
=== 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:
{|borderclass="1" cellspacing="0wikitable" cellpadding="3"
|Works on a full screen quad
|Compute ambient occlusion from the normal buffer and the depth buffer
|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.
== 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
Once your aircraft has been ported, please modify its wiki page and add this symbol to it:
For a list of converted aircraft, please see [].
=== Registering all translucent surfaces ===
Every model is, by default, rendered using the <tt>Effects/model-default</tt> 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 <tt>Effects/model-transparent</tt> 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> '''Beware: <Effect> only works on real objects, not on groups of objects or animations.'''
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.
A surface that uses the [[ALS technical notes#ALS glass effect|ALS glass effect]] does not need to be separately registered for Rembrandt, this is done automatically.
=== Making sure that all geometry will cast shadow ===
To limit the amount of geometry rendered in the shadow map, and also to reduce artifacts (shadow acne), only faces not facing the sun are casting shadows. The test is made using the normal orientation. That means that double-sided polygons, or mesh that are not closed, will be transparent to light at certain sun angles. To avoid that, modelers can either :
* ensure that the object is always in the shadow of another objects,
* close their mesh, or,
* double polygons with the normal set to the opposite.
=== Adding lights to a model ===
Only spotlights There are implemented for two things to consider: the moment. The light volume must be part appearance of the geometry of the model light source and be referenced in the animation fileilluminated area. No need to add a color or an effect to this volume. Light calculation is only done on For the fragments covered by appearance of the light volumesource (what you see when you look at the bulb), but has no influence on you need a model with an emissive material that will produce the color or the attenuation of the light. Typical light volume for a spot light glow effect and that is a conevisible 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 ====
<presyntaxhighlight lang="xml">
<!-- optional begin -->
<expression />
<interpolation />
<!-- optional end -->
{|borderclass="1" cellspacing="0wikitable" cellpadding="3"
|Name of the light volumein the 3d model (typically a cone with an apex at <tt>position</tt>, along <tt>direction</tt> axis if <tt>cutoff</tt> is lesser than 90 degrees, or a sphere centered at <tt>position</tt> if <tt>cutoff</tt> is greater than 90 degrees )|-|<tt>nopreview</tt>|Hide light volume in fgrun 3d preview
|Specular color of the light
|Group of parameters to control a factor that is applied to ambient, diffuse and specular at the same time
|Three element vector. <c> element is the constant factor, <l> element is the linear factor and <&lt;q> &gt; element is the quadratic factor.<br />
Attenuation of color at distance d is [[File:Spotlight_attenuation.png]]
|point Point is lit by this source if <tt>dot( lightDir, <direction> ) > <cutoff></tt> , lightDir being vector from light position to point, in camera space.
|Minimum distance of influence, from position, in meters
|Maximum distance of influence, from position, in meters
== References == Point lights ====*[http:{|cellpadding=10||valign=top|<syntaxhighlight lang="xml"><animation> <type>light</type> <light-type>point</httplight-type> <name>LightSrcRight</name> <object-name>LightRight</object-name> <nopreview/> <position> <x>0.download169</x> <y>0.nvidia570</y> <z>0.com713</developerz> </presentationsposition> <ambient> <r>0.03</2004r> <g>0.03</6800_Leaguesg> <b>0.03</6800_Leagues_Deferred_Shadingb> <a>1.pdf Deferred Shading] by Shawn Hargreaves and Mark Harris0</a>*[http: </ambient> <diffuse> <r>0.7</bat710r> <g>0.univ7</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-lyon1factor> <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.fr0</~jciehlc> <l>0.002</Publicl> <q>0.00005</educq> </GAMAattenuation> <near-m>3.5</2007near-m> <far-m>39</Deferred_Shading_Tutorial_SBGAMES2005far-m> </animation></syntaxhighlight>|valign=top|{| class="wikitable" cellpadding="3"!Name!Purpose|-|<tt>type</tt>|Install the <tt>'''light'''</tt> animation|-|<tt>light-type</tt>|This is a <tt>'''point'''</tt> light|-|<tt>name</tt>|Name given to this animation|-|<tt>object-name</tt>|Name of the light volume in the 3d model (typically a sphere centered on <tt>position</tt>, with a radius of <tt>far-m</tt>)|-|<tt>nopreview</tt>|Hide light volume in fgrun 3d preview|-|<tt>position</tt>|In object space, position of the light|-|<tt>ambient</tt>|Ambient color of the light|-|<tt>diffuse</tt>|Diffuse color of the light|-|<tt>specular</tt>|Specular color of the light|-|<tt>dim-factor</tt>|Group of parameters to control a factor that is applied to ambient, diffuse and specular at the same time|-|<tt>attenuation</tt>|Three element vector.pdf Deferred Shading Tutorial<c> element is the constant factor, <l> element is the linear factor and <q> element is the quadratic factor.<br />Attenuation of color at distance d is [[File:Spotlight_attenuation.png] by Fabio Policarpo ]|-|<tt>near-m</tt>|Minimum distance of influence, from position, in meters|-|<tt>far-m</tt>|Maximum distance of influence, from position, in meters|}|} ==== Performance and Francisco Fonsecacompatibility considerations ====Every light on screen is equivalent for the GPU of redrawing the light volume with a shader, without z buffer culling. So each light comes with a cost, that is small taken individually but noticeable when a lot of them are visible. That cost also increase with the size of the light volume. Beside that, it is wise to allow a model to work with the classical renderer that know nothing about lights and would render light volumes like other geometry. So a good practice is to complement each light animation with a select animation checking :*if Rembrandt is enabled*if the user selected quality match with the purpose of the light*if the light should be on or off according to the other parameters of the simulation (position of the sun, position of switch, presence of power, ...) A quality property is created to reflect the user preferences about quality vs performance concerning lights, and a proper slider is added to the shader dialog.[http[File:Fgfs-shaders-with-light.jpg|thumb|Light quality slider]]The propery to use is : /sim/wwwrendering/shaders/lightsThe quality slider sets its range from 0 (no lights) to 4 (all lights on).guerrillaSimple airport lamp post appears at 1. Few bridge lamps at 2, all simple bridge lamp at 3 and more involved one at 4. Example:<syntaxhighlight lang="xml"><animation> <type>light</type> <light-gamestype>spot</light-type> <name>LightSource</name> <object-name>LightVolume</object-name> .com..</publicationsanimation> <animation> <type>select</dr_kz2_rsx_dev07type> <!-- Select the named animation --> <object-name>LightSource</object-name> <condition> <and> <!-- Rembrandt enabled ? --> <property>/sim/rendering/rembrandt/enabled</property> <!-- Quality ok ? --> <greater-than> <property>/sim/rendering/shaders/lights</property> <value>3.pdf Deferred Rendering in Killzone 20</value> </greater-than> <!-- Simulation conditions ? --> <greater-than> <property>/sim/time/sun-angle-rad</property> <value>1.57</value> </greater-than> </and> </condition></animation> </syntaxhighlight> === Tutorials ===[[User:F-JJTH|F-JJTH] ] compiled his experience and the one acquired by Michal Valient*the PAF team converting aircraft in {{fr}} [ Battlefield 3 Graphics Tech Talkrembrandt this tutorial] by Johan Andersson,
== TODO List ==
 === Mac Issues ===More and more Apple/Mac users are reporting issues related to running Rembrandt []. Looking at the Mac GPU specs, it isn't clear if the Mac/ATI hardware/driver is generally insufficient, it should seem possible to run a customized Rembrandt setup with acceptable frame rates at 15-35 fps (assuming everything else being disabled for starters).  GLSL compilers have varying quality and especially the Mac (ATI/AMD) GLSL compilers are known to have issues with more sophisticated/nested constructs, so that it may help to reduce complexity of GLSL statements by splitting them up, instead of using nested anonymous vectors or functions (fatal error C9999: Nested functions, aborting!) for example. So, the specific issue on Mac is some shaders being miscompiled, so the frame-rates are particularly bad, since the driver is hitting (slow) error paths. Certainly some Rembrandt-related shades fail to compile, though whether or not these are optional or required ones, isn't clear (Fred?). Some users reported that the errors and problems after upgrading their OS from OsX, 10.6.8 to OSX 10.8.2 (Mountain Lion) [] or OS Snow Leopard (10.6. to Mountain Lion (10.8.2), downloaded XQuartz 2.7.4 []. The shader errors would suggest that certain GLSL constructs are not supported by the ATI/AMD glsl compiler - this seems to be a known issue: [!topic/] To address this, one would need to port the corresponding shaders - like just was done to get rid of the constructs that caused errors on old GeForce 7x generation hardware. It seems the hardware is not the problem, but the driver being way out of date. I find the fact that it's the Cg compiler and not a native glsl compiler that returns the errors very strange. Another FG 2.10 user on MacPro 3.2 GHz Quad-Core Xeon, 8GB RAM, MacOS X 10.6.8. ATI Radeon HD 5870 (gl-vendor:ATI Technologies Inc., gl-version:2.1 ATI-1.6.36 gl-renderer:ATI Radeon HD 5870 OpenGL Engine, gl-shading-language-version:1.20) report said "Rembrandt is still unusable on my Mac. One frame every 4-5 seconds and it looks weird."[] It's also worth noting that a number of FG 2.8 users reported that Rembrandt would still work for them using the 2.8 binary, unlike the 2.10 binary on Mac OSX version 10.7.5 on an iMac (AMD Radeon HD Graphics with 512MB) []. So the issue seems to occur largely in combination with older Mac OS versions and newer FG versions (>=2.8+) []. It appears it is the Rembrandt lighting causing issues while in non rembrandt mode with older Mac OS + FG 2.8 and better. On other OS setups, the rembrandt lighting gets ignored when rembrandt is turned off, but not in this case. Both lighting modes are present and creating the weird light cone effects []. If there are any console messages (like warnings or errors) shown, that would be helpful to know. A number of rembrandt related changes got fixed by Fred like this. Obviously, it is difficult for shader developers to troubleshoot shader related issues that they cannot reproduce with their own hardware. Rembrandt is being largely developed by a single Windows/Nvidia-based developer, so it gets very little testing and debugging on different platforms, especially Mac/ATI (AMD) - so as a Mac user, your safest bet is probably providing lots of feedback via the forums (or preferably the issue tracker), FredB (the Rembrandt developer) is generally pretty responsive and appreciates all helpful feedback. Obviously, it helps being able to build from source, and being able to provide detailed troubleshooting reports. These things are hard to debug/troubleshoot without having access to a corresponding system that exhibits the problem, which is why I suggested earlier to provide lots of Mac/Rembrandt-related feedback via the issue tracker, i.e. GLSL errors/warnings and anything else that could be useful.  If you have you ever tried to debug an issue that doesn't cause errors on your computer, you'll understand that it's damn difficult in the first place. Most developers don't own a Mac, and are not going to spend 1000$ or so just to have one more computer to test things on, and we don't know of anyone who buys computers for the whole purpose of testing FG on more platforms.  So as a rule we can try to pin down and solve such issues if, and only if, we get a decent bug report with tons of relevant background info and the possibility to ask follow-up questions. Remember, fixing such issues involves essentially working blind - it is trying to figure out why code that runs pefectly fine on your own computer might have issues on other computers and any traditional bug-hunting technique essentially fails. Posting a screenshot of the issue is nice, but tells little more than that it exists. It's completely impossible to turn that into any action developer-side. The underlying shader code has probably a combined 1000 lines, any of which could be problematic.  Overall, the Rembrandt situation is most likely to improve the more feedback is provided by end users with different hardware/software configurations, Fred has fixed quite a number of shader related issues in the past, so it's largely a matter of time, and obviously the quality of feedback, provided by end-users like yourself. And just in case: Note that GLSL shaders are not really compiled/built by developers (unlike the actual fgfs binary), but on an invididual basis by your GPU/graphics drivers, which happens transparently in the background, each time fgfs is started. Basically, a GLSL shader is a snippet of "source code" that is passed on to your GPU driver, which in turn compiles it down into hardware-specific instructions for your particular hardware. From a troubleshooting perspective, it would be REALLY helpful if Mac users with the corresponding hardware and knowledge could come up with extremely downstripped test cases, that either show the problem, or which no longer show the problem as significantly. Disabling other shader-based features will definitely go a long way here, because many other GLSL features have not yet been explicitly ported to support Rembrandt. In other words, you should preferably disable random building, advanced light scattern, advanced weather etc - and only really use the most basic settings to have an easily reproducable test case. To get this started, you can customize the "zero eye candy" profile and enable Rembrandt using shader level 1: [[Howto:Debugging_FlightGear_Crashes#Minimal_Rembrandt_Startup_Profile]] Some Mac folks have recently reported some success, it may be a good idea to search the forum for details, see for example: * {{cquote|I'm seeing regular crashes here from ALS and Rembrandt, but that's nothing new.<ref>{{cite web |url=|title=<nowiki>Re: [Flightgear-devel] 2.10.1</nowiki>|author=Vivian Meazza|date=Fri, 03 May 2013 10:16:13 -0700}}</ref>|Vivian Meazza}} {{cquote|With an AMD Radeon HD 5670 using free radeon driver I've never seen performance of more than 15fps with Rembrandt and if I turn shadow details up so they don't look crappy I get about 3-4fps.<ref>{{cite web |url=|title=<nowiki>Re: [Flightgear-devel] reminder: entering feature freeze now</nowiki>|author=Stefan Seifert|date=Thu, 20 Jun 2013 10:10:56 -0700}}</ref>|Stefan Seifert}} {{cquote|with a i3770K and a GTX670, I get some hit from ALS (10-30%) but Rembrandt instantly drops me to 20fps, and < 10fps I use an aircraft I actually want to fly (777 or Citation) and go to any major airport (EGKK, EHAM, EDDM, EDDF, EGLC, VHHH) This is at 2560x1600, but on the 670 I would be highly surprised if I'm fill-rate limited, given that AA is off, and the general suboptimal size of our primitive batches. Emilian has explained on IRC this might be due to the out-of-the-box / default config for Rembrandt being highly suboptimal, which I didn't yet evaluate, I would be delighted to have it more usable.<ref>{{cite web |url=|title=<nowiki>Re: [Flightgear-devel] reminder: entering feature freeze now</nowiki>|author=James Turner|date=Thu, 20 Jun 2013 13:29:47 -0700}}</ref>|James Turner}} {{cquote|The Apple OpenGL renderer is a rather interesting beast - it's a clean-room front-end to the drivers, one of aspect of which means it is the only true 'Core Profile' 3.x renderer in wide use. (As opposed to the Ati and Nvidia Core profile drivers, which are simple the compat ones with some checks removed, I have been told). Of course FG is hence limited to 2.1 on Mac since we're a long way from Core profile support in the main code. This does however mean it produces different GLSL compile issues, and different bugs in general, from the same hardware on other platforms. (The renderer backend does of course come from the vendors, but OpenGL.framework always comes from Apple - it's not like Linux where your comes, at least potentially, from your hardware vendor)<ref>{{cite web |url=|title=<nowiki>Re: [Flightgear-devel] Shader compile failure</nowiki>|author=James Turner|date=Sat, 11 May 2013 06:53:32 -0700}}</ref>|James Turner}} {{cquote|concerning the larger issue of different rendering pipelines / approaches, my opinion is, and remains, that the long-term solution is separate viewer codebases - while a plethora would be bad, we would already benefit from a 'fixed-function, no shaders' renderer codebase distinct from a Rembrandt renderer and modern, forward-rendering OpenGL 3.x pipeline. This needs the viewer to be cleanly split out from the simulation backend, via HLA, which is exactly what Mathias (and soon, myself) are working towards, but slowly.<ref>{{cite web |url=|title=<nowiki>Re: [Flightgear-devel] Atmospheric Light Scattering</nowiki>|author=James Turner|date=Thu, 25 Apr 2013 08:09:08 -0700}}</ref>|James Turner}} {{cquote|Like you and Thorsten, I see a very significant drop (50%) in frame-rate with Rembrandt, even without most the nice features such as shadows which has put me off using it. I had thought it was just because my box is now underpowered (the march of technology....) but it sounds like other areseeing similar issues and it would be worth some further investigation.<ref>{{cite web |url=|title=<nowiki>Re: [Flightgear-devel] reminder: entering feature freeze now</nowiki>|author=Stuart Buchanan|date=Fri, 21 Jun 2013 01:40:15 -0700}}</ref>|Stuart Buchanan}} === Completed tasks ===*Fix shadow rendering when using multi threading in OSG*Implement Cascaded Shadow Map (need to be optimized - frustum calculation <del>and night</del>)*Honor <'noshadow> ' animation directive(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*<del>Draw transparent objects with forward rendering (may need to capture the transparent bin from the geometry stage and move it in the display stage)</del> (OK - needs model contribution)*<del>Add spotlights as animations (nearly finished)</del>
*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)
*Fix fog on clouds
=== Near term tasks ===
*Convert existing shaders to deferred rendering
**Modify shadows Avoid to allow multiple casters (limited list)redraw opaque objects in the light pass. Involve OSG node mask not properly initialized.**Implement a priority list take care of light sources, based on priority particles and distance from the viewerprecipitation*Fix shadow matrices in multi-screen*Add new animation to link Fix Lights in multi screen (seems same problem than shadows. Forgot a light source to a model1/w factor ?)*Tidy up the architectureImplement lightfield shader*Add some kind of fog to lights
*Restore depth partitioning using depth ranges
*Move effect of cloud coverage from water shader to sunlight shader
*Allow light masks using textures
*Use stencil double-sided operations to limit the depth of light volumes. Use depth clamp to ensure front faces are always rendered even if the camera is enclosed in the light volume.
=== Long term ideas (unsorted) ===
*Use a separate list of light volumes to avoid traversing the scenegraph again (with transparency problems). Find out how we can detect unloading of models.
*implement volumetric effects by extending lights to arbitrary shaders. Should enable to implement heat haze effect and real wake waves.
*implement strength of glow (in the emissive buffer alpha channel) - use a Poisson-disk distribution to implement variable size blur
**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 stereo and other options currently available in CameraGroup
*Implement quality vs performance user control
== Gallery ==
{{#ev:youtube|PXHhtQb5yzc}} {{#ev:youtube|peEzEapavkg}} {{#ev:youtube|RIetPh8iJXk}} {{#ev:youtube|oaNFrxgQY1c}} {{#ev:youtube|8xGzy12hlis}} {{#ev:youtube|ZyuHBlm3xXU}} {{#ev:youtube|RgH9GZRukOI}} {{#ev:youtube|UQvbHnBkpaM}} {{#ev:youtube|v02phoOqWHE}}{{#ev:youtube|dlSo4sBa7Nk}}
== Model modification log Appendix ==;c172p{{Appendix|all|* {{cite web |url=http:Add an effect to the propeller disk (object Propeller//http.Fast) to put it |title=Deferred Shading |author=Shawn Hargreaves and Mark Harris }}* {{cite web |url= |title=Deferred Shading Tutorial |author=Fabio Policarpo and Francisco Fonseca }}* {{cite web |url= |title=Deferred Rendering in a transparent binKillzone 2 |author=Michal Valient |month=July |year=2007 }};Models* {{cite web |url=http:/Airport/ |title=Battlefield 3 Graphics Tech Talk |author=Johan Andersson |month=October |year=2011 }}* {{cite web |url=http://www.xml & |title=Rendering Techniques in Split/Second |author=Jeremy Moore and David Jefferies |year=2009 }}* {{cite web |url= |title="A bit more Deferred" -baCryEngine 3 (PPT) |author=Martin Mittring }}* {{cite web |url= |title=Deferred Shading in S.T.A.L.K.E.R. |author=Oles Shishkovtsov }}* {{cite web |url=http:Add a spot light animation and a light volume// |title=Deferred Shading in Tabula Rasa |author=Rusty Koonce }};Scenery* {{cite web |url=http:/Objects/ |title=Compact Normal Storage for small g-buffers |author=Aras Pranckevičius |date=4 August 2009 |accessdate=12 April 2012 }}* {{cite web |url=http:Change KSFO_light//the-witness.xml to aptnet/news/2010/03/graphics-lighttech-shadow-maps-part-1/ |title=Graphics Tech: Shadow Maps (part 1) |author=Jonathan Blow |date=3 March 2010 |accessdate=13 April 2012 }}* {{cite web |url= |title=deferred rendering in frameranger. |author=Matt Swoboda |date=13 November 2009 |accessdate=8 July 2012 }};Aircraft* {{cite web |url=http:/followme/ asp?show_category=yes& .acwhich_category=Rendering |author=DICE |title=Publications on rendering |accessdate=15 August 2012 }}* {{cite web |url=http:Add light volumes and spotlight animations for headlights// |author=Martin Mittring |title=The Technology behind the Unreal Engine 4 Elemental Demo |accessdate=15 September 2012 }}}}
== Effect<references/Shader modification log ==;Default shaders:render to the G-buffer;Urban effect:render to the G-buffer;Spot light effect:new effect to render spot lights from the animation file;model-transparent:new effect to classify transparent surfaces (those that are not bound to the glass shader or other shader that use explicitly the transparent bin )>
[[Category:Shader development]]
[[Category:Core development projects]]
[[fr:Projet Rembrandt]]

Navigation menu