Board index FlightGear Development Effects and shaders

LCD/LED shader for cockpit displays

An exciting "new" option in FlightGear, that includes reflections, lightmaps, the particle system etc.. A lot is yet to be discovered/implemented!

LCD/LED shader for cockpit displays

Postby Necolatis » Sun Oct 01, 2017 12:40 pm

Hello,

I made a shader for LCD/LED displays.

Replace the JA37 folder references in the effect file to if you want to test as I haven't applied it to any aircraft yet. Notice some folder references are buried halfway down the effect file.

Features and missing features
- It tries to recreate the color distortion and inversion of brightness of old LCDs when viewed from an angle (sorta works like a negative). At very big angles it can be set to go dark. So no more peeking from co-pilots seat to pilots displays if the displays are old LCDs.
- It attempts to play nice with ALS filters.
- Should work for both Canvas displays or static texture displays.
- You will probably need to tune material values in your AC file. The lightning like ambient / diffuse / specular is added, not modulated in any way with the display output. Only emission is modulated with the actual texture colors.
I used: MATERIAL "screen" rgb 0.0 0.0 0.0 amb 0.000 0.000 0.000 emis 0.000 0.000 0.000 spec 0.5 0.5 0.5 shi 96 trans 0.000
- It probably only supports geometry loaded from AC files due to not taking vertex color into account.
- To turn up the brightness, just make a normal material animation and turn up the emission.
- No Rembrandt support yet.
- Doesn't work with display textures or materials that has transparency.
- No moonlight lightning yet.
- No secondary ALS lights yet.

Some feedback would be nice, both for how you think it works, and for the code itself. Or if there is bugs or something it does not play well with.

Its a work in progress, but if it ends up being usable, then next plan is to make CRT display shader.

Notice that I don't own an old LCD display so I could not investigate how it works, but luckily a friend gave me advice on how the colors distort.

Some pics, please note that this display as its mostly one tone of medium grey don't show the brightness inversion very good, but it does show the color distortion:

Image

Image

lcd.eff
Code: Select all
<!--
License: GPL v2
Author: Nikolai V. Chr.
-->
<PropertyList>
   <name>Aircraft/JA37/Models/Effects/displays/lcd</name>
   <parameters>
      <inner-angle type="float">35</inner-angle><!-- 0-90, use 90 for LED or plasma display-->
      <outer-angle type="float">60</outer-angle><!-- 0-90, but greater than inner -->
      <black-angle type="float">80</black-angle><!-- 0-90, but greater than outer -->

      



      <texture n="0">
         <type>white</type>
      </texture>

      <vertex-program-two-side type="bool">false</vertex-program-two-side>
      <material>
         <color-mode-uniform>1</color-mode-uniform>
      </material>
      <material-id>0</material-id>
      <use-als><use>/sim/rendering/shaders/skydome</use></use-als>
      <rendering-hint>opaque</rendering-hint>
      <transparent>false</transparent>
      <render-bin>
         <bin-number>1</bin-number>
         <bin-name>RenderBin</bin-name>
      </render-bin>
      <shade-model>smooth</shade-model>

      <use_filtering><use>/sim/rendering/als-filters/use-filtering</use></use_filtering>
          <gamma><use>/sim/rendering/als-filters/gamma</use></gamma>
          <brightness><use>/sim/rendering/als-filters/brightness</use></brightness>
          <delta_T><use>/environment/surface/delta-T-structure</use></delta_T>
      <fact_grey><use>/sim/rendering/als-filters/grey-factor</use></fact_grey>
               <fact_black><use>/sim/rendering/als-filters/black-factor</use></fact_black>
          <use_night_vision><use>/sim/rendering/als-filters/use-night-vision</use></use_night_vision>
          <use_IR_vision><use>/sim/rendering/als-filters/use-IR-vision</use></use_IR_vision>
      <display_xsize><use>/sim/startup/xsize</use></display_xsize>
      <display_ysize><use>/sim/startup/ysize</use></display_ysize>
   </parameters>
   <technique n="5">
      <predicate>
         <and>
            <property>/sim/rendering/shaders/quality-level</property>
            <property>/sim/rendering/shaders/model</property>
            <or>
               <less-equal>
                  <value type="float">2.0</value>
                  <glversion/>
               </less-equal>
               <and>
                  <extension-supported>GL_ARB_shader_objects</extension-supported>
                  <extension-supported>GL_ARB_shading_language_100</extension-supported>
                  <extension-supported>GL_ARB_vertex_shader</extension-supported>
                  <extension-supported>GL_ARB_fragment_shader</extension-supported>
               </and>
            </or>
         </and>
       </predicate>
      <pass>
         <lighting>true</lighting>
         <material>
            <active>
               <use>material/active</use>
            </active>
            <ambient>
               <use>material/ambient</use>
            </ambient>
            <diffuse>
               <use>material/diffuse</use>
            </diffuse>
            <specular>
               <use>material/specular</use>
            </specular>
            <emissive>
               <use>material/emissive</use>
            </emissive>
            <shininess>
               <use>material/shininess</use>
            </shininess>
            <color-mode>
               <use>material/color-mode</use>
            </color-mode>
         </material>
         <blend>
            <active>
               <use>blend/active</use>
            </active>
            <source>
               <use>blend/source</use>
            </source>
            <destination>
               <use>blend/destination</use>
            </destination>
         </blend>
         <shade-model>
            <use>shade-model</use>
         </shade-model>
         <cull-face>
            <use>cull-face</use>
         </cull-face>
         <rendering-hint>
            <use>rendering-hint</use>
         </rendering-hint>
         <blend>
            <use>transparent</use>
         </blend>
         <alpha-test>
            <use>transparent</use>
         </alpha-test>
         <render-bin>
            <bin-number>
               <use>render-bin/bin-number</use>
            </bin-number>
            <bin-name>
               <use>render-bin/bin-name</use>
            </bin-name>
            </render-bin>
            <!-- Albedo texture unit-->
         <texture-unit>
            <unit>0</unit>
            <image>
               <use>texture[0]/image</use>
            </image>
            <type>
               <use>texture[0]/type</use>
            </type>
            <filter>
               <use>texture[0]/filter</use>
            </filter>
            <wrap-s>
               <use>texture[0]/wrap-s</use>
            </wrap-s>
            <wrap-t>
               <use>texture[0]/wrap-t</use>
            </wrap-t>
            <internal-format>
               <use>texture[0]/internal-format</use>
            </internal-format>
            </texture-unit>
            <vertex-program-two-side>
               <use>vertex-program-two-side</use>
         </vertex-program-two-side>
         <program>
            <vertex-shader n="0">Aircraft/JA37/Models/Effects/displays/lcd.vert</vertex-shader>
            <fragment-shader n="0">Aircraft/JA37/Models/Effects/displays/lcd.frag</fragment-shader>
            <fragment-shader n="1">Shaders/noise.frag</fragment-shader>
            <fragment-shader n="2">Shaders/filters-ALS.frag</fragment-shader>
         </program>
         <uniform>
            <name>BaseTex</name>
            <type>sampler-2d</type>
            <value type="int">0</value>
         </uniform>
         <uniform>
            <name>innerAngle</name>
            <type>float</type>
            <value>
               <use>inner-angle</use>
            </value>
         </uniform>
         <uniform>
            <name>outerAngle</name>
            <type>float</type>
            <value>
               <use>outer-angle</use>
            </value>
         </uniform>
         <uniform>
            <name>blackAngle</name>
            <type>float</type>
            <value>
               <use>black-angle</use>
            </value>
         </uniform>
         <uniform>
            <name>use_als</name>
            <type>bool</type>
            <value>
               <use>use-als</use>
            </value>
         </uniform>

         <uniform>
                 <name>gamma</name>
                 <type>float</type>
                 <value><use>gamma</use></value>
               </uniform>
               <uniform>
                 <name>brightness</name>
                 <type>float</type>
                 <value><use>brightness</use></value>
               </uniform>
               <uniform>
                 <name>use_filtering</name>
                 <type>bool</type>
                 <value><use>use_filtering</use></value>
               </uniform>
               <uniform>
                    <name>use_night_vision</name>
                   <type>bool</type>
                       <value><use>use_night_vision</use></value>
                 </uniform>
                 <uniform>
                    <name>use_IR_vision</name>
                 <type>bool</type>
                    <value><use>use_IR_vision</use></value>
                  </uniform>
                 <uniform>
                 <name>delta_T</name>
                 <type>float</type>
                 <value><use>delta_T</use></value>
                  </uniform>
            <uniform>
            <name>fact_grey</name>
            <type>float</type>
            <value><use>fact_grey</use></value>
            </uniform>
            <uniform>
            <name>fact_black</name>
            <type>float</type>
            <value><use>fact_black</use></value>
            </uniform>
         <uniform>
              <name>display_xsize</name>
              <type>int</type>
              <value><use>display_xsize</use></value>
         </uniform>
            <uniform>
              <name>display_ysize</name>
              <type>int</type>
              <value><use>display_ysize</use></value>
         </uniform>
      </pass>
   </technique>
</PropertyList>


lcd.vert
Code: Select all
// Author: Nikolai V. Chr.
// License: GPL v2
#version 120

varying   vec3   VNormal;
varying vec3    eyeVec;

void main(void) {
      vec4 ecPosition = gl_ModelViewMatrix * gl_Vertex;
      eyeVec = ecPosition.xyz;

      VNormal = normalize(gl_NormalMatrix * gl_Normal);

      gl_Position = ftransform();
      gl_ClipVertex = ecPosition;
      gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
}


lcd.frag
Code: Select all
// Author: Nikolai V. Chr.
// License: GPL v2
#version 120

varying vec3    VNormal;
varying vec3    eyeVec;

uniform sampler2D BaseTex;
uniform float innerAngle;//inside this angle the display is perfect
uniform float outerAngle;//from inner to outer the display gets more color distorted.
uniform float blackAngle;//from outer to this angle the display gets more black. From this angle to 90 the display stays black.
uniform int use_als;

const vec4  kRGBToYPrime = vec4 (0.299, 0.587, 0.114, 0.0);
const vec4  kRGBToI     = vec4 (0.596, -0.275, -0.321, 0.0);
const vec4  kRGBToQ     = vec4 (0.212, -0.523, 0.311, 0.0);

const vec4  kYIQToR   = vec4 (1.0, 0.956, 0.621, 0.0);
const vec4  kYIQToG   = vec4 (1.0, -0.272, -0.647, 0.0);
const vec4  kYIQToB   = vec4 (1.0, -1.107, 1.704, 0.0);

vec3 filter_combined (in vec3 color) ;

vec3 rotateHue (in vec4 color) {
    // Convert to YIQ
    float   YPrime  = dot (color, kRGBToYPrime);
    float   I      = dot (color, kRGBToI);
    float   Q      = dot (color, kRGBToQ);

    // Calculate the hue and chroma
    float   hue     = atan (Q, I);
    float   chroma  = sqrt (I * I + Q * Q);

    // Make the adjustment
    hue += radians(180.0);
    YPrime = 1 - YPrime;

    // Convert back to YIQ
    Q = chroma * sin (hue);
    I = chroma * cos (hue);

    // Convert back to RGB
    vec4    yIQ   = vec4 (YPrime, I, Q, 0.0);
    color.r = dot (yIQ, kYIQToR);
    color.g = dot (yIQ, kYIQToG);
    color.b = dot (yIQ, kYIQToB);

    // reduce contrast by alot
    color.rgb = ((color.rgb - vec3(0.5,0.5,0.5)) * vec3(0.15,0.15,0.15)) + vec3(0.5,0.5,0.5);

    return color.rgb;
}

// todo: rembrandt and stuff

void main (void) {
    vec3 gamma      = vec3(1.0/2.2);// standard monitor gamma correction
    vec3 gammaInv   = vec3(2.2);
    vec4 texel      = texture2D(BaseTex, gl_TexCoord[0].st);   

    vec3 eye = normalize(-eyeVec);
    vec3 N  = normalize(VNormal);
    float angle = degrees(acos(dot(N,eye)));//angle between normal and viewer
    vec3 color = vec3(0.0,0.0,0.0);
    if (angle <= innerAngle) {
        color = texel.rgb;
    } else if (angle <= outerAngle) {
        vec3 hsl = rotateHue(texel);
        float amount = (angle - innerAngle)/(outerAngle-innerAngle);
        color = mix(texel.rgb, hsl, amount);
    } else if (angle <= blackAngle) {
        vec3 hsl = rotateHue(texel);
        float amount = (angle - outerAngle)/(blackAngle-outerAngle);
        color = mix(hsl, vec3(0,0,0), amount);
    }
    color = pow(color, gammaInv);
    color = color * gl_FrontMaterial.emission.rgb;

    float phong = 0.0;
    vec3 Lphong = normalize(gl_LightSource[0].position.xyz);
    if (dot(N, Lphong) > 0.0) {
        // lightsource is not behind
        vec3 Rphong = normalize(-reflect(Lphong,N));
        phong = pow(max(dot(Rphong,eye),0.0),gl_FrontMaterial.shininess);
        phong = clamp(phong, 0.0, 1.0);
    }
    vec4 specular = gl_FrontMaterial.specular * gl_LightSource[0].diffuse * phong;
    vec3 ambient = gl_FrontMaterial.ambient.rgb * gl_LightSource[0].ambient.rgb * gl_LightSource[0].ambient.rgb * 2;//hack but works, pitch black at night. :)

    vec3 L = normalize((gl_ModelViewMatrixInverse * gl_LightSource[0].position).xyz);
    N = normalize((gl_ModelViewMatrixTranspose * vec4(N,0.0)).xyz);
    float nDotVP = dot(N,L);
    nDotVP = max(0.0, nDotVP);
    vec3 diffuse = gl_FrontMaterial.diffuse.rgb * gl_LightSource[0].diffuse.rgb * nDotVP;

    color = clamp(color+specular.rgb+ambient+diffuse, 0, 1);

    if (use_als > 0) {
        gl_FragColor = vec4(filter_combined(pow(color,gamma)), 0.0);
    } else {
        gl_FragColor = vec4(pow(color,gamma), 0.0);
    }
}


Edit: Now also reduces contrast. Code updated. And added some screenies below of reduced contrast at angle:

Image

Image
Last edited by Necolatis on Sun Oct 01, 2017 2:06 pm, edited 2 times in total.
"Airplane travel is nature's way of making you look like your passport photo."
— Al Gore
User avatar
Necolatis
 
Posts: 2233
Joined: Mon Oct 29, 2012 1:40 am
Location: EKOD
Callsign: Leto
IRC name: Neco
Version: 2020.3.19
OS: Windows 10

Re: LCD/LED shader for cockpit displays

Postby Thorsten » Sun Oct 01, 2017 12:57 pm

Hm... as it happens, I have this display effect in the pipeline (currently with the Shuttle for testing and evaluation, scheduled to go to FGData in this release cycle).

Image

It'd be rather easy to add the color trafos with angle as a simple option. In particular, it already has the correct interaction with the interior shadowing via opacity maps (which is really one of the most pronounced effects in my view).

Edit: I knew I had it somewhere - I mean this

Image
Thorsten
 
Posts: 12490
Joined: Mon Nov 02, 2009 9:33 am

Re: LCD/LED shader for cockpit displays

Postby Necolatis » Sun Oct 01, 2017 1:13 pm

I am sad cause I used alot of time doing my first shader from the bottom, and you made something better.
I am happy cause we are going to get something cool added to flightgear.
Oh well. :)

Does it do CRT displays as well?
"Airplane travel is nature's way of making you look like your passport photo."
— Al Gore
User avatar
Necolatis
 
Posts: 2233
Joined: Mon Oct 29, 2012 1:40 am
Location: EKOD
Callsign: Leto
IRC name: Neco
Version: 2020.3.19
OS: Windows 10

Re: LCD/LED shader for cockpit displays

Postby Thorsten » Sun Oct 01, 2017 1:27 pm

Does it do CRT displays as well?


I've mainly focused on perception effects - bloom and color desaturation for low ambient light, extinction of contrast for high ambient light.

So I suspect it does none of the specific transformations you have in mind, which is why I would propose to add them as option-switchable color transformations (I don't know what you specifically want to do for a CRT display).
Thorsten
 
Posts: 12490
Joined: Mon Nov 02, 2009 9:33 am

Re: LCD/LED shader for cockpit displays

Postby icecode » Sun Oct 01, 2017 1:39 pm

I am sad cause I used alot of time doing my first shader from the bottom, and you made something better.


I worked on shadows for a few months before Rembrandt came by, but I learned A LOT in the process. No time is wasted when you are learning at the same time. :)
icecode
 
Posts: 709
Joined: Thu Aug 12, 2010 1:17 pm
Location: Spain
Version: next
OS: Fedora

Re: LCD/LED shader for cockpit displays

Postby Necolatis » Sun Oct 01, 2017 1:41 pm

I searched if somebody had already made a GPL GLSL CRT effect.
It turns out there is plenty out there on retro websites. Not sure any of them were meant to be used on textures in 3D world though.
I was planning to investigate them further and see if I could adapt one of them to work in FG. If its not too heavy for performance.

Here is an example of what one of them can do: http://mame32fx.altervista.org/forum/viewtopic.php?t=184

With maybe just half of those features, it would still be pretty cool.

Here is a bunch of them: https://github.com/libretro/glsl-shaders/tree/master/crt
"Airplane travel is nature's way of making you look like your passport photo."
— Al Gore
User avatar
Necolatis
 
Posts: 2233
Joined: Mon Oct 29, 2012 1:40 am
Location: EKOD
Callsign: Leto
IRC name: Neco
Version: 2020.3.19
OS: Windows 10

Re: LCD/LED shader for cockpit displays

Postby Thorsten » Sun Oct 01, 2017 1:58 pm

I'm still not quite sure what specifically you want to do. We can sure bend the texture coordinates with a transformation, but, well, if you have a non-planar screen, you can actually model it in 3d, so what's the point?

Or are you after the pixely appearance? That's not too hard to do either.

(I'd much prefer to get an idea of the desired features rather than finished code, because it probably takes me 10 times as long to understand code I am not familiar with than to come up with code that merges into what we have - unless the problem is really tough of course...)
Thorsten
 
Posts: 12490
Joined: Mon Nov 02, 2009 9:33 am

Re: LCD/LED shader for cockpit displays

Postby Necolatis » Sun Oct 01, 2017 2:01 pm

Makes sense, will think about it, did not think it fully through as I planned it after doing LCD/LED display.
"Airplane travel is nature's way of making you look like your passport photo."
— Al Gore
User avatar
Necolatis
 
Posts: 2233
Joined: Mon Oct 29, 2012 1:40 am
Location: EKOD
Callsign: Leto
IRC name: Neco
Version: 2020.3.19
OS: Windows 10

Re: LCD/LED shader for cockpit displays

Postby legoboyvdlp » Sun Oct 01, 2017 4:30 pm

The CRT sprt of looks kind of like it is glass over an image, it is hard to describe, but that is how it looks to me from videos and images.

It would be useful for the A320.
User avatar
legoboyvdlp
 
Posts: 7981
Joined: Sat Jul 26, 2014 2:28 am
Location: Northern Ireland
Callsign: G-LEGO
Version: next
OS: Windows 10 HP

Re: LCD/LED shader for cockpit displays

Postby Octal450 » Sun Oct 01, 2017 4:42 pm

This is for Canvas I assume, so could use it, yes.

Kind Regards,
Josh
Skillset: JSBsim Flight Dynamics, Systems, Canvas, Autoflight/Control, Instrumentation, Animations
Aircraft: A320-family, MD-11, MD-80, Contribs in a few others

Octal450's GitHub|Launcher Catalog
|Airbus Dev Discord|Octal450 Hangar Dev Discord
User avatar
Octal450
 
Posts: 5583
Joined: Tue Oct 06, 2015 1:51 pm
Location: Huntsville, AL
Callsign: WTF411
Version: next
OS: Windows 11

Re: LCD/LED shader for cockpit displays

Postby Thorsten » Sun Oct 01, 2017 5:31 pm

@Necolatis:

If you want to experiment

https://sourceforge.net/p/fgspaceshuttl ... isplay.eff

https://sourceforge.net/p/fgspaceshuttl ... htmap.vert
https://sourceforge.net/p/fgspaceshuttl ... splay.frag

(Well, that's the extended space shader family, the Rolls Royce among the shaders - but they'll process aircraft fine :mrgreen: )
Thorsten
 
Posts: 12490
Joined: Mon Nov 02, 2009 9:33 am

Re: LCD/LED shader for cockpit displays

Postby Necolatis » Sun Oct 01, 2017 6:01 pm

Cool. So you use 12 lightmaps? Is that one for each light source in the shuttle cockpit?
"Airplane travel is nature's way of making you look like your passport photo."
— Al Gore
User avatar
Necolatis
 
Posts: 2233
Joined: Mon Oct 29, 2012 1:40 am
Location: EKOD
Callsign: Leto
IRC name: Neco
Version: 2020.3.19
OS: Windows 10

Re: LCD/LED shader for cockpit displays

Postby Thorsten » Sun Oct 01, 2017 6:40 pm

Yep - Wayne had made it his personal goal to make the lighting perfect, so we extended the shader to support the necessary amount of lightmaps.
Thorsten
 
Posts: 12490
Joined: Mon Nov 02, 2009 9:33 am

Re: LCD/LED shader for cockpit displays

Postby PINTO » Sun Oct 01, 2017 11:58 pm

I am a shader noob, so please forgive the fact that this is a question out of ignorance.

Would it be possible to extend it to an arbitrary amount of light maps? The MiG-21bis has over 30 lights on the front panel alone, and I'd like to do this accurately as well. I'm also not sure about the performance hit of so many light maps?
Actively developing the MiG-21bis (github repo) (forum thread) (dev discord) (fg wiki)

http://opredflag.com is an active flightgear dogfighting community (using a system that isn’t bombable)
User avatar
PINTO
 
Posts: 966
Joined: Wed Oct 21, 2015 7:28 pm
Callsign: pinto
Version: stable
OS: Win10

Re: LCD/LED shader for cockpit displays

Postby Thorsten » Mon Oct 02, 2017 4:59 am

No - you can cram four lights into one texture, and we have eight textures max (including everything - specular, normal, opacity,...) mapping, so there's a limit dependent on what else the effect ought to do.

Okay - you could then think of compressing information and decoding it later, then you can pack more, but this gets ugly quickly.

The MiG-21bis has over 30 lights on the front panel alone


We're not talking front panel lights here - we're talking lights designed to illuminate the whole flightdeck - which is why you need 12 lightmaps for every point in there, because all these lights can affect it. Panel lights I just merged into the ambience model (they're unlikely to be treated well by the raytracer anyway).

A local light which doesn't illuminate the rest of the cabin can have its own effect for its own bit of surface around it, and then you can have a lot of bang for the buck even with just four channels.
Thorsten
 
Posts: 12490
Joined: Mon Nov 02, 2009 9:33 am

Next

Return to Effects and shaders

Who is online

Users browsing this forum: No registered users and 2 guests