Skip to content

Elements

Alex Smith edited this page Apr 30, 2024 · 22 revisions

Elements are actions Photon 2 executes as part of animated sequences. In most contexts, elements are simply individual lights. However, elements can also be sounds, bone manipulation, and more.

Lights

Elements are most commonly lights. Photon 2 supports four different types of lights, each with their own benefits and drawbacks.

2D

2D lights (sometimes called "sprites") are flat materials drawn in 3D space with an artificial glow effect. They are very closely related to the lights in Photon LE.

2D lights are best suited for flat surfaces and are the most flexible in terms of appearance. They have a moderate-to-high impact on performance as they rely on computationally expensive visibility calculations in addition to advanced post-processing effects.

  • Supports intensity transitions: Yes.

Mesh

Mesh lights are 3D models that leverage a bloom shader for glow effects. They are extracted from sub-materials in a .MDL file. They have a light impact on performance and allow for sophisticated shapes that 2D lights cannot feasibly do.

Mesh lights typically require familiarity with 3D modeling software to create and are generally less vivid in appearance (although they can be combined with 2D lighting).

They are most commonly utilized for normal vehicle lights where a 2D shape would not be practical.

  • Supports intensity transitions: Yes.

Standard Vehicle Materials

When creating models to be used for standard vehicle lighting, you can take advantage of Photon's standardized, placeholder materials located in the materials/photon/vehicle folder. (In the future, this is planned to enable more automation when configuring component files.)

Reference
Material Purpose Position
bra_rc Brake Rear Center
bra_rl Brake Rear Left
bra_rr Brake Rear Right
drl_fl Daytime Running Light Front Left
drl_fr Daytime Running Light Front Right
fog_fl Fog Front Left
fog_fr Fog Front Right
hdl_fl Headlight Front Left
hdl_fr Headlight Front Right
hib_fl High-Beam Front Left
hib_fr High-Beam Front Right
lic License Plate Rear
mar_fl Marker Front Left
mar_fr Marker Front Right
mar_l1 Marker Left
mar_r1 Marker Right
rev_rl Reverse Rear Left
rev_rr Reverse Rear Right
sig_fl Signal Front Left
sig_fr Signal Front Right
sig_rl Signal Rear Left
sig_rr Signal Rear Right

Projected

Projected lights illuminate the world and models and can be configured to cast shadows. They have no visible light source and must therefore be paired with a 2D light or mesh light for a realistic appearance. They are integral for illumination functionality but are extremely expensive to render. As a single-player effect, however, they can be highly effective.

Projected lights are a core offering of the Source engine.

  • Supports intensity transitions: Yes.

DynamicLight

Dynamic lights are similar to projected lights but are less performance heavy, have a lower fidelity, and are not as controllable. They have a built-in fade in, fade-out behavior that cannot be removed, and are therefore not usually appropriate for flashing lights.

They are best utilized as a low-impact ambience effect, license plate light, or interior light.

  • Supports intensity transitions: No.

Sub

Refers to sub-materials. Allows the element to change as parent model's sub-material. Sub-materials have the best performance of any light, but are very limited in functionality and fidelity.

  • Supports intensity transitions: No.

Other

Sound

Sound elements play and control different sounds. Various sound attributes can be manipulated using state parameters. Sound elements are used for sirens (using siren speaker components) and can be used for flashing sound effects.

Bone

Bone elements control one axis of a model's bone. Bone elements have four primary activities:

Activities

  1. Rotate Continuously rotates the bone in one direction at a specified speed.
  2. Sweep Moves the bone back and forth between two angles. The start angle, stop angle, move speed, and pause time are user configurable.
  3. Fixed Rotates the bone to a specific angle and then stops. The target angle and speed are configurable.
  4. Spot User-manipulated positioning (still under development).

Proxy States

Bone elements can be configured to adjust a "proxy state," which other elements can reference and use as states on their own. This is utilized to enable light colors to change depending on the current angle of the bone. This is primarily for the Vision SLR lightbar.

The performance impact of bone elements is generally negligible as there typically aren't very many.

Sequence

Sequence elements configure a model's current sequence, which is used to trigger model animations. The term "sequence" in this context has no relation with component sequences.

Pose

Pose elements manipulate a model's pose parameters. Each element can be mapped to one pose parameter. Pose element states configure a gain speed, loss speed, and target value (between 0 and 1).

gmod_9LRUDg9OW4

In the image above, the Valor's feet pose parameter alternates between extended and retracted.

COMPONENT.Templates = {
   ["Pose"] = {
      PoseTemplate = {
         GainSpeed = 1, -- Speed when value increases
         LossSpeed = 0.6, -- Speed when value decreases
         States = {
            -- These are available by default
            ["OFF"] = { Target = 0 },
            ["ON"] = { Target = 1 },
            -- Custom state
            ["HALF"] = { Target = 0.5 },
         }
      }
   }
}

COMPONENT.Elements = {
   -- Implicit element syntax
   [1] = { "PoseTemplate", "pose_param_name" },
   -- Explicit element syntax
   [2] = { "PoseTemplate", Parameter = "pose_param_name", GainSpeed = 2, LossSpeed = 3 }
}

Virtual

Virtual elements are invisible and are designed for user-interface animation.

Properties

These are shared Photon Element properties.

Important

This is not a complete list of element properties as each must by manually documented. It is highly recommended to use the Sumneko Lua plugin on VSCode as it is far more comprehensive.

DeactivationState

-- This is a common use-case when simulating incandescent lights. 
COMPONENT.Templates = {
   ["2D"] = {
      My2dTemplate = {
         -- Whenever an element stops receiving inputs, it will apply the deactivation state.
         -- In this example, it causes the light to fade out.
         DeactivationState = "~OFF"
      }
   }
}

Advanced

Element Groups

Element groups allow for multiple elements to be referenced by one shared name. Elements can belong to an unlimited number of groups and eliminate the need to track multiple indexes of related elements.

COMPONENT.ElementGroups = {
   ["ODD"] = { 1, 3, 5, 7 },
   ["EVEN"] = { 2, 4, 6, 8 },
   ["ALL"] = { 1, 2, 3, 4, 5, 6, 7, 8 }
}

COMPONENT.Segments = {
   MySegment = {
      Frames = {
         -- These two frames are functionally identical
         [1] = "[R] ODD [B] EVEN",
         [2] = "[R] 1 3 5 7 [B] 2 4 6 8",
         -- These two are also identical
         [3] = "[W] ALL",
         [4] = "[W] 1 2 3 4 5 6 7 8",
      },
      Sequences = {}
   }
}

Intensity Transitions

Intensity transitions enable fade-in, fade-out behavior on compatible light elements. States must be manually configured to enable intensity transitions. States that utilize intensity transitions are prefixed with ~ by convention for easy identification. For example, a fade-out state is commonly be called ~OFF, and a fade-in state to red would be ~RED.

Body Group Requirements

On models that have body groups with different light variations or configurations, you can configure an element to only be enabled when specific body group conditions are met.

Specifying within a template:

COMPONENT.Templates = {
   ["2D"] = {
      ["ForwardHotFeet"] = {
         RequiredBodyGroups = {
            -- Requires the "Hotfeet" body group to be 0
            ["Hotfeet"] = 0,
         }
      }
   }
}

Specifying within an element definition:

COMONENT.Elements = {
   -- Enabled only when Hotfeet is 0
   [1] = { "ForwardHotFeet", Vector( 1, 2, 3), Angle( 0, -90, 0 ), RequiredBodyGroups = { ["Hotfeet"] = 0 } },
   -- Enabled when Hotfeet is 0 or 1
   [2] = { "ForwardHotFeet", Vector( 1, 2, 3), Angle( 0, -90, 0 ), RequiredBodyGroups = { ["Hotfeet"] = { 0, 1 } } }
   -- Same as #2, uses a body group index instead of name
   [3] = { "ForwardHotFeet", Vector( 1, 2, 3), Angle( 0, -90, 0 ), RequiredBodyGroups = { [1] = { 0, 1 } } }
}