Flight Docs: Models, Materials, Material Variations, and Seasonal Variations

Overview:

In FSX mdl files contained the mesh, animations, and the associated materials and textures for that model. In Flight we separated out the materials and their association with the model into separate files. The primary reason for this was to facilitate sharing of models, and materials, reduce memory usage and also to enable much better performance via instancing. The new material system is also extremely extensible allowing any number of custom shaders and properties to be created.


Models:

For Flight we switched to using Granny3D for our model and animation pipeline in order to reduce the amount of tool work we needed to do. The Flight .model files are a slightly modified version of their file format. The models contain a set of meshes, bones, animation curves, material slot names, and some other Flight specific data (LOD information, animation scripts, reference\attach points, etc). These model formats also support pretty much any number of vertex formats you want, including having compressed\quantized vertex data which we use a lot in Flight to improve performance and reduce memory usage.


Shader Pipelines:

In Flight we added the concept of a Shader Pipeline. We replaced the uber shader that FSX used with a system that allows any number of shaders to be created. The Shader Pipeline is a set of vertex and pixel shaders (in HLSL), a mapping of material properties to their shader property and textures (including default values for the properties), and a list of supported vertex formats and instance formats for that pipeline.

Here is an example of one that is used for the airport surfaces:

Code:
<SimBase.Document>
  <FlexPipeline.Pipeline FriendlyName  = "Ground polygon shader pipeline">
    <RenderPass
      VertexShader  = "ShadersHLSL\Flexible\GroundPolygon.vs"
      PixelShader  = "ShadersHLSL\Flexible\GroundPolygon.ps"/>
    <ShaderInputDataFormat>
      <!--Position, Normal, UV (All uncompressed)-->
      <VertexDataFormatID>{16958AB6-D728-4659-B75F-CEE930F96159}</VertexDataFormatID>
      <InstanceDataFormatID>{2C4C3F89-EC57-4456-9C1D-3B60325BDE40}</InstanceDataFormatID>
    </ShaderInputDataFormat>
    <ShaderInputDataFormat>
      <!--Position, UV, Normal-->
      <VertexDataFormatID>{D11904F2-6B37-48C3-9204-C4431563F0B7}</VertexDataFormatID>
      <InstanceDataFormatID>{2C4C3F89-EC57-4456-9C1D-3B60325BDE40}</InstanceDataFormatID>
    </ShaderInputDataFormat>
    <ShaderInputDataFormat>
      <!--Position, UV, Normal, No Instance data-->
      <VertexDataFormatID>{D11904F2-6B37-48C3-9204-C4431563F0B7}</VertexDataFormatID>
      <InstanceDataFormatID>{C6DB1555-1296-4162-AC2C-14D4DD2DD91B}</InstanceDataFormatID>
    </ShaderInputDataFormat>
    <Binding SemanticName = "fDetailScale">
      <Optional>TRUE</Optional>
      <FlexMaterial.DetailScale>1.0</FlexMaterial.DetailScale>
    </Binding>
    <Binding SemanticName = "fBumpScale">
      <Optional>TRUE</Optional>
      <FlexMaterial.BumpScale>1.0</FlexMaterial.BumpScale>
    </Binding>
    <Binding SemanticName = "albedoSampler">
      <FlexMaterial.AlbedoMap>{00000000-0000-0000-0000-000000000000}</FlexMaterial.AlbedoMap>
    </Binding>
    <Binding SemanticName = "detailSampler">
      <Optional>TRUE</Optional>
      <FlexMaterial.DetailMap>{71953962-e085-4e06-9a7d-0cd8be75b282}</FlexMaterial.DetailMap>
    </Binding>
    <Binding SemanticName = "lightSampler">
      <Optional>TRUE</Optional>
      <FlexMaterial.LightMap>{00000000-0000-0000-0000-000000000000}</FlexMaterial.LightMap>
    </Binding>
    <Binding SemanticName = "normalSampler">
      <Optional>TRUE</Optional>
      <FlexMaterial.NormalMap>{efb46eb1-5386-4019-a0a4-b09e13734370}</FlexMaterial.NormalMap>
    </Binding>
  </FlexPipeline.Pipeline>
</SimBase.Document>
Each ShaderInputDataFormat determines the pairs of vertex-instance data that are supported, and each Binding specifies which shader property (SemanticName) is bound to which material properties, and whether it is optional and if it is optional what the default value is. One thing to note is that "diffuse" textures in Flight have been renamed to albedo since that more accurately represents what they are.


Materials:

A new SimProp schema was created for the new materials (.material). Each material references either a shader pipeline. This associates which shader will be used to render the material, and also determines what set of properties can be specified in that material.

Example material, using the example above:

Code:
<SimBase.Document version="2,0">
  <FlexMaterial.Material>
    <ShaderPipeline>{0D5E4F8C-A5CF-4502-A1E5-A8B15BE110D0}</ShaderPipeline>
    <Properties>
      <AlbedoMap>{CBDC590A-6617-4CF0-9A8A-9AF20F0D1C35}</AlbedoMap>
      <DetailMap>{CC9F8CB2-094C-4769-8840-41BCCB1B0BC2}</DetailMap>
      <NormalMap>{6F655570-614B-467F-BD1A-CF9AA8658FDB}</NormalMap>
      <DetailScale>80.000000</DetailScale>
      <BumpScale>80.000000</BumpScale>
      <DepthWrite>False</DepthWrite>
      <AlphaMode>BLEND</AlphaMode>
    </Properties>
  </FlexMaterial.Material>
</SimBase.Document>

Material Variations:

Material variations (.materialVar) are another new SimProp file schema for Flight. These files are responsible for mapping a set of materials to the list of material slot names within a model. They are also used in some cases to specify a set of instance data that are used when creating an object of that type. This is used heavily on autogen to get the great performance in Flight.


Here is an example of the material variation for the trees:

Code:
<SimBase.Document version="2,0">
  <MaterialVariation.MaterialVariation>
    <FriendlyName>Tree_Model</FriendlyName>
    <ModelReference>{1a31a4ba-113b-47e8-bc55-865053b13b1f}</ModelReference>
    <MaterialMap>
      <ModelMaterialName>GenericTreeMaterial</ModelMaterialName>
      <MaterialID>{59BF3BDB-6752-49C6-AB6C-5AE48F6B26ED}</MaterialID>
    </MaterialMap>
    <InstanceData FormatID="{113A0A3D-DEAC-4090-8B85-99B288D77236}">
      <InstanceDataGroup FriendlyName="Trees">
        <VegetationWidth>8:12</VegetationWidth>
        <VegetationHeight>10:15</VegetationHeight>
        <VegetationSkew>0:1</VegetationSkew>
        <VegetationTextureIndex>0</VegetationTextureIndex>
        <VegetationTextureSlotWidth>4</VegetationTextureSlotWidth>
        <VegetationTextureSlotHeight>2</VegetationTextureSlotHeight>
        <VegetationCanopyScale>153</VegetationCanopyScale>
      </InstanceDataGroup>
    </InstanceData>
  </MaterialVariation.MaterialVariation>
</SimBase.Document>
This references a model, which contains a material name ("GenericTreeMaterial"), and maps that material slot. It also specifies an instance format to use with the material variation, and some instance data to use. Whenever an object of this type is created, Flight will generate some instance data for that object based on the InstanceDataGroup. Values for these properties can either be constants, or ranges (8:12 means 8-12), and it will randomly pick a number in that range. In some cases in Flight these instance values are overwritten with values form a different system depending on where the object was created from (via the scenery system and obx.bgl, or via the autogen system and .agn).

Material variations can also be based on another material variation instead of a model. This essentially clones the base material variation, and allows overriding a subset of the properties. For instance, for an aircraft livery, you can have one base material variation that specifies all of the materials for one livery, and then you can have another material variation for another livery that is based on the first one and only changes the albedo texture. The primary case where this is used is for autogen buildings as it can be needed for proper instancing (autogen buildings are called procedural buildings in Flight since they can be created via other means than just autogen).


Seasonal Variations:

One final addition to this set of functionality is the season variations (.seasonVar). The seasonal variations were actually refactored out of the seasonalization of autogen annotations from FSX and made more generic so it could be applied to scenery as well. This is a simple SimProp file that just lists a different material variation to use depending on the current season. This allows seasonalizing the scenery as well as the autogen3 equivalent in Flight. OBX files reference either a material variation (if there is no seasonal difference), or a seasonal variation file.

Code:
<SimBase.Document version="2,0">
  <Autogen.MaterialVariationGroups>
    <Seasonalization id="{7a2dc229-7dd6-41cf-8b2f-fb0bad04fa9d}">
      <SeasonDescription>
        <ReferenceEntry>
          <TargetGuid>{6A52C008-E0C2-46CF-8B7F-345B656D211A}</TargetGuid>
        </ReferenceEntry>
      </SeasonDescription>
      <SeasonDescription>
        <Season>HARD_WINTER</Season>
        <ReferenceEntry>
          <TargetGuid>{F8970B2B-6224-4780-A60A-9363D8267638}</TargetGuid>
        </ReferenceEntry>
      </SeasonDescription>
    </Seasonalization>
  </Autogen.MaterialVariationGroups>
</SimBase.Document>
The first SeasonDescription doesn't list a season, so it become the default for all seasons, and then the second SeasonDescription overrides the value for the hard winter season. One thing to note is that we didn't have enough time to fully clean up this system, so the Seasonalization id must be the same as the id for the asset in the .meta file.
 
Top