• Which the release of FS2020 we see an explosition of activity on the forun and of course we are very happy to see this. But having all questions about FS2020 in one forum becomes a bit messy. So therefore we would like to ask you all to use the following guidelines when posting your questions:

    • Tag FS2020 specific questions with the MSFS2020 tag.
    • Questions about making 3D assets can be posted in the 3D asset design forum. Either post them in the subforum of the modelling tool you use or in the general forum if they are general.
    • Questions about aircraft design can be posted in the Aircraft design forum
    • Questions about airport design can be posted in the FS2020 airport design forum. Once airport development tools have been updated for FS2020 you can post tool speciifc questions in the subforums of those tools as well of course.
    • Questions about terrain design can be posted in the FS2020 terrain design forum.
    • Questions about SimConnect can be posted in the SimConnect forum.

    Any other question that is not specific to an aspect of development or tool can be posted in the General chat forum.

    By following these guidelines we make sure that the forums remain easy to read for everybody and also that the right people can find your post to answer it.

FS2004 Boeing 747 Classic

Aaron: I don't know whether this will help, but could I suggest downloading the sd2gau42 documentation from here: Creating C Gauges and reading the section titled 'Understanding how P3D treats Bitmaps and Colours in Gauges'; specifically the sub-section 'This is Where it all Goes Wrong'. I have some suggestions in there on how to defeat the night banding.
Yes, I am aware of this but there are actually 2 different factors when it comes to FS9 and our panel:

I am using GDI+ and not the older MAKE macros, which means that the sim itself never touches our actual bitmaps. Each frame's presenter instead rasterizes the bitmaps with the CPU, but in terms of unconditional compression, it does not happen in the load stage but in the rendering stage.

FS9's panels are limited to 5 bits per color channel, though I noticed while reading the texture's pixel rasterizer that they include dithering, which I didn't include in my render code which can improve the appearance at the cost of noise

C++:
        void ConvertBackToImg(Gdiplus::Bitmap* back, PIMAGE img,
                              int rx, int ry, int rw, int rh)
        {
            if (back == NULL || img == NULL || img->image == NULL)
            { return; }
            const int dimX = (int)back->GetWidth();
            const int dimY = (int)back->GetHeight();
            int x0 = (rx > 0) ? rx : 0;
            int y0 = (ry > 0) ? ry : 0;
            int x1 = rx + rw;
            int y1 = ry + rh;
            if (x1 > dimX) { x1 = dimX; }
            if (y1 > dimY) { y1 = dimY; }
            if (x1 > img->dim.x) { x1 = img->dim.x; }
            if (y1 > img->dim.y) { y1 = img->dim.y; }
            if (x0 >= x1 || y0 >= y1) { return; }
            Gdiplus::BitmapData bd;
            Gdiplus::Rect rc(0, 0, dimX, dimY);
            if (back->LockBits(&rc, Gdiplus::ImageLockModeRead,
                               PixelFormat32bppARGB, &bd) != Gdiplus::Ok)
            { return; }
            for (int y = y0; y < y1; ++y)
            {
                const unsigned int* src = (const unsigned int*)
                    ((char*)bd.Scan0 + y * bd.Stride);
                char* dstRow = img->image + (UINT32)y * img->pitch;
                const unsigned int* bayer = kBayer4[y & 3];
                if (img->format == IMG_15_BIT)
                {
                    unsigned short* dst = (unsigned short*)dstRow;
                    for (int x = x0; x < x1; ++x)
                    {
                        const unsigned int p = src[x];
                        if ((p >> 24) < 128) { dst[x] = 0; continue; }
                        const unsigned int r = (p >> 16) & 0xFF;
                        const unsigned int gg = (p >> 8) & 0xFF;
                        const unsigned int b = p & 0xFF;
                        const unsigned int d = bayer[x & 3];
                        dst[x] = (unsigned short)
                            (0x8000 | (Dither5(r, d) << 10) |
                             (Dither5(gg, d) << 5) | Dither5(b, d));
                    }
                }
                else if (img->format == IMG_32_BIT ||
                         img->format == IMG_32A_BIT)
                {
                    unsigned int* dst = (unsigned int*)dstRow;
                    for (int x = x0; x < x1; ++x)
                    {
                        dst[x] = src[x];
                    }
                }
                else if (img->format == IMG_16_BIT)
                {
                    unsigned short* dst = (unsigned short*)dstRow;
                    for (int x = x0; x < x1; ++x)
                    {
                        const unsigned int p = src[x];
                        if ((p >> 24) < 128) { dst[x] = 0; continue; }
                        const unsigned int r = (p >> 16) & 0xFF;
                        const unsigned int gg = (p >> 8) & 0xFF;
                        const unsigned int b = p & 0xFF;
                        const unsigned int d = bayer[x & 3];
                        unsigned short v = (unsigned short)
                            ((Dither5(r, d) << 11) | (Dither6(gg, d) << 5) |
                             Dither5(b, d));
                        if (v == 0) { v = 0x0821; }   // near-black
                        dst[x] = v;
                    }
                }
            }
            back->UnlockBits(&bd);
        }
 
@DragonflightDesign After applying dithering, the banding doesn't look nearly as terrible.

1793427656360.png


The "noise" solution you presented in sd2gau works as its a more manual form of dithering, but either way, I am much more happy with this result... Thanks for the mention about it.
 
One of the last pieces of the 2D panels is adding some lighting and details. The left is the old panel, the right is the new panel bitmap.

Electrical_PanelOld.jpg
Electrical_Panel.jpg


The new panels comprise of 4 new aspects; panel staining, dust/debris, specular highlights, and ambient occlusion. The latter two are rendered using 3d recreations of the 2d panel projected onto a plane that is the same resolution as the original bitmap.
1793684869674.png
1793684954123.png


The first two consisted of both manual photoshop work and automatic scripting tools. The boundaries for crevices were defined both by the ambient occlusion map and a height map, both generated from the 3D software. These images then feed into heatmap generators to programmatically define exactly where dust, debris, hairs, and small particles should land. Each individual type of dirt is biased towards a specific portion of the panel and some panels receive more dirt than others.

Staining consisted of marking specific parts of the panels and then running a hue/saturation filter over it plus a fractal generator that inverted the operation of the that module's filter. This results in bright and dark spots of the panel, simulating topcoat degradation or UV exposure.

1793685219278.png
1793685236996.png
nookh3.png


These items are then combined and composited to the final image you see above.

Electrical_Panel_Stained.png
1793685583164.png
1793685683288.png
1793685236996.png
 
that is unreal, how did you manage to get all those little details dust parts right? I assume hand drawn?
Yes, though I used a variety of dust brushes in Photoshop and cropping random scraps of paper, egg shells, and bread crumbs. Hair was taken from black and white film damage and I just used line debris as hair.
 
Yes, though I used a variety of dust brushes in Photoshop and cropping random scraps of paper, egg shells, and bread crumbs. Hair was taken from black and white film damage and I just used line debris as hair.
Looks a lot more natural than my method of using a dust brush to unmask photos of garbage dumps.
 
Hey all,

This was quite the effort and took a lot of painful bug testing, but after a lot of trial and error, I have now got skinned animations in FS9. This allows us to have smooth wingflex and VC flap animations without having visible "breaks" or seams.

1794203140332.png


Screenshot 2026-11-08 215031.png


If you are wondering about the technical aspects, each keyframe of the skinned object has its vertex positions saved in a table. The module hooks FS9's G3D's BGL_ANIMATE handler and writes it to the vertex list directly. Because MakeMDL doesn't support bone objects, all bones were converted to regular polygon objects so nonskinned objects that depend on their animations can still be kept without having to bake their animations, and the bone objects were hidden by applying a 64 x 64 pixel wide texture with a black dot. The reason why I didn't just use 0% opacity was because MakeMDL inserts objects with any opacity value of less than 100% into the Alpha section of the ASM, which is run after the opaque section. The hooks for BGL_ANIMATE has to run in the opaque section before the first triangle of a skinned object is rendered, but using bone objects of 99% or less opacity will cause their sections to be further down.

Additionally, I added several new texture details such as NO STEP markings, engine covers, and decals for doors.
Screenshot 2026-11-08 215002.png


Screenshot 2026-11-08 215013.png

Screenshot 2026-11-08 214932.png


For any of those that care to see a before (left) and after (right) here it is. Notice how the outboard VC flaps are clearly not smooth, as they were cut up rectangles rotated. The newer (right) model with skinned animations now has smooth flap rendering (and I also fixed that shadow bug on the right wing ;))

1794204460890.png
1794204446139.png
 
Last edited:
Some more progress on the external model has been made.

One of the last things that needed to be tackled was lighting. However, I didn't want to resort to using _L texture or prebaked light maps. So, considering that I am hooking so many parts of the sim, I decided to hook the render context.

This allowed me to create and inject dynamic lighting into FS9. In the screenshot below is the 747 with its wing lights lit up. Notice how shadows are being casted by the inboard kruger flaps and engine 3 is casting a shadow onto the ground and onto engine 2 as well as a shadow being casted into the engine inlet. Shadows are only casted by the wing light and lower beacon light to save performance.

1794376896221.png


This is a very similar technique with what can be done in today's MSFS 2020/2024, however unlike in those sims which uses a prebaked shadow/light mask, the shadows here are casted dynamically using a general approximation. Shadows are computed by computing the camera frustrum and a perspective projection from the lamp's position directly in the vertex shader. This results in a small (but not insignificant) cost in performance of around ~1.5ms per frame on my system, which at 60FPS nets you a 3 fps loss when all lights are turned on.

Since shadows are dynamic, this allows shadows being casted by moving surfaces (such as the VC flaps) to actually cast correct shadows. Notice how on the two comparison images below, a shadow is being casted by the inboard kruger flap and goes away once the flap is retracted (and yes, the shadow does move with the animation, this hook occurs every single frame).

1794377332422.png
1794377349110.png

1794379710034.png

This results in us having great night lighting in the sim. I expect that most modern PCs can run this with no trouble though you may struggle to run this on hardware from 2004.
 
Love the Fsmuseum livery! any plans for an AF1 livery, or is that hard since its a VC25
Not really any plans for the VC25 in all honesty. The VC25 uses the CF6-80C2, not the CF6-50E2. the -80 and the -50 differ in appearance quite a bit, and personally I don't feel too fond of the idea of making a VC-25 model but with the systems and cockpit of a CF6-50 747.

The VC-25 itself apart from its engines features a very different fuel system, slightly different electrical system (I think the galley busses were chopped out and many cabin fixtures were changed), dual APU fire bottles, an ECS system for the lower cargo hold (civilian versions only have cargo heating, there's no ECS system there) and there's even a 4th navigators station where the observer and spare light bulbs would be at.

1794425312383.png


And to answer your question, I don't plan on making an AF1 livery.
 
Back
Top